From 7b2f7c0503cb5be8bc45f57353d838a4dbf84d7b Mon Sep 17 00:00:00 2001 From: DracoRPG Date: Mon, 17 Jul 2006 00:15:33 +0000 Subject: Orn's and Albator's Homunculus system, finally, YAY!! git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@7706 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 4 + conf-tmpl/battle/misc.conf | 9 + db/exp_homun.txt | 100 +++ db/homun_skill_tree.txt | 73 +++ db/homunculus_db.txt | 17 + db/item_db.txt | 2 +- db/mob_db.txt | 32 +- db/packet_db.txt | 22 +- db/skill_cast_db.txt | 32 +- db/skill_db.txt | 22 +- db/skill_require_db.txt | 20 +- sql-files/homunculus.sql | 21 - sql-files/main.sql | 1124 ++++++++++++++++++---------------- sql-files/upgrade_svn7706.sql | 36 ++ src/char_sql/Makefile | 7 +- src/char_sql/char.c | 9 +- src/char_sql/int_homun.c | 300 +++++++++ src/char_sql/int_homun.h | 14 + src/char_sql/inter.c | 11 +- src/common/mmo.h | 32 +- src/map/atcommand.c | 169 +++++ src/map/atcommand.h | 6 + src/map/battle.c | 29 +- src/map/battle.h | 2 + src/map/charsave.c | 41 +- src/map/charsave.h | 5 + src/map/chrif.c | 1 + src/map/clif.c | 297 ++++++--- src/map/clif.h | 10 +- src/map/intif.c | 170 +++++- src/map/intif.h | 7 + src/map/map.c | 4 + src/map/map.h | 37 +- src/map/mercenary.c | 1217 +++++++++++++++++++++++++++++++------ src/map/mercenary.h | 79 ++- src/map/mob.c | 71 ++- src/map/pc.c | 26 + src/map/script.c | 22 +- src/map/skill.c | 382 +++++++++++- src/map/skill.h | 3 + src/map/status.c | 410 +++++++++---- src/map/status.h | 2 + src/map/unit.c | 24 +- vcproj-7.1/char-server_sql.vcproj | 6 + 44 files changed, 3842 insertions(+), 1065 deletions(-) create mode 100644 db/exp_homun.txt create mode 100644 db/homun_skill_tree.txt create mode 100644 db/homunculus_db.txt delete mode 100644 sql-files/homunculus.sql create mode 100644 sql-files/upgrade_svn7706.sql create mode 100644 src/char_sql/int_homun.c create mode 100644 src/char_sql/int_homun.h diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index ade10bc4d..2072647e3 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,10 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2006/07/17 + * Added Homunculus system, enjoy! [orn aka Nylou] + - WARNING: This currently only works with the SQL version, as the TXT char-server + has no code for it at the moment. You TXT server won't break, but the char-server + will complain of an unknown packet if you try to get an Homunculus * Updated nomemo mapflags based on info from http://ro.doddlercon.com/images/memo.jpg [Poki#3] 2006/07/15 diff --git a/conf-tmpl/battle/misc.conf b/conf-tmpl/battle/misc.conf index eb21bfbbd..5ae83e707 100644 --- a/conf-tmpl/battle/misc.conf +++ b/conf-tmpl/battle/misc.conf @@ -130,3 +130,12 @@ duel_time_interval: 60 // NOTE: For this setting to make effect you have to use a server compiled with // Cell Stack Limit support (see src/map/map.h) cell_stack_limit: 1 + + +// Homunculus settings: I put them there at the moment, they will certainly get their own file later [DracoRPG] + +// Intimacy needed to use Evolved Vanilmirth's Bio Explosion +hvan_explosion_intimate: 45000 + +// Show stat growth to the owner when an Homunculus levels up +homunculus_show_growth: 0 \ No newline at end of file diff --git a/db/exp_homun.txt b/db/exp_homun.txt new file mode 100644 index 000000000..32257b0c9 --- /dev/null +++ b/db/exp_homun.txt @@ -0,0 +1,100 @@ +//Homunculus LvUp experience value table +50 +110 +180 +260 +350 +630 +950 +1310 +1710 +2150 +3180 +4300 +5510 +6810 +8200 +10800 +13560 +16480 +19560 +22800 +28090 +33630 +39420 +45460 +51750 +6150 +70910 +81030 +91510 +102350 +117580 +133300 +149510 +166210 +183400 +206480 +230200 +254560 +279560 +305200 +338450 +372510 +407380 +443060 +479550 +525590 +572630 +620670 +669710 +719750 +781500 +844460 +908630 +974010 +1040600 +1121280 +1203400 +1286960 +1371960 +1458400 +1561530 +1666350 +1772860 +1881060 +1990950 +2120350 +2251710 +2385030 +2520310 +2657550 +2817340 +2979380 +3143670 +3310210 +3479000 +3673600 +3870760 +4070480 +4272760 +4477600 +4711730 +4948750 +5188660 +5431460 +5677150 +5955830 +6237750 +6522910 +6811310 +7102950 +7431500 +7763660 +8099430 +8438810 +8781800 +9165840 +9553880 +9945920 +0 \ No newline at end of file diff --git a/db/homun_skill_tree.txt b/db/homun_skill_tree.txt new file mode 100644 index 000000000..54e7c89ca --- /dev/null +++ b/db/homun_skill_tree.txt @@ -0,0 +1,73 @@ +//CLass,Skill-ID,MaxLV,Prerequisite Skill-ID-1,Prerequisite Skill-ID-1-Lv,PrereqSkill-ID-2,PrereqSkill-ID-2-Lv,PrereqSkill-ID-3,PrereqSkill-ID-3-Lv,PrereqSkill-ID-4,PrereqSkill-ID-4-Lv,PrereqSkill-ID-5,PrereqSkill-ID-5-Lv//CLASS_SKILLNAME#Skill Name# +//Lif +6001,8001,5,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL +6001,8002,5,8001,3,0,0,0,0,0,0,0,0 //HLIF_AVOID +6001,8003,5,8001,5,0,0,0,0,0,0,0,0 //HLIF_BRAIN +//Amistr +6002,8005,5,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE +6002,8006,5,8005,5,0,0,0,0,0,0,0,0 //HAMI_DEFENCE +6002,8007,5,8006,3,0,0,0,0,0,0,0,0 //HAMI_SKIN +//Filir +6003,8009,5,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON +6003,8010,5,8009,3,0,0,0,0,0,0,0,0 //HFLI_FLEET +6003,8011,5,8010,3,0,0,0,0,0,0,0,0 //HFLI_SPEED +//Vanilmirth +6004,8013,5,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE, +6004,8014,5,8013,3,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC +6004,8015,5,8013,5,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT +//Lif2 +6005,8001,5,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL +6005,8002,5,8001,3,0,0,0,0,0,0,0,0 //HLIF_AVOID +6005,8003,5,8001,5,0,0,0,0,0,0,0,0 //HLIF_BRAIN +//Amistr2 +6006,8005,5,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE +6006,8006,5,8005,5,0,0,0,0,0,0,0,0 //HAMI_DEFENCE +6006,8007,5,8006,3,0,0,0,0,0,0,0,0 //HAMI_SKIN +//Filir2 +6007,8009,5,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON +6007,8010,5,8009,3,0,0,0,0,0,0,0,0 //HFLI_FLEET +6007,8011,5,8010,3,0,0,0,0,0,0,0,0 //HFLI_SPEED +//Vanilmirth2 +6008,8013,5,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE, +6008,8014,5,8013,3,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC +6008,8015,5,8013,5,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT +//Lif_H +6009,8001,5,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL +6009,8002,5,8001,3,0,0,0,0,0,0,0,0 //HLIF_AVOID +6009,8003,5,8001,5,0,0,0,0,0,0,0,0 //HLIF_BRAIN +6009,8004,3,0,0,0,0,0,0,0,0,0,0 //HLIF_CHANGE +//Amistr_H +6010,8005,5,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE +6010,8006,5,8005,5,0,0,0,0,0,0,0,0 //HAMI_DEFENCE +6010,8007,5,8006,3,0,0,0,0,0,0,0,0 //HAMI_SKIN +6010,8008,3,0,0,0,0,0,0,0,0,0,0 //HAMI_BLOODLUST +//Filir_H +6011,8009,5,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON +6011,8010,5,8009,3,0,0,0,0,0,0,0,0 //HFLI_FLEET +6011,8011,5,8010,3,0,0,0,0,0,0,0,0 //HFLI_SPEED +6011,8012,3,0,0,0,0,0,0,0,0,0,0 //HFLI_SBR44 +//Vanilmirth_H +6012,8013,5,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE, +6012,8014,5,8013,3,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC +6012,8015,5,8013,5,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT +6012,8016,3,0,0,0,0,0,0,0,0,0,0 //HVAN_EXPLOSION +//Lif2_H +6013,8001,5,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL +6013,8002,5,8001,3,0,0,0,0,0,0,0,0 //HLIF_AVOID +6013,8003,5,8001,5,0,0,0,0,0,0,0,0 //HLIF_BRAIN +6013,8004,3,0,0,0,0,0,0,0,0,0,0 //HLIF_CHANGE +//Amistr2_H +6014,8005,5,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE +6014,8006,5,8005,5,0,0,0,0,0,0,0,0 //HAMI_DEFENCE +6014,8007,5,8006,3,0,0,0,0,0,0,0,0 //HAMI_SKIN +6014,8008,3,0,0,0,0,0,0,0,0,0,0 //HAMI_BLOODLUST +//Filir2_H +6015,8009,5,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON +6015,8010,5,8009,3,0,0,0,0,0,0,0,0 //HFLI_FLEET +6015,8011,5,8010,3,0,0,0,0,0,0,0,0 //HFLI_SPEED +6015,8012,3,0,0,0,0,0,0,0,0,0,0 //HFLI_SBR44 +//Vanilmirth2_H +6016,8013,5,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE, +6016,8014,5,8013,3,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC +6016,8015,5,8013,5,0,0,0,0,0,0,0,0 //HVAN_INSTRUCT +6016,8016,3,0,0,0,0,0,0,0,0,0,0 //HVAN_EXPLOSION diff --git a/db/homunculus_db.txt b/db/homunculus_db.txt new file mode 100644 index 000000000..8f5304f56 --- /dev/null +++ b/db/homunculus_db.txt @@ -0,0 +1,17 @@ +//class,name,baseHP,baseSP,baseSTR,baseAGI,baseVIT,baseINT,baseDEX,baseLUK,baseIntimacy,baseHungry,hungryDelay,foodID,gminHP,gmaxHP,gminSP,gmaxSP,gminSTR,gmaxSTR,gminAGI,gmaxAGI,gminVIT,gmaxVIT,gminINT,gmaxINT,gminDEX,gmaxDEX,gminLUK,gmaxLUK,evol_class,baseASPD,size,race,element,accessID +6001,Lif,150,40,17,20,15,35,24,12,21,32,60000,537,60,100,4,9,1,8,3,8,1,14,1,14,1,14,3,14,6009,700,0,0,0,0 +6002,Amistr,320,10,20,17,35,11,24,12,21,32,60000,912,80,130,1,4,3,14,3,12,1,14,1,2,2,8,3,10,6010,700,0,0,0,0 +6003,Filir,90,25,29,35,9,8,30,9,21,32,60000,910,45,75,3,6,1,14,1,20,1,1,2,8,1,14,3,10,6011,700,0,0,0,0 +6004,Vanilmirth,80,11,11,11,11,11,11,11,21,32,60000,911,30,150,0,7,1,20,1,20,1,20,1,20,1,20,3,20,6012,700,0,0,0,0 +6005,Lif2,150,40,17,20,15,35,24,12,21,32,60000,537,60,100,4,9,1,8,3,8,1,14,1,14,1,14,3,14,6013,700,0,0,0,0 +6006,Amistr2,320,10,20,17,35,11,24,12,21,32,60000,912,80,130,1,4,3,14,3,12,1,14,1,2,2,8,3,10,6014,700,0,0,0,0 +6007,Filir2,90,25,29,35,9,8,30,9,21,32,60000,910,45,75,3,6,1,14,1,20,1,1,2,8,1,14,3,10,6015,700,0,0,0,0 +6008,Vanilmirth2,80,11,11,11,11,11,11,11,21,32,60000,911,30,150,0,7,1,20,1,20,1,20,1,20,1,20,3,20,6016,700,0,0,0,0 +6009,Lif_H,150,40,17,20,15,35,24,12,21,32,60000,537,60,100,4,9,1,8,3,8,1,14,1,14,1,14,3,14,0,700,1,0,0,0 +6010,Amistr_H,320,10,20,17,35,11,24,12,21,32,60000,912,80,130,1,4,3,14,3,12,1,14,1,2,2,8,3,10,0,700,1,0,0,0 +6011,Filir_H,90,25,29,35,9,8,30,9,21,32,60000,910,45,75,3,6,1,14,1,20,1,1,2,8,1,14,3,10,0,700,1,0,0,0 +6012,Vanilmirth_H,80,11,11,11,11,11,11,11,21,32,60000,911,30,150,0,7,1,20,1,20,1,20,1,20,1,20,3,20,0,700,1,0,0,0 +6013,Lif2_H,150,40,17,20,15,35,24,12,21,32,60000,537,60,100,4,9,1,8,3,8,1,14,1,14,1,14,3,14,0,700,1,0,0,0 +6014,Amistr2_H,320,10,20,17,35,11,24,12,21,32,60000,912,80,130,1,4,3,14,3,12,1,14,1,2,2,8,3,10,0,700,1,0,0,0 +6015,Filir2_H,90,25,29,35,9,8,30,9,21,32,60000,910,45,75,3,6,1,14,1,20,1,1,2,8,1,14,3,10,0,700,1,0,0,0 +6016,Vanilmirth2_H,80,11,11,11,11,11,11,11,21,32,60000,911,30,150,0,7,1,20,1,20,1,20,1,20,1,20,3,20,0,700,1,0,0,0 diff --git a/db/item_db.txt b/db/item_db.txt index 7544d05d2..a5affc610 100644 --- a/db/item_db.txt +++ b/db/item_db.txt @@ -2433,7 +2433,7 @@ 12037,Lotto_Box_03,Lotto Box 03,2,,10,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem rand(7381,7390),1; },{},{} 12038,Lotto_Box_04,Lotto Box 04,2,,10,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem groupranditem(IG_LottoBox),1; },{},{} 12039,Lotto_Box_05,Lotto Box 05,2,,10,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem rand(7542,7546),1; },{},{} -12040,Philosopher's_Stone,Philosopher's Stone,2,,50000,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} +12040,Philosopher's_Stone,Philosopher's Stone,2,,50000,300,,,,,0xFFFFFFFF,7,2,,,,,,{ homevolution ; },{},{} // Mixed Foods (+1 to +5) 12041,Boiled_Down_Locust,Boiled Down Locust,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFood, 1200000, 1; percentheal 5,0; },{},{} 12042,Seasoned_Webs,Seasoned Webs,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFood, 1200000, 2; percentheal 5,0; },{},{} diff --git a/db/mob_db.txt b/db/mob_db.txt index 616dfacc4..fbf4f1e95 100644 --- a/db/mob_db.txt +++ b/db/mob_db.txt @@ -831,19 +831,19 @@ 1796,G_AUNOE,Aunoe,Aunoe,1,50,0,2,1,1,7,10,0,5,1,1,1,1,6,30,10,12,1,3,21,131,400,1872,672,480,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 //Homunculi (Don't uncomment) (Why? :P [Poki#3]) -//6001,LIF,Lif,Lif,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,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 -//6002,AMISTR,Amistr,Amistr,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,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 -//6003,FILIR,Filir,Filir,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,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 -//6004,VANILMIRTH,Vanilmirth,Vanilmirth,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,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 -//6005,LIF2,Lif,Lif,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,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 -//6006,AMISTR2,Amistr,Amistr,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,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 -//6007,FILIR2,Filir,Filir,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,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 -//6008,VANILMIRTH2,Vanilmirth,Vanilmirth,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,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 -//6009,LIF_H,Lif,Lif,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,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 -//6010,AMISTR_H,Amistr,Amistr,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,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 -//6011,FILIR_H,Filir,Filir,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,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 -//6012,VANILMIRTH_H,Vanilmirth,Vanilmirth,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,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 -//6013,LIF_H2,Lif,Lif,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,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 -//6014,AMISTR_H2,Amistr,Amistr,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,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 -//6015,FILIR_H2,Filir,Filir,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,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 -//6016,VANILMIRTH_H2,Vanilmirth,Vanilmirth,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,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 +6001,LIF,Lif,Lif,50,8010,708,465,94,1,170,325,48,21,1,94,48,129,99,90,10,12,1,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Lif +6002,AMISTR,Amistr,Amistr,50,12022,255,465,94,1,208,416,83,12,1,89,84,25,76,75,10,12,1,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Amistr +6003,FILIR,Filir,Filir,50,5820,515,3872,2695,1,200,401,18,23,1,129,19,95,111,69,10,12,1,0,80,145,250,1608,864,288,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Filir +6004,VANILMIRTH,Vanilmirth,Vanilmirth,50,9026,358,3872,2695,2,226,452,74,32,1,131,75,155,112,120,10,12,1,0,80,145,250,1264,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Vanilmirth +6005,LIF2,Lif,Lif,50,8010,708,465,94,1,170,325,48,21,1,94,48,129,99,90,10,12,1,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Lif +6006,AMISTR2,Amistr,Amistr,50,12022,255,465,94,1,208,416,83,12,1,89,84,25,76,75,10,12,1,0,80,145,200,1264,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Amistr +6007,FILIR2,Filir,Filir,50,5820,515,3872,2695,1,200,401,18,23,1,129,19,95,111,69,10,12,1,0,80,145,200,1024,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Filir +6008,VANILMIRTH2,Vanimirth,Vanilmirth,50,9026,358,3872,2695,2,226,452,74,32,1,131,75,155,112,120,10,12,1,0,80,145,150,1024,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Vanilmirth +6009,LIF_H,Lif,Lif,50,8010,708,465,94,1,200,410,48,21,1,97,48,155,110,99,10,12,1,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Lif +6010,AMISTR_H,Amistr,Amistr,50,12022,255,465,94,1,230,460,83,12,1,93,84,30,85,83,10,12,2,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Amistr +6011,FILIR_H,Filir,Filir,50,5820,515,3872,2695,1,220,440,18,23,1,138,19,105,126,80,10,12,2,0,80,145,250,1608,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Filir +6012,VANILMIRTH_H,Vanilmirth,Vanilmirth,50,9026,358,3872,2695,2,280,550,74,32,1,135,75,162,120,126,10,12,2,0,80,145,250,1264,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Vanilmirth +6013,LIF_H2,Lif,Lif,50,8010,708,465,94,1,200,410,48,21,1,97,48,155,110,99,10,12,1,0,60,145,300,1608,816,396,0,0,0,0,0,0,0,0,999,150,953,5500,912,220,757,61,1003,120,715,200,998,350,0,0,0,0,4072,5//1Lif +6014,AMISTR_H2,Amistr,Amistr,50,12022,255,465,94,1,230,460,83,12,1,93,84,30,85,83,10,12,2,0,80,145,200,1264,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Amistr +6015,FILIR_H2,Filir,Filir,50,5820,515,3872,2695,1,220,440,18,23,1,138,19,105,126,80,10,12,2,0,80,145,200,1024,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Filir +6016,VANILMIRTH_H2,Vanimirth,Vanilmirth,50,9026,358,3872,2695,2,280,550,74,32,1,135,75,162,120,126,10,12,2,0,80,145,150,1024,864,288,0,0,0,0,0,0,0,0,7004,2000,7054,5500,1000,250,997,30,512,0,757,250,985,163,0,0,0,0,4072,5//1Vanilmirth diff --git a/db/packet_db.txt b/db/packet_db.txt index 9c4296926..6a00e18f9 100644 --- a/db/packet_db.txt +++ b/db/packet_db.txt @@ -676,9 +676,9 @@ packet_ver: 17 0x022b,57 0x022c,64 0x022d,5 -0x0232,9 -0x0233,11 -0x0234,-1 +0x0232,9,hommoveto,6 +0x0233,11,homattack,0 +0x0234,6,hommovetomaster,0 //2005-06-28aSakexe by Sara packet_ver: 18 @@ -695,18 +695,22 @@ packet_ver: 18 0x00f3,-1,globalmessage,2:4 0x00f5,13,takeitem,9 0x00f7,18,movefromkafra,11:14 +0x0112,4,homuseskillpoint,0 0x0113,33,useskilltopos,12:15:18:31 0x0116,12,dropitem,3:10 0x0143,10,npcamountinput,2:6 0x0190,24,actionrequest,11:23 0x0193,2,closekafra,0 0x20e,10 -//Homon Status -0x22e,71 -//Start Homunculus? -0x230,12 -//Homon Skill list -0x235,115 +0x022d,5,hommenu,4 // Menu (1 = feed ; 2 = dead) +0x022e,71 // Status +0x022f,5 // Feeding reply +0x0230,12 // Is Homunculus +0x0231,26,changehomunculusname,0 +0x0232,9,hommoveto,6 +0x0233,11,homattack,0 +0x0234,6,hommovetomaster,0 +0x0235,115 // Skills 0x237,2,rankingpk,0 0x23d,-1 0x23e,4 diff --git a/db/skill_cast_db.txt b/db/skill_cast_db.txt index 52a0574d2..02ebc4f7c 100644 --- a/db/skill_cast_db.txt +++ b/db/skill_cast_db.txt @@ -376,7 +376,13 @@ //-- AM_CP_HELM 237,2000,0,0,120000:240000:360000:480000:600000,0 //========================================== - +//-- AM_CALLHOMUNCULUS +243,2000,0,0,0,0 +//-- AM_REST +244,2000,0,0,0,0 +//-- AM_RESURRECTHOMUN +247,2000,0,0,0,0 +//========================================== //===== Crusader =========================== //-- CR_AUTOGUARD @@ -959,6 +965,30 @@ 1019,2000,1000,0,1800000,0 //========================================== +//========================================== +//-- HLIF_HEAL +8001,0,1000,0,0,1000 +//-- HLIF_AVOID +8002,0,0,0,40000:35000:30000:25000:20000,0 +//-- HLIF_CHANGE +8004,0,0,0,60000:180000:300000,600000:900000:1200000 +//-- HAMI_DEFENCE +8006,0,0,0,40000:35000:30000:25000:20000,30000 +//-- HAMI_BLOODLUST +8008,0,0,0,60000:180000:300000,300000:600000:900000 +//-- HFLI_MOON +8009,0,0,1000,0,0 +//-- HFLI_FLEET +8010,0,0,0,60000:55000:50000:45000:40000,60000:70000:80000:90000:120000 +//-- HFLI_SPEED +8011,0,0,0,60000:55000:50000:45000:40000,60000:70000:80000:90000:120000 +//-- HVAN_CAPRICE +8013,700:1400:2100:2800:3500,0,1000:1200:1400:1600:1800,0,1000:1200:1400:1600:1800 +//-- HVAN_CHAOTIC +8014,0,0,1000,0,1000 +//-- HVAN_EXPLOSION +8016,0,0,1000,0,0 +//========================================== //===== Guild Skills ======================= //-- GD_LEADERSHIP diff --git a/db/skill_db.txt b/db/skill_db.txt index f7acb1481..4d8a54e2c 100644 --- a/db/skill_db.txt +++ b/db/skill_db.txt @@ -263,8 +263,8 @@ //240,0,0,0,0,0,0,5,0,no,0,0,0,none,0 //AM_CREATECREATURE#Life Creation# //241,0,0,0,0,0,0,5,0,no,0,0,0,none,0 //AM_CULTIVATION#Cultivation# //242,0,0,0,0,0,0,5,0,no,0,0,0,none,0 //AM_FLAMECONTROL#Flame Control# -243,0,6,4,0,1,0,1,0,no,0,0,0,none,0 //AM_CALLHOMUN#Call Homunculus# -244,0,6,4,0,1,0,1,0,no,0,0,0,none,0 //AM_REST#Peaceful Rest# +243,0,0,4,0,1,0,1,0,no,0,0,0,none,0 //AM_CALLHOMUN#Call Homunculus# +244,0,0,4,0,1,0,1,0,no,0,0,0,none,0 //AM_REST#Peaceful Rest# //245,0,0,0,0,0,0,10,0,no,0,0,0,none,0 //AM_DRILLMASTER#Drillmaster# //246,9,0,0,0,0,0,10,0,no,0,0,0,none,0 //AM_HEALHOMUN#Heal Homunculus# 247,9,6,4,0,1,0,5,0,no,0,0,0,none,0 //AM_RESURRECTHOMUN#Ressurect Homunculus# @@ -587,6 +587,24 @@ 1018,9,6,1,3,1,0,1,1,yes,0,1,0,magic,0 //SA_ELEMENTFIRE#Elemental Change Fire# 1019,9,6,1,4,1,0,1,1,yes,0,1,0,magic,0 //SA_ELEMENTWIND#Elemental Change Wind# +//homunculus +8001,9,6,16,0,1,0,5,1,no,0,0,0,magic,0 //HLIF_HEAL#Healing hand# +8002,0,6,4,0,3,-1,5,1,no,0,0,0,none,0 //HLIF_AVOID +8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0 //HLIF_BRAIN +8004,0,6,4,0,1,0,3,0,no,0,0,0,none,0 //HLIF_CHANGE +8005,0,6,4,0,1,0,5,0,no,0,0,0,none,0 //HAMI_CASTLE +8006,0,6,4,0,1,0,5,0,no,0,0,0,none,0 //HAMI_DEFENCE +8007,0,0,0,0,1,0,5,0,no,0,0,0,none,0 //HAMI_SKIN +8008,0,6,4,0,1,0,3,0,no,0,0,0,none,0 //HAMI_BLOODLUST +8009,1,8,1,0,0,0,5,1:2:2:2:3,no,0,0,0,weapon,0 //HFLI_MOON +8010,0,6,4,0,1,0,5,0,no,0,0,0,none,0 //HFLI_FLEET +8011,0,6,4,0,1,0,5,0,yes,0,0,0,misc,0 //HFLI_SPEED +8012,1,6,1,0,0,0,3,0,no,0,0,0,none,0 //HFLI_SBR44 +8013,9,6,1,0,0,0,5,1:2:3:4:5,no,0,0,0,magic,0 //HVAN_CAPRICE +8014,0,6,4,0,1,0,5,0,no,0,0,0,none,0 //HVAN_CHAOTIC +8015,0,0,0,0,1,0,5,0,no,0,0,0,none,0 //HVAN_INSTRUCT +8016,0,6,4,-1,2,2,3,1,no,0,0,0,misc,0 //HVAN_EXPLOSION + //id,range,hit,inf,pl,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count 10000,0,0,0,0,0,0,1,0,no,0,16,0,none,0 //GD_APPROVAL#Approval# 10001,0,0,0,0,0,0,1,0,no,0,16,0,none,0 //GD_KAFRACONTRACT#Kafra Contract# diff --git a/db/skill_require_db.txt b/db/skill_require_db.txt index 1fd3591c1..bee3bd80d 100644 --- a/db/skill_require_db.txt +++ b/db/skill_require_db.txt @@ -172,6 +172,10 @@ 236,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_ARMOR#ƒPƒ~ƒJƒ‹ƒA?ƒ}?ƒ`ƒƒ?ƒW# 237,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_HELM#ƒPƒ~ƒJƒ‹ƒwƒ‹ƒ€ƒ`ƒƒ?ƒW# +243,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CALLHOMUNCULUS +244,0,0,50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_REST +247,0,0,74:68:62:56:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_RESURRECTHOMUN + 249,0,0,12:14:16:18:20:22:24:26:28:30,0,0,0,99,0,0,shield,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //CR_AUTOGUARD#ƒI?ƒgƒK?ƒh# 250,0,0,10,0,0,0,99,0,0,shield,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //CR_SHIELDCHARGE#ƒV?ƒ‹ƒhƒ`ƒƒ?ƒW# 251,0,0,12,0,0,0,99,0,0,shield,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //CR_SHIELDBOOMERANG#ƒV?ƒ‹ƒhƒu?ƒƒ‰ƒ“# @@ -456,17 +460,29 @@ 10013,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_EMERGENCYCALL## //Current SP values for Homunculi devs -//AM_HEALHOMUN 12#14#16#18#20#22#24#26#28#30# -//AM_RESURRECTHOMUN 74#68#62#56#50# //HLIF_HEAL 13#16#19#22#25# +8001,0,0,13:16:19:22:25,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL //HLIF_AVOID 20#25#30#35#40# +8002,0,0,20:25:30:35:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_AVOID +//HLIF_CHANGE 1#1#1# +8004,0,1,0,0,0,99,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_CHANGE //HAMI_CASTLE 10#10#10#10#10# +8005,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_CASTLE //HAMI_DEFENCE 20#25#30#35#40# +8006,0,0,20:25:30:35:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_DEFENCE //HAMI_BLOODLUST 120#120#120# +8008,0,0,120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HAMI_BLOODLUST //HFLI_MOON 4#8#12#16#20# +8009,0,0,4:8:12:16:20,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_MOON //HFLI_FLEET 30#40#50#60#70# +8010,0,0,30:40:50:60:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_FLEET //HFLI_SPEED 30#40#50#60#70# +8011,0,0,30:40:50:60:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_SPEED //HFLI_SBR44 1#1#1# +8012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HFLI_SBR44 //HVAN_CAPRICE 22#24#26#28#30# +8013,0,0,22:24:26:28:30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CAPRICE //HVAN_CHAOTIC 40#40#40#40#40# +8014,0,0,40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_CHAOTIC //HVAN_EXPLOSION 1#1#1# +8016,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HVAN_EXPLOSION diff --git a/sql-files/homunculus.sql b/sql-files/homunculus.sql deleted file mode 100644 index b68c74268..000000000 --- a/sql-files/homunculus.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Table for the Homunculus. --- [blackhole89] - -CREATE TABLE `homunculus` ( - `id` int(11) NOT NULL auto_increment, - `char_id` int(11) unsigned NOT NULL default '0', - `class` mediumint(9) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - `level` smallint(4) NOT NULL default '0', - `exp` int(12) NOT NULL default '0', - `hunger` tinyint(10) NOT NULL default '0', - `hp` int(12) NOT NULL default '1', - `sp` int(12) NOT NULL default '1', - `skill1lv` smallint(4) NOT NULL default '0', - `skill2lv` smallint(4) NOT NULL default '0', - `skill3lv` smallint(4) NOT NULL default '0', - `skill4lv` smallint(4) NOT NULL default '0', - `skillpts` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `char_id` (`char_id`) -) \ No newline at end of file diff --git a/sql-files/main.sql b/sql-files/main.sql index 8272499d9..40410b005 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -1,540 +1,584 @@ --- MySQL dump 9.11 --- Server version 4.0.24 - --- --- Table structure for table `cart_inventory` --- - -DROP TABLE IF EXISTS `cart_inventory`; -CREATE TABLE `cart_inventory` ( - `id` int(11) NOT NULL auto_increment, - `char_id` int(11) NOT NULL default '0', - `nameid` int(11) NOT NULL default '0', - `amount` int(11) NOT NULL default '0', - `equip` mediumint(8) unsigned NOT NULL default '0', - `identify` smallint(6) NOT NULL default '0', - `refine` tinyint(3) unsigned NOT NULL default '0', - `attribute` tinyint(4) NOT NULL default '0', - `card0` int(11) NOT NULL default '0', - `card1` int(11) NOT NULL default '0', - `card2` int(11) NOT NULL default '0', - `card3` int(11) NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `char_id` (`char_id`) -) TYPE=MyISAM; - --- --- Table structure for table `char` --- - -DROP TABLE IF EXISTS `char`; -CREATE TABLE `char` ( - `char_id` int(11) unsigned NOT NULL auto_increment, - `account_id` int(11) unsigned NOT NULL default '0', - `char_num` tinyint(1) NOT NULL default '0', - `name` varchar(30) NOT NULL default '', - `class` smallint(6) unsigned NOT NULL default '0', - `base_level` smallint(6) unsigned NOT NULL default '1', - `job_level` smallint(6) unsigned NOT NULL default '1', - `base_exp` bigint(20) unsigned NOT NULL default '0', - `job_exp` bigint(20) unsigned NOT NULL default '0', - `zeny` int(11) unsigned NOT NULL default '0', - `str` smallint(4) unsigned NOT NULL default '0', - `agi` smallint(4) unsigned NOT NULL default '0', - `vit` smallint(4) unsigned NOT NULL default '0', - `int` smallint(4) unsigned NOT NULL default '0', - `dex` smallint(4) unsigned NOT NULL default '0', - `luk` smallint(4) unsigned NOT NULL default '0', - `max_hp` mediumint(8) unsigned NOT NULL default '0', - `hp` mediumint(8) unsigned NOT NULL default '0', - `max_sp` mediumint(6) unsigned NOT NULL default '0', - `sp` mediumint(6) unsigned NOT NULL default '0', - `status_point` smallint(4) unsigned NOT NULL default '0', - `skill_point` smallint(4) unsigned NOT NULL default '0', - `option` int(11) NOT NULL default '0', - `karma` tinyint(3) NOT NULL default '0', - `manner` tinyint(3) NOT NULL default '0', - `party_id` int(11) unsigned NOT NULL default '0', - `guild_id` int(11) unsigned NOT NULL default '0', - `pet_id` int(11) unsigned NOT NULL default '0', - `hair` tinyint(4) unsigned NOT NULL default '0', - `hair_color` smallint(5) unsigned NOT NULL default '0', - `clothes_color` smallint(5) unsigned NOT NULL default '0', - `weapon` smallint(6) unsigned NOT NULL default '1', - `shield` smallint(6) unsigned NOT NULL default '0', - `head_top` smallint(6) unsigned NOT NULL default '0', - `head_mid` smallint(6) unsigned NOT NULL default '0', - `head_bottom` smallint(6) unsigned NOT NULL default '0', - `last_map` varchar(20) NOT NULL default 'prontera.gat', - `last_x` smallint(4) unsigned NOT NULL default '53', - `last_y` smallint(4) unsigned NOT NULL default '111', - `save_map` varchar(20) NOT NULL default 'prontera.gat', - `save_x` smallint(4) unsigned NOT NULL default '53', - `save_y` smallint(4) unsigned NOT NULL default '111', - `partner_id` int(11) unsigned NOT NULL default '0', - `online` tinyint(2) NOT NULL default '0', - `father` int(11) unsigned NOT NULL default '0', - `mother` int(11) unsigned NOT NULL default '0', - `child` int(11) unsigned NOT NULL default '0', - `fame` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`char_id`), - KEY `account_id` (`account_id`), - KEY `party_id` (`party_id`), - KEY `guild_id` (`guild_id`) -) TYPE=InnoDB AUTO_INCREMENT=150000; - --- --- Table structure for table `charlog` --- - -DROP TABLE IF EXISTS `charlog`; -CREATE TABLE `charlog` ( - `time` datetime NOT NULL default '0000-00-00 00:00:00', - `char_msg` varchar(255) NOT NULL default 'char select', - `account_id` int(11) NOT NULL default '0', - `char_num` tinyint(4) NOT NULL default '0', - `name` varchar(255) NOT NULL default '', - `str` int(11) unsigned NOT NULL default '0', - `agi` int(11) unsigned NOT NULL default '0', - `vit` int(11) unsigned NOT NULL default '0', - `int` int(11) unsigned NOT NULL default '0', - `dex` int(11) unsigned NOT NULL default '0', - `luk` int(11) unsigned NOT NULL default '0', - `hair` tinyint(4) NOT NULL default '0', - `hair_color` int(11) NOT NULL default '0' -) TYPE=MyISAM; - --- --- Table structure for table `friends` --- - -DROP TABLE IF EXISTS `friends`; -CREATE TABLE `friends` ( - `char_id` int(11) NOT NULL default '0', - `friend_account` int(11) NOT NULL default '0', - `friend_id` int(11) NOT NULL default '0' -) TYPE=MyISAM; - --- --- Table structure for table `global_reg_value` --- - -DROP TABLE IF EXISTS `global_reg_value`; -CREATE TABLE `global_reg_value` ( - `char_id` int(11) unsigned NOT NULL default '0', - `str` varchar(255) NOT NULL default '', - `value` varchar(255) NOT NULL default '0', - `type` int(11) NOT NULL default '3', - `account_id` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`char_id`,`str`,`account_id`), - KEY `account_id` (`account_id`), - KEY `char_id` (`char_id`) -) TYPE=MyISAM; - --- --- Table structure for table `guild` --- - -DROP TABLE IF EXISTS `guild`; -CREATE TABLE `guild` ( - `guild_id` int(11) unsigned NOT NULL auto_increment, - `name` varchar(24) NOT NULL default '', - `char_id` int(11) unsigned NOT NULL default '0', - `master` varchar(24) NOT NULL default '', - `guild_lv` tinyint(6) unsigned NOT NULL default '0', - `connect_member` tinyint(6) unsigned NOT NULL default '0', - `max_member` tinyint(6) unsigned NOT NULL default '0', - `average_lv` smallint(6) unsigned NOT NULL default '1', - `exp` int(11) unsigned NOT NULL default '0', - `next_exp` int(11) unsigned NOT NULL default '0', - `skill_point` tinyint(11) unsigned NOT NULL default '0', - `mes1` varchar(60) NOT NULL default '', - `mes2` varchar(120) NOT NULL default '', - `emblem_len` int(11) unsigned NOT NULL default '0', - `emblem_id` int(11) unsigned NOT NULL default '0', - `emblem_data` blob NOT NULL, - PRIMARY KEY (`guild_id`,`char_id`), - UNIQUE KEY `guild_id` (`guild_id`), - KEY `char_id` (`char_id`), - CONSTRAINT `guild_ibfk_1` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_alliance` --- - -DROP TABLE IF EXISTS `guild_alliance`; -CREATE TABLE `guild_alliance` ( - `guild_id` int(11) unsigned NOT NULL default '0', - `opposition` int(11) unsigned NOT NULL default '0', - `alliance_id` int(11) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - PRIMARY KEY (`guild_id`,`alliance_id`), - KEY `alliance_id` (`alliance_id`), - CONSTRAINT `guild_alliance_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE, - CONSTRAINT `guild_alliance_ibfk_2` FOREIGN KEY (`alliance_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_castle` --- - -DROP TABLE IF EXISTS `guild_castle`; -CREATE TABLE `guild_castle` ( - `castle_id` int(11) unsigned NOT NULL default '0', - `guild_id` int(11) unsigned NOT NULL default '0', - `economy` int(11) unsigned NOT NULL default '0', - `defense` int(11) unsigned NOT NULL default '0', - `triggerE` int(11) unsigned NOT NULL default '0', - `triggerD` int(11) unsigned NOT NULL default '0', - `nextTime` int(11) unsigned NOT NULL default '0', - `payTime` int(11) unsigned NOT NULL default '0', - `createTime` int(11) unsigned NOT NULL default '0', - `visibleC` int(11) unsigned NOT NULL default '0', - `visibleG0` int(11) unsigned NOT NULL default '0', - `visibleG1` int(11) unsigned NOT NULL default '0', - `visibleG2` int(11) unsigned NOT NULL default '0', - `visibleG3` int(11) unsigned NOT NULL default '0', - `visibleG4` int(11) unsigned NOT NULL default '0', - `visibleG5` int(11) unsigned NOT NULL default '0', - `visibleG6` int(11) unsigned NOT NULL default '0', - `visibleG7` int(11) unsigned NOT NULL default '0', - `gHP0` int(11) unsigned NOT NULL default '0', - `ghP1` int(11) unsigned NOT NULL default '0', - `gHP2` int(11) unsigned NOT NULL default '0', - `gHP3` int(11) unsigned NOT NULL default '0', - `gHP4` int(11) unsigned NOT NULL default '0', - `gHP5` int(11) unsigned NOT NULL default '0', - `gHP6` int(11) unsigned NOT NULL default '0', - `gHP7` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`castle_id`), - KEY `guild_id` (`guild_id`) -) TYPE=MyISAM; - --- --- Table structure for table `guild_expulsion` --- - -DROP TABLE IF EXISTS `guild_expulsion`; -CREATE TABLE `guild_expulsion` ( - `guild_id` int(11) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - `mes` varchar(40) NOT NULL default '', - `acc` varchar(40) NOT NULL default '', - `account_id` int(11) unsigned NOT NULL default '0', - `rsv1` int(11) unsigned NOT NULL default '0', - `rsv2` int(11) unsigned NOT NULL default '0', - `rsv3` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`guild_id`,`name`), - CONSTRAINT `guild_expulsion_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_member` --- - -DROP TABLE IF EXISTS `guild_member`; -CREATE TABLE `guild_member` ( - `guild_id` int(11) unsigned NOT NULL default '0', - `account_id` int(11) unsigned NOT NULL default '0', - `char_id` int(11) unsigned NOT NULL default '0', - `hair` tinyint(6) unsigned NOT NULL default '0', - `hair_color` smallint(6) unsigned NOT NULL default '0', - `gender` tinyint(6) unsigned NOT NULL default '0', - `class` smallint(6) unsigned NOT NULL default '0', - `lv` smallint(6) unsigned NOT NULL default '0', - `exp` bigint(20) unsigned NOT NULL default '0', - `exp_payper` tinyint(11) unsigned NOT NULL default '0', - `online` tinyint(4) unsigned NOT NULL default '0', - `position` tinyint(6) unsigned NOT NULL default '0', - `rsv1` int(11) unsigned NOT NULL default '0', - `rsv2` int(11) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - PRIMARY KEY (`guild_id`,`char_id`), - KEY `char_id` (`char_id`), - CONSTRAINT `guild_member_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE, - CONSTRAINT `guild_member_ibfk_2` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_position` --- - -DROP TABLE IF EXISTS `guild_position`; -CREATE TABLE `guild_position` ( - `guild_id` int(9) unsigned NOT NULL default '0', - `position` tinyint(6) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - `mode` tinyint(11) unsigned NOT NULL default '0', - `exp_mode` tinyint(11) unsigned NOT NULL default '0', - PRIMARY KEY (`guild_id`,`position`), - KEY `guild_id` (`guild_id`), - CONSTRAINT `guild_position_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_skill` --- - -DROP TABLE IF EXISTS `guild_skill`; -CREATE TABLE `guild_skill` ( - `guild_id` int(11) unsigned NOT NULL default '0', - `id` smallint(11) unsigned NOT NULL default '0', - `lv` tinyint(11) unsigned NOT NULL default '0', - PRIMARY KEY (`guild_id`,`id`), - CONSTRAINT `guild_skill_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `guild_storage` --- - -DROP TABLE IF EXISTS `guild_storage`; -CREATE TABLE `guild_storage` ( - `id` int(10) unsigned NOT NULL auto_increment, - `guild_id` int(11) unsigned NOT NULL default '0', - `nameid` int(11) unsigned NOT NULL default '0', - `amount` int(11) unsigned NOT NULL default '0', - `equip` mediumint(8) unsigned NOT NULL default '0', - `identify` smallint(6) unsigned NOT NULL default '0', - `refine` tinyint(3) unsigned NOT NULL default '0', - `attribute` tinyint(4) unsigned NOT NULL default '0', - `card0` smallint(11) NOT NULL default '0', - `card1` smallint(11) NOT NULL default '0', - `card2` smallint(11) NOT NULL default '0', - `card3` smallint(11) NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `guild_id` (`guild_id`), - CONSTRAINT `guild_storage_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- Database: Ragnarok --- Table: 'interlog' --- - -DROP TABLE IF EXISTS `interlog`; -CREATE TABLE `interlog` ( - `time` datetime NOT NULL default '0000-00-00 00:00:00', - `log` varchar(255) NOT NULL default '' -) TYPE=MyISAM; - --- --- Table structure for table `inventory` --- - -DROP TABLE IF EXISTS `inventory`; -CREATE TABLE `inventory` ( - `id` int(11) unsigned NOT NULL auto_increment, - `char_id` int(11) unsigned NOT NULL default '0', - `nameid` int(11) unsigned NOT NULL default '0', - `amount` int(11) unsigned NOT NULL default '0', - `equip` mediumint(8) unsigned NOT NULL default '0', - `identify` smallint(6) NOT NULL default '0', - `refine` tinyint(3) unsigned NOT NULL default '0', - `attribute` tinyint(4) unsigned NOT NULL default '0', - `card0` smallint(11) NOT NULL default '0', - `card1` smallint(11) NOT NULL default '0', - `card2` smallint(11) NOT NULL default '0', - `card3` smallint(11) NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `char_id` (`char_id`) -) TYPE=MyISAM; - --- --- Table structure for table `ipbanlist` --- - -DROP TABLE IF EXISTS `ipbanlist`; -CREATE TABLE `ipbanlist` ( - `list` varchar(255) NOT NULL default '', - `btime` datetime NOT NULL default '0000-00-00 00:00:00', - `rtime` datetime NOT NULL default '0000-00-00 00:00:00', - `reason` varchar(255) NOT NULL default '', - KEY (`list`) -) TYPE=MyISAM; - --- --- Table structure for table `login` --- - -DROP TABLE IF EXISTS `login`; -CREATE TABLE `login` ( - `account_id` int(11) unsigned NOT NULL auto_increment, - `userid` varchar(255) NOT NULL default '', - `user_pass` varchar(32) NOT NULL default '', - `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00', - `sex` char(1) NOT NULL default 'M', - `logincount` mediumint(9) unsigned NOT NULL default '0', - `email` varchar(60) NOT NULL default '', - `level` tinyint(3) NOT NULL default '0', - `error_message` smallint(11) unsigned NOT NULL default '0', - `connect_until` smallint(11) unsigned NOT NULL default '0', - `last_ip` varchar(100) NOT NULL default '', - `memo` smallint(11) unsigned NOT NULL default '0', - `ban_until` int(11) unsigned NOT NULL default '0', - `state` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`account_id`), - KEY `name` (`userid`) -) TYPE=InnoDB AUTO_INCREMENT=2000000; - --- added standard accounts for servers, VERY INSECURE!!! --- inserted into the table called login which is above - -INSERT INTO `login` (`account_id`, `userid`, `user_pass`, `sex`, `email`) VALUES ('1', 's1', 'p1', 'S','athena@athena.com'); - --- --- Table structure for table `sc_data` --- - -DROP TABLE IF EXISTS `sc_data`; -CREATE TABLE `sc_data` ( - `account_id` int(11) unsigned NOT NULL, - `char_id` int(11) unsigned NOT NULL, - `type` smallint(11) unsigned NOT NULL, - `tick` int(11) NOT NULL, - `val1` int(11) NOT NULL default '0', - `val2` int(11) NOT NULL default '0', - `val3` int(11) NOT NULL default '0', - `val4` int(11) NOT NULL default '0', - KEY (`account_id`), - KEY (`char_id`), - CONSTRAINT `scdata_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `login` (`account_id`) ON DELETE CASCADE, - CONSTRAINT `scdata_ibfk_2` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE -) TYPE=InnoDB; - --- --- Table structure for table `loginlog` --- - -DROP TABLE IF EXISTS `loginlog`; -CREATE TABLE `loginlog` ( - `time` datetime NOT NULL default '0000-00-00 00:00:00', - `ip` int(10) unsigned NOT NULL default '0', - `user` varchar(32) NOT NULL default '', - `rcode` tinyint(4) NOT NULL default '0', - `log` varchar(255) NOT NULL default '', - INDEX (`ip`) -) TYPE=MyISAM; - --- --- Table structure for table `memo` --- - -DROP TABLE IF EXISTS `memo`; -CREATE TABLE `memo` ( - `memo_id` int(11) unsigned NOT NULL auto_increment, - `char_id` int(11) unsigned NOT NULL default '0', - `map` varchar(255) NOT NULL default '', - `x` smallint(9) unsigned NOT NULL default '0', - `y` smallint(9) unsigned NOT NULL default '0', - PRIMARY KEY (`memo_id`) -) TYPE=MyISAM; - --- --- Table structure for table `party` --- - -DROP TABLE IF EXISTS `party`; -CREATE TABLE `party` ( - `party_id` int(11) unsigned NOT NULL auto_increment, - `name` char(100) NOT NULL default '', - `exp` tinyint(11) unsigned NOT NULL default '0', - `item` tinyint(11) unsigned NOT NULL default '0', - `leader_id` int(11) unsigned NOT NULL default '0', - `leader_char` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`party_id`) -) TYPE=MyISAM; - --- --- Table structure for table `pet` --- - -DROP TABLE IF EXISTS `pet`; -CREATE TABLE `pet` ( - `pet_id` int(11) unsigned NOT NULL auto_increment, - `class` mediumint(9) unsigned NOT NULL default '0', - `name` varchar(24) NOT NULL default '', - `account_id` int(11) unsigned NOT NULL default '0', - `char_id` int(11) unsigned NOT NULL default '0', - `level` smallint(4) unsigned NOT NULL default '0', - `egg_id` smallint(11) unsigned NOT NULL default '0', - `equip` mediumint(8) unsigned NOT NULL default '0', - `intimate` smallint(9) unsigned NOT NULL default '0', - `hungry` smallint(9) unsigned NOT NULL default '0', - `rename_flag` tinyint(4) unsigned NOT NULL default '0', - `incuvate` int(11) unsigned NOT NULL default '0', - PRIMARY KEY (`pet_id`) -) TYPE=MyISAM; - --- --- Table structure for table `ragsrvinfo` --- - -DROP TABLE IF EXISTS `ragsrvinfo`; -CREATE TABLE `ragsrvinfo` ( - `index` int(11) NOT NULL default '0', - `name` varchar(255) NOT NULL default '', - `exp` int(11) unsigned NOT NULL default '0', - `jexp` int(11) unsigned NOT NULL default '0', - `drop` int(11) unsigned NOT NULL default '0', - `motd` varchar(255) NOT NULL default '' -) TYPE=MyISAM; - --- --- Table structure for table `skill` --- - -DROP TABLE IF EXISTS `skill`; -CREATE TABLE `skill` ( - `char_id` int(11) unsigned NOT NULL default '0', - `id` smallint(11) unsigned NOT NULL default '0', - `lv` tinyint(4) unsigned NOT NULL default '0', - PRIMARY KEY (`char_id`,`id`), - KEY `char_id` (`char_id`) -) TYPE=MyISAM; - --- --- Table structure for table `sstatus` --- - -DROP TABLE IF EXISTS `sstatus`; -CREATE TABLE `sstatus` ( - `index` tinyint(4) unsigned NOT NULL default '0', - `name` varchar(255) NOT NULL default '', - `user` int(11) unsigned NOT NULL default '0' -) TYPE=MyISAM; - --- --- Table structure for table `storage` --- - -DROP TABLE IF EXISTS `storage`; -CREATE TABLE `storage` ( - `id` int(11) unsigned NOT NULL auto_increment, - `account_id` int(11) unsigned NOT NULL default '0', - `nameid` int(11) unsigned NOT NULL default '0', - `amount` smallint(11) unsigned NOT NULL default '0', - `equip` mediumint(8) unsigned NOT NULL default '0', - `identify` smallint(6) unsigned NOT NULL default '0', - `refine` tinyint(3) unsigned NOT NULL default '0', - `attribute` tinyint(4) unsigned NOT NULL default '0', - `card0` smallint(11) NOT NULL default '0', - `card1` smallint(11) NOT NULL default '0', - `card2` smallint(11) NOT NULL default '0', - `card3` smallint(11) NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `account_id` (`account_id`) -) TYPE=MyISAM; - --- --- Table structure for table `mapreg` --- - -DROP TABLE IF EXISTS `mapreg`; -CREATE TABLE `mapreg` ( - `varname` varchar(32) NOT NULL, - `index` int(11) unsigned NOT NULL default '0', - `value` varchar(255) NOT NULL, - KEY `varname` (`varname`), - KEY `index` (`index`) -) TYPE=MyISAM; +-- MySQL dump 9.11 +-- Server version 4.0.24 + +-- +-- Table structure for table `cart_inventory` +-- + +DROP TABLE IF EXISTS `cart_inventory`; +CREATE TABLE `cart_inventory` ( + `id` int(11) NOT NULL auto_increment, + `char_id` int(11) NOT NULL default '0', + `nameid` int(11) NOT NULL default '0', + `amount` int(11) NOT NULL default '0', + `equip` mediumint(8) unsigned NOT NULL default '0', + `identify` smallint(6) NOT NULL default '0', + `refine` tinyint(3) unsigned NOT NULL default '0', + `attribute` tinyint(4) NOT NULL default '0', + `card0` int(11) NOT NULL default '0', + `card1` int(11) NOT NULL default '0', + `card2` int(11) NOT NULL default '0', + `card3` int(11) NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `char_id` (`char_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `char` +-- + +DROP TABLE IF EXISTS `char`; +CREATE TABLE `char` ( + `char_id` int(11) unsigned NOT NULL auto_increment, + `account_id` int(11) unsigned NOT NULL default '0', + `char_num` tinyint(1) NOT NULL default '0', + `name` varchar(30) NOT NULL default '', + `class` smallint(6) unsigned NOT NULL default '0', + `base_level` smallint(6) unsigned NOT NULL default '1', + `job_level` smallint(6) unsigned NOT NULL default '1', + `base_exp` bigint(20) unsigned NOT NULL default '0', + `job_exp` bigint(20) unsigned NOT NULL default '0', + `zeny` int(11) unsigned NOT NULL default '0', + `str` smallint(4) unsigned NOT NULL default '0', + `agi` smallint(4) unsigned NOT NULL default '0', + `vit` smallint(4) unsigned NOT NULL default '0', + `int` smallint(4) unsigned NOT NULL default '0', + `dex` smallint(4) unsigned NOT NULL default '0', + `luk` smallint(4) unsigned NOT NULL default '0', + `max_hp` mediumint(8) unsigned NOT NULL default '0', + `hp` mediumint(8) unsigned NOT NULL default '0', + `max_sp` mediumint(6) unsigned NOT NULL default '0', + `sp` mediumint(6) unsigned NOT NULL default '0', + `status_point` smallint(4) unsigned NOT NULL default '0', + `skill_point` smallint(4) unsigned NOT NULL default '0', + `option` int(11) NOT NULL default '0', + `karma` tinyint(3) NOT NULL default '0', + `manner` tinyint(3) NOT NULL default '0', + `party_id` int(11) unsigned NOT NULL default '0', + `guild_id` int(11) unsigned NOT NULL default '0', + `pet_id` int(11) unsigned NOT NULL default '0', + `homun_id` int(11) unsigned NOT NULL default '0', + `hair` tinyint(4) unsigned NOT NULL default '0', + `hair_color` smallint(5) unsigned NOT NULL default '0', + `clothes_color` smallint(5) unsigned NOT NULL default '0', + `weapon` smallint(6) unsigned NOT NULL default '1', + `shield` smallint(6) unsigned NOT NULL default '0', + `head_top` smallint(6) unsigned NOT NULL default '0', + `head_mid` smallint(6) unsigned NOT NULL default '0', + `head_bottom` smallint(6) unsigned NOT NULL default '0', + `last_map` varchar(20) NOT NULL default 'prontera.gat', + `last_x` smallint(4) unsigned NOT NULL default '53', + `last_y` smallint(4) unsigned NOT NULL default '111', + `save_map` varchar(20) NOT NULL default 'prontera.gat', + `save_x` smallint(4) unsigned NOT NULL default '53', + `save_y` smallint(4) unsigned NOT NULL default '111', + `partner_id` int(11) unsigned NOT NULL default '0', + `online` tinyint(2) NOT NULL default '0', + `father` int(11) unsigned NOT NULL default '0', + `mother` int(11) unsigned NOT NULL default '0', + `child` int(11) unsigned NOT NULL default '0', + `fame` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`char_id`), + KEY `account_id` (`account_id`), + KEY `party_id` (`party_id`), + KEY `guild_id` (`guild_id`) +) TYPE=InnoDB AUTO_INCREMENT=150000; + +-- +-- Table structure for table `charlog` +-- + +DROP TABLE IF EXISTS `charlog`; +CREATE TABLE `charlog` ( + `time` datetime NOT NULL default '0000-00-00 00:00:00', + `char_msg` varchar(255) NOT NULL default 'char select', + `account_id` int(11) NOT NULL default '0', + `char_num` tinyint(4) NOT NULL default '0', + `name` varchar(255) NOT NULL default '', + `str` int(11) unsigned NOT NULL default '0', + `agi` int(11) unsigned NOT NULL default '0', + `vit` int(11) unsigned NOT NULL default '0', + `int` int(11) unsigned NOT NULL default '0', + `dex` int(11) unsigned NOT NULL default '0', + `luk` int(11) unsigned NOT NULL default '0', + `hair` tinyint(4) NOT NULL default '0', + `hair_color` int(11) NOT NULL default '0' +) TYPE=MyISAM; + +-- +-- Table structure for table `friends` +-- + +DROP TABLE IF EXISTS `friends`; +CREATE TABLE `friends` ( + `char_id` int(11) NOT NULL default '0', + `friend_account` int(11) NOT NULL default '0', + `friend_id` int(11) NOT NULL default '0' +) TYPE=MyISAM; + +-- +-- Table structure for table `global_reg_value` +-- + +DROP TABLE IF EXISTS `global_reg_value`; +CREATE TABLE `global_reg_value` ( + `char_id` int(11) unsigned NOT NULL default '0', + `str` varchar(255) NOT NULL default '', + `value` varchar(255) NOT NULL default '0', + `type` int(11) NOT NULL default '3', + `account_id` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`char_id`,`str`,`account_id`), + KEY `account_id` (`account_id`), + KEY `char_id` (`char_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `guild` +-- + +DROP TABLE IF EXISTS `guild`; +CREATE TABLE `guild` ( + `guild_id` int(11) unsigned NOT NULL auto_increment, + `name` varchar(24) NOT NULL default '', + `char_id` int(11) unsigned NOT NULL default '0', + `master` varchar(24) NOT NULL default '', + `guild_lv` tinyint(6) unsigned NOT NULL default '0', + `connect_member` tinyint(6) unsigned NOT NULL default '0', + `max_member` tinyint(6) unsigned NOT NULL default '0', + `average_lv` smallint(6) unsigned NOT NULL default '1', + `exp` int(11) unsigned NOT NULL default '0', + `next_exp` int(11) unsigned NOT NULL default '0', + `skill_point` tinyint(11) unsigned NOT NULL default '0', + `mes1` varchar(60) NOT NULL default '', + `mes2` varchar(120) NOT NULL default '', + `emblem_len` int(11) unsigned NOT NULL default '0', + `emblem_id` int(11) unsigned NOT NULL default '0', + `emblem_data` blob NOT NULL, + PRIMARY KEY (`guild_id`,`char_id`), + UNIQUE KEY `guild_id` (`guild_id`), + KEY `char_id` (`char_id`), + CONSTRAINT `guild_ibfk_1` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_alliance` +-- + +DROP TABLE IF EXISTS `guild_alliance`; +CREATE TABLE `guild_alliance` ( + `guild_id` int(11) unsigned NOT NULL default '0', + `opposition` int(11) unsigned NOT NULL default '0', + `alliance_id` int(11) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + PRIMARY KEY (`guild_id`,`alliance_id`), + KEY `alliance_id` (`alliance_id`), + CONSTRAINT `guild_alliance_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE, + CONSTRAINT `guild_alliance_ibfk_2` FOREIGN KEY (`alliance_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_castle` +-- + +DROP TABLE IF EXISTS `guild_castle`; +CREATE TABLE `guild_castle` ( + `castle_id` int(11) unsigned NOT NULL default '0', + `guild_id` int(11) unsigned NOT NULL default '0', + `economy` int(11) unsigned NOT NULL default '0', + `defense` int(11) unsigned NOT NULL default '0', + `triggerE` int(11) unsigned NOT NULL default '0', + `triggerD` int(11) unsigned NOT NULL default '0', + `nextTime` int(11) unsigned NOT NULL default '0', + `payTime` int(11) unsigned NOT NULL default '0', + `createTime` int(11) unsigned NOT NULL default '0', + `visibleC` int(11) unsigned NOT NULL default '0', + `visibleG0` int(11) unsigned NOT NULL default '0', + `visibleG1` int(11) unsigned NOT NULL default '0', + `visibleG2` int(11) unsigned NOT NULL default '0', + `visibleG3` int(11) unsigned NOT NULL default '0', + `visibleG4` int(11) unsigned NOT NULL default '0', + `visibleG5` int(11) unsigned NOT NULL default '0', + `visibleG6` int(11) unsigned NOT NULL default '0', + `visibleG7` int(11) unsigned NOT NULL default '0', + `gHP0` int(11) unsigned NOT NULL default '0', + `ghP1` int(11) unsigned NOT NULL default '0', + `gHP2` int(11) unsigned NOT NULL default '0', + `gHP3` int(11) unsigned NOT NULL default '0', + `gHP4` int(11) unsigned NOT NULL default '0', + `gHP5` int(11) unsigned NOT NULL default '0', + `gHP6` int(11) unsigned NOT NULL default '0', + `gHP7` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`castle_id`), + KEY `guild_id` (`guild_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `guild_expulsion` +-- + +DROP TABLE IF EXISTS `guild_expulsion`; +CREATE TABLE `guild_expulsion` ( + `guild_id` int(11) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + `mes` varchar(40) NOT NULL default '', + `acc` varchar(40) NOT NULL default '', + `account_id` int(11) unsigned NOT NULL default '0', + `rsv1` int(11) unsigned NOT NULL default '0', + `rsv2` int(11) unsigned NOT NULL default '0', + `rsv3` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guild_id`,`name`), + CONSTRAINT `guild_expulsion_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_member` +-- + +DROP TABLE IF EXISTS `guild_member`; +CREATE TABLE `guild_member` ( + `guild_id` int(11) unsigned NOT NULL default '0', + `account_id` int(11) unsigned NOT NULL default '0', + `char_id` int(11) unsigned NOT NULL default '0', + `hair` tinyint(6) unsigned NOT NULL default '0', + `hair_color` smallint(6) unsigned NOT NULL default '0', + `gender` tinyint(6) unsigned NOT NULL default '0', + `class` smallint(6) unsigned NOT NULL default '0', + `lv` smallint(6) unsigned NOT NULL default '0', + `exp` bigint(20) unsigned NOT NULL default '0', + `exp_payper` tinyint(11) unsigned NOT NULL default '0', + `online` tinyint(4) unsigned NOT NULL default '0', + `position` tinyint(6) unsigned NOT NULL default '0', + `rsv1` int(11) unsigned NOT NULL default '0', + `rsv2` int(11) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + PRIMARY KEY (`guild_id`,`char_id`), + KEY `char_id` (`char_id`), + CONSTRAINT `guild_member_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE, + CONSTRAINT `guild_member_ibfk_2` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_position` +-- + +DROP TABLE IF EXISTS `guild_position`; +CREATE TABLE `guild_position` ( + `guild_id` int(9) unsigned NOT NULL default '0', + `position` tinyint(6) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + `mode` tinyint(11) unsigned NOT NULL default '0', + `exp_mode` tinyint(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guild_id`,`position`), + KEY `guild_id` (`guild_id`), + CONSTRAINT `guild_position_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_skill` +-- + +DROP TABLE IF EXISTS `guild_skill`; +CREATE TABLE `guild_skill` ( + `guild_id` int(11) unsigned NOT NULL default '0', + `id` smallint(11) unsigned NOT NULL default '0', + `lv` tinyint(11) unsigned NOT NULL default '0', + PRIMARY KEY (`guild_id`,`id`), + CONSTRAINT `guild_skill_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `guild_storage` +-- + +DROP TABLE IF EXISTS `guild_storage`; +CREATE TABLE `guild_storage` ( + `id` int(10) unsigned NOT NULL auto_increment, + `guild_id` int(11) unsigned NOT NULL default '0', + `nameid` int(11) unsigned NOT NULL default '0', + `amount` int(11) unsigned NOT NULL default '0', + `equip` mediumint(8) unsigned NOT NULL default '0', + `identify` smallint(6) unsigned NOT NULL default '0', + `refine` tinyint(3) unsigned NOT NULL default '0', + `attribute` tinyint(4) unsigned NOT NULL default '0', + `card0` smallint(11) NOT NULL default '0', + `card1` smallint(11) NOT NULL default '0', + `card2` smallint(11) NOT NULL default '0', + `card3` smallint(11) NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `guild_id` (`guild_id`), + CONSTRAINT `guild_storage_ibfk_1` FOREIGN KEY (`guild_id`) REFERENCES `guild` (`guild_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `homunculus` +-- + +DROP TABLE IF EXISTS `homunculus`; +CREATE TABLE `homunculus` ( + `homun_id` int(11) NOT NULL auto_increment, + `char_id` int(11) NOT NULL, + `class` mediumint(9) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + `level` smallint(4) NOT NULL default '0', + `exp` int(12) NOT NULL default '0', + `intimacy` int(12) NOT NULL default '0', + `hunger` smallint(4) NOT NULL default '0', + `str` smallint(4) unsigned NOT NULL default '0', + `agi` smallint(4) unsigned NOT NULL default '0', + `vit` smallint(4) unsigned NOT NULL default '0', + `int` smallint(4) unsigned NOT NULL default '0', + `dex` smallint(4) unsigned NOT NULL default '0', + `luk` smallint(4) unsigned NOT NULL default '0', + `hp` int(12) NOT NULL default '1', + `max_hp` int(12) NOT NULL default '1', + `sp` int(12) NOT NULL default '1', + `max_sp` int(12) NOT NULL default '1', + `skill_point` smallint(4) unsigned NOT NULL default '0', + `alive` tinyint(2) NOT NULL default '1', + `rename_flag` tinyint(2) NOT NULL default '0', + `vaporize` tinyint(2) NOT NULL default '0', + PRIMARY KEY (`homun_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Table structure for table `interlog` +-- + +DROP TABLE IF EXISTS `interlog`; +CREATE TABLE `interlog` ( + `time` datetime NOT NULL default '0000-00-00 00:00:00', + `log` varchar(255) NOT NULL default '' +) TYPE=MyISAM; + +-- +-- Table structure for table `inventory` +-- + +DROP TABLE IF EXISTS `inventory`; +CREATE TABLE `inventory` ( + `id` int(11) unsigned NOT NULL auto_increment, + `char_id` int(11) unsigned NOT NULL default '0', + `nameid` int(11) unsigned NOT NULL default '0', + `amount` int(11) unsigned NOT NULL default '0', + `equip` mediumint(8) unsigned NOT NULL default '0', + `identify` smallint(6) NOT NULL default '0', + `refine` tinyint(3) unsigned NOT NULL default '0', + `attribute` tinyint(4) unsigned NOT NULL default '0', + `card0` smallint(11) NOT NULL default '0', + `card1` smallint(11) NOT NULL default '0', + `card2` smallint(11) NOT NULL default '0', + `card3` smallint(11) NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `char_id` (`char_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `ipbanlist` +-- + +DROP TABLE IF EXISTS `ipbanlist`; +CREATE TABLE `ipbanlist` ( + `list` varchar(255) NOT NULL default '', + `btime` datetime NOT NULL default '0000-00-00 00:00:00', + `rtime` datetime NOT NULL default '0000-00-00 00:00:00', + `reason` varchar(255) NOT NULL default '', + KEY (`list`) +) TYPE=MyISAM; + +-- +-- Table structure for table `login` +-- + +DROP TABLE IF EXISTS `login`; +CREATE TABLE `login` ( + `account_id` int(11) unsigned NOT NULL auto_increment, + `userid` varchar(255) NOT NULL default '', + `user_pass` varchar(32) NOT NULL default '', + `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00', + `sex` char(1) NOT NULL default 'M', + `logincount` mediumint(9) unsigned NOT NULL default '0', + `email` varchar(60) NOT NULL default '', + `level` tinyint(3) NOT NULL default '0', + `error_message` smallint(11) unsigned NOT NULL default '0', + `connect_until` smallint(11) unsigned NOT NULL default '0', + `last_ip` varchar(100) NOT NULL default '', + `memo` smallint(11) unsigned NOT NULL default '0', + `ban_until` int(11) unsigned NOT NULL default '0', + `state` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`account_id`), + KEY `name` (`userid`) +) TYPE=InnoDB AUTO_INCREMENT=2000000; + +-- added standard accounts for servers, VERY INSECURE!!! +-- inserted into the table called login which is above + +INSERT INTO `login` (`account_id`, `userid`, `user_pass`, `sex`, `email`) VALUES ('1', 's1', 'p1', 'S','athena@athena.com'); + +-- +-- Table structure for table `mapreg` +-- + +DROP TABLE IF EXISTS `mapreg`; +CREATE TABLE `mapreg` ( + `varname` varchar(32) NOT NULL, + `index` int(11) unsigned NOT NULL default '0', + `value` varchar(255) NOT NULL, + KEY `varname` (`varname`), + KEY `index` (`index`) +) TYPE=MyISAM; + +-- +-- Table structure for table `sc_data` +-- + +DROP TABLE IF EXISTS `sc_data`; +CREATE TABLE `sc_data` ( + `account_id` int(11) unsigned NOT NULL, + `char_id` int(11) unsigned NOT NULL, + `type` smallint(11) unsigned NOT NULL, + `tick` int(11) NOT NULL, + `val1` int(11) NOT NULL default '0', + `val2` int(11) NOT NULL default '0', + `val3` int(11) NOT NULL default '0', + `val4` int(11) NOT NULL default '0', + KEY (`account_id`), + KEY (`char_id`), + CONSTRAINT `scdata_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `login` (`account_id`) ON DELETE CASCADE, + CONSTRAINT `scdata_ibfk_2` FOREIGN KEY (`char_id`) REFERENCES `char` (`char_id`) ON DELETE CASCADE +) TYPE=InnoDB; + +-- +-- Table structure for table `loginlog` +-- + +DROP TABLE IF EXISTS `loginlog`; +CREATE TABLE `loginlog` ( + `time` datetime NOT NULL default '0000-00-00 00:00:00', + `ip` int(10) unsigned NOT NULL default '0', + `user` varchar(32) NOT NULL default '', + `rcode` tinyint(4) NOT NULL default '0', + `log` varchar(255) NOT NULL default '', + INDEX (`ip`) +) TYPE=MyISAM; + +-- +-- Table structure for table `memo` +-- + +DROP TABLE IF EXISTS `memo`; +CREATE TABLE `memo` ( + `memo_id` int(11) unsigned NOT NULL auto_increment, + `char_id` int(11) unsigned NOT NULL default '0', + `map` varchar(255) NOT NULL default '', + `x` smallint(9) unsigned NOT NULL default '0', + `y` smallint(9) unsigned NOT NULL default '0', + PRIMARY KEY (`memo_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `party` +-- + +DROP TABLE IF EXISTS `party`; +CREATE TABLE `party` ( + `party_id` int(11) unsigned NOT NULL auto_increment, + `name` char(100) NOT NULL default '', + `exp` tinyint(11) unsigned NOT NULL default '0', + `item` tinyint(11) unsigned NOT NULL default '0', + `leader_id` int(11) unsigned NOT NULL default '0', + `leader_char` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`party_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `pet` +-- + +DROP TABLE IF EXISTS `pet`; +CREATE TABLE `pet` ( + `pet_id` int(11) unsigned NOT NULL auto_increment, + `class` mediumint(9) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + `account_id` int(11) unsigned NOT NULL default '0', + `char_id` int(11) unsigned NOT NULL default '0', + `level` smallint(4) unsigned NOT NULL default '0', + `egg_id` smallint(11) unsigned NOT NULL default '0', + `equip` mediumint(8) unsigned NOT NULL default '0', + `intimate` smallint(9) unsigned NOT NULL default '0', + `hungry` smallint(9) unsigned NOT NULL default '0', + `rename_flag` tinyint(4) unsigned NOT NULL default '0', + `incuvate` int(11) unsigned NOT NULL default '0', + PRIMARY KEY (`pet_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `ragsrvinfo` +-- + +DROP TABLE IF EXISTS `ragsrvinfo`; +CREATE TABLE `ragsrvinfo` ( + `index` int(11) NOT NULL default '0', + `name` varchar(255) NOT NULL default '', + `exp` int(11) unsigned NOT NULL default '0', + `jexp` int(11) unsigned NOT NULL default '0', + `drop` int(11) unsigned NOT NULL default '0', + `motd` varchar(255) NOT NULL default '' +) TYPE=MyISAM; + +-- +-- Table structure for table `skill` +-- + +DROP TABLE IF EXISTS `skill`; +CREATE TABLE `skill` ( + `char_id` int(11) unsigned NOT NULL default '0', + `id` smallint(11) unsigned NOT NULL default '0', + `lv` tinyint(4) unsigned NOT NULL default '0', + PRIMARY KEY (`char_id`,`id`), + KEY `char_id` (`char_id`) +) TYPE=MyISAM; + +-- +-- Table structure for table `skill_homunculus` +-- + +DROP TABLE IF EXISTS `skill_homunculus`; +CREATE TABLE `skill_homunculus` ( + `homun_id` int(11) NOT NULL, + `id` int(11) NOT NULL, + `lv` smallint(6) NOT NULL, + PRIMARY KEY (`homun_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Table structure for table `sstatus` +-- + +DROP TABLE IF EXISTS `sstatus`; +CREATE TABLE `sstatus` ( + `index` tinyint(4) unsigned NOT NULL default '0', + `name` varchar(255) NOT NULL default '', + `user` int(11) unsigned NOT NULL default '0' +) TYPE=MyISAM; + +-- +-- Table structure for table `storage` +-- + +DROP TABLE IF EXISTS `storage`; +CREATE TABLE `storage` ( + `id` int(11) unsigned NOT NULL auto_increment, + `account_id` int(11) unsigned NOT NULL default '0', + `nameid` int(11) unsigned NOT NULL default '0', + `amount` smallint(11) unsigned NOT NULL default '0', + `equip` mediumint(8) unsigned NOT NULL default '0', + `identify` smallint(6) unsigned NOT NULL default '0', + `refine` tinyint(3) unsigned NOT NULL default '0', + `attribute` tinyint(4) unsigned NOT NULL default '0', + `card0` smallint(11) NOT NULL default '0', + `card1` smallint(11) NOT NULL default '0', + `card2` smallint(11) NOT NULL default '0', + `card3` smallint(11) NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `account_id` (`account_id`) +) TYPE=MyISAM; diff --git a/sql-files/upgrade_svn7706.sql b/sql-files/upgrade_svn7706.sql new file mode 100644 index 000000000..afd91d220 --- /dev/null +++ b/sql-files/upgrade_svn7706.sql @@ -0,0 +1,36 @@ +ALTER TABLE `char` ADD `homun_id` int(11) unsigned NOT NULL default '0' AFTER `pet_id`; + +DROP TABLE IF EXISTS `homunculus`; +CREATE TABLE `homunculus` ( + `homun_id` int(11) NOT NULL auto_increment, + `char_id` int(11) NOT NULL, + `class` mediumint(9) unsigned NOT NULL default '0', + `name` varchar(24) NOT NULL default '', + `level` smallint(4) NOT NULL default '0', + `exp` int(12) NOT NULL default '0', + `intimacy` int(12) NOT NULL default '0', + `hunger` smallint(4) NOT NULL default '0', + `str` smallint(4) unsigned NOT NULL default '0', + `agi` smallint(4) unsigned NOT NULL default '0', + `vit` smallint(4) unsigned NOT NULL default '0', + `int` smallint(4) unsigned NOT NULL default '0', + `dex` smallint(4) unsigned NOT NULL default '0', + `luk` smallint(4) unsigned NOT NULL default '0', + `hp` int(12) NOT NULL default '1', + `max_hp` int(12) NOT NULL default '1', + `sp` int(12) NOT NULL default '1', + `max_sp` int(12) NOT NULL default '1', + `skill_point` smallint(4) unsigned NOT NULL default '0', + `alive` tinyint(2) NOT NULL default '1', + `rename_flag` tinyint(2) NOT NULL default '0', + `vaporize` tinyint(2) NOT NULL default '0', + PRIMARY KEY (`homun_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + +CREATE TABLE `skill_homunculus` ( + `homun_id` int(11) NOT NULL, + `id` int(11) NOT NULL, + `lv` smallint(6) NOT NULL, + PRIMARY KEY (`homun_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; diff --git a/src/char_sql/Makefile b/src/char_sql/Makefile index f67a95315..544ba82c0 100644 --- a/src/char_sql/Makefile +++ b/src/char_sql/Makefile @@ -10,7 +10,7 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \ ../common/graph.h ../common/grfio.h ../common/mapindex.h -char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o itemdb.o $(COMMON_OBJ) +char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o itemdb.o $(COMMON_OBJ) $(CC) -o ../../$@ $^ $(LIB_S) clean: @@ -19,9 +19,10 @@ clean: # DO NOT DELETE char.o: char.c char.h ../common/strlib.h itemdb.h ../common/showmsg.h -inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h +inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h int_party.o: int_party.c int_party.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/timer.h ../common/db.h ../common/showmsg.h int_guild.o: int_guild.c int_guild.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/db.h ../common/showmsg.h int_storage.o: int_storage.c int_storage.h char.h itemdb.h ../common/showmsg.h int_pet.o: int_pet.c int_pet.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h -itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h +int_homun.o: int_homun.c int_homun.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h +itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h \ No newline at end of file diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 15da747e5..682a2c7d0 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -491,7 +491,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ "`base_exp`='%u', `job_exp`='%u', `zeny`='%d'," "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," - "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d'," + "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d'," //[orn] add homun_id (homunculus id) "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d'" " WHERE `account_id`='%d' AND `char_id` = '%d'", @@ -499,7 +499,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, - p->option, p->party_id, p->guild_id, p->pet_id, + p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, //[orn] add homun_id (homunculus id) p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom, mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, @@ -956,7 +956,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p){ sprintf(tmp_sql, "SELECT `option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`hair`,`hair_color`," "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`," - "`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child`, `fame`" + "`last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child`, `fame`, `homun_id`" //[orn] homun_id "FROM `%s` WHERE `char_id` = '%d'",char_db, char_id); // TBR if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); @@ -977,6 +977,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus *p){ p->save_point.map = mapindex_name2id(sql_row[17]); p->save_point.x = atoi(sql_row[18]); p->save_point.y = atoi(sql_row[19]); p->partner_id = atoi(sql_row[20]); p->father = atoi(sql_row[21]); p->mother = atoi(sql_row[22]); p->child = atoi(sql_row[23]); p->fame = atoi(sql_row[24]); + p->hom_id = atoi(sql_row[25]); //[orn] homunculus id strcat (t_msg, " status2"); } else @@ -3036,7 +3037,7 @@ int parse_frommap(int fd) { } // no inter server packet. no char server packet -> disconnect - ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); + ShowError("Unknown packet 0x%04x ( %s ) from map server, disconnecting.\n", RFIFOW(fd,0), (char*)RFIFOP(fd,0)); session[fd]->eof = 1; return 0; } diff --git a/src/char_sql/int_homun.c b/src/char_sql/int_homun.c new file mode 100644 index 000000000..cafa67806 --- /dev/null +++ b/src/char_sql/int_homun.c @@ -0,0 +1,300 @@ +// Homunculus saving by Albator and Orn for eAthena. +// GNU/GPL rulez ! + +#include +#include +#include + +#include "char.h" +#include "../common/strlib.h" +#include "../common/showmsg.h" + +struct s_homunculus *homun_pt; + +#ifndef SQL_DEBUG + +#define mysql_query(_x, _y) mysql_real_query(_x, _y, strlen(_y)) //supports ' in names and runs faster [Kevin] + +#else + +#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) + +#endif + + +int inter_homunculus_sql_init(void){ + //memory alloc + homun_pt = (struct s_homunculus*)aCalloc(sizeof(struct s_homunculus), 1); + return 0; +} +void inter_homunculus_sql_final(void){ + if (homun_pt) aFree(homun_pt); + return; +} + +int mapif_saved_homunculus(int fd, short flag) +{ + WFIFOW(fd,0) = 0x3892; + if(flag==1) + WFIFOB(fd,2) = 1; + else + WFIFOB(fd,2) = 0; + WFIFOSET(fd, 3); + return 0; +} +int mapif_info_homunculus(int fd, int account_id, struct s_homunculus *hd) +{ + WFIFOW(fd,0) = 0x3891; + WFIFOW(fd,2) = sizeof(struct s_homunculus)+9; + WFIFOL(fd,4) = account_id; + WFIFOB(fd,8) = 1; // account loaded with success + + memcpy(WFIFOP(fd,9), hd, sizeof(struct s_homunculus)); + WFIFOSET(fd, sizeof(struct s_homunculus)+9); + return 0; +} + +int mapif_homunculus_deleted(int fd, int flag) +{ + WFIFOW(fd, 0) = 0x3893; + if(flag == 1) + WFIFOB(fd,2) = 1; // Homunculus deleted + else + WFIFOB(fd,2) = 0; /* Fail /!\ */ + + WFIFOSET(fd, 3); + + return 0; + +} +int mapif_homunculus_created(int fd, int account_id, struct s_homunculus *sh, short flag) +{ + WFIFOW(fd, 0) =0x3890; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = sh->char_id; + if(flag==1){ + WFIFOW(fd, 10)=1; + WFIFOL(fd,12) = sh->hom_id; + } + else{ + WFIFOW(fd, 10)=0; + WFIFOL(fd,12) = 0; + } + WFIFOSET(fd, 16); + + return 0; +} +void init_homun_skills(struct s_homunculus *hd) +{ + int i; + for(i=0;ihskill[i].id = hd->hskill[i].lv = hd->hskill[i].flag = 0; +} + +// Save/Update Homunculus Skills +int mapif_save_homunculus_skills(struct s_homunculus *hd) +{ + int i; + + for(i=0; ihskill[i].id != 0 && hd->hskill[i].lv != 0 ) + { + sprintf(tmp_sql,"REPLACE INTO `skill_homunculus` (`homun_id`, `id`, `lv`) VALUES (%d, %d, %d)", + hd->hom_id, hd->hskill[i].id, hd->hskill[i].lv); + + if(mysql_query(&mysql_handle, tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + return 0; + } + } + } + + return 1; +} + +int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) +{ + int flag =1; + + if(hd->hom_id==0) // new homunculus + { + ShowInfo("New homunculus name : %s\n",hd->name); + + sprintf(tmp_sql, "INSERT INTO `homunculus` " + "(`char_id`, `class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `alive`, `rename_flag`, `vaporize`) " + "VALUES ('%d', '%d', '%s', '%d', '%lu', '%lu', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + hd->char_id, hd->class_,hd->name,hd->level,hd->exp,hd->intimacy,hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + hd->hp,hd->max_hp,hd->sp,hd->max_sp, hd->skillpts, hd->alive, hd->rename_flag, hd->vaporize); + + } + else + { + sprintf(tmp_sql, "UPDATE `homunculus` SET `char_id`='%d', `class`='%d',`name`='%s',`level`='%d',`exp`='%lu',`intimacy`='%lu',`hunger`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `alive`='%d', `rename_flag`='%d', `vaporize`='%d', `str`='%d' WHERE `homun_id`='%d'", + hd->char_id, hd->class_,hd->name,hd->level,hd->exp,hd->intimacy,hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + hd->hp,hd->max_hp,hd->sp,hd->max_sp, hd->skillpts, hd->alive, hd->rename_flag, hd->vaporize); + } + + if(mysql_query(&mysql_handle, tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + flag = 0; + } + + if(hd->hom_id==0 && flag!=0) + hd->hom_id = (int)mysql_insert_id(&mysql_handle); // new homunculus + else + { + flag = mapif_save_homunculus_skills(hd); + mapif_saved_homunculus(fd, flag); + } + return flag; +} + + + +// Load an homunculus +int mapif_load_homunculus(int fd){ + int i; + memset(homun_pt, 0, sizeof(struct s_homunculus)); + + sprintf(tmp_sql,"SELECT `homun_id`,`char_id`,`class`,`name`,`level`,`exp`,`intimacy`,`hunger`,, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`alive`,`rename_flag`, `vaporize` FROM `homunculus` WHERE `homun_id`='%lu'", RFIFOL(fd,6)); + if(mysql_query(&mysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + + return 0; + } + sql_res = mysql_store_result(&mysql_handle) ; + if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { + sql_row = mysql_fetch_row(sql_res); + + homun_pt->hom_id = RFIFOL(fd,6) ; //RFIFOL(fd,2); + homun_pt->class_ = atoi(sql_row[2]); + memcpy(homun_pt->name, sql_row[3],NAME_LENGTH-1); + homun_pt->char_id = atoi(sql_row[1]); + homun_pt->level = atoi(sql_row[4]); + homun_pt->exp = atoi(sql_row[5]); + homun_pt->intimacy = atoi(sql_row[6]); + homun_pt->hunger = atoi(sql_row[7]); + homun_pt->str = atoi(sql_row[8]); + homun_pt->agi = atoi(sql_row[9]); + homun_pt->vit = atoi(sql_row[10]); + homun_pt->int_ = atoi(sql_row[11]); + homun_pt->dex = atoi(sql_row[12]); + homun_pt->luk = atoi(sql_row[13]); + homun_pt->hp = atoi(sql_row[14]); + homun_pt->max_hp = atoi(sql_row[15]); + homun_pt->sp = atoi(sql_row[16]); + homun_pt->max_sp = atoi(sql_row[17]); + homun_pt->skillpts = atoi(sql_row[18]); + homun_pt->alive = atoi(sql_row[19]); + homun_pt->rename_flag = atoi(sql_row[20]); + homun_pt->vaporize = atoi(sql_row[21]); + } + if(homun_pt->hunger < 0) + homun_pt->hunger = 0; + else if(homun_pt->hunger > 100) + homun_pt->hunger = 100; + if(homun_pt->intimacy < 0) + homun_pt->intimacy = 0; + else if(homun_pt->intimacy > 100000) + homun_pt->intimacy = 100000; + + mysql_free_result(sql_res); + + // Load Homunculus Skill + init_homun_skills(homun_pt); //bousille homun_pt !!! + + sprintf(tmp_sql,"SELECT `id`,`lv` FROM `skill_homunculus` WHERE `homun_id`=%d",homun_pt->hom_id); + if(mysql_query(&mysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + return 0; + } + sql_res = mysql_store_result(&mysql_handle); + if(sql_res){ + while((sql_row = mysql_fetch_row(sql_res))){ + i = (atoi(sql_row[0])-HM_SKILLBASE-1); + homun_pt->hskill[i].id = atoi(sql_row[0]); + homun_pt->hskill[i].lv = atoi(sql_row[1]); + } + } + + mysql_free_result(sql_res); + + ShowInfo("Homunculus loaded (%d - %s).\n", homun_pt->hom_id, homun_pt->name); + return mapif_info_homunculus(fd, RFIFOL(fd,2), homun_pt); +} + + + +int mapif_delete_homunculus(int fd) +{ + sprintf(tmp_sql, "DELETE FROM `homunculus` WHERE `homun_id` = '%lu'", RFIFOL(fd,2)); + if(mysql_query(&mysql_handle, tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + return mapif_homunculus_deleted(fd, 0); + } + + return mapif_homunculus_deleted(fd, 1); +} + + + +int mapif_parse_CreateHomunculus(int fd) +{ + memset(homun_pt, 0, sizeof(struct s_homunculus)); + + /* Data from packet */ + homun_pt->char_id = RFIFOL(fd,6); + homun_pt->class_ = RFIFOW(fd,10); + homun_pt->max_hp = RFIFOL(fd,12); + homun_pt->max_sp = RFIFOL(fd,16); + memcpy(homun_pt->name, (char*)RFIFOP(fd, 20), NAME_LENGTH-1); + homun_pt->str = RFIFOL(fd,44); + homun_pt->agi = RFIFOL(fd,48); + homun_pt->vit = RFIFOL(fd,52); + homun_pt->int_ = RFIFOL(fd,56); + homun_pt->dex = RFIFOL(fd,60); + homun_pt->luk = RFIFOL(fd,64); + + /* Const data for each creation*/ + homun_pt->hom_id = 0; + homun_pt->exp =0; + homun_pt->hp = 10 ; + homun_pt->sp = 0 ; + homun_pt->rename_flag = 0; + homun_pt->skillpts =0; + homun_pt->hunger = 32; + homun_pt->level=1; + homun_pt->intimacy = 21; + + // Save in sql db + if(mapif_save_homunculus(fd,RFIFOL(fd,2), homun_pt)) + return mapif_homunculus_created(fd, RFIFOL(fd,2), homun_pt, 1); // send homun_id + else + return mapif_homunculus_created(fd, RFIFOL(fd,2), homun_pt, 0); // fail + + +} + + + + +int inter_homunculus_parse_frommap(int fd){ + switch(RFIFOW(fd, 0)){ + case 0x3090: mapif_parse_CreateHomunculus(fd); break; + case 0x3091: mapif_load_homunculus(fd); break; + case 0x3092: mapif_save_homunculus(fd, RFIFOL(fd,6), (struct s_homunculus*) RFIFOP(fd, 10)); break; + case 0x3093: mapif_delete_homunculus(fd); break; // doesn't need to be parse, very simple packet... + // rename homunculus is just like save... Map server check the rename flag before, send the save packet + // case 0x3094: mapif_parse_rename_homunculus(fd); break; + + default: + return 0; + } + return 1; +} diff --git a/src/char_sql/int_homun.h b/src/char_sql/int_homun.h new file mode 100644 index 000000000..e274c9ee1 --- /dev/null +++ b/src/char_sql/int_homun.h @@ -0,0 +1,14 @@ +// Homunculus saving by Albator and Orn for eAthena. +// GNU/GPL rulez ! + +#ifndef _INT_HOMUN_H_ +#define _INT_HOMUN_H_ + +int inter_homunculus_sql_init(void); +void inter_homunculus_sql_final(void); +int mapif_save_homunculus(struct s_homunculus *hd); +int mapif_load_homunculus(int fd); +int mapif_delete_homunculus(int fd); +int inter_homunculus_parse_frommap(int fd); + +#endif diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index 37c331141..73b049044 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -15,6 +15,7 @@ #include "int_guild.h" #include "int_storage.h" #include "int_pet.h" +#include "int_homun.h" //albator #define WISDATA_TTL (60*1000) // Wisƒf[ƒ^‚ฬถ‘ถŽžŠิ(60•b) #define WISDELLIST_MAX 256 // Wisƒf[ƒ^ํœƒŠƒXƒg‚ฬ—v‘f” @@ -79,6 +80,10 @@ int inter_recv_packet_length[]={ 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, 0, 0, 0, 0, 48,14,-1, 6, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f +// 44,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator] + 68,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator] + + }; struct WisData { @@ -362,6 +367,7 @@ int inter_init(const char *file) inter_party_sql_init(); inter_pet_sql_init(); + inter_homunculus_sql_init(); // albator inter_accreg_sql_init(); //printf ("interserver timer initializing : %d sec...\n",autosave_interval); @@ -419,6 +425,7 @@ void inter_final(void) { inter_storage_sql_final(); inter_party_sql_final(); inter_pet_sql_final(); + inter_homunculus_sql_final(); //[orn] if (accreg_pt) aFree(accreg_pt); return; @@ -753,7 +760,7 @@ int inter_parse_frommap(int fd) int cmd=RFIFOW(fd,0); int len=0; - // interŽIŠวŠ‚ฉ‚๐’ฒ‚ื‚้ + // interŽIŠวŠ‚ฉ‚๐’ฒ‚ื‚ if(cmd < 0x3000 || cmd >= 0x3000 + (sizeof(inter_recv_packet_length)/ sizeof(inter_recv_packet_length[0]) ) ) return 0; @@ -781,6 +788,8 @@ int inter_parse_frommap(int fd) break; if(inter_pet_parse_frommap(fd)) break; + if(inter_homunculus_parse_frommap(fd)) //albator + break; return 0; } diff --git a/src/common/mmo.h b/src/common/mmo.h index 4f6a92b11..a61a2e321 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -117,6 +117,11 @@ #define CHAR_CONF_NAME "conf/char_athena.conf" +//Base Homun skill. +#define HM_SKILLBASE 8000 +#define MAX_HOMUNSKILL 16 +#define MAX_HOMUNCULUS_CLASS 16 //[orn] + struct item { int id; short nameid; @@ -163,6 +168,29 @@ struct s_pet { char incuvate; }; +struct s_homunculus { //[orn] + char name[NAME_LENGTH]; + int hom_id; + int char_id; + short class_; + int hp,max_hp,sp,max_sp; + short alive; //albator + unsigned long intimacy; //[orn] + short hunger; + struct skill hskill[MAX_HOMUNSKILL]; //albator + short skillpts; + short level; + unsigned long exp; + short rename_flag; + short vaporize; //albator + int str ; + int agi ; + int vit ; + int int_ ; + int dex ; + int luk ; +}; + struct friend { int account_id; int char_id; @@ -188,6 +216,7 @@ struct mmo_charstatus { unsigned char karma; short hair,hair_color,clothes_color; int party_id,guild_id,pet_id; + int hom_id; //[orn] int fame; short weapon,shield; @@ -385,9 +414,6 @@ enum { GD_DEVELOPMENT=10014, }; -//Base Homun skill. -#define HM_SKILLBASE 8001 -#define MAX_HOMUNSKILL 16 //These mark the ID of the jobs, as expected by the client. [Skotlex] enum { diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 7a9c2f604..5c84d0d9b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -27,6 +27,7 @@ #include "skill.h" #include "mob.h" #include "pet.h" +#include "mercenary.h" //[orn] #include "battle.h" #include "party.h" #include "guild.h" @@ -298,6 +299,13 @@ ACMD_FUNC(commands); // [Skotlex] ACMD_FUNC(noask); //LuzZza ACMD_FUNC(request); //[Skotlex] +ACMD_FUNC(homlevel); //[orn] +ACMD_FUNC(homevolution); //[orn] +ACMD_FUNC(makehomun); //[orn] +ACMD_FUNC(homfriendly); //[orn] +ACMD_FUNC(homhungry); //[orn] +ACMD_FUNC(homtalk); //[orn] + /*========================================== *AtCommandInfo atcommand_info[]\‘ข‘ฬ‚ฬ’่‹` *------------------------------------------ @@ -616,6 +624,13 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_NoAsk, "@noask", 1, atcommand_noask }, // [LuzZza] { AtCommand_Request, "@request", 20, atcommand_request }, // [Skotlex] + { AtCommand_HomLevel, "@homlvup", 60, atcommand_homlevel }, + { AtCommand_HomEvolution, "@homevolution", 60, atcommand_homevolution }, + { AtCommand_MakeHomun, "@makehomun", 60, atcommand_makehomun }, + { AtCommand_HomFriendly, "@homfriendly", 60, atcommand_homfriendly }, + { AtCommand_HomHungry, "@homhungry", 60, atcommand_homhungry }, + { AtCommand_HomTalk, "@homtalk", 0, atcommand_homtalk }, + // add new commands before this line { AtCommand_Unknown, NULL, 1, NULL } }; @@ -9425,6 +9440,160 @@ int atcommand_mobinfo( return 0; } +/*========================================== + * homunculus level up [orn] + *------------------------------------------ + */ +int atcommand_homlevel( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int level = 0, i = 0; + + nullpo_retr(-1, sd); + + if (!message || !*message) + return -1; + + if ( sd->status.hom_id == 0 || !sd->homunculus.alive || sd->homunculus.vaporize ) + return 1 ; + + level = atoi(message); + if ( ( level + sd->homunculus.level ) > MAX_LEVEL ) + level = MAX_LEVEL - sd->homunculus.level ; + if (level >= 1) { + for (i = 1; i <= level ; i++){ + merc_hom_levelup(sd->hd) ; + } + clif_misceffect2(&sd->hd->bl,568) ; + } + + return 0; +} + +/*========================================== + * homunculus evolution H [orn] + *------------------------------------------ + */ +int atcommand_homevolution( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + nullpo_retr(-1, sd); + + if (sd->hd && sd->hd->homunculusDB->evo_class) + { + merc_hom_evolution(sd->hd) ; + } + return 0; +} + +/*========================================== + * call choosen homunculus [orn] + *------------------------------------------ + */ +int +atcommand_makehomun( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int homunid; + nullpo_retr(-1, sd); + if(sscanf(message, "%d", &homunid)<1) + return -1; + if( homunid < 6001 || homunid > 6016 ) + return -1; + if(sd->status.hom_id == 0) + { + merc_create_homunculus(sd,homunid); + } + else + { + clif_displaymessage(fd,msg_txt(144)); + } + return 0; +} + +/*========================================== + * modify homunculus intimacy [orn] + *------------------------------------------ + */ +int atcommand_homfriendly( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int friendly = 0; + + nullpo_retr(-1, sd); + + if (!message || !*message) + return -1; + + friendly = atoi(message); + if (sd->status.hom_id > 0 && sd->hd) { + if (friendly > 0 && friendly <= 1000) { + sd->homunculus.intimacy = friendly * 100 ; + clif_send_homdata(sd,SP_INTIMATE,friendly); + } else { + return -1; + } + } + + return 0; +} + +/*========================================== + * modify homunculus hunger [orn] + *------------------------------------------ + */ +int atcommand_homhungry( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + int hungry = 0; + + nullpo_retr(-1, sd); + + if (!message || !*message) + return -1; + + hungry = atoi(message); + if (sd->status.hom_id > 0 && sd->hd) { + if (hungry >= 0 && hungry <= 100) { + sd->homunculus.hunger = hungry; + clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); + } else { + return -1; + } + } + + return 0; +} + +/*========================================== + * modify homunculus hunger [orn] + *------------------------------------------ + */ +int atcommand_homtalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char mes[100],temp[100]; + + nullpo_retr(-1, sd); + + if(!sd->status.hom_id || !sd->hd || !sd->homunculus.alive ) + return -1; + + if (sscanf(message, "%99[^\n]", mes) < 1) + return -1; + + snprintf(temp, sizeof temp ,"%s : %s",sd->homunculus.name,mes); + clif_message(&sd->hd->bl, temp); + + return 0; +} + /*========================================== * Show Items DB Info v 1.0 * originally by [Lupus] eAthena diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 60b20c4ab..11cf113f0 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -271,6 +271,12 @@ enum AtCommandType { AtCommand_Commands, // [Skotlex] AtCommand_NoAsk, // [LuzZza] AtCommand_Request, // [Skotlex], supposedly taken from Freya (heard the command was there, but I haven't seen the code yet) + AtCommand_HomLevel, //[orn] + AtCommand_HomEvolution, //[orn] + AtCommand_MakeHomun, //[orn] + AtCommand_HomFriendly, //[orn] + AtCommand_HomHungry, //[orn] + AtCommand_HomTalk, //[orn] // end <- Ahem, guys, don't place AtCommands after AtCommand_Unknown! [Skotlex] AtCommand_Unknown, AtCommand_MAX diff --git a/src/map/battle.c b/src/map/battle.c index cee888fe0..929b4494c 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -761,6 +761,7 @@ static struct Damage battle_calc_weapon_attack( short i; struct map_session_data *sd, *tsd; + struct homun_data *hd; //[orn] struct Damage wd; struct status_change *sc = status_get_sc(src); struct status_change *tsc = status_get_sc(target); @@ -813,6 +814,7 @@ static struct Damage battle_calc_weapon_attack( BL_CAST(BL_PC, src, sd); BL_CAST(BL_PC, target, tsd); + BL_CAST(BL_HOMUNCULUS, src, hd); //[orn] if(sd) { if (sd->skillblown[0].id != 0) @@ -1029,6 +1031,7 @@ static struct Damage battle_calc_weapon_attack( case NPC_MENTALBREAKER: case GS_GROUNDDRIFT: case NJ_TATAMIGAESHI: + case HVAN_EXPLOSION: //[orn] flag.hit = 1; break; case CR_SHIELDBOOMERANG: @@ -1177,6 +1180,14 @@ static struct Damage battle_calc_weapon_attack( ATK_ADD(sd->inventory_data[index]->weight/10); break; } + case HFLI_SBR44: //[orn] + if(hd){ + wd.damage = hd->master->homunculus.intimacy ; + wd.damage2 = hd->master->homunculus.intimacy ; + hd->master->homunculus.intimacy = 200; + clif_send_homdata(hd->master,0x100,hd->master->homunculus.intimacy/100); + } + break; default: { i = (flag.cri?1:0)|(flag.arrow?2:0)|(skill_num == HW_MAGICCRASHER?4:0)|(skill_num == MO_EXTREMITYFIST?8:0); @@ -1499,6 +1510,12 @@ static struct Damage battle_calc_weapon_attack( case MO_BALKYOUNG: skillratio += 200; break; + case HFLI_MOON: //[orn] + skillratio += ( 110 * (skill_lv + 1) ) - 100 ; + skillratio /= wd.div_ ; + break; + case HFLI_SBR44: //[orn] + skillratio += 100 * skill_lv ; } ATK_RATE(skillratio); @@ -2468,6 +2485,7 @@ struct Damage battle_calc_misc_attack( case CR_ACIDDEMONSTRATION: md.flag = (md.flag&~BF_RANGEMASK)|BF_LONG; break; + case HVAN_EXPLOSION: //[orn] case NPC_SELFDESTRUCTION: case NPC_SMOKING: flag.elefix = flag.cardfix = 0; @@ -2553,6 +2571,9 @@ struct Damage battle_calc_misc_attack( case GS_FLING: md.damage = sd?sd->status.job_level:status_get_lv(src); break; + case HVAN_EXPLOSION: //[orn] + md.damage = sstatus->hp * (50 + 50 * skill_lv) / 100 ; + break ; } damage_div_fix(md.damage, md.div_); @@ -3619,6 +3640,7 @@ static const struct battle_data_short { { "autospell_stacking", &battle_config.autospell_stacking }, { "override_mob_names", &battle_config.override_mob_names }, { "min_chat_delay", &battle_config.min_chat_delay }, + { "homunculus_show_growth", &battle_config.homunculus_show_growth }, //[orn] }; static const struct battle_data_int { @@ -3662,7 +3684,7 @@ static const struct battle_data_int { { "max_heal", &battle_config.max_heal }, { "mob_remove_delay", &battle_config.mob_remove_delay }, { "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration }, - + { "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate }, //[orn] }; int battle_set_value(char *w1, char *w2) { @@ -4045,6 +4067,8 @@ void battle_set_defaults() { battle_config.autospell_stacking = 0; battle_config.override_mob_names = 0; battle_config.min_chat_delay = 0; + battle_config.hvan_explosion_intimate = 45000; //[orn] + battle_config.homunculus_show_growth = 0; //[orn] } void battle_validate_conf() { @@ -4257,6 +4281,9 @@ void battle_validate_conf() { if (battle_config.cell_stack_limit != 1) ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); #endif + + if(battle_config.hvan_explosion_intimate > 100000) //[orn] + battle_config.hvan_explosion_intimate = 100000; } /*========================================== diff --git a/src/map/battle.h b/src/map/battle.h index a4533395a..d1af883a6 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -436,6 +436,8 @@ extern struct Battle_Config { unsigned short autospell_stacking; //Enables autospell cards to stack. [Skotlex] unsigned short override_mob_names; //Enables overriding spawn mob names with the mob_db names. [Skotlex] unsigned short min_chat_delay; //Minimum time between client messages. [Skotlex] + unsigned int hvan_explosion_intimate ; // fix [albator] + unsigned short homunculus_show_growth ; //[orn] } battle_config; diff --git a/src/map/charsave.c b/src/map/charsave.c index 3f5241900..41a3293e4 100644 --- a/src/map/charsave.c +++ b/src/map/charsave.c @@ -26,6 +26,7 @@ struct mmo_charstatus *charsave_loadchar(int charid){ char *str_p; friends = 0; + ShowDebug("charsave_loadchar : charid = %d | hd->master->status.char_id = %d\n", charid) ; c = (struct mmo_charstatus *)aCalloc(1,sizeof(struct mmo_charstatus)); if(charid <= 0){ @@ -33,9 +34,9 @@ struct mmo_charstatus *charsave_loadchar(int charid){ aFree(c); return NULL; } - + // add homun_id [albator] //Tested, Mysql 4.1.9+ has no problems with the long query, the buf is 65k big and the sql server needs for it 0.00009 secs on an athlon xp 2400+ WinXP (1GB Mem) .. [Sirius] - sprintf(tmp_sql, "SELECT `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, `str`,`agi`,`vit`,`int`,`dex`,`luk`, `max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, `option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`hair`,`hair_color`, `clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`, `last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child`, `fame` FROM `char` WHERE `char_id` = '%d'", charid); + sprintf(tmp_sql, "SELECT `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, `str`,`agi`,`vit`,`int`,`dex`,`luk`, `max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, `option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`hair`,`hair_color`, `clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`, `last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child`, `fame`, `homun_id` FROM `char` WHERE `char_id` = '%d'", charid); if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); @@ -102,9 +103,10 @@ struct mmo_charstatus *charsave_loadchar(int charid){ c->mother = atoi(charsql_row[44]); c->child = atoi(charsql_row[45]); c->fame = atoi(charsql_row[46]); - + c->hom_id = atoi(charsql_row[47]); // albator mysql_free_result(charsql_res); + //Check for '0' Savepoint / LastPoint if (c->last_point.x == 0 || c->last_point.y == 0 || c->last_point.map == 0){ c->last_point.map = mapindex_name2id(MAP_PRONTERA); @@ -237,8 +239,10 @@ struct mmo_charstatus *charsave_loadchar(int charid){ c->global_reg_num = i; } */ + + //Shamelessly stolen from its_sparky (ie: thanks) and then assimilated by [Skotlex] - //Friend list + //Friend list sprintf(tmp_sql, "SELECT f.friend_account, f.friend_id, c.name FROM friends f LEFT JOIN `char` c ON f.friend_account=c.account_id AND f.friend_id=c.char_id WHERE f.char_id='%d'", charid); if(mysql_query(&charsql_handle, tmp_sql)){ @@ -248,7 +252,7 @@ struct mmo_charstatus *charsave_loadchar(int charid){ } else sql_res = mysql_store_result(&charsql_handle); - + if(sql_res) { for(i = 0; (sql_row = mysql_fetch_row(sql_res)) && imaster->status.char_id = %d\n", charid) ; sprintf(tmp_sql ,"UPDATE `char` SET `class`='%d', `base_level`='%d', `job_level`='%d'," "`base_exp`='%d', `job_exp`='%d', `zeny`='%d'," "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," @@ -280,7 +285,7 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){ "`option`='%d',`karma`='%d',`manner`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d'," "`hair`='%d',`hair_color`='%d',`clothes_color`='%d',`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d'," - "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d', `fame`='%d'" + "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d', `fame`='%d', `homun_id`='%d'" "WHERE `account_id`='%d' AND `char_id` = '%d'", c->class_, c->base_level, c->job_level, c->base_exp, c->job_exp, c->zeny, @@ -291,7 +296,7 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){ c->weapon, c->shield, c->head_top, c->head_mid, c->head_bottom, mapindex_id2name(c->last_point.map), c->last_point.x, c->last_point.y, mapindex_id2name(c->save_point.map), c->save_point.x, c->save_point.y, c->partner_id, c->father, c->mother, - c->child, c->fame, c->account_id, c->char_id + c->child, c->fame, c->hom_id, c->account_id, c->char_id ); if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); @@ -311,16 +316,16 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){ str_p += sprintf(str_p, "INSERT INTO `inventory` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); for (j = 0; j < MAX_SLOTS; j++) str_p += sprintf(str_p, ", `card%d`", j); - + str_p += sprintf(str_p, ") VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d'", charid, c->inventory[i].nameid, c->inventory[i].amount, c->inventory[i].equip, c->inventory[i].identify, c->inventory[i].refine, c->inventory[i].attribute); for (j = 0; j < MAX_SLOTS; j++) str_p += sprintf(str_p, ", '%d'", c->inventory[i].card[j]); - + strcat(tmp_sql,")"); - + if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); @@ -340,16 +345,16 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){ str_p += sprintf(str_p, "INSERT INTO `cart_inventory` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); for (j = 0; j < MAX_SLOTS; j++) str_p += sprintf(str_p, ", `card%d`", j); - + str_p += sprintf(str_p, ") VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d'", charid, c->cart[i].nameid, c->cart[i].amount, c->cart[i].equip, c->cart[i].identify, c->cart[i].refine, c->cart[i].attribute); for (j = 0; j < MAX_SLOTS; j++) str_p += sprintf(str_p, ", '%d'", c->cart[i].card[j]); - + strcat(tmp_sql,")"); - + if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); @@ -436,7 +441,7 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){ int charsave_load_scdata(int account_id, int char_id) { //Loads character's sc_data struct map_session_data *sd; - + sd = map_id2sd(account_id); if (!sd) { @@ -450,7 +455,7 @@ int charsave_load_scdata(int account_id, int char_id) } sprintf(tmp_sql, "SELECT `type`, `tick`, `val1`, `val2`, `val3`, `val4` FROM `sc_data`" "WHERE `account_id`='%d' AND `char_id`='%d'", account_id, char_id); - + if(mysql_query(&charsql_handle, tmp_sql)){ ShowSQL("DB error - %s\n",mysql_error(&charsql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); @@ -490,7 +495,7 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_ char *p = tmp_sql; p += sprintf(p, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES "); - + for(i = 0; i < max_sc; i++) { if (sc_data->data[i].timer == -1) @@ -498,10 +503,10 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_ timer = get_timer(sc_data->data[i].timer); if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) continue; - + p += sprintf(p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", account_id, char_id, i, DIFF_TICK(timer->tick,tick), sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4); - + count++; } if (count > 0) diff --git a/src/map/charsave.h b/src/map/charsave.h index 6fa119e14..049efebda 100644 --- a/src/map/charsave.h +++ b/src/map/charsave.h @@ -7,6 +7,11 @@ #include "status.h" #ifndef TXT_ONLY + int charsave_loadHomunculus(int hom_id, struct homun_data *p); + int charsave_saveHomunculus(struct homun_data *hd); + int charsave_saveHomunculusSkills(struct homun_data *hd); + int charsave_deleteHomunculus(struct homun_data *hd); + struct mmo_charstatus *charsave_loadchar(int charid); int charsave_savechar(int charid, struct mmo_charstatus *c); int charsave_load_scdata(int account_id, int char_id); diff --git a/src/map/chrif.c b/src/map/chrif.c index 3f253d5a2..6f7415099 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -22,6 +22,7 @@ #include "npc.h" #include "pc.h" #include "status.h" +#include "mercenary.h" #ifndef TXT_ONLY #include "charsave.h" #endif diff --git a/src/map/clif.c b/src/map/clif.c index 5cc780656..bfa2f7eb7 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -41,6 +41,7 @@ #include "guild.h" #include "vending.h" #include "pet.h" +#include "mercenary.h" //[orn] #include "log.h" #include "irc.h" @@ -1449,93 +1450,89 @@ int clif_spawn(struct block_list *bl) } return 0; } -/*========================================== - * Homunculus [blackhole89] - *------------------------------------------ - */ -// Can somebody tell me why exactly I have commented this lot of stuff out? -// acknowledge client it has a homunculus -int clif_homunack(struct map_session_data *sd) -{ - struct homun_data *hd = sd->hd; - unsigned char buf[64]; - - nullpo_retr(0, sd); - nullpo_retr(0, sd->hd); - //memset(buf,0,packet_len_table[0x230]); - memset(buf,0,12); //not yet set that stuff - WBUFW(buf,0)=0x230; - WBUFL(buf,4)=hd->bl.id; - ShowError("in clif_homunack~\n"); - clif_send(buf,/*packet_len_table[0x230]*/12,&sd->bl,SELF); - - return 0; -} - -// homunculus stats et al -int clif_homuninfo(struct map_session_data *sd) +//[orn] +int clif_hominfo(struct map_session_data *sd, int flag) { struct homun_data *hd = sd->hd; struct status_data *status; unsigned char buf[128]; nullpo_retr(0, hd); + +// if ( sd->hd ) +// return 0 ; + status = &hd->battle_status; memset(buf,0,71); //packet_len_table[0x22e]); WBUFW(buf,0)=0x22e; - memcpy(WBUFP(buf,2),hd->name,NAME_LENGTH); - WBUFW(buf,27)=hd->level; - WBUFW(buf,29)=hd->hunger_rate; - WBUFL(buf,31)=0xFF; //intimacy, leave it as is - WBUFW(buf,35)=status->batk; + memcpy(WBUFP(buf,2),hd->master->homunculus.name,NAME_LENGTH); + WBUFB(buf,26)=hd->master->homunculus.rename_flag * 2; + WBUFW(buf,27)=hd->master->homunculus.level; + WBUFW(buf,29)=hd->master->homunculus.hunger; + WBUFW(buf,31)=(unsigned short) (hd->master->homunculus.intimacy / 100) ; + WBUFW(buf,33)=0; // equip id + WBUFW(buf,35)=status->rhw.atk2; WBUFW(buf,37)=status->matk_max; WBUFW(buf,39)=status->hit; WBUFW(buf,41)=status->cri/10; //crit is a +1 decimal value! - WBUFW(buf,43)=status->def; + WBUFW(buf,43)=status->def + status->vit ; WBUFW(buf,45)=status->mdef; WBUFW(buf,47)=status->flee; - WBUFW(buf,49)=status->amotion; + WBUFW(buf,49)=(flag)?0:status->amotion; WBUFW(buf,51)=status->hp; WBUFW(buf,53)=status->max_hp; WBUFW(buf,55)=status->sp; WBUFW(buf,57)=status->max_sp; - WBUFL(buf,59)=hd->exp; + WBUFL(buf,59)=hd->master->homunculus.exp; WBUFL(buf,63)=hd->exp_next; - WBUFW(buf,67)=hd->skillpts; - WBUFW(buf,69)=0x21; + WBUFW(buf,67)=hd->master->homunculus.skillpts; + WBUFW(buf,69)=hd->attackable; clif_send(buf,/*packet_len_table[0x22e]*/71,&sd->bl,SELF); return 0; } +/*========================================== + * + *------------------------------------------ + */ +void clif_send_homdata(struct map_session_data *sd, int type, int param) { //[orn] + int fd; + nullpo_retv(sd); + nullpo_retv(sd->hd); + + fd=sd->fd; + WFIFOW(fd,0)=0x230; + WFIFOW(fd,2)=type; + WFIFOL(fd,4)=sd->hd->bl.id; + WFIFOL(fd,8)=param; + WFIFOSET(fd,packet_len_table[0x230]); + + return; +} // like skillinfoblock, just for homunculi. -int clif_homunskillinfoblock(struct map_session_data *sd) -{ +int clif_homskillinfoblock(struct map_session_data *sd) { //[orn] int fd; - int i,c,len=4,id/*, inf2*/; + int i,j,c,len=4,id/*, inf2*/; nullpo_retr(0, sd); nullpo_retr(0, sd->hd); + if ( !sd->hd ) + return 0 ; + fd=sd->fd; - WFIFOHEAD(fd, 4 * 37 + 4); WFIFOW(fd,0)=0x235; - for ( i = c = 0; i < 4; i++){ - if( (id=sd->hd->hskill[i].id)!=0 ){ - WFIFOW(fd,len ) = id; - WFIFOW(fd,len+2) = skill_get_inf(id-7300); // H. skills mapped to 700 and above - WFIFOW(fd,len+4) = 0; - WFIFOW(fd,len+6) = sd->hd->hskill[i].level; - WFIFOW(fd,len+8) = skill_get_sp(id,sd->hd->hskill[i].level); - WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->hd->hskill[i].level); - strncpy(WFIFOP(fd,len+12), /*merc_skill_get_name(id)*/ "", NAME_LENGTH); // can somebody tell me what exactly that function was good for anyway - /* inf2 = skill_get_inf2(id); - if(((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && - !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL))) || - (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) ) - //WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0; - WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[i].flag ==0 )? 1:0; - else */ + for ( i = c = 0; i < MAX_HOMUNSKILL; i++){ + if( (id = sd->homunculus.hskill[i].id) != 0 ){ + j = id - HM_SKILLBASE - 1 ; + WFIFOW(fd,len ) = id ; + WFIFOW(fd,len+2) = skill_get_inf(id) ; + WFIFOW(fd,len+4) = 0 ; + WFIFOW(fd,len+6) = sd->homunculus.hskill[j].lv ; + WFIFOW(fd,len+8) = skill_get_sp(id,sd->homunculus.hskill[j].lv) ; + WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,sd->homunculus.hskill[j].lv) ; + strncpy(WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH) ; WFIFOB(fd,len+36) = 1;//0; len+=37; c++; @@ -1547,49 +1544,146 @@ int clif_homunskillinfoblock(struct map_session_data *sd) return 0; } +void clif_homskillup(struct map_session_data *sd, int skill_num) { //[orn] + int range,fd,skillid; + + nullpo_retv(sd); + skillid = skill_num - HM_SKILLBASE ; + + fd=sd->fd; + WFIFOW(fd,0) = 0x10e; + WFIFOW(fd,2) = skill_num; + WFIFOW(fd,4) = sd->homunculus.hskill[skillid].lv; + WFIFOW(fd,6) = skill_get_sp(skill_num,sd->homunculus.hskill[skillid].lv); + range = skill_get_range(skill_num,sd->homunculus.hskill[skillid].lv); + if(range < 0) + range = status_get_range(&sd->bl) - (range + 1); + WFIFOW(fd,8) = range; + WFIFOB(fd,10) = (sd->homunculus.hskill[skillid].lv < skill_get_max(sd->homunculus.hskill[skillid].id)) ? 1 : 0; + WFIFOSET(fd,packet_len_table[0x10e]); + + return; +} + // Request a Homunculus name change -void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { +void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { //[orn] RFIFOHEAD(fd); nullpo_retv(sd); nullpo_retv(sd->hd); - memcpy(sd->hd->name,RFIFOP(fd,2),24); - clif_homuninfo(sd); + memcpy(sd->homunculus.name,RFIFOP(fd,2),24); + sd->homunculus.rename_flag = 1 ; + clif_hominfo(sd,0); clif_charnameack(sd->fd,&sd->hd->bl); } // Somebody who is less lazy than me rename this to ReturnToMaster or something -void clif_parse_QueryHomunPos(int fd, struct map_session_data *sd) { +void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) { //[orn] RFIFOHEAD(fd); nullpo_retv(sd); nullpo_retv(sd->hd); + + if ( sd->hd && status_isdead(&sd->hd->bl) ) + return ; + unit_walktoxy(&sd->hd->bl, sd->bl.x,sd->bl.y-1, 0); //move to master - //clif_homunposack(sd->hd); +} + +// player spend a skillpoint for homunculus +void clif_parse_HomUseSKillPoint(int fd, struct map_session_data *sd) { //[orn] + int skillid ; + nullpo_retv(sd); + nullpo_retv(sd->hd); + + if ( !sd->hd ) + return ; + skillid = RFIFOW(fd,2); + + merc_hom_skillup(sd->hd, skillid); } // Request a Homunculus move-to-position -void clif_parse_HMoveTo(int fd,struct map_session_data *sd) { +void clif_parse_HomMoveTo(int fd,struct map_session_data *sd) { //[orn] int x,y,cmd; nullpo_retv(sd); nullpo_retv(sd->hd); + if ( sd->hd && status_isdead(&sd->hd->bl) ) + return ; + cmd = RFIFOW(fd,0); x = RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]) * 4 + (RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 1) >> 6); y = ((RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]+1) & 0x3f) << 4) + (RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 2) >> 4); - unit_walktoxy(&sd->hd->bl,x,y,0); + unit_walktoxy(&(sd->hd->bl),x,y,0); } // Request the Homunculus attacking a bl -void clif_parse_HAttack(int fd,struct map_session_data *sd) { +void clif_parse_HomAttack(int fd,struct map_session_data *sd) { //[orn] + struct block_list *target; nullpo_retv(sd); nullpo_retv(sd->hd); + + target=map_id2bl(RFIFOL(fd,6)); + + if ( sd->hd && target && ( status_isdead(&sd->hd->bl) || status_isdead(target) ) ) + return ; if(sd->hd->bl.id != RFIFOL(fd,2)) return; - - printf("unit_attack returned: %d\n",unit_attack(&sd->hd->bl,RFIFOL(fd,6),0)); + merc_stop_walking(sd->hd, 1); + merc_stop_attack(sd->hd); + if ( sd->hd && target ) { + sd->hd->target_id = RFIFOL(fd,6) ; + unit_attack(&sd->hd->bl,RFIFOL(fd,6),1) ; + } +} + +void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn] + int cmd; + cmd = RFIFOW(fd,0); + RFIFOHEAD(fd); + if ( sd->hd && status_isdead(&sd->hd->bl) ) + return ; + merc_menu(sd,RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0])); +} + +int clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn] +{ + int fd; + + nullpo_retr(0, sd); + + fd=sd->fd; + WFIFOHEAD(fd,packet_len_table[0x22f]); + WFIFOW(fd,0)=0x22f; + WFIFOB(fd,2)=fail; + WFIFOW(fd,3)=foodid; + WFIFOSET(fd,packet_len_table[0x22f]); + + return 0; +} + +/*========================================== + * orn + *------------------------------------------ + */ +int clif_hwalkok(struct homun_data *hd) +{ + int fd; + + nullpo_retr(0, hd); + + fd=hd->master->fd; + WFIFOHEAD(fd, packet_len_table[0x87]); + WFIFOW(fd,0)=0x87; + WFIFOL(fd,2)=gettick(); + WFIFOPOS2(fd,6,hd->bl.x,hd->bl.y,hd->ud.to_x,hd->ud.to_y); + WFIFOB(fd,11)=0x88; + WFIFOSET(fd,packet_len_table[0x87]); + + return 0; } /*========================================== @@ -7751,7 +7845,7 @@ int clif_charnameack (int fd, struct block_list *bl) break; //[blackhole89] case BL_HOMUNCULUS: - memcpy(WBUFP(buf,6), ((struct homun_data*)bl)->name, NAME_LENGTH); + memcpy(WBUFP(buf,6), ((struct homun_data*)bl)->master->homunculus.name, NAME_LENGTH); break; case BL_PET: memcpy(WBUFP(buf,6), ((struct pet_data*)bl)->name, NAME_LENGTH); @@ -8210,10 +8304,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->hd && sd->hd->battle_status.hp) { map_addblock(&sd->hd->bl); clif_spawn(&sd->hd->bl); - clif_homunack(sd); - clif_homuninfo(sd); - clif_homuninfo(sd); //for some reason, at least older clients want this sent twice - clif_homunskillinfoblock(sd); +// clif_homunack(sd); + clif_hominfo(sd,1); + clif_hominfo(sd,0); //for some reason, at least older clients want this sent twice + clif_send_homdata(sd,0,0); + clif_homskillinfoblock(sd); } if(sd->state.connect_new) { @@ -9612,6 +9707,9 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { if (skillnotok(skillnum, sd)) return; + if (sd->hd && skillnotok_hom(skillnum, sd->hd)) //[orn] + return; + if (sd->bl.id != target_id && !sd->state.skill_flag && skill_get_inf(skillnum)&INF_SELF_SKILL) @@ -9680,12 +9778,19 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { if (skillnum >= GD_SKILLBASE && sd->state.gmaster_flag) skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum); - if ((lv = pc_checkskill(sd, skillnum)) > 0) { - if (skilllv > lv) - skilllv = lv; - unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); - if (sd->state.skill_flag) - sd->state.skill_flag = 0; + if ( ( skillnum >= HM_SKILLBASE ) && sd->status.hom_id && sd->homunculus.alive && !sd->homunculus.vaporize ) { //[orn] + if ( ( lv = merc_hom_checkskill(sd, skillnum) ) > 0 ) + if (skilllv > lv) + skilllv = lv; + unit_skilluse_id(&sd->hd->bl, target_id, skillnum, skilllv); + } else { + if ((lv = pc_checkskill(sd, skillnum)) > 0) { + if (skilllv > lv) + skilllv = lv; + unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); + if (sd->state.skill_flag) + sd->state.skill_flag = 0; + } } } } @@ -11559,6 +11664,36 @@ int clif_parse(int fd) { #if DUMP_ALL_PACKETS dump = 1; + int i; + FILE *fp; + char packet_txt[256] = "save/packet.txt"; + time_t now; + dump = 1; + + if ((fp = fopen(packet_txt, "a")) == NULL) { + ShowError("clif.c: cant write [%s] !!! data is lost !!!\n", packet_txt); + return 1; + } else { + time(&now); + if (sd && sd->state.auth) { + if (sd->status.name != NULL) + fprintf(fp, "%sPlayer with account ID %d (character ID %d, player name %s) sent packet:\n", + asctime(localtime(&now)), sd->status.account_id, sd->status.char_id, sd->status.name); + else + fprintf(fp, "%sPlayer with account ID %d sent wrong packet:\n", asctime(localtime(&now)), sd->bl.id); + } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) + fprintf(fp, "%sPlayer with account ID %d sent wrong packet:\n", asctime(localtime(&now)), sd->bl.id); + + fprintf(fp, "\tsession #%d, packet 0x%04x, length %d, version %d\n", fd, cmd, packet_len, packet_ver); + fprintf(fp, "\t---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"); + for(i = 0; i < packet_len; i++) { + if ((i & 15) == 0) + fprintf(fp, "\n\t%04X ", i); + fprintf(fp, "%02X ", RFIFOB(fd,i)); + } + fprintf(fp, "\n\n"); + fclose(fp); + } #endif if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) { // ุ’f‘า‚ฟ‚ฬ๊‡ƒpƒPƒbƒg‚๐ˆ—‚ต‚ศ‚ข @@ -11777,11 +11912,13 @@ static int packetdb_readdb(void) {clif_parse_FeelSaveOk,"feelsaveok"}, {clif_parse_AdoptRequest,"adopt"}, {clif_parse_debug,"debug"}, - //[blackhole89] + //[blackhole89] //[orn] {clif_parse_ChangeHomunculusName,"changehomunculusname"}, - {clif_parse_QueryHomunPos,"queryhomunpos"}, - {clif_parse_HMoveTo,"hmoveto"}, - {clif_parse_HAttack,"hattack"}, + {clif_parse_HomMoveToMaster,"hommovetomaster"}, + {clif_parse_HomMoveTo,"hommoveto"}, + {clif_parse_HomAttack,"homattack"}, + {clif_parse_HomUseSKillPoint,"homuseskillpoint"}, + {clif_parse_HomMenu,"hommenu"}, {NULL,NULL} }; diff --git a/src/map/clif.h b/src/map/clif.h index 53a6332c3..b89471985 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -354,9 +354,13 @@ void clif_mission_mob(struct map_session_data *sd, unsigned short mob_id, unsign // [blackhole89] int clif_spawnhomun(struct homun_data *hd); -int clif_homunack(struct map_session_data *sd); -int clif_homuninfo(struct map_session_data *sd); -int clif_homunskillinfoblock(struct map_session_data *sd); +int clif_hominfo(struct map_session_data *sd, int flag); +int clif_homskillinfoblock(struct map_session_data *sd); +void clif_homskillup(struct map_session_data *sd, int skill_num) ; //[orn] +int clif_hom_food(struct map_session_data *sd,int foodid,int fail); //[orn] +void clif_send_homdata(struct map_session_data *sd, int type, int param); //[orn] +int clif_hwalkok(struct homun_data *hd); //[orn] + #endif diff --git a/src/map/intif.c b/src/map/intif.c index 9f20d3a9c..bb12fa673 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -24,6 +24,7 @@ #include "guild.h" #include "pet.h" #include "atcommand.h" +#include "mercenary.h" //albator static const int packet_len_table[]={ -1,-1,27,-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f @@ -35,6 +36,7 @@ static const int packet_len_table[]={ 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, 0, 0, 0, 0, 11,-1, 7, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 + 16,-1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3890 Homunculus [albator] }; extern int char_fd; // inter server‚ฬfd‚อchar_fd‚๐Žg‚ค @@ -132,13 +134,13 @@ int intif_GMmessage(char* mes,int len,int flag) // Send to the local players clif_GMmessage(NULL, mes, len, flag); - + if (CheckForCharServer()) return 0; - + if (other_mapserver_count < 1) return 0; //No need to send. - + WFIFOHEAD(inter_fd,lp + len + 4); WFIFOW(inter_fd,0) = 0x3000; WFIFOW(inter_fd,2) = lp + len + 4; @@ -156,13 +158,13 @@ int intif_announce(char* mes,int len, unsigned long color, int flag) clif_MainChatMessage(mes); else clif_announce(NULL, mes, len, color, flag); - + if (CheckForCharServer()) return 0; if (other_mapserver_count < 1) return 0; //No need to send. - + WFIFOHEAD(inter_fd, 8 + len); WFIFOW(inter_fd,0) = 0x3000; WFIFOW(inter_fd,2) = 8 + len; @@ -182,8 +184,8 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int me { //Character not found. clif_wis_end(sd->fd, 1); return 0; - } - + } + WFIFOHEAD(inter_fd,mes_len + 52); WFIFOW(inter_fd,0) = 0x3001; WFIFOW(inter_fd,2) = mes_len + 52; @@ -236,7 +238,7 @@ int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes) { int intif_regtostr(char* str, struct global_reg *reg, int qty) { int len =0, i; - + for (i = 0; i < qty; i++) { len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. len+= sprintf(str+len, "%s", reg[i].value)+1; @@ -252,7 +254,7 @@ int intif_saveregistry(struct map_session_data *sd, int type) if (CheckForCharServer()) return -1; - + switch (type) { case 3: //Character reg reg = sd->save_reg.global; @@ -311,7 +313,7 @@ int intif_request_registry(struct map_session_data *sd, int flag) WFIFOW(inter_fd,0) = 0x3005; WFIFOL(inter_fd,2) = sd->status.account_id; WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 + WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg WFIFOSET(inter_fd,13); @@ -405,7 +407,7 @@ int intif_party_addmember(int party_id,struct party_member *member) { if (CheckForCharServer()) return 0; - + WFIFOHEAD(inter_fd,42); WFIFOW(inter_fd,0)=0x3022; WFIFOW(inter_fd,2)=8+sizeof(struct party_member); @@ -448,7 +450,7 @@ int intif_party_changemap(struct map_session_data *sd,int online) return 0; if(!sd) return 0; - + WFIFOHEAD(inter_fd,19); WFIFOW(inter_fd,0)=0x3025; WFIFOL(inter_fd,2)=sd->status.party_id; @@ -776,6 +778,72 @@ int intif_guild_castle_datasave(int castle_id,int index, int value) return 0; } +//----------------------------------------------------------------- +// Homunculus Packets send to Inter server [albator] +//----------------------------------------------------------------- + +int intif_homunculus_create(int account_id, struct s_homunculus *sh) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 44+NAME_LENGHT); + WFIFOW(inter_fd, 0) = 0x3090; + WFIFOL(inter_fd, 2) = account_id; + WFIFOL(inter_fd, 6) = sh->char_id; + WFIFOW(inter_fd, 10) = sh->class_; + WFIFOL(inter_fd,12) = sh->max_hp; + WFIFOL(inter_fd,16) = sh->max_sp; + memcpy(WFIFOP(inter_fd,20), sh->name, NAME_LENGTH); + WFIFOL(inter_fd,44) = sh->str; + WFIFOL(inter_fd,48) = sh->agi; + WFIFOL(inter_fd,52) = sh->vit; + WFIFOL(inter_fd,56) = sh->int_; + WFIFOL(inter_fd,60) = sh->dex; + WFIFOL(inter_fd,64) = sh->luk; + WFIFOSET(inter_fd, 44+NAME_LENGTH); + + return 0; +} + +int intif_homunculus_requestload(int account_id, int homun_id) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 10); + WFIFOW(inter_fd,0) = 0x3091; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = homun_id; + WFIFOSET(inter_fd, 10); + return 0; +} + +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+10); + WFIFOW(inter_fd,0) = 0x3092; + WFIFOL(inter_fd,2) = sizeof(struct s_homunculus)+10; + WFIFOL(inter_fd,6) = account_id; + memcpy(WFIFOP(inter_fd,10),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, sizeof(struct s_homunculus)+10); + return 0; + +} + +int intif_homunculus_requestdelete(int homun_id) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3093; + WFIFOL(inter_fd,2) = homun_id; + WFIFOSET(inter_fd,6); + return 0; + +} + + //----------------------------------------------------------------- // Packets receive from inter server @@ -881,9 +949,9 @@ int intif_parse_Registers(int fd) { if (RFIFOB(fd,12) == 3 && sd->status.char_id != RFIFOL(fd,8)) return 1; //Character registry from another character. - + flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); - + switch (RFIFOB(fd,12)) { case 3: //Character Registry reg = sd->save_reg.global; @@ -1370,6 +1438,74 @@ int intif_parse_RenamePetOk(int fd) return 0; } +//---------------------------------------------------------------- +// Homunculus recv packets [albator] + +int intif_parse_CreateHomunculus(int fd) +{ + struct map_session_data *sd = NULL; + RFIFOHEAD(fd); + + if((sd=map_id2sd(RFIFOL(fd,2)))==NULL || + sd->status.char_id != RFIFOL(fd,6)) + return 0; + + if(RFIFOW(fd,10)==1) + { + ShowInfo("Homunculus created successfully\n"); + sd->status.hom_id = sd->homunculus.hom_id = RFIFOL(fd,12); + merc_hom_recv_data(RFIFOL(fd,2), &sd->homunculus, 1) ; + } + else + { + ShowError("intif_parse_CreateHomunculus: failed to create homunculus\n"); + clif_displaymessage(sd->fd, "[debug] fail to create homunculus"); // display error message.. + } + + return 0; +} + +int intif_parse_RecvHomunculusData(int fd) +{ + struct s_homunculus sh; + int len; + + RFIFOHEAD(fd); + len=RFIFOW(fd,2); + + if(sizeof(struct s_homunculus)!=len-9) { + if(battle_config.etc_log) + ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len-9); + } + else{ + memcpy(&sh,RFIFOP(fd,9),sizeof(struct s_homunculus)); + merc_hom_recv_data(RFIFOL(fd,4),&sh,RFIFOB(fd,8)); + } + + return 0; + +} + +int intif_parse_SaveHomunculusOk(int fd) +{ + RFIFOHEAD(fd); + if(RFIFOB(fd,2) != 1) { + if(battle_config.error_log) + ShowError("homunculus data save failure\n"); + } + return 0; +} + +int intif_parse_DeleteHomunculusOk(int fd) +{ + RFIFOHEAD(fd); + if(RFIFOB(fd,2) != 1) { + if(battle_config.error_log) + ShowError("Homunculus data delete failure\n"); + } + + return 0; +} //----------------------------------------------------------------- // inter server‚ฉ‚็‚ฬ’สM // ƒGƒ‰[‚ช‚ ‚๊‚ฮ0(false)‚๐•ิ‚ท‚ฑ‚ฦ @@ -1398,7 +1534,7 @@ int intif_parse(int fd) } // ˆ—•ชŠ๒ switch(cmd){ - case 0x3800: + case 0x3800: if (RFIFOL(fd,4) == 0xFF000000) //Normal announce. clif_GMmessage(NULL,(char *) RFIFOP(fd,8),packet_len-8,0); else if (RFIFOL(fd,4) == 0xFE000000) //Main chat message [LuzZza] @@ -1445,6 +1581,10 @@ int intif_parse(int fd) case 0x3882: intif_parse_SavePetOk(fd); break; case 0x3883: intif_parse_DeletePetOk(fd); break; case 0x3884: intif_parse_RenamePetOk(fd); break; + case 0x3890: intif_parse_CreateHomunculus(fd); break; + case 0x3891: intif_parse_RecvHomunculusData(fd); break; + case 0x3892: intif_parse_SaveHomunculusOk(fd); break; + case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; default: if(battle_config.error_log) ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); diff --git a/src/map/intif.h b/src/map/intif.h index 38a2cace7..0351642b1 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -60,6 +60,13 @@ int intif_save_petdata(int account_id, struct s_pet *p); int intif_delete_petdata(int pet_id); int intif_rename_pet(struct map_session_data *sd, char *name); + +int intif_homunculus_create(int account_id, struct s_homunculus *sh); +int intif_homunculus_requestload(int account_id, int homun_id); +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh); +int intif_homunculus_requestdelete(int homun_id); + + int CheckForCharServer(void); #endif diff --git a/src/map/map.c b/src/map/map.c index 15a41f4c1..a34805997 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -39,6 +39,7 @@ #include "script.h" #include "guild.h" #include "pet.h" +#include "mercenary.h" //[orn] #include "atcommand.h" #include "charcommand.h" @@ -1664,6 +1665,8 @@ int map_quit(struct map_session_data *sd) { sd->state.waitingdisconnect = 1; if (sd->pd) unit_free(&sd->pd->bl); + if(sd->status.hom_id > 0 && sd->hd) //[orn] + merc_hom_delete(sd->hd, 0) ; unit_free(&sd->bl); chrif_save(sd,1); } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex] @@ -3886,6 +3889,7 @@ int do_init(int argc, char *argv[]) { do_init_storage(); do_init_skill(); do_init_pet(); + do_init_merc(); //[orn] do_init_npc(); do_init_unit(); #ifndef TXT_ONLY /* mail system [Valaris] */ diff --git a/src/map/map.h b/src/map/map.h index 75c6fe95a..a82f8bee1 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -485,6 +485,7 @@ struct party_data { struct npc_data; struct pet_db; +struct homunculus_db; //[orn] struct item_data; struct square; @@ -747,6 +748,7 @@ struct map_session_data { struct s_pet pet; struct pet_data *pd; + struct s_homunculus homunculus ; //[orn] struct homun_data *hd; // [blackhole89] struct{ @@ -932,26 +934,35 @@ struct homun_data { struct view_data *vd; struct status_data base_status, battle_status; struct status_change sc; - - char name[NAME_LENGTH]; - int id; - short class_; + struct homunculus_db *homunculusDB; //[orn] struct map_session_data *master; //pointer back to its master - short hunger_rate; + int hungry_timer; //[orn] - struct { - int id; //0 = none - int level; - } hskill[4]; //skills (max. 4 for now) int target_id,attacked_id; + short attackable; - short level; - short regenhp,regensp; - unsigned long exp,exp_next; - short skillpts; + int natural_heal_timer; //[orn] + int hp_sub,sp_sub; + int inchealhptick,inchealsptick; + int nhealhp,nhealsp,nshealhp,nshealsp,nsshealhp,nsshealsp; + short hp_loss_value; + short sp_loss_value; + short hp_loss_type; + short sp_gain_value; + short hp_gain_value; + int hp_loss_tick; + int sp_loss_tick; + int hp_loss_rate; + int sp_loss_rate; + unsigned int canregen_tick; + + + unsigned short regenhp,regensp; + unsigned long exp_next; + char blockskill[MAX_SKILL]; // [orn] }; struct pet_data { diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 8f599be43..49ebbcde1 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -32,29 +32,19 @@ #include "unit.h" #include "mercenary.h" -// Homunculus and future Mercenary system code go here [Celest] +#include "charsave.h" + typedef char char32[32]; -// everything below is crappy code by [blackhole89]. - -/* -HLIF_HEAL#ฤกภฏภว _ี+ๆ(ศ๚)# -HLIF_AVOID#+ไ+ศธวว# -HLIF_BRAIN#_๚_๖_๚# -HLIF_CHANGE#ธเล> ร_ภฮม๖# -HAMI_CASTLE#ฤ___ธ๗# -HAMI_DEFENCE#๗๐ฦๆ_บ# -HAMI_SKIN#_ฦ_ูธธฦ_ฟ๒ _บล_# -HAMI_BLOODLUST#บํทฏ๗ๅ ทฏ_บฦR# -HFLI_MOON#นRถ๓ภฬฦR# -HFLI_FLEET#วรธ_ น<บ๊# -HFLI_SPEED#ฟภน๖๗ๅ _บวว๗ๅ# -HFLI_SBR44#S.B.R.44# -HVAN_CAPRICE#ฤ<วมธR_บ# -HVAN_CHAOTIC#ฤ<ฟภฦ_ บ__ื๗๑_ว# -HVAN_INSTRUCT#ร_ภฮม๖ ภฮ_บฦRทฐ_ว# -HVAN_EXPLOSION#นูภฬฟภ ภอ_บวรทฮมฏ# -*/ +static int dirx[8]={0,-1,-1,-1,0,1,1,1}; //[orn] +static int diry[8]={1,1,0,-1,-1,-1,0,1}; //[orn] + +//Better equiprobability than rand()% [orn] +#define rand(a, b) a+(int) ((float)(b-a+1)*rand()/(RAND_MAX+1.0)) + +struct homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] +struct skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; + char32 merc_skillname[20] = {"NULL","HLIF_HEAL","HLIF_AVOID","HLIF_BRAIN","HLIF_CHANGE", "HAMI_CASTLE","HAMI_DEFENCE","HAMI_SKIN","HAMI_BLOODLUST", "HFLI_MOON","HFLI_FLEET","HFLI_SPEED","HFLI_SBR44", @@ -62,106 +52,509 @@ char32 merc_skillname[20] = {"NULL","HLIF_HEAL","HLIF_AVOID","HLIF_BRAIN","HLIF_ void merc_load_exptables(void); int mercskill_castend_id( int tid, unsigned int tick, int id,int data ); +static int merc_hom_hungry(int tid,unsigned int tick,int id,int data); int do_init_merc (void) { merc_load_exptables(); + memset(homunculus_db,0,sizeof(homunculus_db)); //[orn] + read_homunculusdb(); //[orn] return 0; } -static unsigned long hexptbl[126]; +static unsigned long hexptbl[MAX_LEVEL+1]; void merc_load_exptables(void) { - FILE *fl; - int i; + FILE *fp; + char line[1024]; + int i,k; + int j=0; + int lines; + char *filename[]={"exp_homun.txt","exp_homun2.txt"}; + char *str[32],*h,*nh; - fl=fopen("db/hexptbl.txt","rb"); - if(!fl) return; - - ShowInfo("reading db/hexptbl.txt\n"); - for(i=0;i<125;++i) - { - fscanf(fl,"%lu,",&(hexptbl[i])); + j = 0; + memset(hexptbl,0,sizeof(hexptbl)); + for(i=0;i<2;i++){ + sprintf(line, "%s/%s", db_path, filename[i]); + fp=fopen(line,"r"); + if(fp==NULL){ + if(i>0) + continue; + ShowError("can't read %s\n",line); + return ; + } + lines = 0; + while(fgets(line,sizeof(line)-1,fp) && j <= MAX_LEVEL){ + + lines++; + + if(line[0] == '/' && line[1] == '/') + continue; + + for(k=0,h=line;k<20;k++){ + if((nh=strchr(h,','))!=NULL){ + str[k]=h; + *nh=0; + h=nh+1; + } else { + str[k]=h; + h+=strlen(h); + } + } + + hexptbl[j]= atoi(str[0]); + + j++; + } + if (j >= MAX_LEVEL) + ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_HOMUNCULUS_CLASS); + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[i]); } - fclose(fl); + + return ; + } -char *merc_skill_get_name(int id) +char *merc_hom_skill_get_name(int id) { return merc_skillname[id-HM_SKILLBASE]; } void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp) { - clif_homuninfo(hd->master); + nullpo_retv(hd); + + if( hd->battle_status.hp < 0) + hd->battle_status.hp = 0; + if( hd->battle_status.sp < 0) + hd->battle_status.sp = 0; + hd->master->homunculus.hp = hd->battle_status.hp ; + hd->master->homunculus.sp = hd->battle_status.sp ; + clif_hominfo(hd->master,0); } -int merc_dead(struct homun_data *hd, struct block_list *src) +int merc_hom_dead(struct homun_data *hd, struct block_list *src) { - //dead lol - merc_save(hd); + hd->master->homunculus.intimacy -= 100 ; + hd->master->homunculus.alive = 0 ; + if(hd->master->homunculus.intimacy <= 0) { + merc_stop_walking(hd, 1); + merc_stop_attack(hd); + clif_emotion(&hd->master->bl, 23) ; //omg + merc_hom_delete(hd,1) ; + return 1 ; + } + clif_emotion(&hd->bl, 16) ; //wah + clif_emotion(&hd->master->bl, 28) ; //sob + merc_hom_delete(hd, 0); + return 3; //Remove it from map. } -void merc_skillup(struct map_session_data *sd,short skillnum) +int merc_hom_delete(struct homun_data *hd, int flag) +{ + nullpo_retr(0, hd); + // Delete homunculus + if ( flag&1 ) { //sabbath + intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ; + merc_stop_walking(hd, 1); + merc_stop_attack(hd); + clif_emotion(&hd->bl, 28) ; //sob + hd->master->status.hom_id = 0; + hd->master->homunculus.hom_id = 0; + chrif_save(hd->master,0); + } + else { + merc_save(hd) ; + } + if ( !unit_free(&hd->bl) ) + return 0 ; + aFree(hd); + + return 1; +} + +int merc_hom_calc_skilltree(struct map_session_data *sd) +{ + int i,id=0 ; + int j,f=1; + int c=0; + + nullpo_retr(0, sd); + c = sd->homunculus.class_ - 6001 ; + + for(i=0;i < MAX_SKILL_TREE && (id = hskill_tree[c][i].id) > 0;i++){ + if(sd->homunculus.hskill[id-HM_SKILLBASE-1].id) + continue; //Skill already known. + if(!battle_config.skillfree) { + for(j=0;j<5;j++) { + if( hskill_tree[c][i].need[j].id && + merc_hom_checkskill(sd,hskill_tree[c][i].need[j].id) < + hskill_tree[c][i].need[j].lv) { + f=0; + break; + } + } + } + if (f){ + sd->homunculus.hskill[id-HM_SKILLBASE-1].id = id ; + } + } + + return 0; +} + +int merc_hom_checkskill(struct map_session_data *sd,int skill_id) +{ + int i = skill_id - HM_SKILLBASE - 1 ; + if(sd == NULL) return 0; + + if(sd->homunculus.hskill[i].id == skill_id) + return (sd->homunculus.hskill[i].lv); + + return 0; +} + +static int merc_skill_tree_get_max(int id, int b_class){ + int i, skillid; + for(i=0;(skillid=hskill_tree[b_class-6001][i].id)>0;i++) + if (id == skillid) return hskill_tree[b_class-6001][i].max; + return skill_get_max (id); +} + +void merc_hom_skillup(struct homun_data *hd,int skillnum) +{ + int i = 0 ; + nullpo_retv(hd); + + if( hd->master->homunculus.vaporize == 0) { + i = skillnum - HM_SKILLBASE - 1 ; + if( hd->master->homunculus.skillpts > 0 && + hd->master->homunculus.hskill[i].id && + ( hd->master->homunculus.hskill[i].flag == 0 ) && //Don't allow raising while you have granted skills. [Skotlex] + hd->master->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->master->homunculus.class_) + ) + { + hd->master->homunculus.hskill[i].lv++ ; + hd->master->homunculus.skillpts-- ; + status_calc_homunculus(hd,1) ; + clif_homskillup(hd->master, skillnum) ; + clif_hominfo(hd->master,0) ; + clif_homskillinfoblock(hd->master) ; + } + } +} + +int merc_hom_levelup(struct homun_data *hd) { - nullpo_retv(sd); - nullpo_retv(sd->hd); - if(!sd->hd->skillpts) return; //no skill points left + int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ; + int growth_max_hp, growth_max_sp ; + char output[256] ; + + if (hd->master->homunculus.level == MAX_LEVEL) return 0 ; + + hd->master->homunculus.level++ ; + if ( ( (hd->master->homunculus.level) % 3 ) == 0 ) hd->master->homunculus.skillpts++ ; //1 skillpoint each 3 base level + + hd->master->homunculus.exp -= hd->exp_next ; + hd->exp_next = hexptbl[hd->master->homunculus.level - 1] ; + + if ( hd->homunculusDB->gmaxHP <= hd->homunculusDB->gminHP ) + growth_max_hp = hd->homunculusDB->gminHP ; + else + growth_max_hp = rand(hd->homunculusDB->gminHP, hd->homunculusDB->gmaxHP) ; + if ( hd->homunculusDB->gmaxSP <= hd->homunculusDB->gminSP ) + growth_max_sp = hd->homunculusDB->gminSP ; + else + growth_max_sp = rand(hd->homunculusDB->gminSP, hd->homunculusDB->gmaxSP) ; + if ( hd->homunculusDB->gmaxSTR <= hd->homunculusDB->gminSTR ) + growth_str = hd->homunculusDB->gminSTR ; + else + growth_str = rand(hd->homunculusDB->gminSTR, hd->homunculusDB->gmaxSTR) ; + if ( hd->homunculusDB->gmaxAGI <= hd->homunculusDB->gminAGI ) + growth_agi = hd->homunculusDB->gminAGI ; + else + growth_agi = rand(hd->homunculusDB->gminAGI, hd->homunculusDB->gmaxAGI) ; + if ( hd->homunculusDB->gmaxVIT <= hd->homunculusDB->gminVIT ) + growth_vit = hd->homunculusDB->gminVIT ; + else + growth_vit = rand(hd->homunculusDB->gminVIT, hd->homunculusDB->gmaxVIT) ; + if ( hd->homunculusDB->gmaxDEX <= hd->homunculusDB->gminDEX ) + growth_dex = hd->homunculusDB->gminDEX ; + else + growth_dex = rand(hd->homunculusDB->gminDEX, hd->homunculusDB->gmaxDEX) ; + if ( hd->homunculusDB->gmaxINT <= hd->homunculusDB->gminINT ) + growth_int = hd->homunculusDB->gminINT ; + else + growth_int = rand(hd->homunculusDB->gminINT, hd->homunculusDB->gmaxINT) ; + if ( hd->homunculusDB->gmaxLUK <= hd->homunculusDB->gminLUK ) + growth_luk = hd->homunculusDB->gminLUK ; + else + growth_luk = rand(hd->homunculusDB->gminLUK, hd->homunculusDB->gmaxLUK) ; + + hd->base_status.max_hp += growth_max_hp ; + hd->base_status.max_sp += growth_max_sp ; + hd->master->homunculus.max_hp = hd->base_status.max_hp ; + hd->master->homunculus.max_sp = hd->base_status.max_sp ; + hd->master->homunculus.str += growth_str ; + hd->master->homunculus.agi += growth_agi ; + hd->master->homunculus.vit += growth_vit ; + hd->master->homunculus.dex += growth_dex ; + hd->master->homunculus.int_ += growth_int ; + hd->master->homunculus.luk += growth_luk ; + + if ( battle_config.homunculus_show_growth ) { + sprintf(output, + "Growth : hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", growth_max_hp, growth_max_sp, growth_str/(float)10, growth_agi/(float)10, growth_vit/(float)10, growth_int/(float)10, growth_dex/(float)10, growth_luk/(float)10 ) ; + clif_disp_onlyself(hd->master,output,strlen(output)); + } + + hd->base_status.str = (int) (hd->master->homunculus.str / 10) ; + hd->base_status.agi = (int) (hd->master->homunculus.agi / 10) ; + hd->base_status.vit = (int) (hd->master->homunculus.vit / 10) ; + hd->base_status.dex = (int) (hd->master->homunculus.dex / 10) ; + hd->base_status.int_ = (int) (hd->master->homunculus.int_ / 10) ; + hd->base_status.luk = (int) (hd->master->homunculus.luk / 10) ; + + memcpy(&hd->battle_status, &hd->base_status, sizeof(struct status_data)) ; + status_calc_homunculus(hd,1) ; - sd->hd->hskill[(skillnum-HM_SKILLBASE)%4].id=skillnum; - sd->hd->hskill[(skillnum-HM_SKILLBASE)%4].level+=1; - sd->hd->skillpts-=1; + status_percent_heal(&hd->bl, 100, 100); +// merc_save(hd) ; //not necessary + + return 1 ; +} - clif_homuninfo(sd); - clif_homunskillinfoblock(sd); - clif_skillup(sd, skillnum); +int merc_hom_evolution(struct homun_data *hd) +{ + nullpo_retr(0, hd); - merc_save(sd->hd); + if(hd && hd->homunculusDB->evo_class) + { + hd->master->homunculus.class_ = hd->homunculusDB->evo_class; + hd->master->homunculus.vaporize = 1; + merc_stop_walking(hd, 1); + merc_stop_attack(hd); + merc_hom_delete(hd, 0) ; + merc_call_homunculus(hd->master); + clif_emotion(&hd->master->bl, 21) ; //no1 + clif_misceffect2(&hd->bl,568); + return 1 ; + } else { + clif_emotion(&hd->bl, 4) ; //swt + return 0 ; + } } -int merc_gainexp(struct homun_data *hd,int exp) +int merc_hom_gainexp(struct homun_data *hd,int exp) { - hd->exp += exp; + if(hd->master->homunculus.vaporize) + return 1; + + if( hd->exp_next == 0 ) { + hd->master->homunculus.exp = 0 ; + return 0; + } + + hd->master->homunculus.exp += exp; - if(hd->exp < hd->exp_next) + if(hd->master->homunculus.exp < hd->exp_next) { + clif_hominfo(hd->master,0); return 0; - //levelup + } + + //levelup do { - hd->exp-=hd->exp_next; - hd->exp_next=hexptbl[hd->level]; - hd->level++; + merc_hom_levelup(hd) ; } - while(hd->exp > hd->exp_next); + while(hd->master->homunculus.exp > hd->exp_next && hd->exp_next != 0 ); - clif_misceffect(&hd->bl,0); - status_calc_homunculus(hd,0); - status_percent_heal(&hd->bl, 100, 100); - clif_homuninfo(hd->master); + if( hd->exp_next == 0 ) { + hd->master->homunculus.exp = 0 ; + } + + status_calc_homunculus(hd,1); + clif_misceffect2(&hd->bl,568); + status_calc_homunculus(hd,1); return 0; } -void merc_heal(struct homun_data *hd,int hp,int sp) +int merc_hom_heal(struct homun_data *hd,int hp,int sp) { - clif_homuninfo(hd->master); + nullpo_retr(0, hd); + + if( hd->battle_status.max_hp < hd->battle_status.hp ) + hd->battle_status.hp = hd->battle_status.max_hp; + else if (hd->battle_status.hp <= 0) { + hd->battle_status.hp = 1; + } + + if( hd->battle_status.max_sp < hd->battle_status.sp ) + hd->battle_status.sp = hd->battle_status.max_sp; + else if (hd->battle_status.sp < 0) { + hd->battle_status.sp = 0; + } + + if ( (hd->battle_status.hp != hd->base_status.hp) || + (hd->battle_status.sp != hd->base_status.sp) ) + { + clif_hominfo(hd->master,0); + } + hd->master->homunculus.hp = hd->base_status.hp = hd->battle_status.hp ; + hd->master->homunculus.sp = hd->base_status.sp = hd->battle_status.sp ; + + return 1; } -#ifndef TXT_ONLY -void merc_save(struct homun_data *hd) +static unsigned int natural_heal_prev_tick,natural_heal_diff_tick; +static void merc_natural_heal_hp(struct homun_data *hd) { - sprintf(tmp_sql, "UPDATE `homunculus` SET `class`='%d',`name`='%s',`level`='%d',`exp`='%lu',`hunger`='%d',`hp`='%u',`sp`='%u',`skill1lv`='%d',`skill2lv`='%d',`skill3lv`='%d',`skill4lv`='%d',`skillpts`='%d' WHERE `id` = '%d'", - hd->class_,hd->name,hd->level,hd->exp,hd->hunger_rate, - hd->battle_status.hp,hd->battle_status.sp, - hd->hskill[0].level,hd->hskill[1].level,hd->hskill[2].level,hd->hskill[3].level, - hd->skillpts,hd->id); - if(mysql_query(&mmysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + + nullpo_retv(hd); + +// ShowDebug("merc_natural_heal_hp (1) : homunculus = %s | hd->ud.walktimer = %d |\n", hd->name, hd->ud.walktimer) ; + if(hd->ud.walktimer == -1) { + hd->inchealhptick += natural_heal_diff_tick; + } + else { + hd->inchealhptick = 0; return; } + +// ShowDebug("merc_natural_heal_hp (2) : homunculus = %s | hd->regenhp = %d |\n", hd->name, hd->regenhp) ; + if (hd->battle_status.hp != hd->battle_status.max_hp) { + if ((unsigned int)status_heal(&hd->bl, hd->regenhp, 0, 1) < hd->regenhp) + { //At full. + hd->inchealhptick = 0; + return; + } + } + + return; +} + +static void merc_natural_heal_sp(struct homun_data *hd) +{ + + nullpo_retv(hd); + +// ShowDebug("merc_natural_heal_sp (1) : homunculus = %s | hd->regensp = %d |\n", hd->name, hd->regensp) ; + if (hd->battle_status.sp != hd->battle_status.max_sp) { + if ((unsigned int)status_heal(&hd->bl, 0, hd->regensp, 1) < hd->regensp) + { //At full. + hd->inchealsptick = 0; + return; + } + } + + return; +} + +static void merc_bleeding (struct homun_data *hd) +{ + int hp = 0, sp = 0; + + if (hd->hp_loss_value > 0) { + hd->hp_loss_tick += natural_heal_diff_tick; + if (hd->hp_loss_tick >= hd->hp_loss_rate) { + do { + hp += hd->hp_loss_value; + hd->hp_loss_tick -= hd->hp_loss_rate; + } while (hd->hp_loss_tick >= hd->hp_loss_rate); + hd->hp_loss_tick = 0; + } + } + + if (hd->sp_loss_value > 0) { + hd->sp_loss_tick += natural_heal_diff_tick; + if (hd->sp_loss_tick >= hd->sp_loss_rate) { + do { + sp += hd->sp_loss_value; + hd->sp_loss_tick -= hd->sp_loss_rate; + } while (hd->sp_loss_tick >= hd->sp_loss_rate); + hd->sp_loss_tick = 0; + } + } + + if (hp > 0 || sp > 0) + status_zap(&hd->bl, hp, sp); + + return; +} + +/*========================================== + * HP/SP natural heal + *------------------------------------------ + */ + +//static int merc_natural_heal_sub(struct homun_data *hd,va_list ap) { +static int merc_natural_heal_sub(struct homun_data *hd,int tick) { +// int tick; + + nullpo_retr(0, hd); +// tick = va_arg(ap,int); + +// -- moonsoul (if conditions below altered to disallow natural healing if under berserk status) + if ( hd && ( status_isdead(&hd->bl) || + ( ( hd->sc.count ) && + ( (hd->sc.data[SC_POISON].timer != -1 ) || ( hd->sc.data[SC_BLEEDING].timer != -1 ) ) + ) ) + ) { //Cannot heal neither natural or special. + hd->hp_sub = hd->inchealhptick = 0; + hd->sp_sub = hd->inchealsptick = 0; + } else { + if ( DIFF_TICK (tick, hd->canregen_tick)<0 ) { + hd->hp_sub = hd->inchealhptick = 0; + hd->sp_sub = hd->inchealsptick = 0; + } else { //natural heal + merc_natural_heal_hp(hd); + merc_natural_heal_sp(hd); + hd->canregen_tick = tick; + } + } + if (hd->hp_loss_value > 0 || hd->sp_loss_value > 0) + merc_bleeding(hd); + else + hd->hp_loss_tick = hd->sp_loss_tick = 0; + + return 0; +} + +/*========================================== + * orn + *------------------------------------------ + */ +int merc_natural_heal(int tid,unsigned int tick,int id,int data) +{ + struct map_session_data *sd; + + sd=map_id2sd(id); + + nullpo_retr(0, sd); + + if(sd->homunculus.vaporize) + return 1; + + if(sd && sd->hd) { + natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick); + merc_natural_heal_sub(sd->hd, tick); + + natural_heal_prev_tick = tick; + sd->hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0); + } + return 0; +} + +#ifndef TXT_ONLY +void merc_save(struct homun_data *hd) +{ + intif_homunculus_requestsave(hd->master->status.account_id, &hd->master->homunculus) ; + } #else void merc_save(struct homun_data *hd) @@ -170,151 +563,581 @@ void merc_save(struct homun_data *hd) } #endif -static void merc_load_sub(struct homun_data *hd, struct map_session_data *sd) +static int merc_calc_pos(struct homun_data *hd,int tx,int ty,int dir) //[orn] +{ + int x,y,dx,dy; + int i,k; + + nullpo_retr(0, hd); + + hd->ud.to_x = tx; + hd->ud.to_y = ty; + + if(dir < 0 || dir >= 8) + return 1; + + dx = -dirx[dir]*2; + dy = -diry[dir]*2; + x = tx + dx; + y = ty + dy; + if(!unit_can_reach_pos(&hd->bl,x,y,0)) { + if(dx > 0) x--; + else if(dx < 0) x++; + if(dy > 0) y--; + else if(dy < 0) y++; + if(!unit_can_reach_pos(&hd->bl,x,y,0)) { + for(i=0;i<12;i++) { + k = rand(1, 8); +// k = rand()%8; + dx = -dirx[k]*2; + dy = -diry[k]*2; + x = tx + dx; + y = ty + dy; + if(unit_can_reach_pos(&hd->bl,x,y,0)) + break; + else { + if(dx > 0) x--; + else if(dx < 0) x++; + if(dy > 0) y--; + else if(dy < 0) y++; + if(unit_can_reach_pos(&hd->bl,x,y,0)) + break; + } + } + if(i>=12) { + x = tx; + y = ty; + if(!unit_can_reach_pos(&hd->bl,x,y,0)) + return 1; + } + } + } + hd->ud.to_x = x; + hd->ud.to_y = y; + return 0; +} + +int merc_menu(struct map_session_data *sd,int menunum) +{ + nullpo_retr(0, sd); + if (sd->hd == NULL) + return 1; + + switch(menunum) { + case 0: + merc_hom_food(sd, sd->hd); + break; + case 1: + merc_hom_food(sd, sd->hd); + break; + case 2: + merc_hom_delete(sd->hd, 1); + break; + default: + ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; + break; + } + return 0; +} + +int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) +{ + int i, k, emotion; + + if(hd->master->homunculus.vaporize) + return 1 ; + + k=hd->homunculusDB->foodID; + i=pc_search_inventory(sd,k); + if(i < 0) { + clif_hom_food(sd,k,0); + return 1; + } + pc_delitem(sd,i,1,0); + + if ( hd->master->homunculus.hunger >= 91 ) { + hd->master->homunculus.intimacy -= 50 ; + emotion = 16 ; + } else if ( hd->master->homunculus.hunger >= 76 ) { + hd->master->homunculus.intimacy -= 30 ; + emotion = 19 ; + } else if ( hd->master->homunculus.hunger >= 26 ) { + hd->master->homunculus.intimacy += 80 ; + emotion = 2 ; + } else if ( hd->master->homunculus.hunger >= 11 ) { + hd->master->homunculus.intimacy += 100 ; + emotion = 2 ; + } else { + hd->master->homunculus.intimacy += 50 ; + emotion = 2 ; + } + if(hd->master->homunculus.intimacy > 100000) + hd->master->homunculus.intimacy = 100000; + if(hd->master->homunculus.intimacy < 0) + hd->master->homunculus.intimacy = 0 ; + + emotion = 5 ; // Thanks + hd->master->homunculus.hunger += 10; //dunno increase value for each food + if(hd->master->homunculus.hunger > 100) + hd->master->homunculus.hunger = 100; + + clif_emotion(&hd->bl,emotion) ; + clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); + clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); + clif_hom_food(sd,hd->homunculusDB->foodID,1); + + return 0; +} + +static int merc_hom_hungry(int tid,unsigned int tick,int id,int data) +{ + struct map_session_data *sd; + struct homun_data *hd; + + sd=map_id2sd(id); + if(!sd) + return 1; + + if(!sd->status.hom_id || !sd->hd) + return 1; + + hd = sd->hd; + if(hd->hungry_timer != tid){ + if(battle_config.error_log) + ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid); + return 0 ; + } + hd->master->homunculus.hunger-- ; + if(hd->master->homunculus.hunger >= 0 && hd->master->homunculus.hunger <= 10) { + clif_emotion(&hd->bl, 6) ; //an + } + if(hd->master->homunculus.hunger == 25) { + clif_emotion(&hd->bl, 20) ; //hmm + } + if(hd->master->homunculus.hunger == 75) { + clif_emotion(&hd->bl, 33) ; //ok + } + if(hd->master->homunculus.hunger < 0) { + hd->master->homunculus.hunger = 0; + hd->master->homunculus.intimacy -= 100 ; + clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); + if ( hd->master->homunculus.intimacy <= 0 ) { + merc_stop_walking(hd, 1); + merc_stop_attack(hd); + clif_emotion(&hd->master->bl, 23) ; //omg + merc_hom_delete(hd,1) ; + } + return 0 ; + } else { + clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); + + hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator + return 1 ; + } + + +} + +int merc_hom_hungry_timer_delete(struct homun_data *hd) +{ + nullpo_retr(0, hd); + if(hd->hungry_timer != -1) { + delete_timer(hd->hungry_timer,merc_hom_hungry); + hd->hungry_timer = -1; + } + + return 1; +} + +int merc_natural_heal_timer_delete(struct homun_data *hd) +{ + nullpo_retr(0, hd); + if(hd->natural_heal_timer != -1) { + delete_timer(hd->natural_heal_timer,merc_natural_heal); + hd->natural_heal_timer = -1; + } + + return 1; +} + +int search_homunculusDB_index(int key,int type) +{ + int i; + + for(i=0;istatus.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); + + i = search_homunculusDB_index(sd->homunculus.class_,HOMUNCULUS_CLASS); + if(i < 0) { + sd->status.hom_id = 0; + return 1; + } + sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data)); + hd->homunculusDB = &homunculus_db[i]; + merc_calc_pos(hd,sd->bl.x,sd->bl.y,sd->ud.dir); + hd->bl.x = hd->ud.to_x; + hd->bl.y = hd->ud.to_y; + hd->master = sd; + + sd->status.hom_id = sd->homunculus.hom_id ; + hd->bl.m=sd->bl.m; hd->bl.x=sd->bl.x; - hd->bl.y=sd->bl.y; + hd->bl.y=sd->bl.y - 1 ; + hd->bl.subtype = MONS; hd->bl.type=BL_HOMUNCULUS; hd->bl.id= npc_get_new_npc_id(); hd->bl.prev=NULL; hd->bl.next=NULL; + hd->exp_next=hexptbl[hd->master->homunculus.level - 1]; + hd->ud.attacktimer=-1; + hd->ud.attackabletime=gettick(); + hd->target_id = 0 ; + hd->attackable = 1 ; - status_set_viewdata(&hd->bl, hd->class_); + for(i=0;isc.data[i].timer=-1; + hd->sc.data[i].val1 = hd->sc.data[i].val2 = hd->sc.data[i].val3 = hd->sc.data[i].val4 = 0; + } + + hd->base_status.hp = hd->master->homunculus.hp ; + hd->base_status.max_hp = hd->master->homunculus.max_hp ; + hd->base_status.sp = hd->master->homunculus.sp ; + hd->base_status.max_sp = hd->master->homunculus.max_sp ; + hd->base_status.str = (int) (hd->master->homunculus.str / 10) ; + hd->base_status.agi = (int) (hd->master->homunculus.agi / 10) ; + hd->base_status.vit = (int) (hd->master->homunculus.vit / 10) ; + hd->base_status.int_ = (int) (hd->master->homunculus.int_ / 10) ; + hd->base_status.dex = (int) (hd->master->homunculus.dex / 10) ; + hd->base_status.luk = (int) (hd->master->homunculus.luk / 10) ; + + memcpy(&hd->battle_status, &hd->base_status, sizeof(struct status_data)) ; + + status_set_viewdata(&hd->bl, hd->master->homunculus.class_); status_change_init(&hd->bl); + hd->ud.dir = sd->ud.dir; unit_dataset(&hd->bl); - + map_addiddb(&hd->bl); - status_calc_homunculus(hd,1); //this function will have more sense later on + status_calc_homunculus(hd,1); + //timer + hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); + natural_heal_prev_tick = gettick(); + hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0); + + return 0; } -#ifndef TXT_ONLY -void merc_load(struct map_session_data *sd) +// FIX call_homunculus [albator] +int merc_call_homunculus(struct map_session_data *sd) { - struct homun_data *hd; - sd->hd=NULL; - - sprintf(tmp_sql, "SELECT `id`,`class`,`name`,`level`,`exp`,`hunger`,`hp`,`sp`,`skill1lv`,`skill2lv`,`skill3lv`,`skill4lv`,`skillpts` FROM `homunculus` WHERE `char_id` = '%d'", sd->char_id); - if(mysql_query(&mmysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return; + int class_ = 0 ; + nullpo_retr(0, sd); + + // call vaporized homunculus [albator] + if(sd->homunculus.vaporize == 1) + { + sd->homunculus.vaporize = 0; + merc_hom_data_init(sd); + + if ( sd->homunculus.alive && sd->hd && sd->bl.prev != NULL) { + map_addblock(&sd->hd->bl); + clif_spawn(&sd->hd->bl); + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,1); + clif_hominfo(sd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif_homskillinfoblock(sd); + } + // save + merc_save(sd->hd); + return 1; + } - sql_res = mysql_store_result(&mmysql_handle); - if(!sql_res) - return; + if ( sd->status.hom_id ) { + return merc_hom_recv_data(sd->status.account_id, &sd->homunculus, 1 ) ; + } else { + class_ = 6000 + rand(1, 8) ; + return merc_create_homunculus(sd, class_) ; + } + + +} +// Albator +// Recv data of an homunculus after it loading +int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag) +{ + struct map_session_data *sd ; - if(mysql_num_rows(sql_res) <= 0){ - mysql_free_result(sql_res); - return; //no homunculus for this char + sd = map_id2sd(account_id); + if(sd == NULL) + return 0; + + if(flag == 0) { + sd->status.hom_id = 0; + return 0; } - sql_row = mysql_fetch_row(sql_res); + memcpy(&sd->homunculus, sh, sizeof(struct s_homunculus)); + - //dummy code - hd=(struct homun_data *) aCalloc(1, sizeof(struct homun_data)); - sd->hd=hd; //pointer from master to homunculus - memset(hd,0,sizeof(struct homun_data)); - hd->master=sd; //pointer from homunculus to master - hd->id=atoi(sql_row[0]); - hd->class_=atoi(sql_row[1]); - hd->level=atoi(sql_row[3]); - hd->battle_status.hp=atoi(sql_row[6]); - hd->battle_status.sp=atoi(sql_row[7]); - hd->exp=atoi(sql_row[4]); - hd->hunger_rate=atoi(sql_row[5]); - hd->hskill[0].level=atoi(sql_row[8]); - hd->hskill[1].level=atoi(sql_row[9]); - hd->hskill[2].level=atoi(sql_row[10]); - hd->hskill[3].level=atoi(sql_row[11]); - hd->skillpts=atoi(sql_row[12]); - hd->exp_next=hexptbl[hd->level-1]; - strncpy(hd->name,sql_row[2],NAME_LENGTH); - mysql_free_result(sql_res); - merc_load_sub(hd, sd); -} -#else -void merc_load(struct map_session_data *sd) + if ( flag == 2 ) { + sh->hp = 1 ; + sd->homunculus.alive = 1 ; + } + if(sd->homunculus.alive && sh->vaporize!=1) + { + merc_hom_data_init(sd); + + if ( sd->hd && sd->bl.prev != NULL) { + map_addblock(&sd->hd->bl); + clif_spawn(&sd->hd->bl); + clif_hominfo(sd,1); + clif_hominfo(sd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif_homskillinfoblock(sd); + clif_hominfo(sd,0); + clif_send_homdata(sd,SP_ACK,0); + } + } + + return 1; + +} + +int merc_create_homunculus(struct map_session_data *sd, int class_) { - struct homun_data *hd; - int id,charid,class_,level,exp,hunger,hp,sp; - char name[24]; - FILE *fl=fopen("save/homunculus.txt","r"); - sd->hd=NULL; - - if(!fl) return; //Unable to open file. - ShowInfo("Looking up Homunculus for %d...\n",sd->char_id); - do { - fscanf(fl,"%d,%d,%d,%s ,%d,%d,%d,%d,%d\n",&id,&charid,&class_,name,&level,&exp,&hunger,&hp,&sp); - ShowInfo("%d",charid); - if(charid==sd->char_id) break; - } while(charid!=0); - if (!charid) - return; //none found - ShowInfo("found it!\n"); + int i=0 ; + + nullpo_retr(1, sd); + + i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); + if(i < 0) { + sd->status.hom_id = 0; + return 0; + } + memcpy(sd->homunculus.name, homunculus_db[i].name, NAME_LENGTH-1); + + sd->homunculus.class_ = class_; + sd->homunculus.level=1; + sd->homunculus.intimacy = 21; + sd->homunculus.hunger = 32; + sd->homunculus.exp = 0; + sd->homunculus.rename_flag = 0; + sd->homunculus.skillpts = 0; + sd->homunculus.char_id = sd->status.char_id; + sd->homunculus.vaporize = 0; // albator + sd->homunculus.alive = 1 ; - //dummy code - hd=(struct homun_data *) aCalloc(1, sizeof(struct homun_data)); - sd->hd=hd; //pointer from master to homunculus - memset(hd,0,sizeof(struct homun_data)); - hd->master=sd; //pointer from homunculus to master - hd->id=id; - hd->class_=class_; - hd->level=level; - hd->exp=exp; - hd->hunger_rate=hunger; - hd->battle_status.hp=hp; - hd->battle_status.sp=sp; - hd->exp_next=hexptbl[hd->level-1]; - strncpy(hd->name,name,NAME_LENGTH); - merc_load_sub(hd, sd); -} -#endif - -int merc_create_homunculus(struct map_session_data *sd,int id,int m,int x,int y) -{ -/* struct homun_data *hd; - //dummy code - hd=(struct homun_data *) aCalloc(1, sizeof(struct homun_data)); - sd->hd=hd; //pointer from master to homunculus - memset(hd,0,sizeof(struct homun_data)); - hd->master=sd; //pointer from homunculus to master - hd->class_=id; - hd->speed=0x96; - hd->level=1; - hd->bl.m=m; - hd->bl.x=hd->to_x=x; - hd->bl.y=hd->to_y=y; - hd->to_x+=2; - hd->bl.type=BL_HOMUNCULUS; - hd->bl.id= npc_get_new_npc_id(); - hd->bl.prev=NULL; - hd->bl.next=NULL; - map_addiddb(&hd->bl); - hd->max_hp=500; - hd->hp=400; - hd->max_sp=300; - hd->sp=200; - hd->atk=15; - hd->matk=2; - hd->hit=3; - hd->crit=90; - hd->def=5; - hd->mdef=6; - hd->flee=7; - hd->exp=10; - hd->exp_next=100; - hd->hunger_rate=32; - hd->walktimer=-1; - memcpy(hd->name,"Homunculus\0",11); - merc_calc_stats(hd); - hd->attackabletime=0; - - merc_save(hd); - - clif_spawnhomun(hd); - clif_homunack(sd); - clif_homuninfo(sd); - clif_homuninfo(sd);*/ // send this x2. dunno why, but kRO does that [blackhole89] + sd->homunculus.hp = 10 ; + sd->homunculus.sp = 0 ; + sd->homunculus.max_hp = homunculus_db[i].basemaxHP ; + sd->homunculus.max_sp = homunculus_db[i].basemaxSP ; + sd->homunculus.str = homunculus_db[i].baseSTR ; + sd->homunculus.agi = homunculus_db[i].baseAGI ; + sd->homunculus.vit = homunculus_db[i].baseVIT; + sd->homunculus.int_ = homunculus_db[i].baseINT ; + sd->homunculus.dex = homunculus_db[i].baseDEX ; + sd->homunculus.luk = homunculus_db[i].baseLUK ; + sd->homunculus.str *= 10 ; + sd->homunculus.agi *= 10 ; + sd->homunculus.vit *= 10 ; + sd->homunculus.int_ *= 10 ; + sd->homunculus.dex *= 10 ; + sd->homunculus.luk *= 10 ; + + for(i=0;ihomunculus.hskill[i].id = sd->homunculus.hskill[i].lv = sd->homunculus.hskill[i].flag = 0; + + intif_homunculus_create(sd->status.account_id, &sd->homunculus); // request homunculus creation + + return 1; +} + +int merc_hom_revive(struct map_session_data *sd, int per) +{ + nullpo_retr(0, sd); + + sd->homunculus.alive = 1; + merc_hom_data_init(sd); + + if ( sd->hd && sd->bl.prev != NULL) { + sd->homunculus.hp = sd->hd->base_status.hp = sd->hd->battle_status.hp = 1 ; + status_heal(&sd->hd->bl, sd->homunculus.max_hp*per/100, 0, 1) ; + map_addblock(&sd->hd->bl); + clif_spawn(&sd->hd->bl); + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,1); + clif_hominfo(sd,0); + clif_homskillinfoblock(sd); + clif_specialeffect(&sd->hd->bl,77,AREA) ; //resurrection angel + } + + return 1 ; +} + +int read_homunculusdb() +{ + FILE *fp; + char line[1024], *p; + int i,k,l; + int j=0; + int c = 0 ; + int lines; + char *filename[]={"homunculus_db.txt","homunculus_db2.txt"}; + char *str[36],*h,*nh; + + + j = 0; + memset(homunculus_db,0,sizeof(homunculus_db)); + for(i=0;i<2;i++){ + sprintf(line, "%s/%s", db_path, filename[i]); + fp=fopen(line,"r"); + if(fp==NULL){ + if(i>0) + continue; + ShowError("can't read %s\n",line); + return -1; + } + lines = 0; + while(fgets(line,sizeof(line)-1,fp) && j < MAX_HOMUNCULUS_CLASS){ + + lines++; + + if(line[0] == '/' && line[1] == '/') + continue; + + for(k=0,h=line;k<36;k++){ + if((nh=strchr(h,','))!=NULL){ + str[k]=h; + *nh=0; + h=nh+1; + } else { + str[k]=h; + h+=strlen(h); + } + } + + if(atoi(str[0]) < 6001 || atoi(str[0]) > 6099) + continue; + + //Class,Homunculus,HP,SP,ATK,MATK,HIT,CRI,DEF,MDEF,FLEE,ASPD,STR,AGI,VIT,INT,DEX,LUK + homunculus_db[j].class_ = atoi(str[0]); + memcpy(homunculus_db[j].name,str[1],NAME_LENGTH-1); + homunculus_db[j].basemaxHP = atoi(str[2]); + homunculus_db[j].basemaxSP = atoi(str[3]); + homunculus_db[j].baseSTR = atoi(str[4]); + homunculus_db[j].baseAGI = atoi(str[5]); + homunculus_db[j].baseVIT = atoi(str[6]); + homunculus_db[j].baseINT = atoi(str[7]); + homunculus_db[j].baseDEX = atoi(str[8]); + homunculus_db[j].baseLUK = atoi(str[9]); + homunculus_db[j].baseIntimacy = atoi(str[10]); + homunculus_db[j].baseHungry = atoi(str[11]); + homunculus_db[j].hungryDelay = atoi(str[12]); + homunculus_db[j].foodID = atoi(str[13]); + homunculus_db[j].gminHP = atoi(str[14]); + homunculus_db[j].gmaxHP = atoi(str[15]); + homunculus_db[j].gminSP = atoi(str[16]); + homunculus_db[j].gmaxSP = atoi(str[17]); + homunculus_db[j].gminSTR = atoi(str[18]); + homunculus_db[j].gmaxSTR = atoi(str[19]); + homunculus_db[j].gminAGI = atoi(str[20]); + homunculus_db[j].gmaxAGI = atoi(str[21]); + homunculus_db[j].gminVIT = atoi(str[22]); + homunculus_db[j].gmaxVIT = atoi(str[23]); + homunculus_db[j].gminINT = atoi(str[24]); + homunculus_db[j].gmaxINT = atoi(str[25]); + homunculus_db[j].gminDEX = atoi(str[26]); + homunculus_db[j].gmaxDEX = atoi(str[27]); + homunculus_db[j].gminLUK = atoi(str[28]); + homunculus_db[j].gmaxLUK = atoi(str[29]); + homunculus_db[j].evo_class = atoi(str[30]); + homunculus_db[j].baseASPD = atoi(str[31]); + homunculus_db[j].size = atoi(str[32]); + homunculus_db[j].race = atoi(str[33]); + homunculus_db[j].element = atoi(str[34]); + homunculus_db[j].accessID = atoi(str[35]); + + 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]); + } + + 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; + } + + while(fgets(line, sizeof(line)-1, fp)){ + char *split[50]; + int f=0, m=3; + if(line[0]=='/' && line[1]=='/') + continue; + for(j=0,p=line;j<14 && p;j++){ + split[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if(j<13) + continue; + if (j == 14) { + f=1; // MinJobLvl has been added + m++; + } + // check for bounds [celest] + c = atoi(split[0]) ; + l = c - 6001 ; + if ( l >= MAX_HOMUNCULUS_CLASS ) + continue; + k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] + for(j = 0; j < MAX_SKILL_TREE && hskill_tree[l][j].id && hskill_tree[l][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, l); + continue; + } + hskill_tree[l][j].id=k; + hskill_tree[l][j].max=atoi(split[2]); + if (f) hskill_tree[l][j].joblv=atoi(split[3]); + + for(k=0;k<5;k++){ + hskill_tree[l][j].need[k].id=atoi(split[k*2+m]); + hskill_tree[l][j].need[k].lv=atoi(split[k*2+m+1]); + } + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","homun_skill_tree.txt"); + + return 0; } diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 84b578245..b55cba8e1 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -1,13 +1,78 @@ // Homunculus and future Mercenary system code go here [Celest] +// implemented by [orn] +struct homunculus_db { + int class_ ; + char name[NAME_LENGTH]; + int basemaxHP ; + int basemaxSP ; + int baseSTR ; + int baseAGI ; + int baseVIT ; + int baseINT ; + int baseDEX ; + int baseLUK ; + int foodID ; + int baseIntimacy ; + short baseHungry ; + long hungryDelay ; + int gminHP ; + int gmaxHP ; + int gminSP ; + int gmaxSP ; + int gminSTR ; + int gmaxSTR ; + int gminAGI ; + int gmaxAGI ; + int gminVIT ; + int gmaxVIT ; + int gminINT ; + int gmaxINT ; + int gminDEX ; + int gmaxDEX ; + int gminLUK ; + int gmaxLUK ; + int evo_class ; + int baseASPD ; + //short size ; + //short race ; + //short element ; + unsigned char element, race, size; // albator + int accessID ; +}; +extern struct homunculus_db homuncumlus_db[MAX_HOMUNCULUS_CLASS]; +enum { HOMUNCULUS_CLASS, HOMUNCULUS_FOOD }; +enum { + SP_ACK = 0x00, + SP_INTIMATE = 0x100, + SP_HUNGRY = 0x200 +}; int do_init_merc (void); +int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator +void merc_load_sub(struct homun_data *hd, struct map_session_data *sd); void merc_load_exptables(void); -char *merc_skill_get_name(int id); +char *merc_hom_skill_get_name(int id); void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp); -int merc_dead(struct homun_data *hd, struct block_list *src); -void merc_skillup(struct map_session_data *sd,short skillnum); -int merc_gainexp(struct homun_data *hd,int exp); -void merc_heal(struct homun_data *hd,int hp,int sp); +int merc_hom_dead(struct homun_data *hd, struct block_list *src); +void merc_hom_skillup(struct homun_data *hd,int skillnum); +int merc_hom_calc_skilltree(struct map_session_data *sd) ; +int merc_hom_checkskill(struct map_session_data *sd,int skill_id) ; +int merc_hom_gainexp(struct homun_data *hd,int exp) ; +int merc_hom_levelup(struct homun_data *hd) ; +int merc_hom_evolution(struct homun_data *hd) ; +int merc_hom_heal(struct homun_data *hd,int hp,int sp); +int merc_hom_delete(struct homun_data *hd, int flag) ; +int merc_hom_revive(struct map_session_data *sd, int per); void merc_save(struct homun_data *hd); -void merc_load(struct map_session_data *sd); -int merc_create_homunculus(struct map_session_data *sd,int id,int m,int x,int y); +int merc_call_homunculus(struct map_session_data *sd); +int merc_create_homunculus(struct map_session_data *sd, int class_); +int search_homunculusDB_index(int key,int type); +int merc_menu(struct map_session_data *sd,int menunum); +int merc_hom_food(struct map_session_data *sd, struct homun_data *hd); +int merc_hom_hungry_timer_delete(struct homun_data *hd); +int merc_natural_heal_timer_delete(struct homun_data *hd); +#define merc_checkoverhp(hd) (hd->battle_status.hp == hd->battle_status.max_hp) +#define merc_checkoversp(hd) (hd->battle_status.sp == hd->battle_status.max_sp) +#define merc_stop_walking(hd, type) { if((hd)->ud.walktimer != -1) unit_stop_walking(&(hd)->bl, type); } +#define merc_stop_attack(hd) { if((hd)->ud.attacktimer != -1) unit_stop_attack(&(hd)->bl); hd->ud.target = 0; } +int read_homunculusdb(void); diff --git a/src/map/mob.c b/src/map/mob.c index 147b424cd..3e425f595 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -22,6 +22,7 @@ #include "pc.h" #include "status.h" #include "mob.h" +#include "mercenary.h" //[orn] #include "guild.h" #include "itemdb.h" #include "skill.h" @@ -761,6 +762,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) */ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) { + struct map_session_data *sd; struct mob_data *md; struct block_list **target; int dist; @@ -783,9 +785,15 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) switch (bl->type) { case BL_PC: + { if (((TBL_PC*)bl)->state.gangsterparadise && !(status_get_mode(&md->bl)&MD_BOSS)) return 0; //Gangster paradise protection. + sd = (TBL_PC*)bl; //[orn] monster target homunculus while hunting + if (sd->hd && sd->homunculus.alive && (distance_bl(&md->bl, &sd->hd->bl ) < md->db->range2 ) ) // + return 0; //Gangster paradise protection. + } + case BL_HOMUNCULUS: //[orn] case BL_MOB: if((dist=distance_bl(&md->bl, bl)) < md->db->range2 && ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && @@ -824,6 +832,7 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) switch (bl->type) { case BL_PC: + case BL_HOMUNCULUS: //[orn] case BL_MOB: if(check_distance_bl(&md->bl, bl, md->status.rhw.range) && battle_check_range (&md->bl, bl, md->status.rhw.range) @@ -1167,13 +1176,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) (mode&MD_ANGRY && md->state.skillstate == MSS_FOLLOW) ) { map_foreachinrange (mob_ai_sub_hard_activesearch, &md->bl, - view_range, md->special_state.ai?BL_CHAR:BL_PC, md, &tbl); + view_range, md->special_state.ai?BL_CHAR:BL_PC|BL_HOMUNCULUS, md, &tbl); //[orn] if(!tbl && mode&MD_ANGRY && !md->state.aggressive) md->state.aggressive = 1; //Restore angry state when no targets are visible. } else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) { search_size = view_rangestatus.rhw.range ? view_range:md->status.rhw.range; map_foreachinrange (mob_ai_sub_hard_changechase, &md->bl, - search_size, (md->special_state.ai?BL_CHAR:BL_PC), md, &tbl); + search_size, (md->special_state.ai?BL_CHAR:BL_PC|BL_HOMUNCULUS), md, &tbl); //[orn] } if (tbl) @@ -1596,7 +1605,16 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) case BL_PC: { struct map_session_data *sd = (TBL_PC*)src; - id = sd->status.char_id; +// id = sd->status.char_id; + id = sd->bl.id; //[orn] + if(rand()%1000 < 1000/md->attacked_players) + md->attacked_id = src->id; + break; + } + case BL_HOMUNCULUS: //[orn] + { + struct homun_data *hd = (TBL_HOMUNCULUS*)src; + id = hd->bl.id; if(rand()%1000 < 1000/md->attacked_players) md->attacked_id = src->id; break; @@ -1605,7 +1623,8 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) { struct pet_data *pd = (TBL_PET*)src; if (battle_config.pet_attack_exp_to_master) { - id = pd->msd->status.char_id; +// id = pd->msd->status.char_id; + id = pd->msd->bl.id; //[orn] damage=(damage*battle_config.pet_attack_exp_rate)/100; //Modify logged damage accordingly. } //Let mobs retaliate against the pet's master [Skotlex] @@ -1618,7 +1637,8 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) struct mob_data* md2 = (TBL_MOB*)src; if(md2->special_state.ai && md2->master_id) { struct map_session_data* msd = map_id2sd(md2->master_id); - if (msd) id = msd->status.char_id; +// if (msd) id = msd->status.char_id; + if (msd) id = msd->bl.id; //[orn] } if(rand()%1000 < 1000/md->attacked_players) { //Let players decide whether to retaliate versus the master or the mob. [Skotlex] @@ -1670,8 +1690,9 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) int mob_dead(struct mob_data *md, struct block_list *src, int type) { struct status_data *status; - struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE], + struct map_session_data *sd = NULL,/**tmpsd[DAMAGELOG_SIZE],*/ *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL; + struct block_list *tmpbl[DAMAGELOG_SIZE] ; //[orn] struct { struct party_data *p; @@ -1706,7 +1727,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) map_freeblock_lock(); - memset(tmpsd,0,sizeof(tmpsd)); + memset(tmpbl,0,sizeof(tmpbl)); memset(pt,0,sizeof(pt)); if(src && src->type == BL_MOB) @@ -1735,16 +1756,19 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) for(temp=0,i=0,mvp_damage=0;idmglog[i].id;i++) { - tmpsd[temp] = map_charid2sd(md->dmglog[i].id); - if(tmpsd[temp] == NULL) + tmpbl[temp] = (struct block_list*)map_id2bl(md->dmglog[i].id); + if(tmpbl[temp] == NULL) continue; - if(tmpsd[temp]->bl.m != md->bl.m || pc_isdead(tmpsd[temp])) + if( (tmpbl[temp])->m != md->bl.m || status_isdead(tmpbl[temp])) continue; if(mvp_damage<(unsigned int)md->dmglog[i].dmg){ third_sd = second_sd; second_sd = mvp_sd; - mvp_sd=tmpsd[temp]; + if ( (tmpbl[temp])->type == BL_HOMUNCULUS ) { + mvp_sd = (struct map_session_data *) ((struct homun_data *)tmpbl[temp])->master ; + } else + mvp_sd=(struct map_session_data *)tmpbl[temp]; mvp_damage=md->dmglog[i].dmg; } @@ -1758,7 +1782,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) (!map[md->bl.m].flag.nobaseexp || !map[md->bl.m].flag.nojobexp) //Gives Exp ) { //Experience calculation. - for(i=0;istatus.party_id)>0) + if( (tmpbl[i]->type == BL_PC) && (temp = ((struct map_session_data *)tmpbl[i])->status.party_id )>0 ) //only pc have party [orn] { int j; for(j=0;jbl, base_exp,job_exp); - if(zeny) // zeny from mobs [Valaris] - pc_getzeny(tmpsd[i], zeny); + if(flag) { //homunculus aren't considered in party [orn] + switch( (tmpbl[i])->type ) { + case BL_PC: + if(base_exp || job_exp) + pc_gainexp((struct map_session_data *)tmpbl[i], &md->bl, base_exp,job_exp); + if(zeny) // zeny from mobs [Valaris] + pc_getzeny((struct map_session_data *)tmpbl[i], zeny); + break ; + case BL_HOMUNCULUS: + if(base_exp) + merc_hom_gainexp((struct homun_data *)tmpbl[i], base_exp); + if(zeny) //homunculus give zeny to master + pc_getzeny((struct map_session_data *)((struct homun_data *)tmpbl[i])->master, zeny); + break ; + + } } } diff --git a/src/map/pc.c b/src/map/pc.c index edd95ae8a..dc1ecbde7 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -24,6 +24,7 @@ #include "npc.h" #include "mob.h" #include "pet.h" +#include "mercenary.h" //orn #include "itemdb.h" #include "script.h" #include "battle.h" @@ -676,6 +677,10 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t if (sd->status.pet_id > 0) intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id); + // Homunculus [albator] + if (sd->status.hom_id > 0) + intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + // ƒp?ƒeƒBAƒMƒ‹ƒhƒf?ƒ^‚ฬ—v‹ if (sd->status.party_id > 0 && party_search(sd->status.party_id) == NULL) party_request_info(sd->status.party_id); @@ -3257,6 +3262,10 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in unit_remove_map(&sd->pd->bl, clrtype); intif_save_petdata(sd->status.account_id,&sd->pet); } + if(sd->status.hom_id > 0 && sd->hd) { //orn + unit_remove_map(&sd->hd->bl, clrtype); + intif_homunculus_requestsave(sd->status.account_id, &sd->homunculus); + } chrif_save(sd,2); chrif_changemapserver(sd, mapindex, x, y, ip, (short)port); return 0; @@ -3289,6 +3298,8 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in unit_remove_map(&sd->bl, clrtype); if(sd->status.pet_id > 0 && sd->pd) unit_remove_map(&sd->pd->bl, clrtype); + if(sd->status.hom_id > 0 && sd->hd) //orn + unit_remove_map(&sd->hd->bl, clrtype); clif_changemap(sd,map[m].index,x,y); // [MouseJstr] } else if(sd->state.auth) //Tag player for rewarping after map-loading is done. [Skotlex] @@ -3306,6 +3317,13 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in sd->pd->ud.dir = sd->ud.dir; } + if(sd->status.hom_id > 0 && sd->hd ) { //orn + sd->hd->bl.m = m; + sd->hd->bl.x = sd->hd->ud.to_x = x; + sd->hd->bl.y = sd->hd->ud.to_y = y; + sd->hd->ud.dir = sd->ud.dir; + } + return 0; } @@ -4717,6 +4735,14 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) pet_unlocktarget(sd->pd); } + if(sd->status.hom_id > 0 && sd->hd) //orn + { + merc_stop_walking(sd->hd, 1) ; + merc_stop_attack(sd->hd) ; + merc_hom_delete(sd->hd,0); + } + + // Leave duel if you die [LuzZza] if(battle_config.duel_autoleave_when_die) { if(sd->duel_group > 0) diff --git a/src/map/script.c b/src/map/script.c index 338a987a1..dbcf96be9 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -36,6 +36,7 @@ #include "mob.h" #include "npc.h" #include "pet.h" +#include "mercenary.h" //[orn] #include "intif.h" #include "skill.h" #include "chat.h" @@ -441,6 +442,7 @@ int buildin_getvariableofnpc(struct script_state *st); // [blackhole89] --> int buildin_warpportal(struct script_state *st); // <-- [blackhole89] +int buildin_homunculus_evolution(struct script_state *st) ; //[orn] void push_val(struct script_stack *stack,int type,int val); int run_func(struct script_state *st); @@ -785,6 +787,7 @@ struct { // [blackhole89] --> {buildin_warpportal,"warpportal","iisii"}, // <--- [blackhole89] + {buildin_homunculus_evolution,"homevolution",""}, //[orn] {NULL,NULL,NULL}, }; @@ -6516,6 +6519,21 @@ int buildin_catchpet(struct script_state *st) return 0; } +/*========================================== + * [orn] + *------------------------------------------ + */ +int buildin_homunculus_evolution(struct script_state *st) +{ + struct map_session_data *sd; + sd=script_rid2sd(st); + if ( sd->hd && sd->hd->homunculusDB->evo_class && sd->homunculus.intimacy > 91000 ) { + return merc_hom_evolution(sd->hd) ; + } + clif_emotion(&sd->hd->bl, 4) ; //swt + return 0; +} + /*========================================== *Œg‘ั—‘›z‰ป‹@Žg—p *------------------------------------------ @@ -10388,7 +10406,7 @@ int buildin_rid2name(struct script_state *st){ push_str(st->stack,C_CONSTSTR,((struct pet_data *)bl)->name); break; case BL_HOMUNCULUS: - push_str(st->stack,C_CONSTSTR,((struct homun_data *)bl)->name); + push_str(st->stack,C_CONSTSTR,((struct homun_data *)bl)->master->homunculus.name); break; default: ShowError("buildin_rid2name: BL type unknown.\n"); @@ -10810,7 +10828,7 @@ int buildin_unittalk(struct script_state *st) memcpy(message, ((TBL_NPC *)bl)->name, NAME_LENGTH); break; case BL_HOMUNCULUS: - memcpy(message, ((TBL_HOMUNCULUS *)bl)->name, NAME_LENGTH); + memcpy(message, ((TBL_HOMUNCULUS *)bl)->master->homunculus.name, NAME_LENGTH); break; case BL_PET: memcpy(message, ((TBL_PET *)bl)->name, NAME_LENGTH); diff --git a/src/map/skill.c b/src/map/skill.c index be9343d7a..b501e9b64 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -20,6 +20,7 @@ #include "pc.h" #include "status.h" #include "pet.h" +#include "mercenary.h" //[orn] #include "mob.h" #include "battle.h" #include "party.h" @@ -706,6 +707,8 @@ const char* skill_get_name( int id ){ return "UNKNOWN_SKILL"; if (id >= GD_SKILLBASE) id = GD_SKILLRANGEMIN + id - GD_SKILLBASE; + if (id >= HM_SKILLBASE) //[orn] + id = HM_SKILLRANGEMIN + id - HM_SKILLBASE; if (id < 1 || id > MAX_SKILL_DB || skill_db[id].name==NULL) return "UNKNOWN_SKILL"; //Can't use skill_chk because we return a string. return skill_db[id].name; @@ -809,6 +812,8 @@ int skill_calc_heal (struct block_list *bl, int skill_lv) if(bl->type == BL_PC && (skill = pc_checkskill((TBL_PC*)bl, HP_MEDITATIO)) > 0) heal += heal * skill * 2 / 100; + if(bl->type == BL_HOMUNCULUS && (skill = merc_hom_checkskill( ((TBL_HOMUNCULUS*)bl)->master, HLIF_BRAIN)) > 0) //[orn] + heal += heal * skill * 2 / 100; return heal; } @@ -846,6 +851,8 @@ int skillnotok (int skillid, struct map_session_data *sd) if (i >= GD_SKILLBASE) i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; if (i > MAX_SKILL || i < 0) return 1; @@ -919,6 +926,49 @@ int skillnotok (int skillid, struct map_session_data *sd) return (map[sd->bl.m].flag.noskill); } +// [orn] - skill ok to cast? and when? //homunculus +int skillnotok_hom (int skillid, struct homun_data *hd) +{ + int i = skillid; + nullpo_retr (1, hd); + //if (sd == 0) + //return 0; + //return 1; + // I think it was meant to be "no skills allowed when not a valid sd" + + if (skillid >= GD_SKILLRANGEMIN && skillid <= GD_SKILLRANGEMAX) + return 1; + + if (i >= GD_SKILLBASE) + i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; + + if (i > MAX_SKILL || i < 0) + return 1; + + if (hd->blockskill[i] > 0) + return 1; + + // Check skill restrictions [Celest] + if(!map_flag_vs(hd->bl.m) && skill_get_nocast (skillid) & 1) + return 1; + if(map[hd->bl.m].flag.pvp) { + if(!battle_config.pk_mode && skill_get_nocast (skillid) & 2) + return 1; + if(battle_config.pk_mode && skill_get_nocast (skillid) & 16) + return 1; + } + if(map_flag_gvg(hd->bl.m) && skill_get_nocast (skillid) & 4) + return 1; + if(agit_flag && skill_get_nocast (skillid) & 8) + return 1; + if(map[hd->bl.m].flag.restricted && map[hd->bl.m].zone && skill_get_nocast (skillid) & (8*map[hd->bl.m].zone)) + return 1; + + return (map[hd->bl.m].flag.noskill); +} + /* ใ‚นใ‚ญใƒซใƒฆใƒ‹ใƒƒใƒˆใฎ้…็ฝฎๆƒ…ๅ ฑใ‚’่ฟ”ใ™ */ struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; int firewall_unit_pos; @@ -2263,6 +2313,99 @@ int skill_guildaura_sub (struct block_list *bl, va_list ap) return 0; } +/*========================================== + * [orn] + * Checks that you have the requirements for casting a skill for homunculus. + * Flag: + * &1: finished casting the skill (invoke hp/sp/item consumption) + * &2: picked menu entry (Warp Portal, Teleport and other menu based skills) + *------------------------------------------ + */ +static int skill_check_condition_hom (struct homun_data *hd, int skill, int lv, int type) +{ + struct status_data *status; + struct status_change *sc; + int j,hp,sp,hp_rate,sp_rate,state,mhp ; + + nullpo_retr(0, hd); + + if (lv <= 0) return 0; + + status = &hd->battle_status; + sc = &hd->sc; + if (!sc->count) + sc = NULL; + + // for the guild skills [celest] + if (skill >= HM_SKILLBASE) //[orn] + j = HM_SKILLRANGEMIN + skill - HM_SKILLBASE; + else + j = skill; + if (j < 0 || j >= MAX_SKILL_DB) + return 0; + //Code speedup, rather than using skill_get_* over and over again. + if (lv < 1 || lv > MAX_SKILL_LEVEL) + return 0; + hp = skill_db[j].hp[lv-1]; + sp = skill_db[j].sp[lv-1]; + hp_rate = skill_db[j].hp_rate[lv-1]; + sp_rate = skill_db[j].sp_rate[lv-1]; + state = skill_db[j].state; + mhp = skill_db[j].mhp[lv-1]; + if(mhp > 0) + hp += (status->max_hp * mhp)/100; + if(hp_rate > 0) + hp += (status->hp * hp_rate)/100; + else + hp += (status->max_hp * (-hp_rate))/100; + if(sp_rate > 0) + sp += (status->sp * sp_rate)/100; + else + sp += (status->max_sp * (-sp_rate))/100; + + switch(skill) { // Check for cost reductions due to skills & SCs + case HFLI_SBR44: + if(hd->master->homunculus.intimacy < 200) + return 0; + break; + case HVAN_EXPLOSION: + if(hd->master->homunculus.intimacy < battle_config.hvan_explosion_intimate) + return 0; + break; + } + if(!(type&2)){ + if( hp>0 && status->hp <= (unsigned int)hp) { + clif_skill_fail(hd->master,skill,2,0); + return 0; + } + if( sp>0 && status->sp < (unsigned int)sp) { + clif_skill_fail(hd->master,skill,1,0); + return 0; + } + } + + switch(state) { + case ST_MOVE_ENABLE: + //Check only on begin casting. [Skotlex] + if(!type && !unit_can_move(&hd->bl)) { + clif_skill_fail(hd->master,skill,0,0); + return 0; + } + break; + } + + if(!(type&1)) + return 1; + + if(type&2) + return 1; + + if(sp || hp) + status_zap(&hd->bl, hp, sp); + + return 1; +} + /*========================================================================= * ็ฏ„ๅ›ฒใ‚นใ‚ญใƒซไฝฟ็”จๅ‡ฆ็†ๅฐๅˆ†ใ‘ใ“ใ“ใ‹ใ‚‰ */ @@ -2454,6 +2597,7 @@ static int skill_reveal_trap (struct block_list *bl, va_list ap) int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; + struct homun_data *hd = NULL ; //[orn] struct status_data *tstatus; struct status_change *sc; @@ -2472,6 +2616,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int sd = (struct map_session_data *)src; if (bl->type == BL_PC) tsd = (struct map_session_data *)bl; + if (bl->type == BL_HOMUNCULUS) //[orn] + hd = (struct homun_data *)bl; if (status_isdead(src) || (src != bl && status_isdead(bl))) return 1; @@ -2568,6 +2714,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case TK_DOWNKICK: case TK_COUNTER: case ASC_BREAKER: + case HFLI_MOON: //[orn] + case HFLI_SBR44: //[orn] skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; @@ -2725,8 +2873,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skill_castend_damage_id); } break; - - case SM_MAGNUM: if(flag&1) skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); @@ -2974,6 +3120,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case TF_THROWSTONE: case NPC_SMOKING: case NPC_SELFDESTRUCTION: + case HVAN_EXPLOSION: //[orn] case GS_FLING: case NJ_ZENYNAGE: skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); @@ -3112,6 +3259,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) { struct map_session_data *sd = NULL; + struct homun_data *hd = NULL; struct map_session_data *dstsd = NULL; struct status_data *sstatus, *tstatus; struct status_change *tsc; @@ -3129,6 +3277,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (src->type == BL_PC) { sd = (struct map_session_data *)src; + } else if (src->type == BL_HOMUNCULUS) { //[orn] + hd = (struct homun_data *)src; } else if (src->type == BL_MOB) { md = (struct mob_data *)src; } @@ -3151,7 +3301,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] switch (skillid) { - case AL_HEAL: + case HLIF_HEAL: //[orn] + if ( !hd ) { + clif_skill_fail(hd->master,skillid,0,0) ; + break ; + } + case AL_HEAL: case ALL_RESURRECTION: case PR_ASPERSIO: if (battle_check_undead(tstatus->race,tstatus->def_ele)) { @@ -3184,6 +3339,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in map_freeblock_lock(); switch(skillid) { + case HLIF_HEAL: //[orn] case AL_HEAL: /* ใƒ’ใƒผใƒซ */ { int heal = skill_calc_heal(src, skilllv); @@ -3971,6 +4127,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in skill_castend_damage_id); status_damage(src, src, sstatus->max_hp,0,0,1); break; + case HVAN_EXPLOSION: //[orn] + ShowDebug("skill_castend_nodamage_id : intimacy = %d\n", hd->master->homunculus.intimacy) ; //ORN DEBUG + clif_skill_nodamage(src, src, skillid, -1, 1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY, + skill_castend_damage_id); + if(hd){ + hd->master->homunculus.intimacy = 200; + clif_send_homdata(hd->master,0x100,hd->master->homunculus.intimacy/100); + } + status_damage(src, src, sstatus->max_hp,0,0,1); + break; /* ใƒ‘ใƒผใƒ†ใ‚ฃใ‚นใ‚ญใƒซ */ case AL_ANGELUS: /* ใ‚จใƒณใ‚ธใ‚งใƒฉใ‚น */ @@ -5397,6 +5566,149 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in pc_delspiritball(sd,1,0); } break; + + case AM_CALLHOMUN: //[orn] + { + int i = 0; + if (sd && (sd->status.hom_id == 0 || sd->homunculus.vaporize == 1)) { + if (sd->status.hom_id == 0) { + i = pc_search_inventory(sd,7142); + if(i < 0) { + clif_skill_fail(sd,skillid,0,0); + break ; + } + pc_delitem(sd,i,1,0); + } + if (merc_call_homunculus(sd)) + break; + } + + clif_skill_fail(sd,skillid,0,0); + break; + } + case AM_REST: //[orn] + { + if (sd && sd->hd && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) { + sd->homunculus.vaporize = 1; + merc_hom_delete(sd->hd, 0) ; + } else if ( sd ) + { + clif_skill_fail(sd,skillid,0,0); + } + + break; + } + case AM_RESURRECTHOMUN: //[orn] + { + if ( sd && sd->status.hom_id ) { + if( map_flag_gvg(bl->m) ) + { //No reviving in WoE grounds! + clif_skill_fail(sd,skillid,0,0); + break; + } + if ( sd->homunculus.alive == 0 ) { + int per = 10 * skilllv; + + if (merc_hom_revive(sd, per) ) + { + clif_skill_nodamage(src,&sd->hd->bl,AM_RESURRECTHOMUN,skilllv,1); + } else { + clif_skill_fail(sd,skillid,0,0); + } + } else { + clif_skill_fail(sd,skillid,0,0); + } + + } + break; + } + + case HAMI_CASTLE: //[orn] + { + if(hd && rand()%100 < 20*skilllv) + { + int x,y; + struct walkpath_data wpd; + struct map_session_data *sd = hd->master; + if( path_search(&wpd,hd->bl.m,hd->bl.x,hd->bl.y,sd->bl.x,sd->bl.y,0) != 0 ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + + clif_skill_nodamage(&hd->bl,&sd->bl,skillid,skilllv,1); + + x = hd->bl.x; + y = hd->bl.y; + + unit_movepos(&hd->bl,sd->bl.x,sd->bl.y,0,0); + unit_movepos(&sd->bl,x,y,0,0); + clif_fixpos(&hd->bl) ; + clif_fixpos(&sd->bl) ; + + map_foreachinarea(skill_chastle_mob_changetarget,hd->bl.m, + hd->bl.x-AREA_SIZE,hd->bl.y-AREA_SIZE, + hd->bl.x+AREA_SIZE,hd->bl.y+AREA_SIZE, + BL_MOB,&hd->master->bl,&hd->bl); + } + } + break; + case HVAN_CHAOTIC: //[orn] + { + if(hd){ + //HOM,PC,MOB + struct block_list* heal_target=NULL; + int heal = skill_calc_heal( src, 1+rand()%skilllv ); + static const int per[10][2]={{20,50},{50,60},{25,75},{60,64},{34,67}, + {34,67},{34,67},{34,67},{34,67},{34,67}}; + int rnd = rand()%100; + if(rndbl; + }else if(rndmaster->bl)) + heal_target = &hd->master->bl; + else + heal_target = &hd->bl; + }else{//MOB + heal_target = map_id2bl(hd->target_id); + if(heal_target==NULL) + heal_target = &hd->bl; + } + clif_skill_nodamage(src,heal_target,AL_HEAL,heal,1); + clif_skill_nodamage(src,heal_target,skillid,heal,1); + status_heal(heal_target, heal, 0, 0); + skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)) ; + } + } + break; + case HLIF_AVOID: //[orn] + case HAMI_DEFENCE: //[orn] + if ( hd ) { + clif_skill_nodamage(src,&hd->master->bl,skillid,skilllv, + sc_start(&hd->master->bl,type,100,skilllv,skill_get_time(skillid,skilllv))) ; + } + case HAMI_BLOODLUST: //[orn] + case HFLI_FLEET: //[orn] + case HFLI_SPEED: //[orn] + if ( hd ) { + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(&hd->bl,type,100,skilllv,skill_get_time(skillid,skilllv))) ; + skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)) ; + } + else + clif_skill_fail(hd->master,skillid,0,0); + break; + case HLIF_CHANGE: //[orn] + if ( hd ) { + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(&hd->bl,type,100,skilllv,skill_get_time(skillid,skilllv))) ; + status_heal(&hd->bl, hd->master->homunculus.max_hp, 0, 0); + skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)) ; + } + else + clif_skill_fail(hd->master,skillid,0,0); + break; default: ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); @@ -5421,6 +5733,7 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) { struct block_list *target, *src = map_id2bl(id); struct map_session_data* sd = NULL; + struct homun_data* hd = NULL; //[orn] struct mob_data* md = NULL; struct unit_data* ud = unit_bl2ud(src); struct status_change *sc; @@ -5429,6 +5742,7 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) nullpo_retr(0, ud); BL_CAST( BL_PC, src, sd); + BL_CAST( BL_HOMUNCULUS, src, hd); //[orn] BL_CAST( BL_MOB, src, md); if( src->prev == NULL ) { @@ -5538,6 +5852,9 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) if(sd && !skill_check_condition(sd,ud->skillid, ud->skilllv,1)) /* ไฝฟ็”จๆกไปถใƒใ‚งใƒƒใ‚ฏ */ break; + if(hd && !skill_check_condition_hom(hd,ud->skillid, ud->skilllv,1)) //[orn] + break; + if (ud->walktimer != -1 && ud->skillid != TK_RUN) unit_stop_walking(src,1); @@ -5585,12 +5902,14 @@ int skill_castend_pos (int tid, unsigned int tick, int id, int data) struct block_list* src = map_id2bl(id); int maxcount; struct map_session_data *sd = NULL; + struct homun_data *hd = NULL; //[orn] struct unit_data *ud = unit_bl2ud(src); struct mob_data *md = NULL; nullpo_retr(0, ud); BL_CAST( BL_PC , src, sd); + BL_CAST( BL_HOMUNCULUS , src, hd); //[orn] BL_CAST( BL_MOB, src, md); if( src->prev == NULL ) { @@ -5651,6 +5970,9 @@ int skill_castend_pos (int tid, unsigned int tick, int id, int data) if(sd && !skill_check_condition(sd,ud->skillid, ud->skilllv, 1)) /* ไฝฟ็”จๆกไปถใƒใ‚งใƒƒใ‚ฏ */ break; + if(hd && !skill_check_condition_hom(hd,ud->skillid, ud->skilllv, 1)) //[orn] + break; + if(md) { md->last_thinktime=tick + (tid==-1?md->status.adelay:md->status.amotion); if(md->skillidx >= 0) { @@ -7586,6 +7908,8 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t // for the guild skills [celest] if (skill >= GD_SKILLBASE) j = GD_SKILLRANGEMIN + skill - GD_SKILLBASE; + else if (skill >= HM_SKILLBASE) //[orn] + j = HM_SKILLRANGEMIN + skill - HM_SKILLBASE; else j = skill; if (j < 0 || j >= MAX_SKILL_DB) @@ -9034,6 +9358,23 @@ int skill_ganbatein (struct block_list *bl, va_list ap) return 1; } +/*========================================== + * ƒLƒƒƒXƒŠƒ“ƒO‚ฬƒ^[ƒQƒbƒg•ฯX + *------------------------------------------ + */ +int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap) +{ + struct mob_data* md; + struct block_list *from_bl; + struct block_list *to_bl; + nullpo_retr(0, md = (struct mob_data*)bl); + nullpo_retr(0, from_bl = va_arg(ap,struct block_list *)); + nullpo_retr(0, to_bl = va_arg(ap,struct block_list *)); + if(md->target_id == from_bl->id) + md->target_id = to_bl->id; + return 0; +} + /*========================================== * ๆŒ‡ๅฎš็ฏ„ๅ›ฒๅ†…ใงsrcใซๅฏพใ—ใฆๆœ‰ๅŠนใชใ‚ฟใƒผใ‚ฒใƒƒใƒˆใฎblใฎๆ•ฐใ‚’ๆ•ฐใˆใ‚‹(foreachinarea) *------------------------------------------ @@ -10303,6 +10644,8 @@ int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick) if (skillid >= GD_SKILLBASE) skillid = GD_SKILLRANGEMIN + skillid - GD_SKILLBASE; + if (skillid >= HM_SKILLBASE) //[orn] + skillid = HM_SKILLRANGEMIN + skillid - HM_SKILLBASE; if (skillid < 1 || skillid > MAX_SKILL) return -1; @@ -10310,6 +10653,31 @@ int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick) return add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,skillid); } +int skill_blockmerc_end (int tid, unsigned int tick, int id, int data) //[orn] +{ + struct homun_data *hd = (TBL_HOMUNCULUS*) map_id2bl(id); + if (data <= 0 || data >= MAX_SKILL) + return 0; + if (hd) hd->blockskill[data] = 0; + + return 1; +} + +int skill_blockmerc_start(struct homun_data *hd, int skillid, int tick) //[orn] +{ + nullpo_retr (-1, hd); + + if (skillid >= GD_SKILLBASE) + skillid = GD_SKILLRANGEMIN + skillid - GD_SKILLBASE; + if (skillid >= HM_SKILLBASE) //[orn] + skillid = HM_SKILLRANGEMIN + skillid - HM_SKILLBASE; + if (skillid < 1 || skillid > MAX_SKILL) + return -1; + + hd->blockskill[skillid] = 1; + return add_timer(gettick()+tick,skill_blockmerc_end,hd->bl.id,skillid); +} + /*---------------------------------------------------------------------------- * ๅˆๆœŸๅŒ–็ณป @@ -10641,6 +11009,8 @@ int skill_readdb (void) } if (i >= GD_SKILLBASE) i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; if(i<=0 || i>MAX_SKILL_DB) continue; @@ -10697,6 +11067,8 @@ int skill_readdb (void) i=atoi(split[0]); if (i >= GD_SKILLBASE) i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; if(i<=0 || i>MAX_SKILL_DB) continue; @@ -10784,6 +11156,8 @@ int skill_readdb (void) i=atoi(split[0]); if (i >= GD_SKILLBASE) i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; if(i<=0 || i>MAX_SKILL_DB) continue; @@ -10816,6 +11190,8 @@ int skill_readdb (void) i=atoi(split[0]); if (i >= GD_SKILLBASE) i = GD_SKILLRANGEMIN + i - GD_SKILLBASE; + if (i >= HM_SKILLBASE) //[orn] + i = HM_SKILLRANGEMIN + i - HM_SKILLBASE; if(i<=0 || i>MAX_SKILL_DB) continue; skill_db[i].unit_id[0] = strtol(split[1],NULL,16); diff --git a/src/map/skill.h b/src/map/skill.h index accc6dfdf..48e88033d 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -237,6 +237,8 @@ int skill_check_cloaking(struct block_list *bl, struct status_change *sc); // ƒXƒe?ƒ^ƒXˆูํ int skill_enchant_elemental_end(struct block_list *bl, int type); int skillnotok(int skillid, struct map_session_data *sd); +int skillnotok_hom (int skillid, struct homun_data *hd) ; //[orn] +int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap); //[orn] // ƒAƒCƒeƒ€์ฌ int skill_can_produce_mix( struct map_session_data *sd, int nameid, int trigger, int qty); @@ -250,6 +252,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ); int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag); int skill_blockpc_start (struct map_session_data*,int,int); // [celest] +int skill_blockmerc_start (struct homun_data*,int,int); //[orn] // ƒXƒLƒ‹U?ˆ๊Š‡?— int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc, diff --git a/src/map/status.c b/src/map/status.c index a349bf08e..09aed9ced 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -54,13 +54,14 @@ int current_equip_item_index; //Contains inventory index of an equipped item. To int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex] //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only //to avoid cards exploits +void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag); //[orn] static void add_sc(int skill, int sc) { int sk = skill; if (sk > GD_SKILLBASE) sk = skill - GD_SKILLBASE + SC_GD_BASE; else - if (sk > HM_SKILLBASE) sk = skill - HM_SKILLBASE + SC_HM_BASE; + if (sk >= HM_SKILLBASE) sk = skill - HM_SKILLBASE + SC_HM_BASE; if (sk < 0 || sk >= MAX_SKILL) { if (battle_config.error_log) ShowError("add_sc: Unsupported skill id %d\n", skill); @@ -374,6 +375,8 @@ void initChangeTables(void) { set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_INT); set_sc(HAMI_BLOODLUST, SC_BLOODLUST, SI_BLANK, SCB_BATK|SCB_WATK); set_sc(HFLI_FLEET, SC_FLEET, SI_BLANK, SCB_ASPD|SCB_BATK|SCB_WATK); + set_sc(HFLI_SPEED, SC_SPEED, SI_BLANK, SCB_FLEE); //[orn] + set_sc(HAMI_DEFENCE, SC_DEFENCE, SI_BLANK, SCB_DEF); //[orn] set_sc(GD_LEADERSHIP, SC_GUILDAURA, SI_GUILDAURA, SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX); set_sc(GD_BATTLEORDER, SC_BATTLEORDERS, SI_BATTLEORDERS, SCB_STR|SCB_INT|SCB_DEX); @@ -452,7 +455,7 @@ int SkillStatusChangeTable(int skill) int sk = skill; if (sk > GD_SKILLBASE) sk = skill - GD_SKILLBASE + SC_GD_BASE; else - if (sk > HM_SKILLBASE) sk = skill - HM_SKILLBASE + SC_HM_BASE; + if (sk >= HM_SKILLBASE) sk = skill - HM_SKILLBASE + SC_HM_BASE; if (sk < 0 || sk >= MAX_SKILL) { if (battle_config.error_log) ShowError("add_sc: Unsupported skill id %d\n", skill); @@ -501,8 +504,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s struct status_data *status; struct status_change *sc; - if(sp && target->type != BL_PC) - sp = 0; //Only players get SP damage. + if(sp && target->type != BL_PC && target->type != BL_HOMUNCULUS) //[orn] + sp = 0; //Only players and Homunculus get SP damage. if (hp < 0) { //Assume absorbed damage. status_heal(target, -hp, 0, 1); @@ -641,7 +644,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s flag = pc_dead((TBL_PC*)target,src); break; case BL_HOMUNCULUS: - flag = merc_dead((TBL_HOMUNCULUS*)target,src); + flag = merc_hom_dead((TBL_HOMUNCULUS*)target,src); break; default: //Unhandled case, do nothing to object. flag = 0; @@ -738,7 +741,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; case BL_HOMUNCULUS: - merc_heal((TBL_HOMUNCULUS*)bl,hp,sp); + merc_hom_heal((TBL_HOMUNCULUS*)bl,hp,sp); break; } return hp+sp; @@ -819,7 +822,9 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per break; case BL_PC: pc_revive((TBL_PC*)bl, hp, sp); - break; +// case BL_HOMUNCULUS: //[orn] +// merc_hom_revive((TBL_HOMUNCULUS*)bl, hp, sp); +// break; } return 1; } @@ -1360,97 +1365,6 @@ int status_calc_pet(struct pet_data *pd, int first) return 1; } -int status_calc_homunculus(struct homun_data *hd, int first) -{ - struct status_data *status = &hd->base_status; - int lv, i; - /* very proprietary */ - lv=hd->level; - memset(status, 0, sizeof(struct status_data)); - switch(hd->class_) - { - case 6001: //LIF ~ int,dex,vit - status->str = 3+lv/7; - status->agi = 3+2*lv/5; - status->vit = 4+lv; - status->int_ = 4+3*lv/4; - status->dex = 4+2*lv/3; - status->luk = 3+lv/4; - for(i=8001;i<8005;++i) - { - hd->hskill[i-8001].id=i; - //hd->hskill[i-8001].level=1; - } - break; - case 6003: //FILIR ~ str,agi,dex - status->str = 4+3*lv/4; - status->agi = 4+2*lv/3; - status->vit = 3+2*lv/5; - status->int_ = 3+lv/4; - status->dex = 4+lv; - status->luk = 3+lv/7; - for(i=8009;i<8013;++i) - { - hd->hskill[i-8009].id=i; - //hd->hskill[i-8009].level=1; - } - break; - case 6002: //AMISTR ~ str,vit,luk - status->str = 4+lv; - status->agi = 3+lv/4; - status->vit = 3+3*lv/4; - status->int_ = 3+lv/10; - status->dex = 3+2*lv/5; - status->luk = 4+2*lv/3; - for(i=8005;i<8009;++i) - { - hd->hskill[i-8005].id=i; - //hd->hskill[i-8005].level=1; - } - break; - case 6004: //VANILMIRTH ~ int,dex,luk - status->str = 3+lv/4; - status->agi = 3+lv/7; - status->vit = 3+2*lv/5; - status->int_ = 4+lv; - status->dex = 4+2*lv/3; - status->luk = 4+3*lv/4; - for(i=8013;i<8017;++i) - { - hd->hskill[i-8013].id=i; - //hd->hskill[i-8013].level=1; - } - break; - default: - if (battle_config.error_log) - ShowError("status_calc_homun: Unknown class %d\n", hd->class_); - memcpy(status, &dummy_status, sizeof(struct status_data)); - break; - } - status->hp = 10; //Revive HP/SP? - status->sp = 0; - status->max_hp=500+lv*10+lv*lv; - status->max_sp=300+lv*11+lv*lv*90/100; - status->aspd_rate = 1000; - status->speed=0x96; - status->batk = status_base_atk(&hd->bl, status); - status_calc_misc(status, hd->level); - - // hp recovery - hd->regenhp = 1 + (status->vit/5) + (status->max_hp/200); - - // sp recovery - hd->regensp = 1 + (status->int_/6) + (status->max_sp/100); - if(status->int_ >= 120) - hd->regensp += ((status->int_-120)>>1) + 4; - - status->amotion = 1800 - (1800 * status->agi / 250 + 1800 * status->dex / 1000); - status->amotion -= 200; - status->dmotion=status->amotion; - status_calc_bl(&hd->bl, SCB_ALL); - return 1; -} - static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data *status) { unsigned int val; @@ -2230,6 +2144,59 @@ int status_calc_pc(struct map_session_data* sd,int first) return 0; } +int status_calc_homunculus(struct homun_data *hd, int first) +{ + struct status_data b_status, *status; + memcpy(&b_status, &hd->base_status, sizeof(struct status_data)); + status = &hd->base_status; + + status->def_ele = b_status.def_ele = hd->homunculusDB->element ; //[orn] + status->ele_lv = b_status.ele_lv = 1 ; //[orn] + status->race = b_status.race = hd->homunculusDB->race ; //[orn] + status->size = b_status.size = hd->homunculusDB->size ; //[orn] + status->rhw.range = b_status.rhw.range = 1 + hd->homunculusDB->size ; //[orn] + status->mode = b_status.mode = MD_CANMOVE|MD_CANATTACK|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR; //[orn] + status->speed = b_status.speed = DEFAULT_WALK_SPEED; + status->aspd_rate = b_status.aspd_rate = 1000; + + merc_hom_calc_skilltree(hd->master); // + + status_cpy(&b_status, status); + status_calc_misc(status, hd->master->homunculus.level); + status_calc_bl(&hd->bl, SCB_ALL); //Status related changes. + + if ( (b_status.str != status->str) || + (b_status.agi != status->agi) || + (b_status.vit != status->vit) || + (b_status.int_ != status->int_) || + (b_status.dex != status->dex) || + (b_status.luk != status->luk) || + (b_status.hit != status->hit) || + (b_status.flee != status->flee) || + (b_status.amotion != status->amotion) || + (b_status.rhw.atk != status->rhw.atk) || + (b_status.def != status->def) || + (b_status.rhw.atk2 != status->rhw.atk2) || + (b_status.def2 != status->def2) || + (b_status.flee2 != status->flee2) || + (b_status.cri != status->cri) || + (b_status.matk_max != status->matk_max) || + (b_status.matk_min != status->matk_min) || + (b_status.mdef != status->mdef) || + (b_status.mdef2 != status->mdef2) || + (b_status.rhw.range != status->rhw.range) || + (b_status.max_hp != status->max_hp) || + (b_status.max_sp != status->max_sp) || + (b_status.hp != status->hp) || + (b_status.sp != status->sp) + ) + { + clif_hominfo(hd->master,0) ; + } + + return 1; +} + static unsigned short status_calc_str(struct block_list *,struct status_change *,int); static unsigned short status_calc_agi(struct block_list *,struct status_change *,int); static unsigned short status_calc_vit(struct block_list *,struct status_change *,int); @@ -2552,12 +2519,210 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) clif_updatestatus(sd,SP_MAXSP); } +//Calculates some attributes that depends on modified stats from status changes. +void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] +{ + struct status_data *status = &hd->battle_status, *b_status = &hd->base_status; + int skill = 0; + + if(flag&(SCB_MAXHP|SCB_VIT)) + { + flag|=SCB_MAXHP; //Ensures client-side refresh + + // Apply relative modifiers from equipment + if(status->max_hp > (unsigned int)battle_config.max_hp) + status->max_hp = battle_config.max_hp; + else if(!status->max_hp) + status->max_hp = 1; + + // hp recovery + hd->regenhp = 1 + (status->vit/5) + (status->max_hp/200); + + if(hd->regenhp < 1) hd->regenhp = 1; + + // Skill-related Adamantium Skin + if((skill=merc_hom_checkskill(hd->master,HAMI_SKIN)) > 0) { + status->max_hp = hd->master->homunculus.max_hp + skill * 2 * hd->master->homunculus.max_hp / 100 ; + hd->regenhp += skill * 5 * hd->regenhp / 100 ; + } + + status->max_hp = status_calc_maxhp(&hd->bl, &hd->sc, status->max_hp); + + } + if(flag&SCB_DEF) + { + status->def = hd->master->homunculus.level / 10 + status->vit / 5 ; + if(hd->sc.data[SC_DEFENCE].timer != -1) + status->def += hd->sc.data[SC_DEFENCE].val2; + if((skill=merc_hom_checkskill(hd->master,HAMI_SKIN)) > 0) { + status->def += skill * 4 ; + } + } + if(flag&(SCB_MAXSP|SCB_INT)) + { + flag|=SCB_MAXSP; + + // Skill-related Instruction Change + if((skill = merc_hom_checkskill(hd->master,HVAN_INSTRUCT)) > 0) { + if ( skill == 5 ) { + status->int_ += 3 ; + } else if ( skill == 1 ) { + status->int_ += 1 ; + } else { + status->int_ += 2 ; + } + if ( skill > 3 ) { + status->str += 4 ; + } else if ( skill == 3 ) { + status->str += 3 ; + } else { + status->str += 1 ; + } + } + + if((skill = merc_hom_checkskill(hd->master,HLIF_BRAIN)) > 0) { + status->max_sp = hd->master->homunculus.max_sp + skill * 2 * hd->master->homunculus.max_sp / 100 ; + hd->regensp += skill * 3 * hd->regensp / 100 ; + if ( skill == 5 ) { + status->max_sp *= 103 / 100 ; + } else if ( skill == 1 ) { + status->max_sp *= 101 / 100 ; + } else { + status->max_sp *= 102 / 100 ; + } + } + + status->mdef = hd->master->homunculus.level / 10 + status->int_ / 5 ; + status->max_sp = status_calc_maxsp(&hd->bl, &hd->sc, status->max_sp); + + if(status->max_sp > (unsigned int)battle_config.max_sp) + status->max_sp = battle_config.max_sp; + else if(!status->max_sp) + status->max_sp = 1; + + if(status->sp > status->max_sp) { + status->sp = status->max_sp; + } + + // sp recovery + hd->regensp = 1 + (status->int_/6) + (status->max_sp/100); + if(status->int_ >= 120) + hd->regensp += ((status->int_-120)>>1) + 4; + + if(hd->regensp < 1) hd->regensp = 1; + + } + + if(flag&(SCB_BATK|SCB_WATK)) { + status->rhw.atk = status->rhw.atk2 = status->str + ( status->str / 10 ) * ( status->str / 10 ) ; + status->rhw.atk += status->dex ; + if ( (status->str + hd->master->homunculus.level) > status->dex ) + status->rhw.atk2 += status->str + hd->master->homunculus.level ; + else + status->rhw.atk2 += status->dex ; + + if(hd->sc.data[SC_FLEET].timer!=-1) + status->rhw.atk2 += status->rhw.atk2 * hd->sc.data[SC_FLEET].val3/100; + } + + if(flag&SCB_MATK) { + status->matk_min = status->int_+(status->int_/7)*(status->int_/7); + status->matk_max = status->int_+(status->int_/5)*(status->int_/5); + + status->matk_min = status_calc_matk(&hd->bl, &hd->sc, status->matk_min); + status->matk_max = status_calc_matk(&hd->bl, &hd->sc, status->matk_max); + + } + + if(flag&SCB_HIT) { + if(status->hit < 1) status->hit = 1; + } + + if(flag&SCB_FLEE) { + if(status->flee < 1) status->flee = 1; + } + + if(flag&SCB_DEF2) { + if(status->def2 < 1) status->def2 = 1; + } + + if(flag&SCB_MDEF2) { + if(status->mdef2 < 1) status->mdef2 = 1; + } + + if(flag&SCB_SPEED) { + if(status->speed < battle_config.max_walk_speed) + status->speed = battle_config.max_walk_speed; + } + if(flag&(SCB_ASPD|SCB_AGI|SCB_DEX)) { + flag|=SCB_ASPD; + status->amotion = hd->homunculusDB->baseASPD - ((status->agi*4+status->dex)* hd->homunculusDB->baseASPD / 1000); + + status->aspd_rate = status_calc_aspd_rate(&hd->bl, &hd->sc , b_status->aspd_rate); + if(status->aspd_rate != 1000) + status->amotion = status->amotion *status->aspd_rate/1000; + + status->amotion = cap_value(status->amotion,battle_config.max_aspd,2000); + + status->adelay = 2*status->amotion; + } + + if(flag&(SCB_AGI|SCB_DSPD)) { + //Even though people insist this is too slow, packet data reports this is the actual real equation. + skill = 800-status->agi*4; + status->dmotion = cap_value(skill, 400, 800); + + if(battle_config.pc_damage_delay_rate != 100) + status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100; + status->dmotion = status_calc_dmotion(&hd->bl, &hd->sc, b_status->dmotion); + } + + if(flag&SCB_CRI) + { + if(status->cri < 10) status->cri = 10; + } + + if(flag&SCB_FLEE2) { + if(status->flee2 < 10) status->flee2 = 10; + } + if (flag == SCB_ALL) + return; //Refresh is done on invoking function (status_calc_hom) + + if ( (flag&SCB_SPEED) || + (flag&SCB_STR) || + (flag&SCB_AGI) || + (flag&SCB_VIT) || + (flag&SCB_INT) || + (flag&SCB_DEX) || + (flag&SCB_LUK) || + (flag&SCB_HIT) || + (flag&SCB_FLEE) || + (flag&SCB_ASPD) || + (flag&(SCB_BATK|SCB_WATK)) || + (flag&SCB_DEF) || + (flag&SCB_WATK) || + (flag&SCB_DEF2) || + (flag&SCB_FLEE2) || + (flag&SCB_CRI) || + (flag&SCB_MATK) || + (flag&SCB_MDEF) || + (flag&SCB_MDEF2) || + (flag&SCB_RANGE) || + (flag&SCB_MAXHP) || + (flag&SCB_MAXSP) + ) + { + clif_hominfo(hd->master,0); + } +} + void status_calc_bl(struct block_list *bl, unsigned long flag) { struct status_data *b_status, *status; struct status_change *sc; int temp; TBL_PC *sd; + TBL_HOMUNCULUS *hd; b_status = status_get_base_status(bl); status = status_get_status_data(bl); sc = status_get_sc(bl); @@ -2566,6 +2731,7 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) return; BL_CAST(BL_PC,bl,sd); + BL_CAST(BL_HOMUNCULUS,bl,hd); if(sd && flag&SCB_PC) { //Recalc everything. @@ -2573,7 +2739,8 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) return; } - if(!sd && (!sc || !sc->count)) { //No difference. +// if(!sd && (!sc || !sc->count)) { //No difference. + if( (!sd && !hd ) && (!sc || !sc->count)) { //No difference. status_cpy(status, b_status); return; } @@ -2716,6 +2883,12 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) return; } + if(hd) { + //The remaining are handled quite different by homunculus, so use their own function. + status_calc_bl_sub_hom(hd, flag); + return; + } + if(flag&SCB_MAXHP) { status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp); if (status->hp > status->max_hp) //FIXME: Should perhaps a status_zap should be issued? @@ -2985,8 +3158,6 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += batk * 3; if(sc->data[SC_BLOODLUST].timer!=-1) batk += batk * sc->data[SC_BLOODLUST].val2/100; - if(sc->data[SC_FLEET].timer!=-1) - batk += batk * sc->data[SC_FLEET].val3/100; if(sc->data[SC_JOINTBEAT].timer!=-1 && sc->data[SC_JOINTBEAT].val2==4) batk -= batk * 25/100; if(sc->data[SC_CURSE].timer!=-1) @@ -3032,8 +3203,6 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan } if(sc->data[SC_BLOODLUST].timer!=-1) watk += watk * sc->data[SC_BLOODLUST].val2/100; - if(sc->data[SC_FLEET].timer!=-1) - watk += watk * sc->data[SC_FLEET].val3/100; if(sc->data[SC_CURSE].timer!=-1) watk -= watk * 25/100; if(sc->data[SC_STRIPWEAPON].timer!=-1) @@ -3140,6 +3309,8 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee += 30; if(sc->data[SC_GATLINGFEVER].timer!=-1) flee -= sc->data[SC_GATLINGFEVER].val1*5; + if(sc->data[SC_SPEED].timer!=-1) + flee += 10 + sc->data[SC_SPEED].val1 * 10 ; return cap_value(flee,0,SHRT_MAX); } @@ -3166,6 +3337,8 @@ static signed char status_calc_def(struct block_list *bl, struct status_change * return 100; if(sc->data[SC_SKA].timer != -1) return sc->data[SC_SKA].val3; + if (sc->data[SC_DEFENCE].timer != -1) //[orn] + def += sc->data[SC_DEFENCE].val2 ; if(sc->data[SC_STEELBODY].timer!=-1) return 90; if(sc->data[SC_DRUMBATTLE].timer!=-1) @@ -3586,6 +3759,8 @@ int status_get_class(struct block_list *bl) return ((struct map_session_data *)bl)->status.class_; if(bl->type==BL_PET) return ((struct pet_data *)bl)->class_; + if(bl->type==BL_HOMUNCULUS) + return ((struct homun_data *)bl)->master->homunculus.class_; return 0; } /*========================================== @@ -3603,7 +3778,7 @@ int status_get_lv(struct block_list *bl) if(bl->type==BL_PET) return ((TBL_PET*)bl)->msd->pet.level; if(bl->type==BL_HOMUNCULUS) - return ((TBL_HOMUNCULUS*)bl)->level; + return ((TBL_HOMUNCULUS*)bl)->master->homunculus.level; return 1; } @@ -3699,6 +3874,16 @@ int status_get_party_id(struct block_list *bl) } return 0; //No party. } + if(bl->type==BL_HOMUNCULUS){ //[orn] + struct homun_data *hd=(struct homun_data *)bl; + if( hd->master->bl.id>0 ) + { + if ( hd->master != NULL) + return hd->master->status.party_id; + return -1; + } + return 0; //No party. + } if(bl->type==BL_SKILL) return ((struct skill_unit *)bl)->group->party_id; return 0; @@ -3721,6 +3906,16 @@ int status_get_guild_id(struct block_list *bl) return msd->status.guild_id; //Alchemist's mobs [Skotlex] return 0; //No guild. } + if(bl->type==BL_HOMUNCULUS){ //[orn] + struct homun_data *hd=(struct homun_data *)bl; + if( hd->master->bl.id>0 ) + { + if ( hd->master != NULL) + return hd->master->status.guild_id; + return -1; + } + return 0; //No guild. + } if (bl->type == BL_NPC && bl->subtype == SCRIPT) return ((TBL_NPC*)bl)->u.scr.guild_id; if(bl->type==BL_SKILL) @@ -4133,6 +4328,7 @@ int status_get_sc_tick(struct block_list *bl, int type, int tick) int status_change_start(struct block_list *bl,int type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) { struct map_session_data *sd = NULL; + struct homun_data *hd = NULL; struct status_change* sc; struct status_data *status; int opt_flag , calc_flag, undead_flag; @@ -4149,6 +4345,9 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val case BL_PC: sd=(struct map_session_data *)bl; break; + case BL_HOMUNCULUS: + hd=(struct homun_data *)bl; //[orn] + break; case BL_MOB: if (((struct mob_data*)bl)->class_ == MOBID_EMPERIUM && type != SC_SAFETYWALL) return 0; //Emperium can't be afflicted by status changes. @@ -5188,6 +5387,9 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val case SC_AVOID: val2 = 10*val1; //Speed change rate. break; + case SC_DEFENCE: + val2 = 2*val1; //Def bonus + break; case SC_BLOODLUST: val2 = 20+10*val1; //Atk rate change. break; diff --git a/src/map/status.h b/src/map/status.h index 526444ab7..2f35a5fbb 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -253,6 +253,8 @@ enum { SC_CHANGE, SC_BLOODLUST, SC_FLEET, + SC_SPEED, //[orn] + SC_DEFENCE, //[orn] SC_INCAGIRATE, SC_INCDEXRATE, SC_MAX, //Automatically updated max, used in for's and at startup to check we are within bounds. [Skotlex] diff --git a/src/map/unit.c b/src/map/unit.c index 2845ff60b..9dd7b33fc 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -15,6 +15,7 @@ #include "pc.h" #include "mob.h" #include "pet.h" +#include "mercenary.h" ///[orn] #include "skill.h" #include "clif.h" #include "npc.h" @@ -38,6 +39,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl) { if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud; if( bl->type == BL_PET) return &((struct pet_data*)bl)->ud; if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud; + if( bl->type == BL_HOMUNCULUS) return &((struct homun_data*)bl)->ud; //[orn] return NULL; } @@ -100,6 +102,7 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data) struct block_list *bl; struct map_session_data *sd = NULL; struct mob_data *md = NULL; + struct homun_data *hd = NULL; //[orn] struct unit_data *ud = NULL; bl=map_id2bl(id); @@ -109,6 +112,8 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data) ud = &sd->ud; } else if( BL_CAST( BL_MOB, bl, md ) ) { ud = &md->ud; + } else if( BL_CAST( BL_HOMUNCULUS, bl, hd ) ) { //[orn] + ud = &hd->ud; } else ud = unit_bl2ud(bl); @@ -262,6 +267,9 @@ int unit_walktoxy( struct block_list *bl, int x, int y, int easy) { nullpo_retr(0, bl); + if ( status_isdead(bl) ) //[orn] + return 0; + ud = unit_bl2ud(bl); if( ud == NULL) return 0; @@ -707,6 +715,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int struct status_data *tstatus; struct status_change *sc; struct map_session_data *sd = NULL; + struct homun_data *hd = NULL; //[orn] struct block_list * target = NULL; unsigned int tick = gettick(); int temp; @@ -717,6 +726,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int if( BL_CAST( BL_PC, src, sd ) ) { ud = &sd->ud; + } else if( BL_CAST( BL_HOMUNCULUS, src, hd ) ) { //[orn] + ud = &hd->ud; } else ud = unit_bl2ud(src); @@ -1184,6 +1195,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t struct status_data *sstatus; struct map_session_data *sd = NULL; struct mob_data *md = NULL; + struct homun_data *hd = NULL; //[orn] int range; if((ud=unit_bl2ud(src))==NULL) @@ -1195,6 +1207,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t } BL_CAST( BL_PC , src, sd); BL_CAST( BL_MOB, src, md); + BL_CAST( BL_HOMUNCULUS, src, hd); //[orn] ud->attacktimer=-1; target=map_id2bl(ud->target); @@ -1704,6 +1717,16 @@ int unit_free(struct block_list *bl) { } if(mob_is_clone(md->class_)) mob_clone_delete(md->class_); + } else if( bl->type == BL_HOMUNCULUS ) { //[orn] + struct homun_data *hd = (struct homun_data*)bl; + struct map_session_data *sd = hd->master; + merc_hom_hungry_timer_delete(hd); + merc_natural_heal_timer_delete(hd) ; + if (sd) { +// if(hd->intimacy > 0) +// intif_save_mercdata(sd->status.account_id,&sd->hom); + sd->hd = NULL; + } } skill_clear_unitgroup(bl); @@ -1729,4 +1752,3 @@ int do_final_unit(void) { // nothing to do return 0; } - diff --git a/vcproj-7.1/char-server_sql.vcproj b/vcproj-7.1/char-server_sql.vcproj index 877f35c31..fc6acfcc5 100644 --- a/vcproj-7.1/char-server_sql.vcproj +++ b/vcproj-7.1/char-server_sql.vcproj @@ -160,6 +160,9 @@ + + @@ -242,6 +245,9 @@ + + -- cgit v1.2.3-70-g09d2