* 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
This commit is contained in:
ai4rei 2011-01-30 00:25:44 +00:00
parent 9256dbfc80
commit d41e850975
118 changed files with 3240 additions and 7899 deletions

View File

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

View File

@ -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.")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

3
configure vendored
View File

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

View File

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

View File

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

View File

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

View File

@ -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; },{},{}

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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_ */

View File

@ -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/%) \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
}
while(fgets(line, sizeof(line), fp))
skillid = atoi(split[0]);
id = skillid - GD_SKILLBASE;
if( id < 0 || id >= MAX_GUILDSKILL )
{
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++;
ShowWarning("guild_read_guildskill_tree_db: Invalid skill id %d.\n", skillid);
return false;
}
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;
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;
}
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]);
}
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;
}
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));
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;
}
idb_put(castle_db,gc->castle_id,gc);
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);
//intif_guild_castle_info(gc->castle_id);
idb_put(castle_db,gc->castle_id,gc);
//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");

View File

@ -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;
}
int read_homunculusdb(void)
static bool read_homunculusdb_sub(char* str[], int columns, int current)
{
FILE *fp;
char line[1024], *p;
int i, k, classid;
int j = 0;
const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
char *str[50];
int classid;
struct s_homunculus_db *db;
memset(homunculus_db,0,sizeof(homunculus_db));
for(i = 0; i<2; i++)
//Base Class,Evo Class
classid = atoi(str[0]);
if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
{
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;
}
while(fgets(line, sizeof(line), fp) && j < MAX_HOMUNCULUS_CLASS)
{
if(line[0] == '/' && line[1] == '/')
continue;
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)
{
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]);
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)
{
int i;
const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
memset(homunculus_db,0,sizeof(homunculus_db));
for(i = 0; i<ARRAYLENGTH(filename); i++)
{
char path[256];
if( i > 0 )
{
sprintf(path, "%s/%s", db_path, filename[i]);
if( !exists(path) )
{
continue;
}
}
sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub);
}
return 0;
}
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;
int minJobLevelPresent = 0;
if( columns == 14 )
minJobLevelPresent = 1; // MinJobLvl has been added
// check for bounds [celest]
classid = atoi(split[0]) - HM_CLASS_BASE;
if ( classid >= MAX_HOMUNCULUS_CLASS )
{
ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0]));
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)
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;
}
hskill_tree[classid][j].id = k;
hskill_tree[classid][j].max = atoi(split[2]);
if (minJobLevelPresent)
hskill_tree[classid][j].joblv = atoi(split[3]);
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]);
}
return true;
}
int read_homunculus_skilldb(void)
{
FILE *fp;
char line[1024], *p;
int k, classid;
int j = 0;
char *split[15];
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;
}
sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 14, -1, &read_homunculus_skilldb_sub);
while(fgets(line, sizeof(line), fp))
{
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
// 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)
for(j = 0; j < MAX_SKILL_TREE && hskill_tree[classid][j].id && hskill_tree[classid][j].id != k; j++);
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;
}
hskill_tree[classid][j].id=k;
hskill_tree[classid][j].max=atoi(split[2]);
if (minJobLevelPresent)
hskill_tree[classid][j].joblv=atoi(split[3]);
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]);
}
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","homun_skill_tree.txt");
return 0;
}

View File

@ -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;
}
if (j < 2 || str[0] == NULL ||
(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
continue;
k = atoi(str[1]);
if (k > 0) {
id->flag.available = 1;
id->view_id = k;
} else
id->flag.available = 0;
ln++;
ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid);
return false;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_avail.txt");
return 0;
sprite = atoi(str[1]);
if( sprite > 0 )
{
id->flag.available = 1;
id->view_id = sprite;
}
else
{
id->flag.available = 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))
nameid = atoi(str[0]);
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;
}
if(str[0]==NULL)
continue;
nameid=atoi(str[0]);
if(nameid<=0 || !(id=itemdb_exists(nameid)))
continue;
id->flag.no_equip |= atoi(str[1]);
ln++;
ShowWarning("itemdb_read_noequip: Invalid item id %d.\n", nameid);
return false;
}
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;
id->flag.no_equip |= atoi(str[1]);
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;
}
if (j < 3 || str[0] == NULL ||
(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
continue;
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++;
}
//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;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_trade.txt");
return 0;
flag = atoi(str[1]);
gmlv = atoi(str[2]);
if( flag < 0 || flag >= 128 )
{//Check range
ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid);
return false;
}
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;
}
if (j < 2 || str[0] == NULL ||
(nameid = atoi(str[0])) < 0 || !(id = itemdb_exists(nameid)))
continue;
id->delay = atoi(str[1]);
item_delays++;
ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", 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;
delay = atoi(str[1]);
if( delay < 0 )
{
ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid);
return false;
}
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);
}

View File

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

View File

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

View File

@ -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");
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 )
{
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]);
return true;
}
int read_mercenarydb(void)
{
memset(mercenary_db,0,sizeof(mercenary_db));
fp = fopen(line, "r");
if( !fp )
{
ShowError("read_mercenarydb : can't read mercenary_db.txt\n");
return -1;
}
while( fgets(line, sizeof(line), fp) && j < MAX_MERCENARY_CLASS )
{
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++;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' mercenaries in '"CL_WHITE"db/mercenary_db.txt"CL_RESET"'.\n",j);
sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub);
return 0;
}
int read_mercenary_skilldb(void)
{
FILE *fp;
char line[1024], *p;
char *str[3];
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;
}
skillid = atoi(str[1]);
if( skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL )
{
ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skillid);
return false;
}
while( fgets(line, sizeof(line), fp) )
{
k++;
if( line[0] == '/' && line[1] == '/' )
continue;
db = &mercenary_db[i];
skilllv = atoi(str[2]);
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;
}
i = skillid - MC_SKILLBASE;
db->skill[i].id = skillid;
db->skill[i].lv = skilllv;
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;
}
return true;
}
db = &mercenary_db[i];
skilllv = atoi(str[2]);
int read_mercenary_skilldb(void)
{
sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub);
i = skillid - MC_SKILLBASE;
db->skill[i].id = skillid;
db->skill[i].lv = skilllv;
j++;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/mercenary_skill_db.txt"CL_RESET"'.\n",j);
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

11
src/plugins/sample.def Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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