summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/Makefile3
-rw-r--r--src/map/battle.c10
-rw-r--r--src/map/clif.c32
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/map.h11
-rw-r--r--src/map/mercenary.c344
-rw-r--r--src/map/mercenary.h9
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/pet.c5
-rw-r--r--src/map/status.c143
-rw-r--r--src/map/status.h5
-rw-r--r--src/map/unit.c5
12 files changed, 263 insertions, 309 deletions
diff --git a/src/map/Makefile b/src/map/Makefile
index 20934f7fc..72bac5471 100644
--- a/src/map/Makefile
+++ b/src/map/Makefile
@@ -25,6 +25,7 @@ OBJECTS = obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/status.o obj/npc.o \
obj/storage.o obj/skill.o obj/atcommand.o obj/charcommand.o obj/battle.o \
obj/intif.o obj/trade.o obj/party.o obj/vending.o obj/guild.o obj/pet.o \
obj/log.o obj/mail.o obj/charsave.o obj/date.o obj/irc.o obj/unit.o \
+ obj/mercenary.o \
$(COMMON_OBJ)
map-server: $(OBJECTS:obj/%=txtobj/%)
@@ -71,6 +72,7 @@ txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h cl
txtobj/date.o: date.c date.h $(COMMON_H)
txtobj/irc.o: irc.c irc.h map.h pc.h $(COMMON_H)
txtobj/unit.o: unit.c unit.h $(COMMON_H)
+txtobj/mercenary.o: mercenary.c mercenary.h $(COMMON_H)
sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h irc.h $(COMMON_H)
sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H)
@@ -101,3 +103,4 @@ sqlobj/charsave.o: charsave.c charsave.h $(COMMON_H)
sqlobj/date.o: date.c date.h $(COMMON_H)
sqlobj/irc.o: irc.c irc.h map.h pc.h $(COMMON_H)
sqlobj/unit.o: unit.c unit.h $(COMMON_H)
+sqlobj/mercenary.o: mercenary.c mercenary.h $(COMMON_H)
diff --git a/src/map/battle.c b/src/map/battle.c
index f655c4619..52aee5c69 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3043,9 +3043,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case BL_MOB:
{
TBL_MOB *md = (TBL_MOB*)t_bl;
- if(md->state.killer)
- if(md->master_id != s_bl->id)
- state |= BCT_ENEMY; // If he can attack you, you can attack him.
+ if(md->state.killer) //Enable retaliation
+ state |= BCT_ENEMY;
+
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
return 0; //Disable guardians/emperiums owned by Guilds on non-woe times.
if (md->special_state.ai == 2)
@@ -3062,8 +3062,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return 0; //Pets cannot be targetted.
}
case BL_HOMUNCULUS:
- {
- t_bl=(struct block_list *)((struct homun_data*)target)->master; //...and vice versa.
+ { //Just fallback on master.
+ t_bl=(struct block_list *)((TBL_HOMUNCULUS*)target)->master;
break;
}
case BL_SKILL: //Skill with no owner? Kinda odd... but.. let it through.
diff --git a/src/map/clif.c b/src/map/clif.c
index 7dda64347..3f26df905 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1392,29 +1392,29 @@ int clif_homunack(struct map_session_data *sd)
int clif_homuninfo(struct map_session_data *sd)
{
struct homun_data *hd = sd->hd;
+ struct status_data *status;
unsigned char buf[128];
- nullpo_retr(0, sd);
- nullpo_retr(0, sd->hd);
-
+ nullpo_retr(0, hd);
+ 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)=hd->atk;
- WBUFW(buf,37)=hd->matk;
- WBUFW(buf,39)=hd->hit;
- WBUFW(buf,41)=hd->crit/10; //crit is a +1 decimal value!
- WBUFW(buf,43)=hd->def;
- WBUFW(buf,45)=hd->mdef;
- WBUFW(buf,47)=hd->flee;
- WBUFW(buf,49)=status_get_amotion(&hd->bl)+200; //credits to jA for this field.
- WBUFW(buf,51)=hd->hp;
- WBUFW(buf,53)=hd->max_hp;
- WBUFW(buf,55)=hd->sp;
- WBUFW(buf,57)=hd->max_sp;
+ WBUFW(buf,35)=status->batk;
+ 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,45)=status->mdef;
+ WBUFW(buf,47)=status->flee;
+ WBUFW(buf,49)=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,63)=hd->exp_next;
WBUFW(buf,67)=hd->skillpts;
@@ -8294,7 +8294,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
}
//homunculus [blackhole89]
- if(sd->hd && sd->hd->alive) {
+ if(sd->hd && sd->hd->battle_status.hp) {
map_addblock(&sd->hd->bl);
clif_spawn(&sd->hd->bl);
clif_homunack(sd);
diff --git a/src/map/clif.h b/src/map/clif.h
index b269f90ae..5f1412569 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -335,8 +335,7 @@ void clif_mission_mob(struct map_session_data *sd, unsigned short mob_id, unsign
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_homuninsight(struct block_list *bl,va_list ap);
-int clif_homunoutsight(struct block_list *bl,va_list ap);
+int clif_homunskillinfoblock(struct map_session_data *sd);
#endif
diff --git a/src/map/map.h b/src/map/map.h
index a4d64fc05..b323b1a7e 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -944,11 +944,11 @@ struct homun_data {
struct block_list bl;
struct unit_data ud;
struct view_data *vd;
+ struct status_data base_status, battle_status;
struct status_change sc;
char name[NAME_LENGTH];
int id;
- short speed;
short class_;
struct map_session_data *master; //pointer back to its master
@@ -960,18 +960,10 @@ struct homun_data {
int level;
} hskill[4]; //skills (max. 4 for now)
- int alive; //does it live
-
int target_id,attacked_id;
- int amotion,dmotion;
-
short level;
- short atk,matk,hit,crit,def,mdef,flee,flee2; //flee2 is not transmitted; lucky flee
short regenhp,regensp;
- short str,agi,vit,int_,dex,luk; //According to various sources, they do have these though they aren't transfered to client.
- short hp,max_hp;
- short sp,max_sp;
unsigned long exp,exp_next;
short skillpts;
};
@@ -1476,6 +1468,7 @@ typedef struct flooritem_data TBL_ITEM;
typedef struct chat_data TBL_CHAT;
typedef struct skill_unit TBL_SKILL;
typedef struct pet_data TBL_PET;
+typedef struct homun_data TBL_HOMUNCULUS;
#define BL_CAST(type_, bl , dest) \
(((bl) == NULL || (bl)->type != type_) ? ((dest) = NULL, 0) : ((dest) = (T ## type_ *)(bl), 1))
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index e84acecf6..155222b53 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -71,11 +71,6 @@ int do_init_merc (void)
return 0;
}
-static int dirx[8]={0,-1,-1,-1,0,1,1,1};
-static int diry[8]={1,1,0,-1,-1,-1,0,1};
-
-
-
static unsigned long hexptbl[126];
void merc_load_exptables(void)
@@ -100,100 +95,22 @@ char *merc_skill_get_name(int id)
return merc_skillname[id-8000];
}
-void merc_die(struct map_session_data *sd)
-{
- if(sd->hd)
- {
- sd->hd->alive=0;
- merc_save(sd);
- clif_clearchar_area(&sd->hd->bl,0);
- map_delblock(&sd->hd->bl);
- }
-}
-
-int merc_damage(struct block_list *src,struct homun_data *hd,int damage,int type)
+void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
{
- if(damage > hd->hp) damage = hd->hp;
- hd->hp -= damage;
-
clif_homuninfo(hd->master);
-
- if(hd->hp == 0)
- {
- //dead lol
- clif_clearchar((struct block_list*)hd,1);
- hd->bl.m = 0;
- hd->bl.x = 0;
- hd->bl.y = 0; //send it somewhere where it doesn't bother us
- merc_save(hd->master);
- merc_die(hd->master);
- return damage;
- }
-
- merc_save(hd->master);
- return damage;
}
-void merc_calc_status(struct homun_data *hd)
+int merc_dead(struct homun_data *hd, struct block_list *src)
{
- int dstr;
- int atk_rate=100,aspd_rate=100,speed_rate=100;
-
- // attack
- dstr = hd->str/10;
- hd->atk = hd->str + dstr*dstr + hd->dex/5;
-
- // matk
- hd->matk = hd->int_+(hd->int_/6)*(hd->int_/6);
-
- // crit
- hd->crit = (hd->luk*3)+10; //x.1
-
- // hit
- hd->hit = hd->dex + hd->level;
-
- // flee
- hd->flee = hd->agi + hd->level;
-
- // lucky flee
- hd->flee2 = hd->luk+10; //x.1
-
- // def
- hd->def = hd->vit;
-
- // mdef
- hd->mdef = hd->int_;
-
- // hp recovery
- hd->regenhp = 1 + (hd->vit/5) + (hd->max_hp/200);
-
- // sp recovery
- hd->regensp = 1 + (hd->int_/6) + (hd->max_sp/100);
- if(hd->int_ >= 120)
- hd->regensp += ((hd->int_-120)>>1) + 4;
-
- if(hd->sc_count && hd->sc.data)
- {
-
- if(hd->sc.data[SC_AVOID].timer!=-1)
- speed_rate -= hd->sc.data[SC_AVOID].val1*10;
-
- if(hd->sc.data[SC_CHANGE].timer!=-1)
- hd->int_ += 60;
-
- if(hd->sc.data[SC_BLOODLUST].timer!=-1)
- atk_rate += hd->sc.data[SC_BLOODLUST].val1*10+20;
-
- if(hd->sc.data[SC_FLEET].timer!=-1)
- {
- aspd_rate -= hd->sc.data[SC_FLEET].val1*3;
- atk_rate+=5+hd->sc.data[SC_FLEET].val1*5;
- }
- }
-
- hd->amotion = 1800 - (1800 * hd->agi / 250 + 1800 * hd->dex / 1000);
- hd->amotion -= 200;
- hd->dmotion=hd->amotion;
+ //dead lol
+ clif_clearchar((struct block_list*)hd,1);
+ hd->bl.m = 0;
+ hd->bl.x = 0;
+ hd->bl.y = 0; //send it somewhere where it doesn't bother us
+ merc_save(hd->master);
+ clif_clearchar_area(&hd->bl,0);
+ map_delblock(&hd->bl);
+ return 1;
}
void merc_skillup(struct map_session_data *sd,short skillnum)
@@ -213,113 +130,31 @@ void merc_skillup(struct map_session_data *sd,short skillnum)
merc_save(sd);
}
-void merc_calc_stats(struct homun_data *hd)
-{
- /* very proprietary */
- int l,i;
- l=hd->level;
- hd->max_hp=500+l*10+l*l;
- hd->max_sp=300+l*11+l*l*90/100;
-/* hd->atk=10+l*5+l*l/125;
- hd->matk=6+l*6+l*l/120;
- hd->hit=3+l+l*l/200;
- hd->crit=1+l*69/125;
- hd->def=5+l+l*l/119;
- hd->mdef=1+l+l*l/80;
- hd->flee=7+l+l*l/150; */ // obsolete
- switch(hd->class_)
- {
- case 6001: //LIF ~ int,dex,vit
- hd->str = 3+l/7;
- hd->agi = 3+2*l/5;
- hd->vit = 4+l;
- hd->int_ = 4+3*l/4;
- hd->dex = 4+2*l/3;
- hd->luk = 3+l/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
- hd->str = 4+3*l/4;
- hd->agi = 4+2*l/3;
- hd->vit = 3+2*l/5;
- hd->int_ = 3+l/4;
- hd->dex = 4+l;
- hd->luk = 3+l/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
- hd->str = 4+l;
- hd->agi = 3+l/4;
- hd->vit = 3+3*l/4;
- hd->int_ = 3+1/10;
- hd->dex = 3+2*l/5;
- hd->luk = 4+2*l/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
- hd->str = 3+l/4;
- hd->agi = 3+l/7;
- hd->vit = 3+2*l/5;
- hd->int_ = 4+l;
- hd->dex = 4+2*l/3;
- hd->luk = 4+3*l/4;
- for(i=8013;i<8017;++i)
- {
- hd->hskill[i-8013].id=i;
- //hd->hskill[i-8013].level=1;
- }
- break;
- }
- merc_calc_status(hd);
- hd->exp_next=hexptbl[l-1];
-}
-
int merc_gainexp(struct homun_data *hd,int exp)
{
hd->exp += exp;
- if(hd->exp > hd->exp_next) //levelup
+ if(hd->exp < hd->exp_next)
+ return 0;
+ //levelup
+ do
{
- while(hd->exp > hd->exp_next)
- {
- hd->exp-=hd->exp_next;
- hd->level += 1;
-
- clif_misceffect(&hd->bl,0);
- merc_calc_stats(hd);
- hd->hp=hd->max_hp;
- hd->sp=hd->max_sp;
- }
+ hd->exp-=hd->exp_next;
+ hd->exp_next=hexptbl[hd->level];
+ hd->level++;
}
-
- merc_save(hd->master);
+ while(hd->exp > hd->exp_next);
+
+ clif_misceffect(&hd->bl,0);
+ status_calc_homunculus(hd,0);
+ status_percent_heal(&hd->bl, 100, 100);
clif_homuninfo(hd->master);
return 0;
}
-int merc_heal(struct homun_data *hd,int hp,int sp)
+void merc_heal(struct homun_data *hd,int hp,int sp)
{
- hd->hp+=hp;
- hd->sp+=sp;
- if(hd->max_hp < hd->hp) hd->hp = hd->max_hp;
- if(hd->max_sp < hd->sp) hd->sp = hd->max_sp;
-
- merc_save(hd->master);
clif_homuninfo(hd->master);
-
- return hp+sp;
}
void merc_save(struct map_session_data *sd)
@@ -337,30 +172,29 @@ void merc_save(struct map_session_data *sd)
#endif
}
-//not nice, but works
-void merc_res(struct map_session_data *sd,int skilllv)
+static void merc_load_sub(struct homun_data *hd, struct map_session_data *sd)
{
- sprintf(tmp_sql, "UPDATE `homunculus` SET `hp`='10' WHERE `char_id` = '%d' AND `hp`=0",sd->char_id);
- if(mysql_query(&mmysql_handle, tmp_sql)){
- ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- return;
- }
- if(sd->hd)
- {
- sd->hd->hp=skilllv*sd->hd->max_hp/10;
- sd->hd->alive=1;
- }
-}
+ hd->bl.m=sd->bl.m;
+ hd->bl.x=sd->bl.x;
+ hd->bl.y=sd->bl.y;
+ hd->bl.type=BL_HOMUNCULUS;
+ hd->bl.id= npc_get_new_npc_id();
+ hd->bl.prev=NULL;
+ hd->bl.next=NULL;
+ status_set_viewdata(&hd->bl, hd->class_);
+ status_change_init(&hd->bl);
+ unit_dataset(&hd->bl);
+
+ map_addiddb(&hd->bl);
+ status_calc_homunculus(hd,1); //this function will have more sense later on
+}
+#ifndef TXT_ONLY
void merc_load(struct map_session_data *sd)
{
struct homun_data *hd;
- int alive=1;
-
sd->hd=NULL;
-
-#ifndef TXT_ONLY
+
sprintf(tmp_sql, "SELECT `id`,`class`,`name`,`level`,`exp`,`hunger`,`hp`,`sp`,`skill1lv`,`skill2lv`,`skill3lv`,`skill4lv`,`skillpts` FROM `homunculus` WHERE `char_id` = '%d'", sd->char_id);
if(mysql_query(&mmysql_handle, tmp_sql)){
ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle));
@@ -369,42 +203,25 @@ void merc_load(struct map_session_data *sd)
}
sql_res = mysql_store_result(&mmysql_handle);
+ if(!sql_res)
+ return;
+
if(mysql_num_rows(sql_res) <= 0){
mysql_free_result(sql_res);
return; //no homunculus for this char
- }
sql_row = mysql_fetch_row(sql_res);
- if(atoi(sql_row[6])==0) alive=0; //it is dead
-#else
- int id,charid,class_,level,exp,hunger,hp,sp;
- char name[24];
- FILE *fl=fopen("save/homunculus.txt","r");
-
- ShowInfo("Looking up Homunculus for %d...\n",sd->char_id);
- charid=1;
- while(charid!=0)
- {
- fscanf(fl,"%d,%d,%d,%s ,%d,%d,%d,%d,%d\n",&id,&charid,&class_,name,&level,&exp,&hunger,&hp,&sp);
- ShowInfo("%d",charid);
- if(charid==sd->char_id) goto gotit;
- }
- return; //none found
-gotit:
- ShowInfo("found it!\n");
-#endif
//dummy code
hd=(struct homun_data *) aCalloc(1, sizeof(struct homun_data));
sd->hd=hd; //pointer from master to homunculus
memset(hd,0,sizeof(struct homun_data));
hd->master=sd; //pointer from homunculus to master
-#ifndef TXT_ONLY
hd->id=atoi(sql_row[0]);
hd->class_=atoi(sql_row[1]);
hd->level=atoi(sql_row[3]);
- hd->hp=atoi(sql_row[6]);
- hd->sp=atoi(sql_row[7]);
+ hd->battle_status.hp=atoi(sql_row[6]);
+ hd->battle_status.sp=atoi(sql_row[7]);
hd->exp=atoi(sql_row[4]);
hd->hunger_rate=atoi(sql_row[5]);
hd->hskill[0].level=atoi(sql_row[8]);
@@ -412,44 +229,48 @@ gotit:
hd->hskill[2].level=atoi(sql_row[10]);
hd->hskill[3].level=atoi(sql_row[11]);
hd->skillpts=atoi(sql_row[12]);
- memcpy(hd->name,sql_row[2],strlen(sql_row[2])<24?strlen(sql_row[2]):24);
-#else
+ hd->exp_next=hexptbl[hd->level-1];
+ strncpy(hd->name,sql_row[2],NAME_LENGTH);
+ mysql_free_result(sql_res);
+ merc_load_sub(hd, sd);
+}
+#else
+void merc_load(struct map_session_data *sd)
+{
+ struct homun_data *hd;
+ int id,charid,class_,level,exp,hunger,hp,sp;
+ char name[24];
+ FILE *fl=fopen("save/homunculus.txt","r");
+ sd->hd=NULL;
+
+ if(!fl) return; //Unable to open file.
+ ShowInfo("Looking up Homunculus for %d...\n",sd->char_id);
+ do {
+ fscanf(fl,"%d,%d,%d,%s ,%d,%d,%d,%d,%d\n",&id,&charid,&class_,name,&level,&exp,&hunger,&hp,&sp);
+ ShowInfo("%d",charid);
+ if(charid==sd->char_id) break;
+ } while(charid!=0);
+ if (!charid)
+ return; //none found
+ ShowInfo("found it!\n");
+
+ //dummy code
+ hd=(struct homun_data *) aCalloc(1, sizeof(struct homun_data));
+ sd->hd=hd; //pointer from master to homunculus
+ memset(hd,0,sizeof(struct homun_data));
+ hd->master=sd; //pointer from homunculus to master
hd->id=id;
hd->class_=class_;
hd->level=level;
hd->exp=exp;
hd->hunger_rate=hunger;
- hd->hp=hp;
- hd->sp=sp;
- memcpy(hd->name,name,strlen(name)<24?strlen(name):24);
-#endif
- hd->alive=alive;
-
- hd->speed=0x96;
-
- hd->bl.m=sd->bl.m;
- hd->bl.x=sd->bl.x;
- hd->bl.y=sd->bl.y;
- hd->bl.type=BL_HOMUNCULUS;
- hd->bl.id= npc_get_new_npc_id();
- hd->bl.prev=NULL;
- hd->bl.next=NULL;
-
- status_set_viewdata(&hd->bl, hd->class_);
- status_change_init(&hd->bl);
- unit_dataset(&hd->bl);
-
- map_addiddb(&hd->bl);
-
- merc_calc_stats(hd); //this function will have more sense later on
-
- mysql_free_result(sql_res);
-
-//clif_spawnhomun(hd);
-// clif_homunack(sd);
-// clif_homuninfo(sd);
-// clif_homuninfo(sd); // send this x2. dunno why, but kRO does that [blackhole89]
+ hd->battle_status.hp=hp;
+ hd->battle_status.sp=sp;
+ hd->exp_next=hexptbl[hd->level-1];
+ strncpy(hd->name,name,NAME_LENGTH);
+ merc_load_sub(hd, sd);
}
+#endif
int merc_create_homunculus(struct map_session_data *sd,int id,int m,int x,int y)
{
@@ -496,6 +317,7 @@ int merc_create_homunculus(struct map_session_data *sd,int id,int m,int x,int y)
clif_homunack(sd);
clif_homuninfo(sd);
clif_homuninfo(sd);*/ // send this x2. dunno why, but kRO does that [blackhole89]
+ return 0;
}
int do_final_merc (void);
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index e4db4e54a..aae36cbcb 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -3,14 +3,11 @@
int do_init_merc (void);
void merc_load_exptables(void);
char *merc_skill_get_name(int id);
-void merc_die(struct map_session_data *sd);
-int merc_damage(struct block_list *src,struct homun_data *hd,int damage,int type);
-void merc_calc_status(struct homun_data *hd);
+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);
-void merc_calc_stats(struct homun_data *hd);
int merc_gainexp(struct homun_data *hd,int exp);
-int merc_heal(struct homun_data *hd,int hp,int sp);
+void merc_heal(struct homun_data *hd,int hp,int sp);
void merc_save(struct map_session_data *sd);
-void merc_res(struct map_session_data *sd,int skilllv);
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);
diff --git a/src/map/npc.c b/src/map/npc.c
index 93fc25e04..3c4e09b41 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -945,7 +945,7 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y)
switch(map[m].npc[i]->bl.subtype) {
case WARP:
// hidden chars cannot use warps -- is it the same for scripts too?
- if (sd->sc.option&6 ||
+ if (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) ||
(!battle_config.duel_allow_teleport && sd->duel_group)) // duel rstrct [LuzZza]
break;
pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,0);
diff --git a/src/map/pet.c b/src/map/pet.c
index 39e16ea70..2b349daff 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -893,13 +893,14 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
return 0;
}
- if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range2) && DIFF_TICK(tick, pd->ud.canmove_tick) > 0) {
+ if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range2)) {
//Master too far, chase.
if(pd->target_id)
pet_unlocktarget(pd);
if(pd->ud.walktimer != -1 && pd->ud.target == sd->bl.id)
return 0; //Already walking to him
-
+ if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0)
+ return 0; //Can't move yet.
pd->status.speed = (sd->battle_status.speed>>1);
if(pd->status.speed <= 0)
pd->status.speed = 1;
diff --git a/src/map/status.c b/src/map/status.c
index eaa6b8c72..7b95364b8 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -23,6 +23,7 @@
#include "status.h"
#include "script.h"
#include "unit.h"
+#include "mercenary.h"
#include "../common/timer.h"
#include "../common/nullpo.h"
@@ -355,6 +356,10 @@ void initChangeTables(void) {
// set_sc(NJ_KAENSIN, SC_KAENSIN, SI_BLANK);
set_sc(NJ_SUITON, SC_SUITON, SI_BLANK, SCB_AGI);
set_sc(NJ_NEN, SC_NEN, SI_NEN, SCB_STR|SCB_INT);
+ set_sc(HLIF_AVOID, SC_AVOID, SI_BLANK, SCB_SPEED);
+ 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);
// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
SkillStatusChangeTable[SL_ALCHEMIST] = MAPID_ALCHEMIST,
@@ -587,6 +592,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
if (!status->hp)
pc_dead((TBL_PC*)target,src);
break;
+ case BL_HOMUNCULUS:
+ merc_damage((TBL_HOMUNCULUS*)target,src,hp,sp);
+ if (!status->hp)
+ merc_dead((TBL_HOMUNCULUS*)target,src);
}
if (walkdelay && status->hp)
@@ -655,6 +664,9 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
case BL_PC:
pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0);
break;
+ case BL_HOMUNCULUS:
+ merc_heal((TBL_HOMUNCULUS*)bl,hp,sp);
+ break;
}
return hp+sp;
}
@@ -1151,6 +1163,7 @@ int status_calc_pet(struct pet_data *pd, int first)
if(status->rhw.atk2 > battle_config.pet_max_atk2)
status->rhw.atk2 = battle_config.pet_max_atk2;
+ status->str = cap_value(status->str,1,battle_config.pet_max_stats);
if(status->str > battle_config.pet_max_stats)
status->str = battle_config.pet_max_stats;
else if (status->str < 1) status->str = 1;
@@ -1191,6 +1204,96 @@ 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->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;
@@ -2632,6 +2735,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
int_ -= int_ * sc->data[SC_STRIPHELM].val2/100;
if(sc->data[SC_NEN].timer!=-1)
int_ += sc->data[SC_NEN].val1;
+ if(sc->data[SC_CHANGE].timer!=-1)
+ int_ += 60;
if(sc->data[SC_MARIONETTE].timer!=-1)
int_ -= (sc->data[SC_MARIONETTE].val4>>16)&0xFF;
if(sc->data[SC_MARIONETTE2].timer!=-1)
@@ -2725,6 +2830,10 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
batk += batk * sc->data[SC_CONCENTRATION].val2/100;
if(sc->data[SC_SKE].timer!=-1)
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)
@@ -2768,6 +2877,10 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
watk += sc->data[SC_NIBELUNGEN].val2;
}
}
+ 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)
@@ -3000,6 +3113,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
speed -= speed * 20/100;
else if(sc->data[SC_BERSERK].timer!=-1)
speed -= speed * 20/100;
+ else if(sc->data[SC_AVOID].timer!=-1)
+ speed -= speed * sc->data[SC_AVOID].val2/100;
else if(sc->data[SC_WINDWALK].timer!=-1)
speed -= speed * sc->data[SC_WINDWALK].val3/100;
if(sc->data[SC_SLOWDOWN].timer!=-1)
@@ -3081,6 +3196,10 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
max < sc->data[SC_GATLINGFEVER].val2)
max = sc->data[SC_GATLINGFEVER].val2;
+ if(sc->data[SC_FLEET].timer!=-1 &&
+ max < sc->data[SC_FLEET].val2)
+ max = sc->data[SC_FLEET].val2;
+
if(sc->data[SC_ASSNCROS].timer!=-1 &&
max < sc->data[SC_ASSNCROS].val2)
{
@@ -3288,12 +3407,14 @@ int status_get_lv(struct block_list *bl)
{
nullpo_retr(0, bl);
if(bl->type==BL_MOB)
- return ((struct mob_data *)bl)->level;
+ return ((TBL_MOB*)bl)->level;
if(bl->type==BL_PC)
- return ((struct map_session_data *)bl)->status.base_level;
+ return ((TBL_PC*)bl)->status.base_level;
if(bl->type==BL_PET)
- return ((struct pet_data *)bl)->msd->pet.level;
- return 0;
+ return ((TBL_PET*)bl)->msd->pet.level;
+ if(bl->type==BL_HOMUNCULUS)
+ return ((TBL_HOMUNCULUS*)bl)->level;
+ return 1;
}
struct status_data *status_get_status_data(struct block_list *bl)
@@ -3307,6 +3428,8 @@ struct status_data *status_get_status_data(struct block_list *bl)
return &((TBL_MOB*)bl)->status;
case BL_PET:
return &((TBL_PET*)bl)->status;
+ case BL_HOMUNCULUS:
+ return &((TBL_HOMUNCULUS*)bl)->battle_status;
default:
return &dummy_status;
}
@@ -3324,6 +3447,8 @@ struct status_data *status_get_base_status(struct block_list *bl)
&((TBL_MOB*)bl)->db->status;
case BL_PET:
return &((TBL_PET*)bl)->db->status;
+ case BL_HOMUNCULUS:
+ return &((TBL_HOMUNCULUS*)bl)->base_status;
default:
return NULL;
}
@@ -4848,6 +4973,16 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
val3 = 2+3*val1; //Atk increase
val4 = 5+5*val1; //Def reduction.
break;
+ case SC_AVOID:
+ val2 = 10*val1; //Speed change rate.
+ break;
+ case SC_BLOODLUST:
+ val2 = 20+10*val1; //Atk rate change.
+ break;
+ case SC_FLEET:
+ val2 = 3*val1; //Aspd change
+ val3 = 5+5*val1; //Atk rate change
+ break;
default:
if (calc_flag == SCB_NONE && StatusSkillChangeTable[type]==0)
{ //Status change with no calc, and no skill associated...? unknown?
diff --git a/src/map/status.h b/src/map/status.h
index 25f6b6734..a13ee7698 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -249,6 +249,10 @@ enum {
SC_KNOWLEDGE,
SC_SMA,
SC_FLING,
+ SC_AVOID, //240
+ SC_CHANGE,
+ SC_BLOODLUST,
+ SC_FLEET,
SC_MAX, //Automatically updated max, used in for's and at startup to check we are within bounds. [Skotlex]
};
extern int SkillStatusChangeTable[MAX_SKILL];
@@ -601,6 +605,7 @@ void status_calc_bl(struct block_list *bl, unsigned long flag);
int status_calc_pet(struct pet_data* pd, int first); // [Skotlex]
int status_calc_pc(struct map_session_data* sd,int first);
int status_calc_mob(struct mob_data* md, int first); //[Skotlex]
+int status_calc_homunculus(struct homun_data *hd, int first);
void status_calc_misc(struct status_data *status, int level);
void status_freecast_switch(struct map_session_data *sd);
diff --git a/src/map/unit.c b/src/map/unit.c
index 39b8c45dc..02a95fd34 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1272,11 +1272,10 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
if(sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support)
pet_target_check(sd,target,0);
- map_freeblock_unlock();
-
-ud->attackabletime = tick + sstatus->adelay;
+ map_freeblock_unlock();
+ ud->attackabletime = tick + sstatus->adelay;
// You can't move if you can't attack neither.
unit_set_walkdelay(src, tick, sstatus->amotion, 1);
}