Orn's and Albator's Homunculus system, finally, YAY!!

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@7706 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
DracoRPG 2006-07-17 00:15:33 +00:00
parent 18d00eb924
commit 15dd140846
44 changed files with 3845 additions and 1068 deletions

View File

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

View File

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

100
db/exp_homun.txt Normal file
View File

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

73
db/homun_skill_tree.txt Normal file
View File

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

17
db/homunculus_db.txt Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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#ケミカルア?マ?チャ?ジ#
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#ケミカルヘルムチャ?ジ#
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#オ?トガ?ド#
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#シ?ルドチャ?ジ#
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#シ?ルドブ?メラン#
@ -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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

300
src/char_sql/int_homun.c Normal file
View File

@ -0,0 +1,300 @@
// Homunculus saving by Albator and Orn for eAthena.
// GNU/GPL rulez !
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;i<MAX_HOMUNSKILL;i++)
hd->hskill[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; i<MAX_HOMUNSKILL; i++)
{
if(hd->hskill[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;
}

14
src/char_sql/int_homun.h Normal file
View File

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

View File

@ -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データの生存時間(60秒)
#define WISDELLIST_MAX 256 // Wisデータ削除リストの要素数
@ -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鯖管轄かを調べる
// interŽIŠÇŠ<EFBFBD>©ð²×
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;
}

View File

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

View File

@ -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[]<EFBFBD>\¢ÌÌè`
*------------------------------------------
@ -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

View File

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

View File

@ -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;
}
/*==========================================

View File

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

View File

@ -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)) && i<MAX_FRIENDS; i++)
@ -273,6 +277,7 @@ int charsave_savechar(int charid, struct mmo_charstatus *c){
// char tmp_str[64];
// char tmp_str2[512];
//First save the 'char'
ShowDebug("charsave_savechar : charid = %d | hd->master->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)

View File

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

View File

@ -22,6 +22,7 @@
#include "npc.h"
#include "pc.h"
#include "status.h"
#include "mercenary.h"
#ifndef TXT_ONLY
#include "charsave.h"
#endif

View File

@ -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;
}
// like skillinfoblock, just for homunculi.
int clif_homunskillinfoblock(struct map_session_data *sd)
{
/*==========================================
*
*------------------------------------------
*/
void clif_send_homdata(struct map_session_data *sd, int type, int param) { //[orn]
int fd;
int i,c,len=4,id/*, inf2*/;
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_homskillinfoblock(struct map_session_data *sd) { //[orn]
int fd;
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) { // 切断待ちの場合パケットを処理しない
@ -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}
};

View File

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

View File

@ -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を使う
@ -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からの通信
// エラーがあれば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));

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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_range<md->status.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;i<DAMAGELOG_SIZE && md->dmglog[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;i<DAMAGELOG_SIZE && tmpsd[i];i++){
for(i=0;i<DAMAGELOG_SIZE && tmpbl[i];i++){
int flag=1,zeny=0;
unsigned int base_exp,job_exp;
double per; //Your share of the mob's exp
@ -1835,7 +1859,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
job_exp = 1;
}
if((temp=tmpsd[i]->status.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;j<pnum && pt[j].id!=temp;j++); //Locate party.
@ -1866,11 +1890,22 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
flag=0;
}
}
if(flag) {
if(base_exp || job_exp)
pc_gainexp(tmpsd[i], &md->bl, 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 ;
}
}
}

View File

@ -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);
// パ?ティ、ギルドデ?タの要求
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)

View File

@ -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»@Žgp
*------------------------------------------
@ -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);

View File

@ -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(rnd<per[skilllv-1][0])
{
heal_target = &hd->bl;
}else if(rnd<per[skilllv-1][1])
{
if(!status_isdead(&hd->master->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;
}
/*==========================================
*
*------------------------------------------
*/
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);

View File

@ -237,6 +237,8 @@ int skill_check_cloaking(struct block_list *bl, struct status_change *sc);
// ステ?タス異常
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]
// アイテム作成
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]
// スキル攻?一括?理
int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,

View File

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

View File

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

View File

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

View File

@ -160,6 +160,9 @@
<File
RelativePath="..\src\char_sql\int_guild.c">
</File>
<File
RelativePath="..\src\char_sql\int_homun.c">
</File>
<File
RelativePath="..\src\char_sql\int_party.c">
</File>
@ -242,6 +245,9 @@
<File
RelativePath="..\src\char_sql\int_guild.h">
</File>
<File
RelativePath="..\src\char_sql\int_homun.h">
</File>
<File
RelativePath="..\src\char_sql\int_party.h">
</File>