From a1fddcf716995eddf1c26e1395c8cc24ce6b3eba Mon Sep 17 00:00:00 2001 From: skotlex Date: Tue, 30 May 2006 15:29:17 +0000 Subject: - Small optimization in battle_check_target - Disabled ontouch npcs triggering on hidden/chase-walk characters. - Added the SC* code blocks relevant to SC_AVOID, SC_CHANGE, SC_BLOODLUST, SC_FLEET - Added structure status_data to homun_data - Added handling of BL_HOMUNCULUS in status_heal, status_damage. - Cleaned up the homun-submitted code, moved the relevant code to status_calc_homunculus. - Updated map-server Makefile to compile mercenary.* files. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6847 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 5 + src/map/Makefile | 3 + src/map/battle.c | 10 +- src/map/clif.c | 32 ++--- src/map/clif.h | 3 +- src/map/map.h | 11 +- src/map/mercenary.c | 344 +++++++++++++--------------------------------------- src/map/mercenary.h | 9 +- src/map/npc.c | 2 +- src/map/pet.c | 5 +- src/map/status.c | 143 +++++++++++++++++++++- src/map/status.h | 5 + src/map/unit.c | 5 +- 13 files changed, 268 insertions(+), 309 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index e39f0ac0f..b71a20edf 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,11 @@ 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/05/30 + * Disabled ontouch npcs triggering on hidden/chase-walk characters. + [Skotlex] + * Updated/adapted current Homun code to use the status_data update. + [Skotlex] + * Updated map-server Makefile to compile mercenary.* files. [Skotlex] * [Fixed]: - Pets attacking even master is dead. [Lance] * Fixed battle_calc_weapon_attack damage capping damage to a minimum of 0 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); } -- cgit v1.2.3-70-g09d2