ソースを参照

* Merged changes from trunk [14636:14686/trunk].

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/renewal@14687 54d463be-8e91-2dee-dedb-b68131a5f0ec
ai4rei 14 年 前
コミット
d41e850975
100 ファイル変更1893 行追加7258 行削除
  1. 2 0
      Changelog-Renewal.txt
  2. 3 10
      Makefile.in
  3. 4 0
      conf/Changelog.txt
  4. 0 4
      conf/atcommand_athena.conf
  5. 0 0
      conf/import-tmpl/ladmin_conf.txt
  6. 0 31
      conf/ladmin_athena.conf
  7. 0 10
      conf/login_athena.conf
  8. 48 5
      conf/maps_athena.conf
  9. 1 7
      conf/msg_athena.conf
  10. 1 2
      configure
  11. 1 1
      configure.in
  12. 19 0
      db/Changelog.txt
  13. 145 7
      db/const.txt
  14. 113 112
      db/item_db.txt
  15. BIN
      db/map_cache.dat
  16. 20 0
      db/map_index.txt
  17. 2 2
      db/mob_db.txt
  18. 12 12
      db/mob_skill_db.txt
  19. 1 1
      db/packet_db.txt
  20. 45 3
      doc/item_bonus.txt
  21. 13 13
      doc/mob_db_mode_list.txt
  22. 2 1
      doc/sample/basejob_baseclass_upper.txt
  23. 3 6
      doc/script_commands.txt
  24. 1 1
      doc/whisper_sys.txt
  25. 0 12
      eAthena-10.sln
  26. 24 0
      eAthena-6.dsw
  27. 12 12
      eAthena-8.sln
  28. 12 12
      eAthena-9.sln
  29. 5 0
      npc/Changelog.txt
  30. 3 2
      npc/custom/quests/bookofthedevil.txt
  31. 3 2
      npc/custom/quests/thq/THQS_Quests.txt
  32. 2 2
      npc/other/Global_Functions.txt
  33. 1 1
      npc/scripts_custom.conf
  34. 0 1
      readme/features.html
  35. 1 1
      readme/setup.html
  36. 8 8
      save-tmpl/account.txt
  37. 1 0
      sql-files/main.sql
  38. 1 0
      sql-files/upgrade_svn14672.sql
  39. 24 164
      src/char/char.c
  40. 24 50
      src/char_sql/char.c
  41. 1 1
      src/char_sql/int_auction.c
  42. 1 1
      src/common/core.h
  43. 2 2
      src/common/db.c
  44. 92 42
      src/common/grfio.c
  45. 2 0
      src/common/plugins.c
  46. 2 3
      src/common/socket.c
  47. 1 6
      src/common/socket.h
  48. 7 3
      src/common/strlib.c
  49. 0 45
      src/ladmin/Makefile.in
  50. 0 3074
      src/ladmin/ladmin.c
  51. 0 9
      src/ladmin/ladmin.h
  52. 1 1
      src/login/Makefile.in
  53. 2 1
      src/login/account.h
  54. 6 3
      src/login/account_sql.c
  55. 26 5
      src/login/account_txt.c
  56. 0 857
      src/login/admin.c
  57. 51 85
      src/login/login.c
  58. 0 4
      src/login/login.h
  59. 26 46
      src/map/atcommand.c
  60. 19 19
      src/map/battle.c
  61. 5 32
      src/map/chrif.c
  62. 72 53
      src/map/clif.c
  63. 0 2
      src/map/clif.h
  64. 36 77
      src/map/guild.c
  65. 160 195
      src/map/homunculus.c
  66. 75 136
      src/map/itemdb.c
  67. 1 1
      src/map/itemdb.h
  68. 84 92
      src/map/map.c
  69. 80 136
      src/map/mercenary.c
  70. 13 13
      src/map/mob.c
  71. 15 15
      src/map/npc.c
  72. 2 2
      src/map/party.c
  73. 43 49
      src/map/pc.c
  74. 1 2
      src/map/pc.h
  75. 16 16
      src/map/pet.c
  76. 86 41
      src/map/script.c
  77. 104 121
      src/map/skill.c
  78. 111 113
      src/map/status.c
  79. 2 1
      src/map/storage.c
  80. 2 1
      src/map/trade.c
  81. 68 67
      src/map/unit.c
  82. 25 8
      src/map/vending.c
  83. 1 1
      src/map/vending.h
  84. 1 9
      src/plugins/Makefile.in
  85. 4 3
      src/plugins/console.c
  86. 0 107
      src/plugins/gui.c
  87. 0 15
      src/plugins/gui.txt
  88. 3 0
      src/plugins/pid.def
  89. 11 0
      src/plugins/sample.def
  90. 28 10
      src/tool/Makefile.in
  91. 0 103
      src/tool/adduser.c
  92. 0 844
      src/tool/grfio.c
  93. 0 20
      src/tool/grfio.h
  94. 31 27
      src/tool/mapcache.c
  95. 0 85
      tools/checkversion.pl
  96. 0 149
      vcproj-10/ladmin.vcxproj
  97. 0 1
      vcproj-10/login-server_sql.vcxproj
  98. 0 1
      vcproj-10/login-server_txt.vcxproj
  99. 17 4
      vcproj-10/mapcache.vcxproj
  100. 0 4
      vcproj-6/login-server_sql.dsp

+ 2 - 0
Changelog-Renewal.txt

@@ -1,5 +1,7 @@
 Date	Added
 
+2011/01/29
+	* Merged changes from trunk (r14636:14686). [Ai4rei]
 2010/12/30
 	* Fixed a nullpo crash in pc_gainexp when receiving exp though script command getexp (topic:262958, since r14625). [Ai4rei]
 2010/12/27

+ 3 - 10
Makefile.in

@@ -2,7 +2,7 @@
 
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)
-	ALL_DEPENDS=common common_sql login login_sql char char_sql map map_sql ladmin tools converters plugins import save
+	ALL_DEPENDS=common common_sql login login_sql char char_sql map map_sql tools converters plugins import save
 	SQL_DEPENDS=common_sql login_sql char_sql map_sql import save
 	COMMON_SQL_DEPENDS=
 	LOGIN_SQL_DEPENDS=common_sql
@@ -10,7 +10,7 @@ ifeq ($(HAVE_MYSQL),yes)
 	MAP_SQL_DEPENDS=common_sql
 	CONVERTERS_DEPENDS=common_sql
 else
-	ALL_DEPENDS=common login char map ladmin tools plugins import save
+	ALL_DEPENDS=common login char map tools plugins import save
 	SQL_DEPENDS=needs_mysql
 	COMMON_SQL_DEPENDS=needs_mysql
 	LOGIN_SQL_DEPENDS=needs_mysql
@@ -25,7 +25,7 @@ endif
 	login login_sql \
 	char char_sql \
 	map map_sql \
-	ladmin tools converters plugins addons import save \
+	tools converters plugins addons import save \
 	clean help
 
 all: $(ALL_DEPENDS)
@@ -60,9 +60,6 @@ map: common
 map_sql: $(MAP_SQL_DEPENDS)
 	@$(MAKE) -C src/map sql
 
-ladmin: common
-	@$(MAKE) -C src/ladmin
-
 tools:
 	@$(MAKE) -C src/tool
 
@@ -96,7 +93,6 @@ clean:
 	@$(MAKE) -C src/char $@
 	@$(MAKE) -C src/char_sql $@
 	@$(MAKE) -C src/map $@
-	@$(MAKE) -C src/ladmin $@
 	@$(MAKE) -C src/plugins $@
 	@$(MAKE) -C src/tool $@
 	@$(MAKE) -C src/txt-converter $@
@@ -112,7 +108,6 @@ help:
 	@echo "'char_sql'    - builds char server (SQL version)"
 	@echo "'map'         - builds map server (TXT version)"
 	@echo "'map_sql'     - builds map server (SQL version)"
-	@echo "'ladmin'      - builds remote administration tool"
 	@echo "'tools'       - builds all the tools in src/tools"
 	@echo "'converters'  - builds the login/char converters"
 	@echo "'plugins'     - builds all the plugins in src/plugins"
@@ -148,7 +143,6 @@ install:	conf/%.conf conf/%.txt
 	$(shell mv npc /opt/eathena/etc/eathena/npc)
 	$(shell mv log/* /opt/eathena/var/log/eathena/)
 	$(shell cp *-server* /opt/eathena/bin/)
-	$(shell cp ladmin /opt/eathena/bin/)
 	$(shell ln -s /opt/eathena/etc/eathena/save/ /opt/eathena/bin/)
 	$(shell ln -s /opt/eathena/etc/eathena/db/ /opt/eathena/bin/)
 	$(shell ln -s /opt/eathena/etc/eathena/conf/ /opt/eathena/bin/)
@@ -159,7 +153,6 @@ bin-clean:
 	$(shell rm /opt/eathena/bin/login-server*)
 	$(shell rm /opt/eathena/bin/char-server*)
 	$(shell rm /opt/eathena/bin/map-server*)
-	$(shell rm /opt/eathena/bin/ladmin)
 
 uninstall:
 	$(shell read -p "WARNING: This target does not work properly yet. Press Ctrl+C to cancel or Enter to continue.")

+ 4 - 0
conf/Changelog.txt

@@ -1,5 +1,9 @@
 Date	Added
 
+2011/01/13
+	* Rev. 14667 Removed ladmin settings (ladmin_athena.conf) and login-server settings for ladmin (login_athena.conf) (topic:262934). [Ai4rei]
+2010/12/30
+	* Rev. 14643 Updated mapcache up to 2010-12-01. Adds Bifrost, Dewata and Malangdo maps. [Ai4rei]
 2010/12/12
 	* Rev. 14587 Corrected wording of the setting homunculus_autoloot (since r12203). [Ai4rei]
 2010/12/10

+ 0 - 4
conf/atcommand_athena.conf

@@ -124,10 +124,6 @@ accept: 1,1
 reject: 1,1
 leave: 1,1
 
-// Away messsage
-away: 1,1
-aw: 1,1
-
 // Main chat
 main: 1,1
 

+ 0 - 0
conf/import-tmpl/ladmin_conf.txt


+ 0 - 31
conf/ladmin_athena.conf

@@ -1,31 +0,0 @@
-// Athena Ladmin configuration file.
- 
-// Login Server IP
-login_ip:127.0.0.1
-// Login Server Port
-login_port: 6900
-
-// Administrative password, used to connect remotely to server.
-// NOTICE: If you enable remote administration, you should change its value for security
-admin_pass: admin
-
-// Encoding type of the password
-// 0: not encoded
-// 1: key+password
-// 2: password+key
-passenc: 2
-
-// Log Filename. All operations done by the software are logged in this file.
-ladmin_log_filename: log/ladmin.log
-
-// Indicate how to display date in logs, to players, etc.
-// 0: 31-12-2004 23:59:59
-// 1: 12-31-2004 23:59:59
-// 2: 2004-31-12 23:59:59
-// 3: 2004-12-31 23:59:59 (default)
-date_format: 3
-
-//If redirected output contains escape sequences (color codes)
-stdout_with_ansisequence: no
-
-import: conf/import/ladmin_conf.txt

+ 0 - 10
conf/login_athena.conf

@@ -35,16 +35,6 @@ stdout_with_ansisequence: no
 //Example: "console_silent: 7" Hides information, status and notice messages (1+2+4)
 console_silent: 0
 
-// Whether remote administration is enabled or disabled
-admin_state: no
-
-// Administrative password, used by ladmin to connect remotely to server.
-// NOTICE: you should change this value for security if you use ladmin.
-admin_pass: admin
-
-// Indicate the IP/host that the server accepts for remote administration.
-admin_allowed_host: 127.0.0.1
-
 // Console Commands
 // Allow for console commands to be used on/off
 // This prevents usage of >& log.file

+ 48 - 5
conf/maps_athena.conf

@@ -898,8 +898,7 @@ map: spl_in01
 map: spl_in02
 
 // 3rd Job Maps
-// -- 2009-05-27??
-map: moc_para01
+// -- 2009-01-29rdata_k2.gpf
 map: job3_arch01
 map: job3_arch02
 map: job3_arch03
@@ -915,16 +914,24 @@ map: job3_war01
 map: job3_war02
 map: jupe_core2
 
+// ???
+// -- 2009-05-27rdata_k.gpf
+map: moc_para01
+
 // Brasilis Maps
-// -- 2009-08-05??
+// -- 2009-08-05rdata_k.gpf
 map: brasilis
 map: bra_in01
 map: bra_fild01
 map: bra_dun01
 map: bra_dun02
 
+// ???
+// -- 2009-09-30rdata_k.gpf
+map: s_atelier
+
 // 13.3 El Discastes
-// -- 2009-12-23
+// -- 2009-12-09rdata_k.gpf
 map: dicastes01
 map: dicastes02
 map: dic_in01
@@ -933,7 +940,6 @@ map: dic_fild02
 map: dic_dun01
 map: dic_dun02
 map: job3_gen01
-map: s_atelier
 map: job3_sha01
 
 // Localized Event Maps
@@ -946,6 +952,43 @@ map: job3_sha01
 //ac_cl_room
 //jp_s_dun11
 
+// 14.1 Bifrost
+// -- 2010-06-09rdata_x.gpf
+map: mora
+map: bif_fild01
+map: bif_fild02
+map: 1@mist
+
+// Dewata Maps
+// -- 2010-09-15rdata_x.gpf
+map: dewata
+map: dew_in01
+map: dew_fild01
+map: dew_dun01
+map: dew_dun02
+
+// ???
+// -- 2010-10-06rdata_x.gpf
+map: que_house_s
+
+// Malangdo Maps
+// -- 2010-11-03rdata_x.gpf
+map: malangdo
+map: mal_in01
+map: mal_in02
+map: mal_dun01
+map: 1@pump
+map: 2@pump
+map: 1@cash
+
+// Undersea Tunnel Expansion
+// -- 2010-11-10rdata_x.gpf
+map: iz_dun05
+
+// ???
+// -- 2010-12-01data_x.gpf
+map: evt_mobroom
+
 //------------------------- Clone Maps ---------------------------
 //------------------------- Extra Maps ---------------------------
 

+ 1 - 7
conf/msg_athena.conf

@@ -453,13 +453,7 @@
 //541: %.0s%.0sSomeone got %s
 542: '%s' stole %s's %s (chance: %0.02f%%)
 //542: %.0s%.0sSomeone stole %s
-// @Away message bits
-543: (Automessage has been sent)
-544: Away [AT] - "%s"
-545: Away - "%s"
-546: Away automessage has been activated.
-547: Away automessage has been disabled.
-548: Usage: @away,@aw <message>. Enter empty message for disable it.
+// 543~548 are not used (previously @away messages)
 // @Autotrade
 549: You should be vending to use @autotrade.
 

+ 1 - 2
configure

@@ -1333,7 +1333,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
                     ac_config_files="$ac_config_files Makefile src/common/Makefile"
 
-                              ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile src/ladmin/Makefile"
+                              ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
 
                     ac_config_files="$ac_config_files src/char_sql/Makefile src/txt-converter/Makefile"
 
@@ -5628,7 +5628,6 @@ do
   "src/common/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/common/Makefile" ;;
   "src/char/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/char/Makefile" ;;
   "src/login/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
-  "src/ladmin/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ladmin/Makefile" ;;
   "src/char_sql/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/char_sql/Makefile" ;;
   "src/txt-converter/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/txt-converter/Makefile" ;;
   "src/map/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;

+ 1 - 1
configure.in

@@ -6,7 +6,7 @@ AC_REVISION($Revision$)
 AC_PREREQ([2.59])
 AC_CONFIG_SRCDIR([src/common/cbasetypes.h])
 AC_CONFIG_FILES([Makefile src/common/Makefile])
-AC_CONFIG_FILES([src/char/Makefile src/login/Makefile src/ladmin/Makefile])
+AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
 AC_CONFIG_FILES([src/char_sql/Makefile src/txt-converter/Makefile])
 AC_CONFIG_FILES([src/map/Makefile src/plugins/Makefile src/tool/Makefile])
 

+ 19 - 0
db/Changelog.txt

@@ -8,6 +8,25 @@
 	1475 Equestrian's Spear:	NEED INFO.
 	13005 Angelic Wing Dagger:	NEED INFO.
 =======================
+
+2011/01/23
+	* Rev. 14679 Updated Aegis NPC ID constants from current npcidentity.lub (bugreport:4706). [Ai4rei]
+	- Fixes some incorrect NPC ID constants (since r12780).
+2011/01/06
+	* Rev. 14653 Updated mapcache once more, because the one from r14643 contained official xmas versions of the town maps, now causing glitches after the xmas event on kRO ended. [Ai4rei]
+2011/01/04
+	* Rev. 14650 Shuffled around disabled headgears, more accurate to what is and isn't avaliable in kRO. Snuck in a few minor fixes. [L0ne_W0lf]
+	* Rev. 14649 Disabled monster BACSOJIN_T (1996) whose drop White Snake Hat (5411) is not enabled (was hidden by '//', which would cause errors now) (since r14412). [Ai4rei]
+2010/12/30
+	* Rev. 14643 Updated mapcache up to 2010-12-01. Adds Bifrost, Dewata and Malangdo maps. [Ai4rei]
+	* Rev. 14641 Bug fixes. Not much else. :3
+	- Lowered the required level to equip Expert Ring from 90 to 50. (bugreport:2853)
+	- Changed equip location for Odin mask, and made it non-refinable. (bugreport:4221)
+	- Changed the weight of the Atroce Blade from 200 to 350. (bugreport:4405)
+	- Added Tatacho Card to Tatacho's drops. (bugreport:4469)
+	- Changed Crunch Toast generated by the F_Toast_Box. (Bugreport:4610)
+	- Corrected typo with Dagger of Hunter, casts Bash level 10 at 10% chance (bugreport:4667)
+	- Corrected Veteran Hammer, now uses bHealPower instead of bSkillheal. (bugreport:4670)
 2010/12/27
 	* Rev. 14634 Added item stacking limitation database 'item_stack.txt'. [Ai4rei]
 2010/12/16

+ 145 - 7
db/const.txt

@@ -1506,7 +1506,7 @@ WARPNPC	45
 4W_F_01	101
 8_F	102
 8_F_GRANDMOTHER	103
-//104	is	shadow	sprite
+EFFECTLAUNCHER	104
 8W_SOLDIER	105
 1_M_MOC_LORD	106
 1_M_PAY_ELDER	107
@@ -1528,9 +1528,6 @@ HIDDEN_NPC	111
 2_F_MAGICMASTER	123
 4_F_TELEPORTER	124
 4_M_TELEPORTER	125
-//Free	Ids
-HIDDEN_WARP_NPC	139
-//Free	Ids
 4_M_MUT2	401
 4_M_SCIENCE	402
 4_F_VALKYRIE2	403
@@ -1558,7 +1555,147 @@ HIDDEN_WARP_NPC	139
 4_M_BONGUN	425
 4_BEAR	426
 4_BLUEWOLF	427
-4_PECO-PECO	428
+4_PECOPECO	428
+4_M_JP_MID	429
+4_M_JP_RUN	430
+4_ORCLADY	431
+4_ORCLADY2	432
+4_ORCWARRIOR	433
+4_ORCWARRIOR2	434
+4_F_FAIRY	435
+4_F_FAIRYKID	436
+4_F_FAIRYKID2	437
+4_F_FAIRYKID3	438
+4_F_FAIRYKID4	439
+4_F_FAIRYKID5	440
+4_F_FAIRYKID6	441
+4_M_FAIRYKID	442
+4_M_FAIRYKID2	443
+4_M_FAIRYKID3	444
+4_M_FAIRYKID4	445
+4_M_FAIRYKID5	446
+4_M_FAIRYSOLDIER	447
+4_M_TUFFOLD	448
+4_MAN_BENKUNI	449
+4_MAN_GALTUN	450
+4_MAN_JERUTOO	451
+4_MAN_LAVAIL	452
+4_MAN_NITT	453
+4_MAN_PIOM	454
+4_MAN_PIOM2	455
+4_M_DSTMAN	456
+4_M_DSTMANDEAD	457
+4_BABYLEOPARD	458
+4_M_REDSWORD	459
+4_MAN_PIOM3	460
+4_M_FAIRYSOLDIER2	461
+4_F_FAIRYSOLDIER	462
+4_DRAGON_EGG	463
+4_MIMIC	464
+4_F_FAIRY1	465
+4_F_GUILLOTINE	466
+4_M_GUILLOTINE	467
+4_M_KNIGHT_BLACK	468
+4_M_KNIGHT_GOLD	469
+4_M_KNIGHT_SILVER	470
+4_SKULL_MUD	471
+4_M_BRZ_INDIAN	472
+4_F_BRZ_INDIAN	473
+4_F_BRZ_INDOLD	474
+4_M_BRZ_JACI	475
+4_M_BRZ_MAN1	476
+4_M_BRZ_MAN2	477
+4_F_BRZ_WOMAN	478
+4_M_MINSTREL	479
+4_M_MINSTREL1	480
+4_M_SHADOWCHASER	481
+4_F_SHADOWCHASER	482
+4_M_SURA	483
+4_F_SURA	484
+4_F_WANDERER	485
+4_M_BARD	486
+1_FLAG_NOFEAR	487
+4_M_NOFEARGUY	488
+4_MAN_PIOM6	489
+4_MAN_PIOM4	490
+4_MAN_PIOM5	491
+4_MAN_GALTUN1	492
+4_HUMAN_GERUTOO	493
+4_M_ROKI	494
+4_M_MERCAT1	495
+4_M_MERCAT2	496
+4_M_CATMAN1	497
+4_M_CATMAN2	498
+4_F_BRZ_WOMAN2	499
+4_M_JP_DISH	500
+4_F_JP_NOAH	501
+4_F_JP_OZ	502
+4_F_JP_CHROME	503
+4_F_JP_RINNE	504
+4_WHITETIGER	505
+4_VENDING_MACHINE	506
+4_MISTY	507
+4_NECORING	508
+4_ELEPHANT	509
+4_F_NYDHOG	510
+4_F_NYDHOG2	511
+4_M_ROKI2	512
+4_M_DOGTRAVELER	513
+4_M_DOGTRAVELER2	514
+4_F_DOGTRAVELER	515
+4_M_RAFLE_GR	516
+4_M_RAFLE_OLD	517
+4_F_RAFLE_PK	518
+4_M_LYINGDOG	519
+4_F_MORAFINE1	520
+4_F_MORAFINE2	521
+4_M_RAFLE_OR	522
+4_F_RAFLE_YE	523
+4_M_RAFLE_VI	524
+4_F_RAFLE_VI	525
+4_M_ARDHA	526
+4_CREEPER	527
+JP_RUFAKU	528
+JP_SUPIKA	529
+JP_SABIKU	530
+JP_ARUGORU	531
+JP_ARUNA	532
+JP_AIRI	533
+4_M_DEWOLDMAN	534
+4_M_DEWOLDWOMAN	535
+4_M_DEWMAN	536
+4_M_DEWWOMAN	537
+4_M_DEWBOY	538
+4_M_DEWGIRL	539
+4_M_DEWZATICHIEF	540
+4_M_DEWZATIMAN	541
+4_M_ALCHE_E	542
+4_MASK_SMOKEY	543
+4_CAT_SAILOR1	544
+4_CAT_SAILOR2	545
+4_CAT_SAILOR3	546
+4_CAT_SAILOR4	547
+4_CAT_CHEF	548
+4_CAT_MERMASTER	549
+4_CRACK	550
+4_ASTER	551
+4_F_STARFISHGIRL	552
+4_CAT_DOWN	553
+4_CAT_REST	554
+4_CAT_3COLOR	555
+4_CAT_ADMIRAL	556
+4_SOIL	557
+4_F_ALCHE_A	558
+4_CAT_ADV1	559
+4_CAT_ADV2	560
+4_CAT_SAILOR5	561
+2_DROP_MACHINE	562
+2_SLOT_MACHINE	563
+2_VENDING_MACHINE1	564
+MOB_TOMB	565
+4_MYSTCASE	566
+4_M_SIT_NOVICE	567
+4_OCTOPUS_LEG	568
 //Free	Ids
 8_F_GIRL	700
 4_F_GODEMOM	701
@@ -1582,7 +1719,7 @@ HIDDEN_WARP_NPC	139
 4_F_NACORURI	719
 4_F_SHAMAN	720
 4_F_KAFRA7	721
-GUILDFLAG90_1	722
+GUILD_FLAG	722
 1_SHADOW_NPC	723
 4_F_07	724
 4_F_JOB_ASSASSIN	725
@@ -1704,6 +1841,7 @@ TW_TOWER	812
 4_M_THAIAYO	841
 4_M_THAIOLD	842
 4_M_THAIONGBAK	843
+CLEAR_NPC	844
 4_F_RACING	845
 4_F_EINOLD	846
 4_M_EINOLD	847
@@ -1770,8 +1908,8 @@ TW_TOWER	812
 4_M_PHILMAN	908
 4_PORING	909
 2_COLAVEND	910
-4_M_SOCCER7	912
 4_F_SOCCER	911
+4_M_SOCCER7	912
 4_M_SOCCER9	913
 4_F_CHILD	914
 4_F_MADAME	915

+ 113 - 112
db/item_db.txt

@@ -525,7 +525,7 @@
 1172,Claymore_,Claymore,4,74000,,2500,180,,1,2,0x00004080,7,2,34,3,33,1,3,{},{},{}
 1173,Muramasa_C,Muramasa,4,1,,0,204,,1,0,0x00004082,7,2,34,4,1,0,3,{ bonus bCritical,30; bonus bAspdRate,8; },{},{}
 1174,Executioner_C,Executioner,4,2,,0,190,,1,0,0x00004082,7,2,34,4,1,0,3,{ bonus bIgnoreDefRace,RC_DemiHuman; bonus2 bAddRace,RC_DemiHuman,20; bonus2 bSubRace,RC_DemiHuman,-10; bonus bAtkEle,Ele_Dark; },{},{}
-1175,Altas_Weapon,Atlas Weapon,4,20,,2000,200,,1,1,0x00004082,2,2,34,4,55,1,3,{ bonus bCritical,10; if(readparam(bStr)>=80) bonus bBreakArmorRate,500; },{},{}
+1175,Altas_Weapon,Atlas Weapon,4,20,,3500,200,,1,1,0x00004082,2,2,34,4,55,1,3,{ bonus bCritical,10; if(readparam(bStr)>=80) bonus bBreakArmorRate,500; },{},{}
 1176,Muscle_Cutter,Muscle Cutter,4,20,,2200,160,,1,2,0x00004082,2,2,34,4,55,1,3,{ bonus2 bAddEff,Eff_Bleeding,800; bonus3 bAutoSpell,"AL_DECAGI",1,30; },{},{}
 1177,Muramash,Muramash,4,20,,0,120,,1,0,0x00004082,7,2,34,1,1,0,3,{ bonus2 bAddRace,RC_Boss,50; bonus2 bAddRace,RC_NonBoss,50; },{},{}
 1178,Schweizersabel_,Schweizersabel,4,20,,1600,160,,1,2,0x00004082,7,2,34,4,48,1,3,{ bonus bAtkEle,Ele_Wind; bonus bDef,1; bonus3 bAutoSpell,"MG_LIGHTNINGBOLT",3,100; },{},{}
@@ -686,7 +686,7 @@
 1384,Veteran_Axe,Veteran Axe,4,0,,3000,250,,1,2,0x000444A2,7,2,34,3,80,1,7,{ if(getskilllv("BS_DAGGER")==3) { bonus bAtk,10; } if(getskilllv("BS_SWORD")==3) { bonus bAtk,10; } if(getskilllv("BS_TWOHANDSWORD")==3) { bonus bAtk,10; } if(getskilllv("BS_KNUCKLE")==3) { bonus bAtk,10; } if(getskilllv("BS_SPEAR")==3) { bonus bAtk,10; } if(getskilllv("BS_AXE")==3) { bonus bAtk,10; } if(getskilllv("BS_MACE")==3) { bonus bAtk,10; } bonus bVit,2; },{},{}
 1385,Bradium_Stonehammer,Bradium Stone Hammer,4,0,,2700,210,,1,0,0x000444A2,2,2,34,4,75,1,7,{ bonus3 bAddEffOnSkill,"BS_HAMMERFALL",Eff_Stun,50+(20*getrefine()); },{},{}
 1386,Doom_Slayer_I,Doom Slayer,4,20,,0,20,,1,0,0x000444A2,7,2,34,4,0,0,7,{ if(readparam(bStr)>=95){ bonus bBaseAtk,400; bonus2 bAddEff,Eff_Stun,3000; bonus bAspdRate,-25; bonus bUseSPrate,100; bonus bBreakArmorRate,500; } },{},{}
-1387,Giant_Axe,Giant Axe,4,0,,4000,330,,1,1,0x000444A2,2,2,34,3,50,1,6,{ bonus2 bSkillAtk,"WS_CARTTERMINATION",15; if(readparam(bStr)>=95) { bonus bHit,10; bonus bAspdRate,3; } },{},{}
+1387,Giant_Axe,Giant Axe,4,0,,4000,330,,1,1,0x000444A2,2,2,34,3,50,1,7,{ bonus2 bSkillAtk,"WS_CARTTERMINATION",15; if(readparam(bStr)>=95) { bonus bHit,10; bonus bAspdRate,3; } },{},{}
 1388,Two_Handed_Axe_C,Two-Handed Axe,4,0,,0,220,,1,0,0x000444A2,7,2,34,3,1,0,7,{ bonus2 bAddSize,0,40; bonus2 bAddSize,1,40; bonus2 bAddSize,2,40; },{},{}
 // 1-Handed Spears
 1401,Javelin,Javelin,4,150,,700,28,,3,3,0x00004082,7,2,2,1,4,1,4,{},{},{}
@@ -808,7 +808,7 @@
 1545,N_Mace,Novice Mace,4,1,,0,57,,1,3,0x0004C5B3,7,2,2,1,2,0,8,{},{},{}
 1546,Krieger_Onehand_Mace1,Glorious Morning Star,4,0,,0,130,,1,0,0x0004C5B3,7,2,2,4,80,1,8,{ bonus2 bAddRace,RC_DemiHuman,75; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; bonus bAspdRate,5; } if(getrefine() > 8) { bonus2 bAddEff,Eff_Stun,2000; bonus bAspdRate,5; } },{},{}
 1547,Mace_Of_Madness,Mace Of Madness,4,0,,0,150,,1,0,0x0004C5B2,7,2,2,2,1,0,8,{ bonus2 bSkillAtk,"MC_CARTREVOLUTION",25; bonus bStr,2; },{},{}
-1548,Veteran_Hammer,Veteran Hammer,4,0,,1800,160,,1,2,0x00008110,7,2,2,3,80,1,8,{ bonus2 bSkillAtk,"AL_HEAL",getskilllv("AL_DP"); bonus bCriticalRate,getskilllv("PR_MACEMASTERY")*2; bonus bInt,1; bonus bLuk,1; },{},{}
+1548,Veteran_Hammer,Veteran Hammer,4,0,,1800,160,,1,2,0x00008110,7,2,2,3,80,1,8,{ bonus bHealPower,getskilllv("AL_DP"); bonus bCritical,getskilllv("PR_MACEMASTERY")*2; bonus bInt,1; bonus bLuk,1; },{},{}
 //1549,Pilebuncker
 // Books
 1550,Book,Book,4,30000,,600,85,,1,3,0x00410100,7,2,2,2,14,1,15,{},{},{}
@@ -1548,7 +1548,7 @@
 2700,Red_Silk_Seal,Red Silk Seal,5,10000,,100,,0,,0,0x00004082,2,2,136,,0,0,0,{},{},{}
 2701,Orleans_Glove,Orleans's Glove,5,10000,,100,,0,,1,0xFFFFFFFE,2,2,136,,90,0,0,{ bonus bDex,2; bonus bMatkRate,3; },{},{}
 2702,Bison_Horn,Bison Horn,5,10000,,100,,0,,1,0xFFFFFFFE,2,2,136,,90,0,0,{ bonus bAgi,2; },{},{}
-2703,Expert_Ring,Expert Ring,5,10000,,150,,0,,1,0xFFFFFFFE,2,2,136,,90,0,0,{ bonus bDelayRate,-5; bonus bUseSPrate,5; },{},{}
+2703,Expert_Ring,Expert Ring,5,10000,,150,,0,,1,0xFFFFFFFE,2,2,136,,50,0,0,{ bonus bDelayRate,-5; bonus bUseSPrate,5; },{},{}
 2704,Golden_Accessory,Golden Accessories,5,20,,100,,4,,0,0xFFFFFFFF,7,2,136,,,,,{ bonus bMdef,4; },{},{}
 2705,Golden_Accessory2,Golden Accessories,5,20,,100,,4,,0,0xFFFFFFFF,7,2,136,,,,,{ bonus2 bAddMonsterDropItem,12018,500; },{},{}
 2706,Handcuff,Arrest Handcuffs,5,20,,10,,0,,0,0xFFFFFFFE,7,2,136,,0,0,0,{},{},{}
@@ -1572,7 +1572,7 @@
 2724,Medal_Archer,Medal of Honor,5,0,,0,,1,,0,0x00080808,7,2,136,,70,0,0,{ bonus2 bAddRace,RC_NonBoss,5; bonus2 bAddRace,RC_Boss,5; bonus bMatkRate,5; bonus bCritical,10; bonus bMaxHP,300; bonus bMaxSP,80; bonus3 bAddEff,Eff_Blind,100,ATF_LONG; },{},{}
 2725,Medal_Merchant,Medal of Honor,5,0,,0,,1,,0,0x00040420,7,2,136,,70,0,0,{ bonus2 bAddRace,RC_NonBoss,5; bonus2 bAddRace,RC_Boss,5; bonus bMatkRate,5; bonus bAspdRate,10; bonus bMaxHP,500; bonus bMaxSP,50; bonus3 bAddEff,Eff_Curse,100,ATF_SHORT; },{},{}
 2726,Icarus_Wing,Icarus Wings,5,20,,100,,0,,0,0x00000800,2,2,136,,70,0,0,{ bonus bMaxSP,50; bonus bDex,3; },{},{}
-2727,Bowman_Scarf,Bowman Scarf,5,20,,200,,0,,0,0x00000800,2,2,136,,0,0,0,{ bonus bMaxSP,50; bonus bDex,3; if (isequipped(2726)) bonus bUseSPrate,-25; },{},{}
+2727,Bowman_Scarf,Bowman Scarf,5,20,,200,,0,,0,0x00000800,2,2,136,,70,0,0,{ bonus bMaxSP,50; bonus bDex,3; if (isequipped(2726)) bonus bUseSPrate,-25; },{},{}
 2728,Cursed_Hand,Cursed Hand,5,0,,50,,0,,1,0xFFFFFFFE,7,2,136,,80,0,0,{ bonus3 bAutoSpell,"NPC_CRITICALWOUND",1,30; bonus bHit,10; bonus bHPrecovRate,20; },{},{}
 2729,Diabolus_Ring,Diabolus Ring,5,0,,50,,0,,1,0x000FDF80,2,2,136,,0,0,0,{ bonus bMaxHP,100; bonus bMaxSP,100; bonus bHealPower,5; bonus2 bAddDamageClass,1916,10; bonus2 bAddDamageClass,1917,10; },{},{}
 2730,Morroc_Seal,Seal of Continental Guard,5,0,,50,,0,,1,0xFFFFFFFE,7,2,136,,80,0,0,{ bonus bMaxHP,50; bonus bAspdRate,3; },{},{}
@@ -2500,7 +2500,7 @@
 5292,Dragon_Skull,Dragon Skull,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,50,1,319,{ bonus2 bSubRace,RC_Dragon,5; },{},{}
 5293,Ramen_Hat,Ramen Hat,5,20,,0,,1,,0,0xFFFFFFFF,7,2,256,,0,1,320,{ bonus bDex,4; bonus4 bAutoSpellWhenHit,"AL_DECAGI",1,30,1; },{},{}
 5294,Whisper_Mask,Whisper Mask,5,20,,0,,0,,0,0xFFFFFFFF,7,2,769,,0,0,321,{ bonus bAgi,3; bonus2 bSubEle,Ele_Ghost,-10; },{},{}
-//5295,Golden_Bandana,Golden Bandana,5,20,,2400,,4,,0,0xFFFFFFFF,7,2,768,,,1,138,{ bonus bMdef,4; },{},{}
+5295,Golden_Bandana,Golden Bandana,5,20,,2400,,4,,0,0xFFFFFFFF,7,2,768,,,1,138,{ bonus bMdef,4; },{},{}
 5296,Drooping_Nine_Tail_,Drooping Nine Tail,5,20,,300,,1,,1,0xFFFFFFFF,7,2,256,,0,0,296,{ bonus bAgi,1; bonus bCritical,1; },{},{}
 5297,Soulless_Wing_,Soul Wing,5,20,,300,,2,,1,0xFFFFFFFF,7,2,256,,0,0,301,{ bonus bAllStats,1; bonus2 bSPRegenRate,2,10000; },{},{}
 5298,Marvelous_Wig_,Dokebi's Wig,5,20,,100,,1,,1,0xFFFFFFFF,7,2,768,,0,0,302,{ bonus2 bSubEle,Ele_Neutral,5; bonus2 bSubEle,Ele_Fire,-5; bonus2 bSubEle,Ele_Water,-5; },{},{}
@@ -2512,22 +2512,22 @@
 5304,Cap_Of_Blindness,Cap Of Blindness,5,20,,800,,4,,1,0xFFFFFFFF,7,2,769,,50,1,326,{ bonus2 bResEff,Eff_Curse,700; bonus2 bResEff,Eff_Blind,10000; },{},{}
 5305,Pirate_Dagger,Pirate Dagger,5,20,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,0,327,{ bonus bBaseAtk,5; },{},{}
 //5306,Freyja_Crown,Freya's Crown,5,0,,500,,12,,0,0xFFFFFFFE,7,2,256,,0,0,328,{ bonus2 bSubRace,RC_DemiHuman,5; },{},{}
-5307,Carmen_Miranda's_Hat,Carmen Miranda's Hat,5,20,,400,,3,,0,0xFFFFFFFF,7,0,256,,0,1,329,{ bonus bMdef,3; bonus3 bAutoSpellWhenHit,"DC_WINKCHARM",1,50; },{},{}
+//5307,Carmen_Miranda's_Hat,Carmen Miranda's Hat,5,20,,400,,3,,0,0xFFFFFFFF,7,0,256,,0,1,329,{ bonus bMdef,3; bonus3 bAutoSpellWhenHit,"DC_WINKCHARM",1,50; },{},{}
 //5308,Brazilian_Flag_Hat,Brazil National Flag Hat,5,20,,300,,3,,1,0xFFFFFFFF,7,0,256,,0,1,330,{ bonus bSpeedAddRate,25; },{},{}
 //5309,Mahican,Wool Mask,5,20,,200,,1,,0,0xFFFFFFFF,7,0,769,,0,1,331,{ skill "RG_GRAFFITI",1; },{},{}
-5310,Bulb_Hairband,Shining Electric Bulb Hairband,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,0,0,332,{ bonus2 bSubEle,Ele_Dark,10; skill "MG_SIGHT",1; },{},{ sc_end SC_SIGHT; }
-5311,Large_Hibiscus,Large Hisbiscus,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,0,333,{ bonus bMdef,15; },{},{}
+//5310,Bulb_Hairband,Shining Electric Bulb Hairband,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,0,0,332,{ bonus2 bSubEle,Ele_Dark,10; skill "MG_SIGHT",1; },{},{ sc_end SC_SIGHT; }
+//5311,Large_Hibiscus,Large Hisbiscus,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,0,333,{ bonus bMdef,15; },{},{}
 //5312,Ayothaya_Hat,Ayothaya King's Hat,5,20,,100,,5,,1,0x000654E2,7,2,256,,0,1,334,{ bonus bStr,1; bonus2 bAddRace,RC_DemiHuman,5; },{},{}
 5313,Diadem,Diadem,5,20,,100,,3,,1,0xFFFFFFFF,7,2,768,,0,1,335,{ bonus bInt,1; bonus bMatkRate,3; bonus bCastrate,-3; },{},{}
 5314,Hockey_Mask,Hockey Mask,5,20,,100,,1,,0,0xFFFFFFFF,7,2,513,,50,0,336,{ bonus2 bAddRace,RC_DemiHuman,5; },{},{}
 5315,Observer,Observer,5,20,,100,,1,,0,0xFFFFFFFF,7,2,512,,35,0,337,{ skill "WZ_ESTIMATION",1; },{},{}
-5316,Umbrella_Hat,Umbrella Hat,5,20,,100,,2,,0,0xFFFFFFFF,7,2,256,,50,1,338,{ bonus2 bSubEle,Ele_Water,3; },{},{}
+//5316,Umbrella_Hat,Umbrella Hat,5,20,,100,,2,,0,0xFFFFFFFF,7,2,256,,50,1,338,{ bonus2 bSubEle,Ele_Water,3; },{},{}
 //5317,Fisherman_Hat,Fisherman's Hat,5,20,,100,,2,,0,0xFFFFFFFF,7,2,256,,50,1,339,{ bonus3 bAutoSpell,"WZ_WATERBALL",3,50; },{},{}
 5318,Poring_Party_Hat,Poring Party Hat,5,20,,700,,2,,0,0xFFFFFFFF,7,2,256,,0,1,340,{ bonus bAllStats,3; },{},{}
 //5319,Hellomother_Hat,Hello Mother Hat,5,20,,200,,2,,0,0xFFFFFFFE,7,2,256,,10,1,341,{ bonus bLuk,3; },{},{}
 5320,Champion_Wreath,Champion Wreath,5,20,,500,,4,,0,0xFFFFFFFF,7,2,256,,0,1,261,{ bonus bAllStats,2; bonus4 bAutoSpellWhenHit,"AL_HEAL",1,50,0; },{},{}
 //5321,Indonesian_Bandana,Bandana Merah Putih,5,20,,500,,4,,0,0xFFFFFFFF,7,2,256,,0,1,342,{ bonus2 bAddMonsterDropItem,518,100; },{},{}
-5322,Scarf,Kerchief,5,20,,100,,2,,0,0xFFFFFFFF,7,2,256,,24,0,343,{ bonus bFlee,5; bonus bMdef,2; },{},{}
+//5322,Scarf,Kerchief,5,20,,100,,2,,0,0xFFFFFFFF,7,2,256,,24,0,343,{ bonus bFlee,5; bonus bMdef,2; },{},{}
 5323,Misstrance_Crown,Misstrance Crown,5,20,,0,,10,,0,0xFFFFFFFF,7,2,256,,1,0,165,{ bonus bAllStats,2; },{},{}
 5324,Little_Angel_Doll,Little Angel Doll,5,20,,300,,2,,0,0xFFFFFFFF,7,2,256,,10,0,344,{ bonus bDex,3; bonus4 bAutoSpellWhenHit,"CR_GRANDCROSS",3,30,0; },{},{}
 5325,Robo_Eye,Robo Eye,5,20,,200,,2,,0,0xFFFFFFFF,7,2,512,,10,0,345,{ bonus2 bAddRace,RC_NonBoss,2; bonus2 bAddRace,RC_Boss,2; bonus bMatkRate,2; bonus bDex,1; },{},{}
@@ -2540,7 +2540,7 @@
 5332,Loki_Mask,Loki Mask,5,0,,200,,0,,0,0xFFFFFFFF,7,2,513,,1,0,346,{ bonus bFlee2,3; },{},{}
 5333,Radio_Antenna,Radio Antenna,5,0,,1500,,2,,0,0xFFFFFFFF,7,2,256,,50,0,347,{ bonus bMdef,5; bonus bCritical,5; bonus bFlee,5; skill "MG_LIGHTNINGBOLT",1; bonus4 bAutoSpellWhenHit,"MG_THUNDERSTORM",5,30,1; },{},{}
 5334,Angeling_Wanna_Fly,Flapping Angeling,5,0,,700,,0,,0,0xFFFFFFFF,7,2,256,,38,1,348,{ bonus bLuk,2; bonus bMdef,2; },{},{}
-5335,Jumping_Poring,Jumping Poring,5,0,,300,,2,,0,0xFFFFFFFF,7,2,256,,10,1,349,{ bonus bLuk,1; bonus bUnbreakableHelm,0; },{},{}
+//5335,Jumping_Poring,Jumping Poring,5,0,,300,,2,,0,0xFFFFFFFF,7,2,256,,10,1,349,{ bonus bLuk,1; bonus bUnbreakableHelm,0; },{},{}
 5336,Guildsman_Recruiter,Guildsman Recruiter Hat,5,,,0,,2,,0,0xFFFFFFFF,7,2,256,,10,1,350,{},{},{}
 5337,Party_Recruiter_Hat,Party Recruiter Hat,5,0,,0,,2,,0,0xFFFFFFFF,7,2,256,,10,1,351,{},{},{}
 5338,Bf_Recruiter_Hat,Bf Recruiter Hat,5,0,,0,,2,,0,0xFFFFFFFF,7,2,256,,10,1,352,{},{},{}
@@ -2563,7 +2563,7 @@
 5355,Muslim_Hat_F,Selendang,5,20,,100,,2,,0,0xFFFFFFFE,7,0,256,,0,1,363,{ bonus bCastrate,-5; },{},{}
 5356,Pumpkin_Hat_H,Festival Pumpkin Hat,5,20,,200,,2,,0,0xFFFFFFFF,7,2,256,,0,1,206,{ bonus2 bSubRace,RC_Demon,5; bonus2 bAddRace,RC_Demon,5; },{},{}
 5357,Wings_Of_Victory,Wings Of Victory,5,20,,0,,10,,0,0xFFFFFFFF,7,2,768,,0,1,365,{ bonus bMdef,10; bonus bUnbreakableHelm,0; },{},{}
-5358,Pecopeco_Wing_Ears,Peco Ears,5,20,,100,,1,,0,0xFFFFFFFF,7,2,512,,70,0,366,{ bonus bAgi,1; bonus bMdef,2; },{},{}
+//5358,Pecopeco_Wing_Ears,Peco Ears,5,20,,100,,1,,0,0xFFFFFFFF,7,2,512,,70,0,366,{ bonus bAgi,1; bonus bMdef,2; },{},{}
 5359,J_Captain_Hat,Ship Captain Hat,5,20,,500,,3,,1,0xFFFFFFFF,7,2,256,,30,1,367,{ bonus bLongAtkRate,7; bonus bMaxHP,100; },{},{}
 5360,Whikebain_Ears,Hyuke's Black Cat Ears,5,20,,200,,2,,0,0xFFFFFFFF,7,2,256,,45,1,368,{ bonus bFlee,10; bonus bCritical,3; bonus2 bCriticalAddRace,RC_Boss,10; bonus2 bCriticalAddRace,RC_NonBoss,10; bonus bDefRate,-50; bonus bDef2Rate,-50; },{},{}
 5361,Gang_Scarf,Gangster Scarf,5,20,,100,,0,,0,0xFFFFFFFF,7,2,1,,60,0,369,{ bonus bBaseAtk,5; if(BaseJob == Job_Rogue) skill "RG_GANGSTER",1; },{},{}
@@ -2572,17 +2572,17 @@
 5364,Dark_Snake_Lord_Hat,Evil Snake Lord Hat,5,20,,500,,2,,1,0xFFFFFFFF,7,2,256,,60,1,372,{ bonus bStr,1; bonus bInt,1; bonus bAgi,2; },{},{}
 5365,Fried_Egg,Magnolia Hat,5,20,,1000,,3,,1,0xFFFFFFFF,7,2,256,,0,0,373,{ bonus2 bResEff,Eff_Stun,500; skill "HT_FLASHER",1; },{},{}
 //5366,Hat_0f_King,Love Dad Bandana,5,20,,200,,3,,0,0xFFFFFFFF,7,2,256,,0,1,374,{ bonus bStr,2; },{},{}
-5367,Hyegun_Hat,Hyegun Hat,5,20,,100,,5,,1,0xFFFFFFFF,7,2,769,,10,0,375,{ bonus bMdef,3; bonus2 bSubRace,RC_Demon,10; },{},{}
+//5367,Hyegun_Hat,Hyegun Hat,5,20,,100,,5,,1,0xFFFFFFFF,7,2,769,,10,0,375,{ bonus bMdef,3; bonus2 bSubRace,RC_Demon,10; },{},{}
 5368,White_Wing,White Wing,5,20,,100,,2,,0,0xFFFFFFFE,7,2,256,,0,1,38,{ bonus2 bAddMonsterDropItem,12280,300; },{},{}
 5369,Dark_Wing,Dark Wing,5,20,,100,,1,,0,0xFFFFFFFE,7,2,256,,0,1,39,{ bonus2 bAddMonsterDropItem,12279,300; },{},{}
-5370,Orchid_Hairband,Orchid Hairband,5,20,,200,,1,,0,0xFFFFFFFF,7,2,256,,0,1,376,{ bonus bInt,1; },{},{}
-5371,Hat_Of_Judge,Judge Hat,5,20,,300,,2,,0,0xFFFFFFFF,7,2,256,,0,1,377,{ bonus bLuk,1; bonus bMaxSP,30; },{},{}
+//5370,Orchid_Hairband,Orchid Hairband,5,20,,200,,1,,0,0xFFFFFFFF,7,2,256,,0,1,376,{ bonus bInt,1; },{},{}
+//5371,Hat_Of_Judge,Judge Hat,5,20,,300,,2,,0,0xFFFFFFFF,7,2,256,,0,1,377,{ bonus bLuk,1; bonus bMaxSP,30; },{},{}
 5372,Drooping_White_Kitty,Koneko Hat,5,20,,500,,1,,0,0xFFFFFFFF,7,2,256,,0,1,378,{ bonus bInt,1; bonus bDelayRate,-3; bonus bMatkRate,3; bonus bMaxSPrate,3; bonus bMdef,3; },{},{}
 5373,Darkness_Helm,Dark Randgris Helm,5,20,,300,,2,,1,0xFFFFFFFF,7,2,768,,0,1,379,{ bonus bDex,4; bonus bMdef,1; },{},{}
 5374,L_Magestic_Goat,Gigantic Majestic Goat,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,0,1,380,{ bonus2 bAddRace,RC_DemiHuman,12; bonus bBaseAtk,(JobLevel*2)/7; },{},{}
 5375,L_Orc_Hero_Helm,Orc Hero Headdress,5,20,,900,,5,,1,0xFFFFFFFF,7,2,768,,0,1,381,{ bonus bStr,3; bonus3 bAutoSpellWhenHit,"BS_WEAPONPERFECT",3,10; },{},{}
 //5376,Satanic_Chain_P,Flying Evil Wing,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,0,1,382,{ bonus bMaxSP,120; bonus3 bAddEffWhenHit,Eff_Curse,100,ATF_SELF; },{},{}
-5377,Antique_Pipe,Gentleman's Pipe,5,20,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,0,383,{ bonus2 bSubRace,RC_DemiHuman,2; },{},{}
+//5377,Antique_Pipe,Gentleman's Pipe,5,20,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,0,383,{ bonus2 bSubRace,RC_DemiHuman,2; },{},{}
 5378,Rabbit_Ear_Hat,Bunny Top Hat,5,20,,300,,0,,0,0xFFFFFFFF,7,2,256,,0,1,384,{ bonus bAgi,3; bonus3 bAutoSpellWhenHit,"AL_INCAGI",5,10; },{},{}
 5379,Balloon_Hat,Tam,5,20,,800,,3,,1,0xFFFFFFFF,7,2,256,,0,1,385,{ bonus bMatkRate,2+(getrefine()/2); },{},{}
 5380,Fish_Head_Hat,Fish Head Hat,5,20,,400,,1,,0,0xFFFFFFFF,7,2,256,,0,1,386,{ bonus3 bAutoSpell,"SA_FROSTWEAPON",1,5; },{},{}
@@ -2590,12 +2590,12 @@
 5382,Bell_Ribbon,Bell Ribbon,5,20,,200,,3,,1,0xFFFFFFFF,7,2,256,,0,1,388,{ bonus bVit,1; skill "AL_ANGELUS",1; },{},{ sc_end SC_ANGELUS; }
 5383,Hunting_Cap,Hunter's Cap,5,20,,250,,3,,1,0xFFFFFFFE,7,2,256,,50,1,389,{ bonus bLuk,1; bonus2 bAddRace,RC_Brute,10; bonus2 bAddRace,RC_DemiHuman,5; },{},{}
 5384,Santa_Hat_1,Twin Pompom By JB,5,20,,100,,1,,1,0xFFFFFFFE,7,2,256,,0,1,390,{ bonus bAllStats,1; skill "WZ_ESTIMATION",1; bonus3 bAutoSpell,"AL_INCAGI",1,500; },{},{}
-5385,Yoyo_Hat,Yoyo Hat,5,20,,300,,1,,0,0xFFFFFFFF,7,2,256,,20,1,391,{ skill "TF_HIDING",1; },{},{ sc_end SC_HIDING; }
+//5385,Yoyo_Hat,Yoyo Hat,5,20,,300,,1,,0,0xFFFFFFFF,7,2,256,,20,1,391,{ skill "TF_HIDING",1; },{},{ sc_end SC_HIDING; }
 5386,Ayam_,Ayam,5,20,,70,,7,,0,0xFFFFFFFF,7,2,256,,0,0,228,{ bonus bMdef,7; bonus bFlee,7; bonus2 bAddMonsterDropItem,12198,200; },{},{}
 5387,Neko_Mimi_Kafra,Neko Mimi Kafra,5,20,,200,,1,,1,0xFFFFFFFF,7,2,256,,30,1,392,{ bonus bMdef,5; },{},{}
 //5388,Snake_Head,Snake Head Hat,5,20,,200,,1,,1,0xFFFFFFFE,7,2,256,,30,1,393,{ bonus bDoubleRate,25; },{},{}
 5389,Angel_Spirit,Angel Spirit,5,20,,200,,0,,0,0xFFFFFFFE,7,2,512,,30,0,394,{ bonus bHit,15; },{},{}
-5390,Santa_Hat_2,Frozen Twin Pompom,5,20,,100,,2,,0,0xFFFFFFFE,7,2,256,,0,1,395,{ bonus2 bResEff,Eff_Freeze,3000; },{},{}
+//5390,Santa_Hat_2,Frozen Twin Pompom,5,20,,100,,2,,0,0xFFFFFFFE,7,2,256,,0,1,395,{ bonus2 bResEff,Eff_Freeze,3000; },{},{}
 5391,Toast_C,Toast,5,20,,100,,0,,0,0xFFFFFFFE,7,2,1,,0,0,188,{ bonus bMaxHP,100; bonus2 bAddMonsterDropItem,617,10; },{},{}
 //5392,Louyang_Cap,Louyang NewYear Hat,5,20,,300,,3,,1,0xFFFFFFFE,7,2,256,,0,1,396,{ bonus bLuk,2; bonus2 bAddMonsterDropItem,668,3; },{},{}
 //5393,Valentine_Hat,Love Valentine's Hat,5,20,,200,,2,,0,0xFFFFFFFE,7,2,256,,0,0,397,{ bonus bMaxSPrate,7; bonus bMaxHPrate,7; },{},{}
@@ -2606,40 +2606,40 @@
 5398,Bone_Head,Bone Head,5,20,,1200,,5,,1,0x000444A2,2,2,256,,85,1,401,{ bonus bStr,2; bonus bMdef,5; bonus2 bResEff,Eff_Stun,500; bonus2 bResEff,Eff_Bleeding,500; },{},{}
 5399,Mandragora_Cap,Mandragora Cap,5,20,,300,,1,,1,0xFFFFFFFF,2,2,256,,85,0,402,{ bonus bVit,3; bonus3 bAutoSpellWhenHit,"DC_SCREAM",5,30; },{},{}
 5400,Fox_Hat,Fox Hat,5,20,,200,,1,,0,0xFFFFFFFF,7,0,769,,0,1,403,{ bonus bLuk,1; },{},{}
-5401,Black_Glasses,Black Frame Glasses,5,20,,200,,1,,0,0xFFFFFFFF,7,2,512,,70,0,404,{ bonus bInt,1; bonus bMdef,2; },{},{}
-5402,Mischievous_Fairy,Mischievous Fairy,5,20,,200,,1,,0,0xFFFFFFFF,7,2,512,,70,0,405,{ bonus bFlee2,3; },{},{}
+//5401,Black_Glasses,Black Frame Glasses,5,20,,200,,1,,0,0xFFFFFFFF,7,2,512,,70,0,404,{ bonus bInt,1; bonus bMdef,2; },{},{}
+//5402,Mischievous_Fairy,Mischievous Fairy,5,20,,200,,1,,0,0xFFFFFFFF,7,2,512,,70,0,405,{ bonus bFlee2,3; },{},{}
 5403,Fish_In_Mouth,Fish In Mouth,5,20,,200,,0,,0,0xFFFFFFFF,7,2,1,,30,0,406,{ bonus2 bAddMonsterDropItem,579,500; bonus2 bAddItemHealRate,579,25; },{},{}
-5404,Blue_Ribbon,Blue Ribbon,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,45,1,407,{ bonus4 bAutoSpellWhenHit,"AC_CONCENTRATION",2,7,0; },{},{}
-5405,Filir_Hat,Filir Hat,5,20,,200,,0,,0,0xFFFFFFFF,7,2,256,,80,0,408,{ bonus bShortWeaponDamageReturn,1; },{},{}
-5406,Academy_Freshman_Hat,Academy Freshman Hat,5,20,,200,,1,,0,0xFFFFFFFF,7,0,256,,0,,409,{ bonus bMaxHP,80; bonus bMaxSP,10; },{},{}
-5407,Academy_Graduating_Cap,Academy Completion Hat,5,20,,200,,1,,1,0xFFFFFFFF,7,0,256,,0,,410,{ bonus bMaxSP,30; },{},{}
+//5404,Blue_Ribbon,Blue Ribbon,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,45,1,407,{ bonus4 bAutoSpellWhenHit,"AC_CONCENTRATION",2,7,0; },{},{}
+//5405,Filir_Hat,Filir Hat,5,20,,200,,0,,0,0xFFFFFFFF,7,2,256,,80,0,408,{ bonus bShortWeaponDamageReturn,1; },{},{}
+//5406,Academy_Freshman_Hat,Academy Freshman Hat,5,20,,200,,1,,0,0xFFFFFFFF,7,0,256,,0,,409,{ bonus bMaxHP,80; bonus bMaxSP,10; },{},{}
+//5407,Academy_Graduating_Cap,Academy Completion Hat,5,20,,200,,1,,1,0xFFFFFFFF,7,0,256,,0,,410,{ bonus bMaxSP,30; },{},{}
 5408,Old_Bandanna,Old Bandana,5,20,,200,,5,,0,0xFFFFFFFF,7,0,256,,0,,6,{ bonus bInt,2; bonus bMaxSP,50; bonus bCastrate,10; },{},{}
 5409,New_Cowboy_Hat,Purple Cowboy Hat,5,20,,500,,4,,1,0xFFFFFFFF,7,2,256,,0,1,411,{ bonus bMaxSP,50; bonus bInt,2; bonus bVit,2; },{},{}
-5410,Bread_Bag2,Brown Paperbag Hat,5,20,,200,,6,,0,0xFFFFFFFF,7,2,769,,0,1,412,{ bonus bMaxHP,100; bonus2 bResEff,Eff_Stun,400; bonus2 bSubRace,RC_DemiHuman,4; },{},{}
+//5410,Bread_Bag2,Brown Paperbag Hat,5,20,,200,,6,,0,0xFFFFFFFF,7,2,769,,0,1,412,{ bonus bMaxHP,100; bonus2 bResEff,Eff_Stun,400; bonus2 bSubRace,RC_DemiHuman,4; },{},{}
 //5411,White_Snake_Hat,White Snake Hat,5,20,,500,,2,,0,0xFFFFFFFF,7,2,256,,0,1,413,{ bonus bDex,2; },{},{}
-5412,Sweet_Candy,Sweet Candy,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,0,0,414,{},{},{}
+//5412,Sweet_Candy,Sweet Candy,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,0,0,414,{},{},{}
 //5413,Popcorn_Hat,Pop Corn Hat,5,20,,300,,2,,0,0xFFFFFFFF,7,2,256,,0,1,415,{ bonus2 bSubEle,Ele_Wind,10; },{},{}
 //5414,Campfire_Hat,Camp Fire Hat,5,20,,300,,2,,0,0xFFFFFFFF,7,2,256,,0,1,416,{ bonus4 bAutoSpellWhenHit,"MG_FIREBALL",5,100,1; bonus2 bSubEle,Ele_Fire,10; },{},{}
 5415,Poring_Cake_Cap,Poring Cake Hat,5,20,,1000,,5,,0,0xFFFFFFFF,7,2,256,,40,1,417,{ bonus bMdef,5; bonus bCritical,5; bonus bFlee,5; bonus bFlee2,5; bonus bAspdRate,5; bonus bCastrate,-5; bonus bDelayRate,-5; },{},{}
 //5416,Beer_Cap,Beer Hat,5,20,,600,,2,,0,0xFFFFFFFE,7,2,256,,18,1,418,{ bonus bFlee2,5; skill "SM_RECOVERY",3; skill "MG_SRECOVERY",3; },{},{}
-5417,Crown_Parrot,Crown Parrots,5,20,,200,,1,,1,0xFFFFFFFF,7,2,256,,0,0,419,{ bonus2 bResEff,Eff_Silence,10000; bonus3 bAutoSpell,"DC_SCREAM",1,50; bonus bInt,1; },{},{}
-5418,Soldier_Hat,Legionnaire Hat,5,20,,400,,4,,1,0xFFFFFFFF,7,2,256,,0,1,420,{ bonus bStr,1; bonus2 bAddRace,RC_NonBoss,3; bonus2 bAddRace,RC_Boss,3; },{},{}
+//5417,Crown_Parrot,Crown Parrots,5,20,,200,,1,,1,0xFFFFFFFF,7,2,256,,0,0,419,{ bonus2 bResEff,Eff_Silence,10000; bonus3 bAutoSpell,"DC_SCREAM",1,50; bonus bInt,1; },{},{}
+//5418,Soldier_Hat,Legionnaire Hat,5,20,,400,,4,,1,0xFFFFFFFF,7,2,256,,0,1,420,{ bonus bStr,1; bonus2 bAddRace,RC_NonBoss,3; bonus2 bAddRace,RC_Boss,3; },{},{}
 5419,Evolved_Leaf,Leaves Of Grass,5,,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,0,57,{ bonus bVit,1; bonus2 bSubRace,RC_Plant,5; },{},{}
-//5420,Mask_Of_Ifrit,Mask Of Ifrit,5,,,0,,8,,0,0xFFFFFFFE,7,2,769,,70,0,421,{ bonus bStr,1; bonus bInt,1; bonus bMdef,5; bonus2 bSubEle,Ele_Fire,10; bonus2 bSubEle,Ele_Water,-10; skill "MG_SIGHT",1; bonus3 bAutoSpellWhenHit,"WZ_METEOR",3,50; bonus3 bAutoSpell,"MG_FIREBOLT",3,50; },{},{ sc_end SC_SIGHT; }
+5420,Mask_Of_Ifrit,Mask Of Ifrit,5,,,0,,8,,0,0xFFFFFFFE,7,2,769,,70,0,421,{ bonus bStr,1; bonus bInt,1; bonus bMdef,5; bonus2 bSubEle,Ele_Fire,10; bonus2 bSubEle,Ele_Water,-10; skill "MG_SIGHT",1; bonus3 bAutoSpellWhenHit,"WZ_METEOR",3,50; bonus3 bAutoSpell,"MG_FIREBOLT",3,50; },{},{ sc_end SC_SIGHT; }
 5421,Ifrit's_Ear,Ears Of Ifrit,5,,,0,,0,,0,0xFFFFFFFE,7,2,512,,70,0,422,{ bonus bStr,1; bonus bMdef,3; bonus2 bSkillAtk,"MG_FIREBOLT",2; bonus2 bSkillAtk,"WZ_FIREPILLAR",2; bonus2 bSkillAtk,"WZ_METEOR",2; bonus2 bSkillAtk,"SM_BASH",2; bonus2 bSkillAtk,"SM_MAGNUM",2; bonus2 bSkillAtk,"KN_PIERCE",2; bonus2 bSubEle,Ele_Fire,5; bonus2 bSubEle,Ele_Water,-5; },{},{}
 //5422,Linguistic_Book_Cap,Linguistic Book Hat,5,,,70,,0,,0,0xFFFFFFFF,7,2,256,,0,0,423,{ bonus bInt,1; bonus bMdef,2; },{},{}
 //5423,Lovecap_China,I Love China,5,,,250,,5,,0,0xFFFFFFFF,7,2,256,,0,0,424,{ bonus bDex,3; bonus2 bSubRace,RC_DemiHuman,10; },{},{}
-5424,Fanta_Orange_Can,Fanta Orange Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,425,{},{},{}
-5425,Fanta_Grape_Can,Fanta Grape Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,426,{},{},{}
-5426,Karada_Meguri_Tea_Hat,Karada Meguricha Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,427,{ bonus bLuk,1; },{},{}
-5427,Royal_Milk_Tea_Hat,Black Tea Kochakaden Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,428,{ bonus bAgi,1; },{},{}
+//5424,Fanta_Orange_Can,Fanta Orange Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,425,{},{},{}
+//5425,Fanta_Grape_Can,Fanta Grape Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,426,{},{},{}
+//5426,Karada_Meguri_Tea_Hat,Karada Meguricha Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,427,{ bonus bLuk,1; },{},{}
+//5427,Royal_Milk_Tea_Hat,Black Tea Kochakaden Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,428,{ bonus bAgi,1; },{},{}
 5428,Bread_Bag1,RWC Anniversary Bread Envelope,5,,,100,,0,,0,0xFFFFFFFF,7,2,769,,0,1,429,{ bonus2 bSubRace,RC_DemiHuman,12; },{},{}
 //5429,Bogy_Cap,Bogy Cap,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,430,{ bonus bHPrecovRate,5; bonus bSPrecovRate,5; },{},{}
-5430,Sacred_Torch_Coronet,Torch Cap,5,,,250,,3,,0,0xFFFFFFFF,7,2,256,,0,0,431,{ bonus2 bSubEle,Ele_Fire,20; skill "MG_FIREBOLT",5; },{},{}
+//5430,Sacred_Torch_Coronet,Torch Cap,5,,,250,,3,,0,0xFFFFFFFF,7,2,256,,0,0,431,{ bonus2 bSubEle,Ele_Fire,20; skill "MG_FIREBOLT",5; },{},{}
 5431,Chicken_Hat,Chicken Hat,5,,,100,,0,,1,0xFFFFFFFF,7,2,256,,30,0,432,{ bonus3 bAutoSpell,"MC_LOUD",1,30; bonus bAspdRate,5; },{},{}
 //5432,Brazil_Baseball_Cap,bRO 4th Anniversary Hat,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,0,0,433,{ bonus bAllStats,4; },{},{}
 //5433,Golden_Wreath,Golden Laurel,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,0,0,434,{},{},{}
-5434,Coke_Hat,Coca Cola Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,435,{},{},{}
+//5434,Coke_Hat,Coca Cola Can Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,435,{},{},{}
 5435,Red_Minstrel_Hat,Red Minstrel Hat,5,,,100,,1,,1,0xFFFFFFFF,7,2,256,,40,1,436,{ bonus bInt,1; bonus bMaxSP,80; bonus bMdef,3; if(getrefine()>5) { bonus bMdef,getrefine()-5; bonus bMaxSP,(getrefine()-5)*10; } },{},{}
 5436,Bride's_Corolla,Bride's Corolla,5,,,200,,1,,0,0xFFFFFFFF,7,2,256,,0,1,437,{ bonus bLuk,3; bonus bMdef,2; },{},{}
 5437,Flower_Of_Fairy,Fairy Flower,5,,,200,,1,,1,0xFFFFFFFF,7,2,256,,0,1,438,{ bonus bInt,1; bonus bMdef,1; bonus2 bSubRace,RC_Insect,5; },{},{}
@@ -2656,42 +2656,42 @@
 5448,Solo_Play_Box1,Soloplay Box1,5,,,300,,0,,1,0xFFFFFFFF,7,2,769,,0,1,449,{},{},{}
 5449,Solo_Play_Box2,Soloplay Box2,5,,,300,,0,,1,0xFFFFFFFF,7,2,769,,0,1,450,{},{},{}
 //5450,Sun_Cap,Solar Hat,5,,,1000,,0,,0,0xFFFFFFFE,7,2,256,,20,1,451,{},{},{}
-//5451,Dragonhelm_Gold,RWC 2008 Dragon Helm Gold,5,,,2500,,7,,0,0xFFFFFFFF,7,2,256,,0,0,452,{ bonus bAspdRate,10; bonus bAllStats,3; bonus2 bAddRace,RC_DemiHuman,5; },{},{}
-//5452,Dragonhelm_Silver,RWC 2008 Dragon Helm Silver,5,,,2500,,5,,0,0xFFFFFFFF,7,2,256,,0,0,453,{ bonus bAspdRate,7; bonus bAllStats,2; bonus2 bAddRace,RC_DemiHuman,3; },{},{}
-//5453,Dragonhelm_Copper,RWC 2008 Dragon Helm Copper,5,,,2500,,0,,0,0xFFFFFFFF,7,2,256,,0,0,454,{ bonus bAspdRate,5; bonus bAllStats,2; bonus2 bAddRace,RC_DemiHuman,1; },{},{}
+5451,Dragonhelm_Gold,RWC 2008 Dragon Helm Gold,5,,,2500,,7,,0,0xFFFFFFFF,7,2,256,,0,0,452,{ bonus bAspdRate,10; bonus bAllStats,3; bonus2 bAddRace,RC_DemiHuman,5; },{},{}
+5452,Dragonhelm_Silver,RWC 2008 Dragon Helm Silver,5,,,2500,,5,,0,0xFFFFFFFF,7,2,256,,0,0,453,{ bonus bAspdRate,7; bonus bAllStats,2; bonus2 bAddRace,RC_DemiHuman,3; },{},{}
+5453,Dragonhelm_Copper,RWC 2008 Dragon Helm Copper,5,,,2500,,0,,0,0xFFFFFFFF,7,2,256,,0,0,454,{ bonus bAspdRate,5; bonus bAllStats,2; bonus2 bAddRace,RC_DemiHuman,1; },{},{}
 5454,Dog_Cap_,Puppy Hat,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,0,1,234,{ autobonus "{ bonus bCritical,100; }",10,3000,BF_WEAPON,"{ specialeffect2 EF_ENHANCE; }"; autobonus "{ bonus bIgnoreMdefRate,100; }",10,3000,BF_MAGIC,"{ specialeffect2 EF_MAGICALATTHIT; }"; },{},{}
 5455,Geographer_Band_,Decorative Geographer,5,,,500,,1,,1,0xFFFFFFFF,7,2,256,,0,1,238,{ bonus3 bAutoSpell,"AL_HEAL",5,50; bonus3 bAutoSpellWhenHit,"AL_HEAL",5,30; },{},{}
 5456,Vacation_Hat_,Summer Hat,5,,,200,,0,,1,0xFFFFFFFF,7,2,256,,0,1,315,{ bonus bHPrecovRate,20; bonus bSPrecovRate,15; },{},{}
 5457,Spring_Rabbit_Hat,Moon Rabbit Hat,5,,,300,,2,,1,0xFFFFFFFE,7,2,256,,0,1,455,{ bonus bAgi,3; bonus bBaseAtk,5; bonus bMatkRate,5; if (getrefine()>4) { bonus bBaseAtk,getrefine()-4; bonus bMatkRate,getrefine()-4; } },{},{}
-5458,Pinwheel_Cap,Pinwheel Hat,5,,,200,,2,,0,0xFFFFFFFF,7,2,256,,0,1,456,{ bonus bHPrecovRate,5; bonus bHPrecovRate,5; },{},{}
+//5458,Pinwheel_Cap,Pinwheel Hat,5,,,200,,2,,0,0xFFFFFFFF,7,2,256,,0,1,456,{ bonus bHPrecovRate,5; bonus bHPrecovRate,5; },{},{}
 5459,Drooping_Bunny_Chusuk,Drooping Bunny,5,,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,249,{ bonus bDex,1; bonus bFlee,2; },{},{}
 //5460,Adv_Dragon_Skull,Evolved Dragon Skull Hat,5,,,1000,,7,,0,0xFFFFFFFF,7,2,256,,60,1,457,{ bonus bAllStats,2; bonus bMaxHPrate,3; },{},{}
 //5461,Adv_Whisper_Mask,Evolved Whisper Mask,5,,,300,,1,,0,0xFFFFFFFF,7,2,769,,50,1,458,{ bonus bDex,3; bonus2 bSubEle,Ele_Ghost,20; },{},{}
-//5462,Spiked_Scarf,Spiked Scarf,5,,,100,,1,,0,0xFFFFFFFF,7,2,1,,90,0,459,{ bonus bVit,1; bonus2 bAddRace,RC_DemiHuman,1; bonus2 bSubRace,RC_DemiHuman,1; },{},{}
-//5463,Rainbow_Scarf,Rainbow Scarf,5,,,100,,1,,0,0xFFFFFFFF,7,2,1,,90,0,460,{ bonus bInt,1; bonus bMdef,2; bonus bMatkRate,1; },{},{}
+5462,Spiked_Scarf,Spiked Scarf,5,,,100,,1,,0,0xFFFFFFFF,7,2,1,,90,0,459,{ bonus bVit,1; bonus2 bAddRace,RC_DemiHuman,1; bonus2 bSubRace,RC_DemiHuman,1; },{},{}
+5463,Rainbow_Scarf,Rainbow Scarf,5,,,100,,1,,0,0xFFFFFFFF,7,2,1,,90,0,460,{ bonus bInt,1; bonus bMdef,2; bonus bMatkRate,1; },{},{}
 //5464,Zaha_Doll_Hat,Zaha Doll Hat,5,,,0,,1,,0,0xFFFFFFFF,7,2,256,,0,0,461,{ bonus bInt,2; skill "PR_MAGNIFICAT",3; },{},{}
-5465,Celestial_Hat,Hat Of Fortune,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,40,1,462,{ bonus bLuk,2; bonus bMdef,5; if(getrefine()>4) bonus bLuk,getrefine()-4; },{},{}
-5466,Wind_Milestone,Wind Milestone,5,,,100,,2,,0,0xFFFFFFFF,7,2,256,,30,1,463,{ bonus bAgi,2; skill "AL_TELEPORT",1; },{},{}
-5467,Helm_Of_Dragoon,Helm Of Dragon,5,,,200,,5,,0,0xFFFFFFFF,7,2,256,,50,1,464,{ bonus2 bAddRace,RC_Dragon,20; bonus3 bAutoSpell,"NPC_DRAGONFEAR",1,30; },{},{}
+//5465,Celestial_Hat,Hat Of Fortune,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,40,1,462,{ bonus bLuk,2; bonus bMdef,5; if(getrefine()>4) bonus bLuk,getrefine()-4; },{},{}
+//5466,Wind_Milestone,Wind Milestone,5,,,100,,2,,0,0xFFFFFFFF,7,2,256,,30,1,463,{ bonus bAgi,2; skill "AL_TELEPORT",1; },{},{}
+//5467,Helm_Of_Dragoon,Helm Of Dragon,5,,,200,,5,,0,0xFFFFFFFF,7,2,256,,50,1,464,{ bonus2 bAddRace,RC_Dragon,20; bonus3 bAutoSpell,"NPC_DRAGONFEAR",1,30; },{},{}
 5468,Parade_Cap,Parade Hat,5,,,800,,3,,0,0xFFFFFFFF,7,2,256,,1,1,465,{ bonus bDelayRate,-5; bonus bMdef,2; if(getrefine()>5) bonus bCastrate,-(getrefine()-5); },{},{}
-5469,Noble_Hat,Musketeer Hat,5,,,300,,2,,0,0xFFFFFFFF,7,2,256,,30,1,466,{ bonus bStr,2; bonus3 bAutoSpellWhenHit,"BS_ADRENALINE",1,7; },{},{}
-5470,Eyes_Of_Darkness,Eye Of Darkness,5,,,100,,1,,0,0xFFFFFFFF,7,2,512,,50,1,467,{ bonus bDex,1; bonus2 bResEff,Eff_Blind,10000; },{},{}
-5471,Hairband_Of_Reginleif,Hairband Of Reginleif,5,,,800,,1,,0,0xFFFFFFFF,7,2,512,,50,0,468,{ bonus2 bSubEle,Ele_Water,3; bonus2 bSubEle,Ele_Fire,3; bonus2 bSubEle,Ele_Undead,3; bonus2 bSubEle,Ele_Ghost,3; },{},{}
-5472,Red_White_Hat,Red Hat,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,0,1,469,{ bonus3 bAddMonsterDropItem,550,RC_DemiHuman,3; },{},{}
-5473,Forceps_Hairpin,Nipper Crab Hairpin,5,,,500,,4,,0,0xFFFFFFFF,7,2,256,,30,1,470,{ bonus3 bAutoSpellWhenHit,"MG_COLDBOLT",1,100; bonus3 bAddMonsterDropItem,991,RC_Fish,3; },{},{}
-5474,Notice_Board,AFK Hat,5,,,700,,2,,0,0xFFFFFFFF,7,2,256,,10,1,471,{},{},{}
-5475,Cube_Mask,Mask Cube,5,,,100,,1,,0,0xFFFFFFFF,7,2,513,,0,1,472,{},{},{}
+//5469,Noble_Hat,Musketeer Hat,5,,,300,,2,,0,0xFFFFFFFF,7,2,256,,30,1,466,{ bonus bStr,2; bonus3 bAutoSpellWhenHit,"BS_ADRENALINE",1,7; },{},{}
+//5470,Eyes_Of_Darkness,Eye Of Darkness,5,,,100,,1,,0,0xFFFFFFFF,7,2,512,,50,0,467,{ bonus bDex,1; bonus2 bResEff,Eff_Blind,10000; },{},{}
+//5471,Hairband_Of_Reginleif,Hairband Of Reginleif,5,,,800,,1,,0,0xFFFFFFFF,7,2,512,,50,0,468,{ bonus2 bSubEle,Ele_Water,3; bonus2 bSubEle,Ele_Fire,3; bonus2 bSubEle,Ele_Undead,3; bonus2 bSubEle,Ele_Ghost,3; },{},{}
+//5472,Red_White_Hat,Red Hat,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,0,1,469,{ bonus3 bAddMonsterDropItem,550,RC_DemiHuman,3; },{},{}
+//5473,Forceps_Hairpin,Nipper Crab Hairpin,5,,,500,,4,,0,0xFFFFFFFF,7,2,256,,30,1,470,{ bonus3 bAutoSpellWhenHit,"MG_COLDBOLT",1,100; bonus3 bAddMonsterDropItem,991,RC_Fish,3; },{},{}
+//5474,Notice_Board,AFK Hat,5,,,700,,2,,0,0xFFFFFFFF,7,2,256,,10,1,471,{},{},{}
+//5475,Cube_Mask,Mask Cube,5,,,100,,1,,0,0xFFFFFFFF,7,2,513,,0,1,472,{},{},{}
 5476,Hairband_Of_Grandpeco,Grand Peco Hairband,5,,,800,,2,,0,0xFFFFFFFF,7,2,768,,30,1,473,{ bonus bStr,2; bonus bMaxHPrate,-10; bonus2 bAddRace2,3,15; },{},{}
 //5477,Bro_Flag,Brazilian Flag Hat,5,,,100,,1,,0,0xFFFFFFFF,7,2,256,,30,1,474,{ skill "SM_BASH",1; },{},{}
-5478,Classic_Hat,Classic Hat,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,0,1,475,{ bonus bStr,2; bonus bMaxHP,300; },{},{}
+//5478,Classic_Hat,Classic Hat,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,0,1,475,{ bonus bStr,2; bonus bMaxHP,300; },{},{}
 5479,Shaman's_Hair_Ornament,Shaman's Hair Decoration,5,,,300,,1,,0,0xFFFFFFFF,7,2,256,,30,1,476,{ bonus bMdef,3; bonus bMaxHP,50; bonus2 bSubEle,Ele_Neutral,5; if(isequipped(2777,2778)) { bonus bMaxHP,300; bonus bMatkRate,5; bonus2 bSubEle,Ele_Neutral,5; } },{},{}
 5480,Bizofnil_Wing_Deco,Bijofnil Wings,5,,,1000,,3,,1,0xFFFFFFFF,7,2,256,,30,1,477,{ bonus3 bAutoSpell,"PR_IMPOSITIO",3,3; },{},{}
 5481,Hermose_Cap,Hermode Cap,5,,,1000,,1,,1,0xFFFFFFFF,7,2,256,,1,1,478,{ bonus bAspdRate,10; bonus bBaseAtk,-20; bonus bMatkRate,-10; },{},{}
 5482,Dark_Knight_Mask,Dark Knight Mask,5,,,3000,,5,,0,0xFFFFFFFF,7,2,769,,80,1,479,{ bonus bStr,3; if(isequipped(2779,2780)) { bonus bMatkRate,10; bonus bInt,5; bonus2 bSubRace,RC_Angel,10; } },{},{}
-5483,Odin_Mask,Odin Mask,5,,,100,,1,,0,0xFFFFFFFE,7,2,512,,50,1,480,{ bonus bHit,-10; bonus2 bAddRace,RC_Demihuman,6; },{},{}
+5483,Odin_Mask,Odin Mask,5,,,100,,1,,0,0xFFFFFFFE,7,2,513,,50,0,480,{ bonus bHit,-10; bonus2 bAddRace,RC_Demihuman,6; },{},{}
 //5484,Taiwan_Flag_Hat,Holidays Hat,5,,,500,,4,,0,0xFFFFFFFF,7,2,256,,0,1,482,{ bonus bAllStats,5; bonus2 bResEff,Eff_Stun,500; },{},{}
-5485,Tiger_Face,Tiger Face,5,,,1000,,3,,0,0xFFFFFFFF,7,2,769,,60,1,483,{ bonus2 bSubRace,RC_Brute,5; bonus2 bAddRace,RC_Brute,5; bonus2 bMagicAddRace,RC_Brute,5; },{},{}
-5486,J_Anniversary_Hat,Anniversary Hat,5,,,300,,3,,0,0xFFFFFFFF,7,2,256,,0,1,395,{ bonus bAllStats,2; },{},{}
+//5485,Tiger_Face,Tiger Face,5,,,1000,,3,,0,0xFFFFFFFF,7,2,769,,60,1,483,{ bonus2 bSubRace,RC_Brute,5; bonus2 bAddRace,RC_Brute,5; bonus2 bMagicAddRace,RC_Brute,5; },{},{}
+//5486,J_Anniversary_Hat,Anniversary Hat,5,,,300,,3,,0,0xFFFFFFFF,7,2,256,,0,1,395,{ bonus bAllStats,2; },{},{}
 5487,J_Poringcake_Hat,Poring Cake Hat,5,,,500,,1,,0,0xFFFFFFFF,7,2,256,,0,1,417,{ bonus bLuk,2; },{},{}
 5488,J_Twin_Santahat,Twin Santa Hat,5,,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,390,{ bonus bLuk,1; bonus bMdef,1; },{},{}
 //5489,Love_Daddy,Love Daddy Hat,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,0,1,484,{ bonus bDex,2; },{},{}
@@ -2703,48 +2703,48 @@
 //5495,Power_Of_Thor,Power Of Thor,5,0,,500,,6,,1,0xFFFFFFFF,7,2,256,,75,0,493,{ bonus bFlee,5; bonus bAllStats,1; },{},{}
 //5496,Dice_Hat,Dice Hat,5,0,,500,,3,,0,0xFFFFFFFF,7,2,256,,50,0,494,{ bonus bLuk,4; },{},{}
 //5497,King_Tiger_Doll_Hat,King Tiger Doll Hat,5,0,,400,,3,,1,0xFFFFFFFF,7,2,256,,30,0,495,{ bonus bStr,2; },{},{}
-5498,Wondering_Wolf_King_Hel,Wandering Wolf Hat,5,,,600,,5,,0,0xFFFFFFFE,7,2,768,,50,0,490,{ bonus bFlee,10; bonus bVit,5; },{},{}
-5499,Pizza_Hat,Pizza Hat,5,20,,6000,,0,,0,0xFFFFFFFF,7,2,256,,0,1,487,{ skill "SM_PROVOKE",1; },{},{}
-5500,Icecream_Hat,Icecream Hat,5,20,,300,,1,,0,0xFFFFFFFF,7,2,256,,30,1,488,{ skill "MG_FROSTDIVER",3; bonus bMdef,3; },{},{}
-5501,Pirate's_Pride,Pirate's Pride,5,20,,100,,3,,0,0xFFFFFFFF,7,2,256,,10,1,496,{ bonus2 bAddRace2,6,5; bonus2 bSubRace2,6,5; },{},{}
+//5498,Wondering_Wolf_King_Hel,Wandering Wolf Hat,5,,,600,,5,,0,0xFFFFFFFE,7,2,768,,50,0,490,{ bonus bFlee,10; bonus bVit,5; },{},{}
+//5499,Pizza_Hat,Pizza Hat,5,20,,6000,,0,,0,0xFFFFFFFF,7,2,256,,0,1,487,{ skill "SM_PROVOKE",1; },{},{}
+//5500,Icecream_Hat,Icecream Hat,5,20,,300,,1,,0,0xFFFFFFFF,7,2,256,,30,1,488,{ skill "MG_FROSTDIVER",3; bonus bMdef,3; },{},{}
+//5501,Pirate's_Pride,Pirate's Pride,5,20,,100,,3,,0,0xFFFFFFFF,7,2,256,,10,1,496,{ bonus2 bAddRace2,6,5; bonus2 bSubRace2,6,5; },{},{}
 5502,Necromencer's_Hood,Necromancer's Hood,5,,,100,,2,,1,0xFFFFFFFF,7,2,768,,10,1,491,{ bonus5 bAutoSpellWhenHit,"NPC_DARKSTRIKE",5,5,BF_WEAPON|BF_MAGIC,1; },{},{}
 5503,Rabbit_Magic_Hat,Magic Rabit Hat,5,20,,800,,2,,0,0xFFFFFFFF,7,2,256,,0,1,497,{ bonus bDex,2; bonus bAgi,2; bonus bMDef,1; bonus bMaxSP,50; bonus3 bAutoSpellWhenHit,"MG_FIREBOLT",1,10; bonus3 bAutoSpellWhenHit,"MG_COLDBOLT",1,10; bonus3 bAutoSpellWhenHit,"MG_LIGHTNINGBOLT",1,10; },{},{}
-5504,China_Wedding_Veil,Wedding Weil,5,20,,500,,1,,0,0xFFFFFFFF,7,2,768,,70,1,489,{ bonus bMDef,10; },{},{}
+//5504,China_Wedding_Veil,Wedding Weil,5,20,,500,,1,,0,0xFFFFFFFF,7,2,768,,70,1,489,{ bonus bMDef,10; },{},{}
 5505,Asara_Fairy_Hat,Asara Fairy Hat,5,20,,500,,2,,0,0xFFFFFFFF,7,2,256,,50,1,492,{ skill "DC_DONTFORGETME",1; bonus bDex,2; bonus bLuk,2; },{},{}
-5506,Blue_Pajamas_Hat,Blue Night Cap,5,20,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,501,{ bonus bBaseAtk,5; bonus bMatkRate,5; },{},{}
-5507,Pink_Pajamas_Hat,Pink Night Cap,5,20,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,502,{ bonus bBaseAtk,5; bonus bMatkRate,5; },{},{}
+//5506,Blue_Pajamas_Hat,Blue Night Cap,5,20,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,501,{ bonus bBaseAtk,5; bonus bMatkRate,5; },{},{}
+//5507,Pink_Pajamas_Hat,Pink Night Cap,5,20,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,502,{ bonus bBaseAtk,5; bonus bMatkRate,5; },{},{}
 5508,Shark_Hat,Shark Hat,5,,,500,,3,,0,0xFFFFFFFF,7,2,256,,0,1,503,{ bonus bStr,1; bonus bAgi,2; bonus bMdef,1; bonus2 bAddEle,Ele_Water,5; bonus2 bSubEle,Ele_Water,10; },{},{}
 5509,Sting_Hat,Sting hat,5,20,,100,,5,,0,0xFFFFFFFF,7,2,256,,0,1,504,{ bonus bStr,2; bonus bVit,1; bonus bMDef,3; bonus2 bAddEle,Ele_fire,5; bonus2 bSubEle,Ele_earth,5; bonus3 bAutoSpell,"WZ_EARTHSPIKE",1,10; },{},{}
-5510,Shower_Cap,Shower Cap,5,20,,0,,2,,0,0xFFFFFFFF,7,2,256,,0,1,507,{ bonus bMdef,3; bonus bFlee,3; bonus2 bAddEle,Ele_Water,10; bonus2 bSubRace,rc_fish,10; },{},{}
+//5510,Shower_Cap,Shower Cap,5,20,,0,,2,,0,0xFFFFFFFF,7,2,256,,0,1,507,{ bonus bMdef,3; bonus bFlee,3; bonus2 bAddEle,Ele_Water,10; bonus2 bSubRace,rc_fish,10; },{},{}
 5511,Samambaia,Samambaia,5,,,1000,,5,,1,0xFFFFFFFF,7,2,768,,30,1,508,{ bonus bSPrecovRate,8; },{},{}
-5512,Aquarius_Diadem,Aquarius Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,509,{ bonus bStr,2; bonus bFlee,10; bonus2 bSubEle,Ele_Wind,5; if(getrefine()>6) { bonus bDef,1; bonus bBaseAtk,15; } },{},{}
-5513,Aquarius_Crown,Aquarius Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,510,{ bonus bStr,2; bonus bFlee,10; bonus2 bSubEle,Ele_Wind,5; if(getrefine()>6) { bonus bDef,1; bonus bBaseAtk,15; } },{},{}
-5514,Pisces_Diadem,Pisces Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,511,{ bonus bInt,2; bonus bMDef,5; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bMatkRate,2; } },{},{}
-5515,Pisces_Crown,Pisces Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,512,{ bonus bInt,2; bonus bMDef,5; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bMatkRate,2; } },{},{}
-//5516,Hawk_Eyes01,hawk Eyes,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{},{},{}
-//5517,Hawk_Eyes02,Hawk Eyes,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{},{},{}
-5518,L_Magestic_Goat2,Gigantic Majestic Goat,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,50,1,513,{ bonus2 bSubRace,RC_DemiHuman,12; bonus bBaseAtk,(JobLevel*2)/7; },{},{}
-5519,Peacock_Feather,Peacock Feather,5,20,,800,,2,,1,0xFFFFFFFF,7,2,256,,0,1,514,{ bonus bInt,2; },{},{}
+//5512,Aquarius_Diadem,Aquarius Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,509,{ bonus bStr,2; bonus bFlee,10; bonus2 bSubEle,Ele_Wind,5; if(getrefine()>6) { bonus bDef,1; bonus bBaseAtk,15; } },{},{}
+//5513,Aquarius_Crown,Aquarius Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,510,{ bonus bStr,2; bonus bFlee,10; bonus2 bSubEle,Ele_Wind,5; if(getrefine()>6) { bonus bDef,1; bonus bBaseAtk,15; } },{},{}
+//5514,Pisces_Diadem,Pisces Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,511,{ bonus bInt,2; bonus bMDef,5; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bMatkRate,2; } },{},{}
+//5515,Pisces_Crown,Pisces Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,512,{ bonus bInt,2; bonus bMDef,5; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bMatkRate,2; } },{},{}
+5516,Hawk_Eyes01,hawk Eyes,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{},{},{}
+5517,Hawk_Eyes02,Hawk Eyes,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{},{},{}
+//5518,L_Magestic_Goat2,Gigantic Majestic Goat,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,50,1,513,{ bonus2 bSubRace,RC_DemiHuman,12; bonus bBaseAtk,(JobLevel*2)/7; },{},{}
+//5519,Peacock_Feather,Peacock Feather,5,20,,800,,2,,1,0xFFFFFFFF,7,2,256,,0,1,514,{ bonus bInt,2; },{},{}
 5520,Rabbit_Earplug,Rabbit Earplugs,5,,,400,,0,,1,0xFFFFFFFF,7,2,768,,1,1,515,{ bonus2 bAddRace,RC_NonBoss,4; bonus2 bAddRace,RC_Boss,4; bonus bMatkRate,4; },{},{}
 5521,Angry_Mouth_C,Angry Mouth,5,0,,0,,0,,0,0xFFFFFFFF,7,2,1,,0,0,194,{ bonus bDelayRate,-3; },{},{}
-5522,Fanta_Zero_Lemon_Hat,Fanta Zero Lemon Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,516,{},{},{}
-5523,Sakura_Mist_Hat,Sakura Mist Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,517,{ bonus bDex,1; },{},{}
-5524,Sakura_Milk_Tea_Hat,Sakura Milk Tea Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,518,{ bonus bVit,1; },{},{}
-5525,First_Leaf_Tea_Hat,Flower Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,519,{ bonus bMaxHP,80; bonus bMaxSP,20; },{},{}
-5526,Lady_Tanee_Doll,Tanigumi Girl Doll,5,,,300,,2,,0,0xFFFFFFFF,7,2,256,,60,1,520,{ bonus bAgi,2; bonus bFlee,3; bonus2 bAddEle,Ele_Wind,-5; bonus2 bAddMonsterDropItem,513,200; },{},{}
+//5522,Fanta_Zero_Lemon_Hat,Fanta Zero Lemon Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,516,{},{},{}
+//5523,Sakura_Mist_Hat,Sakura Mist Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,517,{ bonus bDex,1; },{},{}
+//5524,Sakura_Milk_Tea_Hat,Sakura Milk Tea Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,518,{ bonus bVit,1; },{},{}
+//5525,First_Leaf_Tea_Hat,Flower Hat,5,,,100,,2,,1,0xFFFFFFFF,7,2,256,,0,1,519,{ bonus bMaxHP,80; bonus bMaxSP,20; },{},{}
+//5526,Lady_Tanee_Doll,Tanigumi Girl Doll,5,,,300,,2,,0,0xFFFFFFFF,7,2,256,,60,1,520,{ bonus bAgi,2; bonus bFlee,3; bonus2 bAddEle,Ele_Wind,-5; bonus2 bAddMonsterDropItem,513,200; },{},{}
 5527,Lunatic_Hat,Lunatic Hat,5,,,300,,2,,0,0xFFFFFFFF,7,2,256,,0,1,521,{ bonus bLuk,5; bonus bMdef,2; bonus bFlee2,5; bonus2 bAddMonsterDropItem,622,50; },{},{}
-5528,King_Frog_Hat,Frog King Hat,5,,,500,,2,,1,0xFFFFFFFE,7,2,256,,30,1,522,{ bonus bAgi,1; },{},{}
+//5528,King_Frog_Hat,Frog King Hat,5,,,500,,2,,1,0xFFFFFFFE,7,2,256,,30,1,522,{ bonus bAgi,1; },{},{}
 5529,Evil's_Bone_Hat,Satanic Bone Helm,5,20,,600,,6,,1,0xFFFFFFFF,7,2,256,,70,1,523,{ bonus bDex,3; bonus2 bSubEle,Ele_Neutral,5; skill "WZ_FROSTNOVA",1; },{},{}
-5530,Raven_Cap,Raven Cap,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,30,1,524,{},{},{}
-5531,B_Dragon_Hat,Baby Dragon Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,0,1,525,{},{},{}
-5532,Pirate_Dagger_J,Pirate Dagger,5,,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,1,327,{ bonus bShortWeaponDamageReturn,1; },{},{}
+//5530,Raven_Cap,Raven Cap,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,30,1,524,{},{},{}
+//5531,B_Dragon_Hat,Baby Dragon Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,0,1,525,{},{},{}
+//5532,Pirate_Dagger_J,Pirate Dagger,5,,,100,,0,,0,0xFFFFFFFF,7,2,1,,0,1,327,{ bonus bShortWeaponDamageReturn,1; },{},{}
 5533,Emperor_Wreath_J,Emperor Wreath,5,,,800,,3,,1,0xFFFFFFFF,7,2,256,,80,1,261,{ bonus bAllStats,1; },{},{}
 5534,Fox_Hat_J,Fox Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,0,769,,70,1,403,{ bonus bAgi,1; bonus bFlee2,2; },{},{}
 5535,Side_Cap,Side Cap,5,20,,500,,3,,0,0xFFFFFFFF,7,2,256,,0,1,529,{ bonus2 bSubRace,RC_DemiHuman,5; bonus2 bAddRace,RC_DemiHuman,3; },{},{}
 5536,Spare_Card,Spare Card,5,20,,10,,1,,0,0xFFFFFFFF,7,2,1,,10,1,526,{ bonus2 bAddMonsterDropItem,6187,1000; },{},{}
-5537,Kwati_Hat,Kwati Hat,5,20,,700,,1,,1,0xFFFFFFFF,7,2,256,,45,0,527,{ bonus bAgi,3; },{},{}
-5538,Tucano_Hat,Tucano Hat,5,20,,600,,2,,1,0xFFFFFFFF,7,2,256,,45,0,528,{ bonus bDex,3; },{},{}
-5539,Jaguar_Hat,Jaguar Hat,5,20,,400,,4,,1,0xFFFFFFFF,7,2,769,,25,1,530,{ bonus bMdef,2; skill "MC_LOUD",1; },{},{}
+//5537,Kwati_Hat,Kwati Hat,5,20,,700,,1,,1,0xFFFFFFFF,7,2,256,,45,0,527,{ bonus bAgi,3; },{},{}
+//5538,Tucano_Hat,Tucano Hat,5,20,,600,,2,,1,0xFFFFFFFF,7,2,256,,45,0,528,{ bonus bDex,3; },{},{}
+//5539,Jaguar_Hat,Jaguar Hat,5,20,,400,,4,,1,0xFFFFFFFF,7,2,769,,25,1,530,{ bonus bMdef,2; skill "MC_LOUD",1; },{},{}
 5540,Freya_Soul_Circlet1,Freya Soul Circlet,5,20,,700,,4,,0,0xFFFFFFFF,7,2,256,,20,1,18,{ bonus bStr,1; bonus bint,1; bonus bDex,1; },{},{}
 5541,Freya_Soul_Circlet2,Freya Soul Circlet,5,20,,700,,4,,0,0xFFFFFFFF,7,2,256,,20,1,18,{ bonus bStr,1; bonus bint,1; bonus bDex,1; },{},{}
 5542,Freya_Soul_Circlet3,Freya Soul Circlet,5,20,,700,,4,,0,0xFFFFFFFF,7,2,256,,20,1,18,{ bonus bStr,1; bonus bint,1; bonus bDex,1; },{},{}
@@ -2752,26 +2752,26 @@
 5544,Guardian_Hat,Guardian Hat,5,20,,400,,1,,0,0xFFFFFFFF,7,2,256,,0,1,240,{ bonus bInt,1; bonus bMaxSP,50; },{},{}
 5545,Aries_Diadem,Aries Diadem,5,20,,400,,3,,0,0xFFFFFFFF,7,2,256,,70,1,531,{ bonus bVit,2; bonus2 bSubEle,Ele_fire,5; if(getrefine()>6) { bonus bDef,1; bonus bVit,1; } },{},{}
 5546,Aries_Crown,Aries Crown,5,20,,100,,3,,0,0xFFFFFFFF,7,2,256,,70,1,532,{ bonus bVit,2; bonus2 bSubEle,Ele_fire,5; if(getrefine()>6) { bonus bDef,1; bonus bVit,1; } },{},{}
-5547,RJC_Katyusha_Flower,RJC Katyusha Flower,5,20,,200,,1,,1,0xFFFFFFFF,7,2,256,,0,1,533,{ bonus2 bSkillAtk,"WZ_HEAVENDRIVE",15+getequiprefinerycnt(EQI_HAND_R); bonus2 bSkillAtk,"WZ_HEAVENDRIVE",15+getequiprefinerycnt(EQI_HAND_R); bonus bCastRate,-25; },{},{}
-5548,Rose_Of_Crimson,Rose Of Crimson,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,50,1,534,{ bonus bLuk,1; },{},{}
-5549,Taurus_Diadem,Taurus Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,535,{ bonus bDex,2; bonus bDelayRate,-2; bonus2 bSubEle,Ele_earth,5; if(getrefine()>6) { bonus bDex,1; bonus bMatkRate,1; } },{},{}
-5550,Taurus_Crown,Taurus Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,536,{ bonus bDex,2; bonus bDelayRate,-2; bonus2 bSubEle,Ele_earth,5; if(getrefine()>6) { bonus bDex,1; bonus bMatkRate,1; } },{},{}
+//5547,RJC_Katyusha_Flower,RJC Katyusha Flower,5,20,,200,,1,,1,0xFFFFFFFF,7,2,256,,0,1,533,{ bonus2 bSkillAtk,"WZ_HEAVENDRIVE",15+getequiprefinerycnt(EQI_HAND_R); bonus2 bSkillAtk,"WZ_HEAVENDRIVE",15+getequiprefinerycnt(EQI_HAND_R); bonus bCastRate,-25; },{},{}
+//5548,Rose_Of_Crimson,Rose Of Crimson,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,50,1,534,{ bonus bLuk,1; },{},{}
+//5549,Taurus_Diadem,Taurus Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,535,{ bonus bDex,2; bonus bDelayRate,-2; bonus2 bSubEle,Ele_earth,5; if(getrefine()>6) { bonus bDex,1; bonus bMatkRate,1; } },{},{}
+//5550,Taurus_Crown,Taurus Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,536,{ bonus bDex,2; bonus bDelayRate,-2; bonus2 bSubEle,Ele_earth,5; if(getrefine()>6) { bonus bDex,1; bonus bMatkRate,1; } },{},{}
 //5551,Holy_Egg_Hat,Holy Egg Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,537,{},{},{}
 5552,Festival_Grand_Circlet,Festival Grand Circlet,5,20,,0,,8,,0,0xFFFFFFFF,7,2,256,,0,1,93,{ bonus bStr,3; bonus bInt,3; bonus bMDef,3; },{},{}
 5553,Festival_Bunny_Band,Festival Bunny Band,5,20,,0,,7,,0,0xFFFFFFFF,7,2,256,,0,1,15,{ bonus bMDef,4; bonus2 bSubRace,RC_DemiHuman,9; },{},{}
 5554,Octopus_Hat,Octopus Hat,5,20,,200,,3,,0,0xFFFFFFFF,7,2,256,,20,1,538,{ bonus3 bAutoSpell,"SM_PROVOKE",5,10; bonus bUnbreakableHelm,0; },{},{}
 5555,Leaf_Cat_Hat,Leaf Cat Hat,5,20,,100,,3,,0,0xFFFFFFFF,7,2,256,,0,1,539,{ bonus bAgi,1; bonus3 bAutoSpellWhenHit,"AL_HEAL",3,10; },{},{}
 5556,Seal_Hat,Seal Hat,5,20,,500,,3,,0,0xFFFFFFFF,7,2,769,,55,1,540,{ bonus bInt,1; bonus3 bAutoSpell,"WZ_FROSTNOVA",1,30; },{},{}
-5557,Wild_Rose_Hat,Wild Rose Hat,5,20,,500,,3,,1,0xFFFFFFFE,7,2,256,,20,1,541,{ bonus bAgi,3; },{},{}
-5558,Luxury_Hat,Luxury Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,30,1,542,{ bonus3 bAddMonsterDropItem,511,RC_Plant,500; },{},{}
+//5557,Wild_Rose_Hat,Wild Rose Hat,5,20,,500,,3,,1,0xFFFFFFFE,7,2,256,,20,1,541,{ bonus bAgi,3; },{},{}
+//5558,Luxury_Hat,Luxury Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,30,1,542,{ bonus3 bAddMonsterDropItem,511,RC_Plant,500; },{},{}
 5559,Piece_Of_White_Cloth,Piece Of White Cloth,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,543,{},{},{}
 5560,Bullock_Helm_,Bullock Helm,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,75,1,322,{ bonus bMaxHP,100; bonus bNoKnockback,0; bonus2 bSubEle,Ele_Neutral,-20; bonus2 bSubEle,Ele_Fire,-20; bonus2 bSubEle,Ele_Water,-20; bonus2 bSubEle,Ele_Wind,-20; bonus2 bSubEle,Ele_Earth,-20; bonus2 bSubEle,Ele_Dark,-20; bonus2 bSubEle,Ele_Holy,-20; bonus2 bSubEle,Ele_Ghost,-20; },{},{}
 5561,Magic_Rabbit_Hat,Magic Rabbit Hat,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{ bonus bInt,1; bonus bMaxSP,50; bonus4 bAutoSpellWhenHit,"MG_FIREBOLT",3,10,3; bonus4 bAutoSpellWhenHit,"MG_COLDBOLT",3,10,3; bonus4 bAutoSpellWhenHit,"MG_LIGHTNINGBOLT",3,10,3; bonus3 bAutoSpellWhenHit,"AL_HEAL",1,10; },{},{}
-5562,Luxurious_Wedding_Veil,Luxurious Wedding Veil,5,20,,500,,1,,0,0xFFFFFFFF,7,2,768,,45,1,489,{ bonus bCastRate,-3; bonus bDelayRate,-3; bonus bMDef,10; },{},{}
+//5562,Luxurious_Wedding_Veil,Luxurious Wedding Veil,5,20,,500,,1,,0,0xFFFFFFFF,7,2,768,,45,1,489,{ bonus bCastRate,-3; bonus bDelayRate,-3; bonus bMDef,10; },{},{}
 //5563,Dolor_Hat,Dolor Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,547,{},{},{}
-5564,Crown_of_Deceit,Crown of Deceit,5,20,,300,,3,,1,0xFFFFFFFF,7,2,768,,85,1,544,{ bonus bInt,4; bonus bMDef,4; bonus bCastRate,-10; },{},{}
-5565,Dragon_Arhat_Mask,Dragon Arhat Mask,5,20,,0,,5,,0,0xFFFFFFFF,7,2,769,,0,1,545,{ bonus2 bAddRace,RC_DemiHuman,10; },{},{}
-5566,Tiger_Arhat_Mask,Tiger Arhat Mask,5,20,,0,,1,,0,0xFFFFFFFF,7,2,769,,0,1,546,{ bonus2 bAddRace,RC_DemiHuman,2;},{},{}
+//5564,Crown_of_Deceit,Crown of Deceit,5,20,,300,,3,,1,0xFFFFFFFF,7,2,768,,85,1,544,{ bonus bInt,4; bonus bMDef,4; bonus bCastRate,-10; },{},{}
+//5565,Dragon_Arhat_Mask,Dragon Arhat Mask,5,20,,0,,5,,0,0xFFFFFFFF,7,2,769,,0,1,545,{ bonus2 bAddRace,RC_DemiHuman,10; },{},{}
+//5566,Tiger_Arhat_Mask,Tiger Arhat Mask,5,20,,0,,1,,0,0xFFFFFFFF,7,2,769,,0,1,546,{ bonus2 bAddRace,RC_DemiHuman,2;},{},{}
 5567,Bright_Fury,Bright Fury,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,548,{ bonus2 bAddRace,RC_NonBoss,2; bonus2 bAddRace,RC_Boss,2; bonus bAspdRate,2; },{},{}
 5568,Rabbit_Bonnet,Rabbit Bonnet,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,549,{},{},{}
 5569,Gemini_Diadem,Gemini Diadem,5,20,,300,,4,,1,0xFFFFFFFF,7,2,256,,70,1,550,{ bonus bMatkRate,2; if(getrefine()>6) { bonus bMDef,7; bonus bMAtkRate,8; bonus2 bSubEle,Ele_Wind,5; } },{},{}
@@ -2785,26 +2785,26 @@
 5577,Dark_Knight_Mask_,Dark Knight Mask,5,,,3000,,5,,0,0xFFFFFFFF,7,2,769,,80,1,479,{ bonus bStr,3; if(isequipped(2779,2780)) { bonus bMatkRate,10; bonus bInt,5; bonus2 bSubRace,RC_Angel,10; } },{},{}
 5578,Voyage_Hat,Voyage_Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,236,{},{},{}
 5579,Satgat,Wanderer's Sakkat,5,20,,300,,2,,0,0xFFFFFFFF,7,2,768,,70,1,558,{ bonus bAgi,2; },{},{}
-5580,Red_Beret,Red Beret,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,559,{},{},{}
-5581,Cancer_Diadem,Cancer Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,561,{ bonus bInt,2; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bMDef,1; bonus bHealPower,3; bonus bMatkRate,2; } },{},{}
-5582,Cancer_Crown,Cancer Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,560,{ bonus bStr,2; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bHealPower,3; bonus bFlee,10; } },{},{}
+//5580,Red_Beret,Red Beret,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,559,{},{},{}
+//5581,Cancer_Diadem,Cancer Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,561,{ bonus bInt,2; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bMDef,1; bonus bHealPower,3; bonus bMatkRate,2; } },{},{}
+//5582,Cancer_Crown,Cancer Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,560,{ bonus bStr,2; bonus2 bSubEle,Ele_water,5; if(getrefine()>6) { bonus bDef,1; bonus bHealPower,3; bonus bFlee,10; } },{},{}
 5583,Para_Team_Hat,Eden Team Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,465,{},{},{}
 5584,Majestic_Evil_Horn,Majestic Evil Horns,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,562,{ bonus2 bSubRace,RC_Demon,3; bonus2 bHPDrainRate,3,15; bonus2 bSPDrainRate,1,7; },{},{}
 5585,Rune_Cloth_Circlet,Rune Cloth Circlet,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,564,{},{},{}
 5586,Mogikiller,Mosquito Coil,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,563,{},{},{}
 5587,Mogikiller_,Mosquito Coil,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,563,{},{},{}
-5588,Leo_Crown,Leo Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,565,{ bonus bStr,2; bonus2 bSubEle,Ele_Fire,5; if(getrefine()>6) { bonus bDef,1; bonus bFlee,10; bonus3 bAutoSpell,"TK_SEVENWIND",4,50; } },{},{}
-5589,Leo_Diadem,Leo Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,566,{ bonus bDex,2; bonus2 bSubEle,Ele_Fire,5; if(getrefine()>6) {  bonus bFlee,10; bonus bAspdRate,3; autobonus "{ bonus bSplashRange,1; }",10,10000,BF_WEAPON,"{ specialeffect2 EF_ENHANCE; }"; } },{},{}
+//5588,Leo_Crown,Leo Crown,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,565,{ bonus bStr,2; bonus2 bSubEle,Ele_Fire,5; if(getrefine()>6) { bonus bDef,1; bonus bFlee,10; bonus3 bAutoSpell,"TK_SEVENWIND",4,50; } },{},{}
+//5589,Leo_Diadem,Leo Diadem,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,70,1,566,{ bonus bDex,2; bonus2 bSubEle,Ele_Fire,5; if(getrefine()>6) {  bonus bFlee,10; bonus bAspdRate,3; autobonus "{ bonus bSplashRange,1; }",10,10000,BF_WEAPON,"{ specialeffect2 EF_ENHANCE; }"; } },{},{}
 5590,Poring_Cake_Hat,Poring Cake Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,417,{},{},{}
-5591,Desert_Prince,Desert Prince,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,567,{},{},{}
+//5591,Desert_Prince,Desert Prince,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,567,{},{},{}
 5592,Sigrun's_Wings,Sigrun's Wings,5,20,,100,,2,,0,0xFFFFFFFF,7,2,512,,80,1,568,{ if(BaseClass==Job_Swordman||BaseClass==Job_Merchant||BaseClass==Job_Thief||(BaseJob==Job_Taekwon&&Class!=Job_Soul_Linker)) bonus bStr,1; else if(BaseClass==Job_Mage||BaseClass==Job_Acolyte||class==Job_Ninja||class==Job_Soul_Linker) bonus bInt,1; else if(BaseClass==Job_Archer||BaseClass==Job_Gunslinger) bonus bDex,1; else if (BaseJob==Job_Novice||BaseJob==Job_SuperNovice) { bonus bMaxHP,80; bonus bMaxSP,30; } },{},{}
 5593,Rabbit_Bonnet_,Rabbit Bonnet,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,549,{},{},{}
 5594,Donut_In_Mouth,Donut In Mouth,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,0,1,569,{},{},{}
 //5595,Yuno_Eye,Juno Eye,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,570,{},{},{}
 5596,4_Leaf_Clover_In_Mouth_R,4 Leaf Clover In Mouth,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,0,1,571,{},{},{}
 5597,Chewing_Bubblegum_R,Chewing Bubblegum_R,5,20,,100,,1,,0,0xFFFFFFFF,7,2,1,,0,1,572,{},{},{}
-5598,Virgo_Crown,Virgo Crown,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,70,1,573,{ bonus bDex,2; bonus bAspdRate,1; if(getrefine()>6) { bonus2 bSubEle,Ele_Earth,5; autobonus "{ bonus bDex,20; }",10,6000,BF_WEAPON,"{ specialeffect2 EF_ENHANCE; }"; } },{},{}
-5599,Virgo_Diadem,Virgo Diadem,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,70,1,574,{ bonus bAspdRate,3; bonus2 bSubEle,Ele_Earth,5; if(getrefine()>6) bonus3 bAutoSpell,"MO_BALKYOUNG",1,50; },{},{}
+//5598,Virgo_Crown,Virgo Crown,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,70,1,573,{ bonus bDex,2; bonus bAspdRate,1; if(getrefine()>6) { bonus2 bSubEle,Ele_Earth,5; autobonus "{ bonus bDex,20; }",10,6000,BF_WEAPON,"{ specialeffect2 EF_ENHANCE; }"; } },{},{}
+//5599,Virgo_Diadem,Virgo Diadem,5,20,,300,,3,,1,0xFFFFFFFF,7,2,256,,70,1,574,{ bonus bAspdRate,3; bonus2 bSubEle,Ele_Earth,5; if(getrefine()>6) bonus3 bAutoSpell,"MO_BALKYOUNG",1,50; },{},{}
 5600,Brazil_Twin_Ribbon,Brazil Twin Ribbon,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,575,{},{},{}
 //5601,Banana_Beret,Banana Beret,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,576,{},{},{}
 //5603,RTC_Winner_Only,RTC First Place,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,577,{},{},{}
@@ -2837,12 +2837,12 @@
 5632,Vanilmirth_Hat_M,Vanilmirth Hat,5,20,,100,,0,,0,0xFFFFFFFF,7,2,256,,1,0,317,{ bonus bUnbreakableHelm,0; bonus3 bAutoSpell,MG_FIREBOLT,1,10; bonus3 bAutoSpell,MG_COLDBOLT,1,10; bonus3 bAutoSpell,MG_LIGHTNINGBOLT,1,10; bonus bMdef,5; },{},{}
 5633,Drooping_Bunny_M,Drooping Bunny,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,1,1,249,{ bonus bDex,1; bonus bFlee,2; },{},{}
 5634,Kettle_Hat_M,Kettle Hat,5,20,,600,,4,,0,0xFFFFFFFF,7,2,256,,1,1,318,{ bonus4 bAutoSpell,SA_DELUGE,2,10,0; bonus3 bAutoSpell,WZ_WATERBALL,3,10; },{},{}
-5635,Dragon_Skull_M,Dragon Skull,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,1,1,319,{ bonus2 bSubRace,RC_Dragon,5; },{},{}
+//5635,Dragon_Skull_M,Dragon Skull,5,20,,800,,5,,0,0xFFFFFFFF,7,2,256,,1,1,319,{ bonus2 bSubRace,RC_Dragon,5; },{},{}
 5636,Ramen_Hat_M,Ramen Hat,5,20,,0,,1,,0,0xFFFFFFFF,7,2,256,,1,1,320,{ bonus bDex,4; bonus4 bAutoSpellWhenHit,AL_DECAGI,1,30,1; },{},{}
 5637,Pink_Fur_Hat_M,Pink Beanie,5,20,,350,,2,,0,0xFFFFFFFF,7,2,256,,1,1,281,{ bonus bLuk,1; },{},{}
 5638,Puppy_Hat_M,Puppy Hat,5,20,,500,,2,,0,0xFFFFFFFF,7,2,256,,1,0,234,{ bonus bAgi,1; bonus3 bAutoSpell,PR_GLORIA,1,10+20*(readparam(bAgi)>=77); },{},{}
 5639,Magic_Eyes_M,Magic Eyes,5,20,,300,,1,,0,0x00810204,7,2,256,,1,1,209,{ bonus bMdef,5; bonus bCastrate,-10; bonus bUseSPrate,20; },{},{}
-5640,Jumping_Poring_M,Jumping Poring,5,0,,300,,2,,0,0xFFFFFFFF,7,2,256,,1,1,349,{ bonus bLuk,1; bonus bUnbreakableHelm,0; },{},{}
+//5640,Jumping_Poring_M,Jumping Poring,5,0,,300,,2,,0,0xFFFFFFFF,7,2,256,,1,1,349,{ bonus bLuk,1; bonus bUnbreakableHelm,0; },{},{}
 5641,Robo_Eye_M,Robo Eye,5,20,,200,,2,,0,0xFFFFFFFF,7,2,512,,1,0,345,{ bonus2 bAddRace,RC_NonBoss,3; bonus2 bAddRace,RC_Boss,3; bonus bMatkRate,3; bonus bDex,1; },{},{}
 5642,Yellow_Wizardry_Hat_M,Yellow Mage Hat,5,20,,300,,1,,0,0x810204,7,2,256,,1,1,286,{ bonus bInt,2; bonus bMaxSP,150; },{},{}
 5643,Crescent_Helm_M,Crescent Helm,5,20,,3000,,8,,0,0x000444A2,7,2,768,,1,1,213,{ bonus bVit,1; bonus2 bSubRace,RC_DemiHuman,5; },{},{}
@@ -2856,10 +2856,10 @@
 5651,Brooch_M,Brooch,5,1,,0,,0,,0,0xFFFFFFFE,7,2,136,,1,0,1,{ bonus bAgi,4; },{},{}
 5652,Magestic_Goat_M_,Baphomet Horns,5,2,,0,,5,,0,0xFFFFFFFF,7,2,256,,1,0,41,{ bonus bStr,1; },{},{}
 5653,Darkness_Helm_J,Darkness Helm,5,,,500,,3,,1,0xFFFFFFFF,7,2,256,,70,1,586,{ if(isequipped(5074)) { bonus bStr,1; bonus bAspdRate,2; } else if(isequipped(5068)) { bonus bStr,1; bonus bAtkRate,5; } else if(isequipped(5358)) { bonus bAgi,1; bonus bFlee,3; } else if(isequipped(5401)) { bonus bInt,1; bonus bMatkRate,2; } else if(isequipped(5470)) { bonus bDex,1; bonus bLongAtkRate,3; } },{},{}
-5654,Red_Marcher_Hat,Red Marcher Hat,5,,,200,,2,,1,0xFFFFFFFF,7,2,256,,10,1,587,{ bonus bStr,2; bonus3 bAutoSpell,"PR_ASPERSIO",2,30; },{},{}
+//5654,Red_Marcher_Hat,Red Marcher Hat,5,,,200,,2,,1,0xFFFFFFFF,7,2,256,,10,1,587,{ bonus bStr,2; bonus3 bAutoSpell,"PR_ASPERSIO",2,30; },{},{}
 5655,Evil_Snake_Lord_Hat_J,Evil Snake Lord Hat,5,,,500,,2,,0,0xFFFFFFFF,7,2,256,,50,1,372,{ bonus bInt,2; bonus bAgi,2; bonus bDex,-2; autobonus "{ bonus bCastrate,-50; bonus bFlee,30; }",50,5000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }"; },{},{}
 5656,Scooter_Helmet,Scooter Helmet,5,,,1000,,7,,1,0xFFFFFFFF,7,2,256,,50,1,588,{ bonus bUnbreakableHelm,0; },{},{}
-5657,Captain's_Pipe,Captain's Pipe,5,,,100,,0,,0,0xFFFFFFFF,7,2,1,,30,1,383,{ if(isequipped(5184)) bonus bLongAtkRate,getrefine(); },{},{}
+//5657,Captain's_Pipe,Captain's Pipe,5,,,100,,0,,0,0xFFFFFFFF,7,2,1,,30,1,383,{ if(isequipped(5184)) bonus bLongAtkRate,getrefine(); },{},{}
 //
 //5661,Red_Pirate_Bandana,Red Pirate Banada,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,1,1,592,{ bonus bAspdRate,2; bonus bCastRate,-2; bonus3 bAutoSpell,"MO_EXTREMITYFIST",1,30; },{},{}
 //5662,Libra_Crown,Libra Crown,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,1,1,593,{},{},{}
@@ -2883,9 +2883,9 @@
 5686,Nice_Hat_Feather,Nice Hat Feather,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,104,{},{},{}
 5687,Angle_Helm_Light,Angle_Helm_Light,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,86,{},{},{}
 //5688,2009_Love_Dad,2009_Love_Dad,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,611,{},{},{}
-//5689,Ant_Queen_Crown,Ant_Queen_Crown,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,612,{},{},{}
+5689,Ant_Queen_Crown,Ant_Queen_Crown,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,612,{},{},{}
 //5690,Red_Wing_Hat,Red Wing Hat,5,,,100,,0,,0,0xFFFFFFFF,7,2,256,,1,1,608,{ if (getrefine()>6) { bonus2 bAddRace,RC_NonBoss,2; bonus2 bAddRace,RC_Boss,2; bonus bMatkRate,2; } if (getrefine()>8) { bonus2 bAddRace,RC_NonBoss,2; bonus2 bAddRace,RC_Boss,2; bonus bMatkRate,2; }  },{},{}
-5691,Sailor's_Bandana,Sailor's_Bandana,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,542,{},{},{}
+//5691,Sailor's_Bandana,Sailor's_Bandana,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,542,{},{},{}
 5692,Sea_Cat_Hat,Sea_Cat_Hat,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,539,{},{},{}
 //5693,NoFear_Underwear,NoFear_Underwear,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,614,{},{},{}
 //5694,NoFear_Headband,NoFear_Headband,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,614,{},{},{}
@@ -2911,6 +2911,7 @@
 5756,Wispers_Of_Wind,Wind Whisper,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,633,{},{},{}
 5757,Reissue_Schmitz_Helm,Dip Schmidt Helm,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,634,{},{},{}
 5758,Resting_Swan,Dying Swan,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,635,{},{},{}
+//
 5760,Driver_Band_,Driver Band,5,20,,100,,1,,1,0xFFFFFFFF,7,2,256,,0,1,637,{},{},{}
 //
 5800,Blush_Of_Groom,Blush of Groom,5,20,,50,,0,,0,0xFFFFFFFF,7,2,512,,0,0,125,{ bonus2 bSubRace,RC_DemiHuman,3; },{},{}
@@ -2928,7 +2929,7 @@
 //5812,Hat_Of_Expert
 //5813,Red_Ph.D_Hat
 //5814,Ati_Atihan_Hat3
-5815,Classic_Hat_J,Classic Hat,5,,,500,,1,,1,0xFFFFFFFF,7,2,256,,0,1,475,{ bonus2 bAddSize,0,5; bonus2 bAddSize,1,5; bonus2 bAddSize,2,5; bonus bStr,1; },{},{}
+//5815,Classic_Hat_J,Classic Hat,5,,,500,,1,,1,0xFFFFFFFF,7,2,256,,0,1,475,{ bonus2 bAddSize,0,5; bonus2 bAddSize,1,5; bonus2 bAddSize,2,5; bonus bStr,1; },{},{}
 5816,Cowboy_Hat_J,Purple Cowboy Hat,5,,,500,,0,,1,0xFFFFFFFF,7,2,256,,0,1,411,{ bonus bAtk,15; bonus bFlee,-5; },{},{}
 //5817,Valentine_Pledge
 //5818,Carnival_Hat
@@ -5016,7 +5017,7 @@
 13035,Sandstorm,Sandstorm,4,20,,600,50,,1,4,0x00001000,2,2,2,2,70,1,1,{},{},{}
 13036,BF_Dagger1,Brave Assassin's Damascus,4,0,,0,120,,1,0,0x028F5EEF,7,2,2,3,80,1,1,{ bonus bStr,1; bonus bAgi,1; bonus2 bAddRace,RC_DemiHuman,75; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; if (Class == Job_Ninja || Class == Job_Rogue || Class == Job_Stalker) bonus bMatkRate,15; },{},{}
 13037,BF_Dagger2,Valorous Assassin's Damascus,4,0,,0,120,,1,0,0x029E7CEB,7,2,2,3,80,1,1,{ bonus bStr,1; bonus bAgi,1; bonus2 bAddRace,RC_DemiHuman,75; bonus bUnbreakableWeapon,0; autobonus "{ bonus bDefRatioAtkRace,RC_Boss; bonus bDefRatioAtkRace,RC_NonBoss; }",10,6000,BF_WEAPON,"{ specialeffect2 EF_HASTEUP; }"; if (Class == Job_Ninja || Class == Job_Rogue || Class == Job_Stalker) bonus bMatkRate,15; },{},{}
-13038,Dagger_Of_Hunter,Dagger of Hunter,4,20,,700,120,,1,3,0x00020000,2,2,2,3,70,1,1,{ bonus bStr,1; bonus bAgi,2; bonus bDex,1; bonus4 bAutoSpellOnSkill,"RG_BACKSTAP","SM_BASH",100,10; bonus2 bSkillAtk,"RG_BACKSTAP",20; },{},{}
+13038,Dagger_Of_Hunter,Dagger of Hunter,4,20,,700,120,,1,3,0x00020000,2,2,2,3,70,1,1,{ bonus bStr,1; bonus bAgi,2; bonus bDex,1; bonus4 bAutoSpellOnSkill,"RG_BACKSTAP","SM_BASH",10,100; bonus2 bSkillAtk,"RG_BACKSTAP",20; },{},{}
 13039,Ivory_Knife,Ivory Knife,4,20,,700,130,,1,2,0x000F5EEE,2,2,2,3,50,1,1,{ bonus bAgi,2; bonus bAspdRate,3; bonus2 bAddEff,Eff_Bleeding,300; bonus3 bAutoSpell,"NPC_CRITICALWOUNDS",1,30; },{},{}
 13040,N_Cutter,Novice Cutter,4,1,,0,50,,1,3,0xFE9F7EEF,7,2,2,1,1,0,1,{},{},{}
 13041,N_Main_Gauche,Novice Main Gauche,4,1,,0,65,,1,3,0xFE9F7EEF,7,2,2,1,1,0,1,{},{},{}
@@ -5025,7 +5026,7 @@
 //13044,House_Auger_I
 //13045,Kamaitachi_I
 13046,Krieg,Krierg,4,20,,500,110,,1,3,0x00021040,2,2,2,2,50,1,1,{ bonus3 bAddEffOnSkill,"RG_BACKSTAP",Eff_Bleeding,100; bonus2 bSkillAtk,"RG_BACKSTAP",15; },{},{}
-13047,Weihna,Weihna,4,20,,500,135,,1,2,0x00021040,2,2,2,2,50,1,1,{ bonus3 bAddEffOnSkill,"RG_RAID",Eff_Poison,100; autobonus "{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; }",5,5000,BF_WEAPON|BF_SHORT,"{ specialeffect2 EF_POTION_BERSERK; }"; },{},{}
+13047,Weihna,Weihna,4,20,,500,135,,1,2,0x00021040,2,2,2,3,50,1,1,{ bonus3 bAddEffOnSkill,"RG_RAID",Eff_Poison,100; autobonus "{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; }",5,5000,BF_WEAPON|BF_SHORT,"{ specialeffect2 EF_POTION_BERSERK; }"; },{},{}
 //13048,Damascus_C
 13050,P_Dagger1,Eden Dagger I,4,0,,0,124,,1,0,0xFE9F7EEF,7,2,2,2,26,0,1,{},{},{}
 13051,P_Dagger2,Eden Dagger II,4,0,,0,158,,1,0,0xFE9F7EEF,7,2,2,2,40,0,1,{},{},{}
@@ -5688,7 +5689,7 @@
 14020,F_Shelter_Resist_Box,Shell Of Resistance Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ rentitem 2132,604800; },{},{}
 14021,F_Sylphid_Manteau_Box,Silf Manteau Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ rentitem 2543,604800; },{},{}
 14022,F_Refresh_Shoes_Box,Refresh Shoes Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ rentitem 2439,604800; },{},{}
-14023,F_Toast_Box,Crunch Toast Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ rentitem 5107,604800; },{},{}
+14023,F_Toast_Box,Crunch Toast Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ rentitem 5391,604800; },{},{}
 14024,F_Robo_Eye_Box,Robo Eye Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 5325,1; },{},{}
 14025,F_Twin_Ribbon_Box,Maiden's Twin Ribbon Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 5187,1; },{},{}
 //14026,F_Diadem_Box,Diadem Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 5313,1; },{},{}

BIN
db/map_cache.dat


+ 20 - 0
db/map_index.txt

@@ -791,6 +791,26 @@ job3_sha01
 //ac_cl_room
 //jp_s_dun11
 
+mora
+bif_fild01
+bif_fild02
+1@mist
+dewata
+dew_in01
+dew_fild01
+dew_dun01
+dew_dun02
+que_house_s
+malangdo
+mal_in01
+mal_in02
+mal_dun01
+1@pump
+2@pump
+1@cash
+iz_dun05
+evt_mobroom
+
 // Only add maps under this line if they are not standard maps!
 
 

+ 2 - 2
db/mob_db.txt

@@ -1038,7 +1038,7 @@
 1984,I_ORC_LADY,Shaman Cargalache,Shaman Cargalache,58,50058,0,4870,98,1,823,1212,35,10,60,35,52,18,79,20,10,12,1,7,42,0x3695,145,1050,900,288,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 // Another World (13.1)
 1985,DANDELION,Dandelion Member,Dandelion Member,37,5176,0,0,0,1,305,360,0,10,28,19,32,0,63,20,10,12,1,7,47,0x3695,250,1772,72,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-1986,TATACHO,Tatacho,Tatacho,128,33336,0,3762,3092,2,727,799,151,14,119,33,70,56,78,33,10,12,1,2,22,0x108B,200,1000,768,360,0,0,0,0,0,0,0,0,1544,20,1925,10,6020,4000,6021,3000,579,3100,516,3000,0,0,0,0,0,0,0,0
+1986,TATACHO,Tatacho,Tatacho,128,33336,0,3762,3092,2,727,799,151,14,119,33,70,56,78,33,10,12,1,2,22,0x108B,200,1000,768,360,0,0,0,0,0,0,0,0,1544,20,1925,10,6020,4000,6021,3000,579,3100,516,3000,0,0,0,0,0,0,4442,1
 1987,CENTIPEDE,Centipede,Centipede,125,24992,0,3201,2711,2,601,713,143,25,133,71,69,39,86,49,10,12,1,4,45,0x3795,150,1000,792,336,0,0,0,0,0,0,0,0,2746,2,2747,2,1741,10,1042,5335,912,5000,955,9000,943,2500,0,0,0,0,4447,1
 1988,NEPENTHES,Nepenthes,Nepenthes,114,15099,0,2599,1793,7,602,727,25,5,94,32,41,39,150,59,10,12,1,3,45,0x84,1000,500,576,504,0,0,0,0,0,0,0,0,5399,1,1979,1,1926,1,1740,1,6041,3000,993,50,905,9000,0,0,0,0,0,0
 1989,HILLSRION,Hillslion,Hillthrion,123,21422,0,2909,1698,1,450,552,83,11,110,69,72,41,102,12,10,12,0,2,22,0x308D,130,400,780,576,0,0,0,0,0,0,0,0,2440,10,1825,20,6032,3000,6020,2000,1268,10,7063,120,7054,4850,0,0,0,0,4453,1
@@ -1048,7 +1048,7 @@
 1993,NAGA,Naga,Naga,117,21099,0,2944,2212,3,489,591,72,5,112,65,71,32,71,33,10,12,2,2,42,0x3695,150,400,864,432,0,0,0,0,0,0,0,0,2389,10,2134,10,1485,10,926,5000,936,3500,954,2000,1408,20,0,0,0,0,0,0
 1994,LUCIOLA_VESPA,Luciola Vespa,Luciola Vespa,109,12466,0,1622,1806,1,299,410,59,55,88,89,55,32,119,59,10,12,1,4,24,0x7795,110,1000,864,432,0,0,0,0,0,0,0,0,2744,2,955,9000,939,9000,518,300,992,160,526,200,943,3000,0,0,0,0,4445,1
 1995,PINGUICULA,Pinguicula,Pinguicula,105,13058,0,2221,1662,1,189,511,46,77,67,60,64,107,64,34,10,12,1,3,62,0x308D,200,700,600,360,0,0,0,0,0,0,0,0,2745,1,1980,10,2270,10,7100,5000,7198,2000,7188,3000,712,1000,0,0,0,0,0,0
-1996,BACSOJIN_T,Bacsojin,White Lady,85,253221,0,45250,16445,3,1868,6124,20,55,52,65,44,112,152,35,10,12,2,7,64,0x37B5,130,576,960,480,0,0,0,0,0,0,0,0,//5411,500,2638,80,2639,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+//1996,BACSOJIN_T,Bacsojin,White Lady,85,253221,0,45250,16445,3,1868,6124,20,55,52,65,44,112,152,35,10,12,2,7,64,0x37B5,130,576,960,480,0,0,0,0,0,0,0,0,5411,500,2638,80,2639,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 1997,G_TATACHO,Tatacho,Tatacho,106,39500,0,0,0,2,10000,11000,20,17,106,40,30,25,115,6,10,12,1,2,22,0x108B,150,1000,768,360,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 1998,G_HILLSRION,Hillslion,Hillslion,105,34600,0,0,0,1,5000,5500,28,15,105,60,30,15,115,5,10,12,0,2,22,0x308D,100,400,780,576,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 1999,CENTIPEDE_LARVA,Centipede Larva,Centipede Larva,118,20667,0,2930,2003,2,521,609,98,17,103,62,66,27,77,44,10,12,0,4,25,0x3795,150,1000,792,336,0,0,0,0,0,0,0,0,2406,9,732,50,0,0,1042,5335,912,5000,955,9000,943,2500,0,0,0,0,4452,1

+ 12 - 12
db/mob_skill_db.txt

@@ -5471,18 +5471,18 @@
 1995,Pinguicula@NPC_STOP,attack,342,1,500,500,5000,no,target,always,0,,,,,,30,
 1995,Pinguicula@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
 1995,Pinguicula@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,6,0x3885,,,,,
-1996,Bacsojin@NPC_INVISIBLE,chase,353,1,2000,1000,30000,yes,target,always,0,,,,,,29,
-1996,Bacsojin@PR_SANCTUARY,attack,70,10,2000,0,10000,yes,target,always,0,,,,,,18,
-1996,Bacsojin@HP_ASSUMPTIO,idle,361,5,10000,500,100000,yes,self,always,0,,,,,,,
-1996,Bacsojin@HP_ASSUMPTIO,chase,361,5,10000,500,100000,yes,self,always,0,,,,,,,
-1996,Bacsojin@HP_ASSUMPTIO,attack,361,5,10000,500,100000,yes,self,always,0,,,,,,,
-1996,Bacsojin@WZ_WATERBALL,chase,86,3,2000,1000,5000,yes,target,always,0,,,,,,,
-1996,Bacsojin@WZ_WATERBALL,attack,86,5,1000,0,5000,yes,target,always,0,,,,,,,
-1996,Bacsojin@NPC_STOP,attack,342,1,2000,500,15000,yes,target,always,0,,,,,,6,
-1996,Bacsojin@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
-1996,Bacsojin@NPC_SUMMONSLAVE,idle,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
-1996,Bacsojin@NPC_SUMMONSLAVE,attack,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
-1996,Bacsojin@NPC_SUMMONSLAVE,chase,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
+//1996,Bacsojin@NPC_INVISIBLE,chase,353,1,2000,1000,30000,yes,target,always,0,,,,,,29,
+//1996,Bacsojin@PR_SANCTUARY,attack,70,10,2000,0,10000,yes,target,always,0,,,,,,18,
+//1996,Bacsojin@HP_ASSUMPTIO,idle,361,5,10000,500,100000,yes,self,always,0,,,,,,,
+//1996,Bacsojin@HP_ASSUMPTIO,chase,361,5,10000,500,100000,yes,self,always,0,,,,,,,
+//1996,Bacsojin@HP_ASSUMPTIO,attack,361,5,10000,500,100000,yes,self,always,0,,,,,,,
+//1996,Bacsojin@WZ_WATERBALL,chase,86,3,2000,1000,5000,yes,target,always,0,,,,,,,
+//1996,Bacsojin@WZ_WATERBALL,attack,86,5,1000,0,5000,yes,target,always,0,,,,,,,
+//1996,Bacsojin@NPC_STOP,attack,342,1,2000,500,15000,yes,target,always,0,,,,,,6,
+//1996,Bacsojin@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
+//1996,Bacsojin@NPC_SUMMONSLAVE,idle,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
+//1996,Bacsojin@NPC_SUMMONSLAVE,attack,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
+//1996,Bacsojin@NPC_SUMMONSLAVE,chase,196,1,10000,0,5000,yes,self,slavele,1,,,,,,,
 1997,Tatacho@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1997,Tatacho@BS_HAMMERFALL,attack,110,3,500,1500,5000,no,target,always,0,,,,,,,
 1997,Tatacho@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,

+ 1 - 1
db/packet_db.txt

@@ -505,7 +505,7 @@ packet_ver: 9
 0x0214,42
 
 //2004-08-17aSakexe
-0x020f,10
+0x020f,10,pvpinfo,2:6
 0x0210,22
 
 //2004-09-06aSakexe

+ 45 - 3
doc/item_bonus.txt

@@ -3,7 +3,7 @@
 //===== By ================================================
 //= Developers
 //===== Version ===========================================
-//= 1.1.20101205
+//= 1.1.20110124
 //=========================================================
 //= 1.0 - Standardized doc file
 //= 1.1.20080612 - skill command and bonuses (bAutoSpell, bSkillAtk, 
@@ -19,6 +19,13 @@
 //=   bUnbreakableWeapon, bUnbreakableArmor, bUnbreakableHelm,
 //=   bUnbreakableShield, bUnbreakableShoes, bBreakWeaponRate and
 //=   bBreakArmorRate. [Ai4rei]
+//= 1.1.20110124 - added documentation for bAgiVit, bAgiDexStr,
+//=   bUnbreakable, bShortWeaponDamageReturn, bLongWeaponDamageReturn,
+//=   bWeaponComaEle, bAddEff2, bMagicDamageReturn, bRandomAttackIncrease,
+//=   bPerfectHide, bNoKnockback, bClassChange, bHPDrainValue, bWeaponAtk,
+//=   bWeaponAtkRate, bDelayrate, bHPDrainRateRace, bSPDrainRateRace,
+//=   bAddEffOnSkill, bNoMiscDamage, bLongAtkRate, bUnstripable,
+//=   bHPDrainValueRace, bMagicSPGainValue and bMagicHPGainValue. [Ai4rei]
 //===== Description =======================================
 //= List of script instructions used in item bonuses,
 //= mainly bonus/bonus2/bonus3/bonus4/bonus5 arguments
@@ -34,6 +41,8 @@ bonus bInt,n;				INT + n
 bonus bDex,n;				DEX + n
 bonus bLuk,n;				LUK + n
 bonus bAllStats,n;			STR + n, AGI + n, VIT + n, INT + n, DEX + n, LUK + n
+bonus bAgiVit,n;			AGI + n, VIT + n
+bonus bAgiDexStr,n;			STR + n, AGI + n, DEX + n
 bonus bMaxHP,n;				MaxHP + n
 bonus bMaxSP,n;				MaxSP + n
 bonus bMaxHPrate,n;			MaxHP + n% 
@@ -120,9 +129,9 @@ bonus bIntravision,n;			Always see Hiding and Cloaking players/mobs (n is meanin
 bonus bHealPower,n;			Increase heal amount of all heal skills by n%
 bonus bHealPower2,n;			Increase heal amount if you are healed by any skills by n%
 bonus2 bAddEff,e,x;			Adds a x/10000 chance to cause effect e to the target when attacking (e.g. x=100 makes 1% chance, x=10000 makes 100% chance, etc)
-							e: Eff_Blind, Eff_Sleep, Eff_Poison, Eff_Freeze, Eff_Silence, Eff_Stan, Eff_Curse, Eff_Confusion, Eff_Stone, Eff_Bleeding
+							e: Eff_Blind, Eff_Sleep, Eff_Poison, Eff_Freeze, Eff_Silence, Eff_Stun, Eff_Curse, Eff_Confusion, Eff_Stone, Eff_Bleeding
 bonus2 bResEff,e,x;			Adds a x/10000 tolerance to effect e (e.g. x=100 makes 1% tolerance, x=10000 makes 100% tolerance, etc)
-							e: Eff_Blind, Eff_Sleep, Eff_Poison, Eff_Freeze, Eff_Silence, Eff_Stan, Eff_Curse, Eff_Confusion, Eff_Stone, Eff_Bleeding
+							e: Eff_Blind, Eff_Sleep, Eff_Poison, Eff_Freeze, Eff_Silence, Eff_Stun, Eff_Curse, Eff_Confusion, Eff_Stone, Eff_Bleeding
 bonus2 bCastrate,n,x;			Adjust casting time of skill n by x% (supports skill names)
 bonus2 bAddSize,n,x;			+x% physical damage against size n.
 							n: 0=Small  1=Medium  2=Large
@@ -395,3 +404,36 @@ bonus bUnbreakableShield,n;	Shield cannot be damaged/broken by any means (n is m
 bonus bUnbreakableShoes,n;	Shoes cannot be damaged/broken by any means (n is meaningless)
 bonus bBreakWeaponRate,n;	Adds a n/100% chance to break enemy's weapon while attacking (stacks with other break chances).
 bonus bBreakArmorRate,n;	Adds a n/100% chance to break enemy's armor while attacking (stacks with other break chances).
+bonus bUnbreakable,n;		Reduces the break chance of all equipped equipment by n%.
+bonus bShortWeaponDamageReturn,n;	Reflects n% of received melee damage back to the enemy that caused it.
+bonus bLongWeaponDamageReturn,n;	Reflects n% of received ranged damage back to the enemy that caused it.
+bonus2 bWeaponComaEle,x,n;	Adds a n/100% chance to cause Coma when attacking a monster of element x with normal attack.
+							x:	0=Neutral, 1=Water, 2=Earth, 3=Fire, 4=Wind, 5=Poison,
+								6=Holy, 7=Dark, 8=Spirit, 9=Undead
+bonus2 bAddEff2,x,n;	Adds a n/100% chance to cause status change x on self when attacking.
+						x:	Eff_Blind, Eff_Sleep, Eff_Poison, Eff_Freeze, Eff_Silence,
+							Eff_Stun, Eff_Curse, Eff_Confusion, Eff_Stone, Eff_Bleeding
+bonus bMagicDamageReturn,n;	Adds a n% chance to reflect targetted magic spells back to the enemy that caused it.
+bonus2 bRandomAttackIncrease,x,n;	Adds a n% chance to inflict x% additional damage to the enemy with normal attack.
+bonus bPerfectHide,n;	Hidden/cloaked character is no longer detected by monsters with 'detector' mode (n is meaningless).
+bonus bNoKnockback,n;	Character is no longer knocked back by enemy skills with such effect (n is meaningless).
+bonus bClassChange,n;	Gives a n/100% chance to change the attacked monster's class with normal attack.
+bonus bHPDrainValue,n;	Heals +n HP with normal attack.
+bonus2 bHPDrainValue,n,x;	Heals +n HP with normal attack. When x is non-zero, the HP is drained instead.
+bonus2 bWeaponAtk,x,n;	Adds n ATK when weapon of type x is equipped.
+						x: see doc/item_db.txt -> view -> weapons for possible values
+bonus2 bWeaponAtkRate,x,n;	Adds n% damage to normal attacks when weapon of type x is equipped.
+							x: see doc/item_db.txt -> view -> weapons for possible values
+bonus bDelayrate,n;	Increases skill delay by n%.
+bonus3 bHPDrainRateRace,r,n,x;	Adds a n/10% chance to receive x% of dealed damage as HP from a monster of race r with normal attack.
+bonus3 bSPDrainRateRace,r,n,x;	Adds a n/10% chance to receive x% of dealed damage as SP from a monster of race r with normal attack.
+bonus3 bAddEffOnSkill,s,x,n;	Adds a n/100% chance to cause status change x on enemy when using skill s (supports skill names)
+bonus4 bAddEffOnSkill,s,x,n,t;	Adds a n/100% chance to cause status change x when using skill s (supports skill names)
+								t:	ATF_SELF   = causes status change to oneself
+									ATF_TARGET = causes status change to the enemy
+bonus bNoMiscDamage,n;	Adds n% reduction to received misc damage.
+bonus bLongAtkRate,n;	Increases damage of ranged attacks by n%.
+bonus bUnstripable,n;	Armor cannot be taken off via strip skills (n is meaningless)
+bonus2 bHPDrainValueRace,r,n;	Heals +n HP when attacking a monster of race r with normal attack.
+bonus bMagicSPGainValue,n;	Heals +n SP when killing an enemy with magic attack.
+bonus bMagicHPGainValue,n;	Heals +n HP when killing an enemy with magic attack.

+ 13 - 13
doc/mob_db_mode_list.txt

@@ -82,7 +82,7 @@ Random Target: Picks a new random target in range on each attack / skill.
 Aegis Mob Types:
 -------------------------------------------------------------------------------
 
-What Aegis has are mob-types, where each type represents an AI behaviour that
+What Aegis has are mob-types, where each type represents an AI behavior that
 is mimicked by a group of eA mode bits. This is the table to convert from one
 to another:
 
@@ -91,22 +91,22 @@ Aegis/eA (description)
 02: 0x0083 (passive, looter)
 03: 0x1089 (passive, assist and change-target melee)
 04: 0x3885 (angry, change-target melee/chase)
-05: 0x2085 (aggro, change-target chase)
+05: 0x2085 (aggressive, change-target chase)
 06: 0x0000 (passive, immobile, can't attack) [plants]
 07: 0x108B (passive, looter, assist, change-target melee)
-08: 0x6085 (aggro, change-target chase, target weak enemies)
-09: 0x3095 (aggro, change-target melee/chase, cast sensor idle) [Guardian]
-10: 0x0084 (aggro, immobile)
-11: 0x0084 (aggro, immobile) [Guardian]
-12: 0x2085 (aggro, change-target chase) [Guardian]
-13: 0x308D (aggro, change-target melee/chase, assist)
+08: 0x6085 (aggressive, change-target chase, target weak enemies)
+09: 0x3095 (aggressive, change-target melee/chase, cast sensor idle) [Guardian]
+10: 0x0084 (aggressive, immobile)
+11: 0x0084 (aggressive, immobile) [Guardian]
+12: 0x2085 (aggressive, change-target chase) [Guardian]
+13: 0x308D (aggressive, change-target melee/chase, assist)
 17: 0x0091 (passive, cast sensor idle)
-19: 0x3095 (aggro, change-target melee/chase, cast sensor idle)
-20: 0x3295 (aggro, change-target melee/chase, cast sensor idle/chase)
-21: 0x3695 (aggro, change-target melee/chase, cast sensor idle/chase, chase-change target)
+19: 0x3095 (aggressive, change-target melee/chase, cast sensor idle)
+20: 0x3295 (aggressive, change-target melee/chase, cast sensor idle/chase)
+21: 0x3695 (aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target)
 25: 0x0001 (passive, can't attack) [Pet]
-26: 0xB695 (aggro, change-target melee/chase, cast sensor idle/chase, chase-change target, random target)
-27: 0x8084 (aggro, immobile, random target)
+26: 0xB695 (aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target, random target)
+27: 0x8084 (aggressive, immobile, random target)
 
 - Note that the detector bit due to being Insect/Demon, plant and Boss mode
   bits need to be added independently of this list.

+ 2 - 1
doc/sample/basejob_baseclass_upper.txt

@@ -3,5 +3,6 @@ prontera,155,177,1	script	Tell Me	725,{
 	mes "Class: " + Class;
 	mes "BaseClass: " + BaseClass;
 	mes "BaseJob: " + BaseJob;
-	mes "Upper: " + Uppser;
+	mes "Upper: " + Upper;
+	close;
 }

+ 3 - 6
doc/script_commands.txt

@@ -4,7 +4,7 @@
 //= A reference manual for the eAthena scripting language.
 //= Commands are sorted depending on their functionality.
 //===== Version ===========================================
-//= 3.34.20101217
+//= 3.35.20110106
 //=========================================================
 //= 1.0 - First release, filled will as much info as I could
 //=       remember or figure out, most likely there are errors,
@@ -153,6 +153,8 @@
 //=       behavior. [Ai4rei]
 //= 3.34.20101217
 //=       Spellcheck. [Ai4rei]
+//= 3.35.20110106
+//=       Removed bug warning from 'deletearray'. [Ai4rei]
 //=========================================================
 
 This document is a reference manual for all the scripting commands and functions 
@@ -2105,11 +2107,6 @@ array, shifting all the elements beyond this towards the beginning.
 
     deletearray @array[1],3
 
-IMPORTANT: deletarray is horribly broken since the earliest days of jAthena. It 
-tends to merrily remove much more variables than it's told to remove, which 
-makes it pretty much useless for anything other than removing an array from 
-memory entirely. This would be very handy, if it always worked. 
-
 ---------------------------------------
 
 ======================================

+ 1 - 1
doc/whisper_sys.txt

@@ -11,7 +11,7 @@ You whisper to NPCCommander in Game with formatted instructions like these:
 
 //============================================================
 
-[To NPC:Commander]       Report#Killstealing#Lordalfa
+[To NPC:NPCCommander]       Report#Killstealing#Lordalfa
 
 //============================================================
 

+ 0 - 12
eAthena-10.sln

@@ -14,8 +14,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-server_sql", "vcproj-10
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapcache", "vcproj-10\mapcache.vcxproj", "{D356871D-58E1-450B-967A-E7E9646175AF}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ladmin", "vcproj-10\ladmin.vcxproj", "{D356871D-58E1-450B-967A-E8E9646175AF}"
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-login", "vcproj-10\txt-converter-login.vcxproj", "{D356871D-58E1-450B-967A-E9E9646175AF}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-char", "vcproj-10\txt-converter-char.vcxproj", "{D356871D-58E1-450B-967A-EAE9646175AF}"
@@ -102,16 +100,6 @@ Global
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-sql|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32

+ 24 - 0
eAthena-6.dsw

@@ -75,6 +75,30 @@ Package=<4>
 
 ###############################################################################
 
+Project: "console"=".\vcproj-6\plugin-console.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pid"=".\vcproj-6\plugin-pid.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
 Global:
 
 Package=<5>

+ 12 - 12
eAthena-8.sln

@@ -14,12 +14,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-server_sql", "vcproj-8\
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapcache", "vcproj-8\mapcache.vcproj", "{D356871D-58E1-450B-967A-E7E9646175AF}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ladmin", "vcproj-8\ladmin.vcproj", "{D356871D-58E1-450B-967A-E8E9646175AF}"
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-login", "vcproj-8\txt-converter-login.vcproj", "{D356871D-58E1-450B-967A-E9E9646175AF}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-char", "vcproj-8\txt-converter-char.vcproj", "{D356871D-58E1-450B-967A-EAE9646175AF}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin-console", "vcproj-8\plugin-console.vcproj", "{73E1101A-310C-4453-8F45-FD2795ABEF15}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin-pid", "vcproj-8\plugin-pid.vcproj", "{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -102,16 +104,6 @@ Global
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-sql|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32
@@ -132,6 +124,14 @@ Global
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Debug|Win32.ActiveCfg = Debug|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Debug|Win32.Build.0 = Debug|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Release|Win32.ActiveCfg = Release|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Release|Win32.Build.0 = Release|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Debug|Win32.Build.0 = Debug|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Release|Win32.ActiveCfg = Release|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 12 - 12
eAthena-9.sln

@@ -14,12 +14,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-server_sql", "vcproj-9\
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapcache", "vcproj-9\mapcache.vcproj", "{D356871D-58E1-450B-967A-E7E9646175AF}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ladmin", "vcproj-9\ladmin.vcproj", "{D356871D-58E1-450B-967A-E8E9646175AF}"
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-login", "vcproj-9\txt-converter-login.vcproj", "{D356871D-58E1-450B-967A-E9E9646175AF}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txt-converter-char", "vcproj-9\txt-converter-char.vcproj", "{D356871D-58E1-450B-967A-EAE9646175AF}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin-console", "vcproj-9\plugin-console.vcproj", "{73E1101A-310C-4453-8F45-FD2795ABEF15}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin-pid", "vcproj-9\plugin-pid.vcproj", "{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -102,16 +104,6 @@ Global
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-sql|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-E7E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.ActiveCfg = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Debug-txt|Win32.Build.0 = Debug|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release|Win32.Build.0 = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
-		{D356871D-58E1-450B-967A-E8E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.Build.0 = Debug|Win32
 		{D356871D-58E1-450B-967A-E9E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32
@@ -132,6 +124,14 @@ Global
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32
 		{D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.Build.0 = Release|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Debug|Win32.ActiveCfg = Debug|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Debug|Win32.Build.0 = Debug|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Release|Win32.ActiveCfg = Release|Win32
+		{73E1101A-310C-4453-8F45-FD2795ABEF15}.Release|Win32.Build.0 = Release|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Debug|Win32.Build.0 = Debug|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Release|Win32.ActiveCfg = Release|Win32
+		{9509E1B9-DA2B-4153-9EE0-CBCA6597F198}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 5 - 0
npc/Changelog.txt

@@ -1,5 +1,10 @@
 Date		Added
 ======
+2011/01/16
+	* Rev. 14676 Various fixes for scripts that are disabled by default. [Ai4rei]
+	- Fixed name collision in Baphomet Jr. taming item quest (custom) with 'Little Boy' in cities/lutie.txt
+	- Fixed name collision in THQS_Quests (custom) with 'Little Girl' in cities/lutie.txt
+	- Fixed outdated reference to npc_dynamic_shop sample (follow up to r14277).
 2010/12/03
 	* Rev. 14555 Updated instances with more proper English, care of Resplendent. [L0ne_W0lf]
 2010/12/02

+ 3 - 2
npc/custom/quests/bookofthedevil.txt

@@ -3,7 +3,7 @@
 //===== By: ================================================== 
 //= eAthena Dev Team
 //===== Current Version: ===================================== 
-//= 1.1
+//= 1.2
 //===== Compatible With: ===================================== 
 //= eAthena 1.0
 //===== Description: ========================================= 
@@ -11,6 +11,7 @@
 //===== Additional Comments: ================================= 
 //= 1.0 ????
 //= 1.1 Optimized Book of Devil quest. used bit-wise var. [Lupus]
+//= 1.2 Fixed name collision with 'Little Boy' in cities/lutie.txt [Ai4rei]
 //============================================================ 
 
 //=============================================================
@@ -62,7 +63,7 @@ M_NO:
 	close;
 }
 
-nif_fild01,213,268,5	script	Little Boy	797,{
+nif_fild01,213,268,5	script	Little Boy#02	797,{
 	if(MISC_QUEST & 256){
 L_DONE:
 		set @niflheimlost,2;

+ 3 - 2
npc/custom/quests/thq/THQS_Quests.txt

@@ -10,7 +10,7 @@
 //                    revised By Warlock                    //
 //////////////////////////////////////////////////////////////
 //===== Version ==============================================
-//= 1.4
+//= 1.5
 //===== Compatible With ======================================
 //= eAthena 1.0
 //===== Description ==========================================
@@ -22,6 +22,7 @@
 //= 1.2 some bugfixes, typos [Lupus]
 //= 1.3 Removed Duplicates [Silent]
 //= 1.4 Further removed duplicates. [L0ne_W0lf]
+//= 1.5 Fixed name collision with 'Little Girl' in cities/lutie.txt [Ai4rei]
 //============================================================
 
 
@@ -671,7 +672,7 @@ N_QuestStart:
 }
 ///////Job list 7///////
 //7-1 goes to 8-1 using callfunc;
-prontera,123,208,6	script	Little Girl	717,{
+prontera,123,208,6	script	Little Girl#thq	717,{
 	if (seven_qset == 1 && countitem(531) > 4) goto N_QuestComp;
 	if (seven_qset == 1) goto N_QuestStart;
 	if (eight_qset == 1) goto N_QuestStart2;

+ 2 - 2
npc/other/Global_Functions.txt

@@ -340,9 +340,9 @@ function	script	Time2Str	{
 		set .@Time$, .@Time$ + .@Minutes + " minute, ";
 
 	if( .@Time_Left > 1 || .@Time_Left == 0 )
-		set .@Time$, .@Time$ + .@Time_Left + " seconds.";
+		set .@Time$, .@Time$ + .@Time_Left + " seconds";
 	else if( .@Time_Left == 1 )
-		set .@Time$, .@Time$ + .@Time_Left + " second.";
+		set .@Time$, .@Time$ + .@Time_Left + " second";
 	
 	return .@Time$;
 }

+ 1 - 1
npc/scripts_custom.conf

@@ -86,7 +86,7 @@
 //npc: npc/custom/Lance/FR_HallOfFame.c
 //npc: npc/custom/Lance/FR_WeatherController.c
 //npc: npc/custom/Lance/FR_MailSystem.c
-//npc: npc/sample/npc_dynamic_shop.txt
+//npc: doc/sample/npc_dynamic_shop.txt
 // --------------------------------------------------------------
 
 // --------------------------------------------------------------

+ 0 - 1
readme/features.html

@@ -109,7 +109,6 @@ so we will focus mainly on stability for the time being, not new features.
 	<li>2-2 Jobs (Alternate 2nd Jobs)</li>
 	<li>Super Novice (Alternate 1st Job)</li>
 	<li>WoE (War of Emperium)</li>
-	<li>Remote administration of accounts (ladmin)</li>
 	<li>Weddings</li>
 	<li>Pet equipped mobs</li>
 	<li>Management of day/night</li>

+ 1 - 1
readme/setup.html

@@ -92,7 +92,7 @@
 It's extremely easy to set up eAthena, just follow these simple steps.
 <ol>
 	<li>Edit motd.txt, grf-files.txt and the .conf files in your /conf/ folder as you see fit</li>
-	<li>If you want to add a user, run adduser.exe in the main eAthena directory before starting the server.</li>
+	<li>If you want to add a user, edit save/account.txt in the main eAthena directory before starting the server.</li>
 	<li>Run runserver.bat or runserver-sql.bat (depending on which storage system you're using, or you could run login-server.exe, char-server.exe, and map-server.exe manually)</li>
 	<li>Give people your IP address (can be found at <a href="http://www.whatismyip.com">http://www.whatismyip.com</a>) to people to add in their sclientinfo.xml</li>
 	<li>You're done!</li>

+ 8 - 8
save-tmpl/account.txt

@@ -1,16 +1,16 @@
-20080409
+20110114
 // Accounts file: here are saved all information about the accounts.
-// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, repeated(register key, register value)
+// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, birth date, repeated(register key, register value)
 // where:
 //   sex             : M or F for normal accounts, S for server accounts
 //   level           : this account's gm level
 //   state           : 0: account is ok, 1 to 256: error code of packet 0x006a + 1
 //   unban time      : 0: no ban, <other value>: banned until the date (unix timestamp)
 //   expiration time : 0: unlimited account, <other value>: account expires on the date (unix timestamp)
-1	s1	p1	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
-2	s2	p2	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
-3	s3	p3	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
-4	s4	p4	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
-5	s5	p5	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
-2000001	Test	Test	M	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	
+1	s1	p1	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
+2	s2	p2	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
+3	s3	p3	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
+4	s4	p4	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
+5	s5	p5	S	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
+2000001	Test	Test	M	a@a.com	0	0	0	0	0	0000-00-00 00:00:00	-	0000-00-00	
 2000002	%newid%

+ 1 - 0
sql-files/main.sql

@@ -406,6 +406,7 @@ CREATE TABLE IF NOT EXISTS `login` (
   `logincount` mediumint(9) unsigned NOT NULL default '0',
   `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00',
   `last_ip` varchar(100) NOT NULL default '',
+  `birthdate` DATE NOT NULL DEFAULT '0000-00-00',
   PRIMARY KEY  (`account_id`),
   KEY `name` (`userid`)
 ) ENGINE=MyISAM AUTO_INCREMENT=2000000; 

+ 1 - 0
sql-files/upgrade_svn14672.sql

@@ -0,0 +1 @@
+ALTER TABLE `login` ADD `birthdate` DATE NOT NULL DEFAULT '0000-00-00';

+ 24 - 164
src/char/char.c

@@ -184,7 +184,7 @@ static void* create_online_char_data(DBKey key, va_list args)
 	character->char_id = -1;
   	character->server = -1;
 	character->fd = -1;
-	character->waiting_disconnect = -1;
+	character->waiting_disconnect = INVALID_TIMER;
 	return character;
 }
 
@@ -201,9 +201,9 @@ void set_char_charselect(int account_id)
 	character->char_id = -1;
 	character->server = -1;
 
-	if(character->waiting_disconnect != -1) {
+	if(character->waiting_disconnect != INVALID_TIMER) {
 		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 	}
 
 	if (login_fd > 0 && !session[login_fd]->flag.eof)
@@ -237,9 +237,9 @@ void set_char_online(int map_id, int char_id, int account_id)
 		server[character->server].users++;
 
 	//Get rid of disconnect timer
-	if(character->waiting_disconnect != -1) {
+	if(character->waiting_disconnect != INVALID_TIMER) {
 		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 	}
 
 	//Notify login server
@@ -262,9 +262,9 @@ void set_char_offline(int char_id, int account_id)
 			if( server[character->server].users > 0 ) // Prevent this value from going negative.
 				server[character->server].users--;
 
-		if(character->waiting_disconnect != -1){
+		if(character->waiting_disconnect != INVALID_TIMER){
 			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-			character->waiting_disconnect = -1;
+			character->waiting_disconnect = INVALID_TIMER;
 		}
 
 		if(character->char_id == char_id)
@@ -293,9 +293,9 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap)
 	if (server == -1) {
 		character->char_id = -1;
 		character->server = -1;
-		if(character->waiting_disconnect != -1){
+		if(character->waiting_disconnect != INVALID_TIMER){
 			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-			character->waiting_disconnect = -1;
+			character->waiting_disconnect = INVALID_TIMER;
 		}
 	} else if (character->server == server)
 		character->server = -2; //In some map server that we aren't connected to.
@@ -313,7 +313,7 @@ static int char_db_kickoffline(DBKey key, void* data, va_list ap)
 	//Kick out any connected characters, and set them offline as appropiate.
 	if (character->server > -1)
 		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
-	else if (character->waiting_disconnect == -1)
+	else if (character->waiting_disconnect == INVALID_TIMER)
 		set_char_offline(character->char_id, character->account_id);
 	else
 		return 0; // fail
@@ -1937,7 +1937,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 		if (character->server > -1)
 		{	//Character already online. KICK KICK KICK
 			mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
-			if (character->waiting_disconnect == -1)
+			if (character->waiting_disconnect == INVALID_TIMER)
 				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
 			WFIFOB(fd,2) = 8;
@@ -2016,7 +2016,7 @@ int parse_fromlogin(int fd)
 				ShowStatus("Connected to login-server (connection #%d).\n", fd);
 				
 				//Send online accounts to login server.
-				send_accounts_tologin(-1, gettick(), 0, 0);
+				send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
 
 				// if no map-server already connected, display a message...
 				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
@@ -2176,72 +2176,6 @@ int parse_fromlogin(int fd)
 		}
 		break;
 
-		case 0x2726:	// Request to send a broadcast message (no answer)
-			if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4)))
-				return 0;
-			if (RFIFOL(fd,4) < 1)
-				char_log("Receiving a message for broadcast, but message is void.\n");
-			else
-			{
-				// at least 1 map-server
-				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd >= 0 );
-				if (i == MAX_MAP_SERVERS)
-					char_log("'ladmin': Receiving a message for broadcast, but no map-server is online.\n");
-				else {
-					unsigned char buf[128];
-					char message[4096]; // +1 to add a null terminated if not exist in the packet
-					int lp;
-					char *p;
-					memset(message, '\0', sizeof(message));
-					memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4));
-					message[sizeof(message)-1] = '\0';
-					remove_control_chars(message);
-					// remove all first spaces
-					p = message;
-					while(p[0] == ' ')
-						p++;
-					// if message is only composed of spaces
-					if (p[0] == '\0')
-						char_log("Receiving a message for broadcast, but message is only a lot of spaces.\n");
-					// else send message to all map-servers
-					else {
-						if (RFIFOW(fd,2) == 0) {
-							char_log("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n",
-							         message);
-							lp = 4;
-						} else {
-							char_log("'ladmin': Receiving a message for broadcast (message (in blue): %s)\n",
-							         message);
-							lp = 8;
-						}
-						// split message to max 80 char
-						while(p[0] != '\0') { // if not finish
-							if (p[0] == ' ') // jump if first char is a space
-								p++;
-							else {
-								char split[80];
-								char* last_space;
-								sscanf(p, "%79[^\t]", split); // max 79 char, any char (\t is control char and control char was removed before)
-								split[sizeof(split)-1] = '\0'; // last char always \0
-								if ((last_space = strrchr(split, ' ')) != NULL) { // searching space from end of the string
-									last_space[0] = '\0'; // replace it by NULL to have correct length of split
-									p++; // to jump the new NULL
-								}
-								p += strlen(split);
-								// send broadcast to all map-servers
-								WBUFW(buf,0) = 0x3800;
-								WBUFW(buf,2) = lp + strlen(split) + 1;
-								WBUFL(buf,4) = 0x65756c62; // only write if in blue (lp = 8)
-								memcpy(WBUFP(buf,lp), split, strlen(split) + 1);
-								mapif_sendall(buf, WBUFW(buf,2));
-							}
-						}
-					}
-				}
-			}
-			RFIFOSKIP(fd,8 + RFIFOL(fd,4));
-		break;
-
 		// reply to an account_reg2 registry request
 		case 0x2729:
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
@@ -2256,54 +2190,6 @@ int parse_fromlogin(int fd)
 		}
 		break;
 
-		// Account deletion notification (from login-server)
-		case 0x2730:
-			if (RFIFOREST(fd) < 6)
-				return 0;
-			// Deletion of all characters of the account
-			for(i = 0; i < char_num; i++) {
-				if (char_dat[i].status.account_id == RFIFOL(fd,2)) {
-					char_delete(&char_dat[i].status);
-					if (i < char_num - 1) {
-						memcpy(&char_dat[i], &char_dat[char_num-1], sizeof(struct character_data));
-						// if moved character owns to deleted account, check again it's character
-						if (char_dat[i].status.account_id == RFIFOL(fd,2)) {
-							i--;
-						// Correct moved character reference in the character's owner by [Yor]
-						} else {
-							int j, k;
-							struct char_session_data *sd2;
-							for (j = 0; j < fd_max; j++) {
-								if (session[j] && (sd2 = (struct char_session_data*)session[j]->session_data) &&
-									sd2->account_id == char_dat[char_num-1].status.account_id) {
-									for (k = 0; k < MAX_CHARS; k++) {
-										if (sd2->found_char[k] == char_num-1) {
-											sd2->found_char[k] = i;
-											break;
-										}
-									}
-									break;
-								}
-							}
-						}
-					}
-					char_num--;
-				}
-			}
-			// Deletion of the storage
-			inter_storage_delete(RFIFOL(fd,2));
-			// send to all map-servers to disconnect the player
-			{
-				unsigned char buf[6];
-				WBUFW(buf,0) = 0x2b13;
-				WBUFL(buf,2) = RFIFOL(fd,2);
-				mapif_sendall(buf, 6);
-			}
-			// disconnect player if online on char-server
-			disconnect_player(RFIFOL(fd,2));
-			RFIFOSKIP(fd,6);
-		break;
-
 		// State change of account/ban notification (from login-server)
 		case 0x2731:
 			if (RFIFOREST(fd) < 11)
@@ -2336,7 +2222,7 @@ int parse_fromlogin(int fd)
 				if( character->server > -1 )
 				{	//Kick it from the map server it is on.
 					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
-					if (character->waiting_disconnect == -1)
+					if (character->waiting_disconnect == INVALID_TIMER)
 						character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
 				}
 				else
@@ -3550,7 +3436,7 @@ int parse_char(int fd)
 
 			ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
 			memcpy(email, RFIFOP(fd,6), 40);
-			RFIFOSKIP(fd,RFIFOREST(fd)); // hack to make the other deletion packet work
+			RFIFOSKIP(fd,( cmd == 0x68 ) ? 46 : 56);
 
 			if (e_mail_check(email) == 0)
 				safestrncpy(email, "a@a.com", sizeof(email)); // default e-mail
@@ -3750,22 +3636,6 @@ int parse_char(int fd)
 		}
 		return 0; // avoid processing of followup packets here
 
-		// Athena info get
-		case 0x7530:
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x7531;
-			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
-			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
-			WFIFOB(fd,4) = ATHENA_REVISION;
-			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
-			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
-			WFIFOB(fd,7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR;
-			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
-			WFIFOSET(fd,10);
-
-			RFIFOSKIP(fd,2);
-		break;
-
 		// unknown packet received
 		default:
 			ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));
@@ -3779,29 +3649,19 @@ int parse_char(int fd)
 }
 
 // Console Command Parser [Wizputer]
-int parse_console(char* buf)
+int parse_console(const char* command)
 {
-	char command[256];
+	ShowNotice("Console command: %s\n", command);
 
-	memset(command, 0, sizeof(command));
-
-	sscanf(buf, "%[^\n]", command);
-
-	//login_log("Console command :%s\n", command);
-
-	if( strcmpi("shutdown", command) == 0 ||
-	    strcmpi("exit", command) == 0 ||
-	    strcmpi("quit", command) == 0 ||
-	    strcmpi("end", command) == 0 )
+	if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 )
 		runflag = 0;
-	else if( strcmpi("alive", command) == 0 ||
-	         strcmpi("status", command) == 0 )
+	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("help", command) == 0 ){
-		ShowInfo(CL_BOLD"Help of commands:"CL_RESET"\n");
-		ShowInfo("  To shutdown the server:\n");
-		ShowInfo("  'shutdown|exit|qui|end'\n");
-		ShowInfo("  To know if server is alive:\n");
+	else if( strcmpi("help", command) == 0 )
+	{
+		ShowInfo("To shutdown the server:\n");
+		ShowInfo("  'shutdown|exit|quit|end'\n");
+		ShowInfo("To know if server is alive:\n");
 		ShowInfo("  'alive|status'\n");
 	}
 
@@ -3978,7 +3838,7 @@ static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr
 	struct online_char_data* character;
 	if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
 	{	//Mark it offline due to timeout.
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 		set_char_offline(character->char_id, character->account_id);
 	}
 	return 0;

+ 24 - 50
src/char_sql/char.c

@@ -202,7 +202,7 @@ static void* create_online_char_data(DBKey key, va_list args)
 	character->char_id = -1;
   	character->server = -1;
 	character->fd = -1;
-	character->waiting_disconnect = -1;
+	character->waiting_disconnect = INVALID_TIMER;
 	return character;
 }
 
@@ -219,9 +219,9 @@ void set_char_charselect(int account_id)
 	character->char_id = -1;
 	character->server = -1;
 
-	if(character->waiting_disconnect != -1) {
+	if(character->waiting_disconnect != INVALID_TIMER) {
 		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 	}
 
 	if (login_fd > 0 && !session[login_fd]->flag.eof)
@@ -260,9 +260,9 @@ void set_char_online(int map_id, int char_id, int account_id)
 		server[character->server].users++;
 
 	//Get rid of disconnect timer
-	if(character->waiting_disconnect != -1) {
+	if(character->waiting_disconnect != INVALID_TIMER) {
 		delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 	}
 
 	//Set char online in guild cache. If char is in memory, use the guild id on it, otherwise seek it.
@@ -305,9 +305,9 @@ void set_char_offline(int char_id, int account_id)
 			if( server[character->server].users > 0 ) // Prevent this value from going negative.
 				server[character->server].users--;
 
-		if(character->waiting_disconnect != -1){
+		if(character->waiting_disconnect != INVALID_TIMER){
 			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-			character->waiting_disconnect = -1;
+			character->waiting_disconnect = INVALID_TIMER;
 		}
 
 		if(character->char_id == char_id)
@@ -336,9 +336,9 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap)
 	if (server == -1) {
 		character->char_id = -1;
 		character->server = -1;
-		if(character->waiting_disconnect != -1){
+		if(character->waiting_disconnect != INVALID_TIMER){
 			delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
-			character->waiting_disconnect = -1;
+			character->waiting_disconnect = INVALID_TIMER;
 		}
 	} else if (character->server == server)
 		character->server = -2; //In some map server that we aren't connected to.
@@ -356,7 +356,7 @@ static int char_db_kickoffline(DBKey key, void* data, va_list ap)
 	//Kick out any connected characters, and set them offline as appropiate.
 	if (character->server > -1)
 		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
-	else if (character->waiting_disconnect == -1)
+	else if (character->waiting_disconnect == INVALID_TIMER)
 		set_char_offline(character->char_id, character->account_id);
 	else
 		return 0; // fail
@@ -1722,7 +1722,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 		if (character->server > -1)
 		{	//Character already online. KICK KICK KICK
 			mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
-			if (character->waiting_disconnect == -1)
+			if (character->waiting_disconnect == INVALID_TIMER)
 				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
 			WFIFOB(fd,2) = 8;
@@ -1801,7 +1801,7 @@ int parse_fromlogin(int fd)
 				ShowStatus("Connected to login-server (connection #%d).\n", fd);
 				
 				//Send online accounts to login server.
-				send_accounts_tologin(-1, gettick(), 0, 0);
+				send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
 
 				// if no map-server already connected, display a message...
 				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
@@ -2008,7 +2008,7 @@ int parse_fromlogin(int fd)
 				if( character->server > -1 )
 				{	//Kick it from the map server it is on.
 					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
-					if (character->waiting_disconnect == -1)
+					if (character->waiting_disconnect == INVALID_TIMER)
 						character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
 				}
 				else
@@ -3256,7 +3256,7 @@ int parse_char(int fd)
 
 			ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
 			memcpy(email, RFIFOP(fd,6), 40);
-			RFIFOSKIP(fd,RFIFOREST(fd)); // hack to make the other deletion packet work
+			RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
 			
 			// Check if e-mail is correct 
 			if(strcmpi(email, sd->email) && //email does not matches and 
@@ -3429,22 +3429,6 @@ int parse_char(int fd)
 		}
 		return 0; // avoid processing of followup packets here
 
-		// Athena info get
-		case 0x7530:
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x7531;
-			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
-			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
-			WFIFOB(fd,4) = ATHENA_REVISION;
-			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
-			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
-			WFIFOB(fd,7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR;
-			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
-			WFIFOSET(fd,10);
-
-			RFIFOSKIP(fd,2);
-		break;
-
 		// unknown packet received
 		default:
 			ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));
@@ -3458,29 +3442,19 @@ int parse_char(int fd)
 }
 
 // Console Command Parser [Wizputer]
-int parse_console(char* buf)
+int parse_console(const char* command)
 {
-	char command[256];
+	ShowNotice("Console command: %s\n", command);
 
-	memset(command, 0, sizeof(command));
-
-	sscanf(buf, "%[^\n]", command);
-
-	//login_log("Console command :%s\n", command);
-
-	if( strcmpi("shutdown", command) == 0 ||
-	    strcmpi("exit", command) == 0 ||
-	    strcmpi("quit", command) == 0 ||
-	    strcmpi("end", command) == 0 )
+	if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 )
 		runflag = 0;
-	else if( strcmpi("alive", command) == 0 ||
-	         strcmpi("status", command) == 0 )
+	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("help", command) == 0 ){
-		ShowInfo(CL_BOLD"Help of commands:"CL_RESET"\n");
-		ShowInfo("  To shutdown the server:\n");
-		ShowInfo("  'shutdown|exit|qui|end'\n");
-		ShowInfo("  To know if server is alive:\n");
+	else if( strcmpi("help", command) == 0 )
+	{
+		ShowInfo("To shutdown the server:\n");
+		ShowInfo("  'shutdown|exit|quit|end'\n");
+		ShowInfo("To know if server is alive:\n");
 		ShowInfo("  'alive|status'\n");
 	}
 
@@ -3654,7 +3628,7 @@ static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr
 	struct online_char_data* character;
 	if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
 	{	//Mark it offline due to timeout.
-		character->waiting_disconnect = -1;
+		character->waiting_disconnect = INVALID_TIMER;
 		set_char_offline(character->char_id, character->account_id);
 	}
 	return 0;

+ 1 - 1
src/char_sql/int_auction.c

@@ -166,7 +166,7 @@ void auction_delete(struct auction_data *auction)
 	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) )
 		Sql_ShowDebug(sql_handle);
 
-	if( auction->auction_end_timer != -1 )
+	if( auction->auction_end_timer != INVALID_TIMER )
 		delete_timer(auction->auction_end_timer, auction_end_timer);
 
 	idb_remove(auction_db_, auction_id);

+ 1 - 1
src/common/core.h

@@ -11,7 +11,7 @@ extern int runflag;
 extern char *SERVER_NAME;
 extern char SERVER_TYPE;
 
-extern int parse_console(char* buf);
+extern int parse_console(const char* buf);
 extern const char *get_svn_revision(void);
 extern int do_init(int,char**);
 extern void set_server_type(void);

+ 2 - 2
src/common/db.c

@@ -697,7 +697,7 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root)
 				db->alloc_file, db->alloc_line);
 		exit(EXIT_FAILURE);
 	}
-	if (!(db->options&DB_OPT_DUP_KEY)) { // Make shure we have a key until the node is freed
+	if (!(db->options&DB_OPT_DUP_KEY)) { // Make sure we have a key until the node is freed
 		old_key = node->key;
 		node->key = db_dup_key(db, node->key);
 		db->release(old_key, node->data, DB_RELEASE_KEY);
@@ -1976,13 +1976,13 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args)
 				node->deleted = 1;
 			}
 			DB_COUNTSTAT(db_node_free);
-			ers_free(db->nodes, node);
 			if (parent) {
 				if (parent->left == node)
 					parent->left = NULL;
 				else
 					parent->right = NULL;
 			}
+			ers_free(db->nodes, node);
 			node = parent;
 		}
 		db->ht[i] = NULL;

+ 92 - 42
src/common/grfio.c

@@ -12,6 +12,8 @@
 #include "../common/cbasetypes.h"
 #include "../common/showmsg.h"
 #include "../common/malloc.h"
+#include "../common/strlib.h"
+#include "../common/utils.h"
 
 
 //----------------------------
@@ -381,6 +383,35 @@ static void filelist_adjust(void)
 	}
 }
 
+
+/// Combines are resource path with the data folder location to
+/// create local resource path.
+static void grfio_localpath_create(char* buffer, size_t size, const char* filename)
+{
+	unsigned int i;
+	size_t len;
+
+	len = strlen(data_dir);
+
+	if( data_dir[0] == 0 || data_dir[len-1] == '/' || data_dir[len-1] == '\\' )
+	{
+		safesnprintf(buffer, size, "%s%s", data_dir, filename);
+	}
+	else
+	{
+		safesnprintf(buffer, size, "%s/%s", data_dir, filename);
+	}
+
+	for( i = 0; buffer[i]; i++ )
+	{// normalize path
+		if( buffer[i] == '\\' )
+		{
+			buffer[i] = '/';
+		}
+	}
+}
+
+
 /***********************************************************
  ***                  Grfio Sobroutines                  ***
  ***********************************************************/
@@ -398,13 +429,10 @@ int grfio_size(char* fname)
 		FILELIST lentry;
 		struct stat st;
 
-		sprintf(lfname, "%s%s", data_dir, fname);
-
-		for (p = &lfname[0]; *p != 0; p++)
-			if (*p=='\\') *p = '/';
+		grfio_localpath_create(lfname, sizeof(lfname), fname);
 
 		if (stat(lfname, &st) == 0) {
-			strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1);
+			safestrncpy(lentry.fn, fname, sizeof(lentry.fn));
 			lentry.fnd = NULL;
 			lentry.declen = st.st_size;
 			lentry.gentry = 0;	// 0:LocalFile
@@ -428,35 +456,28 @@ void* grfio_reads(char* fname, int* size)
 	entry = filelist_find(fname);
 
 	if (entry == NULL || entry->gentry <= 0) {	// LocalFileCheck
-		char lfname[256], *p;
-		FILELIST lentry;
+		char lfname[256];
+		int declen;
 
-		sprintf(lfname, "%s%s", data_dir, fname);
-		
-		for (p = &lfname[0]; *p != 0; p++)
-			if (*p == '\\') *p = '/';
+		grfio_localpath_create(lfname, sizeof(lfname), ( entry && entry->fnd ) ? entry->fnd : fname);
 
 		in = fopen(lfname, "rb");
 		if (in != NULL) {
-			if (entry != NULL && entry->gentry == 0) {
-				lentry.declen = entry->declen;
-			} else {
-				fseek(in,0,SEEK_END);
-				lentry.declen = ftell(in);
-			}
+			fseek(in,0,SEEK_END);
+			declen = ftell(in);
 			fseek(in,0,SEEK_SET);
-			buf2 = (unsigned char *)aMallocA(lentry.declen + 1024);
-			fread(buf2, 1, lentry.declen, in);
+			buf2 = (unsigned char *)aMallocA(declen+1);  // +1 for resnametable zero-termination
+			fread(buf2, 1, declen, in);
 			fclose(in);
-			strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1);
-			lentry.fnd = NULL;
-			lentry.gentry = 0;	// 0:LocalFile
-			entry = filelist_modify(&lentry);
+			if( size )
+			{
+				size[0] = declen;
+			}
 		} else {
 			if (entry != NULL && entry->gentry < 0) {
 				entry->gentry = -entry->gentry;	// local file checked
 			} else {
-				ShowError("%s not found (grfio_reads - local file %s)\n", fname, lfname);
+				ShowError("grfio_reads: %s not found (local file: %s)\n", fname, lfname);
 				return NULL;
 			}
 		}
@@ -465,11 +486,11 @@ void* grfio_reads(char* fname, int* size)
 		char* grfname = gentry_table[entry->gentry - 1];
 		in = fopen(grfname, "rb");
 		if(in != NULL) {
-			unsigned char *buf = (unsigned char *)aMallocA(entry->srclen_aligned + 1024);
+			unsigned char *buf = (unsigned char *)aMallocA(entry->srclen_aligned);
 			fseek(in, entry->srcpos, 0);
 			fread(buf, 1, entry->srclen_aligned, in);
 			fclose(in);
-			buf2 = (unsigned char *)aMallocA(entry->declen + 1024);
+			buf2 = (unsigned char *)aMallocA(entry->declen+1);  // +1 for resnametable zero-termination
 			if (entry->type == 1 || entry->type == 3 || entry->type == 5) {
 				uLongf len;
 				if (entry->cycle >= 0)
@@ -485,14 +506,16 @@ void* grfio_reads(char* fname, int* size)
 			} else {
 				memcpy(buf2, buf, entry->declen);
 			}
+			if( size )
+			{
+				size[0] = entry->declen;
+			}
 			aFree(buf);
 		} else {
-			ShowError("%s not found (grfio_reads - GRF file %s)\n", fname, grfname);
+			ShowError("grfio_reads: %s not found (GRF file: %s)\n", fname, grfname);
 			return NULL;
 		}
 	}
-	if (size != NULL && entry != NULL)
-		*size = entry->declen;
 
 	return buf2;
 }
@@ -590,7 +613,7 @@ static int grfio_entryread(char* grfname, int gentry)
 				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e;
 				aentry.cycle          = srccount;
 				aentry.type           = type;
-				strncpy(aentry.fn, fname,sizeof(aentry.fn)-1);
+				safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
 				aentry.fnd			  = NULL;
 #ifdef	GRFIO_LOCAL
 				aentry.gentry         = -(gentry+1);	// As Flag for making it a negative number carrying out the first time LocalFileCheck
@@ -657,7 +680,7 @@ static int grfio_entryread(char* grfname, int gentry)
 				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e;
 				aentry.cycle          = srccount;
 				aentry.type           = type;
-				strncpy(aentry.fn,fname,sizeof(aentry.fn)-1);
+				safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
 				aentry.fnd			  = NULL;
 #ifdef	GRFIO_LOCAL
 				aentry.gentry         = -(gentry+1);	// As Flag for making it a negative number carrying out the first time LocalFileCheck
@@ -686,17 +709,16 @@ static int grfio_entryread(char* grfname, int gentry)
  *------------------------------------------*/
 static void grfio_resourcecheck(void)
 {
-	char w1[256], w2[256], src[256], dst[256], restable[256], line[256];
+	char w1[256], w2[256], src[256], dst[256], restable[256], line[256], local[256];
 	char *ptr, *buf;
 	FILELIST* entry;
+	FILELIST fentry;
 	int size;
 	FILE* fp;
 	int i = 0;
 
 	// read resnametable from data directory and return if successful
-	sprintf(restable, "%sdata\\resnametable.txt", data_dir);
-	for (ptr = &restable[0]; *ptr != 0; ptr++)
-		if (*ptr == '\\') *ptr = '/';
+	grfio_localpath_create(restable, sizeof(restable), "data\\resnametable.txt");
 
 	fp = fopen(restable, "rb");
 	if (fp) {
@@ -710,14 +732,28 @@ static void grfio_resourcecheck(void)
 				sprintf(dst, "data\\%s", w2);
 				entry = filelist_find(dst);
 				// create new entries reusing the original's info
-				if (entry != NULL) {
-					FILELIST fentry;
+				if (entry != NULL)
+				{// alias for GRF resource
 					memcpy(&fentry, entry, sizeof(FILELIST));
-					strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
+					safestrncpy(fentry.fn, src, sizeof(fentry.fn));
 					fentry.fnd = aStrdup(dst);
 					filelist_modify(&fentry);
 					i++;
 				}
+				else
+				{
+					grfio_localpath_create(local, sizeof(local), dst);
+
+					if( exists(local) )
+					{// alias for local resource
+						memset(&fentry, 0, sizeof(fentry));
+						//fentry.gentry = 0;
+						safestrncpy(fentry.fn, src, sizeof(fentry.fn));
+						fentry.fnd = aStrdup(dst);
+						filelist_modify(&fentry);
+						i++;
+					}
+				}
 			}
 		}
 		fclose(fp);
@@ -738,14 +774,28 @@ static void grfio_resourcecheck(void)
 				sprintf(src, "data\\%s", w1);
 				sprintf(dst, "data\\%s", w2);
 				entry = filelist_find(dst);
-				if (entry != NULL) {
-					FILELIST fentry;
+				if (entry != NULL)
+				{// alias for GRF resource
 					memcpy(&fentry, entry, sizeof(FILELIST));
-					strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
+					safestrncpy(fentry.fn, src, sizeof(fentry.fn));
 					fentry.fnd = aStrdup(dst);
 					filelist_modify(&fentry);
 					i++;
 				}
+				else
+				{
+					grfio_localpath_create(local, sizeof(local), dst);
+
+					if( exists(local) )
+					{// alias for local resource
+						memset(&fentry, 0, sizeof(fentry));
+						//fentry.gentry = 0;
+						safestrncpy(fentry.fn, src, sizeof(fentry.fn));
+						fentry.fnd = aStrdup(dst);
+						filelist_modify(&fentry);
+						i++;
+					}
+				}
 			}
 			ptr = strchr(ptr, '\n');	// Next line
 			if (!ptr) break;
@@ -824,7 +874,7 @@ void grfio_init(char* fname)
 			if(strcmp(w1, "grf") == 0)	// GRF file
 				grf_num += (grfio_add(w2) == 0);
 			else if(strcmp(w1,"data_dir") == 0) {	// Data directory
-				strcpy(data_dir, w2);
+				safestrncpy(data_dir, w2, sizeof(data_dir));
 			}
 		}
 		fclose(data_conf);

+ 2 - 0
src/common/plugins.c

@@ -251,6 +251,8 @@ Plugin* plugin_open(const char* filename)
 				func = (Plugin_Event_Func*)DLL_SYM(plugin->dll, events[i].func_name);
 				if (func)
 					register_plugin_event(func, events[i].event_name);
+				else
+					ShowError("Failed to locate function '%s' in '%s'.\n", events[i].func_name, filename);
 			}
 			i++;
 		}

+ 2 - 3
src/common/socket.c

@@ -996,10 +996,10 @@ int access_ipmask(const char* str, AccessControl* acc)
 				(n == 5 && m[0] > 32) ){ // invalid bit mask
 			return 0;
 		}
-		ip = (uint32)(a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24));
+		ip = MAKEIP(a[0],a[1],a[2],a[3]);
 		if( n == 8 )
 		{// standard mask
-			mask = (uint32)(a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24));
+			mask = MAKEIP(m[0],m[1],m[2],m[3]);
 		} else if( n == 5 )
 		{// bit mask
 			mask = 0;
@@ -1007,7 +1007,6 @@ int access_ipmask(const char* str, AccessControl* acc)
 				mask = (mask >> 1) | 0x80000000;
 				--m[0];
 			}
-			mask = ntohl(mask);
 		} else
 		{// just this ip
 			mask = 0xFFFFFFFF;

+ 1 - 6
src/common/socket.h

@@ -135,6 +135,7 @@ uint32 host2ip(const char* hostname);
 const char* ip2str(uint32 ip, char ip_str[16]);
 uint32 str2ip(const char* ip_str);
 #define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF
+#define MAKEIP(a,b,c,d) (uint32)( ( ( (a)&0xFF ) << 24 ) | ( ( (b)&0xFF ) << 16 ) | ( ( (c)&0xFF ) << 8 ) | ( ( (d)&0xFF ) << 0 ) )
 uint16 ntows(uint16 netshort);
 
 int socket_getips(uint32* ips, int max);
@@ -152,12 +153,6 @@ void set_eof(int fd);
 #define SEND_SHORTLIST
 
 #ifdef SEND_SHORTLIST
-struct send_shortlist_node {
-	struct send_shortlist_node *next; // Next node in the linked list
-	struct send_shortlist_node *prev; // Previous node in the linked list
-	int fd; // FD that needs sending.
-};
-
 // Add a fd to the shortlist so that it'll be recognized as a fd that needs
 // sending done on it.
 void send_shortlist_add_fd(int fd);

+ 7 - 3
src/common/strlib.c

@@ -925,6 +925,7 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc
 	char** fields; // buffer for fields ([0] is reserved)
 	int columns, fields_length;
 	char path[1024], line[1024];
+	char* match;
 
 	snprintf(path, sizeof(path), "%s/%s", directory, filename);
 
@@ -944,9 +945,12 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc
 	while( fgets(line, sizeof(line), fp) )
 	{
 		lines++;
-		if( line[0] == '/' && line[1] == '/' )
-			continue;
-		//TODO: strip trailing // comment
+
+		if( ( match = strstr(line, "//") ) != NULL )
+		{// strip comments
+			match[0] = 0;
+		}
+
 		//TODO: strip trailing whitespace
 		if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
 			continue;

+ 0 - 45
src/ladmin/Makefile.in

@@ -1,45 +0,0 @@
-
-COMMON_OBJ = ../common/obj_all/minicore.o ../common/obj_all/minisocket.o ../common/obj_all/timer.o \
-	../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/strlib.o \
-	../common/obj_all/utils.o ../common/obj_all/md5calc.o
-COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
-	../common/version.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h \
-	../common/utils.h ../common/md5calc.h ../common/cbasetypes.h
-
-LADMIN_OBJ = obj_all/ladmin.o
-LADMIN_H = ladmin.h
-
-@SET_MAKE@
-
-#####################################################################
-.PHONY : all ladmin clean help
-
-all: ladmin
-
-ladmin: obj_all $(LADMIN_OBJ) $(COMMON_OBJ)
-	@CC@ @LDFLAGS@ -o ../../ladmin@EXEEXT@ $(LADMIN_OBJ) $(COMMON_OBJ) @LIBS@
-
-clean:
-	rm -rf *.o obj_all ../../ladmin@EXEEXT@
-
-help:
-	@echo "possible targets are 'ladmin' 'all' 'clean' 'help'"
-	@echo "'ladmin'  - remote administration tool"
-	@echo "'all'     - builds all above targets"
-	@echo "'clean'   - cleans builds and objects"
-	@echo "'help'    - outputs this message"
-
-#####################################################################
-
-obj_all:
-	-mkdir obj_all
-
-obj_all/%.o: %.c $(LADMIN_H) $(COMMON_H)
-	@CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-
-# missing common object files
-../common/obj_all/%.o:
-	@$(MAKE) -C ../common txt
-
-../common/obj_all/mini%.o:
-	@$(MAKE) -C ../common txt

+ 0 - 3074
src/ladmin/ladmin.c

@@ -1,3074 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-///////////////////////////////////////////////////////////////////////////
-// EAthena login-server remote administration tool
-///////////////////////////////////////////////////////////////////////////
-
-#include "../common/cbasetypes.h"
-#include "../common/core.h"
-#include "../common/strlib.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/version.h"
-#include "../common/mmo.h"
-#include "../common/md5calc.h"
-#include "../common/showmsg.h"
-#include "ladmin.h"
-
-#include <sys/types.h>
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h> // str*
-#include <stdarg.h> // valist
-
-
-//-------------------------------INSTRUCTIONS------------------------------
-// Set the variables below:
-//   IP of the login server.
-//   Port where the login-server listens incoming packets.
-//   Password of administration (same of config_athena.conf).
-// IMPORTANT:
-//   Be sure that you authorize remote administration in login-server
-//   (see login_athena.conf, 'admin_state' parameter)
-//-------------------------------------------------------------------------
-char loginserverip[16] = "127.0.0.1";        // IP of login-server
-int loginserverport = 6900;                  // Port of login-server
-char loginserveradminpassword[24] = "admin"; // Administration password
-int passenc = 0;                             // Encoding type of the password
-char ladmin_log_filename[1024] = "log/ladmin.log";
-char date_format[32] = "%Y-%m-%d %H:%M:%S";
-
-//-------------------------------------------------------------------------
-//  LIST of COMMANDs that you can type at the prompt:
-//    To use these commands you can only type only the first letters.
-//    You must type a minimum of letters (you can not type 'a',
-//      because ladmin doesn't know if it's for 'aide' or for 'add')
-//    <Example> q <= quit, li <= list, pass <= passwd, etc.
-//
-//  Note: every time you must give a account_name, you can use "" or '' (spaces can be included)
-//
-//  aide/help/?
-//    Display the description of the commands
-//  aide/help/? [command]
-//    Display the description of the specified command
-//
-//  add <account_name> <sex> <password>
-//    Create an account with the default email (a@a.com).
-//    Concerning the sex, only the first letter is used (F or M).
-//    The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.
-//    When the password is omitted, the input is done without displaying of the pressed keys.
-//    <example> add testname Male testpass
-//
-//  ban/banish yyyy/mm/dd hh:mm:ss <account name>
-//    Changes the final date of a banishment of an account.
-//    Like banset, but <account name> is at end.
-//
-//  banadd <account_name> <modifier>
-//    Adds or substracts time from the final date of a banishment of an account.
-//    Modifier is done as follows:
-//      Adjustment value (-1, 1, +1, etc...)
-//      Modified element:
-//        a or y: year
-//        m:  month
-//        j or d: day
-//        h:  hour
-//        mn: minute
-//        s:  second
-//    <example> banadd testname +1m-2mn1s-6y
-//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-//  NOTE: If you modify the final date of a non-banished account,
-//        you fix the final date to (actual time +- adjustments)
-//
-//  banset <account_name> yyyy/mm/dd [hh:mm:ss]
-//    Changes the final date of a banishment of an account.
-//    Default time [hh:mm:ss]: 23:59:59.
-//  banset <account_name> 0
-//    Set a non-banished account (0 = unbanished).
-//
-//  block <account name>
-//    Set state 5 (You have been blocked by the GM Team) to an account.
-//    Like state <account name> 5.
-//
-//  check <account_name> <password>
-//    Check the validity of a password for an account
-//    NOTE: Server will never send back a password.
-//          It's the only method you have to know if a password is correct.
-//          The other method is to have a ('physical') access to the accounts file.
-//
-//  create <account_name> <sex> <email> <password>
-//    Like the 'add' command, but with e-mail moreover.
-//    <example> create testname Male my@mail.com testpass
-//
-//  del <account name>
-//    Remove an account.
-//    This order requires confirmation. After confirmation, the account is deleted.
-//
-//  email <account_name> <email>
-//    Modify the e-mail of an account.
-//
-//  getcount
-//    Give the number of players online on all char-servers.
-//
-//  gm <account_name> [GM_level]
-//    Modify the GM level of an account.
-//    Default value remove GM level (GM level = 0).
-//    <example> gm testname 80
-//
-//  id <account name>
-//    Give the id of an account.
-//
-//  info <account_id>
-//    Display complete information of an account.
-//
-//  kami <message>
-//    Sends a broadcast message on all map-server (in yellow).
-//  kamib <message>
-//    Sends a broadcast message on all map-server (in blue).
-//
-//  list/ls [start_id [end_id]]
-//    Display a list of accounts.
-//    'start_id', 'end_id': indicate end and start identifiers.
-//    Research by name is not possible with this command.
-//    <example> list 10 9999999
-//
-//  listBan/lsBan [start_id [end_id]]
-//    Like list/ls, but only for accounts with state or banished
-//
-//  listGM/lsGM [start_id [end_id]]
-//    Like list/ls, but only for GM accounts
-//
-//  listOK/lsOK [start_id [end_id]]
-//    Like list/ls, but only for accounts without state and not banished
-//
-//  memo <account_name> <memo>
-//    Modify the memo of an account.
-//    'memo': it can have until 253 characters (with spaces or not).
-//
-//  name <account_id>
-//    Give the name of an account.
-//
-//  passwd <account_name> <new_password>
-//    Change the password of an account.
-//    When new password is omitted, the input is done without displaying of the pressed keys.
-//
-//  quit/end/exit
-//    End of the program of administration
-//
-//  reloadGM
-//    Reload GM configuration file
-//
-//  search <expression>
-//    Seek accounts.
-//    Displays the accounts whose names correspond.
-//  search -r/-e/--expr/--regex <expression>
-//    Seek accounts by regular expression.
-//    Displays the accounts whose names correspond.
-//
-//  sex <account_name> <sex>
-//    Modify the sex of an account.
-//    <example> sex testname Male
-//
-//  state <account_name> <new_state> <error_message_#7>
-//    Change the state of an account.
-//    'new_state': state is the state of the packet 0x006a + 1. The possibilities are:
-//                 0 = Account ok            6 = Your Game's EXE file is not the latest version
-//                 1 = Unregistered ID       7 = You are Prohibited to log in until %s
-//                 2 = Incorrect Password    8 = Server is jammed due to over populated
-//                 3 = This ID is expired    9 = No MSG
-//                 4 = Rejected from Server  100 = This ID has been totally erased
-//                 5 = You have been blocked by the GM Team
-//                 all other values are 'No MSG', then use state 9 please.
-//    'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
-//
-//  timeadd <account_name> <modifier>
-//    Adds or substracts time from the validity limit of an account.
-//    Modifier is done as follows:
-//      Adjustment value (-1, 1, +1, etc...)
-//      Modified element:
-//        a or y: year
-//        m:  month
-//        j or d: day
-//        h:  hour
-//        mn: minute
-//        s:  second
-//    <example> timeadd testname +1m-2mn1s-6y
-//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-//  NOTE: You can not modify a unlimited validity limit.
-//        If you want modify it, you want probably create a limited validity limit.
-//        So, at first, you must set the validity limit to a date/time.
-//
-//  timeset <account_name> yyyy/mm/dd [hh:mm:ss]
-//    Changes the validity limit of an account.
-//    Default time [hh:mm:ss]: 23:59:59.
-//  timeset <account_name> 0
-//    Gives an unlimited validity limit (0 = unlimited).
-//
-//  unban/unbanish <account name>
-//    Unban an account.
-//    Like banset <account name> 0.
-//
-//  unblock <account name>
-//    Set state 0 (Account ok) to an account.
-//    Like state <account name> 0.
-//
-//  version
-//    Display the version of the login-server.
-//
-//  who <account name>
-//    Displays complete information of an account.
-//
-//-------------------------------------------------------------------------
-
-int login_fd;
-int login_ip;
-int bytes_to_read = 0; // flag to know if we waiting bytes from login-server
-char command[1024];
-char parameters[1024];
-int list_first, list_last, list_type, list_count; // parameter to display a list of accounts
-int already_exit_function = 0; // sometimes, the exit function is called twice... so, don't log twice the message
-
-//------------------------------
-// Writing function of logs file
-//------------------------------
-int ladmin_log(char *fmt, ...)
-{
-	FILE *logfp;
-	va_list ap;
-	time_t t;
-	char tmpstr[2048];
-
-	va_start(ap, fmt);
-
-	logfp = fopen(ladmin_log_filename, "a");
-	if (logfp) {
-		if (fmt[0] == '\0') // jump a line if no message
-			fprintf(logfp, "\n");
-		else {
-			t = time(NULL);
-			strftime(tmpstr, 24, date_format, localtime(&t));
-			sprintf(tmpstr + strlen(tmpstr), ": %s", fmt);
-			vfprintf(logfp, tmpstr, ap);
-		}
-		fclose(logfp);
-	}
-
-	va_end(ap);
-	return 0;
-}
-
-//---------------------------------------------
-// Function to return ordinal text of a number.
-//---------------------------------------------
-char* makeordinal(int number)
-{
-	if ((number % 10) < 4 && (number % 10) != 0 && (number < 10 || number > 20)) {
-		if ((number % 10) == 1)
-			return "st";
-		else if ((number % 10) == 2)
-			return "nd";
-		else
-			return "rd";
-	} else {
-		return "th";
-	}
-}
-
-//-----------------------------------------------------------------------------------------
-// Function to test of the validity of an account name (return 0 if incorrect, and 1 if ok)
-//-----------------------------------------------------------------------------------------
-int verify_accountname(char* account_name)
-{
-	int i;
-
-	for(i = 0; account_name[i]; i++) {
-		if (account_name[i] < 32) {
-			ShowMessage("Illegal character found in the account name (%d%s character).\n", i+1, makeordinal(i+1));
-			ladmin_log("Illegal character found in the account name (%d%s character).\n", i+1, makeordinal(i+1));
-			return 0;
-		}
-	}
-
-	if (strlen(account_name) < 4) {
-		ShowMessage("Account name is too short. Please input an account name of 4-23 bytes.\n");
-		ladmin_log("Account name is too short. Please input an account name of 4-23 bytes.\n");
-		return 0;
-	}
-
-	if (strlen(account_name) > 23) {
-		ShowMessage("Account name is too long. Please input an account name of 4-23 bytes.\n");
-		ladmin_log("Account name is too long. Please input an account name of 4-23 bytes.\n");
-		return 0;
-	}
-
-	return 1;
-}
-
-//----------------------------------
-// Sub-function: Input of a password
-//----------------------------------
-int typepasswd(char * password)
-{
-	char password1[1023], password2[1023];
-	int letter;
-	int i;
-
-	ladmin_log("No password was given. Request to obtain a password.\n");
-
-	memset(password1, '\0', sizeof(password1));
-	memset(password2, '\0', sizeof(password2));
-
-	ShowMessage("\033[1;36m Type the password > \033[0;32;42m");
-
-	i = 0;
-	while ((letter = getchar()) != '\n')
-		password1[i++] = letter;
-
-	ShowMessage("\033[0m\033[1;36m Verify the password > \033[0;32;42m");
-
-	i = 0;
-	while ((letter = getchar()) != '\n')
-		password2[i++] = letter;
-
-	ShowMessage("\033[0m");
-	fflush(stdout);
-	fflush(stdin);
-
-	if (strcmp(password1, password2) != 0) {
-		ShowMessage("Password verification failed. Please input same password.\n");
-		ladmin_log("Password verification failed. Please input same password.\n");
-		ladmin_log("  First password: %s, second password: %s.\n", password1, password2);
-		return 0;
-	}
-	ladmin_log("Typed password: %s.\n", password1);
-	strcpy(password, password1);
-	return 1;
-}
-
-//------------------------------------------------------------------------------------
-// Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
-//------------------------------------------------------------------------------------
-int verify_password(char * password)
-{
-	int i;
-
-	for(i = 0; password[i]; i++) {
-		if (password[i] < 32) {
-			ShowMessage("Illegal character found in the password (%d%s character).\n", i+1, makeordinal(i+1));
-			ladmin_log("Illegal character found in the password (%d%s character).\n", i+1, makeordinal(i+1));
-			return 0;
-		}
-	}
-
-	if (strlen(password) < 4) {
-		ShowMessage("Account name is too short. Please input an account name of 4-23 bytes.\n");
-		ladmin_log("Account name is too short. Please input an account name of 4-23 bytes.\n");
-		return 0;
-	}
-
-	if (strlen(password) > 23) {
-		ShowMessage("Password is too long. Please input a password of 4-23 bytes.\n");
-		ladmin_log("Password is too long. Please input a password of 4-23 bytes.\n");
-		return 0;
-	}
-
-	return 1;
-}
-
-//------------------------------------------------------------------
-// Sub-function: Check the name of a command (return complete name)
-//-----------------------------------------------------------------
-int check_command(char * command)
-{
-// help
-	if (strncmp(command, "help", 1) == 0 && strncmp(command, "help", strlen(command)) == 0)
-		strcpy(command, "help");
-// general commands
-	else if (strncmp(command, "add", 2) == 0 && strncmp(command, "add", strlen(command)) == 0) // not 1 letter command: 'aide' or 'add'?
-		strcpy(command, "add");
-	else if ((strncmp(command, "ban", 3) == 0 && strncmp(command, "ban", strlen(command)) == 0) ||
-	         (strncmp(command, "banish", 4) == 0 && strncmp(command, "banish", strlen(command)) == 0))
-		strcpy(command, "ban");
-	else if ((strncmp(command, "banadd", 4) == 0 && strncmp(command, "banadd", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
-	         strcmp(command,   "ba") == 0)
-		strcpy(command, "banadd");
-	else if ((strncmp(command, "banset", 4) == 0 && strncmp(command, "banset", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
-	         strcmp(command,   "bs") == 0)
-		strcpy(command, "banset");
-	else if (strncmp(command, "block", 2) == 0 && strncmp(command, "block", strlen(command)) == 0)
-		strcpy(command, "block");
-	else if (strncmp(command, "check", 2) == 0 && strncmp(command, "check", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
-		strcpy(command, "check");
-	else if (strncmp(command, "create", 2) == 0 && strncmp(command, "create", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
-		strcpy(command, "create");
-	else if (strncmp(command, "delete", 1) == 0 && strncmp(command, "delete", strlen(command)) == 0)
-		strcpy(command, "delete");
-	else if ((strncmp(command, "email", 2) == 0 && strncmp(command, "email", strlen(command)) == 0) || // not 1 letter command: 'email', 'end' or 'exit'?
-	         (strncmp(command, "e-mail", 2) == 0 && strncmp(command, "e-mail", strlen(command)) == 0))
-		strcpy(command, "email");
-	else if (strncmp(command, "getcount", 2) == 0 && strncmp(command, "getcount", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
-		strcpy(command, "getcount");
-//	else if (strncmp(command, "gm", 2) == 0 && strncmp(command, "gm", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
-//		strcpy(command, "gm");
-//	else if (strncmp(command, "id", 2) == 0 && strncmp(command, "id", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
-//		strcpy(command, "id");
-	else if (strncmp(command, "info", 2) == 0 && strncmp(command, "info", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
-		strcpy(command, "info");
-//	else if (strncmp(command, "kami", 4) == 0 && strncmp(command, "kami", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-//		strcpy(command, "kami");
-//	else if (strncmp(command, "kamib", 5) == 0 && strncmp(command, "kamib", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-//		strcpy(command, "kamib");
-	else if ((strncmp(command, "list", 2) == 0 && strncmp(command, "list", strlen(command)) == 0) || // 'list' is default list command // not 1 letter command: 'list'?
-	         strcmp(command,   "ls") == 0)
-		strcpy(command, "list");
-	else if ((strncmp(command, "listban", 5) == 0 && strncmp(command, "listban", strlen(command)) == 0) ||
-	         (strncmp(command, "lsban", 3) == 0 && strncmp(command, "lsban", strlen(command)) == 0) ||
-	         strcmp(command, "lb") == 0)
-		strcpy(command, "listban");
-	else if ((strncmp(command, "listgm", 5) == 0 && strncmp(command, "listgm", strlen(command)) == 0) ||
-	         (strncmp(command, "lsgm", 3) == 0 && strncmp(command, "lsgm", strlen(command)) == 0) ||
-	         strcmp(command,  "lg") == 0)
-		strcpy(command, "listgm");
-	else if ((strncmp(command, "listok", 5) == 0 && strncmp(command, "listok", strlen(command)) == 0) ||
-	         (strncmp(command, "lsok", 3) == 0 && strncmp(command, "lsok", strlen(command)) == 0) ||
-	         strcmp(command, "lo") == 0)
-		strcpy(command, "listok");
-	else if (strncmp(command, "memo", 1) == 0 && strncmp(command, "memo", strlen(command)) == 0)
-		strcpy(command, "memo");
-	else if (strncmp(command, "name", 1) == 0 && strncmp(command, "name", strlen(command)) == 0)
-		strcpy(command, "name");
-	else if ((strncmp(command, "password", 1) == 0 && strncmp(command, "password", strlen(command)) == 0) ||
-	         strcmp(command, "passwd") == 0)
-		strcpy(command, "password");
-	else if (strncmp(command, "reloadgm", 1) == 0 && strncmp(command, "reloadgm", strlen(command)) == 0)
-		strcpy(command, "reloadgm");
-	else if (strncmp(command, "search", 3) == 0 && strncmp(command, "search", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-		strcpy(command, "search"); // not 2 letters command: 'search' or 'sex'?
-//	else if (strncmp(command, "sex", 3) == 0 && strncmp(command, "sex", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-//		strcpy(command, "sex"); // not 2 letters command: 'search' or 'sex'?
-	else if (strncmp(command, "state", 2) == 0 && strncmp(command, "state", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-		strcpy(command, "state");
-	else if ((strncmp(command, "timeadd", 5) == 0 && strncmp(command, "timeadd", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
-	         strcmp(command,  "ta") == 0)
-		strcpy(command, "timeadd");
-	else if ((strncmp(command, "timeset", 5) == 0 && strncmp(command, "timeset", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
-	         strcmp(command,  "ts") == 0)
-		strcpy(command, "timeset");
-	else if ((strncmp(command, "unban", 5) == 0 && strncmp(command, "unban", strlen(command)) == 0) ||
-	         (strncmp(command, "unbanish", 4) == 0 && strncmp(command, "unbanish", strlen(command)) == 0))
-		strcpy(command, "unban");
-	else if (strncmp(command, "unblock", 4) == 0 && strncmp(command, "unblock", strlen(command)) == 0)
-		strcpy(command, "unblock");
-	else if (strncmp(command, "version", 1) == 0 && strncmp(command, "version", strlen(command)) == 0)
-		strcpy(command, "version");
-	else if (strncmp(command, "who", 1) == 0 && strncmp(command, "who", strlen(command)) == 0)
-		strcpy(command, "who");
-// quit
-	else if (strncmp(command, "quit", 1) == 0 && strncmp(command, "quit", strlen(command)) == 0)
-		strcpy(command, "quit");
-	else if (strncmp(command, "exit", 2) == 0 && strncmp(command, "exit", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
-		strcpy(command, "exit");
-	else if (strncmp(command, "end", 2) == 0 && strncmp(command, "end", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
-		strcpy(command, "end");
-
-	return 0;
-}
-
-//-----------------------------------------
-// Sub-function: Display commands of ladmin
-//-----------------------------------------
-void display_help(char* param)
-{
-	char command[1023];
-	int i;
-
-	memset(command, '\0', sizeof(command));
-
-	if (sscanf(param, "%s ", command) < 1 || strlen(command) == 0)
-		strcpy(command, ""); // any value that is not a command
-
-	if (command[0] == '?')
-		strcpy(command, "help");
-
-	// lowercase for command
-	for (i = 0; command[i]; i++)
-		command[i] = TOLOWER(command[i]);
-
-	// Analyse of the command
-	check_command(command); // give complete name to the command
-
-	ladmin_log("Displaying of the commands or a command.\n");
-
-	if (strcmp(command, "help") == 0 ) {
-		ShowMessage("aide/help/?\n");
-		ShowMessage("  Display the description of the commands\n");
-		ShowMessage("aide/help/? [command]\n");
-		ShowMessage("  Display the description of the specified command\n");
-// general commands
-	} else if (strcmp(command, "add") == 0) {
-		ShowMessage("add <account_name> <sex> <password>\n");
-		ShowMessage("  Create an account with the default email (a@a.com).\n");
-		ShowMessage("  Concerning the sex, only the first letter is used (F or M).\n");
-		ShowMessage("  The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n");
-		ShowMessage("  When the password is omitted,\n");
-		ShowMessage("  the input is done without displaying of the pressed keys.\n");
-		ShowMessage("  <example> add testname Male testpass\n");
-	} else if (strcmp(command, "ban") == 0) {
-		ShowMessage("ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-		ShowMessage("  Changes the final date of a banishment of an account.\n");
-		ShowMessage("  Like banset, but <account name> is at end.\n");
-	} else if (strcmp(command, "banadd") == 0) {
-		ShowMessage("banadd <account_name> <modifier>\n");
-		ShowMessage("  Adds or substracts time from the final date of a banishment of an account.\n");
-		ShowMessage("  Modifier is done as follows:\n");
-		ShowMessage("    Adjustment value (-1, 1, +1, etc...)\n");
-		ShowMessage("    Modified element:\n");
-		ShowMessage("      a or y: year\n");
-		ShowMessage("      m:  month\n");
-		ShowMessage("      j or d: day\n");
-		ShowMessage("      h:  hour\n");
-		ShowMessage("      mn: minute\n");
-		ShowMessage("      s:  second\n");
-		ShowMessage("  <example> banadd testname +1m-2mn1s-6y\n");
-		ShowMessage("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("            and 6 years at the same time.\n");
-		ShowMessage("NOTE: If you modify the final date of a non-banished account,\n");
-		ShowMessage("      you fix the final date to (actual time +- adjustments)\n");
-	} else if (strcmp(command, "banset") == 0) {
-		ShowMessage("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("  Changes the final date of a banishment of an account.\n");
-		ShowMessage("  Default time [hh:mm:ss]: 23:59:59.\n");
-		ShowMessage("banset <account_name> 0\n");
-		ShowMessage("  Set a non-banished account (0 = unbanished).\n");
-	} else if (strcmp(command, "block") == 0) {
-		ShowMessage("block <account name>\n");
-		ShowMessage("  Set state 5 (You have been blocked by the GM Team) to an account.\n");
-		ShowMessage("  This command works like state <account_name> 5.\n");
-	} else if (strcmp(command, "check") == 0) {
-		ShowMessage("check <account_name> <password>\n");
-		ShowMessage("  Check the validity of a password for an account.\n");
-		ShowMessage("  NOTE: Server will never send back a password.\n");
-		ShowMessage("        It's the only method you have to know if a password is correct.\n");
-		ShowMessage("        The other method is to have a ('physical') access to the accounts file.\n");
-	} else if (strcmp(command, "create") == 0) {
-		ShowMessage("create <account_name> <sex> <email> <password>\n");
-		ShowMessage("  Like the 'add' command, but with e-mail moreover.\n");
-		ShowMessage("  <example> create testname Male my@mail.com testpass\n");
-	} else if (strcmp(command, "delete") == 0) {
-		ShowMessage("del <account name>\n");
-		ShowMessage("  Remove an account.\n");
-		ShowMessage("  This order requires confirmation. After confirmation, the account is deleted.\n");
-	} else if (strcmp(command, "email") == 0) {
-		ShowMessage("email <account_name> <email>\n");
-		ShowMessage("  Modify the e-mail of an account.\n");
-	} else if (strcmp(command, "getcount") == 0) {
-		ShowMessage("getcount\n");
-		ShowMessage("  Give the number of players online on all char-servers.\n");
-	} else if (strcmp(command, "gm") == 0) {
-		ShowMessage("gm <account_name> [GM_level]\n");
-		ShowMessage("  Modify the GM level of an account.\n");
-		ShowMessage("  Default value remove GM level (GM level = 0).\n");
-		ShowMessage("  <example> gm testname 80\n");
-	} else if (strcmp(command, "id") == 0) {
-		ShowMessage("id <account name>\n");
-		ShowMessage("  Give the id of an account.\n");
-	} else if (strcmp(command, "info") == 0) {
-		ShowMessage("info <account_id>\n");
-		ShowMessage("  Display complete information of an account.\n");
-	} else if (strcmp(command, "kami") == 0) {
-		ShowMessage("kami <message>\n");
-		ShowMessage("  Sends a broadcast message on all map-server (in yellow).\n");
-	} else if (strcmp(command, "kamib") == 0) {
-		ShowMessage("kamib <message>\n");
-		ShowMessage("  Sends a broadcast message on all map-server (in blue).\n");
-	} else if (strcmp(command, "list") == 0) {
-		ShowMessage("list/ls [start_id [end_id]]\n");
-		ShowMessage("  Display a list of accounts.\n");
-		ShowMessage("  'start_id', 'end_id': indicate end and start identifiers.\n");
-		ShowMessage("  Research by name is not possible with this command.\n");
-		ShowMessage("  <example> list 10 9999999\n");
-	} else if (strcmp(command, "listban") == 0) {
-		ShowMessage("listBan/lsBan [start_id [end_id]]\n");
-		ShowMessage("  Like list/ls, but only for accounts with state or banished.\n");
-	} else if (strcmp(command, "listgm") == 0) {
-		ShowMessage("listGM/lsGM [start_id [end_id]]\n");
-		ShowMessage("  Like list/ls, but only for GM accounts.\n");
-	} else if (strcmp(command, "listok") == 0) {
-		ShowMessage("listOK/lsOK [start_id [end_id]]\n");
-		ShowMessage("  Like list/ls, but only for accounts without state and not banished.\n");
-	} else if (strcmp(command, "memo") == 0) {
-		ShowMessage("memo <account_name> <memo>\n");
-		ShowMessage("  Modify the memo of an account.\n");
-		ShowMessage("  'memo': it can have until 253 characters (with spaces or not).\n");
-	} else if (strcmp(command, "name") == 0) {
-		ShowMessage("name <account_id>\n");
-		ShowMessage("  Give the name of an account.\n");
-	} else if (strcmp(command, "password") == 0) {
-		ShowMessage("passwd <account_name> <new_password>\n");
-		ShowMessage("  Change the password of an account.\n");
-		ShowMessage("  When new password is omitted,\n");
-		ShowMessage("  the input is done without displaying of the pressed keys.\n");
-	} else if (strcmp(command, "reloadgm") == 0) {
-		ShowMessage("reloadGM\n");
-		ShowMessage("  Reload GM configuration file\n");
-	} else if (strcmp(command, "search") == 0) {
-		ShowMessage("search <expression>\n");
-		ShowMessage("  Seek accounts.\n");
-		ShowMessage("  Displays the accounts whose names correspond.\n");
-//			ShowMessage("search -r/-e/--expr/--regex <expression>\n");
-//			ShowMessage("  Seek accounts by regular expression.\n");
-//			ShowMessage("  Displays the accounts whose names correspond.\n");
-	} else if (strcmp(command, "sex") == 0) {
-		ShowMessage("sex <account_name> <sex>\n");
-		ShowMessage("  Modify the sex of an account.\n");
-		ShowMessage("  <example> sex testname Male\n");
-	} else if (strcmp(command, "state") == 0) {
-		ShowMessage("state <account_name> <new_state> <error_message_#7>\n");
-		ShowMessage("  Change the state of an account.\n");
-		ShowMessage("  'new_state': state is the state of the packet 0x006a + 1.\n");
-		ShowMessage("               The possibilities are:\n");
-		ShowMessage("               0 = Account ok\n");
-		ShowMessage("               1 = Unregistered ID\n");
-		ShowMessage("               2 = Incorrect Password\n");
-		ShowMessage("               3 = This ID is expired\n");
-		ShowMessage("               4 = Rejected from Server\n");
-		ShowMessage("               5 = You have been blocked by the GM Team\n");
-		ShowMessage("               6 = Your Game's EXE file is not the latest version\n");
-		ShowMessage("               7 = You are Prohibited to log in until...\n");
-		ShowMessage("               8 = Server is jammed due to over populated\n");
-		ShowMessage("               9 = No MSG\n");
-		ShowMessage("               100 = This ID has been totally erased\n");
-		ShowMessage("               all other values are 'No MSG', then use state 9 please.\n");
-		ShowMessage("  'error_message_#7': message of the code error 6\n");
-		ShowMessage("                      = Your are Prohibited to log in until... (packet 0x006a)\n");
-	} else if (strcmp(command, "timeadd") == 0) {
-		ShowMessage("timeadd <account_name> <modifier>\n");
-		ShowMessage("  Adds or substracts time from the validity limit of an account.\n");
-		ShowMessage("  Modifier is done as follows:\n");
-		ShowMessage("    Adjustment value (-1, 1, +1, etc...)\n");
-		ShowMessage("    Modified element:\n");
-		ShowMessage("      a or y: year\n");
-		ShowMessage("      m:  month\n");
-		ShowMessage("      j or d: day\n");
-		ShowMessage("      h:  hour\n");
-		ShowMessage("      mn: minute\n");
-		ShowMessage("      s:  second\n");
-		ShowMessage("  <example> timeadd testname +1m-2mn1s-6y\n");
-		ShowMessage("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("            and 6 years at the same time.\n");
-		ShowMessage("NOTE: You can not modify a unlimited validity limit.\n");
-		ShowMessage("      If you want modify it, you want probably create a limited validity limit.\n");
-		ShowMessage("      So, at first, you must set the validity limit to a date/time.\n");
-	} else if (strcmp(command, "timeadd") == 0) {
-		ShowMessage("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("  Changes the validity limit of an account.\n");
-		ShowMessage("  Default time [hh:mm:ss]: 23:59:59.\n");
-		ShowMessage("timeset <account_name> 0\n");
-		ShowMessage("  Gives an unlimited validity limit (0 = unlimited).\n");
-	} else if (strcmp(command, "unban") == 0) {
-		ShowMessage("unban/unbanish <account name>\n");
-		ShowMessage("  Remove the banishment of an account.\n");
-		ShowMessage("  This command works like banset <account_name> 0.\n");
-	} else if (strcmp(command, "unblock") == 0) {
-		ShowMessage("unblock <account name>\n");
-		ShowMessage("  Set state 0 (Account ok) to an account.\n");
-		ShowMessage("  This command works like state <account_name> 0.\n");
-	} else if (strcmp(command, "version") == 0) {
-		ShowMessage("version\n");
-		ShowMessage("  Display the version of the login-server.\n");
-	} else if (strcmp(command, "who") == 0) {
-		ShowMessage("who <account name>\n");
-		ShowMessage("  Displays complete information of an account.\n");
-// quit
-	} else if (strcmp(command, "quit") == 0 ||
-	           strcmp(command, "exit") == 0 ||
-	           strcmp(command, "end") == 0) {
-		ShowMessage("quit/end/exit\n");
-		ShowMessage("  End of the program of administration.\n");
-// unknown command
-	} else {
-		if (strlen(command) > 0)
-			ShowMessage("Unknown command [%s] for help. Displaying of all commands.\n", command);
-		ShowMessage(" aide/help/?                          -- Display this help\n");
-		ShowMessage(" aide/help/? [command]                -- Display the help of the command\n");
-		ShowMessage(" add <account_name> <sex> <password>  -- Create an account with default email\n");
-		ShowMessage(" ban/banish yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n");
-		ShowMessage(" banadd/ba <account_name> <modifier>  -- Add or substract time from the final\n");
-		ShowMessage("   example: ba apple +1m-2mn1s-2y        date of a banishment of an account\n");
-		ShowMessage(" banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n");
-		ShowMessage(" banset/bs <account_name> 0           -- Un-banish an account\n");
-		ShowMessage(" block <account name>     -- Set state 5 (blocked by the GM Team) to an account\n");
-		ShowMessage(" check <account_name> <password>      -- Check the validity of a password\n");
-		ShowMessage(" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n");
-		ShowMessage(" del <account name>                   -- Remove an account\n");
-		ShowMessage(" email <account_name> <email>         -- Modify an email of an account\n");
-		ShowMessage(" getcount                             -- Give the number of players online\n");
-		ShowMessage(" gm <account_name> [GM_level]         -- Modify the GM level of an account\n");
-		ShowMessage(" id <account name>                    -- Give the id of an account\n");
-		ShowMessage(" info <account_id>                    -- Display all information of an account\n");
-		ShowMessage(" kami <message>                       -- Sends a broadcast message (in yellow)\n");
-		ShowMessage(" kamib <message>                      -- Sends a broadcast message (in blue)\n");
-		ShowMessage(" list/ls [First_id [Last_id]]         -- Display a list of accounts\n");
-		ShowMessage(" listBan/lsBan [First_id [Last_id] ]  -- Display a list of accounts\n");
-		ShowMessage("                                         with state or banished\n");
-		ShowMessage(" listGM/lsGM [First_id [Last_id]]     -- Display a list of GM accounts\n");
-		ShowMessage(" listOK/lsOK [First_id [Last_id] ]    -- Display a list of accounts\n");
-		ShowMessage("                                         without state and not banished\n");
-		ShowMessage(" memo <account_name> <memo>           -- Modify the memo of an account\n");
-		ShowMessage(" name <account_id>                    -- Give the name of an account\n");
-		ShowMessage(" passwd <account_name> <new_password> -- Change the password of an account\n");
-		ShowMessage(" quit/end/exit                        -- End of the program of administation\n");
-		ShowMessage(" reloadGM                             -- Reload GM configuration file\n");
-		ShowMessage(" search <expression>                  -- Seek accounts\n");
-//			ShowMessage(" search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression\n");
-		ShowMessage(" sex <nomcompte> <sexe>               -- Modify the sex of an account\n");
-		ShowMessage(" state <account_name> <new_state> <error_message_#7> -- Change the state\n");
-		ShowMessage(" timeadd/ta <account_name> <modifier> -- Add or substract time from the\n");
-		ShowMessage("   example: ta apple +1m-2mn1s-2y        validity limit of an account\n");
-		ShowMessage(" timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n");
-		ShowMessage(" timeset/ts <account_name> 0          -- Give a unlimited validity limit\n");
-		ShowMessage(" unban/unbanish <account name>        -- Remove the banishment of an account\n");
-		ShowMessage(" unblock <account name>               -- Set state 0 (Account ok) to an account\n");
-		ShowMessage(" version                              -- Gives the version of the login-server\n");
-		ShowMessage(" who <account name>                   -- Display all information of an account\n");
-		ShowMessage(" who <account name>                   -- Display all information of an account\n");
-		ShowMessage(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n");
-	}
-}
-
-//-----------------------------
-// Sub-function: add an account
-//-----------------------------
-int addaccount(char* param, int emailflag)
-{
-	char name[1023], sex[1023], email[1023], password[1023];
-//	int i;
-	WFIFOHEAD(login_fd,91);
-
-	memset(name, '\0', sizeof(name));
-	memset(sex, '\0', sizeof(sex));
-	memset(email, '\0', sizeof(email));
-	memset(password, '\0', sizeof(password));
-
-	if (emailflag == 0) { // add command
-		if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, sex, password) < 2 && // password can be void
-		    sscanf(param, "'%[^']' %s %[^\r\n]", name, sex, password) < 2 && // password can be void
-		    sscanf(param, "%s %s %[^\r\n]", name, sex, password) < 2) { // password can be void
-			ShowMessage("Please input an account name, a sex and a password.\n");
-			ShowMessage("<example> add testname Male testpass\n");
-			ladmin_log("Incomplete parameters to create an account ('add' command).\n");
-			return 136;
-		}
-		strcpy(email, "a@a.com"); // default email
-	} else { // 1: create command
-		if (sscanf(param, "\"%[^\"]\" %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
-		    sscanf(param, "'%[^']' %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
-		    sscanf(param, "%s %s %s %[^\r\n]", name, sex, email, password) < 3) { // password can be void
-			ShowMessage("Please input an account name, a sex and a password.\n");
-			ShowMessage("<example> create testname Male my@mail.com testpass\n");
-			ladmin_log("Incomplete parameters to create an account ('create' command).\n");
-			return 136;
-		}
-	}
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	sex[0] = TOUPPER(sex[0]);
-	if (strchr("MF", sex[0]) == NULL) {
-		ShowMessage("Illegal gender [%s]. Please input M or F.\n", sex);
-		ladmin_log("Illegal gender [%s]. Please input M or F.\n", sex);
-		return 103;
-	}
-
-	if (strlen(email) < 3) {
-		ShowMessage("Email is too short [%s]. Please input a valid e-mail.\n", email);
-		ladmin_log("Email is too short [%s]. Please input a valid e-mail.\n", email);
-		return 109;
-	}
-	if (strlen(email) > 39) {
-		ShowMessage("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
-		ladmin_log("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
-		return 109;
-	}
-	if (e_mail_check(email) == 0) {
-		ShowMessage("Invalid email [%s]. Please input a valid e-mail.\n", email);
-		ladmin_log("Invalid email [%s]. Please input a valid e-mail.\n", email);
-		return 109;
-	}
-
-	if (strlen(password) == 0) {
-		if (typepasswd(password) == 0)
-			return 108;
-	}
-	if (verify_password(password) == 0)
-		return 104;
-
-	ladmin_log("Request to login-server to create an account.\n");
-
-	WFIFOW(login_fd,0) = 0x7930;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	memcpy(WFIFOP(login_fd,26), password, 24);
-	WFIFOB(login_fd,50) = sex[0];
-	memcpy(WFIFOP(login_fd,51), email, 40);
-	WFIFOSET(login_fd,91);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//---------------------------------------------------------------------------------
-// Sub-function: Add/substract time to the final date of a banishment of an account
-//---------------------------------------------------------------------------------
-int banaddaccount(char* param)
-{
-	char name[1023], modif[1023];
-	int year, month, day, hour, minute, second;
-	char * p_modif;
-	int value, i;
-	WFIFOHEAD(login_fd,38);
-
-	memset(name, '\0', sizeof(name));
-	memset(modif, '\0', sizeof(modif));
-	year = month = day = hour = minute = second = 0;
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
-	    sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
-	    sscanf(param, "%s %[^\r\n]", name, modif) < 2) {
-		ShowMessage("Please input an account name and a modifier.\n");
-		ShowMessage("  <example>: banadd testname +1m-2mn1s-6y\n");
-		ShowMessage("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("             and 6 years at the same time.\n");
-		ladmin_log("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n");
-		return 136;
-	}
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	// lowercase for modif
-	for (i = 0; modif[i]; i++)
-		modif[i] = TOLOWER(modif[i]);
-	p_modif = modif;
-	while (strlen(p_modif) > 0) {
-		value = atoi(p_modif);
-		if (value == 0) {
-			p_modif++;
-		} else {
-			if (p_modif[0] == '-' || p_modif[0] == '+')
-				p_modif++;
-			while (strlen(p_modif) > 0 && p_modif[0] >= '0' && p_modif[0] <= '9') {
-				p_modif++;
-			}
-			if (p_modif[0] == 's') {
-				second = value;
-				p_modif++;
-			} else if (p_modif[0] == 'm' && p_modif[1] == 'n') {
-				minute = value;
-				p_modif += 2;
-			} else if (p_modif[0] == 'h') {
-				hour = value;
-				p_modif++;
-			} else if (p_modif[0] == 'd' || p_modif[0] == 'j') {
-				day = value;
-				p_modif += 2;
-			} else if (p_modif[0] == 'm') {
-				month = value;
-				p_modif++;
-			} else if (p_modif[0] == 'y' || p_modif[0] == 'a') {
-				year = value;
-				p_modif++;
-			} else {
-				p_modif++;
-			}
-		}
-	}
-
-	ShowMessage(" year:   %d\n", year);
-	ShowMessage(" month:  %d\n", month);
-	ShowMessage(" day:    %d\n", day);
-	ShowMessage(" hour:   %d\n", hour);
-	ShowMessage(" minute: %d\n", minute);
-	ShowMessage(" second: %d\n", second);
-
-	if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) {
-		ShowMessage("Please give an adjustment with this command:\n");
-		ShowMessage("  Adjustment value (-1, 1, +1, etc...)\n");
-		ShowMessage("  Modified element:\n");
-		ShowMessage("    a or y: year\n");
-		ShowMessage("    m: month\n");
-		ShowMessage("    j or d: day\n");
-		ShowMessage("    h: hour\n");
-		ShowMessage("    mn: minute\n");
-		ShowMessage("    s: second\n");
-		ShowMessage("  <example> banadd testname +1m-2mn1s-6y\n");
-		ShowMessage("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("            and 6 years at the same time.\n");
-		ladmin_log("No adjustment isn't an adjustment ('banadd' command).\n");
-		return 137;
-	}
-	if (year > 127 || year < -127) {
-		ShowMessage("Please give a correct adjustment for the years (from -127 to 127).\n");
-		ladmin_log("Abnormal adjustment for the year ('banadd' command).\n");
-		return 137;
-	}
-	if (month > 255 || month < -255) {
-		ShowMessage("Please give a correct adjustment for the months (from -255 to 255).\n");
-		ladmin_log("Abnormal adjustment for the month ('banadd' command).\n");
-		return 137;
-	}
-	if (day > 32767 || day < -32767) {
-		ShowMessage("Please give a correct adjustment for the days (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the days ('banadd' command).\n");
-		return 137;
-	}
-	if (hour > 32767 || hour < -32767) {
-		ShowMessage("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the hours ('banadd' command).\n");
-		return 137;
-	}
-	if (minute > 32767 || minute < -32767) {
-		ShowMessage("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the minutes ('banadd' command).\n");
-		return 137;
-	}
-	if (second > 32767 || second < -32767) {
-		ShowMessage("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the seconds ('banadd' command).\n");
-		return 137;
-	}
-
-	ladmin_log("Request to login-server to modify a ban date/time.\n");
-
-	WFIFOW(login_fd,0) = 0x794c;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOW(login_fd,26) = (short)year;
-	WFIFOW(login_fd,28) = (short)month;
-	WFIFOW(login_fd,30) = (short)day;
-	WFIFOW(login_fd,32) = (short)hour;
-	WFIFOW(login_fd,34) = (short)minute;
-	WFIFOW(login_fd,36) = (short)second;
-	WFIFOSET(login_fd,38);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-----------------------------------------------------------------------
-// Sub-function of sub-function banaccount, unbanaccount or bansetaccount
-// Set the final date of a banishment of an account
-//-----------------------------------------------------------------------
-int bansetaccountsub(char* name, char* date, char* time)
-{
-	int year, month, day, hour, minute, second;
-	time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-	struct tm *tmtime;
-	WFIFOHEAD(login_fd,30);
-
-	year = month = day = hour = minute = second = 0;
-	unban_time = 0;
-	tmtime = localtime(&unban_time); // initialize
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (atoi(date) != 0 &&
-	    ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
-	      sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
-	      sscanf(date, "%d.%d.%d", &year, &month, &day) < 3) ||
-	     sscanf(time, "%d:%d:%d", &hour, &minute, &second) < 3))
-	{
-		ShowMessage("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
-		ShowMessage("You can imput 0 instead of if you use 'banset' command.\n");
-		ladmin_log("Invalid format for the date/time ('banset' or 'ban' command).\n");
-		return 102;
-	}
-
-	if (atoi(date) == 0) {
-		unban_time = 0;
-	} else {
-		if (year < 70) {
-			year = year + 100;
-		}
-		if (year >= 1900) {
-			year = year - 1900;
-		}
-		if (month < 1 || month > 12) {
-			ShowMessage("Please give a correct value for the month (from 1 to 12).\n");
-			ladmin_log("Invalid month for the date ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		month = month - 1;
-		if (day < 1 || day > 31) {
-			ShowMessage("Please give a correct value for the day (from 1 to 31).\n");
-			ladmin_log("Invalid day for the date ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) ||
-		    (month == 1 && day > 29)) {
-			ShowMessage("Please give a correct value for a day of this month (%d).\n", month);
-			ladmin_log("Invalid day for this month ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		if (hour < 0 || hour > 23) {
-			ShowMessage("Please give a correct value for the hour (from 0 to 23).\n");
-			ladmin_log("Invalid hour for the time ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		if (minute < 0 || minute > 59) {
-			ShowMessage("Please give a correct value for the minutes (from 0 to 59).\n");
-			ladmin_log("Invalid minute for the time ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		if (second < 0 || second > 59) {
-			ShowMessage("Please give a correct value for the seconds (from 0 to 59).\n");
-			ladmin_log("Invalid second for the time ('banset' or 'ban' command).\n");
-			return 102;
-		}
-		tmtime->tm_year = year;
-		tmtime->tm_mon = month;
-		tmtime->tm_mday = day;
-		tmtime->tm_hour = hour;
-		tmtime->tm_min = minute;
-		tmtime->tm_sec = second;
-		tmtime->tm_isdst = -1; // -1: no winter/summer time modification
-		unban_time = mktime(tmtime);
-		if (unban_time == -1) {
-			ShowMessage("Invalid date.\n");
-			ShowMessage("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
-			ShowMessage("You can imput 0 instead of if you use 'banset' command.\n");
-			ladmin_log("Invalid date. ('banset' or 'ban' command).\n");
-			return 102;
-		}
-	}
-
-	ladmin_log("Request to login-server to set a ban.\n");
-
-	WFIFOW(login_fd,0) = 0x794a;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOL(login_fd,26) = (int)unban_time;
-	WFIFOSET(login_fd,30);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//---------------------------------------------------------------------
-// Sub-function: Set the final date of a banishment of an account (ban)
-//---------------------------------------------------------------------
-int banaccount(char* param)
-{
-	char name[1023], date[1023], time[1023];
-
-	memset(name, '\0', sizeof(name));
-	memset(date, '\0', sizeof(date));
-	memset(time, '\0', sizeof(time));
-
-	if (sscanf(param, "%s %s \"%[^\"]\"", date, time, name) < 3 &&
-	    sscanf(param, "%s %s '%[^']'", date, time, name) < 3 &&
-	    sscanf(param, "%s %s %[^\r\n]", date, time, name) < 3) {
-		ShowMessage("Please input an account name, a date and a hour.\n");
-		ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("           banset <account_name> 0   (0 = un-banished)\n");
-		ShowMessage("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-		ShowMessage("           unban/unbanish <account name>\n");
-		ShowMessage("           Default time [hh:mm:ss]: 23:59:59.\n");
-		ladmin_log("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
-		return 136;
-	}
-
-	return bansetaccountsub(name, date, time);
-}
-
-//------------------------------------------------------------------------
-// Sub-function: Set the final date of a banishment of an account (banset)
-//------------------------------------------------------------------------
-int bansetaccount(char* param)
-{
-	char name[1023], date[1023], time[1023];
-
-	memset(name, '\0', sizeof(name));
-	memset(date, '\0', sizeof(date));
-	memset(time, '\0', sizeof(time));
-
-	if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
-	    sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
-	    sscanf(param, "%s %s %[^\r\n]", name, date, time) < 2) { // if date = 0, time can be void
-		ShowMessage("Please input an account name, a date and a hour.\n");
-		ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("           banset <account_name> 0   (0 = un-banished)\n");
-		ShowMessage("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-		ShowMessage("           unban/unbanish <account name>\n");
-		ShowMessage("           Default time [hh:mm:ss]: 23:59:59.\n");
-		ladmin_log("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
-		return 136;
-	}
-
-	if (time[0] == '\0')
-		strcpy(time, "23:59:59");
-
-	return bansetaccountsub(name, date, time);
-}
-
-//-------------------------------------------------
-// Sub-function: unbanishment of an account (unban)
-//-------------------------------------------------
-int unbanaccount(char* param)
-{
-	char name[1023];
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("           banset <account_name> 0   (0 = un-banished)\n");
-		ShowMessage("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-		ShowMessage("           unban/unbanish <account name>\n");
-		ShowMessage("           Default time [hh:mm:ss]: 23:59:59.\n");
-		ladmin_log("Incomplete parameters to set a ban ('unban' command).\n");
-		return 136;
-	}
-
-	return bansetaccountsub(name, "0", "");
-}
-
-//---------------------------------------------------------
-// Sub-function: Asking to check the validity of a password
-// (Note: never send back a password with login-server!! security of passwords)
-//---------------------------------------------------------
-int checkaccount(char* param)
-{
-	char name[1023], password[1023];
-	WFIFOHEAD(login_fd,50);
-
-	memset(name, '\0', sizeof(name));
-	memset(password, '\0', sizeof(password));
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 && // password can be void
-	    sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 && // password can be void
-	    sscanf(param, "%s %[^\r\n]", name, password) < 1) { // password can be void
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example> check testname password\n");
-		ladmin_log("Incomplete parameters to check the password of an account ('check' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (strlen(password) == 0) {
-		if (typepasswd(password) == 0)
-			return 134;
-	}
-	if (verify_password(password) == 0)
-		return 131;
-
-	ladmin_log("Request to login-server to check a password.\n");
-
-	WFIFOW(login_fd,0) = 0x793a;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	memcpy(WFIFOP(login_fd,26), password, 24);
-	WFIFOSET(login_fd,50);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//------------------------------------------------
-// Sub-function: Asking for deletion of an account
-//------------------------------------------------
-int delaccount(char* param)
-{
-	char name[1023];
-	char letter;
-	char confirm[1023];
-	int i;
-	WFIFOHEAD(login_fd,26);
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example> del testnametodelete\n");
-		ladmin_log("No name given to delete an account ('delete' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	memset(confirm, '\0', sizeof(confirm));
-	while (confirm[0] != 'n' && confirm[0] != 'y')
-	{
-		ShowMessage("\033[1;36m ** Are you really sure to DELETE account [$userid]? (y/n) > \033[0m");
-		fflush(stdout);
-		memset(confirm, '\0', sizeof(confirm));
-		i = 0;
-		while ((letter = getchar()) != '\n')
-			confirm[i++] = letter;
-	}
-
-	if (confirm[0] == 'n') {
-		ShowMessage("Deletion canceled.\n");
-		ladmin_log("Deletion canceled by user ('delete' command).\n");
-		return 121;
-	}
-
-	ladmin_log("Request to login-server to delete an acount.\n");
-
-	WFIFOW(login_fd,0) = 0x7932;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOSET(login_fd,26);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//----------------------------------------------------------
-// Sub-function: Asking to modification of an account e-mail
-//----------------------------------------------------------
-int changeemail(char* param)
-{
-	char name[1023], email[1023];
-	WFIFOHEAD(login_fd,66);
-
-	memset(name, '\0', sizeof(name));
-	memset(email, '\0', sizeof(email));
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, email) < 2 &&
-	    sscanf(param, "'%[^']' %[^\r\n]", name, email) < 2 &&
-	    sscanf(param, "%s %[^\r\n]", name, email) < 2) {
-		ShowMessage("Please input an account name and an email.\n");
-		ShowMessage("<example> email testname newemail\n");
-		ladmin_log("Incomplete parameters to change the email of an account ('email' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (strlen(email) < 3) {
-		ShowMessage("Email is too short [%s]. Please input a valid e-mail.\n", email);
-		ladmin_log("Email is too short [%s]. Please input a valid e-mail.\n", email);
-		return 109;
-	}
-	if (strlen(email) > 39) {
-		ShowMessage("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
-		ladmin_log("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
-		return 109;
-	}
-	if (e_mail_check(email) == 0) {
-		ShowMessage("Invalid email [%s]. Please input a valid e-mail.\n", email);
-		ladmin_log("Invalid email [%s]. Please input a valid e-mail.\n", email);
-		return 109;
-	}
-
-	ladmin_log("Request to login-server to change an email.\n");
-
-	WFIFOW(login_fd,0) = 0x7940;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	memcpy(WFIFOP(login_fd,26), email, 40);
-	WFIFOSET(login_fd,66);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-----------------------------------------------------
-// Sub-function: Asking of the number of online players
-//-----------------------------------------------------
-int getlogincount(void)
-{
-	WFIFOHEAD(login_fd,2);
-	ladmin_log("Request to login-server to obtain the # of online players.\n");
-
-	WFIFOW(login_fd,0) = 0x7938;
-	WFIFOSET(login_fd,2);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//----------------------------------------------------------
-// Sub-function: Asking to modify the GM level of an account
-//----------------------------------------------------------
-int changegmlevel(char* param)
-{
-	char name[1023];
-	int GM_level;
-	WFIFOHEAD(login_fd,27);
-
-	memset(name, '\0', sizeof(name));
-	GM_level = 0;
-
-	if (sscanf(param, "\"%[^\"]\" %d", name, &GM_level) < 1 &&
-	    sscanf(param, "'%[^']' %d", name, &GM_level) < 1 &&
-	    sscanf(param, "%s %d", name, &GM_level) < 1) {
-		ShowMessage("Please input an account name and a GM level.\n");
-		ShowMessage("<example> gm testname 80\n");
-		ladmin_log("Incomplete parameters to change the GM level of an account ('gm' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (GM_level < 0 || GM_level > 99) {
-		ShowMessage("Illegal GM level [%d]. Please input a value from 0 to 99.\n", GM_level);
-		ladmin_log("Illegal GM level [%d]. The value can be from 0 to 99.\n", GM_level);
-		return 103;
-	}
-
-	ladmin_log("Request to login-server to change a GM level.\n");
-
-	WFIFOW(login_fd,0) = 0x793e;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOB(login_fd,26) = GM_level;
-	WFIFOSET(login_fd,27);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//---------------------------------------------
-// Sub-function: Asking to obtain an account id
-//---------------------------------------------
-int idaccount(char* param)
-{
-	char name[1023];
-	WFIFOHEAD(login_fd,26);
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example> id testname\n");
-		ladmin_log("No name given to search an account id ('id' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	ladmin_log("Request to login-server to know an account id.\n");
-
-	WFIFOW(login_fd,0) = 0x7944;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOSET(login_fd,26);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//----------------------------------------------------------------------------
-// Sub-function: Asking to displaying information about an account (by its id)
-//----------------------------------------------------------------------------
-int infoaccount(int account_id)
-{
-	WFIFOHEAD(login_fd,6);
-	if (account_id < 0) {
-		ShowMessage("Please input a positive value for the id.\n");
-		ladmin_log("Negative value was given to found the account.\n");
-		return 136;
-	}
-
-	ladmin_log("Request to login-server to obtain information about an account (by its id).\n");
-
-	WFIFOW(login_fd,0) = 0x7954;
-	WFIFOL(login_fd,2) = account_id;
-	WFIFOSET(login_fd,6);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//---------------------------------------
-// Sub-function: Send a broadcast message
-//---------------------------------------
-int sendbroadcast(short type, char* message)
-{
-	int len = strlen(message);
-	WFIFOHEAD(login_fd,9+len);
-	if (len == 0) {
-		ShowMessage("Please input a message.\n");
-		if (type == 0) {
-			ShowMessage("<example> kami a message\n");
-		} else {
-			ShowMessage("<example> kamib a message\n");
-		}
-		ladmin_log("The message is void ('kami(b)' command).\n");
-		return 136;
-	}
-	len++; //+'\0'
-	WFIFOW(login_fd,0) = 0x794e;
-	WFIFOW(login_fd,2) = type;
-	WFIFOL(login_fd,4) = len;
-	memcpy(WFIFOP(login_fd,8), message, len);
-	WFIFOSET(login_fd,8+len);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//--------------------------------------------------------
-// Sub-function: Asking to Displaying of the accounts list
-//--------------------------------------------------------
-int listaccount(char* param, int type)
-{
-//int list_first, list_last, list_type; // parameter to display a list of accounts
-	int i;
-	WFIFOHEAD(login_fd,10);
-
-	list_type = type;
-
-	// set default values
-	list_first = 0;
-	list_last = 0;
-
-	if (list_type == 1) { // if listgm
-		// get all accounts = use default
-	} else if (list_type == 2) { // if search
-		for (i = 0; param[i]; i++)
-			param[i] = TOLOWER(param[i]);
-		// get all accounts = use default
-	} else if (list_type == 3) { // if listban
-		// get all accounts = use default
-	} else if (list_type == 4) { // if listok
-		// get all accounts = use default
-	} else { // if list (list_type == 0)
-		switch(sscanf(param, "%d %d", &list_first, &list_last)) {
-		case 0:
-			// get all accounts = use default
-			break;
-		case 1:
-			list_last = 0;
-			// use tests of the following value
-		default:
-			if (list_first < 0)
-				list_first = 0;
-			if (list_last < list_first || list_last < 0)
-				list_last = 0;
-			break;
-		}
-	}
-
-	ladmin_log("Request to login-server to obtain the list of accounts from %d to %d.\n", list_first, list_last);
-
-	WFIFOW(login_fd,0) = 0x7920;
-	WFIFOL(login_fd,2) = list_first;
-	WFIFOL(login_fd,6) = list_last;
-	WFIFOSET(login_fd,10);
-	bytes_to_read = 1;
-
-	//          0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
-	ShowMessage("account_id GM user_name               sex    count state\n");
-	ShowMessage("-------------------------------------------------------------------------------\n");
-	list_count = 0;
-
-	return 0;
-}
-
-//--------------------------------------------
-// Sub-function: Asking to modify a memo field
-//--------------------------------------------
-int changememo(char* param)
-{
-	char name[1023], memo[1023];
-	WFIFOHEAD(login_fd,28+255);
-
-	memset(name, '\0', sizeof(name));
-	memset(memo, '\0', sizeof(memo));
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, memo) < 1 && // memo can be void
-	    sscanf(param, "'%[^']' %[^\r\n]", name, memo) < 1 && // memo can be void
-	    sscanf(param, "%s %[^\r\n]", name, memo) < 1) { // memo can be void
-		ShowMessage("Please input an account name and a memo.\n");
-		ShowMessage("<example> memo testname new memo\n");
-		ladmin_log("Incomplete parameters to change the memo of an account ('email' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (strlen(memo) > 254) {
-		ShowMessage("Memo is too long (%lu characters).\n", (unsigned long)strlen(memo));
-		ShowMessage("Please input a memo of 254 bytes at the maximum.\n");
-		ladmin_log("Email is too long (%d characters). Please input a memo of 254 bytes at the maximum.\n", strlen(memo));
-		return 102;
-	}
-
-	ladmin_log("Request to login-server to change a memo.\n");
-
-	WFIFOW(login_fd,0) = 0x7942;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOW(login_fd,26) = strlen(memo);
-	if (strlen(memo) > 0)
-		memcpy(WFIFOP(login_fd,28), memo, strlen(memo));
-	WFIFOSET(login_fd,28+strlen(memo));
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-----------------------------------------------
-// Sub-function: Asking to obtain an account name
-//-----------------------------------------------
-int nameaccount(int id)
-{
-	WFIFOHEAD(login_fd,6);
-	if (id < 0) {
-		ShowMessage("Please input a positive value for the id.\n");
-		ladmin_log("Negativ id given to search an account name ('name' command).\n");
-		return 136;
-	}
-
-	ladmin_log("Request to login-server to know an account name.\n");
-
-	WFIFOW(login_fd,0) = 0x7946;
-	WFIFOL(login_fd,2) = id;
-	WFIFOSET(login_fd,6);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//------------------------------------------
-// Sub-function: Asking to modify a password
-// (Note: never send back a password with login-server!! security of passwords)
-//------------------------------------------
-int changepasswd(char* param)
-{
-	char name[1023], password[1023];
-	WFIFOHEAD(login_fd,50);
-
-	memset(name, '\0', sizeof(name));
-	memset(password, '\0', sizeof(password));
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&
-	    sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 &&
-	    sscanf(param, "%s %[^\r\n]", name, password) < 1) {
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example> passwd testname newpassword\n");
-		ladmin_log("Incomplete parameters to change the password of an account ('password' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (strlen(password) == 0) {
-		if (typepasswd(password) == 0)
-			return 134;
-	}
-	if (verify_password(password) == 0)
-		return 131;
-
-	ladmin_log("Request to login-server to change a password.\n");
-
-	WFIFOW(login_fd,0) = 0x7934;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	memcpy(WFIFOP(login_fd,26), password, 24);
-	WFIFOSET(login_fd,50);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//----------------------------------------------------------------------
-// Sub-function: Request to login-server to reload GM configuration file
-// this function have no answer
-//----------------------------------------------------------------------
-int reloadGM(void)
-{
-	WFIFOHEAD(login_fd,2);
-	WFIFOW(login_fd,0) = 0x7955;
-	WFIFOSET(login_fd,2);
-	bytes_to_read = 0;
-
-	ladmin_log("Request to reload the GM configuration file sended.\n");
-	ShowMessage("Request to reload the GM configuration file sended.\n");
-	ShowMessage("Check the actual GM accounts (after reloading):\n");
-	listaccount(parameters, 1); // 1: to list only GM
-
-	return 180;
-}
-
-//-----------------------------------------------------
-// Sub-function: Asking to modify the sex of an account
-//-----------------------------------------------------
-int changesex(char* param)
-{
-	char name[1023], sex[1023];
-	WFIFOHEAD(login_fd,27);
-
-	memset(name, '\0', sizeof(name));
-	memset(sex, '\0', sizeof(sex));
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, sex) < 2 &&
-	    sscanf(param, "'%[^']' %[^\r\n]", name, sex) < 2 &&
-	    sscanf(param, "%s %[^\r\n]", name, sex) < 2) {
-		ShowMessage("Please input an account name and a sex.\n");
-		ShowMessage("<example> sex testname Male\n");
-		ladmin_log("Incomplete parameters to change the sex of an account ('sex' command).\n");
-		return 136;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	sex[0] = TOUPPER(sex[0]);
-	if (strchr("MF", sex[0]) == NULL) {
-		ShowMessage("Illegal gender [%s]. Please input M or F.\n", sex);
-		ladmin_log("Illegal gender [%s]. Please input M or F.\n", sex);
-		return 103;
-	}
-
-	ladmin_log("Request to login-server to change a sex.\n");
-
-	WFIFOW(login_fd,0) = 0x793c;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOB(login_fd,26) = sex[0];
-	WFIFOSET(login_fd,27);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-------------------------------------------------------------------------
-// Sub-function of sub-function changestate, blockaccount or unblockaccount
-// Asking to modify the state of an account
-//-------------------------------------------------------------------------
-int changestatesub(char* name, int state, char* error_message7)
-{
-	char error_message[1023]; // need to use, because we can modify error_message7
-	WFIFOHEAD(login_fd,50);
-
-	memset(error_message, '\0', sizeof(error_message));
-	strncpy(error_message, error_message7, sizeof(error_message)-1);
-
-	if ((state < 0 || state > 9) && state != 100) { // Valid values: 0: ok, or value of the 0x006a packet + 1
-		ShowMessage("Please input one of these states:\n");
-		ShowMessage("  0 = Account ok            6 = Your Game's EXE file is not the latest version\n");
-		ShowMessage("  1 = Unregistered ID       7 = You are Prohibited to log in until + message\n");
-		ShowMessage("  2 = Incorrect Password    8 = Server is jammed due to over populated\n");
-		ShowMessage("  3 = This ID is expired    9 = No MSG\n");
-		ShowMessage("  4 = Rejected from Server  100 = This ID has been totally erased\n");
-		ShowMessage("  5 = You have been blocked by the GM Team\n");
-		ShowMessage("<examples> state testname 5\n");
-		ShowMessage("           state testname 7 end of your ban\n");
-		ShowMessage("           block <account name>\n");
-		ShowMessage("           unblock <account name>\n");
-		ladmin_log("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n");
-		return 151;
-	}
-
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (state != 7) {
-		strcpy(error_message, "-");
-	} else {
-		if (strlen(error_message) < 1) {
-			ShowMessage("Error message is too short. Please input a message of 1-19 bytes.\n");
-			ladmin_log("Error message is too short. Please input a message of 1-19 bytes.\n");
-			return 102;
-		}
-		if (strlen(error_message) > 19) {
-			ShowMessage("Error message is too long. Please input a message of 1-19 bytes.\n");
-			ladmin_log("Error message is too long. Please input a message of 1-19 bytes.\n");
-			return 102;
-		}
-	}
-
-	ladmin_log("Request to login-server to change a state.\n");
-
-	WFIFOW(login_fd,0) = 0x7936;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOL(login_fd,26) = state;
-	memcpy(WFIFOP(login_fd,30), error_message, 20);
-	WFIFOSET(login_fd,50);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-------------------------------------------------------
-// Sub-function: Asking to modify the state of an account
-//-------------------------------------------------------
-int changestate(char* param)
-{
-	char name[1023], error_message[1023];
-	int state;
-
-	memset(name, '\0', sizeof(name));
-	memset(error_message, '\0', sizeof(error_message));
-
-	if (sscanf(param, "\"%[^\"]\" %d %[^\r\n]", name, &state, error_message) < 2 &&
-	    sscanf(param, "'%[^']' %d %[^\r\n]", name, &state, error_message) < 2 &&
-	    sscanf(param, "%s %d %[^\r\n]", name, &state, error_message) < 2) {
-		ShowMessage("Please input an account name and a state.\n");
-		ShowMessage("<examples> state testname 5\n");
-		ShowMessage("           state testname 7 end of your ban\n");
-		ShowMessage("           block <account name>\n");
-		ShowMessage("           unblock <account name>\n");
-		ladmin_log("Incomplete parameters to change the state of an account ('state' command).\n");
-		return 136;
-	}
-
-	return changestatesub(name, state, error_message);
-}
-
-//-------------------------------------------
-// Sub-function: Asking to unblock an account
-//-------------------------------------------
-int unblockaccount(char* param)
-{
-	char name[1023];
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<examples> state testname 5\n");
-		ShowMessage("           state testname 7 end of your ban\n");
-		ShowMessage("           block <account name>\n");
-		ShowMessage("           unblock <account name>\n");
-		ladmin_log("Incomplete parameters to change the state of an account ('unblock' command).\n");
-		return 136;
-	}
-
-	return changestatesub(name, 0, "-"); // state 0, no error message
-}
-
-//-------------------------------------------
-// Sub-function: Asking to unblock an account
-//-------------------------------------------
-int blockaccount(char* param)
-{
-	char name[1023];
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<examples> state testname 5\n");
-		ShowMessage("           state testname 7 end of your ban\n");
-		ShowMessage("           block <account name>\n");
-		ShowMessage("           unblock <account name>\n");
-		ladmin_log("Incomplete parameters to change the state of an account ('block' command).\n");
-		return 136;
-	}
-
-	return changestatesub(name, 5, "-"); // state 5, no error message
-}
-
-//---------------------------------------------------------------------
-// Sub-function: Add/substract time to the validity limit of an account
-//---------------------------------------------------------------------
-int timeaddaccount(char* param)
-{
-	char name[1023], modif[1023];
-	int year, month, day, hour, minute, second;
-	char * p_modif;
-	int value, i;
-	WFIFOHEAD(login_fd,38);
-
-	memset(name, '\0', sizeof(name));
-	memset(modif, '\0', sizeof(modif));
-	year = month = day = hour = minute = second = 0;
-
-	if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
-	    sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
-	    sscanf(param, "%s %[^\r\n]", name, modif) < 2)
-	{
-		ShowMessage("Please input an account name and a modifier.\n");
-		ShowMessage("  <example>: timeadd testname +1m-2mn1s-6y\n");
-		ShowMessage("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("             and 6 years at the same time.\n");
-		ladmin_log("Incomplete parameters to modify a limit time ('timeadd' command).\n");
-		return 136;
-	}
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	// lowercase for modif
-	for (i = 0; modif[i]; i++)
-		modif[i] = TOLOWER(modif[i]);
-	p_modif = modif;
-	while (strlen(p_modif) > 0) {
-		value = atoi(p_modif);
-		if (value == 0) {
-			p_modif++;
-		} else {
-			if (p_modif[0] == '-' || p_modif[0] == '+')
-				p_modif++;
-			while (strlen(p_modif) > 0 && p_modif[0] >= '0' && p_modif[0] <= '9') {
-				p_modif++;
-			}
-			if (p_modif[0] == 's') {
-				second = value;
-				p_modif++;
-			} else if (p_modif[0] == 'm' && p_modif[1] == 'n') {
-				minute = value;
-				p_modif += 2;
-			} else if (p_modif[0] == 'h') {
-				hour = value;
-				p_modif++;
-			} else if (p_modif[0] == 'd' || p_modif[0] == 'j') {
-				day = value;
-				p_modif += 2;
-			} else if (p_modif[0] == 'm') {
-				month = value;
-				p_modif++;
-			} else if (p_modif[0] == 'y' || p_modif[0] == 'a') {
-				year = value;
-				p_modif++;
-			} else {
-				p_modif++;
-			}
-		}
-	}
-
-	ShowMessage(" year:   %d\n", year);
-	ShowMessage(" month:  %d\n", month);
-	ShowMessage(" day:    %d\n", day);
-	ShowMessage(" hour:   %d\n", hour);
-	ShowMessage(" minute: %d\n", minute);
-	ShowMessage(" second: %d\n", second);
-
-	if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) {
-		ShowMessage("Please give an adjustment with this command:\n");
-		ShowMessage("  Adjustment value (-1, 1, +1, etc...)\n");
-		ShowMessage("  Modified element:\n");
-		ShowMessage("    a or y: year\n");
-		ShowMessage("    m:      month\n");
-		ShowMessage("    j or d: day\n");
-		ShowMessage("    h:      hour\n");
-		ShowMessage("    mn:     minute\n");
-		ShowMessage("    s:      second\n");
-		ShowMessage("  <example> timeadd testname +1m-2mn1s-6y\n");
-		ShowMessage("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-		ShowMessage("            and 6 years at the same time.\n");
-		ladmin_log("No adjustment isn't an adjustment ('timeadd' command).\n");
-		return 137;
-	}
-	if (year > 127 || year < -127) {
-		ShowMessage("Please give a correct adjustment for the years (from -127 to 127).\n");
-		ladmin_log("Abnormal adjustment for the year ('timeadd' command).\n");
-		return 137;
-	}
-	if (month > 255 || month < -255) {
-		ShowMessage("Please give a correct adjustment for the months (from -255 to 255).\n");
-		ladmin_log("Abnormal adjustment for the month ('timeadd' command).\n");
-		return 137;
-	}
-	if (day > 32767 || day < -32767) {
-		ShowMessage("Please give a correct adjustment for the days (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the days ('timeadd' command).\n");
-		return 137;
-	}
-	if (hour > 32767 || hour < -32767) {
-		ShowMessage("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the hours ('timeadd' command).\n");
-		return 137;
-	}
-	if (minute > 32767 || minute < -32767) {
-		ShowMessage("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the minutes ('timeadd' command).\n");
-		return 137;
-	}
-	if (second > 32767 || second < -32767) {
-		ShowMessage("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
-		ladmin_log("Abnormal adjustment for the seconds ('timeadd' command).\n");
-		return 137;
-	}
-
-	ladmin_log("Request to login-server to modify a time limit.\n");
-
-	WFIFOW(login_fd,0) = 0x7950;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOW(login_fd,26) = (short)year;
-	WFIFOW(login_fd,28) = (short)month;
-	WFIFOW(login_fd,30) = (short)day;
-	WFIFOW(login_fd,32) = (short)hour;
-	WFIFOW(login_fd,34) = (short)minute;
-	WFIFOW(login_fd,36) = (short)second;
-	WFIFOSET(login_fd,38);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//-------------------------------------------------
-// Sub-function: Set a validity limit of an account
-//-------------------------------------------------
-int timesetaccount(char* param)
-{
-	char name[1023], date[1023], time[1023];
-	int year, month, day, hour, minute, second;
-	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-	struct tm *tmtime;
-	WFIFOHEAD(login_fd,30);
-
-	memset(name, '\0', sizeof(name));
-	memset(date, '\0', sizeof(date));
-	memset(time, '\0', sizeof(time));
-	year = month = day = hour = minute = second = 0;
-	expiration_time = 0;
-	tmtime = localtime(&expiration_time); // initialize
-
-	if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
-	    sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
-	    sscanf(param, "%s %s %[^\r\n]", name, date, time) < 2) { // if date = 0, time can be void
-		ShowMessage("Please input an account name, a date and a hour.\n");
-		ShowMessage("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-		ShowMessage("           timeset <account_name> 0   (0 = unlimited)\n");
-		ShowMessage("           Default time [hh:mm:ss]: 23:59:59.\n");
-		ladmin_log("Incomplete parameters to set a limit time ('timeset' command).\n");
-		return 136;
-	}
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	if (time[0] == '\0')
-		strcpy(time, "23:59:59");
-
-	if (atoi(date) != 0 &&
-	    ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
-	      sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
-	      sscanf(date, "%d.%d.%d", &year, &month, &day) < 3 &&
-	      sscanf(date, "%d'%d'%d", &year, &month, &day) < 3) ||
-	     sscanf(time, "%d:%d:%d", &hour, &minute, &second) < 3))
-	{
-		ShowMessage("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
-		ladmin_log("Invalid format for the date/time ('timeset' command).\n");
-		return 102;
-	}
-
-	if (atoi(date) == 0) {
-		expiration_time = 0;
-	} else {
-		if (year < 70) {
-			year = year + 100;
-		}
-		if (year >= 1900) {
-			year = year - 1900;
-		}
-		if (month < 1 || month > 12) {
-			ShowMessage("Please give a correct value for the month (from 1 to 12).\n");
-			ladmin_log("Invalid month for the date ('timeset' command).\n");
-			return 102;
-		}
-		month = month - 1;
-		if (day < 1 || day > 31) {
-			ShowMessage("Please give a correct value for the day (from 1 to 31).\n");
-			ladmin_log("Invalid day for the date ('timeset' command).\n");
-			return 102;
-		}
-		if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) ||
-		    (month == 1 && day > 29)) {
-			ShowMessage("Please give a correct value for a day of this month (%d).\n", month);
-			ladmin_log("Invalid day for this month ('timeset' command).\n");
-			return 102;
-		}
-		if (hour < 0 || hour > 23) {
-			ShowMessage("Please give a correct value for the hour (from 0 to 23).\n");
-			ladmin_log("Invalid hour for the time ('timeset' command).\n");
-			return 102;
-		}
-		if (minute < 0 || minute > 59) {
-			ShowMessage("Please give a correct value for the minutes (from 0 to 59).\n");
-			ladmin_log("Invalid minute for the time ('timeset' command).\n");
-			return 102;
-		}
-		if (second < 0 || second > 59) {
-			ShowMessage("Please give a correct value for the seconds (from 0 to 59).\n");
-			ladmin_log("Invalid second for the time ('timeset' command).\n");
-			return 102;
-		}
-		tmtime->tm_year = year;
-		tmtime->tm_mon = month;
-		tmtime->tm_mday = day;
-		tmtime->tm_hour = hour;
-		tmtime->tm_min = minute;
-		tmtime->tm_sec = second;
-		tmtime->tm_isdst = -1; // -1: no winter/summer time modification
-		expiration_time = mktime(tmtime);
-		if (expiration_time == -1) {
-			ShowMessage("Invalid date.\n");
-			ShowMessage("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
-			ladmin_log("Invalid date. ('timeset' command).\n");
-			return 102;
-		}
-	}
-
-	ladmin_log("Request to login-server to set a time limit.\n");
-
-	WFIFOW(login_fd,0) = 0x7948;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOL(login_fd,26) = (int)expiration_time;
-	WFIFOSET(login_fd,30);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//------------------------------------------------------------------------------
-// Sub-function: Asking to displaying information about an account (by its name)
-//------------------------------------------------------------------------------
-int whoaccount(char* param)
-{
-	char name[1023];
-	WFIFOHEAD(login_fd,26);
-
-	memset(name, '\0', sizeof(name));
-
-	if (strlen(param) == 0 ||
-	    (sscanf(param, "\"%[^\"]\"", name) < 1 &&
-	     sscanf(param, "'%[^']'", name) < 1 &&
-	     sscanf(param, "%[^\r\n]", name) < 1) ||
-	     strlen(name) == 0)
-	{
-		ShowMessage("Please input an account name.\n");
-		ShowMessage("<example> who testname\n");
-		ladmin_log("No name was given to found the account.\n");
-		return 136;
-	}
-	if (verify_accountname(name) == 0) {
-		return 102;
-	}
-
-	ladmin_log("Request to login-server to obtain information about an account (by its name).\n");
-
-	WFIFOW(login_fd,0) = 0x7952;
-	memcpy(WFIFOP(login_fd,2), name, 24);
-	WFIFOSET(login_fd,26);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//--------------------------------------------------------
-// Sub-function: Asking of the version of the login-server
-//--------------------------------------------------------
-int checkloginversion(void)
-{
-	WFIFOHEAD(login_fd,2);
-	ladmin_log("Request to login-server to obtain its version.\n");
-
-	WFIFOW(login_fd,0) = 0x7530;
-	WFIFOSET(login_fd,2);
-	bytes_to_read = 1;
-
-	return 0;
-}
-
-//---------------------------------------------
-// Prompt function
-// this function wait until user type a command
-// and analyse the command.
-//---------------------------------------------
-int prompt(void)
-{
-	int i, j;
-	char buf[1024];
-	char *p;
-
-	// while we don't wait new packets
-	while (bytes_to_read == 0) {
-		// for help with the console colors look here:
-		// http://www.edoceo.com/liberum/?doc=printf-with-color
-		// some code explanation (used here):
-		// \033[2J : clear screen and go up/left (0, 0 position)
-		// \033[K  : clear line from actual position to end of the line
-		// \033[0m : reset color parameter
-		// \033[1m : use bold for font
-		ShowMessage("\n");
-		ShowMessage("\033[32mTo list the commands, type 'enter'.\033[0m\n");
-		ShowMessage("\033[0;36mLadmin-> \033[0m");
-		ShowMessage("\033[1m");
-		fflush(stdout);
-
-		// get command and parameter
-		memset(buf, '\0', sizeof(buf));
-		fflush(stdin);
-		fgets(buf, sizeof(buf), stdin);
-
-		ShowMessage("\033[0m");
-		fflush(stdout);
-
-		// remove final \n
-		if((p = strrchr(buf, '\n')) != NULL)
-			p[0] = '\0';
-		// remove all control char
-		for (i = 0; buf[i]; i++)
-			if (buf[i] < 32) {
-				// remove cursor control.
-				if (buf[i] == 27 && buf[i+1] == '[' &&
-				    (buf[i+2] == 'H' || // home position (cursor)
-				     buf[i+2] == 'J' || // clear screen
-				     buf[i+2] == 'A' || // up 1 line
-				     buf[i+2] == 'B' || // down 1 line
-				     buf[i+2] == 'C' || // right 1 position
-				     buf[i+2] == 'D' || // left 1 position
-				     buf[i+2] == 'G')) { // center cursor (windows)
-					for (j = i; buf[j]; j++)
-						buf[j] = buf[j+3];
-				} else if (buf[i] == 27 && buf[i+1] == '[' && buf[i+2] == '2' && buf[i+3] == 'J') { // clear screen
-					for (j = i; buf[j]; j++)
-						buf[j] = buf[j+4];
-				} else if (buf[i] == 27 && buf[i+1] == '[' && buf[i+3] == '~' &&
-				           (buf[i+2] == '1' || // home (windows)
-				            buf[i+2] == '2' || // insert (windows)
-				            buf[i+2] == '3' || // del (windows)
-				            buf[i+2] == '4' || // end (windows)
-				            buf[i+2] == '5' || // pgup (windows)
-				            buf[i+2] == '6')) { // pgdown (windows)
-					for (j = i; buf[j]; j++)
-						buf[j] = buf[j+4];
-				} else {
-					// remove other control char.
-					for (j = i; buf[j]; j++)
-						buf[j] = buf[j+1];
-				}
-				i--;
-			}
-
-		// extract command name and parameters
-		memset(command, '\0', sizeof(command));
-		memset(parameters, '\0', sizeof(parameters));
-		sscanf(buf, "%1023s %[^\n]", command, parameters);
-		command[1023] = '\0';
-		parameters[1023] = '\0';
-
-		// lowercase for command line
-		for (i = 0; command[i]; i++)
-			command[i] = TOLOWER(command[i]);
-
-		if (command[0] == '?' || strlen(command) == 0) {
-			strcpy(buf, "help");
-			strcpy(command, "help");
-		}
-
-		// Analyse of the command
-		check_command(command); // give complete name to the command
-
-		if (strlen(parameters) == 0) {
-			ladmin_log("Command: '%s' (without parameters)\n", command, parameters);
-		} else {
-			ladmin_log("Command: '%s', parameters: '%s'\n", command, parameters);
-		}
-
-		// Analyse of the command
-// help
-		if (strcmp(command, "help") == 0 ) {
-			display_help(parameters);
-// general commands
-		} else if (strcmp(command, "add") == 0) {
-			addaccount(parameters, 0); // 0: no email
-		} else if (strcmp(command, "ban") == 0) {
-			banaccount(parameters);
-		} else if (strcmp(command, "banadd") == 0) {
-			banaddaccount(parameters);
-		} else if (strcmp(command, "banset") == 0) {
-			bansetaccount(parameters);
-		} else if (strcmp(command, "block") == 0) {
-			blockaccount(parameters);
-		} else if (strcmp(command, "check") == 0) {
-			checkaccount(parameters);
-		} else if (strcmp(command, "create") == 0) {
-			addaccount(parameters, 1); // 1: with email
-		} else if (strcmp(command, "delete") == 0) {
-			delaccount(parameters);
-		} else if (strcmp(command, "email") == 0) {
-			changeemail(parameters);
-		} else if (strcmp(command, "getcount") == 0) {
-			getlogincount();
-		} else if (strcmp(command, "gm") == 0) {
-			changegmlevel(parameters);
-		} else if (strcmp(command, "id") == 0) {
-			idaccount(parameters);
-		} else if (strcmp(command, "info") == 0) {
-			infoaccount(atoi(parameters));
-		} else if (strcmp(command, "kami") == 0) {
-			sendbroadcast(0, parameters); // flag for normal
-		} else if (strcmp(command, "kamib") == 0) {
-			sendbroadcast(0x10, parameters); // flag for blue
-		} else if (strcmp(command, "list") == 0) {
-			listaccount(parameters, 0); // 0: to list all
-		} else if (strcmp(command, "listban") == 0) {
-			listaccount(parameters, 3); // 3: to list only accounts with state or bannished
-		} else if (strcmp(command, "listgm") == 0) {
-			listaccount(parameters, 1); // 1: to list only GM
-		} else if (strcmp(command, "listok") == 0) {
-			listaccount(parameters, 4); // 4: to list only accounts without state and not bannished
-		} else if (strcmp(command, "memo") == 0) {
-			changememo(parameters);
-		} else if (strcmp(command, "name") == 0) {
-			nameaccount(atoi(parameters));
-		} else if (strcmp(command, "password") == 0) {
-			changepasswd(parameters);
-		} else if (strcmp(command, "reloadgm") == 0) {
-			reloadGM();
-		} else if (strcmp(command, "search") == 0) { // no regex in C version
-			listaccount(parameters, 2); // 2: to list with pattern
-		} else if (strcmp(command, "sex") == 0) {
-			changesex(parameters);
-		} else if (strcmp(command, "state") == 0) {
-			changestate(parameters);
-		} else if (strcmp(command, "timeadd") == 0) {
-			timeaddaccount(parameters);
-		} else if (strcmp(command, "timeset") == 0) {
-			timesetaccount(parameters);
-		} else if (strcmp(command, "unban") == 0) {
-			unbanaccount(parameters);
-		} else if (strcmp(command, "unblock") == 0) {
-			unblockaccount(parameters);
-		} else if (strcmp(command, "version") == 0) {
-			checkloginversion();
-		} else if (strcmp(command, "who") == 0) {
-			whoaccount(parameters);
-// quit
-		} else if (strcmp(command, "quit") == 0 ||
-		           strcmp(command, "exit") == 0 ||
-		           strcmp(command, "end") == 0) {
-			ShowMessage("Bye.\n");
-			exit(EXIT_SUCCESS);
-// unknown command
-		} else {
-			ShowMessage("Unknown command [%s].\n", buf);
-			ladmin_log("Unknown command [%s].\n", buf);
-		}
-	}
-
-	return 0;
-}
-
-//-------------------------------------------------------------
-// Function: Parse receiving informations from the login-server
-//-------------------------------------------------------------
-int parse_fromlogin(int fd)
-{
-	struct char_session_data *sd;
-	int id;
-	RFIFOHEAD(fd);
-	if (session[fd]->flag.eof) {
-		ShowMessage("Impossible to have a connection with the login-server [%s:%d] !\n", loginserverip, loginserverport);
-		ladmin_log("Impossible to have a connection with the login-server [%s:%d] !\n", loginserverip, loginserverport);
-		do_close(fd);
-		exit(EXIT_FAILURE);
-	}
-
-//	ShowMessage("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
-	sd = (struct char_session_data*)session[fd]->session_data;
-
-	while(RFIFOREST(fd) >= 2) {
-		switch(RFIFOW(fd,0)) {
-		case 0x7919:	// answer of a connection request
-			if (RFIFOREST(fd) < 3)
-				return 0;
-			if (RFIFOB(fd,2) != 0) {
-				ShowMessage("Error at login:\n");
-				ShowMessage(" - incorrect password,\n");
-				ShowMessage(" - administration system not activated, or\n");
-				ShowMessage(" - unauthorised IP.\n");
-				ladmin_log("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n");
-				set_eof(fd);
-				//bytes_to_read = 1; // not stop at prompt
-				return 0;
-			} else {
-				ShowMessage("Established connection.\n");
-				ladmin_log("Established connection.\n");
-				ShowMessage("Reading of the version of the login-server...\n");
-				ladmin_log("Reading of the version of the login-server...\n");
-				//bytes_to_read = 1; // unchanged
-				checkloginversion();
-			}
-			RFIFOSKIP(fd,3);
-			break;
-
-		case 0x01dc:	// answer of a coding key request
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-		  {
-			char md5str[64] = "", md5bin[32];
-			WFIFOHEAD(login_fd, 20);
-			if (passenc == 1) {
-				strncpy(md5str, (const char*)RFIFOP(fd,4), RFIFOW(fd,2) - 4);
-				strcat(md5str, loginserveradminpassword);
-			} else if (passenc == 2) {
-				strncpy(md5str, loginserveradminpassword, sizeof(loginserveradminpassword));
-				strcat(md5str, (const char*)RFIFOP(fd,4));
-			}
-			MD5_Binary(md5str, md5bin);
-			WFIFOW(login_fd,0) = 0x7918; // Request for administation login (encrypted password)
-			WFIFOW(login_fd,2) = passenc; // Encrypted type
-			memcpy(WFIFOP(login_fd,4), md5bin, 16);
-			WFIFOSET(login_fd,20);
-			ShowMessage("Receiving of the MD5 key.\n");
-			ladmin_log("Receiving of the MD5 key.\n");
-			ShowMessage("Sending of the encrypted password...\n");
-			ladmin_log("Sending of the encrypted password...\n");
-		  }
-			bytes_to_read = 1;
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-			break;
-
-		case 0x7531:	// Displaying of the version of the login-server
-			if (RFIFOREST(fd) < 10)
-				return 0;
-			ShowMessage("  Login-Server [%s:%d]\n", loginserverip, loginserverport);
-			if (((int)RFIFOB(login_fd,5)) == 0) {
-				ShowMessage("  eAthena version stable-%d.%d", (int)RFIFOB(login_fd,2), (int)RFIFOB(login_fd,3));
-			} else {
-				ShowMessage("  eAthena version dev-%d.%d", (int)RFIFOB(login_fd,2), (int)RFIFOB(login_fd,3));
-			}
-			if (((int)RFIFOB(login_fd,4)) == 0)
-				ShowMessage(" revision %d", (int)RFIFOB(login_fd,4));
-			if (((int)RFIFOB(login_fd,6)) == 0)
-				ShowMessage("%d.\n", RFIFOW(login_fd,8));
-			else
-				ShowMessage("-mod%d.\n", RFIFOW(login_fd,8));
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,10);
-			break;
-
-		case 0x7921:	// Displaying of the list of accounts
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-			if (RFIFOW(fd,2) < 5) {
-				ladmin_log("  Receiving of a void accounts list.\n");
-				if (list_count == 0)
-					ShowMessage("No account found.\n");
-				else if (list_count == 1)
-					ShowMessage("1 account found.\n");
-				else
-					ShowMessage("%d accounts found.\n", list_count);
-				bytes_to_read = 0;
-			} else {
-				int i;
-				WFIFOHEAD(login_fd,10);
-				ladmin_log("  Receiving of a accounts list.\n");
-				for(i = 4; i < RFIFOW(fd,2); i += 38) {
-					int j;
-					char userid[24];
-					char lower_userid[24];
-					memcpy(userid, RFIFOP(fd,i + 5), sizeof(userid));
-					userid[sizeof(userid)-1] = '\0';
-					memset(lower_userid, '\0', sizeof(lower_userid));
-					for (j = 0; userid[j]; j++)
-						lower_userid[j] = TOLOWER(userid[j]);
-					list_first = RFIFOL(fd,i) + 1;
-					// here are checks...
-					if (list_type == 0 ||
-					    (list_type == 1 && RFIFOB(fd,i+4) > 0) ||
-					    (list_type == 2 && strstr(lower_userid, parameters) != NULL) ||
-					    (list_type == 3 && RFIFOL(fd,i+34) != 0) ||
-					    (list_type == 4 && RFIFOL(fd,i+34) == 0)) {
-						ShowMessage("%10d ", (int)RFIFOL(fd,i));
-						if (RFIFOB(fd,i+4) == 0)
-							ShowMessage("   ");
-						else
-							ShowMessage("%2d ", (int)RFIFOB(fd,i+4));
-						ShowMessage("%-24s", userid);
-						if (RFIFOB(fd,i+29) == 0)
-							ShowMessage("%-5s ", "Femal");
-						else if (RFIFOB(fd,i+29) == 1)
-							ShowMessage("%-5s ", "Male");
-						else
-							ShowMessage("%-5s ", "Servr");
-						ShowMessage("%6d ", (int)RFIFOL(fd,i+30));
-						switch(RFIFOL(fd,i+34)) {
-						case 0:
-							ShowMessage("%-27s\n", "Account OK");
-							break;
-						case 1:
-							ShowMessage("%-27s\n", "Unregistered ID");
-							break;
-						case 2:
-							ShowMessage("%-27s\n", "Incorrect Password");
-							break;
-						case 3:
-							ShowMessage("%-27s\n", "This ID is expired");
-							break;
-						case 4:
-							ShowMessage("%-27s\n", "Rejected from Server");
-							break;
-						case 5:
-							ShowMessage("%-27s\n", "Blocked by the GM Team"); // You have been blocked by the GM Team
-							break;
-						case 6:
-							ShowMessage("%-27s\n", "Your EXE file is too old"); // Your Game's EXE file is not the latest version
-							break;
-						case 7:
-							ShowMessage("%-27s\n", "Banishement or");
-							ShowMessage("                                                   Prohibited to login until...\n"); // You are Prohibited to log in until %s
-							break;
-						case 8:
-							ShowMessage("%-27s\n", "Server is over populated");
-							break;
-						case 9:
-							ShowMessage("%-27s\n", "No MSG");
-							break;
-						default: // 100
-							ShowMessage("%-27s\n", "This ID is totally erased"); // This ID has been totally erased
-							break;
-						}
-						list_count++;
-					}
-				}
-				// asking of the following acounts
-				ladmin_log("Request to login-server to obtain the list of accounts from %d to %d (complement).\n", list_first, list_last);
-				WFIFOW(login_fd,0) = 0x7920;
-				WFIFOL(login_fd,2) = list_first;
-				WFIFOL(login_fd,6) = list_last;
-				WFIFOSET(login_fd,10);
-				bytes_to_read = 1;
-			}
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-			break;
-
-		case 0x7931:	// Answer of login-server about an account creation
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id != -1) {
-				ShowMessage("Account [%s] creation failed. Return code %d.\n", RFIFOP(fd,6), id);
-				ladmin_log("Account [%s] creation failed. Return code %d.\n", RFIFOP(fd,6), id);
-			} else {
-				ShowMessage("Account [%s] is successfully created.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] is successfully created.\n", RFIFOP(fd,6));
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7933:	// Answer of login-server about an account deletion
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			if (RFIFOL(fd,2) == -1) {
-				ShowMessage("Account [%s] deletion failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] deletion failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] is successfully DELETED.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
-				ladmin_log("Account [%s][id: %d] is successfully DELETED.\n", RFIFOP(fd,6), RFIFOL(fd,2));
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7935:	// answer of the change of an account password
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			if (RFIFOL(fd,2) == -1) {
-				ShowMessage("Account [%s] password changing failed.\n", RFIFOP(fd,6));
-				ShowMessage("Account [%s] doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account password changing failed. The compte [%s] doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] password successfully changed.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
-				ladmin_log("Account [%s][id: %d] password successfully changed.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7937:	// answer of the change of an account state
-			if (RFIFOREST(fd) < 34)
-				return 0;
-			if (RFIFOL(fd,2) == -1) {
-				ShowMessage("Account [%s] state changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] state changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				char tmpstr[256];
-				sprintf(tmpstr, "Account [%s] state successfully changed in [", RFIFOP(fd,6));
-				switch(RFIFOL(fd,30)) {
-				case 0:
-					strcat(tmpstr, "0: Account OK");
-				case 1:
-					strcat(tmpstr, "1: Unregistered ID");
-					break;
-				case 2:
-					strcat(tmpstr, "2: Incorrect Password");
-					break;
-				case 3:
-					strcat(tmpstr, "3: This ID is expired");
-					break;
-				case 4:
-					strcat(tmpstr, "4: Rejected from Server");
-					break;
-				case 5:
-					strcat(tmpstr, "5: You have been blocked by the GM Team");
-					break;
-				case 6:
-					strcat(tmpstr, "6: [Your Game's EXE file is not the latest version");
-					break;
-				case 7:
-					strcat(tmpstr, "7: You are Prohibited to log in until...");
-					break;
-				case 8:
-					strcat(tmpstr, "8: Server is jammed due to over populated");
-					break;
-				case 9:
-					strcat(tmpstr, "9: No MSG");
-					break;
-				default: // 100
-					strcat(tmpstr, "100: This ID is totally erased");
-					break;
-				}
-				strcat(tmpstr, "]");
-				ShowMessage("%s\n", tmpstr);
-				ladmin_log("%s\n", tmpstr);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,34);
-			break;
-
-		case 0x7939:	// answer of the number of online players
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-		  {
-			// Get length of the received packet
-			int i;
-			char name[20];
-			ladmin_log("  Receiving of the number of online players.\n");
-			// Read information of the servers
-			if (RFIFOW(fd,2) < 5) {
-				ShowMessage("  No server is connected to the login-server.\n");
-			} else {
-				ShowMessage("  Number of online players (server: number).\n");
-				// Displaying of result
-				for(i = 4; i < RFIFOW(fd,2); i += 32) {
-					memcpy(name, RFIFOP(fd,i+6), sizeof(name));
-					name[sizeof(name) - 1] = '\0';
-					ShowMessage("    %-20s : %5d\n", name, RFIFOW(fd,i+26));
-				}
-			}
-		  }
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-			break;
-
-		case 0x793b:	// answer of the check of a password
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("The account [%s] doesn't exist or the password is incorrect.\n", RFIFOP(fd,6));
-				ladmin_log("The account [%s] doesn't exist or the password is incorrect.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("The proposed password is correct for the account [%s][id: %d].\n", RFIFOP(fd,6), id);
-				ladmin_log("The proposed password is correct for the account [%s][id: %d].\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x793d:	// answer of the change of an account sex
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] sex changing failed.\n", RFIFOP(fd,6));
-				ShowMessage("Account [%s] doesn't exist or the sex is already the good sex.\n", RFIFOP(fd,6));
-				ladmin_log("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] sex successfully changed.\n", RFIFOP(fd,6), id);
-				ladmin_log("Account [%s][id: %d] sex successfully changed.\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x793f:	// answer of the change of an account GM level
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] GM level changing failed.\n", RFIFOP(fd,6));
-				ShowMessage("Account [%s] doesn't exist, the GM level is already the good GM level\n", RFIFOP(fd,6));
-				ShowMessage("or it's impossible to modify the GM accounts file.\n");
-				ladmin_log("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] GM level successfully changed.\n", RFIFOP(fd,6), id);
-				ladmin_log("Account [%s][id: %d] GM level successfully changed.\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7941:	// answer of the change of an account email
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] e-mail changing failed.\n", RFIFOP(fd,6));
-				ShowMessage("Account [%s] doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account e-mail changing failed. The compte [%s] doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] e-mail successfully changed.\n", RFIFOP(fd,6), id);
-				ladmin_log("Account [%s][id: %d] e-mail successfully changed.\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7943:	// answer of the change of an account memo
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] memo changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] memo changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("Account [%s][id: %d] memo successfully changed.\n", RFIFOP(fd,6), id);
-				ladmin_log("Account [%s][id: %d] memo successfully changed.\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7945:	// answer of an account id search
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Unable to find the account [%s] id. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Unable to find the account [%s] id. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				ShowMessage("The account [%s] have the id: %d.\n", RFIFOP(fd,6), id);
-				ladmin_log("The account [%s] have the id: %d.\n", RFIFOP(fd,6), id);
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7947:	// answer of an account name search
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (strcmp((const char*)RFIFOP(fd,6), "") == 0) {
-				ShowMessage("Unable to find the account [%d] name. Account doesn't exist.\n", id);
-				ladmin_log("Unable to find the account [%d] name. Account doesn't exist.\n", id);
-			} else {
-				ShowMessage("The account [id: %d] have the name: %s.\n", id, RFIFOP(fd,6));
-				ladmin_log("The account [id: %d] have the name: %s.\n", id, RFIFOP(fd,6));
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x7949:	// answer of an account validity limit set
-			if (RFIFOREST(fd) < 34)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				time_t timestamp = RFIFOL(fd,30);
-				if (timestamp == 0) {
-					ShowMessage("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", RFIFOP(fd,6), id);
-					ladmin_log("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", RFIFOP(fd,6), id);
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&timestamp));
-					ShowMessage("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-					ladmin_log("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-				}
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,34);
-			break;
-
-		case 0x794b:	// answer of an account ban set
-			if (RFIFOREST(fd) < 34)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				time_t timestamp = RFIFOL(fd,30);
-				if (timestamp == 0) {
-					ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
-					ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&timestamp));
-					ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-					ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-				}
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,34);
-			break;
-
-		case 0x794d:	// answer of an account ban date/time changing
-			if (RFIFOREST(fd) < 34)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				time_t timestamp = RFIFOL(fd,30);
-				if (timestamp == 0) {
-					ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
-					ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&timestamp));
-					ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-					ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-				}
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,34);
-			break;
-
-		case 0x794f:	// answer of a broadcast
-			if (RFIFOREST(fd) < 4)
-				return 0;
-			if (RFIFOW(fd,2) == (unsigned short)-1) {
-				ShowMessage("Message sending failed. No online char-server.\n");
-				ladmin_log("Message sending failed. No online char-server.\n");
-			} else {
-				ShowMessage("Message successfully sended to login-server.\n");
-				ladmin_log("Message successfully sended to login-server.\n");
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,4);
-			break;
-
-		case 0x7951:	// answer of an account validity limit changing
-			if (RFIFOREST(fd) < 34)
-				return 0;
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-				ladmin_log("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
-			} else {
-				time_t timestamp = RFIFOL(fd,30);
-				if (timestamp == 0) {
-					ShowMessage("Validity limit of the account [%s][id: %d] unchanged.\n", RFIFOP(fd,6), id);
-					ShowMessage("The account have an unlimited validity limit or\n");
-					ShowMessage("the changing is impossible with the proposed adjustments.\n");
-					ladmin_log("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n", RFIFOP(fd,6), id);
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&timestamp));
-					ShowMessage("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-					ladmin_log("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
-				}
-			}
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,34);
-			break;
-
-		case 0x7953:	// answer of a request about informations of an account (by account name/id)
-			if (RFIFOREST(fd) < 150 || RFIFOREST(fd) < (size_t)(150 + RFIFOW(fd,148)))
-				return 0;
-		{
-			char userid[24], error_message[20], lastlogin[24], last_ip[16], email[40], memo[255];
-			time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-			time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-			safestrncpy(userid, (char*)RFIFOP(fd,7), sizeof(userid));
-			safestrncpy(error_message, (char*)RFIFOP(fd,40), sizeof(error_message));
-			safestrncpy(lastlogin, (char*)RFIFOP(fd,60), sizeof(lastlogin));
-			safestrncpy(last_ip, (char*)RFIFOP(fd,84), sizeof(last_ip));
-			safestrncpy(email, (char*)RFIFOP(fd,100), sizeof(email));
-			expiration_time = (time_t)RFIFOL(fd,140);
-			unban_time = (time_t)RFIFOL(fd,144);
-			memset(memo, '\0', sizeof(memo));
-			safestrncpy(memo, (const char*)RFIFOP(fd,150), RFIFOW(fd,148));
-			id = RFIFOL(fd,2);
-			if (id == -1) {
-				ShowMessage("Unabled to find the account [%s]. Account doesn't exist.\n", parameters);
-				ladmin_log("Unabled to find the account [%s]. Account doesn't exist.\n", parameters);
-			} else if (strlen(userid) == 0) {
-				ShowMessage("Unabled to find the account [id: %s]. Account doesn't exist.\n", parameters);
-				ladmin_log("Unabled to find the account [id: %s]. Account doesn't exist.\n", parameters);
-			} else {
-				ladmin_log("Receiving information about an account.\n");
-				ShowMessage("The account is set with:\n");
-				if (RFIFOB(fd,6) == 0) {
-					ShowMessage(" Id:     %d (non-GM)\n", id);
-				} else {
-					ShowMessage(" Id:     %d (GM level %d)\n", id, (int)RFIFOB(fd,6));
-				}
-				ShowMessage(" Name:   '%s'\n", userid);
-				if (RFIFOB(fd,31) == 0)
-					ShowMessage(" Sex:    Female\n");
-				else if (RFIFOB(fd,31) == 1)
-					ShowMessage(" Sex:    Male\n");
-				else
-					ShowMessage(" Sex:    Server\n");
-				ShowMessage(" E-mail: %s\n", email);
-				switch(RFIFOL(fd,36)) {
-				case 0: ShowMessage(" State: 0 [Account OK]\n"); break;
-				case 1: ShowMessage(" State: 1 [Unregistered ID]\n"); break;
-				case 2: ShowMessage(" State: 2 [Incorrect Password]\n"); break;
-				case 3: ShowMessage(" State: 3 [This ID is expired]\n"); break;
-				case 4: ShowMessage(" State: 4 [Rejected from Server]\n"); break;
-				case 5: ShowMessage(" State: 5 [You have been blocked by the GM Team]\n"); break;
-				case 6: ShowMessage(" State: 6 [Your Game's EXE file is not the latest version]\n"); break;
-				case 7: ShowMessage(" State: 7 [You are Prohibited to log in until %s]\n", error_message); break;
-				case 8: ShowMessage(" State: 8 [Server is jammed due to over populated]\n"); break;
-				case 9: ShowMessage(" State: 9 [No MSG]\n"); break;
-				default: // 100
-					ShowMessage(" State: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36));
-					break;
-				}
-				if (unban_time == 0) {
-					ShowMessage(" Banishment: not banished.\n");
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&unban_time));
-					ShowMessage(" Banishment: until %s.\n", tmpstr);
-				}
-				if (RFIFOL(fd,32) > 1)
-					ShowMessage(" Count:  %d connections.\n", (int)RFIFOL(fd,32));
-				else
-					ShowMessage(" Count:  %d connection.\n", (int)RFIFOL(fd,32));
-				ShowMessage(" Last connection at: %s (ip: %s)\n", lastlogin, last_ip);
-				if (expiration_time == 0) {
-					ShowMessage(" Validity limit: unlimited.\n");
-				} else {
-					char tmpstr[128];
-					strftime(tmpstr, 24, date_format, localtime(&expiration_time));
-					ShowMessage(" Validity limit: until %s.\n", tmpstr);
-				}
-				ShowMessage(" Memo:   '%s'\n", memo);
-			}
-		  }
-			bytes_to_read = 0;
-			RFIFOSKIP(fd,150 + RFIFOW(fd,148));
-			break;
-
-		default:
-			ShowMessage("Remote administration has been disconnected (unknown packet).\n");
-			ladmin_log("'End of connection, unknown packet.\n");
-			set_eof(fd);
-			return 0;
-		}
-	}
-
-	// if we don't wait new packets, do the prompt
-	prompt();
-
-	return 0;
-}
-
-//------------------------------------
-// Function to connect to login-server
-//------------------------------------
-int Connect_login_server(void)
-{
-	ShowMessage("Attempt to connect to login-server...\n");
-	ladmin_log("Attempt to connect to login-server...\n");
-
-	login_fd = make_connection(login_ip, loginserverport);
-	if (login_fd == -1)
-	{	//Might not be the most elegant way to handle this, but I've never used ladmin so I dunno what else you could do. [Skotlex]
-		ShowMessage("Error: Failed to connect to Login Server\n");
-		exit(EXIT_FAILURE);
-	}
-	session[login_fd]->flag.server = 1;
-	if (passenc == 0) {
-		WFIFOHEAD(login_fd,28);
-		WFIFOW(login_fd,0) = 0x7918; // Request for administation login
-		WFIFOW(login_fd,2) = 0; // no encrypted
-		memcpy(WFIFOP(login_fd,4), loginserveradminpassword, 24);
-		WFIFOSET(login_fd,28);
-		bytes_to_read = 1;
-		ShowMessage("Sending of the password...\n");
-		ladmin_log("Sending of the password...\n");
-	} else {
-		WFIFOHEAD(login_fd,2);
-		WFIFOW(login_fd,0) = 0x791a; // Sending request about the coding key
-		WFIFOSET(login_fd,2);
-		bytes_to_read = 1;
-		ShowMessage("Request about the MD5 key...\n");
-		ladmin_log("Request about the MD5 key...\n");
-	}
-
-	return 0;
-}
-
-// sends a ping packet to login server (will receive pong 0x2718)
-int ping_login_server(int tid, unsigned int tick, int id, intptr data)
-{
-	if (login_fd > 0 && session[login_fd] != NULL)
-	{
-		WFIFOHEAD(login_fd,2);
-		WFIFOW(login_fd,0) = 0x2719;
-		WFIFOSET(login_fd,2);
-	}
-	return 0;
-}
-
-//-----------------------------------
-// Reading general configuration file
-//-----------------------------------
-int ladmin_config_read(const char *cfgName)
-{
-	char line[1024], w1[1024], w2[1024];
-	FILE *fp;
-
-	fp = fopen(cfgName, "r");
-	if (fp == NULL) {
-		ShowMessage("\033[0mConfiguration file (%s) not found.\n", cfgName);
-		return 1;
-	}
-
-	ShowMessage("\033[0m---Start reading of Ladmin configuration file (%s)\n", cfgName);
-	while(fgets(line, sizeof(line), fp))
-	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-
-		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
-			remove_control_chars(w1);
-			remove_control_chars(w2);
-
-			if(strcmpi(w1,"login_ip")==0) {
-				uint32 ipl = host2ip(w2);
-				if (ipl != 0) {
-					ip2str(ipl, loginserverip);
-					ShowMessage("Login server IP address: %s -> %s\n", w2, loginserverip);
-				} else
-					memcpy(loginserverip, w2, 16);
-			} else if (strcmpi(w1, "login_port") == 0) {
-				loginserverport = atoi(w2);
-			} else if (strcmpi(w1, "admin_pass") == 0) {
-				strncpy(loginserveradminpassword, w2, sizeof(loginserveradminpassword));
-				loginserveradminpassword[sizeof(loginserveradminpassword)-1] = '\0';
-			} else if (strcmpi(w1, "passenc") == 0) {
-				passenc = atoi(w2);
-				if (passenc < 0 || passenc > 2)
-					passenc = 0;
-			} else if (strcmpi(w1, "ladmin_log_filename") == 0) {
-				strncpy(ladmin_log_filename, w2, sizeof(ladmin_log_filename));
-				ladmin_log_filename[sizeof(ladmin_log_filename)-1] = '\0';
-			} else if (strcmpi(w1, "date_format") == 0) {
-				strncpy(date_format, w2, sizeof(date_format));
-			} else if(strcmpi(w1,"stdout_with_ansisequence") == 0) {
-				stdout_with_ansisequence = config_switch(w2);
-			} else if (strcmpi(w1, "import") == 0) {
-				ladmin_config_read(w2);
-			}
-		}
-	}
-	fclose(fp);
-
-	login_ip = str2ip(loginserverip);
-
-	ShowMessage("---End reading of Ladmin configuration file.\n");
-
-	return 0;
-}
-
-//------------------------------
-// Function called when the server
-// has received a crash signal.
-//------------------------------
-void do_abort(void)
-{
-}
-
-//--------------------------------------
-// Function called at exit of the server
-//--------------------------------------
-void do_final(void)
-{
-	if (already_exit_function == 0) {
-
-		ShowMessage("\033[0m----End of Ladmin (normal end with closing of all files).\n");
-		ladmin_log("----End of Ladmin (normal end with closing of all files).\n");
-
-		already_exit_function = 1;
-		do_close(login_fd);
-	}
-}
-
-//------------------------
-// Main function of ladmin
-//------------------------
-int do_init(int argc, char **argv)
-{
-	int next;
-	socket_init();
-
-	// read ladmin configuration
-	ladmin_config_read((argc > 1) ? argv[1] : LADMIN_CONF_NAME);
-
-	ladmin_log("");
-	ladmin_log("Configuration file readed.\n");
-
-	srand(time(NULL));
-
-	set_defaultparse(parse_fromlogin);
-
-	ShowMessage("EAthena login-server administration tool.\n");
-	ShowMessage("(for eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION);
-
-	ladmin_log("Ladmin is ready.\n");
-	ShowMessage("Ladmin is \033[1;32mready\033[0m.\n\n");
-
-	Connect_login_server();
-
-	// keep the char-login connection alive
-	add_timer_func_list(ping_login_server, "ping_login_server");
-	add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
-
-	// minimalist core doesn't have sockets parsing,
-	// so we have to do this ourselves
-	while (runflag) {
-		next = do_timer(gettick_nocache());
-		do_sockets(next);
-	}
-
-	return 0;
-}

+ 0 - 9
src/ladmin/ladmin.h

@@ -1,9 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#ifndef _LADMIN_H_
-#define _LADMIN_H_
-
-#define LADMIN_CONF_NAME	"conf/ladmin_athena.conf"
-
-#endif /* _LADMIN_H_ */

+ 1 - 1
src/login/Makefile.in

@@ -13,7 +13,7 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h
 COMMON_SQL_OBJ = ../common/obj_sql/sql.o
 COMMON_SQL_H = ../common/sql.h
 
-LOGIN_OBJ = login.o admin.o
+LOGIN_OBJ = login.o
 LOGIN_TXT_OBJ = $(LOGIN_OBJ:%=obj_txt/%) \
 	obj_txt/account_txt.o obj_txt/ipban_txt.o obj_txt/loginlog_txt.o
 LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) \

+ 2 - 1
src/login/account.h

@@ -41,7 +41,7 @@ AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_4)(void);
 struct mmo_account
 {
 	int account_id;
-	char userid[24];
+	char userid[NAME_LENGTH];
 	char pass[32+1];        // 23+1 for plaintext, 32+1 for md5-ed passwords
 	char sex;               // gender (M/F/S)
 	char email[40];         // e-mail (by default: a@a.com)
@@ -52,6 +52,7 @@ struct mmo_account
 	unsigned int logincount;// number of successful auth attempts
 	char lastlogin[24];     // date+time of last successful login
 	char last_ip[16];       // save of last IP of connection
+	char birthdate[10+1];   // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00)
 	int account_reg2_num;
 	struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
 };

+ 6 - 3
src/login/account_sql.c

@@ -522,7 +522,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
 
 	// retrieve login entry for the specified account
 	if( SQL_ERROR == Sql_Query(sql_handle,
-	    "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`level`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip` FROM `%s` WHERE `account_id` = %d",
+	    "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`level`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d",
 		db->account_db, account_id )
 	) {
 		Sql_ShowDebug(sql_handle);
@@ -547,6 +547,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
 	Sql_GetData(sql_handle,  9, &data, NULL); acc->logincount = strtoul(data, NULL, 10);
 	Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
 	Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
+	Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate));
 
 	Sql_FreeResult(sql_handle);
 
@@ -595,7 +596,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
 	if( is_new )
 	{// insert into account table
 		if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
-			"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `level`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+			"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `level`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
 			db->account_db)
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_INT,    (void*)&acc->account_id,      sizeof(acc->account_id))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
@@ -609,6 +610,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate,       strlen(acc->birthdate))
 		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
 		) {
 			SqlStmt_ShowDebug(stmt);
@@ -617,7 +619,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
 	}
 	else
 	{// update account table
-		if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`level`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
+		if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`level`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->pass,             strlen(acc->pass))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  2, SQLDT_ENUM,   (void*)&acc->sex,             sizeof(acc->sex))
@@ -629,6 +631,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  8, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
 		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate,       strlen(acc->birthdate))
 		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
 		) {
 			SqlStmt_ShowDebug(stmt);

+ 26 - 5
src/login/account_txt.c

@@ -14,7 +14,7 @@
 #include <string.h>
 
 /// global defines
-#define ACCOUNT_TXT_DB_VERSION 20080409
+#define ACCOUNT_TXT_DB_VERSION 20110114
 #define AUTHS_BEFORE_SAVE 10 // flush every 10 saves
 #define AUTH_SAVING_INTERVAL 60000 // flush every 10 minutes
 
@@ -452,10 +452,31 @@ static bool mmo_auth_fromstr(struct mmo_account* a, char* str, unsigned int vers
 	// zero out the destination first
 	memset(a, 0x00, sizeof(struct mmo_account));
 
+	// defaults for older format versions
+	safestrncpy(a->birthdate, "0000-00-00", sizeof(a->birthdate));
+
 	// extract tab-separated columns from line
 	count = sv_split(str, strlen(str), 0, '\t', fields, ARRAYLENGTH(fields), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF));
 
-	if( version == ACCOUNT_TXT_DB_VERSION && count == 13 )
+	if( version == ACCOUNT_TXT_DB_VERSION && count == 14 )
+	{
+		a->account_id = strtol(fields[1], NULL, 10);
+		safestrncpy(a->userid, fields[2], sizeof(a->userid));
+		safestrncpy(a->pass, fields[3], sizeof(a->pass));
+		a->sex = fields[4][0];
+		safestrncpy(a->email, fields[5], sizeof(a->email));
+		a->level = strtoul(fields[6], NULL, 10);
+		a->state = strtoul(fields[7], NULL, 10);
+		a->unban_time = strtol(fields[8], NULL, 10);
+		a->expiration_time = strtol(fields[9], NULL, 10);
+		a->logincount = strtoul(fields[10], NULL, 10);
+		safestrncpy(a->lastlogin, fields[11], sizeof(a->lastlogin));
+		safestrncpy(a->last_ip, fields[12], sizeof(a->last_ip));
+		safestrncpy(a->birthdate, fields[13], sizeof(a->birthdate));
+		regs = fields[14];
+	}
+	else
+	if( version == 20080409 && count == 13 )
 	{
 		a->account_id = strtol(fields[1], NULL, 10);
 		safestrncpy(a->userid, fields[2], sizeof(a->userid));
@@ -558,10 +579,10 @@ static bool mmo_auth_tostr(const struct mmo_account* a, char* str)
 	int i;
 	char* str_p = str;
 
-	str_p += sprintf(str_p, "%d\t%s\t%s\t%c\t%s\t%u\t%u\t%ld\t%ld\t%u\t%s\t%s\t",
+	str_p += sprintf(str_p, "%d\t%s\t%s\t%c\t%s\t%u\t%u\t%ld\t%ld\t%u\t%s\t%s\t%s\t",
 	                 a->account_id, a->userid, a->pass, a->sex, a->email, a->level,
 	                 a->state, (long)a->unban_time, (long)a->expiration_time,
-	                 a->logincount, a->lastlogin, a->last_ip);
+	                 a->logincount, a->lastlogin, a->last_ip, a->birthdate);
 
 	for( i = 0; i < a->account_reg2_num; ++i )
 		if( a->account_reg2[i].str[0] )
@@ -587,7 +608,7 @@ static void mmo_auth_sync(AccountDB_TXT* db)
 	fprintf(fp, "%d\n", ACCOUNT_TXT_DB_VERSION); // savefile version
 
 	fprintf(fp, "// Accounts file: here are saved all information about the accounts.\n");
-	fprintf(fp, "// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, repeated(register key, register value)\n");
+	fprintf(fp, "// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, birth date, repeated(register key, register value)\n");
 	fprintf(fp, "// where:\n");
 	fprintf(fp, "//   sex             : M or F for normal accounts, S for server accounts\n");
 	fprintf(fp, "//   level           : this account's gm level\n");

+ 0 - 857
src/login/admin.c

@@ -1,857 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/core.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/strlib.h"
-#include "../common/showmsg.h"
-#include "../common/version.h"
-#include "../common/md5calc.h"
-#include "../common/lock.h"
-#include "account.h"
-#include "login.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h> // for stat/lstat/fstat
-
-extern AccountDB* accounts;
-
-int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len);
-bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass);
-int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
-int parse_admin(int fd);
-
-
-bool ladmin_auth(struct login_session_data* sd, const char* ip)
-{
-	bool result = false;
-
-	if( str2ip(ip) != host2ip(login_config.admin_allowed_host) )
-		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - IP isn't authorised (ip: %s).\n", ip);
-	else
-	if( !login_config.admin_state )
-		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (ip: %s)\n", ip);
-	else
-	if( !check_password(sd->md5key, sd->passwdenc, sd->passwd, login_config.admin_pass) )
-		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - invalid password (ip: %s)\n", ip);
-	else
-	{
-		ShowNotice("'ladmin'-login: Connection in administration mode accepted (ip: %s)\n", ip);
-		session[sd->fd]->func_parse = parse_admin;
-		result = true;
-	}
-
-	return result;
-}
-
-//---------------------------------------
-// Packet parsing for administation login
-//
-// List of supported operations:
-// 0x7530 - request server version (response: 0x7531)
-// 0x7938 - request server list (response: 0x7939)
-// 0x7920 - request entire list of accounts (response: 0x7921)
-// 0x794e - request message broadcast (response: 0x794f + 0x2726)
-
-// 0x7930 - request account creation (response: 0x7931)
-// 0x7932 - request account deletion (response: 0x7933 + 0x2730)
-
-// 0x7934 - request account password modification (response: 0x7935)
-// 0x7936 - request account state modification (response: 0x7937 + 0x2731)
-// 0x793a - request password check (response: 0x793b)
-// 0x793c - request account sex modification (response: 0x793d + 0x2723)
-// 0x793e - request account gm-level modification (response: 0x793f)
-// 0x7940 - request account email modification (response: 0x7941)
-// 0x7942 - request account memo modification (response: 0x7943)
-// 0x7948 - request account expiration-time modification - absolute (response: 0x7949)
-// 0x7950 - request account expiration-time modification - relative (response: 0x7951)
-// 0x794a - request account unban-time modification - absolute (response: 0x794b + 0x2731)
-// 0x794c - request account unban-time modification - relative (response: 0x794d + 0x2731)
-
-// 0x7944 - request account id lookup by name (response: 0x7945)
-// 0x7946 - request account name lookup by id (response: 0x7947)
-// 0x7952 - request account information lookup by name (response: 0x7953)
-// 0x7954 - request account information lookup by id (response: 0x7953)
-//---------------------------------------
-int parse_admin(int fd)
-{
-	char* account_name;
-
-	uint32 ipl = session[fd]->client_addr;
-	char ip[16];
-	ip2str(ipl, ip);
-
-	if( session[fd]->flag.eof )
-	{
-		do_close(fd);
-		ShowInfo("Remote administration has disconnected (session #%d).\n", fd);
-		return 0;
-	}
-
-	while( RFIFOREST(fd) >= 2 )
-	{
-		uint16 command = RFIFOW(fd,0);
-
-		switch( command )
-		{
-		
-		case 0x7530:	// Request of the server version
-			ShowStatus("'ladmin': Sending of the server version (ip: %s)\n", ip);
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x7531;
-			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
-			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
-			WFIFOB(fd,4) = ATHENA_REVISION;
-			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
-			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
-			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
-			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
-			WFIFOSET(fd,10);
-			RFIFOSKIP(fd,2);
-			break;
-/*
-		case 0x7920:	// Request of an accounts list
-			if (RFIFOREST(fd) < 10)
-				return 0;
-			{
-				int st, ed;
-				uint16 len;
-				CREATE_BUFFER(id, int, auth_num);
-				st = RFIFOL(fd,2);
-				ed = RFIFOL(fd,6);
-				RFIFOSKIP(fd,10);
-				WFIFOW(fd,0) = 0x7921;
-				if (st < 0)
-					st = 0;
-				if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
-					ed = END_ACCOUNT_NUM;
-				ShowStatus("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n", st, ed, ip);
-				// Sort before send
-				for(i = 0; i < auth_num; i++) {
-					unsigned int k;
-					id[i] = i;
-					for(j = 0; j < i; j++) {
-						if (auth_dat[id[i]].account_id < auth_dat[id[j]].account_id) {
-							for(k = i; k > j; k--) {
-								id[k] = id[k-1];
-							}
-							id[j] = i; // id[i]
-							break;
-						}
-					}
-				}
-				// Sending accounts information
-				len = 4;
-				for(i = 0; i < auth_num && len < 30000; i++) {
-					int account_id = auth_dat[id[i]].account_id; // use sorted index
-					if (account_id >= st && account_id <= ed) {
-						j = id[i];
-						WFIFOL(fd,len) = account_id;
-						WFIFOB(fd,len+4) = (unsigned char)isGM(account_id);
-						memcpy(WFIFOP(fd,len+5), auth_dat[j].userid, 24);
-						WFIFOB(fd,len+29) = auth_dat[j].sex;
-						WFIFOL(fd,len+30) = auth_dat[j].logincount;
-						if (auth_dat[j].state == 0 && auth_dat[j].unban_time != 0) // if no state and banished
-							WFIFOL(fd,len+34) = 7; // 6 = Your are Prohibited to log in until %s
-						else
-							WFIFOL(fd,len+34) = auth_dat[j].state;
-						len += 38;
-					}
-				}
-				WFIFOW(fd,2) = len;
-				WFIFOSET(fd,len);
-				//if (id) free(id);
-				DELETE_BUFFER(id);
-			}
-			break;
-*/
-		case 0x7930:	// Request for an account creation
-			if (RFIFOREST(fd) < 91)
-				return 0;
-		{
-			struct mmo_account ma;
-			safestrncpy(ma.userid, (char*)RFIFOP(fd, 2), sizeof(ma.userid));
-			safestrncpy(ma.pass, (char*)RFIFOP(fd,26), sizeof(ma.pass));
-			ma.sex = RFIFOB(fd,50);
-			safestrncpy(ma.email, (char*)RFIFOP(fd,51), sizeof(ma.email));
-			safestrncpy(ma.lastlogin, "-", sizeof(ma.lastlogin));
-
-			ShowNotice("'ladmin': Account creation request (account: %s pass: %s, sex: %c, email: %s, ip: %s)\n", ma.userid, ma.pass, ma.sex, ma.email, ip);
-
-			WFIFOW(fd,0) = 0x7931;
-			WFIFOL(fd,2) = mmo_auth_new(ma.userid, ma.pass, ma.sex, ip);
-			safestrncpy((char*)WFIFOP(fd,6), ma.userid, 24);
-			WFIFOSET(fd,30);
-		}
-			RFIFOSKIP(fd,91);
-			break;
-/*
-		case 0x7932:	// Request for an account deletion
-			if (RFIFOREST(fd) < 26)
-				return 0;
-		{
-			struct mmo_account acc;
-
-			char* account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-
-			WFIFOW(fd,0) = 0x7933;
-
-			if( accounts->load_str(accounts, &acc, account_name) )
-			{
-				// Char-server is notified of deletion (for characters deletion).
-				unsigned char buf[65535];
-				WBUFW(buf,0) = 0x2730;
-				WBUFL(buf,2) = acc.account_id;
-				charif_sendallwos(-1, buf, 6);
-
-				// send answer
-				memcpy(WFIFOP(fd,6), acc.userid, 24);
-				WFIFOL(fd,2) = acc.account_id;
-
-				// delete account
-				memset(acc.userid, '\0', sizeof(acc.userid));
-				auth_dat[i].account_id = -1;
-				mmo_auth_sync();
-			} else {
-				WFIFOL(fd,2) = -1;
-				memcpy(WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", account_name, ip);
-			}
-			WFIFOSET(fd,30);
-		}
-			RFIFOSKIP(fd,26);
-			break;
-*/
-		case 0x7934:	// Request to change a password
-			if (RFIFOREST(fd) < 50)
-				return 0;
-		{
-			struct mmo_account acc;
-
-			char* account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-
-			WFIFOW(fd,0) = 0x7935;
-
-			if( accounts->load_str(accounts, &acc, account_name) )
-			{
-				WFIFOL(fd,2) = acc.account_id;
-				safestrncpy((char*)WFIFOP(fd,6), acc.userid, 24);
-				safestrncpy(acc.pass, (char*)RFIFOP(fd,26), 24);
-				ShowNotice("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", acc.userid, acc.pass, ip);
-
-				accounts->save(accounts, &acc);
-			}
-			else
-			{
-				WFIFOL(fd,2) = -1;
-				safestrncpy((char*)WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-			}
-
-			WFIFOSET(fd,30);
-		}
-			RFIFOSKIP(fd,50);
-			break;
-
-		case 0x7936:	// Request to modify a state
-			if (RFIFOREST(fd) < 50)
-				return 0;
-		{
-			struct mmo_account acc;
-
-			char* account_name = (char*)RFIFOP(fd,2);
-			uint32 state = RFIFOL(fd,26);
-			account_name[23] = '\0';
-
-			WFIFOW(fd,0) = 0x7937;
-
-			if( accounts->load_str(accounts, &acc, account_name) )
-			{
-				memcpy(WFIFOP(fd,6), acc.userid, 24);
-				WFIFOL(fd,2) = acc.account_id;
-
-				if (acc.state == state)
-					ShowNotice("'ladmin': Modification of a state, but the state of the account already has this value (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
-				else
-				{
-					ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", acc.userid, state, ip);
-
-					if (acc.state == 0) {
-						unsigned char buf[16];
-						WBUFW(buf,0) = 0x2731;
-						WBUFL(buf,2) = acc.account_id;
-						WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
-						WBUFL(buf,7) = state; // status or final date of a banishment
-						charif_sendallwos(-1, buf, 11);
-					}
-					acc.state = state;
-					accounts->save(accounts, &acc);
-				}
-			}
-			else
-			{
-				ShowNotice("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
-				WFIFOL(fd,2) = -1;
-				memcpy(WFIFOP(fd,6), account_name, 24);
-			}
-
-			WFIFOL(fd,30) = state;
-			WFIFOSET(fd,34);
-		}
-			RFIFOSKIP(fd,50);
-			break;
-/*
-		case 0x7938:	// Request for servers list and # of online players
-		{		
-			uint8 server_num = 0;
-			ShowStatus("'ladmin': Sending of servers list (ip: %s)\n", ip);
-			for(i = 0; i < MAX_SERVERS; i++) {
-				if (server[i].fd >= 0) {
-					WFIFOL(fd,4+server_num*32) = htonl(server[i].ip);
-					WFIFOW(fd,4+server_num*32+4) = htons(server[i].port);
-					memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20);
-					WFIFOW(fd,4+server_num*32+26) = server[i].users;
-					WFIFOW(fd,4+server_num*32+28) = server[i].maintenance;
-					WFIFOW(fd,4+server_num*32+30) = server[i].new_;
-					server_num++;
-				}
-			}
-			WFIFOW(fd,0) = 0x7939;
-			WFIFOW(fd,2) = 4 + 32 * server_num;
-			WFIFOSET(fd,4+32*server_num);
-			RFIFOSKIP(fd,2);
-			break;
-		}
-
-		case 0x793a:	// Request to password check
-			if (RFIFOREST(fd) < 50)
-				return 0;
-			WFIFOW(fd,0) = 0x793b;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			if( accounts->load_str(accounts, &acc, account_name) )
-			{
-				char pass[25];
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				memcpy(pass, RFIFOP(fd,26), 24);
-				pass[24] = '\0';
-				remove_control_chars(pass);
-				if (strcmp(acc.pass, pass) == 0) {
-					WFIFOL(fd,2) = acc.account_id;
-					ShowNotice("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", acc.userid, acc.pass, ip);
-				} else {
-					ShowNotice("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", acc.userid, pass, ip);
-				}
-			} else {
-				memcpy(WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,50);
-			break;
-
-		case 0x793c:	// Request to modify sex
-			if (RFIFOREST(fd) < 27)
-				return 0;
-			WFIFOW(fd,0) = 0x793d;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			memcpy(WFIFOP(fd,6), account_name, 24);
-			{
-				char sex;
-				sex = RFIFOB(fd,26);
-				if (sex != 'F' && sex != 'M') {
-					if (sex > 31)
-						ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
-					else
-						ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n", account_name, ip);
-				} else {
-					if( accounts->load_str(accounts, &acc, account_name) )
-					{
-						memcpy(WFIFOP(fd,6), acc.userid, 24);
-						if (acc.sex != sex)
-						{
-							unsigned char buf[16];
-							ShowNotice("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", acc.userid, sex, ip);
-
-							WFIFOL(fd,2) = acc.account_id;
-							acc.sex = sex;
-							accounts->save(accounts, &acc);
-
-							// send to all char-server the change
-							WBUFW(buf,0) = 0x2723;
-							WBUFL(buf,2) = acc.account_id;
-							WBUFB(buf,6) = acc.sex;
-							charif_sendallwos(-1, buf, 7);
-						} else {
-							ShowNotice("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", acc.userid, sex, ip);
-						}
-					} else {
-						ShowNotice("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
-					}
-				}
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,27);
-			break;
-
-		case 0x793e:	// Request to modify GM level
-			if (RFIFOREST(fd) < 27)
-				return 0;
-			WFIFOW(fd,0) = 0x793f;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			memcpy(WFIFOP(fd,6), account_name, 24);
-		{
-			char new_gm_level;
-			new_gm_level = RFIFOB(fd,26);
-			if( new_gm_level < 0 || new_gm_level > 99 )
-				ShowNotice("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
-			else
-			if( !accounts->load_str(accounts, &acc, account_name) )
-				ShowNotice("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
-			else
-			{
-				memcpy(WFIFOP(fd,6), acc.userid, 24);
-
-				if (isGM(acc.account_id) == new_gm_level)
-					ShowNotice("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", acc.userid, acc.account_id, (int)new_gm_level, ip);
-				else
-				{
-					//TODO: change level
-				}
-			}
-		}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,27);
-			break;
-
-		case 0x7940:	// Request to modify e-mail
-			if (RFIFOREST(fd) < 66)
-				return 0;
-			WFIFOW(fd,0) = 0x7941;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			memcpy(WFIFOP(fd,6), account_name, 24);
-			{
-				char email[40];
-				memcpy(email, RFIFOP(fd,26), 40);
-				if (e_mail_check(email) == 0) {
-					ShowNotice("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", account_name, ip);
-				} else {
-					remove_control_chars(email);
-					i = search_account_index(account_name);
-					if (i != -1) {
-						memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-						memcpy(auth_dat[i].email, email, 40);
-						WFIFOL(fd,2) = auth_dat[i].account_id;
-						ShowNotice("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n", auth_dat[i].userid, email, ip);
-						mmo_auth_sync();
-					} else {
-						ShowNotice("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n", account_name, email, ip);
-					}
-				}
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,66);
-			break;
-
-		case 0x7942:	// Request to modify memo field
-			if ((int)RFIFOREST(fd) < 28 || (int)RFIFOREST(fd) < (28 + RFIFOW(fd,26)))
-				return 0;
-			WFIFOW(fd,0) = 0x7943;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
-				int size_of_memo = sizeof(auth_dat[i].memo);
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				memset(auth_dat[i].memo, '\0', size_of_memo);
-				if (RFIFOW(fd,26) == 0) {
-					strncpy(auth_dat[i].memo, "-", size_of_memo);
-				} else if (RFIFOW(fd,26) > size_of_memo - 1) {
-					memcpy(auth_dat[i].memo, RFIFOP(fd,28), size_of_memo - 1);
-				} else {
-					memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26));
-				}
-				auth_dat[i].memo[size_of_memo - 1] = '\0';
-				remove_control_chars(auth_dat[i].memo);
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				ShowNotice("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].memo, ip);
-				mmo_auth_sync();
-			} else {
-				memcpy(WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,28 + RFIFOW(fd,26));
-			break;
-
-		case 0x7944:	// Request to found an account id
-			if (RFIFOREST(fd) < 26)
-				return 0;
-			WFIFOW(fd,0) = 0x7945;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				ShowNotice("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
-			} else {
-				memcpy(WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,26);
-			break;
-
-		case 0x7946:	// Request to found an account name
-			if (RFIFOREST(fd) < 6)
-				return 0;
-			WFIFOW(fd,0) = 0x7947;
-			WFIFOL(fd,2) = RFIFOL(fd,2);
-			memset(WFIFOP(fd,6), '\0', 24);
-			for(i = 0; i < auth_num; i++) {
-				if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) {
-					strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24);
-					ShowNotice("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, RFIFOL(fd,2), ip);
-					break;
-				}
-			}
-			if (i == auth_num) {
-				ShowNotice("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd,2), ip);
-				strncpy((char*)WFIFOP(fd,6), "", 24);
-			}
-			WFIFOSET(fd,30);
-			RFIFOSKIP(fd,6);
-			break;
-
-		case 0x7948:	// Request to change the validity limit (timestamp) (absolute value)
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			{
-				time_t timestamp;
-				char tmpstr[2048];
-				WFIFOW(fd,0) = 0x7949;
-				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-				account_name = (char*)RFIFOP(fd,2);
-				account_name[23] = '\0';
-				remove_control_chars(account_name);
-				timestamp = (time_t)RFIFOL(fd,26);
-				strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
-				i = search_account_index(account_name);
-				if (i != -1) {
-					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-					ShowNotice("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
-					auth_dat[i].expiration_time = timestamp;
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					mmo_auth_sync();
-				} else {
-					memcpy(WFIFOP(fd,6), account_name, 24);
-					ShowNotice("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
-				}
-				WFIFOL(fd,30) = (unsigned int)timestamp;
-			}
-			WFIFOSET(fd,34);
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x794a:	// Request to change the final date of a banishment (timestamp) (absolute value)
-			if (RFIFOREST(fd) < 30)
-				return 0;
-			{
-				time_t timestamp;
-				char tmpstr[2048];
-				WFIFOW(fd,0) = 0x794b;
-				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-				account_name = (char*)RFIFOP(fd,2);
-				account_name[23] = '\0';
-				remove_control_chars(account_name);
-				timestamp = (time_t)RFIFOL(fd,26);
-				if (timestamp <= time(NULL))
-					timestamp = 0;
-				strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
-				i = search_account_index(account_name);
-				if (i != -1) {
-					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					ShowNotice("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
-					if (auth_dat[i].unban_time != timestamp) {
-						if (timestamp != 0) {
-							unsigned char buf[16];
-							WBUFW(buf,0) = 0x2731;
-							WBUFL(buf,2) = auth_dat[i].account_id;
-							WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
-							WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
-							charif_sendallwos(-1, buf, 11);
-						}
-						auth_dat[i].unban_time = timestamp;
-						mmo_auth_sync();
-					}
-				} else {
-					memcpy(WFIFOP(fd,6), account_name, 24);
-					ShowNotice("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
-				}
-				WFIFOL(fd,30) = (unsigned int)timestamp;
-			}
-			WFIFOSET(fd,34);
-			RFIFOSKIP(fd,30);
-			break;
-
-		case 0x794c:	// Request to change the final date of a banishment (timestamp) (relative change)
-			if (RFIFOREST(fd) < 38)
-				return 0;
-			{
-				time_t timestamp;
-				struct tm *tmtime;
-				char tmpstr[2048];
-				WFIFOW(fd,0) = 0x794d;
-				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-				account_name = (char*)RFIFOP(fd,2);
-				account_name[23] = '\0';
-				remove_control_chars(account_name);
-				i = search_account_index(account_name);
-				if (i != -1) {
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-					if (auth_dat[i].unban_time == 0 || auth_dat[i].unban_time < time(NULL))
-						timestamp = time(NULL);
-					else
-						timestamp = auth_dat[i].unban_time;
-					tmtime = localtime(&timestamp);
-					tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
-					tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
-					tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
-					tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
-					tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
-					tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
-					timestamp = mktime(tmtime);
-					if (timestamp != -1) {
-						if (timestamp <= time(NULL))
-							timestamp = 0;
-						strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
-						ShowNotice("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
-						if (auth_dat[i].unban_time != timestamp) {
-							if (timestamp != 0) {
-								unsigned char buf[16];
-								WBUFW(buf,0) = 0x2731;
-								WBUFL(buf,2) = auth_dat[i].account_id;
-								WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
-								WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
-								charif_sendallwos(-1, buf, 11);
-							}
-							auth_dat[i].unban_time = timestamp;
-							mmo_auth_sync();
-						}
-					} else {
-						strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].unban_time));
-						ShowNotice("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].unban_time, (auth_dat[i].unban_time == 0 ? "no banishment" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
-					}
-					WFIFOL(fd,30) = (unsigned long)auth_dat[i].unban_time;
-				} else {
-					memcpy(WFIFOP(fd,6), account_name, 24);
-					ShowNotice("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-					WFIFOL(fd,30) = 0;
-				}
-			}
-			WFIFOSET(fd,34);
-			RFIFOSKIP(fd,38);
-			break;
-
-		case 0x794e:	// Request to send a broadcast message
-			if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4)))
-				return 0;
-			WFIFOW(fd,0) = 0x794f;
-			WFIFOW(fd,2) = 0xFFFF; // WTF???
-			if (RFIFOL(fd,4) < 1) {
-				ShowNotice("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n", ip);
-			} else {
-				// at least 1 char-server
-				for(i = 0; i < MAX_SERVERS; i++)
-					if (server[i].fd >= 0)
-						break;
-				if (i == MAX_SERVERS) {
-					ShowNotice("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n", ip);
-				} else {
-					unsigned char buf[32000];
-					char message[32000];
-					WFIFOW(fd,2) = 0;
-					memset(message, '\0', sizeof(message));
-					memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4));
-					message[sizeof(message)-1] = '\0';
-					remove_control_chars(message);
-					if (RFIFOW(fd,2) == 0)
-						ShowNotice("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n", message, ip);
-					else
-						ShowNotice("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n", message, ip);
-					// send same message to all char-servers (no answer)
-					memcpy(WBUFP(buf,0), RFIFOP(fd,0), 8 + RFIFOL(fd,4));
-					WBUFW(buf,0) = 0x2726;
-					charif_sendallwos(-1, buf, 8 + RFIFOL(fd,4));
-				}
-			}
-			WFIFOSET(fd,4);
-			RFIFOSKIP(fd,8 + RFIFOL(fd,4));
-			break;
-
-		case 0x7950:	// Request to change the validity limite (timestamp) (relative change)
-			if (RFIFOREST(fd) < 38)
-				return 0;
-		{
-			time_t timestamp;
-			struct tm *tmtime;
-			char tmpstr[2048];
-			char tmpstr2[2048];
-			WFIFOW(fd,0) = 0x7951;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				timestamp = auth_dat[i].expiration_time;
-				if (timestamp == 0 || timestamp < time(NULL))
-					timestamp = time(NULL);
-				tmtime = localtime(&timestamp);
-				tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
-				tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
-				tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
-				tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
-				tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
-				tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
-				timestamp = mktime(tmtime);
-				if (timestamp != -1) {
-					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
-					strftime(tmpstr2, 24, login_config.date_format, localtime(&timestamp));
-					ShowNotice("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
-					auth_dat[i].expiration_time = timestamp;
-					mmo_auth_sync();
-					WFIFOL(fd,30) = (unsigned long)auth_dat[i].expiration_time;
-				} else {
-					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
-					ShowNotice("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
-					WFIFOL(fd,30) = 0;
-				}
-			} else {
-				memcpy(WFIFOP(fd,6), account_name, 24);
-				ShowNotice("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-				WFIFOL(fd,30) = 0;
-			}
-
-			WFIFOSET(fd,34);
-		}
-			RFIFOSKIP(fd,38);
-			break;
-*/
-		case 0x7952:	// Request about informations of an account (by account name)
-			if (RFIFOREST(fd) < 26)
-				return 0;
-		{
-			struct mmo_account acc;
-
-			WFIFOW(fd,0) = 0x7953;
-
-			account_name = (char*)RFIFOP(fd,2);
-			account_name[23] = '\0';
-
-			if( accounts->load_str(accounts, &acc, account_name) )
-			{
-				ShowNotice("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", acc.userid, acc.account_id, ip);
-				WFIFOL(fd,2) = acc.account_id;
-				WFIFOB(fd,6) = acc.level;
-				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
-				WFIFOB(fd,31) = acc.sex;
-				WFIFOL(fd,32) = acc.logincount;
-				WFIFOL(fd,36) = acc.state;
-				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
-				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
-				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
-				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
-				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
-				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
-				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
-			}
-			else
-			{
-				ShowNotice("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-				WFIFOL(fd,2) = -1;
-				safestrncpy((char*)WFIFOP(fd,7), account_name, 24); // not found
-			}
-
-			WFIFOSET(fd,150);
-		}
-			RFIFOSKIP(fd,26);
-			break;
-
-		case 0x7954:	// Request about information of an account (by account id)
-			if (RFIFOREST(fd) < 6)
-				return 0;
-		{
-			struct mmo_account acc;
-
-			int account_id = RFIFOL(fd,2);
-
-			WFIFOHEAD(fd,150);
-			WFIFOW(fd,0) = 0x7953;
-			WFIFOL(fd,2) = account_id;
-
-			if( accounts->load_num(accounts, &acc, account_id) )
-			{
-				ShowNotice("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", acc.userid, account_id, ip);
-				WFIFOB(fd,6) = acc.level;
-				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
-				WFIFOB(fd,31) = acc.sex;
-				WFIFOL(fd,32) = acc.logincount;
-				WFIFOL(fd,36) = acc.state;
-				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
-				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
-				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
-				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
-				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
-				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
-				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
-			}
-			else
-			{
-				ShowNotice("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", account_id, ip);
-				safestrncpy((char*)WFIFOP(fd,7), "", 24); // not found
-			}
-
-			WFIFOSET(fd,150);
-		}
-			RFIFOSKIP(fd,6);
-			break;
-
-		default:
-			ShowStatus("'ladmin': End of connection, unknown packet (ip: %s)\n", ip);
-			set_eof(fd);
-			return 0;
-		}
-	}
-	RFIFOSKIP(fd,RFIFOREST(fd));
-	return 0;
-}

+ 51 - 85
src/login/login.c

@@ -19,7 +19,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-bool ladmin_auth(struct login_session_data* sd, const char* ip);
 struct Login_Config login_config;
 
 int login_fd; // login server socket
@@ -70,6 +69,7 @@ struct s_subnet {
 
 int subnet_count = 0;
 
+int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
 
 //-----------------------------------------------------
 // Auth database
@@ -109,7 +109,7 @@ static void* create_online_user(DBKey key, va_list args)
 	CREATE(p, struct online_login_data, 1);
 	p->account_id = key.i;
 	p->char_server = -1;
-	p->waiting_disconnect = -1;
+	p->waiting_disconnect = INVALID_TIMER;
 	return p;
 }
 
@@ -118,10 +118,10 @@ struct online_login_data* add_online_user(int char_server, int account_id)
 	struct online_login_data* p;
 	p = (struct online_login_data*)idb_ensure(online_db, account_id, create_online_user);
 	p->char_server = char_server;
-	if( p->waiting_disconnect != -1 )
+	if( p->waiting_disconnect != INVALID_TIMER )
 	{
 		delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-		p->waiting_disconnect = -1;
+		p->waiting_disconnect = INVALID_TIMER;
 	}
 	return p;
 }
@@ -132,7 +132,7 @@ void remove_online_user(int account_id)
 	p = (struct online_login_data*)idb_get(online_db, account_id);
 	if( p == NULL )
 		return;
-	if( p->waiting_disconnect != -1 )
+	if( p->waiting_disconnect != INVALID_TIMER )
 		delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
 
 	idb_remove(online_db, account_id);
@@ -143,7 +143,7 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr d
 	struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
 	if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
 	{
-		p->waiting_disconnect = -1;
+		p->waiting_disconnect = INVALID_TIMER;
 		remove_online_user(id);
 		idb_remove(auth_db, id);
 	}
@@ -157,10 +157,10 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
 	if( server == -1 )
 	{
 		p->char_server = -1;
-		if( p->waiting_disconnect != -1 )
+		if( p->waiting_disconnect != INVALID_TIMER )
 		{
 			delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-			p->waiting_disconnect = -1;
+			p->waiting_disconnect = INVALID_TIMER;
 		}
 	}
 	else if( p->char_server == server )
@@ -323,32 +323,49 @@ int login_lan_config_read(const char *lancfgName)
 //-----------------------
 // Console Command Parser [Wizputer]
 //-----------------------
-int parse_console(char* buf)
+int parse_console(const char* command)
 {
-	char command[256];
+	ShowNotice("Console command: %s\n", command);
 
-	memset(command, 0, sizeof(command));
-
-	sscanf(buf, "%[^\n]", command);
-
-	ShowInfo("Console command :%s", command);
-
-	if( strcmpi("shutdown", command) == 0 ||
-	    strcmpi("exit", command) == 0 ||
-	    strcmpi("quit", command) == 0 ||
-	    strcmpi("end", command) == 0 )
+	if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 )
 		runflag = 0;
-	else
-	if( strcmpi("alive", command) == 0 ||
-	    strcmpi("status", command) == 0 )
+	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("help", command) == 0 ) {
-		ShowInfo(CL_BOLD"Help of commands:"CL_RESET"\n");
-		ShowInfo("  To shutdown the server:\n");
+	else if( strcmpi("help", command) == 0 )
+	{
+		ShowInfo("To shutdown the server:\n");
 		ShowInfo("  'shutdown|exit|quit|end'\n");
-		ShowInfo("  To know if server is alive:\n");
+		ShowInfo("To know if server is alive:\n");
 		ShowInfo("  'alive|status'\n");
+		ShowInfo("To create a new account:\n");
+		ShowInfo("  'create'\n");
+	}
+	else
+	{// commands with parameters
+		char cmd[128], params[256];
+
+		if( sscanf(command, "%127s %255[^\r\n]", cmd, params) < 2 )
+		{
+			return 0;
+		}
+
+		if( strcmpi(cmd, "create") == 0 )
+		{
+			char username[NAME_LENGTH], password[NAME_LENGTH], sex;
+
+			if( sscanf(params, "%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", cmd, cmd);
+				return 0;
+			}
+
+			if( mmo_auth_new(username, password, TOUPPER(sex), "0.0.0.0") != -1 )
+			{
+				ShowError("Console: Account creation failed.\n");
+				return 0;
+			}
+			ShowStatus("Console: Account '%s' created successfully.\n", username);
+		}
 	}
 
 	return 0;
@@ -524,8 +541,6 @@ int parse_fromchar(int fd)
 		break;
 
 		case 0x2719: // ping request from charserver
-			if( RFIFOREST(fd) < 2 )
-				return 0;
 			RFIFOSKIP(fd,2);
 
 			WFIFOHEAD(fd,2);
@@ -733,8 +748,8 @@ int parse_fromchar(int fd)
 				// Sending information towards the other char-servers.
 				RFIFOW(fd,0) = 0x2729;// reusing read buffer
 				charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
-				RFIFOSKIP(fd,RFIFOW(fd,2));
 			}
+			RFIFOSKIP(fd,RFIFOW(fd,2));
 		}
 		break;
 
@@ -788,10 +803,10 @@ int parse_fromchar(int fd)
 					aid = RFIFOL(fd,6+i*4);
 					p = (struct online_login_data*)idb_ensure(online_db, aid, create_online_user);
 					p->char_server = id;
-					if (p->waiting_disconnect != -1)
+					if (p->waiting_disconnect != INVALID_TIMER)
 					{
 						delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-						p->waiting_disconnect = -1;
+						p->waiting_disconnect = INVALID_TIMER;
 					}
 				}
 			}
@@ -854,7 +869,6 @@ int parse_fromchar(int fd)
 		} // switch
 	} // while
 
-	RFIFOSKIP(fd,RFIFOREST(fd));
 	return 0;
 }
 
@@ -898,6 +912,7 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha
 	acc.expiration_time = ( login_config.start_limited_time != -1 ) ? time(NULL) + login_config.start_limited_time : 0;
 	safestrncpy(acc.lastlogin, "0000-00-00 00:00:00", sizeof(acc.lastlogin));
 	safestrncpy(acc.last_ip, last_ip, sizeof(acc.last_ip));
+	safestrncpy(acc.birthdate, "0000-00-00", sizeof(acc.birthdate));
 
 	if( !accounts->create(accounts, &acc) )
 		return 0;
@@ -1077,7 +1092,7 @@ void login_auth_ok(struct login_session_data* sd)
 				WBUFW(buf,0) = 0x2734;
 				WBUFL(buf,2) = sd->account_id;
 				charif_sendallwos(-1, buf, 6);
-				if( data->waiting_disconnect == -1 )
+				if( data->waiting_disconnect == INVALID_TIMER )
 					data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
 
 				WFIFOHEAD(fd,3);
@@ -1209,7 +1224,7 @@ void login_auth_failed(struct login_session_data* sd, int result)
 
 
 //----------------------------------------------------------------------------------------
-// Default packet parsing (normal players or administation/char-server connection requests)
+// Default packet parsing (normal players or char-server connection requests)
 //----------------------------------------------------------------------------------------
 int parse_login(int fd)
 {
@@ -1343,7 +1358,6 @@ int parse_login(int fd)
 		break;
 
 		case 0x01db:	// Sending request of the coding key
-		case 0x791a:	// Sending request of the coding key (administration packet)
 			RFIFOSKIP(fd,2);
 		{
 			memset(sd->md5key, '\0', sizeof(sd->md5key));
@@ -1419,45 +1433,6 @@ int parse_login(int fd)
 		}
 		return 0; // processing will continue elsewhere
 
-		case 0x7530:	// Server version information request
-			ShowStatus("Sending server version information to ip: %s\n", ip);
-			RFIFOSKIP(fd,2);
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x7531;
-			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
-			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
-			WFIFOB(fd,4) = ATHENA_REVISION;
-			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
-			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
-			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
-			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
-			WFIFOSET(fd,10);
-		break;
-
-		case 0x7918:	// Request for administation login
-			if ((int)RFIFOREST(fd) < 4 || (int)RFIFOREST(fd) < ((RFIFOW(fd,2) == 0) ? 28 : 20))
-				return 0;
-		{
-			int passwdenc = (int)RFIFOW(fd,2);
-			const char* passwd = (char*)RFIFOP(fd,4);
-
-			if( passwdenc == 0 ) { // non encrypted password
-				safestrncpy(sd->passwd, passwd, NAME_LENGTH);
-				sd->passwdenc = 0;
-			} else { // encrypted password
-				memcpy(sd->passwd, passwd, 16); sd->passwd[16] = '\0'; // raw binary data here!
-				sd->passwdenc = passwdenc;
-			}
-
-			RFIFOSKIP(fd, (passwdenc == 0) ? 28 : 20);
-
-			WFIFOHEAD(fd,3);
-			WFIFOW(fd,0) = 0x7919;
-			WFIFOB(fd,2) = ladmin_auth(sd, ip) ? 0 : 1;
-			WFIFOSET(fd,3);
-		}
-		break;
-
 		default:
 			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
 			set_eof(fd);
@@ -1465,7 +1440,6 @@ int parse_login(int fd)
 		}
 	}
 
-	RFIFOSKIP(fd,RFIFOREST(fd));
 	return 0;
 }
 
@@ -1564,14 +1538,6 @@ int login_config_read(const char* cfgName)
 			login_config.ipban_cleanup_interval = (unsigned int)atoi(w2);
 		else if(!strcmpi(w1, "ip_sync_interval"))
 			login_config.ip_sync_interval = (unsigned int)1000*60*atoi(w2); //w2 comes in minutes.
-
-		else if(!strcmpi(w1, "admin_state"))
-			login_config.admin_state = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "admin_pass"))
-			safestrncpy(login_config.admin_pass, w2, sizeof(login_config.admin_pass));
-		else if(!strcmpi(w1, "admin_allowed_host"))
-			safestrncpy(login_config.admin_allowed_host, w2, sizeof(login_config.admin_pass));
-
 		else if(!strcmpi(w1, "import"))
 			login_config_read(w2);
 		else

+ 0 - 4
src/login/login.h

@@ -60,10 +60,6 @@ struct Login_Config {
 	bool check_client_version;                      // check the clientversion set in the clientinfo ?
 	uint32 client_version_to_connect;               // the client version needed to connect (if checking is enabled)
 
-	bool admin_state;                               // is ladmin support enabled?
-	char admin_pass[24];                            // security password for ladmin
-	char admin_allowed_host[32];                    // host/ip that is allowed to connect as ladmin
-
 	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
 	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
 	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures

+ 26 - 46
src/map/atcommand.c

@@ -1937,7 +1937,7 @@ static int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
 {
 	TBL_PC* sd = (TBL_PC*)bl;
 	clif_pvpset(sd, 0, 0, 2);
-	if (sd->pvp_timer != -1) {
+	if (sd->pvp_timer != INVALID_TIMER) {
 		delete_timer(sd->pvp_timer, pc_calc_pvprank_timer);
 		sd->pvp_timer = INVALID_TIMER;
 	}
@@ -1969,7 +1969,7 @@ ACMD_FUNC(pvpoff)
 static int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
 {
 	TBL_PC* sd = (TBL_PC*)bl;
-	if (sd->pvp_timer == -1) {
+	if (sd->pvp_timer == INVALID_TIMER) {
 		sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0);
 		sd->pvp_rank = 0;
 		sd->pvp_lastusers = 0;
@@ -6095,7 +6095,7 @@ ACMD_FUNC(autoloot)
 }
 
 /*==========================================
- * @autolootitem
+ * @alootid
  *------------------------------------------*/
 ACMD_FUNC(autolootitem)
 {
@@ -6104,9 +6104,9 @@ ACMD_FUNC(autolootitem)
 	if (!message || !*message) {
 		if (sd->state.autolootid) {
 			sd->state.autolootid = 0;
-			clif_displaymessage(fd, "Autolootitem have been turned OFF.");
+			clif_displaymessage(fd, "Autolootitem has been turned OFF.");
 		} else
-			clif_displaymessage(fd, "Please, enter Item name or its ID (usage: @autolootitem <item_name_or_ID>).");
+			clif_displaymessage(fd, "Please, enter item name or it's ID (usage: @alootid <item_name_or_ID>).");
 
 		return -1;
 	}
@@ -6122,7 +6122,7 @@ ACMD_FUNC(autolootitem)
 
 	sd->state.autolootid = item_data->nameid; // Autoloot Activated
 
-	sprintf(atcmd_output, "Autolooting Item: '%s'/'%s' {%d}",
+	sprintf(atcmd_output, "Autolooting item: '%s'/'%s' (%d)",
 		item_data->name, item_data->jname, item_data->nameid);
 	clif_displaymessage(fd, atcmd_output);
 
@@ -6741,7 +6741,7 @@ ACMD_FUNC(unmute)
 	}
 
 	pl_sd->status.manner = 0;
-	status_change_end(&pl_sd->bl,SC_NOCHAT,-1);
+	status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
 	clif_displaymessage(sd->fd,"Player unmuted");
 	
 	return 0;
@@ -6815,7 +6815,7 @@ ACMD_FUNC(mute)
 		sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0);
 	} else {
 		pl_sd->status.manner = 0;
-		status_change_end(&pl_sd->bl,SC_NOCHAT,-1);
+		status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
 	}
 
 	clif_GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0));
@@ -6986,7 +6986,7 @@ ACMD_FUNC(mobinfo)
 		strcpy(atcmd_output, " ");
 		j = 0;
 		for (i = 0; i < MAX_MOB_DROP; i++) {
-			if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_search(mob->dropitem[i].nameid)) == NULL)
+			if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL)
 				continue;
 			if (item_data->slot)
 				sprintf(atcmd_output2, " - %s[%d]  %02.02f%%", item_data->jname, item_data->slot, (float)mob->dropitem[i].p / 100);
@@ -7009,7 +7009,7 @@ ACMD_FUNC(mobinfo)
 			strcpy(atcmd_output, " MVP Items:");
 			j = 0;
 			for (i = 0; i < 3; i++) {
-				if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_search(mob->mvpitem[i].nameid)) == NULL)
+				if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL)
 					continue;
 				if (mob->mvpitem[i].p > 0) {
 					j++;
@@ -7115,19 +7115,18 @@ ACMD_FUNC(homlevel)
 
 	nullpo_retr(-1, sd);
 
-	if (!message || !*message) {
-		clif_displaymessage(fd, "Please, enter a level adjustment: (usage: @homlevel <+/- # of levels>.");
+	if ( !message || !*message || ( level = atoi(message) ) < 1 ) {
+		clif_displaymessage(fd, "Please, enter a level adjustment: (usage: @homlevel <# of levels to level up>.");
 		return -1;
 	}
-		
+
 	if ( !merc_is_hom_active(sd->hd) ) {
 		clif_displaymessage(fd, "You do not have a homunculus.");
 		return -1;
 	}
 
-	level = atoi(message);
 	hd = sd->hd;
-	
+
 	for (i = 1; i <= level && hd->exp_next; i++){
 		hd->homunculus.exp += hd->exp_next;
 		merc_hom_levelup(hd);
@@ -7616,8 +7615,8 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
 		pl_sd->status.manner -= time;
 		if (pl_sd->status.manner < 0)
 			sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0);
-		else if (pl_sd->sc.data[SC_NOCHAT])
-			status_change_end(&pl_sd->bl, SC_NOCHAT, -1);
+		else
+			status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
 	}
 	return 0;
 }
@@ -7964,6 +7963,13 @@ ACMD_FUNC(accept)
 		return 0;
 	}
 
+	if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit )
+	{
+		// "Duel: Limit of players is reached."
+		clif_displaymessage(fd, msg_txt(351));
+		return 0;
+	}
+
 	duel_accept(sd->duel_invite, sd);
 	// "Duel: Invitation has been accepted."
 	clif_displaymessage(fd, msg_txt(361));
@@ -8015,30 +8021,6 @@ ACMD_FUNC(cash)
 	return 0;
 }
 
-/*===================================
- * Away message (@away, @aw) [LuzZza]
- *-----------------------------------*/
-ACMD_FUNC(away)
-{
-	if(strlen(message) > 0) {
-		if(strlen(message) > 128)
-			return -1;
-		strcpy(sd->away_message, message);
-		//"Away automessage has been activated."
-		clif_displaymessage(fd, msg_txt(546));
-	} else {
-		if(strlen(sd->away_message) > 0) {
-			sd->away_message[0] = 0;
-			//"Away automessage has been disabled."
-			clif_displaymessage(fd, msg_txt(547));
-			return 0;
-		}
-		//"Usage: @away,@aw <message>. Enter empty message for disable it."
-		clif_displaymessage(fd, msg_txt(548));
-	}
-	return 0;
-}
-
 // @clone/@slaveclone/@evilclone <playername> [Valaris]
 ACMD_FUNC(clone)
 {
@@ -8323,7 +8305,7 @@ ACMD_FUNC(itemlist)
 		const struct item* it = &items[i];
 		struct item_data* itd;
 
-		if( it->nameid == 0 || (itd = itemdb_search(it->nameid)) == NULL )
+		if( it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL )
 			continue;
 
 		counter += it->amount;
@@ -8406,7 +8388,7 @@ ACMD_FUNC(itemlist)
 			{
 				struct item_data* card;
 
-				if( it->card[j] == 0 || (card = itemdb_search(it->card[j])) == NULL )
+				if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL )
 					continue;
 
 				counter2++;
@@ -8872,8 +8854,6 @@ AtCommandInfo atcommand_info[] = {
 	{ "leave",              1,1,      atcommand_leave },
 	{ "accept",             1,1,      atcommand_accept },
 	{ "reject",             1,1,      atcommand_reject },
-	{ "away",               1,1,      atcommand_away },
-	{ "aw",                 1,1,      atcommand_away },
 	{ "main",               1,1,      atcommand_main },
 	{ "clone",             50,50,     atcommand_clone },
 	{ "slaveclone",        50,50,     atcommand_clone },
@@ -9118,8 +9098,8 @@ int atcommand_config_read(const char* cfgName)
 			}
 			else {
 				p->level2 = atoi(w3);
-				p->level2 = cap_value(p->level2, 0, 100);
 			}
+			p->level2 = cap_value(p->level2, 0, 100);
 		}
 		else
 		if( strcmpi(w1, "import") == 0 )

+ 19 - 19
src/map/battle.c

@@ -160,7 +160,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data)
 	struct block_list *target = map_id2bl(dat->target);
 	if (target && dat && map_id2bl(id) == dat->src && target->prev != NULL && !status_isdead(target) &&
 		target->m == dat->src->m &&
-		(target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == -1) &&
+		(target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) &&
 		check_distance_bl(dat->src, target, dat->distance)) //Check to see if you haven't teleported. [Skotlex]
 	{
 		map_freeblock_lock();
@@ -263,7 +263,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
 		if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
 			damage <<= 1; // double damage
 		if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
-			status_change_end(target,SC_SPIDERWEB,-1);
+			status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
 	}
 	return damage*ratio/100;
 }
@@ -326,7 +326,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 				d->dmg_lv = ATK_BLOCK;
 				return 0;
 			}
-			status_change_end(bl,SC_SAFETYWALL,-1);
+			status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER);
 		}
 
 		if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG )
@@ -381,7 +381,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			//Shouldn't end until Breaker's non-weapon part connects.
 			if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON))
 				if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
-					status_change_end(bl, SC_KAUPE, -1);
+					status_change_end(bl, SC_KAUPE, INVALID_TIMER);
 			return 0;
 		}
 
@@ -395,9 +395,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			}
 			//Both need to be consumed if they are active.
 			if (sce && --(sce->val2) <= 0)
-				status_change_end(bl, SC_UTSUSEMI, -1);
+				status_change_end(bl, SC_UTSUSEMI, INVALID_TIMER);
 			if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0)
-				status_change_end(bl, SC_BUNSINJYUTSU, -1);
+				status_change_end(bl, SC_BUNSINJYUTSU, INVALID_TIMER);
 			return 0;
 		}
 
@@ -408,7 +408,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 				damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries
 
 			if( skill_num != ASC_BREAKER || !(flag&BF_WEAPON) )
-				status_change_end( bl,SC_AETERNA,-1 ); //Shouldn't end until Breaker's non-weapon part connects.
+				status_change_end(bl, SC_AETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects.
 		}
 
 		//Finally damage reductions....
@@ -464,7 +464,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			per /=20; //Uses 20% SP intervals.
 			//SP Cost: 1% + 0.5% per every 20% SP
 			if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
-				status_change_end( bl,SC_ENERGYCOAT,-1 );
+				status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER);
 			//Reduction: 6% + 6% every 20%
 			damage -= damage * 6 * (1+per) / 100;
 		}
@@ -484,7 +484,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0));
 			clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1);
 			if(--(sce->val3)<=0)
-				status_change_end(bl, SC_REJECTSWORD, -1);
+				status_change_end(bl, SC_REJECTSWORD, INVALID_TIMER);
 		}
 
 		//Finally Kyrie because it may, or not, reduce damage to 0.
@@ -497,7 +497,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 				  	damage=-sce->val2;
 			}
 			if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT)
-				status_change_end(bl, SC_KYRIE, -1);
+				status_change_end(bl, SC_KYRIE, INVALID_TIMER);
 		}
 
 		if (!damage) return 0;
@@ -3090,7 +3090,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 	}
 
 	if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2))
-		status_change_end(src,SC_CLOAKING,-1);
+		status_change_end(src, SC_CLOAKING, INVALID_TIMER);
 
 	if( tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1) )
 	{
@@ -3102,7 +3102,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 			int skilllv = tsc->data[SC_AUTOCOUNTER]->val1;
 			clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
 			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
-			status_change_end(target,SC_AUTOCOUNTER,-1);
+			status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
 			skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0);
 			return ATK_NONE;
 		}
@@ -3112,7 +3112,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 	{
 		int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1;
 		int duration = skill_get_time2(MO_BLADESTOP,skilllv);
-		status_change_end(target, SC_BLADESTOP_WAIT, -1);
+		status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
 		if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
 	  	{	//Target locked.
 			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
@@ -3128,7 +3128,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK)
 		{
 			triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
-			status_change_end(src,SC_SKILLRATE_UP,-1);
+			status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
 		}
 		if (rand()%100 < triple_rate)
 			//FIXME: invalid return type!
@@ -3142,7 +3142,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 			int skilllv = sc->data[SC_SACRIFICE]->val1;
 
 			if( --sc->data[SC_SACRIFICE]->val2 <= 0 )
-				status_change_end(src, SC_SACRIFICE,-1);
+				status_change_end(src, SC_SACRIFICE, INVALID_TIMER);
 
 			status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9%
 
@@ -3154,7 +3154,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 			return (damage_lv)skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0);
 	}
 
-	if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == -1 && tstatus->hp < tstatus->max_hp)
+	if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp)
 		tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal.
 
 	wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag);	
@@ -3197,7 +3197,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 			status_fix_damage(NULL, d_bl, damage, 0);
 		}
 		else
-			status_change_end(target, SC_DEVOTION, -1);
+			status_change_end(target, SC_DEVOTION, INVALID_TIMER);
 	}
 
 	if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) {
@@ -3256,7 +3256,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 				--sce->val2;
 			}
 			if (sce->val2 <= 0)
-				status_change_end(target, SC_POISONREACT, -1);
+				status_change_end(target, SC_POISONREACT, INVALID_TIMER);
 		}
 	}
 	map_freeblock_unlock();
@@ -3344,7 +3344,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 	switch( target->type )
 	{ // Checks on actual target
 		case BL_PC:
-			if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target))
+			if (((TBL_PC*)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC*)target))
 				return -1; //Cannot be targeted yet.
 			break;
 		case BL_MOB:

+ 5 - 32
src/map/chrif.c

@@ -36,9 +36,9 @@ static DBMap* auth_db; // int id -> struct auth_node*
 
 static const int packet_len_table[0x3d] = { // U - used, F - free
 	60, 3,-1,27,10,-1, 6,-1,	// 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
-	 6,-1,18, 7,-1,35,30,-1,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, F->2b07
-	 6,30,-1,-1,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
-	11,10,10, 6,11,-1,266,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, F->2b15, U->2b16, U->2b17
+	 6,-1,18, 7,-1,35,30, 0,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, F->2b07
+	 6,30, 0, 0,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
+	11,10,10, 0,11, 0,266,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
 	 2,10, 2,-1,-1,-1, 2, 7,	// 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
 	-1,10, 8, 2, 2,14,19,19,	// 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
 };
@@ -71,7 +71,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
 //2b10: Outgoing, chrif_updatefamelist -> 'Update the fame ranking lists and send them'
 //2b11: Outgoing, chrif_divorce -> 'tell the charserver to do divorce'
 //2b12: Incoming, chrif_divorceack -> 'divorce chars
-//2b13: Incoming, chrif_accountdeletion -> 'Delete acc XX, if the player is on, kick ....'
+//2b13: FREE
 //2b14: Incoming, chrif_accountban -> 'not sure: kick the player with message XY'
 //2b15: FREE
 //2b16: Outgoing, chrif_ragsrvinfo -> 'sends base / job / drop rates ....'
@@ -942,32 +942,6 @@ int chrif_deadopt(int father_id, int mother_id, int child_id)
 
 	return 0;
 }
-/*==========================================
- * Disconnection of a player (account has been deleted in login-server) by [Yor]
- *------------------------------------------*/
-int chrif_accountdeletion(int fd)
-{
-	int acc;
-	struct map_session_data *sd;
-
-	acc = RFIFOL(fd,2);
-	if (battle_config.etc_log)
-		ShowNotice("chrif_accountdeletion %d.\n", acc);
-	sd = map_id2sd(acc);
-	if (acc > 0) {
-		if (sd != NULL) {
-			sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
-			clif_displaymessage(sd->fd, "Your account has been deleted (disconnection)...");
-			set_eof(sd->fd); // forced to disconnect for the change
-			map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
-		}
-	} else {
-		if (sd != NULL)
-			ShowError("chrif_accountdeletion failed - player not online.\n");
-	}
-
-	return 0;
-}
 
 /*==========================================
  * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
@@ -1169,7 +1143,7 @@ int chrif_save_scdata(struct map_session_data *sd)
 	{
 		if (!sc->data[i])
 			continue;
-		if (sc->data[i]->timer != -1)
+		if (sc->data[i]->timer != INVALID_TIMER)
 		{
 			timer = get_timer(sc->data[i]->timer);
 			if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
@@ -1426,7 +1400,6 @@ int chrif_parse(int fd)
 		case 0x2b0d: chrif_changedsex(fd); break;
 		case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
 		case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
-		case 0x2b13: chrif_accountdeletion(fd); break;
 		case 0x2b14: chrif_accountban(fd); break;
 		case 0x2b1b: chrif_recvfamelist(fd); break;
 		case 0x2b1d: chrif_load_scdata(fd); break;

+ 72 - 53
src/map/clif.c

@@ -5599,9 +5599,9 @@ void clif_closevendingboard(struct block_list* bl, int fd)
 }
 
 /*==========================================
- * Sends a list of items in a shop
+ * Sends a list of items in a shop (ZC_PC_PURCHASE_ITEMLIST_FROMMC/ZC_PC_PURCHASE_ITEMLIST_FROMMC2)
  * R 0133 <len>.w <ID>.l {<value>.l <amount>.w <index>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B
- * R 0800 <len>.w <ID>.l <ID?>.l {<value>.l  <amount>.w <index>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B
+ * R 0800 <len>.w <ID>.l <UniqueID>.l {<value>.l  <amount>.w <index>.w <type>.B <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w}.22B
  *------------------------------------------*/
 void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending)
 {
@@ -5628,7 +5628,7 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven
 	WFIFOW(fd,2) = offset+count*22;
 	WFIFOL(fd,4) = id;
 #if PACKETVER >= 20100105
-	WFIFOL(fd,8) = vsd->status.char_id;
+	WFIFOL(fd,8) = vsd->vender_id;
 #endif
 
 	for( i = 0; i < count; i++ )
@@ -5649,12 +5649,14 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven
 }
 
 /*==========================================
- * Shop purchase failure
+ * Shop purchase failure (ZC_PC_PURCHASE_RESULT_FROMMC)
  * R 0135 <index>.w <amount>.w <fail>.B
  * fail=1 - not enough zeny
  * fail=2 - overweight
  * fail=4 - out of stock
  * fail=5 - "cannot use an npc shop while in a trade"
+ * fail=6 - Because the store information was incorrect the item was not purchased.
+ * fail=7 - No sales information.
  *------------------------------------------*/
 void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail)
 {
@@ -8398,8 +8400,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
 
 	// item
+	clif_inventorylist(sd);  // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item'
 	pc_checkitem(sd);
-	clif_inventorylist(sd);
 	
 	// cart
 	if(pc_iscarton(sd)) {
@@ -8724,11 +8726,13 @@ void clif_progressbar_abort(struct map_session_data * sd)
 
 void clif_parse_progressbar(int fd, struct map_session_data * sd)
 {
+	int npc_id = sd->progressbar.npc_id;
+
 	if( gettick() < sd->progressbar.timeout && sd->st )
 		sd->st->state = END;
 
-	npc_scriptcont(sd, sd->progressbar.npc_id);
 	sd->progressbar.npc_id = sd->progressbar.timeout = 0;
+	npc_scriptcont(sd, npc_id);
 }
 
 /*==========================================
@@ -9075,7 +9079,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 			return;
 		}
 
-		if (sd->ud.skilltimer != -1 || sd->sc.opt1)
+		if (sd->ud.skilltimer != INVALID_TIMER || sd->sc.opt1)
 			break;
 
 		if (sd->sc.count && (
@@ -9279,19 +9283,6 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
 	// notify sender of success
 	clif_wis_end(fd, 0); // 0: success to send wisper
 
-	// if player has an auto-away message
-	if(dstsd->away_message[0] != '\0')
-	{
-		char output[256];
-		sprintf(output, "%s %s", message, msg_txt(543)); // "(Automessage has been sent)"
-		clif_wis_message(dstsd->fd, sd->status.name, output, strlen(output) + 1);
-		if(dstsd->state.autotrade)
-			sprintf(output, msg_txt(544), dstsd->away_message); // "Away [AT] - "%s""
-		else
-			sprintf(output, msg_txt(545), dstsd->away_message); // "Away - "%s""
-		clif_wis_message(fd, dstsd->status.name, output, strlen(output) + 1);
-		return;
-	}
 	// Normal message
 	clif_wis_message(dstsd->fd, sd->status.name, message, messagelen);
 	return;
@@ -9562,9 +9553,11 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
 	WFIFOSET(fd,packet_len(0xca));
 }
 
-/*==========================================
- *
- *------------------------------------------*/
+/// Request to sell chosen items to npc shop
+/// R 00c9 <packet len>.W {<index>.W <amount>.W}.4B*
+/// S 00cb <result>.B
+/// result = 00 -> "The deal has successfully completed."
+/// result = 01 -> "The deal has failed."
 void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
 {
 	int fail=0,n;
@@ -9848,7 +9841,7 @@ static void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_sess
 		return;
 	if( hd->bl.id != target_id && skill_get_inf(skillnum)&INF_SELF_SKILL )
 		target_id = hd->bl.id;
-	if( hd->ud.skilltimer != -1 )
+	if( hd->ud.skilltimer != INVALID_TIMER )
 	{
 		if( skillnum != SA_CASTCANCEL ) return;
 	}
@@ -9958,7 +9951,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
 	if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris]
 		target_id = sd->bl.id;
 	
-	if( sd->ud.skilltimer != -1 )
+	if( sd->ud.skilltimer != INVALID_TIMER )
 	{
 		if( skillnum != SA_CASTCANCEL )
 			return;
@@ -10050,7 +10043,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil
 		safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE);
 	}
 
-	if( sd->ud.skilltimer != -1 )
+	if( sd->ud.skilltimer != INVALID_TIMER )
 		return;
 
 	if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 )
@@ -10880,7 +10873,7 @@ void clif_parse_VendingListReq(int fd, struct map_session_data* sd)
 }
 
 /*==========================================
- * Shop item(s) purchase request
+ * Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC)
  * S 0134 <len>.w <ID>.l {<amount>.w <index>.w}.4B*
  *------------------------------------------*/
 void clif_parse_PurchaseReq(int fd, struct map_session_data* sd)
@@ -10889,21 +10882,27 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd)
 	int id = (int)RFIFOL(fd,4);
 	const uint8* data = (uint8*)RFIFOP(fd,8);
 
-	vending_purchasereq(sd, id, -1, data, len/4);
+	vending_purchasereq(sd, id, sd->vended_id, data, len/4);
+
+	// whether it fails or not, the buy window is closed
+	sd->vended_id = 0;
 }
 
 /*==========================================
- * Shop item(s) purchase request
- * S 0134/0801 <len>.w <AID>.l <CID>.l {<amount>.w <index>.w}.4B*
+ * Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC2)
+ * S 0801 <len>.w <AID>.l <UniqueID>.l {<amount>.w <index>.w}.4B*
  *------------------------------------------*/
 void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd)
 {
 	int len = (int)RFIFOW(fd,2) - 12;
 	int aid = (int)RFIFOL(fd,4);
-	int cid = (int)RFIFOL(fd,8);
+	int uid = (int)RFIFOL(fd,8);
 	const uint8* data = (uint8*)RFIFOP(fd,12);
 
-	vending_purchasereq(sd, aid, cid, data, len/4);
+	vending_purchasereq(sd, aid, uid, data, len/4);
+
+	// whether it fails or not, the buy window is closed
+	sd->vended_id = 0;
 }
 
 /*==========================================
@@ -11615,7 +11614,7 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd)
 			sc_start(&dstsd->bl,SC_NOCHAT,100,0,0);
 		} else {
 			dstsd->status.manner = 0;
-			status_change_end(&dstsd->bl,SC_NOCHAT,-1);
+			status_change_end(&dstsd->bl, SC_NOCHAT, INVALID_TIMER);
 		}
 
 		if( type != 2 )
@@ -11674,7 +11673,7 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
  * S 0198 <x>.W <y>.W <gat>.W
  *------------------------------------------*/
 void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd)
-{// FIXME: type sent by client is 0 or 1 (even if you enter 2+); that suggests, that it is walkable gat attribute
+{
 	int x,y,type;
 
 	if( battle_config.atc_gmonly && !pc_isGM(sd) )
@@ -12013,7 +12012,6 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
 	account_id = RFIFOL(fd,2);
 	char_id = RFIFOL(fd,6);
 	reply = RFIFOB(fd,10);
-	//printf ("reply: %d %d %d\n", char_id, id, reply);
 
 	f_sd = map_id2sd(account_id); //The account id is the same as the bl.id of players.
 	if (f_sd == NULL)
@@ -12096,20 +12094,20 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
 }
 
 /*==========================================
- * /pvpinfo
+ * /pvpinfo (CZ_REQ_PVPPOINT & ZC_ACK_PVPPOINT)
+ * R 020f <char id>.L <account id>.L
+ * S 0210 <char id>.L <account id>.L <win point>.L <lose point>.L <point>.L
  *------------------------------------------*/
 void clif_parse_PVPInfo(int fd,struct map_session_data *sd)
 {
 	WFIFOHEAD(fd,packet_len(0x210));
 	WFIFOW(fd,0) = 0x210;
-	//WFIFOL(fd,2) = 0;	// not sure what for yet
-	//WFIFOL(fd,6) = 0;
+	WFIFOL(fd,2) = sd->status.char_id;
+	WFIFOL(fd,6) = sd->status.account_id;
 	WFIFOL(fd,10) = sd->pvp_won;	// times won
 	WFIFOL(fd,14) = sd->pvp_lost;	// times lost
 	WFIFOL(fd,18) = sd->pvp_point;
 	WFIFOSET(fd, packet_len(0x210));
-
-	return;
 }
 
 /*==========================================
@@ -12584,7 +12582,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
 		WFIFOL(fd,72) = 0;
 		WFIFOL(fd,76) = msg->zeny;
 
-		if( item->nameid && (data = itemdb_search(item->nameid)) != NULL )
+		if( item->nameid && (data = itemdb_exists(item->nameid)) != NULL )
 		{
 			WFIFOL(fd,80) = item->amount;
 			WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid;
@@ -12650,7 +12648,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
 		struct item_data *data;
 		unsigned int weight;
 
-		if ((data = itemdb_search(sd->mail.inbox.msg[i].item.nameid)) == NULL)
+		if ((data = itemdb_exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
 			return;
 
 		switch( pc_checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount) )
@@ -12863,7 +12861,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
 		WFIFOL(fd,k) = auction.auction_id;
 		safestrncpy((char*)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH);
 
-		if( (item = itemdb_search(auction.item.nameid)) != NULL && item->view_id > 0 )
+		if( (item = itemdb_exists(auction.item.nameid)) != NULL && item->view_id > 0 )
 			WFIFOW(fd,28+k) = item->view_id;
 		else
 			WFIFOW(fd,28+k) = auction.item.nameid;
@@ -12924,7 +12922,7 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
 		return;
 	}
 
-	if( (item = itemdb_search(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )
+	if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )
 	{ // Consumible or pets are not allowed
 		clif_Auction_setitem(sd->fd, idx, true);
 		return;
@@ -13025,7 +13023,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
 		return;
 	}
 
-	if( (item = itemdb_search(sd->status.inventory[sd->auction.index].nameid)) == NULL )
+	if( (item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL )
 	{ // Just in case
 		clif_Auction_message(fd, 2); // The auction has been canceled
 		return;
@@ -13139,6 +13137,31 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd)
 	WFIFOSET(fd,WFIFOW(fd,2));
 }
 
+/// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE)
+/// S 0289 <cash point>.L <kafra point>.L <error>.W
+///
+/// @param error
+/// 0: The deal has successfully completed. (ERROR_TYPE_NONE)
+/// 1: The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
+/// 2: The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
+/// 3: You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
+/// 4: You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
+/// 5: The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
+/// 6: You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
+/// 7: You can purchase up to 10 items.
+/// 8: Some items could not be purchased.
+void clif_cashshop_ack(struct map_session_data* sd, int error)
+{
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x289));
+	WFIFOW(fd,0) = 0x289;
+	WFIFOL(fd,2) = sd->cashPoints;
+	WFIFOL(fd,6) = sd->kafraPoints;
+	WFIFOW(fd,10) = TOW(error);
+	WFIFOSET(fd, packet_len(0x289));
+}
+
 void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
 {
 	int fail = 0, amount, points;
@@ -13154,12 +13177,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
 	else
 		fail = npc_cashshop_buy(sd, nameid, amount, points);
 
-	WFIFOHEAD(fd,12);
-	WFIFOW(fd,0) = 0x289;
-	WFIFOL(fd,2) = sd->cashPoints;
-	WFIFOL(fd,6) = sd->kafraPoints;
-	WFIFOW(fd,10) = fail;
-	WFIFOSET(fd,12);
+	clif_cashshop_ack(sd, fail);
 }
 
 /*==========================================
@@ -13248,7 +13266,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
 			else
 				WFIFOB(fd,2) = 2; // First Time
 		}
-		else if (md->spawn_timer != -1)
+		else if (md->spawn_timer != INVALID_TIMER)
 		{ // Boss is Dead
 			const struct TimerData * timer_data = get_timer(md->spawn_timer);
 			unsigned int seconds;
@@ -14268,7 +14286,7 @@ static int packetdb_readdb(void)
 	    6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	//#0x0280
-	    0,  0,  0,  6,  0,  0,  0,  0,  0,  8, 18,  0,  0,  0,  0,  0,
+	    0,  0,  0,  6,  0,  0,  0,  0,  0, 12, 18,  0,  0,  0,  0,  0,
 	    0,  4,  0, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	   85, -1, -1,107,  6, -1,  7,  7, 22,191,  0,  0,  0,  0,  0,  0,
@@ -14579,6 +14597,7 @@ static int packetdb_readdb(void)
 		{clif_parse_PartyBookingUpdateReq,"bookingupdatereq"},
 		{clif_parse_PartyBookingDeleteReq,"bookingdelreq"},
 #endif
+		{clif_parse_PVPInfo,"pvpinfo"},
 		{NULL,NULL}
 	};
 

+ 0 - 2
src/map/clif.h

@@ -461,8 +461,6 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap);
 void clif_friendslist_send(struct map_session_data *sd);
 void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type);
 
-// [Valaris]
-int clif_mob_hp(struct mob_data *md);
 void clif_weather(int m); // [Valaris]
 int clif_specialeffect(struct block_list* bl, int type, enum send_target target); // special effects [Valaris]
 void clif_specialeffect_single(struct block_list* bl, int type, int fd);

+ 36 - 77
src/map/guild.c

@@ -103,46 +103,34 @@ int guild_checkskill(struct guild *g,int id)
 /*==========================================
  * guild_skill_tree.txt reading - from jA [Komurka]
  *------------------------------------------*/
-int guild_read_guildskill_tree_db(void)
-{
-	int i,k,id=0,ln=0;
-	FILE *fp;
-	char line[1024],*p;
+static bool guild_read_guildskill_tree_db(char* split[], int columns, int current)
+{// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
+	int k, id, skillid;
 
-	memset(guild_skill_tree,0,sizeof(guild_skill_tree));
-	sprintf(line, "%s/guild_skill_tree.txt", db_path);
-	if( (fp=fopen(line,"r"))==NULL){
-		ShowError("can't read %s\n", line);
-		return -1;
+	skillid = atoi(split[0]);
+	id = skillid - GD_SKILLBASE;
+
+	if( id < 0 || id >= MAX_GUILDSKILL )
+	{
+		ShowWarning("guild_read_guildskill_tree_db: Invalid skill id %d.\n", skillid);
+		return false;
+	}
+
+	guild_skill_tree[id].id = skillid;
+	guild_skill_tree[id].max = atoi(split[1]);
+
+	if( guild_skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max == 0 )
+	{// enable guild's glory when required for emblems
+		guild_skill_tree[id].max = 1;
 	}
-	while(fgets(line, sizeof(line), fp))
+
+	for( k = 0; k < 5; k++ )
 	{
-		char *split[50];
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-		for(i=0,p=line;i<12 && p;i++){
-			split[i]=p;
-			p=strchr(p,',');
-			if(p) *p++=0;
-		}
-		if(i<12)
-			continue;
-		id = atoi(split[0]) - GD_SKILLBASE;
-		if(id<0 || id>=MAX_GUILDSKILL)
-			continue;
-		guild_skill_tree[id].id=atoi(split[0]);
-		guild_skill_tree[id].max=atoi(split[1]);
-		if (guild_skill_tree[id].id==GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max==0) guild_skill_tree[id].max=1;
-		for(k=0;k<5;k++){
-			guild_skill_tree[id].need[k].id=atoi(split[k*2+2]);
-			guild_skill_tree[id].need[k].lv=atoi(split[k*2+3]);
-		}
-	ln++;
+		guild_skill_tree[id].need[k].id = atoi(split[k*2+2]);
+		guild_skill_tree[id].need[k].lv = atoi(split[k*2+3]);
 	}
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"guild_skill_tree.txt");
 
-	return 0;
+	return true;
 }
 
 /*==========================================
@@ -168,51 +156,21 @@ int guild_check_skill_require(struct guild *g,int id)
 	return 1;
 }
 
-static int guild_read_castledb(void)
-{
-	FILE *fp;
-	char line[1024];
-	int j,ln=0;
-	char *str[32],*p;
+static bool guild_read_castledb(char* str[], int columns, int current)
+{// <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>]
 	struct guild_castle *gc;
 
-	sprintf(line, "%s/castle_db.txt", db_path);
-	if( (fp=fopen(line,"r"))==NULL){
-		ShowError("can't read %s\n", line);
-		return -1;
-	}
-
-	while(fgets(line, sizeof(line), fp))
-	{
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-		memset(str,0,sizeof(str));
-		for(j=0,p=line;j<6 && p;j++){
-			str[j]=p;
-			p=strchr(p,',');
-			if(p) *p++=0;
-		}
-		if (j < 4) //Insufficient data for castle. [Skotlex]
-		{
-			ShowError("castle_db.txt: invalid line '%s'\n", line);
-			continue;
-		}
-
-		gc=(struct guild_castle *)aCalloc(1,sizeof(struct guild_castle));
-		gc->castle_id=atoi(str[0]);
-		gc->mapindex = mapindex_name2id(str[1]);
-		safestrncpy(gc->castle_name,str[2],NAME_LENGTH);
-		safestrncpy(gc->castle_event,str[3],NAME_LENGTH);
+	CREATE(gc, struct guild_castle, 1);
+	gc->castle_id = atoi(str[0]);
+	gc->mapindex = mapindex_name2id(str[1]);
+	safestrncpy(gc->castle_name, str[2], sizeof(gc->castle_name));
+	safestrncpy(gc->castle_event, str[3], sizeof(gc->castle_event));
 
-		idb_put(castle_db,gc->castle_id,gc);
+	idb_put(castle_db,gc->castle_id,gc);
 
-		//intif_guild_castle_info(gc->castle_id);
+	//intif_guild_castle_info(gc->castle_id);
 
-		ln++;
-	}
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"castle_db.txt");
-	return 0;
+	return true;
 }
 
 /// lookup: guild id -> guild*
@@ -1969,9 +1927,10 @@ void do_init_guild(void)
 	expcache_ers = ers_new(sizeof(struct guild_expcache)); 
 	guild_castleinfoevent_db=idb_alloc(DB_OPT_BASE);
 
-	guild_read_castledb();
+	sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb);
 
-	guild_read_guildskill_tree_db(); //guild skill tree [Komurka]
+	memset(guild_skill_tree,0,sizeof(guild_skill_tree));
+	sv_readdb(db_path, "guild_skill_tree.txt", ',', 12, 12, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka]
 
 	add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
 	add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");

+ 160 - 195
src/map/homunculus.c

@@ -8,6 +8,7 @@
 #include "../common/nullpo.h"
 #include "../common/mmo.h"
 #include "../common/showmsg.h"
+#include "../common/strlib.h"
 #include "../common/utils.h"
 
 #include "log.h"
@@ -523,7 +524,7 @@ static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr data)
 int merc_hom_hungry_timer_delete(struct homun_data *hd)
 {
 	nullpo_ret(hd);
-	if(hd->hungry_timer != -1) {
+	if(hd->hungry_timer != INVALID_TIMER) {
 		delete_timer(hd->hungry_timer,merc_hom_hungry);
 		hd->hungry_timer = INVALID_TIMER;
 	}
@@ -637,7 +638,7 @@ int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom)
 
 void merc_hom_init_timers(struct homun_data * hd)
 {
-	if (hd->hungry_timer == -1)
+	if (hd->hungry_timer == INVALID_TIMER)
 		hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0);
 	hd->regen.state.block = 0; //Restore HP/SP block.
 }
@@ -876,226 +877,190 @@ int merc_hom_shuffle(struct homun_data *hd)
 	return 1;
 }
 
+static bool read_homunculusdb_sub(char* str[], int columns, int current)
+{
+	int classid; 
+	struct s_homunculus_db *db;
+
+	//Base Class,Evo Class
+	classid = atoi(str[0]);
+	if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
+	{
+		ShowError("read_homunculusdb : Invalid class %d\n", classid);
+		return false;
+	}
+	db = &homunculus_db[current];
+	db->base_class = classid;
+	classid = atoi(str[1]);
+	if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
+	{
+		db->base_class = 0;
+		ShowError("read_homunculusdb : Invalid class %d\n", classid);
+		return false;
+	}
+	db->evo_class = classid;
+	//Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD
+	strncpy(db->name,str[2],NAME_LENGTH-1);
+	db->foodID = atoi(str[3]);
+	db->hungryDelay = atoi(str[4]);
+	db->base_size = atoi(str[5]);
+	db->evo_size = atoi(str[6]);
+	db->race = atoi(str[7]);
+	db->element = atoi(str[8]);
+	db->baseASPD = atoi(str[9]);
+	//base HP, SP, str, agi, vit, int, dex, luk
+	db->base.HP = atoi(str[10]);
+	db->base.SP = atoi(str[11]);
+	db->base.str = atoi(str[12]);
+	db->base.agi = atoi(str[13]);
+	db->base.vit = atoi(str[14]);
+	db->base.int_= atoi(str[15]);
+	db->base.dex = atoi(str[16]);
+	db->base.luk = atoi(str[17]);
+	//Growth Min/Max HP, SP, str, agi, vit, int, dex, luk
+	db->gmin.HP = atoi(str[18]);
+	db->gmax.HP = atoi(str[19]);
+	db->gmin.SP = atoi(str[20]);
+	db->gmax.SP = atoi(str[21]);
+	db->gmin.str = atoi(str[22]);
+	db->gmax.str = atoi(str[23]);
+	db->gmin.agi = atoi(str[24]);
+	db->gmax.agi = atoi(str[25]);
+	db->gmin.vit = atoi(str[26]);
+	db->gmax.vit = atoi(str[27]);
+	db->gmin.int_= atoi(str[28]);
+	db->gmax.int_= atoi(str[29]);
+	db->gmin.dex = atoi(str[30]);
+	db->gmax.dex = atoi(str[31]);
+	db->gmin.luk = atoi(str[32]);
+	db->gmax.luk = atoi(str[33]);
+	//Evolution Min/Max HP, SP, str, agi, vit, int, dex, luk
+	db->emin.HP = atoi(str[34]);
+	db->emax.HP = atoi(str[35]);
+	db->emin.SP = atoi(str[36]);
+	db->emax.SP = atoi(str[37]);
+	db->emin.str = atoi(str[38]);
+	db->emax.str = atoi(str[39]);
+	db->emin.agi = atoi(str[40]);
+	db->emax.agi = atoi(str[41]);
+	db->emin.vit = atoi(str[42]);
+	db->emax.vit = atoi(str[43]);
+	db->emin.int_= atoi(str[44]);
+	db->emax.int_= atoi(str[45]);
+	db->emin.dex = atoi(str[46]);
+	db->emax.dex = atoi(str[47]);
+	db->emin.luk = atoi(str[48]);
+	db->emax.luk = atoi(str[49]);
+
+	//Check that the min/max values really are below the other one.
+	if(db->gmin.HP > db->gmax.HP)
+		db->gmin.HP = db->gmax.HP;
+	if(db->gmin.SP > db->gmax.SP)
+		db->gmin.SP = db->gmax.SP;
+	if(db->gmin.str > db->gmax.str)
+		db->gmin.str = db->gmax.str;
+	if(db->gmin.agi > db->gmax.agi)
+		db->gmin.agi = db->gmax.agi;
+	if(db->gmin.vit > db->gmax.vit)
+		db->gmin.vit = db->gmax.vit;
+	if(db->gmin.int_> db->gmax.int_)
+		db->gmin.int_= db->gmax.int_;
+	if(db->gmin.dex > db->gmax.dex)
+		db->gmin.dex = db->gmax.dex;
+	if(db->gmin.luk > db->gmax.luk)
+		db->gmin.luk = db->gmax.luk;
+
+	if(db->emin.HP > db->emax.HP)
+		db->emin.HP = db->emax.HP;
+	if(db->emin.SP > db->emax.SP)
+		db->emin.SP = db->emax.SP;
+	if(db->emin.str > db->emax.str)
+		db->emin.str = db->emax.str;
+	if(db->emin.agi > db->emax.agi)
+		db->emin.agi = db->emax.agi;
+	if(db->emin.vit > db->emax.vit)
+		db->emin.vit = db->emax.vit;
+	if(db->emin.int_> db->emax.int_)
+		db->emin.int_= db->emax.int_;
+	if(db->emin.dex > db->emax.dex)
+		db->emin.dex = db->emax.dex;
+	if(db->emin.luk > db->emax.luk)
+		db->emin.luk = db->emax.luk;
+
+	return true;
+}
+
 int read_homunculusdb(void)
 {
-	FILE *fp;
-	char line[1024], *p;
-	int i, k, classid; 
-	int j = 0;
+	int i;
 	const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
-	char *str[50];
-	struct s_homunculus_db *db;
 
 	memset(homunculus_db,0,sizeof(homunculus_db));
-	for(i = 0; i<2; i++)
+	for(i = 0; i<ARRAYLENGTH(filename); i++)
 	{
-		sprintf(line, "%s/%s", db_path, filename[i]);
-		fp = fopen(line,"r");
-		if(!fp){
-			if(i != 0)
-				continue;
-			ShowError("read_homunculusdb : can't read %s\n", line);
-			return -1;
-		}
+		char path[256];
 
-		while(fgets(line, sizeof(line), fp) && j < MAX_HOMUNCULUS_CLASS)
+		if( i > 0 )
 		{
-			if(line[0] == '/' && line[1] == '/')
-				continue;
+			sprintf(path, "%s/%s", db_path, filename[i]);
 
-			k = 0;
-			p = strtok (line,",");
-			while (p != NULL && k < 50)
-			{
-				str[k++] = p;
-				p = strtok (NULL, ",");
-			}
-			if (k < 50 )
-			{
-				ShowError("read_homunculusdb : Incorrect number of columns at %s, homunculus %d. Read %d columns, 50 are needed.\n", filename[i], j+1, k);
-				continue;
-			}
-			
-			//Base Class,Evo Class
-			classid = atoi(str[0]);
-			if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
-			{
-				ShowError("read_homunculusdb : Invalid class %d (%s)\n", classid, filename[i]);
-				continue;
-			}
-			db = &homunculus_db[j];
-			db->base_class = classid;
-			classid = atoi(str[1]);
-			if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
+			if( !exists(path) )
 			{
-				db->base_class = 0;
-				ShowError("read_homunculusdb : Invalid class %d (%s)\n", classid, filename[i]);
 				continue;
 			}
-			db->evo_class = classid;
-			//Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD
-			strncpy(db->name,str[2],NAME_LENGTH-1);
-			db->foodID = atoi(str[3]);
-			db->hungryDelay = atoi(str[4]);
-			db->base_size = atoi(str[5]);
-			db->evo_size = atoi(str[6]);
-			db->race = atoi(str[7]);
-			db->element = atoi(str[8]);
-			db->baseASPD = atoi(str[9]);
-			//base HP, SP, str, agi, vit, int, dex, luk
-			db->base.HP = atoi(str[10]);
-			db->base.SP = atoi(str[11]);
-			db->base.str = atoi(str[12]);
-			db->base.agi = atoi(str[13]);
-			db->base.vit = atoi(str[14]);
-			db->base.int_= atoi(str[15]);
-			db->base.dex = atoi(str[16]);
-			db->base.luk = atoi(str[17]);
-			//Growth Min/Max HP, SP, str, agi, vit, int, dex, luk
-			db->gmin.HP = atoi(str[18]);
-			db->gmax.HP = atoi(str[19]);
-			db->gmin.SP = atoi(str[20]);
-			db->gmax.SP = atoi(str[21]);
-			db->gmin.str = atoi(str[22]);
-			db->gmax.str = atoi(str[23]);
-			db->gmin.agi = atoi(str[24]);
-			db->gmax.agi = atoi(str[25]);
-			db->gmin.vit = atoi(str[26]);
-			db->gmax.vit = atoi(str[27]);
-			db->gmin.int_= atoi(str[28]);
-			db->gmax.int_= atoi(str[29]);
-			db->gmin.dex = atoi(str[30]);
-			db->gmax.dex = atoi(str[31]);
-			db->gmin.luk = atoi(str[32]);
-			db->gmax.luk = atoi(str[33]);
-			//Evolution Min/Max HP, SP, str, agi, vit, int, dex, luk
-			db->emin.HP = atoi(str[34]);
-			db->emax.HP = atoi(str[35]);
-			db->emin.SP = atoi(str[36]);
-			db->emax.SP = atoi(str[37]);
-			db->emin.str = atoi(str[38]);
-			db->emax.str = atoi(str[39]);
-			db->emin.agi = atoi(str[40]);
-			db->emax.agi = atoi(str[41]);
-			db->emin.vit = atoi(str[42]);
-			db->emax.vit = atoi(str[43]);
-			db->emin.int_= atoi(str[44]);
-			db->emax.int_= atoi(str[45]);
-			db->emin.dex = atoi(str[46]);
-			db->emax.dex = atoi(str[47]);
-			db->emin.luk = atoi(str[48]);
-			db->emax.luk = atoi(str[49]);
-
-			//Check that the min/max values really are below the other one.
-			if(db->gmin.HP > db->gmax.HP)
-				db->gmin.HP = db->gmax.HP;
-			if(db->gmin.SP > db->gmax.SP)
-				db->gmin.SP = db->gmax.SP;
-			if(db->gmin.str > db->gmax.str)
-				db->gmin.str = db->gmax.str;
-			if(db->gmin.agi > db->gmax.agi)
-				db->gmin.agi = db->gmax.agi;
-			if(db->gmin.vit > db->gmax.vit)
-				db->gmin.vit = db->gmax.vit;
-			if(db->gmin.int_> db->gmax.int_)
-				db->gmin.int_= db->gmax.int_;
-			if(db->gmin.dex > db->gmax.dex)
-				db->gmin.dex = db->gmax.dex;
-			if(db->gmin.luk > db->gmax.luk)
-				db->gmin.luk = db->gmax.luk;
-
-			if(db->emin.HP > db->emax.HP)
-				db->emin.HP = db->emax.HP;
-			if(db->emin.SP > db->emax.SP)
-				db->emin.SP = db->emax.SP;
-			if(db->emin.str > db->emax.str)
-				db->emin.str = db->emax.str;
-			if(db->emin.agi > db->emax.agi)
-				db->emin.agi = db->emax.agi;
-			if(db->emin.vit > db->emax.vit)
-				db->emin.vit = db->emax.vit;
-			if(db->emin.int_> db->emax.int_)
-				db->emin.int_= db->emax.int_;
-			if(db->emin.dex > db->emax.dex)
-				db->emin.dex = db->emax.dex;
-			if(db->emin.luk > db->emax.luk)
-				db->emin.luk = db->emax.luk;
-
-			j++;
 		}
-		if (j > MAX_HOMUNCULUS_CLASS)
-			ShowWarning("read_homunculusdb: Reached max number of homunculus [%d]. Remaining homunculus were not read.\n ", MAX_HOMUNCULUS_CLASS);
-		fclose(fp);
-		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' homunculus in '"CL_WHITE"db/%s"CL_RESET"'.\n",j,filename[i]);
+
+		sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub);
 	}
+
 	return 0;
 }
 
-int read_homunculus_skilldb(void)
-{
-	FILE *fp;
-	char line[1024], *p;
+static bool read_homunculus_skilldb_sub(char* split[], int columns, int current)
+{// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
 	int k, classid; 
-	int j = 0;
-	char *split[15];
+	int j;
+	int minJobLevelPresent = 0;
 
-	memset(hskill_tree,0,sizeof(hskill_tree));
-	sprintf(line, "%s/homun_skill_tree.txt", db_path);
-	fp=fopen(line,"r");
-	if(fp==NULL){
-		ShowError("can't read %s\n", line);
-		return 1;
-	}
+	if( columns == 14 )
+		minJobLevelPresent = 1;	// MinJobLvl has been added
 
-	while(fgets(line, sizeof(line), fp))
+	// check for bounds [celest]
+	classid = atoi(split[0]) - HM_CLASS_BASE;
+	if ( classid >= MAX_HOMUNCULUS_CLASS )
 	{
-		int minJobLevelPresent = 0;
-
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-
-		k = 0;
-		p = strtok(line,",");
-		while (p != NULL && k < 15)
-		{
-			split[k++] = p;
-			p = strtok(NULL, ",");
-		}
-
-		if(k < 13)
-			continue;
-
-		if (k == 14)
-			minJobLevelPresent = 1;	// MinJobLvl has been added
+		ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0]));
+		return false;
+	}
 
-		// check for bounds [celest]
-		classid = atoi(split[0]) - HM_CLASS_BASE;
-		if ( classid >= MAX_HOMUNCULUS_CLASS )
-			continue;
+	k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex]
+	// Search an empty line or a line with the same skill_id (stored in j)
+	ARR_FIND( 0, MAX_SKILL_TREE, j, !hskill_tree[classid][j].id || hskill_tree[classid][j].id == k );
+	if (j == MAX_SKILL_TREE)
+	{
+		ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid);
+		return false;
+	}
 
-		k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex]
-		// Search an empty line or a line with the same skill_id (stored in j)
-		for(j = 0; j < MAX_SKILL_TREE && hskill_tree[classid][j].id && hskill_tree[classid][j].id != k; j++);
+	hskill_tree[classid][j].id = k;
+	hskill_tree[classid][j].max = atoi(split[2]);
+	if (minJobLevelPresent)
+		hskill_tree[classid][j].joblv = atoi(split[3]);
 
-		if (j == MAX_SKILL_TREE)
-		{
-			ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid);
-			continue;
-		}
+	for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ )
+	{
+		hskill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]);
+		hskill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]);
+	}
 
-		hskill_tree[classid][j].id=k;
-		hskill_tree[classid][j].max=atoi(split[2]);
-		if (minJobLevelPresent)
-			hskill_tree[classid][j].joblv=atoi(split[3]);
+	return true;
+}
 
-		for(k=0;k<MAX_PC_SKILL_REQUIRE;k++){
-			hskill_tree[classid][j].need[k].id=atoi(split[3+k*2+minJobLevelPresent]);
-			hskill_tree[classid][j].need[k].lv=atoi(split[3+k*2+minJobLevelPresent+1]);
-		}
-	}
+int read_homunculus_skilldb(void)
+{
+	memset(hskill_tree,0,sizeof(hskill_tree));
+	sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 14, -1, &read_homunculus_skilldb_sub);
 
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","homun_skill_tree.txt");
 	return 0;
 }
 

+ 75 - 136
src/map/itemdb.c

@@ -471,46 +471,32 @@ int itemdb_isidentified(int nameid)
 /*==========================================
  * アイテム使用可能フラグのオーバーライド
  *------------------------------------------*/
-static int itemdb_read_itemavail (void)
-{
-	FILE *fp;
-	int nameid, j, k, ln = 0;
-	char line[1024], *str[10], *p;
+static bool itemdb_read_itemavail(char* str[], int columns, int current)
+{// <nameid>,<sprite>
+	int nameid, sprite;
 	struct item_data *id;
 
-	sprintf(line, "%s/item_avail.txt", db_path);
-	if ((fp = fopen(line,"r")) == NULL) {
-		ShowError("can't read %s\n", line);
-		return -1;
-	}
+	nameid = atoi(str[0]);
 
-	while(fgets(line, sizeof(line), fp))
+	if( ( id = itemdb_exists(nameid) ) == NULL )
 	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-		memset(str, 0, sizeof(str));
-		for (j = 0, p = line; j < 2 && p; j++) {
-			str[j] = p;
-			p = strchr(p, ',');
-			if(p) *p++ = 0;
-		}
+		ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid);
+		return false;
+	}
 
-		if (j < 2 || str[0] == NULL ||
-			(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
-			continue;
+	sprite = atoi(str[1]);
 
-		k = atoi(str[1]);
-		if (k > 0) {
-			id->flag.available = 1;
-			id->view_id = k;
-		} else
-			id->flag.available = 0;
-		ln++;
+	if( sprite > 0 )
+	{
+		id->flag.available = 1;
+		id->view_id = sprite;
+	}
+	else
+	{
+		id->flag.available = 0;
 	}
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_avail.txt");
 
-	return 0;
+	return true;
 }
 
 /*==========================================
@@ -591,137 +577,90 @@ static void itemdb_read_itemgroup(void)
 /*==========================================
  * 装備制限ファイル読み出し
  *------------------------------------------*/
-static int itemdb_read_noequip(void)
-{
-	FILE *fp;
-	char line[1024];
-	int ln=0;
-	int nameid,j;
-	char *str[32],*p;
+static bool itemdb_read_noequip(char* str[], int columns, int current)
+{// <nameid>,<mode>
+	int nameid;
 	struct item_data *id;
 
-	sprintf(line, "%s/item_noequip.txt", db_path);
-	if( (fp=fopen(line,"r"))==NULL ){
-		ShowError("can't read %s\n", line);
-		return -1;
-	}
-	while(fgets(line, sizeof(line), fp))
-	{
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-		memset(str,0,sizeof(str));
-		for(j=0,p=line;j<2 && p;j++){
-			str[j]=p;
-			p=strchr(p,',');
-			if(p) *p++=0;
-		}
-		if(str[0]==NULL)
-			continue;
-
-		nameid=atoi(str[0]);
-		if(nameid<=0 || !(id=itemdb_exists(nameid)))
-			continue;
+	nameid = atoi(str[0]);
 
-		id->flag.no_equip |= atoi(str[1]);
+	if( ( id = itemdb_exists(nameid) ) == NULL )
+	{
+		ShowWarning("itemdb_read_noequip: Invalid item id %d.\n", nameid);
+		return false;
+	}
 
-		ln++;
+	id->flag.no_equip |= atoi(str[1]);
 
-	}
-	fclose(fp);
-	if (ln > 0) {
-		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"item_noequip.txt");
-	}	
-	return 0;
+	return true;
 }
 
 /*==========================================
  * Reads item trade restrictions [Skotlex]
  *------------------------------------------*/
-static int itemdb_read_itemtrade(void)
-{
-	FILE *fp;
-	int nameid, j, flag, gmlv, ln = 0;
-	char line[1024], *str[10], *p;
+static bool itemdb_read_itemtrade(char* str[], int columns, int current)
+{// <nameid>,<mask>,<gm level>
+	int nameid, flag, gmlv;
 	struct item_data *id;
 
-	sprintf(line, "%s/item_trade.txt", db_path);
-	if ((fp = fopen(line,"r")) == NULL) {
-		ShowError("can't read %s\n", line);
-		return -1;
-	}
+	nameid = atoi(str[0]);
 
-	while(fgets(line, sizeof(line), fp))
+	if( ( id = itemdb_exists(nameid) ) == NULL )
 	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-		memset(str, 0, sizeof(str));
-		for (j = 0, p = line; j < 3 && p; j++) {
-			str[j] = p;
-			p = strchr(p, ',');
-			if(p) *p++ = 0;
-		}
+		//ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid);
+		//return false;
+		// FIXME: item_trade.txt contains items, which are commented in item database.
+		return true;
+	}
 
-		if (j < 3 || str[0] == NULL ||
-			(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
-			continue;
+	flag = atoi(str[1]);
+	gmlv = atoi(str[2]);
 
-		flag = atoi(str[1]);
-		gmlv = atoi(str[2]);
-		
-		if (flag > 0 && flag < 128 && gmlv > 0) { //Check range
-			id->flag.trade_restriction = flag;
-			id->gm_lv_trade_override = gmlv;
-			ln++;
-		}
+	if( flag < 0 || flag >= 128 )
+	{//Check range
+		ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid);
+		return false;
 	}
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_trade.txt");
 
-	return 0;
+	if( gmlv < 1 )
+	{
+		ShowWarning("itemdb_read_itemtrade: Invalid override GM level %d for item id %d.\n", gmlv, nameid);
+		return false;
+	}
+
+	id->flag.trade_restriction = flag;
+	id->gm_lv_trade_override = gmlv;
+
+	return true;
 }
 
 /*==========================================
  * Reads item delay amounts [Paradox924X]
  *------------------------------------------*/
-static int itemdb_read_itemdelay(void)
-{
-	FILE *fp;
-	int nameid, j, item_delays = 0;
-	char line[1024], *str[10], *p;
+static bool itemdb_read_itemdelay(char* str[], int columns, int current)
+{// <nameid>,<delay>
+	int nameid, delay;
 	struct item_data *id;
 
-	sprintf(line, "%s/item_delay.txt", db_path);
-	if ((fp = fopen(line,"r")) == NULL) {
-		ShowError("can't read %s\n", line);
-		return -1;
-	}
+	nameid = atoi(str[0]);
 
-	while(fgets(line, sizeof(line), fp))
+	if( ( id = itemdb_exists(nameid) ) == NULL )
 	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-		if (item_delays == MAX_ITEMDELAYS) {
-			ShowError("itemdb_read_itemdelay: Too many entries specified in %s/item_delay.txt! Increase MAX_ITEMDELAYS in itemdb.h!\n", db_path);
-			break;
-		}
-		memset(str, 0, sizeof(str));
-		for (j = 0, p = line; j < 2 && p; j++) {
-			str[j] = p;
-			p = strchr(p, ',');
-			if(p) *p++ = 0;
-		}
+		ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", nameid);
+		return false;
+	}
 
-		if (j < 2 || str[0] == NULL ||
-			(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
-			continue;
+	delay = atoi(str[1]);
 
-		id->delay = atoi(str[1]);
-		item_delays++;
+	if( delay < 0 )
+	{
+		ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid);
+		return false;
 	}
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_delays, "item_delay.txt");
 
-	return 0;
+	id->delay = delay;
+
+	return true;
 }
 
 /*==================================================================
@@ -1076,10 +1015,10 @@ static void itemdb_read(void)
 		itemdb_readdb();
 
 	itemdb_read_itemgroup();
-	itemdb_read_itemavail();
-	itemdb_read_noequip();
-	itemdb_read_itemtrade();
-	itemdb_read_itemdelay();
+	sv_readdb(db_path, "item_avail.txt",   ',', 2, 2, -1,             &itemdb_read_itemavail);
+	sv_readdb(db_path, "item_noequip.txt", ',', 2, 2, -1,             &itemdb_read_noequip);
+	sv_readdb(db_path, "item_trade.txt",   ',', 3, 3, -1,             &itemdb_read_itemtrade);
+	sv_readdb(db_path, "item_delay.txt",   ',', 2, 2, MAX_ITEMDELAYS, &itemdb_read_itemdelay);
 	sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
 }
 

+ 1 - 1
src/map/itemdb.h

@@ -111,7 +111,7 @@ struct item_data* itemdb_exists(int nameid);
 #define itemdb_wlv(n) itemdb_search(n)->wlv
 #define itemdb_range(n) itemdb_search(n)->range
 #define itemdb_slot(n) itemdb_search(n)->slot
-#define itemdb_available(n) (itemdb_exists(n) && itemdb_search(n)->flag.available)
+#define itemdb_available(n) (itemdb_search(n)->flag.available)
 #define itemdb_viewid(n) (itemdb_search(n)->view_id)
 #define itemdb_autoequip(n) (itemdb_search(n)->flag.autoequip)
 const char* itemdb_typename(int type);

+ 84 - 92
src/map/map.c

@@ -393,19 +393,11 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
 	//TODO: Perhaps some outs of bounds checking should be placed here?
 	if (bl->type&BL_CHAR) {
 		skill_unit_move(bl,tick,2);
-		sc = status_get_sc(bl);
-		if (sc && sc->count) {
-			if (sc->data[SC_CLOSECONFINE])
-				status_change_end(bl, SC_CLOSECONFINE, -1);
-			if (sc->data[SC_CLOSECONFINE2])
-				status_change_end(bl, SC_CLOSECONFINE2, -1);
-//			if (sc->data[SC_BLADESTOP]) //Won't stop when you are knocked away, go figure...
-//				status_change_end(bl, SC_BLADESTOP, -1);
-			if (sc->data[SC_TATAMIGAESHI])
-				status_change_end(bl, SC_TATAMIGAESHI, -1);
-			if (sc->data[SC_MAGICROD])
-				status_change_end(bl, SC_MAGICROD, -1);
-		}
+		status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER);
+		status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
+//		status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
+		status_change_end(bl, SC_TATAMIGAESHI, INVALID_TIMER);
+		status_change_end(bl, SC_MAGICROD, INVALID_TIMER);
 	} else
 	if (bl->type == BL_NPC)
 		npc_unsetcells((TBL_NPC*)bl);
@@ -423,6 +415,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
 
 	if (bl->type&BL_CHAR) {
 		skill_unit_move(bl,tick,3);
+		sc = status_get_sc(bl);
 		if (sc) {
 			if (sc->count) {
 				if (sc->data[SC_CLOAKING])
@@ -1566,7 +1559,7 @@ int map_quit(struct map_session_data *sd)
 		return 0;
 	}
 
-	if (sd->npc_timer_id != -1) //Cancel the event timer.
+	if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer.
 		npc_timerevent_quit(sd);
 
 	if (sd->npc_id)
@@ -1580,64 +1573,40 @@ int map_quit(struct map_session_data *sd)
 	if( sd->sc.count )
 	{
 		//Status that are not saved...
-		if(sd->sc.data[SC_BOSSMAPINFO])
-			status_change_end(&sd->bl,SC_BOSSMAPINFO,-1);
-		if(sd->sc.data[SC_AUTOTRADE])
-			status_change_end(&sd->bl,SC_AUTOTRADE,-1);
-		if(sd->sc.data[SC_SPURT])
-			status_change_end(&sd->bl,SC_SPURT,-1);
-		if(sd->sc.data[SC_BERSERK])
-			status_change_end(&sd->bl,SC_BERSERK,-1);
-		if(sd->sc.data[SC_TRICKDEAD])
-			status_change_end(&sd->bl,SC_TRICKDEAD,-1);
-		if(sd->sc.data[SC_GUILDAURA])
-			status_change_end(&sd->bl,SC_GUILDAURA,-1);
+		status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_GUILDAURA, INVALID_TIMER);
 		if(sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4)
-			status_change_end(&sd->bl,SC_ENDURE,-1); //No need to save infinite endure.
-		if(sd->sc.data[SC_WEIGHT50])
-			status_change_end(&sd->bl,SC_WEIGHT50,-1);
-		if(sd->sc.data[SC_WEIGHT90])
-			status_change_end(&sd->bl,SC_WEIGHT90,-1);
+			status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure.
+		status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
 		if (battle_config.debuff_on_logout&1) {
-			if(sd->sc.data[SC_ORCISH])
-				status_change_end(&sd->bl,SC_ORCISH,-1);
-			if(sd->sc.data[SC_STRIPWEAPON])
-				status_change_end(&sd->bl,SC_STRIPWEAPON,-1);
-			if(sd->sc.data[SC_STRIPARMOR])
-				status_change_end(&sd->bl,SC_STRIPARMOR,-1);
-			if(sd->sc.data[SC_STRIPSHIELD])
-				status_change_end(&sd->bl,SC_STRIPSHIELD,-1);
-			if(sd->sc.data[SC_STRIPHELM])
-				status_change_end(&sd->bl,SC_STRIPHELM,-1);
-			if(sd->sc.data[SC_EXTREMITYFIST])
-				status_change_end(&sd->bl,SC_EXTREMITYFIST,-1);
-			if(sd->sc.data[SC_EXPLOSIONSPIRITS])
-				status_change_end(&sd->bl,SC_EXPLOSIONSPIRITS,-1);
+			status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STRIPSHIELD, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
 			if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4)
-				status_change_end(&sd->bl,SC_REGENERATION,-1);
+				status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER);
 			//TO-DO Probably there are way more NPC_type negative status that are removed
-			if(sd->sc.data[SC_CHANGEUNDEAD])
-				status_change_end(&sd->bl,SC_CHANGEUNDEAD,-1);
+			status_change_end(&sd->bl, SC_CHANGEUNDEAD, INVALID_TIMER);
 			// Both these statuses are removed on logout. [L0ne_W0lf]
-			if(sd->sc.data[SC_SLOWCAST])
-				status_change_end(&sd->bl,SC_SLOWCAST,-1);
-			if(sd->sc.data[SC_CRITICALWOUND])
-				status_change_end(&sd->bl,SC_CRITICALWOUND,-1);
+			status_change_end(&sd->bl, SC_SLOWCAST, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_CRITICALWOUND, INVALID_TIMER);
 		}
 		if (battle_config.debuff_on_logout&2)
 		{
-			if(sd->sc.data[SC_MAXIMIZEPOWER])
-				status_change_end(&sd->bl,SC_MAXIMIZEPOWER,-1);
-			if(sd->sc.data[SC_MAXOVERTHRUST])
-				status_change_end(&sd->bl,SC_MAXOVERTHRUST,-1);
-			if(sd->sc.data[SC_STEELBODY])
-				status_change_end(&sd->bl,SC_STEELBODY,-1);
-			if(sd->sc.data[SC_PRESERVE])
-				status_change_end(&sd->bl,SC_PRESERVE,-1);
-			if(sd->sc.data[SC_KAAHI])
-				status_change_end(&sd->bl,SC_KAAHI,-1);
-			if(sd->sc.data[SC_SPIRIT])
-				status_change_end(&sd->bl,SC_SPIRIT,-1);
+			status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER);
 		}
 	}
 	
@@ -2109,7 +2078,7 @@ int map_addmobtolist(unsigned short m, struct spawn_data *spawn)
 void map_spawnmobs(int m)
 {
 	int i, k=0;
-	if (map[m].mob_delete_timer != -1)
+	if (map[m].mob_delete_timer != INVALID_TIMER)
 	{	//Mobs have not been removed yet [Skotlex]
 		delete_timer(map[m].mob_delete_timer, map_removemobs_timer);
 		map[m].mob_delete_timer = INVALID_TIMER;
@@ -2184,7 +2153,7 @@ int map_removemobs_timer(int tid, unsigned int tick, int id, intptr data)
 
 void map_removemobs(int m)
 {
-	if (map[m].mob_delete_timer != -1) // should never happen
+	if (map[m].mob_delete_timer != INVALID_TIMER) // should never happen
 		return; //Mobs are already scheduled for removal
 
 	map[m].mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0);
@@ -2804,8 +2773,16 @@ void map_flags_init(void)
 
 	for( i = 0; i < map_num; i++ )
 	{
+		// mapflags
 		memset(&map[i].flag, 0, sizeof(map[i].flag));
 
+		// additional mapflag data
+		map[i].zone      = 0;  // restricted mapflag zone
+		map[i].nocommand = 0;  // nocommand mapflag level
+		map[i].bexp      = 100;  // per map base exp multiplicator
+		map[i].jexp      = 100;  // per map job exp multiplicator
+
+		// adjustments
 		if( battle_config.pk_mode )
 			map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
 	}
@@ -2975,11 +2952,7 @@ int map_readallmaps (void)
 
 		map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
 		map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		
-		// default experience multiplicators
-		map[i].jexp = 100;
-		map[i].bexp = 100;
-		
+
 		size = map[i].bxs * map[i].bys * sizeof(struct block_list*);
 		map[i].block = (struct block_list**)aCalloc(size, 1);
 		map[i].block_mob = (struct block_list**)aCalloc(size, 1);
@@ -3012,7 +2985,7 @@ static int char_ip_set = 0;
 /*==========================================
  * Console Command Parser [Wizputer]
  *------------------------------------------*/
-int parse_console(char* buf)
+int parse_console(const char* buf)
 {
 	char type[64];
 	char command[64];
@@ -3026,14 +2999,20 @@ int parse_console(char* buf)
 	memset(&sd, 0, sizeof(struct map_session_data));
 	strcpy(sd.status.name, "console");
 
-	if( (n=sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]",type,command,map,&x,&y)) < 5 )
-		if( (n=sscanf(buf, "%[^:]:%[^\n]",type,command)) < 2 )
-			n = sscanf(buf,"%[^\n]",type);
+	if( ( n = sscanf(buf, "%63[^:]:%63[^:]:%63s %d %d[^\n]", type, command, map, &x, &y) ) < 5 )
+	{
+		if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 )
+		{
+			n = sscanf(buf, "%63[^\n]", type);
+		}
+	}
 
-	if( n == 5 ) {
+	if( n == 5 )
+	{
 		m = map_mapname2mapid(map);
-		if( m < 0 ){
-			ShowWarning("Console: Unknown map\n");
+		if( m < 0 )
+		{
+			ShowWarning("Console: Unknown map.\n");
 			return 0;
 		}
 		sd.bl.m = m;
@@ -3042,32 +3021,40 @@ int parse_console(char* buf)
 			sd.bl.x = x;
 		if( y > 0 )
 			sd.bl.y = y;
-	} else {
+	}
+	else
+	{
 		map[0] = '\0';
-		if( n < 2 ) command[0] = '\0';
-		if( n < 1 ) type[0] = '\0';
+		if( n < 2 )
+			command[0] = '\0';
+		if( n < 1 )
+			type[0] = '\0';
 	}
 
-	ShowInfo("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y);
+	ShowNotice("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y);
 
-	if( n == 5 && strcmpi("admin",type) == 0 ){
-		if( !is_atcommand(sd.fd,&sd,command,0) )
+	if( n == 5 && strcmpi("admin",type) == 0 )
+	{
+		if( !is_atcommand(sd.fd, &sd, command, 0) )
 			ShowInfo("Console: not atcommand\n");
-	} else if( n == 2 && strcmpi("server",type) == 0 ){
-		if( strcmpi("shutdown",command) == 0 ||
-		    strcmpi("exit",command) == 0 ||
-		    strcmpi("quit",command) == 0 ){
+	}
+	else if( n == 2 && strcmpi("server", type) == 0 )
+	{
+		if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 )
+		{
 			runflag = 0;
 		}
-	} else if( strcmpi("help",type) == 0 ){
-		ShowNotice("To use GM commands:\n");
-		ShowInfo("admin:<gm command>:<map of \"gm\"> <x> <y>\n");
+	}
+	else if( strcmpi("help", type) == 0 )
+	{
+		ShowInfo("To use GM commands:\n");
+		ShowInfo("  admin:<gm command>:<map of \"gm\"> <x> <y>\n");
 		ShowInfo("You can use any GM command that doesn't require the GM.\n");
 		ShowInfo("No using @item or @warp however you can use @charwarp\n");
 		ShowInfo("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n");
 		ShowInfo("IE: @spawn\n");
 		ShowInfo("To shutdown the server:\n");
-		ShowInfo("server:shutdown\n");
+		ShowInfo("  server:shutdown\n");
 	}
 
 	return 0;
@@ -3412,9 +3399,14 @@ void do_final(void)
 
 	ShowStatus("Terminating...\n");
 
+	// remove all objects on maps
 	for (i = 0; i < map_num; i++)
+	{
+		ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map_num, map[i].name);
 		if (map[i].m >= 0)
 			map_foreachinmap(cleanup_sub, i, BL_ALL);
+	}
+	ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num);
 
 	//Scan any remaining players (between maps?) to kick them out. [Skotlex]
 	iter = mapit_getallusers();

+ 80 - 136
src/map/mercenary.c

@@ -8,6 +8,7 @@
 #include "../common/nullpo.h"
 #include "../common/mmo.h"
 #include "../common/showmsg.h"
+#include "../common/strlib.h"
 #include "../common/utils.h"
 
 #include "log.h"
@@ -249,7 +250,7 @@ int merc_delete(struct mercenary_data *md, int reply)
 	if( md->devotion_flag )
 	{
 		md->devotion_flag = 0;
-		status_change_end(&sd->bl, SC_DEVOTION, -1);
+		status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER);
 	}
 
 	switch( reply )
@@ -402,162 +403,105 @@ int mercenary_checkskill(struct mercenary_data *md, int skill_id)
 	return 0;
 }
 
-int read_mercenarydb(void)
+static bool read_mercenarydb_sub(char* str[], int columns, int current)
 {
-	FILE *fp;
-	char line[1024], *p;
-	char *str[26];
-	int i, j = 0, k = 0, ele;
+	int ele;
 	struct s_mercenary_db *db;
 	struct status_data *status;
 
-	sprintf(line, "%s/%s", db_path, "mercenary_db.txt");
-	memset(mercenary_db,0,sizeof(mercenary_db));
-
-	fp = fopen(line, "r");
-	if( !fp )
+	db = &mercenary_db[current];
+	db->class_ = atoi(str[0]);
+	strncpy(db->sprite, str[1], NAME_LENGTH);
+	strncpy(db->name, str[2], NAME_LENGTH);
+	db->lv = atoi(str[3]);
+
+	status = &db->status;
+	db->vd.class_ = db->class_;
+
+	status->max_hp = atoi(str[4]);
+	status->max_sp = atoi(str[5]);
+	status->rhw.range = atoi(str[6]);
+	status->rhw.atk = atoi(str[7]);
+	status->rhw.atk2 = status->rhw.atk + atoi(str[8]);
+	status->def = atoi(str[9]);
+	status->mdef = atoi(str[10]);
+	status->str = atoi(str[11]);
+	status->agi = atoi(str[12]);
+	status->vit = atoi(str[13]);
+	status->int_ = atoi(str[14]);
+	status->dex = atoi(str[15]);
+	status->luk = atoi(str[16]);
+	db->range2 = atoi(str[17]);
+	db->range3 = atoi(str[18]);
+	status->size = atoi(str[19]);
+	status->race = atoi(str[20]);
+
+	ele = atoi(str[21]);
+	status->def_ele = ele%10;
+	status->ele_lv = ele/20;
+	if( status->def_ele >= ELE_MAX )
 	{
-		ShowError("read_mercenarydb : can't read mercenary_db.txt\n");
-		return -1;
+		ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1);
+		status->def_ele = ELE_NEUTRAL;
 	}
-
-	while( fgets(line, sizeof(line), fp) && j < MAX_MERCENARY_CLASS )
+	if( status->ele_lv < 1 || status->ele_lv > 4 )
 	{
-		k++;
-		if( line[0] == '/' && line[1] == '/' )
-			continue;
-
-		i = 0;
-		p = strtok(line, ",");
-		while( p != NULL && i < 26 )
-		{
-			str[i++] = p;
-			p = strtok(NULL, ",");
-		}
-		if( i < 26 )
-		{
-			ShowError("read_mercenarydb : Incorrect number of columns at mercenary_db.txt line %d.\n", k);
-			continue;
-		}
-
-		db = &mercenary_db[j];
-		db->class_ = atoi(str[0]);
-		strncpy(db->sprite, str[1], NAME_LENGTH);
-		strncpy(db->name, str[2], NAME_LENGTH);
-		db->lv = atoi(str[3]);
-
-		status = &db->status;
-		db->vd.class_ = db->class_;
-
-		status->max_hp = atoi(str[4]);
-		status->max_sp = atoi(str[5]);
-		status->rhw.range = atoi(str[6]);
-		status->rhw.atk = atoi(str[7]);
-		status->rhw.atk2 = status->rhw.atk + atoi(str[8]);
-		status->def = atoi(str[9]);
-		status->mdef = atoi(str[10]);
-		status->str = atoi(str[11]);
-		status->agi = atoi(str[12]);
-		status->vit = atoi(str[13]);
-		status->int_ = atoi(str[14]);
-		status->dex = atoi(str[15]);
-		status->luk = atoi(str[16]);
-		db->range2 = atoi(str[17]);
-		db->range3 = atoi(str[18]);
-		status->size = atoi(str[19]);
-		status->race = atoi(str[20]);
-	
-		ele = atoi(str[21]);
-		status->def_ele = ele%10;
-		status->ele_lv = ele/20;
-		if( status->def_ele >= ELE_MAX )
-		{
-			ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1);
-			status->def_ele = ELE_NEUTRAL;
-		}
-		if( status->ele_lv < 1 || status->ele_lv > 4 )
-		{
-			ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
-			status->ele_lv = 1;
-		}
-
-		status->aspd_rate = 1000;
-		status->speed = atoi(str[22]);
-		status->adelay = atoi(str[23]);
-		status->amotion = atoi(str[24]);
-		status->dmotion = atoi(str[25]);
-
-		j++;
+		ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
+		status->ele_lv = 1;
 	}
 
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' mercenaries in '"CL_WHITE"db/mercenary_db.txt"CL_RESET"'.\n",j);
+	status->aspd_rate = 1000;
+	status->speed = atoi(str[22]);
+	status->adelay = atoi(str[23]);
+	status->amotion = atoi(str[24]);
+	status->dmotion = atoi(str[25]);
 
-	return 0;
+	return true;
 }
 
-int read_mercenary_skilldb(void)
+int read_mercenarydb(void)
 {
-	FILE *fp;
-	char line[1024], *p;
-	char *str[3];
+	memset(mercenary_db,0,sizeof(mercenary_db));
+	sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub);
+
+	return 0;
+}
+
+static bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
+{// <merc id>,<skill id>,<skill level>
 	struct s_mercenary_db *db;
-	int i, j = 0, k = 0, class_;
+	int i, class_;
 	int skillid, skilllv;
 
-	sprintf(line, "%s/%s", db_path, "mercenary_skill_db.txt");
-	fp = fopen(line, "r");
-	if( !fp )
+	class_ = atoi(str[0]);
+	ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_);
+	if( i == MAX_MERCENARY_CLASS )
 	{
-		ShowError("read_mercenary_skilldb : can't read mercenary_skill_db.txt\n");
-		return -1;
+		ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_);
+		return false;
 	}
-
-	while( fgets(line, sizeof(line), fp) )
+	
+	skillid = atoi(str[1]);
+	if( skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL )
 	{
-		k++;
-		if( line[0] == '/' && line[1] == '/' )
-			continue;
-
-		i = 0;
-		p = strtok(line, ",");
-		while( p != NULL && i < 3 )
-		{
-			str[i++] = p;
-			p = strtok(NULL, ",");
-		}
-		if( i < 3 )
-		{
-			ShowError("read_mercenary_skilldb : Incorrect number of columns at mercenary_skill_db.txt line %d.\n", k);
-			continue;
-		}
-
-		class_ = atoi(str[0]);
-		ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_);
-		if( i == MAX_MERCENARY_CLASS )
-		{
-			ShowError("read_mercenary_skilldb : Class not found in mercenary_db for skill entry, line %d.\n", k);
-			continue;
-		}
-		
-		skillid = atoi(str[1]);
-		if( skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL )
-		{
-			ShowError("read_mercenary_skilldb : Skill out of range, line %d.\n", k);
-			continue;
-		}
-
-		db = &mercenary_db[i];
-		skilllv = atoi(str[2]);
-
-		i = skillid - MC_SKILLBASE;
-		db->skill[i].id = skillid;
-		db->skill[i].lv = skilllv;
-		j++;
+		ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skillid);
+		return false;
 	}
 
-	fclose(fp);
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/mercenary_skill_db.txt"CL_RESET"'.\n",j);
+	db = &mercenary_db[i];
+	skilllv = atoi(str[2]);
+
+	i = skillid - MC_SKILLBASE;
+	db->skill[i].id = skillid;
+	db->skill[i].lv = skilllv;
+
+	return true;
+}
+
+int read_mercenary_skilldb(void)
+{
+	sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub);
+
 	return 0;
 }
 

+ 13 - 13
src/map/mob.c

@@ -1183,7 +1183,7 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick)
 
 	switch (md->state.skillstate) {
 	case MSS_WALK:
-		if (md->ud.walktimer != -1)
+		if (md->ud.walktimer != INVALID_TIMER)
 			break;
 		//Because it is not unset when the mob finishes walking.
 		md->state.skillstate = MSS_IDLE;
@@ -1274,7 +1274,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target)
 	if (target->m == md->bl.m && check_distance_bl(&md->bl, target, AREA_SIZE))
 		return 0; //No need to do a warp chase.
 
-	if (md->ud.walktimer != -1 &&
+	if (md->ud.walktimer != INVALID_TIMER &&
 		map_getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC))
 		return 1; //Already walking to a warp.
 
@@ -1306,10 +1306,10 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 
 	md->last_thinktime = tick;
 
-	if (md->ud.skilltimer != -1)
+	if (md->ud.skilltimer != INVALID_TIMER)
 		return false;
 
-	if(md->ud.walktimer != -1 && md->ud.walkpath.path_pos <= 3)
+	if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= 3)
 		return false;
 
 	// Abnormalities
@@ -1331,8 +1331,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	{	//Check validity of current target. [Skotlex]
 		tbl = map_id2bl(md->target_id);
 		if (!tbl || tbl->m != md->bl.m ||
-			(md->ud.attacktimer == -1 && !status_check_skilluse(&md->bl, tbl, 0, 0)) ||
-			(md->ud.walktimer != -1 && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase)) ||
+			(md->ud.attacktimer == INVALID_TIMER && !status_check_skilluse(&md->bl, tbl, 0, 0)) ||
+			(md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase)) ||
 			(
 				tbl->type == BL_PC &&
 				((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) ||
@@ -1447,7 +1447,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	if (tbl->type == BL_ITEM)
 	{	//Loot time.
 		struct flooritem_data *fitem;
-		if (md->ud.target == tbl->id && md->ud.walktimer != -1)
+		if (md->ud.target == tbl->id && md->ud.walktimer != INVALID_TIMER)
 			return true; //Already locked.
 		if (md->lootitem == NULL)
 		{	//Can't loot...
@@ -1469,7 +1469,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 			return true;
 		}
 		//Within looting range.
-		if (md->ud.attacktimer != -1)
+		if (md->ud.attacktimer != INVALID_TIMER)
 			return true; //Busy attacking?
 
 		fitem = (struct flooritem_data *)tbl;
@@ -1497,7 +1497,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	}
 	//Attempt to attack.
 	//At this point we know the target is attackable, we just gotta check if the range matches.
-	if (md->ud.target == tbl->id && md->ud.attacktimer != -1) //Already locked.
+	if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked.
 		return true;
 	
 	if (battle_check_range (&md->bl, tbl, md->status.rhw.range))
@@ -1526,7 +1526,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 		return true;
 	}
 
-	if (md->ud.walktimer != -1 && md->ud.target == tbl->id &&
+	if (md->ud.walktimer != INVALID_TIMER && md->ud.target == tbl->id &&
 		(
 			!(battle_config.mob_ai&0x1) ||
 			check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range)
@@ -2432,7 +2432,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 		md->status.hp = 1;
 	}
 
-	if(md->deletetimer!=-1) {
+	if(md->deletetimer != INVALID_TIMER) {
 		delete_timer(md->deletetimer,mob_timer_delete);
 		md->deletetimer = INVALID_TIMER;
 	}
@@ -2900,7 +2900,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 	nullpo_ret(md);
 	nullpo_ret(ms = md->db->skill);
 
-	if (!battle_config.mob_skill_rate || md->ud.skilltimer != -1 || !md->db->maxskill)
+	if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill)
 		return 0;
 
 	if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0)
@@ -4123,7 +4123,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
 			ms->target = MST_TARGET;
 		}
 	} else if (ms->target > MST_MASTER) {
-		ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s\n.",
+		ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n",
 			ms->skill_id, skill_get_name(ms->skill_id),
 			mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite);
 		ms->target = MST_TARGET;

+ 15 - 15
src/map/npc.c

@@ -493,10 +493,10 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr data)
 	else
 	{
 		if( sd )
-			sd->npc_timer_id = -1;
+			sd->npc_timer_id = INVALID_TIMER;
 		else
 		{
-			nd->u.scr.timerid = -1;
+			nd->u.scr.timerid = INVALID_TIMER;
 			nd->u.scr.timertick = 0; // NPC timer stopped
 		}
 		ers_free(timer_event_ers, ted);
@@ -544,10 +544,10 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
 	// Check if timer is already started.
 	if( sd )
 	{
-		if( sd->npc_timer_id != -1 )
+		if( sd->npc_timer_id != INVALID_TIMER )
 			return 0;
 	}
-	else if( nd->u.scr.timerid != -1 )
+	else if( nd->u.scr.timerid != INVALID_TIMER )
 		return 0;
 
 	// Arrange for the next event		
@@ -587,7 +587,7 @@ int npc_timerevent_stop(struct npc_data* nd)
 	}
 	
 	tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid;
-	if( *tid == -1 ) // Nothing to stop
+	if( *tid == INVALID_TIMER ) // Nothing to stop
 		return 0;
 
 	// Delete timer
@@ -595,7 +595,7 @@ int npc_timerevent_stop(struct npc_data* nd)
 	if( td && td->data ) 
 		ers_free(timer_event_ers, (void*)td->data);
 	delete_timer(*tid,npc_timerevent);
-	*tid = -1;
+	*tid = INVALID_TIMER;
 
 	if( !sd )
 	{
@@ -615,11 +615,11 @@ void npc_timerevent_quit(struct map_session_data* sd)
 	struct timer_event_data *ted;
 
 	// Check timer existance
-	if( sd->npc_timer_id == -1 )
+	if( sd->npc_timer_id == INVALID_TIMER )
 		return;
 	if( !(td = get_timer(sd->npc_timer_id)) )
 	{
-		sd->npc_timer_id = -1;
+		sd->npc_timer_id = INVALID_TIMER;
 		return;
 	}
 
@@ -627,7 +627,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
 	nd = (struct npc_data *)map_id2bl(td->id);
 	ted = (struct timer_event_data*)td->data;
 	delete_timer(sd->npc_timer_id, npc_timerevent);
-	sd->npc_timer_id = -1;
+	sd->npc_timer_id = INVALID_TIMER;
 
 	// Execute OnTimerQuit
 	if( nd && nd->bl.type == BL_NPC )
@@ -873,7 +873,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y)
 			{ // failed to run OnTouch event, so just click the npc
 				struct unit_data *ud = unit_bl2ud(&sd->bl);
 				if( ud && ud->walkpath.path_pos < ud->walkpath.path_len )
-				{ // Since walktimer always == -1 at this time, we stop walking manually. [Inkfish]
+				{ // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish]
 					clif_fixpos(&sd->bl);
 					ud->walkpath.path_pos = ud->walkpath.path_len;
 				}
@@ -1183,7 +1183,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
 	if( sd->state.trading )
 		return 4;
 
-	if( (item = itemdb_search(nameid)) == NULL )
+	if( (item = itemdb_exists(nameid)) == NULL )
 		return 5; // Invalid Item
 
 	ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid);
@@ -1600,7 +1600,7 @@ int npc_unload(struct npc_data* nd)
 		}  
 		mapit_free(iter);
 
-		if (nd->u.scr.timerid != -1) {
+		if (nd->u.scr.timerid != INVALID_TIMER) {
 			const struct TimerData *td = NULL;
 			td = get_timer(nd->u.scr.timerid);
 			if (td && td->data) 
@@ -2245,7 +2245,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
 			nd->u.scr.timeramount++;
 		}
 	}
-	nd->u.scr.timerid = -1;
+	nd->u.scr.timerid = INVALID_TIMER;
 
 	return end;
 }
@@ -2428,7 +2428,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
 			nd->u.scr.timeramount++;
 		}
 	}
-	nd->u.scr.timerid = -1;
+	nd->u.scr.timerid = INVALID_TIMER;
 
 	return end;
 }
@@ -3536,7 +3536,7 @@ int do_init_npc(void)
 	fake_nd->subtype = SCRIPT;
 
 	strdb_put(npcname_db, fake_nd->exname, fake_nd);
-	fake_nd->u.scr.timerid = -1;
+	fake_nd->u.scr.timerid = INVALID_TIMER;
 	map_addiddb(&fake_nd->bl);
 	// End of initialization
 

+ 2 - 2
src/map/party.c

@@ -298,11 +298,11 @@ int party_recv_info(struct party *sp)
 
 int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
 {
-	struct party_data *p=party_search(sd->status.party_id);
+	struct party_data *p;
 	int i,flag=0;
 	
 	nullpo_ret(sd);
-	if( p == NULL )
+	if( ( p = party_search(sd->status.party_id) ) == NULL )
 		return 0;
 	if( tsd == NULL) {	//TODO: Find the correct reply packet.
 		clif_displaymessage(sd->fd, msg_txt(3));

+ 43 - 49
src/map/pc.c

@@ -170,7 +170,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
 
 	if( sd->spiritball && sd->spiritball >= max )
 	{
-		if(sd->spirit_timer[0] != -1)
+		if(sd->spirit_timer[0] != INVALID_TIMER)
 			delete_timer(sd->spirit_timer[0],pc_spiritball_timer);
 		sd->spiritball--;
 		if( sd->spiritball != 0 )
@@ -209,14 +209,14 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
 		count = MAX_SKILL_LEVEL;
 
 	for(i=0;i<count;i++) {
-		if(sd->spirit_timer[i] != -1) {
+		if(sd->spirit_timer[i] != INVALID_TIMER) {
 			delete_timer(sd->spirit_timer[i],pc_spiritball_timer);
-			sd->spirit_timer[i] = -1;
+			sd->spirit_timer[i] = INVALID_TIMER;
 		}
 	}
 	for(i=count;i<MAX_SKILL_LEVEL;i++) {
 		sd->spirit_timer[i-count] = sd->spirit_timer[i];
-		sd->spirit_timer[i] = -1;
+		sd->spirit_timer[i] = INVALID_TIMER;
 	}
 
 	if(!type)
@@ -317,7 +317,7 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
 	if( sd->rental_timer != INVALID_TIMER )
 	{
 		delete_timer(sd->rental_timer, pc_inventory_rental_end);
-		sd->rental_timer = -1;
+		sd->rental_timer = INVALID_TIMER;
 	}
 
 	return 1;
@@ -892,9 +892,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	if (!(battle_config.display_skill_fail&2))
 		sd->state.showdelay = 1;
 		
-	// ƒAƒCƒeƒ€ƒ`ƒFƒbƒN
 	pc_setinventorydata(sd);
-	pc_checkitem(sd);
 
 	status_change_init(&sd->bl);
 	if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(atcommand_hide)))
@@ -912,7 +910,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 
 	// Event Timers
 	for( i = 0; i < MAX_EVENTTIMER; i++ )
-		sd->eventtimer[i] = -1;
+		sd->eventtimer[i] = INVALID_TIMER;
 	// Rental Timer
 	sd->rental_timer = INVALID_TIMER;
 
@@ -1418,9 +1416,9 @@ int pc_updateweightstatus(struct map_session_data *sd)
 
 	// stop old status change
 	if( old_overweight == 1 )
-		status_change_end(&sd->bl, SC_WEIGHT50, -1);
+		status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
 	else if( old_overweight == 2 )
-		status_change_end(&sd->bl, SC_WEIGHT90, -1);
+		status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
 
 	// start new status change
 	if( new_overweight == 1 )
@@ -3718,7 +3716,7 @@ int pc_useitem(struct map_session_data *sd,int n)
 	//perform a skill-use check before going through. [Skotlex]
 	//resurrection was picked as testing skill, as a non-offensive, generic skill, it will do.
 	//FIXME: Is this really needed here? It'll be checked in unit.c after all and this prevents skill items using when silenced [Inkfish]
-	if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != -1 /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
+	if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
 		return 0;
 
 	if( sd->inventory_data[n]->delay > 0 ) { // Check if there is a delay on this item [Paradox924X]
@@ -4118,21 +4116,15 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
 		{ // Cancel some map related stuff.
 			if (sd->sc.data[SC_JAILED])
 				return 1; //You may not get out!
-			if (sd->sc.data[SC_BOSSMAPINFO])
-				status_change_end(&sd->bl,SC_BOSSMAPINFO,-1);
-			if (sd->sc.data[SC_WARM])
-				status_change_end(&sd->bl,SC_WARM,-1);
-			if (sd->sc.data[SC_SUN_COMFORT])
-				status_change_end(&sd->bl,SC_SUN_COMFORT,-1);
-			if (sd->sc.data[SC_MOON_COMFORT])
-				status_change_end(&sd->bl,SC_MOON_COMFORT,-1);
-			if (sd->sc.data[SC_STAR_COMFORT])
-				status_change_end(&sd->bl,SC_STAR_COMFORT,-1);
-			if (sd->sc.data[SC_MIRACLE])
-				status_change_end(&sd->bl,SC_MIRACLE,-1);
+			status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_WARM, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
+			status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
 			if (sd->sc.data[SC_KNOWLEDGE]) {
 				struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
-				if (sce->timer != -1)
+				if (sce->timer != INVALID_TIMER)
 					delete_timer(sce->timer, status_change_timer);
 				sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE);
 			}
@@ -4404,17 +4396,17 @@ int pc_checkallowskill(struct map_session_data *sd)
 	{	// Skills requiring specific weapon types
 		if(sd->sc.data[scw_list[i]] &&
 			!pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i]))))
-			status_change_end(&sd->bl,scw_list[i],-1);
+			status_change_end(&sd->bl, scw_list[i], INVALID_TIMER);
 	}
 	
 	if(sd->sc.data[SC_SPURT] && sd->status.weapon)
 		// Spurt requires bare hands (feet, in fact xD)
-		status_change_end(&sd->bl,SC_SPURT,-1);
+		status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER);
 	
 	if(sd->status.shield <= 0) { // Skills requiring a shield
 		for (i = 0; i < ARRAYLENGTH(scs_list); i++)
 			if(sd->sc.data[scs_list[i]])
-				status_change_end(&sd->bl,scs_list[i],-1);
+				status_change_end(&sd->bl, scs_list[i], INVALID_TIMER);
 	}
 	return 0;
 }
@@ -4776,7 +4768,7 @@ int pc_follow_timer(int tid, unsigned int tick, int id, intptr data)
 	// either player or target is currently detached from map blocks (could be teleporting),
 	// but still connected to this map, so we'll just increment the timer and check back later
 	if (sd->bl.prev != NULL && tbl->prev != NULL &&
-		sd->ud.skilltimer == -1 && sd->ud.attacktimer == -1 && sd->ud.walktimer == -1)
+		sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER)
 	{
 		if((sd->bl.m == tbl->m) && unit_can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) {
 			if (!check_distance_bl(&sd->bl, tbl, 5))
@@ -4808,11 +4800,11 @@ int pc_follow(struct map_session_data *sd,int target_id)
 	struct block_list *bl = map_id2bl(target_id);
 	if (bl == NULL /*|| bl->type != BL_PC*/)
 		return 1;
-	if (sd->followtimer != -1)
+	if (sd->followtimer != INVALID_TIMER)
 		pc_stop_following(sd);
 
 	sd->followtarget = target_id;
-	pc_follow_timer(-1,gettick(),sd->bl.id,0);
+	pc_follow_timer(INVALID_TIMER, gettick(), sd->bl.id, 0);
 
 	return 0;
 }
@@ -5705,7 +5697,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	for(k = 0; k < 5; k++)
 	if (sd->devotion[k]){
 		struct map_session_data *devsd = map_id2sd(sd->devotion[k]);
-		if (devsd) status_change_end(&devsd->bl,SC_DEVOTION,-1);
+		if (devsd)
+			status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
 		sd->devotion[k] = 0;
 	}
 
@@ -5774,6 +5767,11 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			md->level++;
 			status_calc_mob(md, 0);
 			status_percent_heal(src,10,0);
+
+			if( battle_config.show_mob_info&4 )
+			{// update name with new level
+				clif_charnameack(0, &md->bl);
+			}
 		}
 		src = battle_get_master(src); // Maybe Player Summon
 	}
@@ -5854,7 +5852,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 				pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
 			sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill_get_time(MO_STEELBODY,1));
 			if(map_flag_gvg(sd->bl.m))
-				pc_respawn_timer(-1, gettick(), sd->bl.id, 0);
+				pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0);
 			return 0;
 		}
 	}
@@ -6352,7 +6350,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 			//Remove status specific to your current tree skills.
 			enum sc_type sc = status_skill2sc(id);
 			if (sc > SC_COMMON_MAX && sd->sc.data[sc])
-				status_change_end(&sd->bl, sc, -1);
+				status_change_end(&sd->bl, sc, INVALID_TIMER);
 		}
 	}
 	
@@ -6998,7 +6996,7 @@ static int pc_eventtimer(int tid, unsigned int tick, int id, intptr data)
 	ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == tid );
 	if( i < MAX_EVENTTIMER )
 	{
-		sd->eventtimer[i] = -1;
+		sd->eventtimer[i] = INVALID_TIMER;
 		sd->eventcount--;
 		npc_event(sd,p,0);
 	}
@@ -7017,7 +7015,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
 	int i;
 	nullpo_ret(sd);
 
-	ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == -1 );
+	ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER );
 	if( i == MAX_EVENTTIMER )
 		return 0;
 
@@ -7042,7 +7040,7 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
 
 	// find the named event timer
 	ARR_FIND( 0, MAX_EVENTTIMER, i,
-		sd->eventtimer[i] != -1 &&
+		sd->eventtimer[i] != INVALID_TIMER &&
 		(p = (char *)(get_timer(sd->eventtimer[i])->data)) != NULL &&
 		strcmp(p, name) == 0
 	);
@@ -7050,7 +7048,7 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
 		return 0; // not found
 
 	delete_timer(sd->eventtimer[i],pc_eventtimer);
-	sd->eventtimer[i]=-1;
+	sd->eventtimer[i] = INVALID_TIMER;
 	sd->eventcount--;
 	aFree(p);
 
@@ -7067,7 +7065,7 @@ int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick)
 	nullpo_ret(sd);
 
 	for(i=0;i<MAX_EVENTTIMER;i++)
-		if( sd->eventtimer[i]!=-1 && strcmp(
+		if( sd->eventtimer[i] != INVALID_TIMER && strcmp(
 			(char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){
 				addtick_timer(sd->eventtimer[i],tick);
 				break;
@@ -7089,10 +7087,10 @@ int pc_cleareventtimer(struct map_session_data *sd)
 		return 0;
 
 	for(i=0;i<MAX_EVENTTIMER;i++)
-		if( sd->eventtimer[i]!=-1 ){
+		if( sd->eventtimer[i] != INVALID_TIMER ){
 			char *p = (char *)(get_timer(sd->eventtimer[i])->data);
 			delete_timer(sd->eventtimer[i],pc_eventtimer);
-			sd->eventtimer[i]=-1;
+			sd->eventtimer[i] = INVALID_TIMER;
 			sd->eventcount--;
 			if (p) aFree(p);
 		}
@@ -7299,8 +7297,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 		sd->status.weapon = sd->weapontype2;
 		pc_calcweapontype(sd);
 		clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
-		if(sd->sc.data[SC_DANCING]) //When unequipping, stop dancing. [Skotlex]
-			status_change_end(&sd->bl, SC_DANCING, -1);
+		status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); //When unequipping, stop dancing. [Skotlex]
 	}
 	if(sd->status.inventory[n].equip & EQP_HAND_L) {
 		sd->status.shield = sd->weapontype2 = 0;
@@ -7330,10 +7327,8 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 
 	if(sd->status.inventory[n].equip & EQP_ARMOR) {
 		// On Armor Change...
-		if( sd->sc.data[SC_BENEDICTIO] )
-			status_change_end(&sd->bl, SC_BENEDICTIO, -1);
-		if( sd->sc.data[SC_ARMOR_RESIST] )
-			status_change_end(&sd->bl, SC_ARMOR_RESIST, -1);
+		status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
+		status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
 	}
 
 	if( sd->state.autobonus&sd->status.inventory[n].equip )
@@ -7347,7 +7342,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 	}
 
 	if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele))
-		status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+		status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER);
 
 	//OnUnEquip script [Skotlex]
 	if (sd->inventory_data[n]) {
@@ -7793,8 +7788,7 @@ int map_night_timer(int tid, unsigned int tick, int id, intptr data)
 void pc_setstand(struct map_session_data *sd){
 	nullpo_retv(sd);
 
-	if(sd->sc.data[SC_TENSIONRELAX])
-		status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
+	status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
 
 	//Reset sitting tick.
 	sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;

+ 1 - 2
src/map/pc.h

@@ -350,6 +350,7 @@ struct map_session_data {
 	int guildspy; // [Syrus22]
 	int partyspy; // [Syrus22]
 
+	int vended_id;
 	int vender_id;
 	int vend_num;
 	char message[MESSAGE_SIZE];
@@ -383,8 +384,6 @@ struct map_session_data {
 
 	int killerrid, killedrid;
 
-	char away_message[128]; // [LuzZza]
-
 	int cashPoints, kafraPoints;
 	int rental_timer;
 

+ 16 - 16
src/map/pet.c

@@ -180,7 +180,7 @@ int pet_sc_check(struct map_session_data *sd, int type)
 	if( pd == NULL
 	||  (battle_config.pet_equip_required && pd->pet.equip == 0)
 	||  pd->recovery == NULL
-	||  pd->recovery->timer != -1
+	||  pd->recovery->timer != INVALID_TIMER
 	||  pd->recovery->type != type )
 		return 1;
 
@@ -263,7 +263,7 @@ int search_petDB_index(int key,int type)
 int pet_hungry_timer_delete(struct pet_data *pd)
 {
 	nullpo_ret(pd);
-	if(pd->pet_hungry_timer != -1) {
+	if(pd->pet_hungry_timer != INVALID_TIMER) {
 		delete_timer(pd->pet_hungry_timer,pet_hungry);
 		pd->pet_hungry_timer = INVALID_TIMER;
 	}
@@ -666,14 +666,14 @@ int pet_equipitem(struct map_session_data *sd,int index)
 	if (battle_config.pet_equip_required)
 	{ 	//Skotlex: start support timers if need
 		unsigned int tick = gettick();
-		if (pd->s_skill && pd->s_skill->timer == -1)
+		if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER)
 		{
 			if (pd->s_skill->id)
 				pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_skill_support_timer, sd->bl.id, 0);
 			else
 				pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_heal_timer, sd->bl.id, 0);
 		}
-		if (pd->bonus && pd->bonus->timer == -1)
+		if (pd->bonus && pd->bonus->timer == INVALID_TIMER)
 			pd->bonus->timer=add_timer(tick+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0);
 	}
 
@@ -706,7 +706,7 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
 			pd->state.skillbonus = 0;
 			status_calc_pc(sd,0);
 		}
-		if( pd->s_skill && pd->s_skill->timer != -1 )
+		if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
 		{
 			if( pd->s_skill->id )
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
@@ -714,7 +714,7 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
 				delete_timer(pd->s_skill->timer, pet_heal_timer);
 			pd->s_skill->timer = INVALID_TIMER;
 		}
-		if( pd->bonus && pd->bonus->timer != -1 )
+		if( pd->bonus && pd->bonus->timer != INVALID_TIMER )
 		{
 			delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 			pd->bonus->timer = INVALID_TIMER;
@@ -825,10 +825,10 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 		return 0;
 	pd->last_thinktime=tick;
 
-	if(pd->ud.attacktimer != -1 || pd->ud.skilltimer != -1 || pd->bl.m != sd->bl.m)
+	if(pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m)
 		return 0;
 
-	if(pd->ud.walktimer != -1 && pd->ud.walkpath.path_pos <= 2)
+	if(pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2)
 		return 0; //No thinking when you just started to walk.
 
 	if(pd->pet.intimate <= 0) {
@@ -841,7 +841,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 		//Master too far, chase.
 		if(pd->target_id)
 			pet_unlocktarget(pd);
-		if(pd->ud.walktimer != -1 && pd->ud.target == sd->bl.id)
+		if(pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id)
 			return 0; //Already walking to him
 		if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0)
 			return 0; //Can't move yet.
@@ -855,7 +855,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 
 	//Return speed to normal.
 	if (pd->status.speed != pd->petDB->speed) {
-		if (pd->ud.walktimer != -1)
+		if (pd->ud.walktimer != INVALID_TIMER)
 			return 0; //Wait until the pet finishes walking back to master.
 		pd->status.speed = pd->petDB->speed;
 	}
@@ -881,7 +881,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 		if (check_distance_bl(&sd->bl, &pd->bl, 3))
 			return 0; //Already next to master.
 
-		if(pd->ud.walktimer != -1 && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3))
+		if(pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3))
 			return 0; //Already walking to him
 
 		unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
@@ -892,7 +892,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 	}
 	
 	if(pd->ud.target == target->id &&
-		(pd->ud.attacktimer != -1 || pd->ud.walktimer != -1))
+		(pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
 		return 0; //Target already locked.
 
 	if (target->type != BL_ITEM) 
@@ -915,7 +915,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
 			struct flooritem_data *fitem = (struct flooritem_data *)target;
 			if(pd->loot->count < pd->loot->max){
 				memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0]));
-				pd->loot->weight += itemdb_search(fitem->item_data.nameid)->weight*fitem->item_data.amount;
+				pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount;
 				map_clearflooritem(target->id);
 			} 
 			//Target is unlocked regardless of whether it was picked or not.
@@ -1099,7 +1099,7 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data)
 	{	//Display a heal animation? 
 		//Detoxify is chosen for now.
 		clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1);
-		status_change_end(&sd->bl,pd->recovery->type,-1);
+		status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER);
 		clif_emotion(&pd->bl, E_OK);
 	}
 
@@ -1130,7 +1130,7 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr data)
 	if(pc_isdead(sd) ||
 		(rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp ||
 		(rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp ||
-		(rate = (pd->ud.skilltimer != -1)) //Another skill is in effect
+		(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
 	) {  //Wait (how long? 1 sec for every 10% of remaining)
 		pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0);
 		return 0;
@@ -1173,7 +1173,7 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr data)
 	if(pc_isdead(sd) ||
 		(rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp ||
 		(rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp ||
-		(rate = (pd->ud.skilltimer != -1)) //Another skill is in effect
+		(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
 	) {  //Wait (how long? 1 sec for every 10% of remaining)
 		pd->s_skill->timer=add_timer(tick+(rate>10?rate:10)*100,pet_skill_support_timer,sd->bl.id,0);
 		return 0;

+ 86 - 41
src/map/script.c

@@ -70,6 +70,7 @@
 // - remove dynamic allocation in add_word()
 // - remove GETVALUE / SETVALUE
 // - clean up the set_reg / set_val / setd_sub mess
+// - detect invalid label references at parse-time
 
 //
 // struct script_state* st;
@@ -977,6 +978,23 @@ const char* parse_callfunc(const char* p, int require_paren)
 	return p;
 }
 
+/// Processes end of logical script line.
+/// @param first When true, only fix up scheduling data is initialized
+/// @param p Script position for error reporting in set_label
+static void parse_nextline(bool first, const char* p)
+{
+	if( !first )
+	{
+		add_scriptc(C_EOL);  // mark end of line for stack cleanup
+		set_label(LABEL_NEXTLINE, script_pos, p);  // fix up '-' labels
+	}
+
+	// initialize data for new '-' label fix up scheduling
+	str_data[LABEL_NEXTLINE].type      = C_NOP;
+	str_data[LABEL_NEXTLINE].backpatch = -1;
+	str_data[LABEL_NEXTLINE].label     = -1;
+}
+
 /*==========================================
  * 項の解析
  *------------------------------------------*/
@@ -1541,12 +1559,17 @@ const char* parse_syntax(const char* p)
 				// function declaration - just register the name
 				int l;
 				l = add_word(func_name);
-				if( str_data[l].type == C_NOP )// set type only if the name did not exist before
+				if( str_data[l].type == C_NOP )// register only, if the name was not used by something else
 					str_data[l].type = C_USERFUNC;
+				else if( str_data[l].type == C_USERFUNC )
+					;  // already registered
+				else
+					disp_error_message("parse_syntax:function: function name is invalid", func_name);
 
 				// if, for , while の閉じ判定
 				p = parse_syntax_close(p2 + 1);
-				return p;			}
+				return p;
+			}
 			else if(*p2 == '{')
 			{// function <name> <line/block of code>
 				char label[256];
@@ -1567,11 +1590,16 @@ const char* parse_syntax(const char* p)
 
 				// Set the position of the function (label)
 				l=add_word(func_name);
-				if( str_data[l].type == C_NOP )// set type only if the name did not exist before
+				if( str_data[l].type == C_NOP || str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
+				{
 					str_data[l].type = C_USERFUNC;
-				set_label(l, script_pos, p);
-				if( parse_options&SCRIPT_USE_LABEL_DB )
-					strdb_put(scriptlabel_db, get_str(l), (void*)script_pos);
+					set_label(l, script_pos, p);
+					if( parse_options&SCRIPT_USE_LABEL_DB )
+						strdb_put(scriptlabel_db, get_str(l), (void*)script_pos);
+				}
+				else
+					disp_error_message("parse_syntax:function: function name is invalid", func_name);
+
 				return skip_space(p);
 			}
 			else
@@ -1691,6 +1719,10 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
 	} else if(syntax.curly[pos].type == TYPE_IF) {
 		const char *bp = p;
 		const char *p2;
+
+		// if-block and else-block end is a new line
+		parse_nextline(false, p);
+
 		// if 最終場所へ飛ばす
 		sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index);
 		syntax.curly[syntax.curly_count++].type = TYPE_NULL;
@@ -1766,6 +1798,10 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
 		if(*p != '(') {
 			disp_error_message("need '('",p);
 		}
+
+		// do-block end is a new line
+		parse_nextline(false, p);
+
 		sprintf(label,"__DO%x_FIN",syntax.curly[pos].index);
 		add_scriptl(add_str("jump_zero"));
 		add_scriptc(C_ARG);
@@ -1793,6 +1829,9 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
 		syntax.curly_count--;
 		return p;
 	} else if(syntax.curly[pos].type == TYPE_FOR) {
+		// for-block end is a new line
+		parse_nextline(false, p);
+
 		// 次のループに飛ばす
 		sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index);
 		syntax.curly[syntax.curly_count++].type = TYPE_NULL;
@@ -1806,6 +1845,9 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
 		syntax.curly_count--;
 		return p;
 	} else if(syntax.curly[pos].type == TYPE_WHILE) {
+		// while-block end is a new line
+		parse_nextline(false, p);
+
 		// while 条件判断へ飛ばす
 		sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index);
 		syntax.curly[syntax.curly_count++].type = TYPE_NULL;
@@ -1974,6 +2016,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 	struct script_code* code = NULL;
 	static int first=1;
 	char end;
+	bool unresolved_names = false;
 
 	if( src == NULL )
 		return NULL;// empty script
@@ -1988,9 +2031,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 	script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
 	script_pos=0;
 	script_size=SCRIPT_BLOCK_SIZE;
-	str_data[LABEL_NEXTLINE].type=C_NOP;
-	str_data[LABEL_NEXTLINE].backpatch=-1;
-	str_data[LABEL_NEXTLINE].label=-1;
+	parse_nextline(true, NULL);
 
 	// who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
 	if( options&SCRIPT_USE_LABEL_DB )
@@ -2077,12 +2118,8 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 		// 他は全部一緒くた
 		p=parse_line(p);
 		p=skip_space(p);
-		add_scriptc(C_EOL);
 
-		set_label(LABEL_NEXTLINE,script_pos,p);
-		str_data[LABEL_NEXTLINE].type=C_NOP;
-		str_data[LABEL_NEXTLINE].backpatch=-1;
-		str_data[LABEL_NEXTLINE].label=-1;
+		parse_nextline(false, p);
 	}
 
 	add_scriptc(C_NOP);
@@ -2103,13 +2140,23 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 				j=next;
 			}
 		}
+		else if( str_data[i].type == C_USERFUNC )
+		{// 'function name;' without follow-up code
+			ShowError("parse_script: function '%s' declared but not defined.\n", str_buf+str_data[i].str);
+			unresolved_names = true;
+		}
+	}
+
+	if( unresolved_names )
+	{
+		disp_error_message("parse_script: unresolved function references", p);
 	}
 
 #ifdef DEBUG_DISP
 	for(i=0;i<script_pos;i++){
-		if((i&15)==0) printf("%04x : ",i);
+		if((i&15)==0) ShowMessage("%04x : ",i);
 		ShowMessage("%02x ",script_buf[i]);
-		if((i&15)==15) printf("\n");
+		if((i&15)==15) ShowMessage("\n");
 	}
 	ShowMessage("\n");
 #endif
@@ -3235,7 +3282,7 @@ int run_script_timer(int tid, unsigned int tick, int id, intptr data)
 		st->rid = 0;
 		st->state = END;
 	}
-	while( node && st->sleep.timer != -1 ) {
+	while( node && st->sleep.timer != INVALID_TIMER ) {
 		if( (int)node->key == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) {
 			script_erase_sleepdb(node);
 			st->sleep.timer = INVALID_TIMER;
@@ -4882,8 +4929,8 @@ BUILDIN_FUNC(setarray)
 	}
 
 	end = start + script_lastdata(st) - 2;
-	if( end >= SCRIPT_MAX_ARRAYSIZE )
-		end = SCRIPT_MAX_ARRAYSIZE-1;
+	if( end > SCRIPT_MAX_ARRAYSIZE )
+		end = SCRIPT_MAX_ARRAYSIZE;
 
 	if( is_string_variable(name) )
 	{// string array
@@ -4945,10 +4992,10 @@ BUILDIN_FUNC(cleararray)
 		v = (void*)script_getnum(st, 3);
 
 	end = start + script_getnum(st, 4);
-	if( end >= SCRIPT_MAX_ARRAYSIZE )
-		end = SCRIPT_MAX_ARRAYSIZE-1;
+	if( end > SCRIPT_MAX_ARRAYSIZE )
+		end = SCRIPT_MAX_ARRAYSIZE;
 
-	for( ; start <= end; ++start )
+	for( ; start < end; ++start )
 		set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2));
 	return 0;
 }
@@ -5015,8 +5062,8 @@ BUILDIN_FUNC(copyarray)
 	}
 
 	count = script_getnum(st, 4);
-	if( count >= SCRIPT_MAX_ARRAYSIZE - idx1 )
-		count = (SCRIPT_MAX_ARRAYSIZE-1) - idx1;
+	if( count > SCRIPT_MAX_ARRAYSIZE - idx1 )
+		count = SCRIPT_MAX_ARRAYSIZE - idx1;
 	if( count <= 0 || (id1 == id2 && idx1 == idx2) )
 		return 0;// nothing to copy
 
@@ -5121,7 +5168,8 @@ BUILDIN_FUNC(deletearray)
 			return 0;// no player attached
 	}
 
-	end = getarraysize(st, id, start, is_string_variable(name), reference_getref(data));
+	end = SCRIPT_MAX_ARRAYSIZE;
+
 	if( start >= end )
 		return 0;// nothing to free
 
@@ -6191,7 +6239,7 @@ BUILDIN_FUNC(readparam)
 	if( script_hasdata(st,3) )
 		sd=map_nick2sd(script_getstr(st,3));
 	else
-	sd=script_rid2sd(st);
+		sd=script_rid2sd(st);
 
 	if(sd==NULL){
 		script_pushint(st,-1);
@@ -8321,10 +8369,10 @@ BUILDIN_FUNC(getnpctimer)
 				ShowError("buildin_getnpctimer: Attached player not found!\n");
 				break;
 			}
-			val = (sd->npc_timer_id != -1);
+			val = (sd->npc_timer_id != INVALID_TIMER);
 		}
 		else
-			val = (nd->u.scr.timerid !=-1);
+			val = (nd->u.scr.timerid != INVALID_TIMER);
 		break;
 	case 2: val = nd->u.scr.timeramount; break;
 	}
@@ -9705,7 +9753,7 @@ BUILDIN_FUNC(pvpon)
 	iter = mapit_getallusers();
 	for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
 	{
-		if( sd->bl.m != m || sd->pvp_timer != -1 )
+		if( sd->bl.m != m || sd->pvp_timer != INVALID_TIMER )
 			continue; // not applicable
 
 		sd->pvp_timer = add_timer(gettick()+200,pc_calc_pvprank_timer,sd->bl.id,0);
@@ -9724,7 +9772,7 @@ static int buildin_pvpoff_sub(struct block_list *bl,va_list ap)
 {
 	TBL_PC* sd = (TBL_PC*)bl;
 	clif_pvpset(sd, 0, 0, 2);
-	if (sd->pvp_timer != -1) {
+	if (sd->pvp_timer != INVALID_TIMER) {
 		delete_timer(sd->pvp_timer, pc_calc_pvprank_timer);
 		sd->pvp_timer = INVALID_TIMER;
 	}
@@ -10809,7 +10857,7 @@ BUILDIN_FUNC(petskillbonus)
 	pd=sd->pd;
 	if (pd->bonus)
 	{ //Clear previous bonus
-		if (pd->bonus->timer != -1)
+		if (pd->bonus->timer != INVALID_TIMER)
 			delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 	} else //init
 		pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus));
@@ -11162,7 +11210,7 @@ BUILDIN_FUNC(petrecovery)
 	
 	if (pd->recovery)
 	{ //Halt previous bonus
-		if (pd->recovery->timer != -1)
+		if (pd->recovery->timer != INVALID_TIMER)
 			delete_timer(pd->recovery->timer, pet_recovery_timer);
 	} else //Init
 		pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery));
@@ -11188,7 +11236,7 @@ BUILDIN_FUNC(petheal)
 	pd=sd->pd;
 	if (pd->s_skill)
 	{ //Clear previous skill
-		if (pd->s_skill->timer != -1)
+		if (pd->s_skill->timer != INVALID_TIMER)
 		{
 			if (pd->s_skill->id)
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
@@ -11282,7 +11330,7 @@ BUILDIN_FUNC(petskillsupport)
 	pd=sd->pd;
 	if (pd->s_skill)
 	{ //Clear previous skill
-		if (pd->s_skill->timer != -1)
+		if (pd->s_skill->timer != INVALID_TIMER)
 		{
 			if (pd->s_skill->id)
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
@@ -11636,9 +11684,6 @@ BUILDIN_FUNC(jump_zero)
 		pos=script_getnum(st,3);
 		st->pos=pos;
 		st->state=GOTO;
-		// printf("script: jump_zero: jumpto : %d\n",pos);
-	} else {
-		// printf("script: jump_zero: fail\n");
 	}
 	return 0;
 }
@@ -12312,7 +12357,7 @@ BUILDIN_FUNC(autoequip)
 	struct item_data *item_data;
 	nameid=script_getnum(st,2);
 	flag=script_getnum(st,3);
-	if(nameid>=500 && (item_data = itemdb_search(nameid)) != NULL){
+	if(nameid>=500 && (item_data = itemdb_exists(nameid)) != NULL){
 		item_data->flag.autoequip = flag>0?1:0;
 	}
 	return 0;
@@ -12362,7 +12407,7 @@ BUILDIN_FUNC(charisalpha)
 	const char *str=script_getstr(st,2);
 	int pos=script_getnum(st,3);
 
-	int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISALPHA( str[pos] ) : 0;
+	int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISALPHA( str[pos] ) != 0 : 0;
 
 	script_pushint(st,val);
 	return 0;
@@ -13557,7 +13602,7 @@ BUILDIN_FUNC(awake)
 			struct script_state* tst = (struct script_state*)node->data;
 			TBL_PC* sd = map_id2sd(tst->rid);
 
-			if( tst->sleep.timer == -1 )
+			if( tst->sleep.timer == INVALID_TIMER )
 			{// already awake ???
 				node = node->next;
 				continue;
@@ -14590,7 +14635,7 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
 	if( md->class_ != mobid )
 		return 0;
 
-	if( md->ud.skilltimer != -1 ) // Cancel the casting skill.
+	if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill.
 		unit_skillcastcancel(bl,0);
 
 	// 0:self, 1:target, 2:master, default:random

+ 104 - 121
src/map/skill.c

@@ -611,7 +611,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 					rate = 20;
 					if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) {
 						rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100;
-						status_change_end(src,SC_SKILLRATE_UP,-1);
+						status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
 					}
 					sc_start4(src,SC_COMBO, rate, TK_COUNTER, bl->id,0,0,
 						(2000 - 4*sstatus->agi - 2*sstatus->dex));
@@ -883,12 +883,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 	case TK_JUMPKICK:
 		if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] )
 		{// debuff the following statuses
-			status_change_end(bl, SC_SPIRIT, -1);
-			status_change_end(bl, SC_ADRENALINE2, -1);
-			status_change_end(bl, SC_KAITE, -1);
-			status_change_end(bl, SC_KAAHI, -1);
-			status_change_end(bl, SC_ONEHAND, -1);
-			status_change_end(bl, SC_ASPDPOTION2, -1);
+			status_change_end(bl, SC_SPIRIT, INVALID_TIMER);
+			status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
+			status_change_end(bl, SC_KAITE, INVALID_TIMER);
+			status_change_end(bl, SC_KAAHI, INVALID_TIMER);
+			status_change_end(bl, SC_ONEHAND, INVALID_TIMER);
+			status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER);
 		}
 		break;
 	case TK_TURNKICK:
@@ -1544,7 +1544,7 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in
 	{// Kaite only works against non-players if they are low-level.
 		clif_specialeffect(bl, 438, AREA);
 		if( --sc->data[SC_KAITE]->val2 <= 0 )
-			status_change_end(bl, SC_KAITE, -1);
+			status_change_end(bl, SC_KAITE, INVALID_TIMER);
 		return 2;
 	}
 
@@ -1719,7 +1719,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 				break;
 			default:
 				if( src == dsrc ) // Ground skills are exceptions. [Inkfish]
-					status_change_end(src,SC_COMBO,-1);
+					status_change_end(src, SC_COMBO, INVALID_TIMER);
 			}
 		}
 		switch(skillid)
@@ -1904,7 +1904,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 			status_fix_damage(NULL, d_bl, damage, 0);
 		}
 		else
-			status_change_end(bl, SC_DEVOTION, -1);
+			status_change_end(bl, SC_DEVOTION, INVALID_TIMER);
 	}
 
 	if(skillid == RG_INTIMIDATE && damage > 0 && !(tstatus->mode&MD_BOSS)) {
@@ -2338,8 +2338,7 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr data)
 					} else {
 						struct status_change *sc = status_get_sc(src);
 						if(sc) {
-							if(sc->data[SC_MAGICPOWER])
-								status_change_end(src,SC_MAGICPOWER,-1);
+							status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 							if(sc->data[SC_SPIRIT] &&
 								sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 								sc->data[SC_SPIRIT]->val3 == skl->skill_id)
@@ -2469,7 +2468,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 	{	//GTB makes all targetted magic display miss with a single bolt.
 		sc_type sct = status_skill2sc(skillid);
 		if(sct != SC_NONE)
-			status_change_end(bl, sct, -1);
+			status_change_end(bl, sct, INVALID_TIMER);
 		clif_skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skillid, skilllv, skill_get_hit(skillid));
 		return 1;
 	}
@@ -2662,16 +2661,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 
 	case MO_INVESTIGATE:
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		if (sc && sc->data[SC_BLADESTOP])
-			status_change_end(src,SC_BLADESTOP,-1);
+		status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
 		break;
 
 	case RG_BACKSTAP:
 		{
 			int dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl);
 			if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
-				if (sc && sc->data[SC_HIDING])
-					status_change_end(src, SC_HIDING, -1);
+				status_change_end(src, SC_HIDING, INVALID_TIMER);
 				skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
 				dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
 				unit_setdir(bl,dir);
@@ -2688,25 +2685,23 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 			for (i = 1; i < sd->spiritball_old; i++)
 				skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag);
 		}
-		if (sc && sc->data[SC_BLADESTOP])
-			status_change_end(src,SC_BLADESTOP,-1);
+		status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
 		break;
 
 	case MO_CHAINCOMBO:
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		if (sc && sc->data[SC_BLADESTOP])
-			status_change_end(src,SC_BLADESTOP,-1);
+		status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
 		break;
 
 	case NJ_ISSEN:
-		status_change_end(src,SC_NEN,-1);
-		status_change_end(src,SC_HIDING,-1);
+		status_change_end(src, SC_NEN, INVALID_TIMER);
+		status_change_end(src, SC_HIDING, INVALID_TIMER);
 		// fall through
 	case MO_EXTREMITYFIST:
 		if( skillid == MO_EXTREMITYFIST )
 		{
-			status_change_end(src,SC_EXPLOSIONSPIRITS,-1);
-			status_change_end(src,SC_BLADESTOP,-1);
+			status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
+			status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
 		}
 		//Client expects you to move to target regardless of distance
 		{
@@ -2991,8 +2986,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 	break;
 
 	case SL_SMA:
-		if (sc && sc->data[SC_SMA])
-			status_change_end(src,SC_SMA,-1);
+		status_change_end(src, SC_SMA, INVALID_TIMER);
 	case SL_STIN:
 	case SL_STUN:
 		if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
@@ -3065,8 +3059,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 			if (unit_movepos(src, x, y, 0, 0))
 				clif_slide(src,src->x,src->y);
 		}
-		if (sc && sc->data[SC_HIDING])
-			status_change_end(src, SC_HIDING, -1);
+		status_change_end(src, SC_HIDING, INVALID_TIMER);
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 	case 0:
@@ -3208,7 +3201,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) )
 				{ //Bounce back heal
 					if (--tsc->data[SC_KAITE]->val2 <= 0)
-						status_change_end(bl, SC_KAITE, -1);
+						status_change_end(bl, SC_KAITE, INVALID_TIMER);
 					if (src == bl)
 						heal=0; //When you try to heal yourself under Kaite, the heal is voided.
 					else {
@@ -3327,7 +3320,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case PR_LEXDIVINA:
 	case MER_LEXDIVINA:
 		if( tsce )
-			status_change_end(bl,type, -1);
+			status_change_end(bl,type, INVALID_TIMER);
 		else
 			sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
 		clif_skill_nodamage (src, bl, skillid, skilllv, 1);
@@ -3441,9 +3434,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			{
 				const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP };
 				for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++)
-					if (tsc->data[i]) status_change_end(bl, (sc_type)i, -1);
+					if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER);
 				for (i = 0; i < ARRAYLENGTH(scs); i++)
-					if (tsc->data[scs[i]]) status_change_end(bl, scs[i], -1);
+					if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
 			}
 		}
 		break;
@@ -3508,8 +3501,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				if(  sc->data[SC_MARIONETTE ] &&  sc->data[SC_MARIONETTE ]->val1 == bl->id &&
 					tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id )
 				{
-					status_change_end(src, SC_MARIONETTE, -1);
-					status_change_end(bl, SC_MARIONETTE2, -1);
+					status_change_end(src, SC_MARIONETTE, INVALID_TIMER);
+					status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER);
 				}
 				else
 				{
@@ -3698,8 +3691,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case NJ_BUNSINJYUTSU:
 		clif_skill_nodamage(src,bl,skillid,skilllv,
 			sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
-		if (tsc && tsc->data[SC_NEN])
-			status_change_end(bl,SC_NEN,-1);
+		status_change_end(bl, SC_NEN, INVALID_TIMER);
 		break;
 /* Was modified to only affect targetted char.	[Skotlex]
 	case HP_ASSUMPTIO:
@@ -3804,12 +3796,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 
 		if( tsc && tsc->count )
 		{
-			if( tsc->data[SC_FREEZE] )
-				status_change_end(bl,SC_FREEZE,-1);
+			status_change_end(bl, SC_FREEZE, INVALID_TIMER);
 			if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE )
-				status_change_end(bl,SC_STONE,-1);
-			if( tsc->data[SC_SLEEP] )
-				status_change_end(bl,SC_SLEEP,-1);
+				status_change_end(bl, SC_STONE, INVALID_TIMER);
+			status_change_end(bl, SC_SLEEP, INVALID_TIMER);
 		}
 
 		if( dstmd )
@@ -3947,7 +3937,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			skill_get_splash(skillid, skilllv), splash_target(src),
 			src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
 			skill_castend_damage_id);
-		status_change_end(src, SC_HIDING, -1);
+		status_change_end(src, SC_HIDING, INVALID_TIMER);
 		break;
 
 	case ASC_METEORASSAULT:
@@ -4016,7 +4006,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 
 	case WZ_SIGHTRASHER:
 		//Passive side of the attack.
-		status_change_end(src,SC_SIGHT,-1);
+		status_change_end(src, SC_SIGHT, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		map_foreachinrange(skill_area_sub,src,
 			skill_get_splash(skillid, skilllv),BL_CHAR|BL_SKILL,
@@ -4104,7 +4094,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case GS_GATLINGFEVER:
 		if( tsce )
 		{
-			clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, -1));
+			clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER));
 			map_freeblock_unlock();
 			return 0;
 		}
@@ -4133,7 +4123,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case SM_AUTOBERSERK:
 	case MER_AUTOBERSERK:
 		if( tsce )
-			i = status_change_end(bl, type, -1);
+			i = status_change_end(bl, type, INVALID_TIMER);
 		else
 			i = sc_start(bl,type,100,skilllv,60000);
 		clif_skill_nodamage(src,bl,skillid,skilllv,i);
@@ -4142,7 +4132,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case ST_CHASEWALK:
 		if (tsce)
 		{
-			clif_skill_nodamage(src,bl,skillid,-1,status_change_end(bl, type, -1)); //Hide skill-scream animation.
+			clif_skill_nodamage(src,bl,skillid,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation.
 			map_freeblock_unlock();
 			return 0;
 		}
@@ -4151,7 +4141,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case TK_RUN:
 		if (tsce)
 		{
-			clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, -1));
+			clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER));
 			map_freeblock_unlock();
 			return 0;
 		}
@@ -4162,7 +4152,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case AS_CLOAKING:
 		if (tsce)
 		{
-			i = status_change_end(bl, type, -1);
+			i = status_change_end(bl, type, INVALID_TIMER);
 			if( i )
 				clif_skill_nodamage(src,bl,skillid,-1,i);
 			else if( sd )
@@ -4180,7 +4170,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case BD_ADAPTATION:
 		if(tsc && tsc->data[SC_DANCING]){
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-			status_change_end(bl, SC_DANCING, -1);
+			status_change_end(bl, SC_DANCING, INVALID_TIMER);
 		}
 		break;
 
@@ -4253,7 +4243,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				break;
 
 			if (tsc->data[SC_STONE]) {
-				status_change_end(bl,SC_STONE,-1);
+				status_change_end(bl, SC_STONE, INVALID_TIMER);
 				if (sd) clif_skill_fail(sd,skillid,0,0);
 				break;
 			}
@@ -4283,16 +4273,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			clif_skill_nodamage(src,bl,skillid,skilllv,0);
 			break;
 		}
-		status_change_end(bl, SC_SILENCE	, -1 );
-		status_change_end(bl, SC_BLIND	, -1 );
-		status_change_end(bl, SC_CONFUSION, -1 );
+		status_change_end(bl, SC_SILENCE, INVALID_TIMER);
+		status_change_end(bl, SC_BLIND, INVALID_TIMER);
+		status_change_end(bl, SC_CONFUSION, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 
 	case TF_DETOXIFY:
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		status_change_end(bl, SC_POISON	, -1 );
-		status_change_end(bl, SC_DPOISON	, -1 );
+		status_change_end(bl, SC_POISON, INVALID_TIMER);
+		status_change_end(bl, SC_DPOISON, INVALID_TIMER);
 		break;
 
 	case PR_STRECOVERY:
@@ -4301,10 +4291,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			break;
 		}
 		if (tsc && tsc->opt1) {
-			status_change_end(bl, SC_FREEZE, -1 );
-			status_change_end(bl, SC_STONE, -1 );
-			status_change_end(bl, SC_SLEEP, -1 );
-			status_change_end(bl, SC_STUN, -1 );
+			status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+			status_change_end(bl, SC_STONE, INVALID_TIMER);
+			status_change_end(bl, SC_SLEEP, INVALID_TIMER);
+			status_change_end(bl, SC_STUN, INVALID_TIMER);
 		}
 		//Is this equation really right? It looks so... special.
 		if(battle_check_undead(tstatus->race,tstatus->def_ele))
@@ -4321,31 +4311,31 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 
 	// Mercenary Supportive Skills
 	case MER_BENEDICTION:
-		status_change_end(bl, SC_CURSE, -1);
-		status_change_end(bl, SC_BLIND, -1);
+		status_change_end(bl, SC_CURSE, INVALID_TIMER);
+		status_change_end(bl, SC_BLIND, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 	case MER_COMPRESS:
-		status_change_end(bl, SC_BLEEDING, -1);
+		status_change_end(bl, SC_BLEEDING, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 	case MER_MENTALCURE:
-		status_change_end(bl, SC_CONFUSION, -1);
+		status_change_end(bl, SC_CONFUSION, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 	case MER_RECUPERATE:
-		status_change_end(bl, SC_POISON, -1);
-		status_change_end(bl, SC_SILENCE, -1);
+		status_change_end(bl, SC_POISON, INVALID_TIMER);
+		status_change_end(bl, SC_SILENCE, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 	case MER_REGAIN:
-		status_change_end(bl, SC_SLEEP, -1);
-		status_change_end(bl, SC_STUN, -1);
+		status_change_end(bl, SC_SLEEP, INVALID_TIMER);
+		status_change_end(bl, SC_STUN, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 	case MER_TENDER:
-		status_change_end(bl, SC_FREEZE, -1);
-		status_change_end(bl, SC_STONE, -1);
+		status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+		status_change_end(bl, SC_STONE, INVALID_TIMER);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		break;
 
@@ -4642,8 +4632,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case AM_CP_HELM:
 		{
 			enum sc_type scid = (sc_type)(SC_STRIPWEAPON + (skillid - AM_CP_WEAPON));
-			if(tsc && tsc->data[scid])
-				status_change_end(bl, scid, -1 );
+			status_change_end(bl, scid, INVALID_TIMER);
 			clif_skill_nodamage(src,bl,skillid,skilllv,
 				sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
 		}
@@ -4735,7 +4724,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 					break;
 				}
 				if(i==SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
-				status_change_end(bl,(sc_type)i,-1);
+				status_change_end(bl, (sc_type)i, INVALID_TIMER);
 			}
 			break;
 		}
@@ -4796,7 +4785,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			} else {
 				struct unit_data *ud = unit_bl2ud(bl);
 				int bl_skillid=0,bl_skilllv=0,hp = 0;
-				if (!ud || ud->skilltimer == -1) break; //Nothing to cancel.
+				if (!ud || ud->skilltimer == INVALID_TIMER)
+					break; //Nothing to cancel.
 				bl_skillid = ud->skillid;
 				bl_skilllv = ud->skilllv;
 				if (tstatus->mode & MD_BOSS)
@@ -5021,7 +5011,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		{
 			clif_emotion(bl, md->db->skill[md->skillidx].val[0]);
 			if(md->db->skill[md->skillidx].val[4] && tsce)
-				status_change_end(bl, type, -1);
+				status_change_end(bl, type, INVALID_TIMER);
 
 			if(md->db->skill[md->skillidx].val[1] || md->db->skill[md->skillidx].val[2])
 				sc_start4(src, type, 100, skilllv,
@@ -5225,12 +5215,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			unit_skillcastcancel(bl,0);
 
 			if(tsc && tsc->count){
-				if(tsc->data[SC_FREEZE])
-					status_change_end(bl,SC_FREEZE,-1);
+				status_change_end(bl, SC_FREEZE, INVALID_TIMER);
 				if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)
-					status_change_end(bl,SC_STONE,-1);
-				if(tsc->data[SC_SLEEP])
-					status_change_end(bl,SC_SLEEP,-1);
+					status_change_end(bl, SC_STONE, INVALID_TIMER);
+				status_change_end(bl, SC_SLEEP, INVALID_TIMER);
 			}
 
 			if(dstmd)
@@ -5297,8 +5285,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				break;
 			}
 			for (i=0; i<4; i++) {
-				if(tsc->data[SC_STRIPWEAPON + i])
-					status_change_end(bl, (sc_type)(SC_STRIPWEAPON + i), -1 );
+				status_change_end(bl, (sc_type)(SC_STRIPWEAPON + i), INVALID_TIMER);
 				sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skilllv,skilltime);
 			}
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -5771,7 +5758,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 			return 0;
 		}
 
-		if( sd && ud->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0 )
+		if( sd && ud->skilltimer != INVALID_TIMER && pc_checkskill(sd,SA_FREECAST) > 0 )
 		{// restore original walk speed
 			ud->skilltimer = INVALID_TIMER;
 			status_calc_bl(&sd->bl, SCB_SPEED);
@@ -5875,7 +5862,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 		}
 
 		//Avoid doing double checks for instant-cast skills.
-		if (tid != -1 && !status_check_skilluse(src, target, ud->skillid, 1))
+		if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skillid, 1))
 			break;
 
 		if(md) {
@@ -5909,7 +5896,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 		if (ud->state.running && ud->skillid == TK_JUMPKICK)
 			flag = 1;
 
-		if (ud->walktimer != -1 && ud->skillid != TK_RUN)
+		if (ud->walktimer != INVALID_TIMER && ud->skillid != TK_RUN)
 			unit_stop_walking(src,1);
 
 		if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) )
@@ -5952,7 +5939,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 		if(sc && sc->count) {
 		  	if(sc->data[SC_MAGICPOWER] &&
 				ud->skillid != HW_MAGICPOWER && ud->skillid != WZ_WATERBALL)
-				status_change_end(src,SC_MAGICPOWER,-1);
+				status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 			if(sc->data[SC_SPIRIT] &&
 				sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 				sc->data[SC_SPIRIT]->val3 == ud->skillid &&
@@ -5966,7 +5953,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 		if( sd && ud->skillid != SA_ABRACADABRA ) // Hocus-Pocus has just set the data so leave it as it is.[Inkfish]
 			sd->skillitem = sd->skillitemlv = 0;
 
-		if (ud->skilltimer == -1) {
+		if (ud->skilltimer == INVALID_TIMER) {
 			if(md) md->skillidx = -1;
 			else ud->skillid = 0; //mobs can't clear this one as it is used for skill condition 'afterskill'
 			ud->skilllv = ud->skilltarget = 0;
@@ -5984,10 +5971,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
 		sc = &sd->sc;
 		if (sc->count)
 		{	//End states
-			if (sc->data[SC_EXPLOSIONSPIRITS])
-				status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
-			if (sc->data[SC_BLADESTOP])
-				status_change_end(src,SC_BLADESTOP,-1);
+			status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
+			status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
 		}
 		if (target && target->m == src->m)
 		{	//Move character to target anyway.
@@ -6049,7 +6034,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
 		return 0;
 	}
 
-	if( sd && ud->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0 )
+	if( sd && ud->skilltimer != INVALID_TIMER && pc_checkskill(sd,SA_FREECAST) > 0 )
 	{// restore original walk speed
 		ud->skilltimer = INVALID_TIMER;
 		status_calc_bl(&sd->bl, SCB_SPEED);
@@ -6091,7 +6076,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
 			}
 		}
 
-		if(tid != -1)
+		if(tid != INVALID_TIMER)
 		{	//Avoid double checks on instant cast skills. [Skotlex]
 			if (!status_check_skilluse(src, NULL, ud->skillid, 1))
 				break;
@@ -6124,7 +6109,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
 			ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n",
 				src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly);
 
-		if (ud->walktimer != -1)
+		if (ud->walktimer != INVALID_TIMER)
 			unit_stop_walking(src,1);
 
 		if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) )
@@ -6148,7 +6133,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
 		if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
 			sd->skillitem = sd->skillitemlv = 0;
 
-		if (ud->skilltimer == -1) {
+		if (ud->skilltimer == INVALID_TIMER) {
 			if (md) md->skillidx = -1;
 			else ud->skillid = 0; //Non mobs can't clear this one as it is used for skill condition 'afterskill'
 			ud->skilllv = ud->skillx = ud->skilly = 0;
@@ -6335,7 +6320,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 		break;
 	case HP_BASILICA:
 		if( sc->data[SC_BASILICA] )
-			status_change_end(src, SC_BASILICA, -1); // Cancel Basilica
+			status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica
 		else
 		{ // Create Basilica. Start SC on caster. Unit timer start SC on others.
 			skill_clear_unitgroup(src);
@@ -6408,8 +6393,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			unit_movepos(src, x, y, 1, 0);
 			clif_slide(src,x,y);
 		}
-		if (sc && sc->data[SC_HIDING])
-			status_change_end(src, SC_HIDING, -1);
+		status_change_end(src, SC_HIDING, INVALID_TIMER);
 		break;
 	case AM_SPHEREMINE:
 	case AM_CANNIBALIZE:
@@ -6544,7 +6528,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 	case PA_GOSPEL:
 		if (sce && sce->val4 == BCT_SELF)
 		{
-			status_change_end(src,SC_GOSPEL,-1);
+			status_change_end(src, SC_GOSPEL, INVALID_TIMER);
 			return 0;
 		}
 		else
@@ -6552,7 +6536,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
 			if (!sg) break;
 			if (sce)
-				status_change_end(src,type,-1); //Was under someone else's Gospel. [Skotlex]
+				status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex]
 			sc_start4(src,type,100,skilllv,0,sg->group_id,BCT_SELF,skill_get_time(skillid,skilllv));
 			clif_skill_poseffect(src, skillid, skilllv, 0, 0, tick); // PA_GOSPEL music packet
 		}
@@ -6578,8 +6562,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 		return 1;
 	}
 
-	if (sc && sc->data[SC_MAGICPOWER])
-		status_change_end(src,SC_MAGICPOWER,-1);
+	status_change_end(src, SC_MAGICPOWER, INVALID_TIMER);
 
 	if( sd )
 	{
@@ -7807,17 +7790,17 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
 	case UNT_SAFETYWALL:
 	case UNT_PNEUMA:
 		if (sce)
-			status_change_end(bl,type,-1);
+			status_change_end(bl, type, INVALID_TIMER);
 		break;
 
 	case UNT_BASILICA:
 		if( sce && sce->val4 == src->bl.id )
-			status_change_end(bl,type,-1);
+			status_change_end(bl, type, INVALID_TIMER);
 		break;
 
 	case UNT_HERMODE:	//Clear Hermode if the owner moved.
 		if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id)
-			status_change_end(bl,type,-1);
+			status_change_end(bl, type, INVALID_TIMER);
 		break;
 
 	case UNT_SPIDERWEB:
@@ -7826,7 +7809,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
 			if (target && target==bl)
 			{
 				if (sce && sce->val3 == sg->group_id)
-					status_change_end(bl,type,-1);
+					status_change_end(bl, type, INVALID_TIMER);
 				sg->limit = DIFF_TICK(tick,sg->tick)+1000;
 			}
 			break;
@@ -7857,7 +7840,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 			if (bl->type==BL_MOB)
 				break;
 			if (sce)
-				status_change_end(bl, type, -1);
+				status_change_end(bl, type, INVALID_TIMER);
 			break;
 
 		case BD_LULLABY:
@@ -7875,7 +7858,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 				//it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble
 				//which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel
 				//your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it.
-				status_change_end(bl, SC_DANCING, -1);
+				status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			}
 		case MG_SAFETYWALL:
 		case AL_PNEUMA:
@@ -7886,7 +7869,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 		case HW_GRAVITATION:
 		case NJ_SUITON:
 			if (sce)
-				status_change_end(bl, type, -1);
+				status_change_end(bl, type, INVALID_TIMER);
 			break;
 
 		case BA_POEMBRAGI:
@@ -7909,11 +7892,11 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 		case PF_FOGWALL:
 			if (sce)
 			{
-				status_change_end(bl,type,-1);
+				status_change_end(bl, type, INVALID_TIMER);
 				if ((sce=sc->data[SC_BLIND]))
 				{
 					if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex]
-						status_change_end(bl, SC_BLIND, -1);
+						status_change_end(bl, SC_BLIND, INVALID_TIMER);
 					else {
 						delete_timer(sce->timer, status_change_timer);
 						sce->timer = add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND);
@@ -8252,7 +8235,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
 	switch( skill )
 	{
 	case SA_CASTCANCEL:
-		if(sd->ud.skilltimer == -1) {
+		if(sd->ud.skilltimer == INVALID_TIMER) {
 			clif_skill_fail(sd,skill,0,0);
 			return 0;
 		}
@@ -8352,7 +8335,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
 		if (pc_famerank(sd->status.char_id,MAPID_TAEKWON))
 		{	//Unlimited Combo
 			if (skill == sd->skillid_old) {
-				status_change_end(&sd->bl, SC_COMBO, -1);
+				status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER);
 				sd->skillid_old = sd->skilllv_old = 0;
 				return 0; //Can't repeat previous combo skill.
 			}
@@ -9046,12 +9029,12 @@ int skill_castfix_sc (struct block_list *bl, int time)
 			time += time * sc->data[SC_SLOWCAST]->val2 / 100;
 		if (sc->data[SC_SUFFRAGIUM]) {
 			time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
-			status_change_end(bl, SC_SUFFRAGIUM, -1);
+			status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
 		}
 		if (sc->data[SC_MEMORIZE]) {
 			time>>=1;
 			if ((--sc->data[SC_MEMORIZE]->val2) <= 0)
-				status_change_end(bl, SC_MEMORIZE, -1);
+				status_change_end(bl, SC_MEMORIZE, INVALID_TIMER);
 		}
 		if (sc->data[SC_POEMBRAGI])
 			time -= time * sc->data[SC_POEMBRAGI]->val2 / 100;
@@ -9915,7 +9898,7 @@ int skill_enchant_elemental_end (struct block_list *bl, int type)
 
 	for (i = 0; i < ARRAYLENGTH(scs); i++)
 		if (type != scs[i] && sc->data[scs[i]])
-			status_change_end(bl, scs[i], -1);
+			status_change_end(bl, scs[i], INVALID_TIMER);
 
 	return 0;
 }
@@ -9940,7 +9923,7 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
 		if( !wall )
 		{
 			if( sce->val1 < 3 ) //End cloaking.
-				status_change_end(bl, SC_CLOAKING, -1);
+				status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
 			else
 			if( sce->val4&1 )
 			{	//Remove wall bonus
@@ -10039,7 +10022,7 @@ int skill_delunit (struct skill_unit* unit)
 		{
 		struct block_list* target = map_id2bl(group->val2);
 		if( target )
-			status_change_end(target,SC_ANKLE,-1);
+			status_change_end(target, SC_ANKLE, INVALID_TIMER);
 		}
 		break;
 	case WZ_ICEWALL:
@@ -10185,7 +10168,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 		if (sc && sc->data[SC_DANCING])
 		{
 			sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex]
-			status_change_end(src,SC_DANCING,-1);
+			status_change_end(src, SC_DANCING, INVALID_TIMER);
 		}
 	}
 
@@ -10195,7 +10178,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 		struct status_change *sc = status_get_sc(src);
 		if(sc && sc->data[SC_GOSPEL]) {
 			sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex]
-			status_change_end(src,SC_GOSPEL,-1);
+			status_change_end(src, SC_GOSPEL, INVALID_TIMER);
 		}
 	}
 
@@ -10205,7 +10188,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 		struct status_change *sc = status_get_sc(src);
 		if(sc && sc->data[SC_WARM]) {
 			sc->data[SC_WARM]->val4 = 0;
-			status_change_end(src,SC_WARM,-1);
+			status_change_end(src, SC_WARM, INVALID_TIMER);
 		}
 	}
 

+ 111 - 113
src/map/status.c

@@ -698,20 +698,20 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 		if( sc ) {
 			struct status_change_entry *sce;
 			if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
-				status_change_end(target,SC_STONE,-1);
-			status_change_end(target,SC_FREEZE,-1);
-			status_change_end(target,SC_SLEEP,-1);
-			status_change_end(target,SC_WINKCHARM,-1);
-			status_change_end(target,SC_CONFUSION,-1);
-			status_change_end(target,SC_TRICKDEAD,-1);
-			status_change_end(target,SC_HIDING,-1);
-			status_change_end(target,SC_CLOAKING,-1);
-			status_change_end(target,SC_CHASEWALK,-1);
+				status_change_end(target, SC_STONE, INVALID_TIMER);
+			status_change_end(target, SC_FREEZE, INVALID_TIMER);
+			status_change_end(target, SC_SLEEP, INVALID_TIMER);
+			status_change_end(target, SC_WINKCHARM, INVALID_TIMER);
+			status_change_end(target, SC_CONFUSION, INVALID_TIMER);
+			status_change_end(target, SC_TRICKDEAD, INVALID_TIMER);
+			status_change_end(target, SC_HIDING, INVALID_TIMER);
+			status_change_end(target, SC_CLOAKING, INVALID_TIMER);
+			status_change_end(target, SC_CHASEWALK, INVALID_TIMER);
 			if ((sce=sc->data[SC_ENDURE]) && !sce->val4) {
 				//Endure count is only reduced by non-players on non-gvg maps.
 				//val4 signals infinite endure. [Skotlex]
 				if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0)
-					status_change_end(target, SC_ENDURE, -1);
+					status_change_end(target, SC_ENDURE, INVALID_TIMER);
 			}
 			if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF)
 			{
@@ -719,11 +719,11 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 				if (sg) {
 					skill_delunitgroup(sg);
 					sce->val4 = 0;
-					status_change_end(target, SC_GRAVITATION, -1);
+					status_change_end(target, SC_GRAVITATION, INVALID_TIMER);
 				}
 			}
 			if(sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2)
-				status_change_end(target, SC_DANCING, -1);
+				status_change_end(target, SC_DANCING, INVALID_TIMER);
 		}
 		unit_skillcastcancel(target, 2);
 	}
@@ -747,7 +747,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 			status->hp < status->max_hp>>2)
 			sc_start4(target,SC_PROVOKE,100,10,1,0,0,0);
 		if (sc->data[SC_BERSERK] && status->hp <= 100)
-			status_change_end(target, SC_BERSERK, -1);
+			status_change_end(target, SC_BERSERK, INVALID_TIMER);
 	}
 
 	switch (target->type)
@@ -899,7 +899,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
 		sc->data[SC_PROVOKE]->val2==1 &&
 		status->hp>=status->max_hp>>2
 	)	//End auto berserk.
-		status_change_end(bl,SC_PROVOKE,-1);
+		status_change_end(bl, SC_PROVOKE, INVALID_TIMER);
 
 	// send hp update to client
 	switch(bl->type) {
@@ -2869,9 +2869,9 @@ void status_calc_bl_main(struct block_list *bl, enum scb_flag flag)
 		struct unit_data *ud = unit_bl2ud(bl);
 		status->speed = status_calc_speed(bl, sc, b_status->speed);
 
-		//Re-walk to adjust speed (we do not check if walktimer != -1
+		//Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
 		//because if you step on something while walking, the moment this
-		//piece of code triggers the walk-timer is set on -1) [Skotlex]
+		//piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
 	  	if (ud)
 			ud->state.change_walk_target = ud->state.speed_changed = 1;
 
@@ -3757,7 +3757,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 	if( sc == NULL )
 		return cap_value(speed,10,USHRT_MAX);
 
-	if( sd && sd->ud.skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0 )
+	if( sd && sd->ud.skilltimer != INVALID_TIMER && pc_checkskill(sd,SA_FREECAST) > 0 )
 	{
 		speed_rate = 175 - 5 * pc_checkskill(sd,SA_FREECAST);
 	}
@@ -4213,7 +4213,7 @@ signed char status_get_def(struct block_list *bl)
 	struct status_data *status = status_get_status_data(bl);
 	int def = status?status->def:0;
 	ud = unit_bl2ud(bl);
-	if (ud && ud->skilltimer != -1)
+	if (ud && ud->skilltimer != INVALID_TIMER)
 		def -= def * skill_get_castdef(ud->skillid)/100;
 	return cap_value(def, CHAR_MIN, CHAR_MAX);
 }
@@ -4846,7 +4846,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		if (val3) mode|= val3; //Add mode
 		if (mode == bstatus->mode) { //No change.
 			if (sc->data[type]) //Abort previous status
-				return status_change_end(bl, type, -1);
+				return status_change_end(bl, type, INVALID_TIMER);
 			return 0;
 		}
 	}
@@ -5001,133 +5001,132 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		//TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
 		//but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
 		if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) {
-			if (sc->data[SC_CURSE])
-				status_change_end(bl,SC_CURSE,-1);
+			status_change_end(bl, SC_CURSE, INVALID_TIMER);
 			if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
-				status_change_end(bl,SC_STONE,-1);
+				status_change_end(bl, SC_STONE, INVALID_TIMER);
 		}
 		break;
 	case SC_INCREASEAGI:
-		status_change_end(bl,SC_DECREASEAGI,-1);
+		status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER);
 		break;
 	case SC_QUAGMIRE:
-		status_change_end(bl,SC_CONCENTRATE,-1);
-		status_change_end(bl,SC_TRUESIGHT,-1);
-		status_change_end(bl,SC_WINDWALK,-1);
+		status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER);
+		status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
+		status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
 		//Also blocks the ones below...
 	case SC_DECREASEAGI:
-		status_change_end(bl,SC_CARTBOOST,-1);
+		status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
 		//Also blocks the ones below...
 	case SC_DONTFORGETME:
-		status_change_end(bl,SC_INCREASEAGI,-1);
-		status_change_end(bl,SC_ADRENALINE,-1);
-		status_change_end(bl,SC_ADRENALINE2,-1);
-		status_change_end(bl,SC_SPEARQUICKEN,-1);
-		status_change_end(bl,SC_TWOHANDQUICKEN,-1);
-		status_change_end(bl,SC_ONEHAND,-1);
-		status_change_end(bl,SC_MERC_QUICKEN,-1);
+		status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER);
+		status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
+		status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
+		status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
+		status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+		status_change_end(bl, SC_ONEHAND, INVALID_TIMER);
+		status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER);
 		break;
 	case SC_ONEHAND:
 	  	//Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
-		status_change_end(bl,SC_ASPDPOTION0,-1);
-		status_change_end(bl,SC_ASPDPOTION1,-1);
-		status_change_end(bl,SC_ASPDPOTION2,-1);
-		status_change_end(bl,SC_ASPDPOTION3,-1);
+		status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER);
+		status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER);
+		status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER);
+		status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER);
 		break;
 	case SC_MAXOVERTHRUST:
 	  	//Cancels Normal Overthrust. [Skotlex]
-		status_change_end(bl, SC_OVERTHRUST, -1);
+		status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
 		break;
 	case SC_KYRIE:
 		//Cancels Assumptio
-		status_change_end(bl,SC_ASSUMPTIO,-1);
+		status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
 		break;
 	case SC_DELUGE:
 		if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
-			status_change_end(bl,SC_BLIND,-1);
+			status_change_end(bl, SC_BLIND, INVALID_TIMER);
 		break;
 	case SC_SILENCE:
 		if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
-			status_change_end(bl,SC_GOSPEL,-1);
+			status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
 		break;
 	case SC_HIDING:
-		status_change_end(bl, SC_CLOSECONFINE, -1);
-		status_change_end(bl, SC_CLOSECONFINE2, -1);
+		status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER);
+		status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
 		break;
 	case SC_BERSERK:
 		if(battle_config.berserk_cancels_buffs)
 		{
-			status_change_end(bl,SC_ONEHAND,-1);
-			status_change_end(bl,SC_TWOHANDQUICKEN,-1);
-			status_change_end(bl,SC_CONCENTRATION,-1);
-			status_change_end(bl,SC_PARRYING,-1);
-			status_change_end(bl,SC_AURABLADE,-1);
-			status_change_end(bl,SC_MERC_QUICKEN,-1);
+			status_change_end(bl, SC_ONEHAND, INVALID_TIMER);
+			status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+			status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
+			status_change_end(bl, SC_PARRYING, INVALID_TIMER);
+			status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
+			status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER);
 		}
 		break;
 	case SC_ASSUMPTIO:
-		status_change_end(bl,SC_KYRIE,-1);
-		status_change_end(bl,SC_KAITE,-1);
+		status_change_end(bl, SC_KYRIE, INVALID_TIMER);
+		status_change_end(bl, SC_KAITE, INVALID_TIMER);
 		break;
 	case SC_KAITE:
-		status_change_end(bl,SC_ASSUMPTIO,-1);
+		status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
 		break;
 	case SC_CARTBOOST:
 		if(sc->data[SC_DECREASEAGI])
 		{	//Cancel Decrease Agi, but take no further effect [Skotlex]
-			status_change_end(bl,SC_DECREASEAGI,-1);
+			status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER);
 			return 0;
 		}
 		break;
 	case SC_FUSION:
-		status_change_end(bl,SC_SPIRIT,-1);
+		status_change_end(bl, SC_SPIRIT, INVALID_TIMER);
 		break;
 	case SC_ADJUSTMENT:
-		status_change_end(bl,SC_MADNESSCANCEL,-1);
+		status_change_end(bl, SC_MADNESSCANCEL, INVALID_TIMER);
 		break;
 	case SC_MADNESSCANCEL:
-		status_change_end(bl,SC_ADJUSTMENT,-1);
+		status_change_end(bl, SC_ADJUSTMENT, INVALID_TIMER);
 		break;
 	//NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
 	case SC_CHANGEUNDEAD:
-		status_change_end(bl,SC_BLESSING,-1);
-		status_change_end(bl,SC_INCREASEAGI,-1);
+		status_change_end(bl, SC_BLESSING, INVALID_TIMER);
+		status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER);
 		break;
 	case SC_STRFOOD:
-		status_change_end(bl,SC_FOOD_STR_CASH,-1);
+		status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
 		break;
 	case SC_AGIFOOD:
-		status_change_end(bl,SC_FOOD_AGI_CASH,-1);
+		status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
 		break;
 	case SC_VITFOOD:
-		status_change_end(bl,SC_FOOD_VIT_CASH,-1);
+		status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
 		break;
 	case SC_INTFOOD:
-		status_change_end(bl,SC_FOOD_INT_CASH,-1);
+		status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
 		break;
 	case SC_DEXFOOD:
-		status_change_end(bl,SC_FOOD_DEX_CASH,-1);
+		status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
 		break;
 	case SC_LUKFOOD:
-		status_change_end(bl,SC_FOOD_LUK_CASH,-1);
+		status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
 		break;
 	case SC_FOOD_STR_CASH:
-		status_change_end(bl,SC_STRFOOD,-1);
+		status_change_end(bl, SC_STRFOOD, INVALID_TIMER);
 		break;
 	case SC_FOOD_AGI_CASH:
-		status_change_end(bl,SC_AGIFOOD,-1);
+		status_change_end(bl, SC_AGIFOOD, INVALID_TIMER);
 		break;
 	case SC_FOOD_VIT_CASH:
-		status_change_end(bl,SC_VITFOOD,-1);
+		status_change_end(bl, SC_VITFOOD, INVALID_TIMER);
 		break;
 	case SC_FOOD_INT_CASH:
-		status_change_end(bl,SC_INTFOOD,-1);
+		status_change_end(bl, SC_INTFOOD, INVALID_TIMER);
 		break;
 	case SC_FOOD_DEX_CASH:
-		status_change_end(bl,SC_DEXFOOD,-1);
+		status_change_end(bl, SC_DEXFOOD, INVALID_TIMER);
 		break;
 	case SC_FOOD_LUK_CASH:
-		status_change_end(bl,SC_LUKFOOD,-1);
+		status_change_end(bl, SC_LUKFOOD, INVALID_TIMER);
 		break;
 	}
 
@@ -5198,9 +5197,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			case SC_KAAHI:
 				//Kaahi overwrites previous level regardless of existing level.
 				//Delete timer if it exists.
-				if (sce->val4 != -1) {
+				if (sce->val4 != INVALID_TIMER) {
 					delete_timer(sce->val4,kaahi_heal_timer);
-					sce->val4=-1;
+					sce->val4 = INVALID_TIMER;
 				}
 				break;
 			case SC_JAILED:
@@ -5821,7 +5820,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		case SC_KAAHI:
 			val2 = 200*val1; //HP heal
 			val3 = 5*val1; //SP cost 
-			val4 = -1;	//Kaahi Timer.
+			val4 = INVALID_TIMER;	//Kaahi Timer.
 			break;
 		case SC_BLESSING:
 			if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC)
@@ -6087,7 +6086,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			clif_changelook(bl,LOOK_CLOTHES_COLOR,val4);
 			break;	
 		case SC_KAAHI:
-			val4 = -1;
+			val4 = INVALID_TIMER;
 			break;
 	}
 
@@ -6102,7 +6101,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 				pc_setstand(sd);
 		case SC_TRICKDEAD:
 			unit_stop_attack(bl);
-			status_change_end(bl, SC_DANCING, -1);
+			status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			// Cancel cast when get status [LuzZza]
 			if (battle_config.sc_castcancel&bl->type)
 				unit_skillcastcancel(bl, 0);
@@ -6448,14 +6447,14 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 
 	sd = BL_CAST(BL_PC,bl);
 
-	if (sce->timer != tid && tid != -1)
+	if (sce->timer != tid && tid != INVALID_TIMER)
 		return 0;
 
-	if (tid == -1) {
+	if (tid == INVALID_TIMER) {
 		if (type == SC_ENDURE && sce->val4)
 			//Do not end infinite endure.
 			return 0;
-		if (sce->timer != -1) //Could be a SC with infinite duration
+		if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration
 			delete_timer(sce->timer,status_change_timer);
 		if (sc->opt1)
 		switch (type) {
@@ -6514,7 +6513,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				if(!ud->state.running)
 					begin_spurt = false;
 				ud->state.running = 0;
-				if (ud->walktimer != -1)
+				if (ud->walktimer != INVALID_TIMER)
 					unit_stop_walking(bl,1);
 			}
 			if (begin_spurt && sce->val1 >= 7 &&
@@ -6526,7 +6525,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 		break;
 		case SC_AUTOBERSERK:
 			if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1)
-				status_change_end(bl,SC_PROVOKE,-1);
+				status_change_end(bl, SC_PROVOKE, INVALID_TIMER);
 			break;
 
 		case SC_ENDURE:
@@ -6541,14 +6540,14 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 					for( i = 0; i < 5; i++ )
 					{
 						if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type] )
-							status_change_end(&tsd->bl, type, -1);
+							status_change_end(&tsd->bl, type, INVALID_TIMER);
 					}
 				}
 				else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag )
 				{ // Clear Status from Master
 					tsd = ((TBL_MER*)bl)->master;
 					if( tsd && tsd->sc.data[type] )
-						status_change_end(&tsd->bl, type, -1);
+						status_change_end(&tsd->bl, type, INVALID_TIMER);
 				}
 			}
 			break;
@@ -6564,10 +6563,10 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 					clif_devotion(d_bl, NULL);
 				}
 
-				status_change_end(bl,SC_AUTOGUARD,-1);
-				status_change_end(bl,SC_DEFENDER,-1);
-				status_change_end(bl,SC_REFLECTSHIELD,-1);
-				status_change_end(bl,SC_ENDURE,-1);
+				status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER);
+				status_change_end(bl, SC_DEFENDER, INVALID_TIMER);
+				status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+				status_change_end(bl, SC_ENDURE, INVALID_TIMER);
 			}
 			break;
 
@@ -6581,7 +6580,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				if(tbl && tsc && tsc->data[SC_BLADESTOP])
 				{
 					tsc->data[SC_BLADESTOP]->val4 = 0;
-					status_change_end(tbl,SC_BLADESTOP,-1);
+					status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER);
 				}
 				clif_bladestop(bl, tid, 0);
 			}
@@ -6598,7 +6597,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 					if(dsc)
 					{	//This will prevent recursive loops. 
 						dsc->val2 = dsc->val4 = 0;
-						status_change_end(&dsd->bl, SC_DANCING, -1);
+						status_change_end(&dsd->bl, SC_DANCING, INVALID_TIMER);
 					}
 				}
 
@@ -6621,11 +6620,11 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				if((sce->val1&0xFFFF) == CG_MOONLIT)
 					clif_status_change(bl,SI_MOONLIT,0,0);
 
-				status_change_end(bl,SC_LONGING,-1);
+				status_change_end(bl, SC_LONGING, INVALID_TIMER);
 			}
 			break;
 		case SC_NOCHAT:
-			if (sd && sd->status.manner < 0 && tid != -1)
+			if (sd && sd->status.manner < 0 && tid != INVALID_TIMER)
 				sd->status.manner = 0;
 			if (sd)
 			{
@@ -6636,7 +6635,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 		case SC_SPLASHER:	
 			{
 				struct block_list *src=map_id2bl(sce->val3);
-				if(src && tid!=-1)
+				if(src && tid != INVALID_TIMER)
 					skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL );
 			}
 			break;
@@ -6648,7 +6647,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 					//If status was already ended, do nothing.
 					//Decrease count
 					if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up.
-						status_change_end(src, SC_CLOSECONFINE, -1);
+						status_change_end(src, SC_CLOSECONFINE, INVALID_TIMER);
 				}
 			}
 		case SC_CLOSECONFINE:
@@ -6685,7 +6684,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				if (sc2 && sc2->data[type2])
 				{
 					sc2->data[type2]->val1 = 0;
-					status_change_end(pbl, type2, -1);
+					status_change_end(pbl, type2, INVALID_TIMER);
 				}
 			}
 			break;
@@ -6697,7 +6696,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 			if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2)
 			{
 				sc->data[SC_ENDURE]->val4 = 0;
-				status_change_end(bl, SC_ENDURE, -1);
+				status_change_end(bl, SC_ENDURE, INVALID_TIMER);
 			}
 			sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1));
 			break;
@@ -6727,25 +6726,25 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 			break;
 		case SC_KAAHI:
 			//Delete timer if it exists.
-			if (sce->val4 != -1)
+			if (sce->val4 != INVALID_TIMER)
 				delete_timer(sce->val4,kaahi_heal_timer);
 			break;
 		case SC_JAILED:
-			if(tid == -1)
+			if(tid == INVALID_TIMER)
 				break;
 		  	//natural expiration.
 			if(sd && sd->mapindex == sce->val2)
 				pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT);
 			break; //guess hes not in jail :P
 		case SC_CHANGE:
-			if (tid == -1)
+			if (tid == INVALID_TIMER)
 		 		break;
 			// "lose almost all their HP and SP" on natural expiration.
 			status_set_hp(bl, 10, 0);
 			status_set_sp(bl, 10, 0);
 			break;
 		case SC_AUTOTRADE:
-			if (tid == -1)
+			if (tid == INVALID_TIMER)
 				break;
 			vending_closevending(sd);
 			map_quit(sd);
@@ -6759,7 +6758,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				struct block_list* tbl = map_id2bl(sce->val2);
 				sce->val2 = 0;
 				if( tbl && (sc = status_get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id )
-					status_change_end(tbl, SC_STOP, -1);
+					status_change_end(tbl, SC_STOP, INVALID_TIMER);
 			}
 			break;
 		}
@@ -6956,13 +6955,13 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data)
 
 	if(sce->val4 != tid) {
 		ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sce->val4);
-		sce->val4=-1;
+		sce->val4 = INVALID_TIMER;
 		return 0;
 	}
 
 	status=status_get_status_data(bl);
 	if(!status_charge(bl, 0, sce->val3)) {
-		sce->val4=-1;
+		sce->val4 = INVALID_TIMER;
 		return 0;
 	}
 
@@ -6971,7 +6970,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data)
 		hp = sce->val2;
 	if (hp)
 		status_heal(bl, hp, 0, 2);
-	sce->val4=-1;
+	sce->val4 = INVALID_TIMER;
 	return 1;
 }
 
@@ -7350,13 +7349,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
 	{
 	case SC_SIGHT:	/* ƒTƒCƒg */
 	case SC_CONCENTRATE:
-		status_change_end(bl, SC_HIDING, -1);
-		status_change_end(bl, SC_CLOAKING, -1);
+		status_change_end(bl, SC_HIDING, INVALID_TIMER);
+		status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
 		break;
 	case SC_RUWACH:	/* ƒ‹ƒAƒt */
 		if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING])) {
-			status_change_end(bl, SC_HIDING, -1);
-			status_change_end(bl, SC_CLOAKING, -1);
+			status_change_end(bl, SC_HIDING, INVALID_TIMER);
+			status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
 			if(battle_check_target( src, bl, BCT_ENEMY ) > 0)
 				skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0);
 		}
@@ -7373,7 +7372,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
 		//Lock char has released the hold on everyone...
 		if (tsc && tsc->data[SC_CLOSECONFINE2] && tsc->data[SC_CLOSECONFINE2]->val2 == src->id) {
 			tsc->data[SC_CLOSECONFINE2]->val2 = 0;
-			status_change_end(bl, SC_CLOSECONFINE2, -1);
+			status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
 		}
 		break;
 	}
@@ -7395,8 +7394,7 @@ int status_change_clear_buffs (struct block_list* bl, int type)
 	if (type&2) //Debuffs
 	for( i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++ )
 	{
-		if(sc->data[i])
-			status_change_end(bl,(sc_type)i,-1);
+		status_change_end(bl, (sc_type)i, INVALID_TIMER);
 	}
 
 	for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ )
@@ -7469,7 +7467,7 @@ int status_change_clear_buffs (struct block_list* bl, int type)
 					continue;
 				break;
 		}
-		status_change_end(bl,(sc_type)i,-1);
+		status_change_end(bl, (sc_type)i, INVALID_TIMER);
 	}
 	return 0;
 }
@@ -7557,7 +7555,7 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 
 	ud = unit_bl2ud(bl);
 
-	if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != -1)
+	if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER)
 	{
 		flag&=~(RGN_SHP|RGN_SSP);
 		if(!regen->state.walk)
@@ -7580,7 +7578,7 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 	if (flag&RGN_HP)
 	{
 		rate = natural_heal_diff_tick*(regen->rate.hp+bonus);
-		if (ud && ud->walktimer != -1)
+		if (ud && ud->walktimer != INVALID_TIMER)
 			rate/=2;
 		// Homun HP regen fix (they should regen as if they were sitting (twice as fast) 
 		if(bl->type==BL_HOM) rate *=2;

+ 2 - 1
src/map/storage.c

@@ -398,11 +398,12 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
 	nullpo_retr(1, sd);
 	nullpo_retr(1, stor);
 	nullpo_retr(1, item_data);
-	nullpo_retr(1, data = itemdb_search(item_data->nameid));
 
 	if(item_data->nameid <= 0 || amount <= 0)
 		return 1;
 
+	data = itemdb_search(item_data->nameid);
+
 	if( data->stack.guildstorage && amount > data->stack.amount )
 	{// item stack limitation
 		return 1;

+ 2 - 1
src/map/trade.c

@@ -56,7 +56,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
 		}
 	}
 
-	if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
+	if (target_sd->trade_partner != 0) {
 		clif_tradestart(sd, 2); // person is in another trade
 		return;
 	}
@@ -110,6 +110,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
 	if (tsd->state.trading || tsd->trade_partner != sd->bl.id)
 	{
 		clif_tradestart(sd, 2);
+		sd->trade_partner=0;
 		return; //Already trading or wrong partner.
 	}
 

+ 68 - 67
src/map/unit.c

@@ -157,7 +157,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
 	map_moveblock(bl, x, y, tick);
 	ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex]
 
-	if (bl->x != x || bl->y != y || ud->walktimer != -1)
+	if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER)
 		return 0; //map_moveblock has altered the object beyond what we expected (moved/warped it)
 
 	ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets
@@ -197,11 +197,11 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
 		if (md->min_chase > md->db->range3) md->min_chase--;
 		//Walk skills are triggered regardless of target due to the idle-walk mob state.
 		//But avoid triggering on stop-walk calls.
-		if(tid != -1 &&
+		if(tid != INVALID_TIMER &&
 			!(ud->walk_count%WALK_SKILL_INTERVAL) &&
 			mobskill_use(md, tick, -1))
 	  	{
-			if (!(ud->skillid == NPC_SELFDESTRUCTION && ud->skilltimer != -1))
+			if (!(ud->skillid == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
 			{	//Skill used, abort walking
 				clif_fixpos(bl); //Fix position as walk has been cancelled.
 				return 0;
@@ -211,7 +211,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
 		}
 	}
 
-	if(tid == -1) //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;
 		
 	if(ud->state.change_walk_target)
@@ -306,14 +306,14 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
 	if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
 		map_random_dir(bl, &ud->to_x, &ud->to_y);
 
-	if(ud->walktimer != -1) {
+	if(ud->walktimer != INVALID_TIMER) {
 		// 現在歩いている最中の目的地変更なのでマス目の中心に来た時に
 		// timer関数からunit_walktoxy_subを呼ぶようにする
 		ud->state.change_walk_target = 1;
 		return 1;
 	}
 
-	if(ud->attacktimer != -1) {
+	if(ud->attacktimer != INVALID_TIMER) {
 		delete_timer( ud->attacktimer, unit_attack_timer );
 		ud->attacktimer = INVALID_TIMER;
 	}
@@ -331,7 +331,7 @@ static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr data)
 	struct block_list *bl = map_id2bl(id);
 	struct unit_data *ud = bl?unit_bl2ud(bl):NULL;
 
-	if (ud && ud->walktimer == -1 && ud->target == data)
+	if (ud && ud->walktimer == INVALID_TIMER && ud->target == data)
 	{
 		if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting?
 			add_timer(ud->canmove_tick+1, unit_walktobl_sub, id, data);
@@ -374,7 +374,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
 	if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
 		map_random_dir(bl, &ud->to_x, &ud->to_y);
 
-	if(ud->walktimer != -1) {
+	if(ud->walktimer != INVALID_TIMER) {
 		ud->state.change_walk_target = 1;
 		set_mobstate(bl, flag&2);
 		return 1;
@@ -389,7 +389,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
 	if(!unit_can_move(bl))
 		return 0;
 
-	if(ud->attacktimer != -1) {
+	if(ud->attacktimer != INVALID_TIMER) {
 		delete_timer( ud->attacktimer, unit_attack_timer );
 		ud->attacktimer = INVALID_TIMER;
 	}
@@ -413,7 +413,7 @@ int unit_run(struct block_list *bl)
 		return 0;
 	
 	if (!unit_can_move(bl)) {
-		status_change_end(bl,SC_RUN,-1);
+		status_change_end(bl, SC_RUN, INVALID_TIMER);
 		return 0;
 	}
 	
@@ -443,7 +443,7 @@ int unit_run(struct block_list *bl)
 
 		//Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
 		unit_bl2ud(bl)->state.running = 0;
-		status_change_end(bl,SC_RUN,-1);
+		status_change_end(bl, SC_RUN, INVALID_TIMER);
 
 		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0);
 		clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis.
@@ -463,7 +463,7 @@ int unit_run(struct block_list *bl)
 
 		//Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
 		unit_bl2ud(bl)->state.running = 0;
-		status_change_end(bl,SC_RUN,-1);
+		status_change_end(bl, SC_RUN, INVALID_TIMER);
 
 		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0);
 		clif_fixpos(bl);
@@ -725,7 +725,7 @@ int unit_stop_walking(struct block_list *bl,int type)
 	nullpo_ret(bl);
 
 	ud = unit_bl2ud(bl);
-	if(!ud || ud->walktimer == -1)
+	if(!ud || ud->walktimer == INVALID_TIMER)
 		return 0;
 	//NOTE: We are using timer data after deleting it because we know the 
 	//delete_timer function does not messes with it. If the function's 
@@ -739,7 +739,7 @@ int unit_stop_walking(struct block_list *bl,int type)
 	||  (type&0x04 && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell
 	) {	
 		ud->walkpath.path_len = ud->walkpath.path_pos+1;
-		unit_walktoxy_timer(-1, tick, bl->id, ud->walkpath.path_pos);
+		unit_walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
 	}
 
 	if(type&0x01)
@@ -754,7 +754,7 @@ int unit_stop_walking(struct block_list *bl,int type)
 
 	//Readded, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin]
 	if (ud->state.running)
-		status_change_end(bl, SC_RUN, -1);
+		status_change_end(bl, SC_RUN, INVALID_TIMER);
 	return 1;
 }
 
@@ -774,7 +774,7 @@ int unit_is_walking(struct block_list *bl)
 	struct unit_data *ud = unit_bl2ud(bl);
 	nullpo_ret(bl);
 	if(!ud) return 0;
-	return (ud->walktimer != -1);
+	return (ud->walktimer != INVALID_TIMER);
 }
 
 /*==========================================
@@ -794,7 +794,7 @@ int unit_can_move(struct block_list *bl)
 	if (!ud)
 		return 0;
 	
-	if (ud->skilltimer != -1 && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skillid)&INF2_GUILD_SKILL))
+	if (ud->skilltimer != INVALID_TIMER && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skillid)&INF2_GUILD_SKILL))
 		return 0; // prevent moving while casting
 	
 	if (DIFF_TICK(ud->canmove_tick, gettick()) > 0)
@@ -880,7 +880,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
 			return 0;
 	}
 	ud->canmove_tick = tick + delay;
-	if (ud->walktimer != -1)
+	if (ud->walktimer != INVALID_TIMER)
 	{	//Stop walking, if chasing, readjust timers.
 		if (delay == 1)
 		{	//Minimal delay (walk-delay) disabled. Just stop walking.
@@ -939,8 +939,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 		if(skillnotok(skill_num, sd)) // [MouseJstr]
 			return 0;
 
-		mob_ksprotected(src, map_id2bl(target_id));
-
 		switch(skill_num)
 		{	//Check for skills that auto-select target
 		case MO_CHAINCOMBO:
@@ -987,8 +985,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 	if( !target || src->m != target->m || !src->prev || !target->prev )
 		return 0;
 
+	if( mob_ksprotected(src, target) )
+		return 0;
+
 	//Normally not needed because clif.c checks for it, but the at/char/script commands don't! [Skotlex]
-	if(ud->skilltimer != -1 && skill_num != SA_CASTCANCEL)
+	if(ud->skilltimer != INVALID_TIMER && skill_num != SA_CASTCANCEL)
 		return 0;
 
 	if(skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF && src->id == target_id)
@@ -1047,7 +1048,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 
 	//Check range when not using skill on yourself or is a combo-skill during attack
 	//(these are supposed to always have the same range as your attack)
-	if( src->id != target_id && (!temp || ud->attacktimer == -1) )
+	if( src->id != target_id && (!temp || ud->attacktimer == INVALID_TIMER) )
 	{
 		if( skill_get_state(ud->skillid) == ST_MOVE_ENABLE )
 		{
@@ -1065,7 +1066,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 
 	if (!temp) //Stop attack on non-combo skills [Skotlex]
 		unit_stop_attack(src);
-	else if(ud->attacktimer != -1) //Elsewise, delay current attack sequence
+	else if(ud->attacktimer != INVALID_TIMER) //Elsewise, delay current attack sequence
 		ud->attackabletime = tick + status_get_adelay(src);
 	
 	ud->state.skillcastcancel = castcancel;
@@ -1180,7 +1181,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 
  	if( sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING )
 	{
-		status_change_end(src,SC_CLOAKING,-1);
+		status_change_end(src, SC_CLOAKING, INVALID_TIMER);
 		if (!src->prev) return 0; //Warped away!
 	}
 
@@ -1224,7 +1225,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 	ud = unit_bl2ud(src);
 	if(ud == NULL) return 0;
 
-	if(ud->skilltimer != -1) //Normally not needed since clif.c checks for it, but at/char/script commands don't! [Skotlex]
+	if(ud->skilltimer != INVALID_TIMER) //Normally not needed since clif.c checks for it, but at/char/script commands don't! [Skotlex]
 		return 0;
 	
 	sc = status_get_sc(src);
@@ -1285,7 +1286,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 
 	if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4))
 	{
-		status_change_end(src,SC_CLOAKING,-1);
+		status_change_end(src, SC_CLOAKING, INVALID_TIMER);
 		if (!src->prev) return 0; //Warped away!
 	}
 
@@ -1310,7 +1311,7 @@ int unit_stop_attack(struct block_list *bl)
 	struct unit_data *ud = unit_bl2ud(bl);
 	nullpo_ret(bl);
 
-	if(!ud || ud->attacktimer == -1)
+	if(!ud || ud->attacktimer == INVALID_TIMER)
 		return 0;
 
 	delete_timer( ud->attacktimer, unit_attack_timer );
@@ -1380,7 +1381,7 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
 		ud->chaserange = status_get_range(src);
 
 	//Just change target/type. [Skotlex]
-	if(ud->attacktimer != -1)
+	if(ud->attacktimer != INVALID_TIMER)
 		return 0;
 
 	//Set Mob's ANGRY/BERSERK states.
@@ -1391,7 +1392,7 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
 		//Do attack next time it is possible. [Skotlex]
 		ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
 	else //Attack NOW.
-		unit_attack_timer(-1,gettick(),src->id,0);
+		unit_attack_timer(INVALID_TIMER, gettick(), src->id, 0);
 
 	return 0;
 }
@@ -1402,7 +1403,7 @@ int unit_cancel_combo(struct block_list *bl)
 {
 	struct unit_data  *ud;
 
-	if (!status_change_end(bl, SC_COMBO, -1))
+	if (!status_change_end(bl, SC_COMBO, INVALID_TIMER))
 		return 0; //Combo wasn't active.
 
 	ud = unit_bl2ud(bl);
@@ -1410,7 +1411,7 @@ int unit_cancel_combo(struct block_list *bl)
 
 	ud->attackabletime = gettick() + status_get_amotion(bl);
 
-	if (ud->attacktimer == -1)
+	if (ud->attacktimer == INVALID_TIMER)
 		return 1; //Nothing more to do.
 	
 	delete_timer(ud->attacktimer, unit_attack_timer);
@@ -1563,12 +1564,12 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 		return 0;
 	}
 
-	if( ud->skilltimer != -1 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) )
+	if( ud->skilltimer != INVALID_TIMER && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) )
 		return 0; // can't attack while casting
 	
 	if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) )
 	{ // attacking when under cast delay has restrictions:
-		if( tid == -1 )
+		if( tid == INVALID_TIMER )
 		{ //requested attack.
 			if(sd) clif_skill_fail(sd,1,4,0);
 			return 0;
@@ -1612,14 +1613,14 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 
 	//Sync packet only for players.
 	//Non-players use the sync packet on the walk timer. [Skotlex]
-	if (tid == -1 && sd) clif_fixpos(src);
+	if (tid == INVALID_TIMER && sd) clif_fixpos(src);
 
 	if( DIFF_TICK(ud->attackabletime,tick) <= 0 )
 	{
 		if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) {
 			ud->dir = map_calc_dir(src, target->x,target->y );
 		}
-		if(ud->walktimer != -1)
+		if(ud->walktimer != INVALID_TIMER)
 			unit_stop_walking(src,1);
 		if(md) {
 			if (mobskill_use(md,tick,-1))
@@ -1674,7 +1675,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
 	int ret=0, skill;
 	
 	nullpo_ret(bl);
-	if (!ud || ud->skilltimer==-1)
+	if (!ud || ud->skilltimer == INVALID_TIMER)
 		return 0; //Nothing to cancel.
 
 	sd = BL_CAST(BL_PC, bl);
@@ -1732,9 +1733,9 @@ void unit_dataset(struct block_list *bl)
 
 	memset( ud, 0, sizeof( struct unit_data) );
 	ud->bl             = bl;
-	ud->walktimer      = -1;
-	ud->skilltimer     = -1;
-	ud->attacktimer    = -1;
+	ud->walktimer      = INVALID_TIMER;
+	ud->skilltimer     = INVALID_TIMER;
+	ud->attacktimer    = INVALID_TIMER;
 	ud->attackabletime = 
 	ud->canact_tick    = 
 	ud->canmove_tick   = gettick();
@@ -1754,7 +1755,7 @@ static int unit_counttargeted_sub(struct block_list* bl, va_list ap)
 
 	ud = unit_bl2ud(bl);
 
-	if (ud && ud->target == id && ud->attacktimer != -1 && ud->attacktarget_lv >= target_lv)
+	if (ud && ud->target == id && ud->attacktimer != INVALID_TIMER && ud->attacktarget_lv >= target_lv)
 		return 1;
 
 	return 0;	
@@ -1821,36 +1822,36 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 	map_freeblock_lock();
 
 	ud->target = 0; //Unlock walk/attack target.
-	if (ud->walktimer != -1)
+	if (ud->walktimer != INVALID_TIMER)
 		unit_stop_walking(bl,0);
-	if (ud->attacktimer != -1)
+	if (ud->attacktimer != INVALID_TIMER)
 		unit_stop_attack(bl);
-	if (ud->skilltimer != -1)
+	if (ud->skilltimer != INVALID_TIMER)
 		unit_skillcastcancel(bl,0);
 // Do not reset can-act delay. [Skotlex]
 	ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick();
 	
 	if(sc && sc->count ) { //map-change/warp dispells.
-		status_change_end(bl,SC_BLADESTOP,-1);
-		status_change_end(bl,SC_BASILICA,-1);
-		status_change_end(bl,SC_ANKLE,-1);
-		status_change_end(bl,SC_TRICKDEAD,-1);
-		status_change_end(bl,SC_BLADESTOP_WAIT,-1);
-		status_change_end(bl,SC_RUN,-1);
-		status_change_end(bl,SC_DANCING,-1);
-		status_change_end(bl,SC_WARM,-1);
-		status_change_end(bl,SC_DEVOTION,-1);
-		status_change_end(bl,SC_MARIONETTE,-1);
-		status_change_end(bl,SC_MARIONETTE2,-1);
-		status_change_end(bl,SC_CLOSECONFINE,-1);
-		status_change_end(bl,SC_CLOSECONFINE2,-1);
-		status_change_end(bl,SC_HIDING,-1);
-		status_change_end(bl,SC_CLOAKING,-1);
-		status_change_end(bl,SC_CHASEWALK,-1);
+		status_change_end(bl, SC_BLADESTOP, INVALID_TIMER);
+		status_change_end(bl, SC_BASILICA, INVALID_TIMER);
+		status_change_end(bl, SC_ANKLE, INVALID_TIMER);
+		status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER);
+		status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER);
+		status_change_end(bl, SC_RUN, INVALID_TIMER);
+		status_change_end(bl, SC_DANCING, INVALID_TIMER);
+		status_change_end(bl, SC_WARM, INVALID_TIMER);
+		status_change_end(bl, SC_DEVOTION, INVALID_TIMER);
+		status_change_end(bl, SC_MARIONETTE, INVALID_TIMER);
+		status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER);
+		status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER);
+		status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
+		status_change_end(bl, SC_HIDING, INVALID_TIMER);
+		status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
+		status_change_end(bl, SC_CHASEWALK, INVALID_TIMER);
 		if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
-			status_change_end(bl,SC_GOSPEL,-1);
-		status_change_end(bl,SC_CHANGE,-1);
-		status_change_end(bl,SC_STOP,-1);
+			status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
+		status_change_end(bl, SC_CHANGE, INVALID_TIMER);
+		status_change_end(bl, SC_STOP, INVALID_TIMER);
 	}
 
 	if (bl->type&BL_CHAR) {
@@ -1890,7 +1891,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 		sd->npc_shopid = 0;
 		sd->adopt_invite = 0;
 
-		if(sd->pvp_timer!=-1) {
+		if(sd->pvp_timer != INVALID_TIMER) {
 			delete_timer(sd->pvp_timer,pc_calc_pvprank_timer);
 			sd->pvp_timer = INVALID_TIMER;
 			sd->pvp_rank = 0;
@@ -2052,7 +2053,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),false);
 			pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),false);
 			
-			if( sd->followtimer != -1 )
+			if( sd->followtimer != INVALID_TIMER )
 				pc_stop_following(sd);
 				
 			if( sd->duel_invite > 0 )
@@ -2103,7 +2104,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			}
 			if( pd->s_skill )
 			{
-				if (pd->s_skill->timer != -1) {
+				if (pd->s_skill->timer != INVALID_TIMER) {
 					if (pd->s_skill->id)
 						delete_timer(pd->s_skill->timer, pet_skill_support_timer);
 					else
@@ -2114,14 +2115,14 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			}
 			if( pd->recovery )
 			{
-				if(pd->recovery->timer != -1)
+				if(pd->recovery->timer != INVALID_TIMER)
 					delete_timer(pd->recovery->timer, pet_recovery_timer);
 				aFree(pd->recovery);
 				pd->recovery = NULL;
 			}
 			if( pd->bonus )
 			{
-				if (pd->bonus->timer != -1)
+				if (pd->bonus->timer != INVALID_TIMER)
 					delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 				aFree(pd->bonus);
 				pd->bonus = NULL;

+ 25 - 8
src/map/vending.c

@@ -19,6 +19,18 @@
 #include <stdio.h>
 #include <string.h>
 
+static int vending_nextid = 1;
+
+/// Returns an unique vending shop id.
+static int vending_getuid(void)
+{
+	if(!vending_nextid)
+	{// wrapped around, 0 is reserved for "not vending" state on eathena
+		vending_nextid = 1;
+	}
+
+	return vending_nextid++;
+}
 
 /*==========================================
  * Close shop
@@ -50,13 +62,15 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
 		return;
 	} 
 
+	sd->vended_id = vsd->vender_id;  // register vending uid
+
 	clif_vendinglist(sd, id, vsd->vending);
 }
 
 /*==========================================
  * Purchase item(s) from a shop
  *------------------------------------------*/
-void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const uint8* data, int count)
+void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count)
 {
 	int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING];
 	double z;
@@ -64,12 +78,15 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const ui
 	struct map_session_data* vsd = map_id2sd(aid);
 
 	nullpo_retv(sd);
-	if( vsd == NULL || vsd->vender_id == 0 || vsd->vender_id == sd->bl.id )
+	if( vsd == NULL || vsd->vender_id == 0 || vsd->bl.id == sd->bl.id )
 		return; // invalid shop
-#if PACKETVER >= 20100105
-	if( vsd->status.char_id != cid )
-		return; //Char-ID check
-#endif
+
+	if( vsd->vender_id != uid )
+	{// shop has changed
+		clif_buyvending(sd, 0, 0, 6);  // store information was incorrect
+		return;
+	}
+
 	if( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) )
 		return; // shop too far away
 	if( count < 1 || count > MAX_VENDING || count > vsd->vend_num )
@@ -289,11 +306,11 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
 		return;
 	}
 
-	sd->vender_id = sd->bl.id;
+	sd->vender_id = vending_getuid();
 	sd->vend_num = i;
 	safestrncpy(sd->message, message, MESSAGE_SIZE);
 
 	pc_stop_walking(sd,1);
-	clif_openvending(sd,sd->vender_id,sd->vending);
+	clif_openvending(sd,sd->bl.id,sd->vending);
 	clif_showvendingboard(&sd->bl,message,0);
 }

+ 1 - 1
src/map/vending.h

@@ -17,6 +17,6 @@ struct s_vending {
 void vending_closevending(struct map_session_data* sd);
 void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count);
 void vending_vendinglistreq(struct map_session_data* sd, int id);
-void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const uint8* data, int count);
+void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count);
 
 #endif /* _VENDING_H_ */

+ 1 - 9
src/plugins/Makefile.in

@@ -5,7 +5,7 @@ COMMON_H = ../common/plugin.h ../common/cbasetypes.h \
 	../common/showmsg.h ../common/utils.h ../common/strlib.h \
 	../common/malloc.h
 
-PLUGINS = sample sig pid gui console
+PLUGINS = sample sig pid console
 
 @SET_MAKE@
 
@@ -20,8 +20,6 @@ sig: sig@DLLEXT@
 
 pid: pid@DLLEXT@
 
-gui: gui@DLLEXT@
-
 console: console@DLLEXT@
 
 clean:
@@ -32,7 +30,6 @@ help:
 	@echo "'sample'   - sample plugin"
 	@echo "'sig'      - signal handler plugin"
 	@echo "'pid'      - process id plugin"
-	@echo "'gui'      - gui plugin"
 	@echo "'console'  - console plugin"
 	@echo "'all'      - builds all above targets"
 	@echo "'clean'    - cleans builds and objects"
@@ -43,14 +40,9 @@ help:
 %@DLLEXT@: %.c
 	@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $<
 
-gui@DLLEXT@: ../../plugins/gui.conf
-
 sig@DLLEXT@: sig.c $(COMMON_OBJ)
 	@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $< $(COMMON_OBJ)
 
-../../plugins/%.conf: %.txt
-	cp -r $< $@
-
 # missing common object files
 ../common/obj_all/%.o: ../common/%.c $(COMMON_H)
 	@$(MAKE) -C ../common txt

+ 4 - 3
src/plugins/console.c

@@ -32,7 +32,8 @@
 #define WORKER_FUNC_END(name) } ExitThread(0); return 0; }
 #define WORKER_EXECUTE(name,errvar) \
 	do{ \
-		buf.worker = CreateThread(NULL, 0, worker_ ## name, NULL, CREATE_SUSPENDED, NULL); \
+		DWORD dwThreadId; \
+		buf.worker = CreateThread(NULL, 0, worker_ ## name, NULL, CREATE_SUSPENDED, &dwThreadId); \
 		if( errvar ) \
 			*errvar = ( buf.worker == NULL ); \
 	}while(0)
@@ -132,10 +133,10 @@ int (*add_timer_func_list)(TimerFunc func, char* name);
 int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr data, int interval);
 int (*delete_timer)(int tid, TimerFunc func);
 unsigned int (*gettick)(void);
-int (*parse_console)(char* buf);
+int (*parse_console)(const char* buf);
 
 // Locals
-int tid; // timer id
+int tid = -1; // timer id
 BUFFER buf; // input buffer
 WORKER_FUNC_DECLARE(getinput); // worker for the input buffer
 

+ 0 - 107
src/plugins/gui.c

@@ -1,107 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "../common/plugin.h"
-//Needed for strcmpi
-#include "../common/mmo.h"
-
-// "I'm Alive" and "Flush stdout" Originally by Mugendai
-// Ported to plugin by Celest
-
-PLUGIN_INFO = {
-	"AthenaGUI",
-	PLUGIN_CORE,
-	"1.0",
-	PLUGIN_VERSION,
-	"Core plugin for Athena GUI functions"
-};
-
-PLUGIN_EVENTS_TABLE = {
-	{ "gui_init", "Plugin_Init" },
-	{ NULL, NULL }
-};
-
-typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data);
-unsigned int (*gettick)();
-int (*add_timer_func_list)(TimerFunc func, char* name);
-int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr data, int interval);
-
-//-----------------------------------------------------
-//I'm Alive Alert
-//Used to output 'I'm Alive' every few seconds
-//Intended to let frontends know if the app froze
-//-----------------------------------------------------
-int imalive_timer(int tid, unsigned int tick, int id, intptr data)
-{
-	printf("I'm Alive\n");
-	return 0;
-}
-
-//-----------------------------------------------------
-//Flush stdout
-//stdout buffer needs flushed to be seen in GUI
-//-----------------------------------------------------
-int flush_timer(int tid, unsigned int tick, int id, intptr data)
-{
-	fflush(stdout);
-	return 0;
-}
-
-void gui_init ()
-{
-	char line[1024], w1[1024], w2[1024];
-	int flush_on = 0;
-	int flush_time = 100;
-	int imalive_on = 0;
-	int imalive_time = 30;
-	char **argv;
-	int *argc;
-	FILE *fp;
-	int i;
-
-	IMPORT_SYMBOL(argc, 2);
-	IMPORT_SYMBOL(argv, 3);
-	IMPORT_SYMBOL(gettick, 5);
-	IMPORT_SYMBOL(add_timer_interval, 8);
-	IMPORT_SYMBOL(add_timer_func_list, 9);
-
-	do {
-		fp = fopen("plugins/gui.conf","r");
-		if (fp == NULL)
-			break;
-
-		while(fgets(line, sizeof(line), fp))
-		{
-			if (line[0] == '/' && line[1] == '/')
-				continue;
-			if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
-				if(strcmpi(w1,"imalive_on")==0){
-					imalive_on = atoi(w2);
-				} else if(strcmpi(w1,"imalive_time")==0){
-					imalive_time = atoi(w2);
-				} else if(strcmpi(w1,"flush_on")==0){
-					flush_on = atoi(w2);
-				} else if(strcmpi(w1,"flush_time")==0){
-					flush_time = atoi(w2);
-				}
-			}
-		}
-		fclose(fp);
-	} while (0);
-
-	for (i = 1; i < *argc ; i++)
-		if (strcmp(argv[i], "--gui") == 0)
-			flush_on = imalive_on = 1;
-
-	if (flush_on) {
-		add_timer_func_list(flush_timer, "flush_timer");
-		add_timer_interval(gettick()+1000,flush_timer,0,0,flush_time);
-	}
-	if (imalive_on) {
-		add_timer_func_list(imalive_timer, "imalive_timer");
-		add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
-	}
-}

+ 0 - 15
src/plugins/gui.txt

@@ -1,15 +0,0 @@
-//
-// GUI Plugin Configuration
-//
-
-// Enable I'm Alive?
-imalive_on: 0
-
-// How often to display I'm Alive (in seconds)
-imalive_time: 30
-
-// Enable GUI flushing for Mugendai's GUI?
-flush_on: 0
-
-// How often to flush the buffer on-screen (in seconds)
-flush_time: 60

+ 3 - 0
src/plugins/plugin.def → src/plugins/pid.def

@@ -2,3 +2,6 @@ EXPORTS
 	plugin_info         DATA
 	plugin_event_table  DATA
 	plugin_call_table   DATA
+
+	pid_create
+	pid_delete

+ 11 - 0
src/plugins/sample.def

@@ -0,0 +1,11 @@
+EXPORTS
+	; common exports
+	plugin_info         DATA
+	plugin_event_table  DATA
+	plugin_call_table   DATA
+
+	; plugin-specific exports
+	test_me
+	do_init
+	do_final
+	some_function

+ 28 - 10
src/tool/Makefile.in

@@ -1,26 +1,44 @@
 
+COMMON_OBJ = ../common/obj_all/minicore.o ../common/obj_all/malloc.o \
+	../common/obj_all/showmsg.o ../common/obj_all/strlib.o \
+	../common/obj_all/utils.o ../common/obj_all/grfio.o
+COMMON_H = ../common/core.h ../common/mmo.h ../common/version.h \
+	../common/malloc.h ../common/showmsg.h ../common/strlib.h \
+	../common/utils.h ../common/cbasetypes.h ../common/grfio.h
+
+MAPCACHE_OBJ = obj_all/mapcache.o
+
 @SET_MAKE@
 
 #####################################################################
-.PHONY : all adduser mapcache clean help
+.PHONY : all mapcache clean help
 
-all: adduser mapcache
+all: mapcache
 
-adduser:
-	@CC@ -o ../../tools/adduser@EXEEXT@ adduser.c
-
-mapcache:
-	@CC@ -o ../../mapcache@EXEEXT@ mapcache.c grfio.c -lz
+mapcache: obj_all $(MAPCACHE_OBJ) $(COMMON_OBJ)
+	@CC@ @LDFLAGS@ -o ../../mapcache@EXEEXT@ $(MAPCACHE_OBJ) $(COMMON_OBJ) @LIBS@
 
 clean:
-	rm -rf *.o ../../tools/adduser@EXEEXT@ ../../mapcache@EXEEXT@
+	rm -rf obj_all/*.o ../../mapcache@EXEEXT@
 
 help:
-	@echo "possible targets are 'adduser' 'mapcache' 'all' 'clean' 'help'"
-	@echo "'adduser'   - ???"
+	@echo "possible targets are 'mapcache' 'all' 'clean' 'help'"
 	@echo "'mapcache'  - mapcache generator"
 	@echo "'all'       - builds all above targets"
 	@echo "'clean'     - cleans builds and objects"
 	@echo "'help'      - outputs this message"
 
 #####################################################################
+
+obj_all:
+	-mkdir obj_all
+
+obj_all/%.o: %.c $(COMMON_H)
+	@CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+
+# missing common object files
+../common/obj_all/%.o:
+	@$(MAKE) -C ../common txt
+
+../common/obj_all/mini%.o:
+	@$(MAKE) -C ../common txt

+ 0 - 103
src/tool/adduser.c

@@ -1,103 +0,0 @@
-// (c) eAthena Dev Team - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-/*
-	This program adds an user to account.txt
-	Don't usr it When login-sever is working.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-char *account_txt = "../save/account.txt";
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars(char* str)
-{
-	int i;
-	int change = 0;
-
-	for(i = 0; str[i]; i++) {
-		if (iscntrl((unsigned char)(str[i]))) {
-			str[i] = '_';
-			change = 1;
-		}
-	}
-
-	return change;
-}
-
-int main(int argc, char *argv[])
-{
-	char username[24];
-	char password[24];
-	char sex[2];
-
-	int next_id, id;
-	char line[1024];
-	FILE *FPaccin,*FPaccout;
-
-	// Check to see if account.txt exists.
-	printf("Checking if '%s' file exists...\n", account_txt);
-	FPaccin = fopen(account_txt, "r");
-	if (FPaccin == NULL) {
-		printf("'%s' file not found!\n", account_txt);
-		printf("Run the setup wizard please.\n");
-		exit(EXIT_SUCCESS);
-	}
-
-	next_id = 2000000;
-	while(fgets(line, sizeof(line), FPaccin))
-	{
-		if (line[0] == '/' && line[1] == '/') { continue; }
-		if (sscanf(line, "%d\t%%newid%%\n", &id) == 1) {
-			if (next_id < id) {
-				next_id = id;
-			}
-		} else {
-			sscanf(line,"%i%[^	]", &id);
-			if (next_id <= id) {
-				next_id = id +1;
-			}
-		}
-	}
-	fclose(FPaccin);
-	printf("File exists.\n");
-
-	printf("Don't create an account if the login-server is online!!!\n");
-	printf("If the login-server is online, press ctrl+C now to stop this software.\n");
-	printf("\n");
-
-	strcpy(username, "");
-	while (strlen(username) < 4 || strlen(username) > 23) {
-		printf("Enter an username (4-23 characters): ");
-		scanf("%s", username);
-		username[23] = 0;
-		remove_control_chars(username);
-	}
-
-	strcpy(password, "");
-	while (strlen(password) < 4 || strlen(password) > 23) {
-		printf("Enter a password (4-23 characters): ");
-		scanf("%s", password);
-		password[23] = 0;
-		remove_control_chars(password);
-	}
-
-	strcpy(sex, "");
-	while (strcmp(sex, "F") != 0 && strcmp(sex, "M") != 0) {
-		printf("Enter a gender (M for male, F for female): ");
-		scanf("%s", sex);
-	}
-
-	FPaccout = fopen(account_txt, "r+");
-	fseek(FPaccout, 0, SEEK_END);
-	fprintf(FPaccout, "%i	%s	%s	-	%s	-\r\n", next_id, username, password, sex);
-	fclose(FPaccout);
-
-	printf("Account added.\n");
-}

+ 0 - 844
src/tool/grfio.c

@@ -1,844 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <ctype.h> // tolower()
-
-#include "grfio.h"
-#include <zlib.h>
-
-
-#ifndef __WIN32
-	#define strcmpi strcasecmp
-#endif
-	
-
-//----------------------------
-//	file entry table struct
-//----------------------------
-typedef struct _FILELIST {
-	int		srclen;				// compressed size
-	int		srclen_aligned;
-	int		declen;				// original size
-	int		srcpos;				// position of entry in grf
-	int		next;				// index of next filelist entry with same hash (-1: end of entry chain)
-	int		cycle;
-	char	type;
-	char	fn[128-4*5];		// file name
-	char*	fnd;				// if the file was cloned, contains name of original file
-	char	gentry;				// read grf file select
-} FILELIST;
-
-//gentry ... > 0  : data read from a grf file (gentry_table[gentry-1])
-//gentry ... 0    : data read from a local file (data directory)
-//gentry ... < 0  : entry "-(gentry)" is marked for a local file check
-//                  - if local file exists, gentry will be set to 0 (thus using the local file)
-//                  - if local file doesn't exist, sign is inverted (thus using the original file inside a grf)
-//                  (NOTE: this case is only used once (during startup) and only if GRFIO_LOCAL is enabled)
-//                  (NOTE: probably meant to be used to override grf contents by files in the data directory)
-//#define GRFIO_LOCAL
-
-// stores info about every loaded file
-FILELIST* filelist		= NULL;
-int filelist_entrys		= 0;
-int filelist_maxentry	= 0;
-
-// stores grf file names
-char** gentry_table		= NULL;
-int gentry_entrys		= 0;
-int gentry_maxentry		= 0;
-
-// the path to the data directory
-char data_dir[1024] = "";
-
-//----------------------------
-//	file list hash table
-//----------------------------
-int filelist_hash[256];
-
-//----------------------------
-//	grf decode data table
-//----------------------------
-static unsigned char BitMaskTable[8] = {
-	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
-};
-
-static char	BitSwapTable1[64] = {
-	58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
-	62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
-	57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
-	61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
-};
-static char	BitSwapTable2[64] = {
-	40,  8, 48, 16, 56, 24, 64, 32, 39,  7, 47, 15, 55, 23, 63, 31,
-	38,  6, 46, 14, 54, 22, 62, 30, 37,  5, 45, 13, 53, 21, 61, 29,
-	36,  4, 44, 12, 52, 20, 60, 28, 35,  3, 43, 11, 51, 19, 59, 27,
-	34,  2, 42, 10, 50, 18, 58, 26, 33,  1, 41,  9, 49, 17, 57, 25
-};
-static char	BitSwapTable3[32] = {
-	16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
-     2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
-};
-
-static unsigned char NibbleData[4][64]={
-	{
-		0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47,  0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,
-		0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba,  0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,
-		0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21,  0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,
-		0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec,  0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9,
-	}, {
-		0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95,  0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,
-		0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec,  0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,
-		0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06,  0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,
-		0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b,  0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce,
-	}, {
-		0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2,  0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,
-		0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae,  0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,
-		0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c,  0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,
-		0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97,  0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d,
-	}, {
-		0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78,  0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,
-		0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb,  0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,
-		0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87,  0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,
-		0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0,  0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb,
-	}
-};
-
-// little endian char array to uint conversion
-static unsigned int getlong(unsigned char* p)
-{
-	return (p[0] | p[1] << 0x08 | p[2] << 0x10 | p[3] << 0x18);
-}
-
-/*==========================================
- *	Grf data decode : Subs
- *------------------------------------------*/
-static void NibbleSwap(unsigned char* Src, int len)
-{
-	for(;0<len;len--,Src++) {
-		*Src = (*Src>>4) | (*Src<<4);
-	}
-}
-
-static void BitConvert(unsigned char* Src, char* BitSwapTable)
-{
-	int lop,prm;
-	unsigned char tmp[8];
-	memset(tmp,0,8);
-	for(lop=0;lop!=64;lop++) {
-		prm = BitSwapTable[lop]-1;
-		if (Src[(prm >> 3) & 7] & BitMaskTable[prm & 7]) {
-			tmp[(lop >> 3) & 7] |= BitMaskTable[lop & 7];
-		}
-	}
-	memcpy(Src,tmp,8);
-}
-
-static void BitConvert4(unsigned char* Src)
-{
-	int lop,prm;
-	unsigned char tmp[8];
-	tmp[0] = ((Src[7]<<5) | (Src[4]>>3)) & 0x3f;	// ..0 vutsr
-	tmp[1] = ((Src[4]<<1) | (Src[5]>>7)) & 0x3f;	// ..srqpo n
-	tmp[2] = ((Src[4]<<5) | (Src[5]>>3)) & 0x3f;	// ..o nmlkj
-	tmp[3] = ((Src[5]<<1) | (Src[6]>>7)) & 0x3f;	// ..kjihg f
-	tmp[4] = ((Src[5]<<5) | (Src[6]>>3)) & 0x3f;	// ..g fedcb
-	tmp[5] = ((Src[6]<<1) | (Src[7]>>7)) & 0x3f;	// ..cba98 7
-	tmp[6] = ((Src[6]<<5) | (Src[7]>>3)) & 0x3f;	// ..8 76543
-	tmp[7] = ((Src[7]<<1) | (Src[4]>>7)) & 0x3f;	// ..43210 v
-
-	for(lop=0;lop!=4;lop++) {
-		tmp[lop] = (NibbleData[lop][tmp[lop*2]] & 0xf0)
-		         | (NibbleData[lop][tmp[lop*2+1]] & 0x0f);
-	}
-
-	memset(tmp+4,0,4);
-	for(lop=0;lop!=32;lop++) {
-		prm = BitSwapTable3[lop]-1;
-		if (tmp[prm >> 3] & BitMaskTable[prm & 7]) {
-			tmp[(lop >> 3) + 4] |= BitMaskTable[lop & 7];
-		}
-	}
-	Src[0] ^= tmp[4];
-	Src[1] ^= tmp[5];
-	Src[2] ^= tmp[6];
-	Src[3] ^= tmp[7];
-}
-
-static void decode_des_etc(unsigned char* buf, size_t len, int type, int cycle)
-{
-	size_t lop,cnt=0;
-	if(cycle<3) cycle=3;
-	else if(cycle<5) cycle++;
-	else if(cycle<7) cycle+=9;
-	else cycle+=15;
-
-	for(lop=0; lop*8<len; lop++, buf+=8)
-	{
-		if(lop<20 || (type==0 && lop%cycle==0)) { // des
-			BitConvert(buf,BitSwapTable1);
-			BitConvert4(buf);
-			BitConvert(buf,BitSwapTable2);
-		} else {
-			if(cnt==7 && type==0) {
-				unsigned char a;
-				unsigned char tmp[8];
-				memcpy(tmp,buf,8);
-				cnt=0;
-				buf[0]=tmp[3];
-				buf[1]=tmp[4];
-				buf[2]=tmp[6];
-				buf[3]=tmp[0];
-				buf[4]=tmp[1];
-				buf[5]=tmp[2];
-				buf[6]=tmp[5];
-				a=tmp[7];
-				if(a==0x00) a=0x2b;
-				else if(a==0x2b) a=0x00;
-				else if(a==0x01) a=0x68;
-				else if(a==0x68) a=0x01;
-				else if(a==0x48) a=0x77;
-				else if(a==0x77) a=0x48;
-				else if(a==0x60) a=0xff;
-				else if(a==0xff) a=0x60;
-				else if(a==0x6c) a=0x80;
-				else if(a==0x80) a=0x6c;
-				else if(a==0xb9) a=0xc0;
-				else if(a==0xc0) a=0xb9;
-				else if(a==0xeb) a=0xfe;
-				else if(a==0xfe) a=0xeb;
-				buf[7]=a;
-			}
-			cnt++;
-		}
-	}
-}
-/*==========================================
- *	Grf data decode sub : zip
- *------------------------------------------*/
-int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen)
-{
-	z_stream stream;
-	int err;
-
-	stream.next_in = (Bytef*)source;
-	stream.avail_in = (uInt)sourceLen;
-	/* Check for source > 64K on 16-bit machine: */
-	if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-
-	stream.next_out = (Bytef*) dest;
-	stream.avail_out = (uInt)*destLen;
-	if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
-	stream.zalloc = (alloc_func)0;
-	stream.zfree = (free_func)0;
-
-	err = inflateInit(&stream);
-	if (err != Z_OK) return err;
-
-	err = inflate(&stream, Z_FINISH);
-	if (err != Z_STREAM_END) {
-		inflateEnd(&stream);
-		return err == Z_OK ? Z_BUF_ERROR : err;
-	}
-	*destLen = stream.total_out;
-
-	err = inflateEnd(&stream);
-	return err;
-}
-
-int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen)
-{
-	z_stream stream;
-	int err;
-	memset(&stream, 0, sizeof(stream));
-	stream.next_in = (Bytef*)source;
-	stream.avail_in = (uInt)sourceLen;
-	/* Check for source > 64K on 16-bit machine: */
-	if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-
-	stream.next_out = (Bytef*) dest;
-	stream.avail_out = (uInt)*destLen;
-	if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
-	stream.zalloc = (alloc_func)0;
-	stream.zfree = (free_func)0;
-
-	err = deflateInit(&stream,Z_DEFAULT_COMPRESSION);
-	if (err != Z_OK) return err;
-
-	err = deflate(&stream, Z_FINISH);
-	if (err != Z_STREAM_END) {
-		inflateEnd(&stream);
-		return err == Z_OK ? Z_BUF_ERROR : err;
-	}
-	*destLen = stream.total_out;
-
-	err = deflateEnd(&stream);
-	return err;
-}
-
-unsigned long grfio_crc32 (const unsigned char* buf, unsigned int len)
-{
-	return crc32(crc32(0L, Z_NULL, 0), buf, len);
-}
-
-/***********************************************************
- ***                File List Subroutines                ***
- ***********************************************************/
-
-// initializes the table that holds the first elements of all hash chains
-static void hashinit(void)
-{
-	int i;
-	for (i = 0; i < 256; i++)
-		filelist_hash[i] = -1;
-}
-
-// hashes a filename string into a number from {0..255}
-static int filehash(char* fname)
-{
-	unsigned int hash = 0;
-	while(*fname) {
-		hash = ((hash<<1) + (hash>>7)*9 + (unsigned int)tolower((unsigned char)(*fname)));
-		fname++;
-	}
-	return hash & 255;
-}
-
-// finds a FILELIST entry with the specified file name
-static FILELIST* filelist_find(char* fname)
-{
-	int hash, index;
-
-	if (!filelist)
-		return NULL;
-
-	hash = filelist_hash[filehash(fname)];
-	for (index = hash; index != -1; index = filelist[index].next)
-		if(!strcmpi(filelist[index].fn, fname))
-			break;
-
-	return (index >= 0) ? &filelist[index] : NULL;
-}
-
-// returns the original file name
-/*
-char* grfio_find_file(char* fname)
-{
-	FILELIST *filelist = filelist_find(fname);
-	if (!filelist) return NULL;
-	return (!filelist->fnd ? filelist->fn : filelist->fnd);
-}
-*/
-
-// adds a FILELIST entry into the list of loaded files
-static FILELIST* filelist_add(FILELIST* entry)
-{
-	int hash;
-
-	#define	FILELIST_ADDS	1024	// number increment of file lists `
-
-	if (filelist_entrys >= filelist_maxentry) {
-		filelist = (FILELIST *)realloc(filelist, (filelist_maxentry + FILELIST_ADDS) * sizeof(FILELIST));
-		memset(filelist + filelist_maxentry, '\0', FILELIST_ADDS * sizeof(FILELIST));
-		filelist_maxentry += FILELIST_ADDS;
-	}
-
-	memcpy (&filelist[filelist_entrys], entry, sizeof(FILELIST));
-
-	hash = filehash(entry->fn);
-	filelist[filelist_entrys].next = filelist_hash[hash];
-	filelist_hash[hash] = filelist_entrys;
-
-	filelist_entrys++;
-
-	return &filelist[filelist_entrys - 1];
-}
-
-// adds a new FILELIST entry or overwrites an existing one
-static FILELIST* filelist_modify(FILELIST* entry)
-{
-	FILELIST* fentry = filelist_find(entry->fn);
-	if (fentry != NULL) {
-		int tmp = fentry->next;
-		memcpy(fentry, entry, sizeof(FILELIST));
-		fentry->next = tmp;
-	} else {
-		fentry = filelist_add(entry);
-	}
-	return fentry;
-}
-
-// shrinks the file list array if too long
-static void filelist_adjust(void)
-{
-	if (filelist == NULL)
-		return;
-	
-	if (filelist_entrys < filelist_maxentry) {
-		filelist = (FILELIST *)realloc(filelist, filelist_entrys * sizeof(FILELIST));
-		filelist_maxentry = filelist_entrys;
-	}
-}
-
-/***********************************************************
- ***                  Grfio Sobroutines                  ***
- ***********************************************************/
-
-// returns a file's size
-/*
-int grfio_size(char* fname)
-{
-	FILELIST* entry;
-
-	entry = filelist_find(fname);
-
-	if (entry == NULL || entry->gentry < 0) {	// LocalFileCheck
-		char lfname[256], *p;
-		FILELIST lentry;
-		struct stat st;
-
-		sprintf(lfname, "%s%s", data_dir, fname);
-
-		for (p = &lfname[0]; *p != 0; p++)
-			if (*p=='\\') *p = '/';
-
-		if (stat(lfname, &st) == 0) {
-			strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1);
-			lentry.fnd = NULL;
-			lentry.declen = st.st_size;
-			lentry.gentry = 0;	// 0:LocalFile
-			entry = filelist_modify(&lentry);
-		} else if (entry == NULL) {
-			printf("%s not found (grfio_size)\n", fname);
-			return -1;
-		}
-	}
-	return entry->declen;
-}
-*/
-
-// reads a file into a newly allocated buffer (from grf or data directory)
-void* grfio_reads(char* fname, int* size)
-{
-	FILE* in;
-	FILELIST* entry;
-	unsigned char* buf2 = NULL;
-
-	entry = filelist_find(fname);
-
-	if (entry == NULL || entry->gentry <= 0) {	// LocalFileCheck
-		char lfname[256], *p;
-		FILELIST lentry;
-
-		sprintf(lfname, "%s%s", data_dir, fname);
-		
-		for (p = &lfname[0]; *p != 0; p++)
-			if (*p == '\\') *p = '/';
-
-		in = fopen(lfname, "rb");
-		if (in != NULL) {
-			if (entry != NULL && entry->gentry == 0) {
-				lentry.declen = entry->declen;
-			} else {
-				fseek(in,0,SEEK_END);
-				lentry.declen = ftell(in);
-			}
-			fseek(in,0,SEEK_SET);
-			buf2 = (unsigned char *)malloc(lentry.declen + 1024);
-			fread(buf2, 1, lentry.declen, in);
-			fclose(in);
-			strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1);
-			lentry.fnd = NULL;
-			lentry.gentry = 0;	// 0:LocalFile
-			entry = filelist_modify(&lentry);
-		} else {
-			if (entry != NULL && entry->gentry < 0) {
-				entry->gentry = -entry->gentry;	// local file checked
-			} else {
-				printf("%s not found (grfio_reads - local file %s)\n", fname, lfname);
-				return NULL;
-			}
-		}
-	}
-	if (entry != NULL && entry->gentry > 0) {	// Archive[GRF] File Read
-		char* grfname = gentry_table[entry->gentry - 1];
-		in = fopen(grfname, "rb");
-		if(in != NULL) {
-			unsigned char *buf = (unsigned char *)malloc(entry->srclen_aligned + 1024);
-			fseek(in, entry->srcpos, 0);
-			fread(buf, 1, entry->srclen_aligned, in);
-			fclose(in);
-			buf2 = (unsigned char *)malloc(entry->declen + 1024);
-			if (entry->type == 1 || entry->type == 3 || entry->type == 5) {
-				uLongf len;
-				if (entry->cycle >= 0)
-					decode_des_etc(buf, entry->srclen_aligned, entry->cycle == 0, entry->cycle);
-				len = entry->declen;
-				decode_zip(buf2, &len, buf, entry->srclen);
-				if (len != (uLong)entry->declen) {
-					printf("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen);
-					free(buf);
-					free(buf2);
-					return NULL;
-				}
-			} else {
-				memcpy(buf2, buf, entry->declen);
-			}
-			free(buf);
-		} else {
-			printf("%s not found (grfio_reads - GRF file %s)\n", fname, grfname);
-			return NULL;
-		}
-	}
-	if (size != NULL && entry != NULL)
-		*size = entry->declen;
-
-	return buf2;
-}
-
-/*==========================================
- *	Resource filename decode
- *------------------------------------------*/
-static char* decode_filename(unsigned char* buf, int len)
-{
-	int lop;
-	for(lop=0;lop<len;lop+=8) {
-		NibbleSwap(&buf[lop],8);
-		BitConvert(&buf[lop],BitSwapTable1);
-		BitConvert4(&buf[lop]);
-		BitConvert(&buf[lop],BitSwapTable2);
-	}
-	return (char*)buf;
-}
-
-// loads all entries in the specified grf file into the filelist
-// gentry - index of the grf file name in the gentry_table
-static int grfio_entryread(char* grfname, int gentry)
-{
-	FILE* fp;
-	long grf_size,list_size;
-	unsigned char grf_header[0x2e];
-	int lop,entry,entrys,ofs,grf_version;
-	char *fname;
-	unsigned char *grf_filelist;
-
-	fp = fopen(grfname, "rb");
-	if (fp == NULL) {
-		printf("GRF data file not found: '%s'\n",grfname);
-		return 1;	// 1:not found error
-	} else
-		printf("GRF data file found: '%s'\n",grfname);
-
-	fseek(fp,0,SEEK_END);
-	grf_size = ftell(fp);
-	fseek(fp,0,SEEK_SET);
-	fread(grf_header,1,0x2e,fp);
-	if (strcmp((const char *) grf_header,"Master of Magic") ||
-		fseek(fp,getlong(grf_header+0x1e),SEEK_CUR))
-	{
-		fclose(fp);
-		printf("GRF %s read error\n", grfname);
-		return 2;	// 2:file format error
-	}
-
-	grf_version = getlong(grf_header+0x2a) >> 8;
-
-	if (grf_version == 0x01) {	//****** Grf version 01xx ******
-		list_size = grf_size - ftell(fp);
-		grf_filelist = (unsigned char *) malloc(list_size);
-		fread(grf_filelist,1,list_size,fp);
-		fclose(fp);
-
-		entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7;
-
-		// Get an entry
-		for (entry = 0,ofs = 0; entry < entrys; entry++) {
-			int ofs2, srclen, srccount;
-			unsigned char type;
-			char* period_ptr;
-			FILELIST aentry;
-
-			ofs2 = ofs+getlong(grf_filelist+ofs)+4;
-			type = grf_filelist[ofs2+12];
-			if (type != 0) {	// Directory Index ... skip
-				fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
-				if (strlen(fname) > sizeof(aentry.fn) - 1) {
-					printf("GRF file name %s is too long\n", fname);
-					free(grf_filelist);
-					exit(EXIT_FAILURE);
-				}
-				srclen = 0;
-				if ((period_ptr = strrchr(fname, '.')) != NULL) {
-					for(lop = 0; lop < 4; lop++) {
-						if (strcmpi(period_ptr, ".gnd\0.gat\0.act\0.str"+lop*5) == 0)
-							break;
-					}
-					srclen = getlong(grf_filelist+ofs2) - getlong(grf_filelist+ofs2+8) - 715;
-					if(lop == 4) {
-						for(lop = 10, srccount = 1; srclen >= lop; lop = lop * 10, srccount++);
-					} else {
-						srccount = 0;
-					}
-				} else {
-					srccount = 0;
-				}
-
-				aentry.srclen         = srclen;
-				aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579;
-				aentry.declen         = getlong(grf_filelist+ofs2+8);
-				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e;
-				aentry.cycle          = srccount;
-				aentry.type           = type;
-				strncpy(aentry.fn, fname,sizeof(aentry.fn)-1);
-				aentry.fnd			  = NULL;
-#ifdef	GRFIO_LOCAL
-				aentry.gentry         = -(gentry+1);	// As Flag for making it a negative number carrying out the first time LocalFileCheck
-#else
-				aentry.gentry         = gentry+1;		// With no first time LocalFileCheck
-#endif
-				filelist_modify(&aentry);
-			}
-			ofs = ofs2 + 17;
-		}
-		free(grf_filelist);
-
-	} else if (grf_version == 0x02) {	//****** Grf version 02xx ******
-		unsigned char eheader[8];
-		unsigned char *rBuf;
-		uLongf rSize, eSize;
-
-		fread(eheader,1,8,fp);
-		rSize = getlong(eheader);	// Read Size
-		eSize = getlong(eheader+4);	// Extend Size
-
-		if ((long)rSize > grf_size-ftell(fp)) {
-			fclose(fp);
-			printf("Illegal data format: GRF compress entry size\n");
-			return 4;
-		}
-
-		rBuf = (unsigned char *)malloc(rSize);	// Get a Read Size
-		grf_filelist = (unsigned char *)malloc(eSize);	// Get a Extend Size
-		fread(rBuf,1,rSize,fp);
-		fclose(fp);
-		decode_zip(grf_filelist, &eSize, rBuf, rSize);	// Decode function
-		list_size = eSize;
-		free(rBuf);
-
-		entrys = getlong(grf_header+0x26) - 7;
-
-		// Get an entry
-		for(entry = 0, ofs = 0; entry < entrys; entry++) {
-			int ofs2, srclen, srccount, type;
-			FILELIST aentry;
-
-			fname = (char*)(grf_filelist+ofs);
-			if (strlen(fname) > sizeof(aentry.fn)-1) {
-				printf("GRF file name %s is too long\n", fname);
-				free(grf_filelist);
-				exit(EXIT_FAILURE);
-			}
-			ofs2 = ofs + (int)strlen(fname)+1;
-			type = grf_filelist[ofs2+12];
-			if (type == 1 || type == 3 || type == 5) {
-				srclen = getlong(grf_filelist+ofs2);
-				if (grf_filelist[ofs2+12] == 3) {
-					for (lop = 10, srccount = 1; srclen >= lop; lop = lop * 10, srccount++);
-				} else if (grf_filelist[ofs2+12] == 5) {
-					srccount = 0;
-				} else {	// if (grf_filelist[ofs2+12]==1) {
-					srccount = -1;
-				}
-
-				aentry.srclen         = srclen;
-				aentry.srclen_aligned = getlong(grf_filelist+ofs2+4);
-				aentry.declen         = getlong(grf_filelist+ofs2+8);
-				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e;
-				aentry.cycle          = srccount;
-				aentry.type           = type;
-				strncpy(aentry.fn,fname,sizeof(aentry.fn)-1);
-				aentry.fnd			  = NULL;
-#ifdef	GRFIO_LOCAL
-				aentry.gentry         = -(gentry+1);	// As Flag for making it a negative number carrying out the first time LocalFileCheck
-#else
-				aentry.gentry         = gentry+1;		// With no first time LocalFileCheck
-#endif
-				filelist_modify(&aentry);
-			}
-			ofs = ofs2 + 17;
-		}
-		free(grf_filelist);
-
-	} else {	//****** Grf Other version ******
-		fclose(fp);
-		printf("GRF version %04x not supported\n",getlong(grf_header+0x2a));
-		return 4;
-	}
-
-	filelist_adjust();	// Unnecessary area release of filelist
-
-	return 0;	// 0:no error
-}
-
-/*==========================================
- * Grfio : Resource file check
- *------------------------------------------*/
-static void grfio_resourcecheck(void)
-{
-	char w1[256], w2[256], src[256], dst[256], restable[256], line[256];
-	char *ptr, *buf;
-	FILELIST* entry;
-	int size;
-	FILE* fp;
-
-	// read resnametable from data directory and return if successful
-	sprintf(restable, "%sdata\\resnametable.txt", data_dir);
-	for (ptr = &restable[0]; *ptr != 0; ptr++)
-		if (*ptr == '\\') *ptr = '/';
-
-	fp = fopen(restable, "rb");
-	if (fp) {
-		while(fgets(line, sizeof(line), fp))
-		{
-			if (sscanf(line, "%[^#]#%[^#]#", w1, w2) == 2 &&
-				// we only need the maps' GAT and RSW files
-				(strstr(w2, ".gat") || strstr(w2, ".rsw")))
-			{
-				sprintf(src, "data\\%s", w1);
-				sprintf(dst, "data\\%s", w2);
-				entry = filelist_find(dst);
-				// create new entries reusing the original's info
-				if (entry != NULL) {
-					FILELIST fentry;
-					memcpy(&fentry, entry, sizeof(FILELIST));
-					strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
-					fentry.fnd = strdup(dst);
-					filelist_modify(&fentry);
-				}
-			}
-		}
-		fclose(fp);
-		return;	// we're done here!
-	}
-	
-	// read resnametable from loaded GRF's, only if it cannot be loaded from the data directory
-	buf = (char *)grfio_reads("data\\resnametable.txt", &size);
-	if (buf) {
-		buf[size] = 0;
-
-		ptr = buf;
-		while (ptr - buf < size) {
-			if (sscanf(ptr, "%[^#]#%[^#]#", w1, w2) == 2 &&
-				(strstr(w2, ".gat") || strstr(w2, ".rsw")))
-			{
-				sprintf(src, "data\\%s", w1);
-				sprintf(dst, "data\\%s", w2);
-				entry = filelist_find(dst);
-				if (entry != NULL) {
-					FILELIST fentry;
-					memcpy(&fentry, entry, sizeof(FILELIST));
-					strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
-					fentry.fnd = strdup(dst);
-					filelist_modify(&fentry);
-				}
-			}
-			ptr = strchr(ptr, '\n');	// Next line
-			if (!ptr) break;
-			ptr++;
-		}
-		free(buf);
-		return;
-	}
-
-}
-
-// reads a grf file and adds it to the list
-static int grfio_add(char* fname)
-{
-	#define	GENTRY_ADDS	4	// The number increment of gentry_table entries
-
-	if (gentry_entrys >= gentry_maxentry) {
-		gentry_maxentry += GENTRY_ADDS;
-		gentry_table = (char**)realloc(gentry_table, gentry_maxentry * sizeof(char*));
-		memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char*) * GENTRY_ADDS);
-	}
-
-	gentry_table[gentry_entrys++] = strdup(fname);
-
-	return grfio_entryread(fname, gentry_entrys - 1);
-}
-
-// removes all entries
-void grfio_final(void)
-{
-	if (filelist != NULL) {
-		int i;
-		for (i = 0; i < filelist_entrys; i++)
-			if (filelist[i].fnd != NULL)
-				free(filelist[i].fnd);
-
-		free(filelist);
-		filelist = NULL;
-	}
-	filelist_entrys = filelist_maxentry = 0;
-
-	if (gentry_table != NULL) {
-		int i;
-		for (i = 0; i < gentry_entrys; i++)
-			if (gentry_table[i] != NULL)
-				free(gentry_table[i]);
-
-		free(gentry_table);
-		gentry_table = NULL;
-	}
-	gentry_entrys = gentry_maxentry = 0;
-}
-
-/*==========================================
- * Grfio : Initialize
- *------------------------------------------*/
-void grfio_init(char* fname)
-{
-	FILE* data_conf;
-	char line[1024], w1[1024], w2[1024];
-	int grf_num = 0;
-
-	hashinit();	// hash table initialization
-
-	data_conf = fopen(fname, "r");
-	// It will read, if there is grf-files.txt.
-	if (data_conf) {
-		while(fgets(line, sizeof(line), data_conf))
-		{
-			if (line[0] == '/' && line[1] == '/')
-				continue;
-			if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
-				continue;
-			// Entry table reading
-			if(strcmp(w1, "grf") == 0)	// GRF file
-				grf_num += (grfio_add(w2) == 0);
-			else if(strcmp(w1,"data_dir") == 0) {	// Data directory
-				strcpy(data_dir, w2);
-				printf("Use data directory %s\n", w2);
-			}
-		}
-		fclose(data_conf);
-	} // end of reading grf-files.txt
-
-	if (grf_num == 0) {
-		printf("No GRF loaded, using default data directory\n");
-	}
-
-	// Unneccessary area release of filelist
-	filelist_adjust();
-
-	// Resource check
-	grfio_resourcecheck();
-
-	return;
-}

+ 0 - 20
src/tool/grfio.h

@@ -1,20 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#ifndef	_GRFIO_H_
-#define	_GRFIO_H_
-
-void grfio_init(char*);			// GRFIO Initialize
-void grfio_final(void);			// GRFIO Finalize
-void* grfio_reads(char*,int*);	// GRFIO data file read & size get
-char *grfio_find_file(char *fname);
-
-#define grfio_read(fn) grfio_reads(fn, NULL)
-
-int grfio_size(char*);			// GRFIO data file size get
-unsigned long grfio_crc32(const unsigned char *buf, unsigned int len);
-
-int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
-int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
-
-#endif /* _GRFIO_H_ */

+ 31 - 27
src/tool/mapcache.c

@@ -1,6 +1,12 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
+#include "../common/cbasetypes.h"
+#include "../common/grfio.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -9,11 +15,6 @@
 #include <unistd.h>
 #endif
 
-#include "../common/cbasetypes.h"
-#include "grfio.h"
-
-#define MAP_NAME_LENGTH 12
-#define MAP_NAME_LENGTH_EXT 16
 #define NO_WATER 1000000
 
 char grf_list_file[256] = "conf/grf-files.txt";
@@ -124,7 +125,7 @@ int read_map(char *name, struct map_data *m)
 	// Read water height
 	if (rsw) { 
 		water_height = (int)GetFloat(rsw+166);
-		free(rsw);
+		aFree(rsw);
 	} else
 		water_height = NO_WATER;
 
@@ -132,11 +133,11 @@ int read_map(char *name, struct map_data *m)
 	m->xs = (int16)GetULong(gat+6);
 	m->ys = (int16)GetULong(gat+10);
 	if (m->xs <= 0 || m->ys <= 0) {
-		free(gat);
+		aFree(gat);
 		return 0;
 	}
 	num_cells = (size_t)m->xs*(size_t)m->ys;
-	m->cells = (unsigned char *)malloc(num_cells);
+	m->cells = (unsigned char *)aMalloc(num_cells);
 
 	// Set cell properties
 	off = 14;
@@ -154,7 +155,7 @@ int read_map(char *name, struct map_data *m)
 		m->cells[xy] = (unsigned char)type;
 	}
 
-	free(gat);
+	aFree(gat);
 
 	return 1;
 }
@@ -168,7 +169,7 @@ void cache_map(char *name, struct map_data *m)
 
 	// Create an output buffer twice as big as the uncompressed map... this way we're sure it fits
 	len = (unsigned long)m->xs*(unsigned long)m->ys*2;
-	write_buf = (unsigned char *)malloc(len);
+	write_buf = (unsigned char *)aMalloc(len);
 	// Compress the cells and get the compressed length
 	encode_zip(write_buf, &len, m->cells, m->xs*m->ys);
 
@@ -185,8 +186,8 @@ void cache_map(char *name, struct map_data *m)
 	header.file_size += sizeof(struct map_info) + len;
 	header.map_count++;
 
-	free(write_buf);
-	free(m->cells);
+	aFree(write_buf);
+	aFree(m->cells);
 
 	return;
 }
@@ -245,7 +246,7 @@ void process_args(int argc, char *argv[])
 
 }
 
-int main(int argc, char *argv[])
+int do_init(int argc, char *argv[])
 {
 	FILE *list;
 	char line[1024];
@@ -255,15 +256,15 @@ int main(int argc, char *argv[])
 	// Process the command-line arguments
 	process_args(argc, argv);
 
-	printf("Initializing grfio with %s\n", grf_list_file);
+	ShowStatus("Initializing grfio with %s\n", grf_list_file);
 	grfio_init(grf_list_file);
 
 	// Attempt to open the map cache file and force rebuild if not found
-	printf("Opening map cache: %s\n", map_cache_file);
+	ShowStatus("Opening map cache: %s\n", map_cache_file);
 	if(!rebuild) {
 		map_cache_fp = fopen(map_cache_file, "rb");
 		if(map_cache_fp == NULL) {
-			printf("Existing map cache not found, forcing rebuild mode\n");
+			ShowNotice("Existing map cache not found, forcing rebuild mode\n");
 			rebuild = 1;
 		} else
 			fclose(map_cache_fp);
@@ -273,15 +274,15 @@ int main(int argc, char *argv[])
 	else
 		map_cache_fp = fopen(map_cache_file, "r+b");
 	if(map_cache_fp == NULL) {
-		printf("Failure when opening map cache file %s\n", map_cache_file);
+		ShowError("Failure when opening map cache file %s\n", map_cache_file);
 		exit(EXIT_FAILURE);
 	}
 
 	// Open the map list
-	printf("Opening map list: %s\n", map_list_file);
+	ShowStatus("Opening map list: %s\n", map_list_file);
 	list = fopen(map_list_file, "r");
 	if(list == NULL) {
-		printf("Failure when opening maps list file %s\n", map_list_file);
+		ShowError("Failure when opening maps list file %s\n", map_list_file);
 		exit(EXIT_FAILURE);
 	}
 
@@ -309,30 +310,33 @@ int main(int argc, char *argv[])
 
 		name[MAP_NAME_LENGTH_EXT-1] = '\0';
 		remove_extension(name);
-		printf("%s", name);
 		if(find_map(name))
-			printf(" already in cache!\n");
+			ShowInfo("Map '"CL_WHITE"%s"CL_RESET"' already in cache.\n", name);
 		else if(read_map(name, &map)) {
 			cache_map(name, &map);
-			printf(" successfully cached\n");
+			ShowInfo("Map '"CL_WHITE"%s"CL_RESET"' successfully cached.\n", name);
 		} else
-			printf(" not found in GRF!\n");
+			ShowError("Map '"CL_WHITE"%s"CL_RESET"' not found!\n", name);
 
 	}
 
-	printf("Closing map list: %s\n", map_list_file);
+	ShowStatus("Closing map list: %s\n", map_list_file);
 	fclose(list);
 
 	// Write the main header and close the map cache
-	printf("Closing map cache: %s\n", map_cache_file);
+	ShowStatus("Closing map cache: %s\n", map_cache_file);
 	fseek(map_cache_fp, 0, SEEK_SET);
 	fwrite(&header, sizeof(struct main_header), 1, map_cache_fp);
 	fclose(map_cache_fp);
 
-	printf("Finalizing grfio\n");
+	ShowStatus("Finalizing grfio\n");
 	grfio_final();
 
-	printf("%d maps now in cache\n", header.map_count);
+	ShowInfo("%d maps now in cache\n", header.map_count);
 
 	return 0;
 }
+
+void do_final(void)
+{
+}

+ 0 - 85
tools/checkversion.pl

@@ -1,85 +0,0 @@
-#!/usr/bin/perl -w
-
-##########################################################################
-# INFORMATION TOOL ABOUT THE SERVERS VERSION OF ATHENA
-#
-# By connection on a server, this software display the version of the
-# designed server.
-#-------------------------------------------------------------------------
-# Usages:
-#   ./checkversion.pl IP:port
-#   ./checkversion.pl IP port
-#   perl checkversion.pl IP:port
-#   perl checkversion.pl IP port
-#
-# note: default port: 6900
-#
-# When successfull, the software return the value 0.
-#
-##########################################################################
-
-#------------------------- start of configuration ------------------------
-
-$connecttimeout = 10;   # Connection Timeout (in seconds)
-
-#-------------------------- End of configuration -------------------------
-
-use IO::Socket;
-
-unless($ARGV[0]) {
-	print "USAGE: $0 server_ip:port\n";
-	exit(1);
-}
-
-$server = $ARGV[0];
-$port = $ARGV[1];
-$port = $1 if ($server =~ s/:(\d+)//);
-$port ||= 6900;
-
-# Connection to the server
-my($so,$er) = ();
-eval{
-	$so = IO::Socket::INET->new(
-		PeerAddr=> $server,
-		PeerPort=> $port,
-		Proto   => "tcp",
-		Timeout => $connecttimeout) or $er = 1;
-};
-
-if($er || $@) {
-	print "Can't not connect to server [$server:$port] !\n";
-	exit(2);
-}
-
-# Request for the server version
-print $so pack("v",30000); # 0x7530
-$so->flush();
-
-# Receiving of the answer of the server
-if (read($so,$buf,10) < 10) {
-	print "Invalid answer. It isn't an athena server or it is a too old version.\n";
-	exit(5);
-}
-
-# Sending end of connection to the server
-print $so pack("v",30002); # 0x7532
-$so->flush();
-
-# Analyse of the answer
-my($ret,$maver,$miver,$rev,$dev,$mod,$type,$mdver) = unpack("v c6 v",$buf);
-
-if ($ret != 30001) { # 0x7531
-	print "Invalid answer. It isn't an athena server or it is a too old version.\n";
-	exit(6);
-}
-
-my(@stype) = ();
-foreach $i(0..3) {
-	push @stype,(("login","char","inter","map")[$i]) if( $type & (1<<$i) );
-}
-print "  ".join("/",@stype)." server [$server:$port].\n";
-printf "  Athena version %s-%d.%d", ("stable","dev")[$dev], $maver,$miver;
-printf " revision %d",$rev if $rev;
-printf "%s%d\n",("","-mod")[$mod],$mdver;
-
-exit(0);

+ 0 - 149
vcproj-10/ladmin.vcxproj

@@ -1,149 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D356871D-58E1-450B-967A-E8E9646175AF}</ProjectGuid>
-    <RootNamespace>ladmin</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)\$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)\$(Configuration)\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;MINICORE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessToFile>false</PreprocessToFile>
-      <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers>
-      <MinimalRebuild>true</MinimalRebuild>
-      <ExceptionHandling>
-      </ExceptionHandling>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <AdditionalOptions>
-      </AdditionalOptions>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <AdditionalOptions>/FIXED:NO %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>libcmtd.lib;oldnames.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <OutputFile>$(OutDir)ladmin.exe</OutputFile>
-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
-      <OmitFramePointers>true</OmitFramePointers>
-      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
-      <WholeProgramOptimization>true</WholeProgramOptimization>
-      <AdditionalIncludeDirectories>..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;MINICORE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>false</FunctionLevelLinking>
-      <AdditionalOptions>
-      </AdditionalOptions>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <AdditionalDependencies>libcmt.lib;oldnames.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <OutputFile>$(OutDir)ladmin.exe</OutputFile>
-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <OptimizeReferences>true</OptimizeReferences>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\ladmin\ladmin.c" />
-    <ClCompile Include="..\src\common\core.c" />
-    <ClCompile Include="..\src\common\malloc.c" />
-    <ClCompile Include="..\src\common\md5calc.c" />
-    <ClCompile Include="..\src\common\showmsg.c" />
-    <ClCompile Include="..\src\common\socket.c" />
-    <ClCompile Include="..\src\common\strlib.c" />
-    <ClCompile Include="..\src\common\timer.c" />
-    <ClCompile Include="..\src\common\utils.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\src\ladmin\ladmin.h" />
-    <ClInclude Include="..\src\common\core.h" />
-    <ClInclude Include="..\src\common\malloc.h" />
-    <ClInclude Include="..\src\common\md5calc.h" />
-    <ClInclude Include="..\src\common\mmo.h" />
-    <ClInclude Include="..\src\common\showmsg.h" />
-    <ClInclude Include="..\src\common\socket.h" />
-    <ClInclude Include="..\src\common\strlib.h" />
-    <ClInclude Include="..\src\common\timer.h" />
-    <ClInclude Include="..\src\common\utils.h" />
-    <ClInclude Include="..\src\common\version.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>

+ 0 - 1
vcproj-10/login-server_sql.vcxproj

@@ -153,7 +153,6 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\src\login\account_sql.c" />
-    <ClCompile Include="..\src\login\admin.c" />
     <ClCompile Include="..\src\login\ipban_sql.c" />
     <ClCompile Include="..\src\login\login.c" />
     <ClCompile Include="..\src\login\loginlog_sql.c" />

+ 0 - 1
vcproj-10/login-server_txt.vcxproj

@@ -144,7 +144,6 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\src\login\account_txt.c" />
-    <ClCompile Include="..\src\login\admin.c" />
     <ClCompile Include="..\src\login\ipban_txt.c" />
     <ClCompile Include="..\src\login\login.c" />
     <ClCompile Include="..\src\login\loginlog_txt.c" />

+ 17 - 4
vcproj-10/mapcache.vcxproj

@@ -48,7 +48,7 @@
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessToFile>false</PreprocessToFile>
       <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers>
       <MinimalRebuild>true</MinimalRebuild>
@@ -90,7 +90,7 @@
       <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
       <WholeProgramOptimization>true</WholeProgramOptimization>
       <AdditionalIncludeDirectories>..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>false</FunctionLevelLinking>
@@ -120,11 +120,24 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\tool\grfio.c" />
+    <ClCompile Include="..\src\common\core.c" />
+    <ClCompile Include="..\src\common\grfio.c" />
+    <ClCompile Include="..\src\common\malloc.c" />
+    <ClCompile Include="..\src\common\showmsg.c" />
+    <ClCompile Include="..\src\common\strlib.c" />
+    <ClCompile Include="..\src\common\utils.c" />
     <ClCompile Include="..\src\tool\mapcache.c" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\src\tool\grfio.h" />
+    <ClInclude Include="..\src\common\cbasetypes.h" />
+    <ClInclude Include="..\src\common\core.h" />
+    <ClInclude Include="..\src\common\grfio.h" />
+    <ClInclude Include="..\src\common\malloc.h" />
+    <ClInclude Include="..\src\common\mmo.h" />
+    <ClInclude Include="..\src\common\showmsg.h" />
+    <ClInclude Include="..\src\common\strlib.h" />
+    <ClInclude Include="..\src\common\utils.h" />
+    <ClInclude Include="..\src\common\version.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 0 - 4
vcproj-6/login-server_sql.dsp

@@ -207,10 +207,6 @@ SOURCE=..\src\login\account_sql.c
 # End Source File
 # Begin Source File
 
-SOURCE=..\src\login\admin.c
-# End Source File
-# Begin Source File
-
 SOURCE=..\src\login\ipban.h
 # End Source File
 # Begin Source File

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません