diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/Makefile | 3 | ||||
-rw-r--r-- | src/map/battle.c | 10 | ||||
-rw-r--r-- | src/map/clif.c | 32 | ||||
-rw-r--r-- | src/map/clif.h | 3 | ||||
-rw-r--r-- | src/map/map.h | 11 | ||||
-rw-r--r-- | src/map/mercenary.c | 344 | ||||
-rw-r--r-- | src/map/mercenary.h | 9 | ||||
-rw-r--r-- | src/map/npc.c | 2 | ||||
-rw-r--r-- | src/map/pet.c | 5 | ||||
-rw-r--r-- | src/map/status.c | 143 | ||||
-rw-r--r-- | src/map/status.h | 5 | ||||
-rw-r--r-- | src/map/unit.c | 5 |
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);
}
|