From 8cb6244382cb6e1bb8b2edd13bba6b91f9c67b1f Mon Sep 17 00:00:00 2001 From: zephyrus Date: Sun, 24 Aug 2008 13:33:36 +0000 Subject: - Implemented unit_calc_pos (copy from pet_calc_pos) to implement it on Mercenary/Homunculus and don't use x,y-1 always. - Implemented Mercenary walk to master (same packet as Homunculus). - Starting work on Stats but i will need lot of help. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13121 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/clif.c | 24 ++++++++++++----- src/map/mercenary.c | 22 +++++---------- src/map/mercenary.h | 2 +- src/map/pet.c | 57 ++------------------------------------- src/map/status.c | 78 ++++++++++++++++++++++++++++++++++++++++------------- src/map/status.h | 5 ++-- src/map/unit.c | 56 ++++++++++++++++++++++++++++++++++++++ src/map/unit.h | 1 + 8 files changed, 147 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/map/clif.c b/src/map/clif.c index a82495aa0..78d73bca0 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11270,10 +11270,19 @@ void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) { - if(!merc_is_hom_active(sd->hd)) - return; + int id = RFIFOL(fd,2); // Mercenary or Homunculus + struct block_list *bl = NULL; + struct unit_data *ud = NULL; + + if( sd->md && sd->md->bl.id == id ) + bl = &sd->md->bl; + else if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + bl = &sd->hd->bl; // Moving Homunculus + else return; - unit_walktoxy(&sd->hd->bl, sd->bl.x,sd->bl.y-1, 4); + unit_calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir); + ud = unit_bl2ud(bl); + unit_walktoxy(bl, ud->to_x, ud->to_y, 4); } void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) @@ -12349,6 +12358,7 @@ void clif_mercenary_info(struct map_session_data *sd) int fd; struct mercenary_data *md; struct status_data *status; + int atk; if( sd == NULL || (md = sd->md) == NULL ) return; @@ -12359,14 +12369,16 @@ void clif_mercenary_info(struct map_session_data *sd) WFIFOHEAD(fd,80); WFIFOW(fd,0) = 0x029b; WFIFOL(fd,2) = md->bl.id; - WFIFOW(fd,6) = cap_value(status->rhw.atk2+status->batk, 0, SHRT_MAX); + // Mercenary shows ATK as a random value between ATK ~ ATK2 + atk = rand()%(status->rhw.atk - status->rhw.atk2 + 1) + status->rhw.atk; + WFIFOW(fd,6) = cap_value(atk, 0, SHRT_MAX); WFIFOW(fd,8) = cap_value(status->matk_max, 0, SHRT_MAX); WFIFOW(fd,10) = status->hit; WFIFOW(fd,12) = status->cri/10; - WFIFOW(fd,14) = status->def + status->vit; + WFIFOW(fd,14) = status->def + (status->vit/2); WFIFOW(fd,16) = status->mdef; WFIFOW(fd,18) = status->flee; - WFIFOW(fd,20) = status->amotion; + WFIFOW(fd,20) = status->aspd_rate; safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH); WFIFOW(fd,46) = md->db->lv; WFIFOL(fd,48) = status->hp; diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 16851d8f7..a127f7fad 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -120,8 +120,6 @@ int merc_data_received(struct s_mercenary *merc, bool flag) if( !sd->md ) { - short x = sd->bl.x, y = sd->bl.y; - sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); md->bl.type = BL_MER; md->bl.id = npc_get_new_npc_id(); @@ -137,14 +135,12 @@ int merc_data_received(struct s_mercenary *merc, bool flag) md->bl.m = sd->bl.m; md->bl.x = sd->bl.x; md->bl.y = sd->bl.y; - x = sd->bl.x + 1; - y = sd->bl.y + 1; - map_random_dir(&md->bl, &x, &y); - md->bl.x = x; - md->bl.y = y; + unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + md->bl.x = md->ud.to_x; + md->bl.y = md->ud.to_y; map_addiddb(&md->bl); - // status_calc_mercenary(md,1); + status_calc_mercenary(md,1); } else memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); @@ -719,8 +715,6 @@ int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) { struct homun_data *hd; int i = 0; - short x,y; - nullpo_retr(1, sd); Assert((sd->status.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); @@ -750,11 +744,9 @@ int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) hd->bl.m = sd->bl.m; hd->bl.x = sd->bl.x; hd->bl.y = sd->bl.y; - x = sd->bl.x + 1; - y = sd->bl.y + 1; - map_random_dir(&hd->bl, &x, &y); - hd->bl.x = x; - hd->bl.y = y; + unit_calc_pos(&hd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + hd->bl.x = hd->ud.to_x; + hd->bl.y = hd->ud.to_y; map_addiddb(&hd->bl); status_calc_homunculus(hd,1); diff --git a/src/map/mercenary.h b/src/map/mercenary.h index a9e572f50..17a519cc7 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -28,7 +28,7 @@ struct mercenary_data { struct block_list bl; struct unit_data ud; struct view_data *vd; - struct status_data *base_status, battle_status; + struct status_data base_status, battle_status; struct status_change sc; struct regen_data regen; diff --git a/src/map/pet.c b/src/map/pet.c index f439c793f..3c3d33d1d 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -56,59 +56,6 @@ int pet_hungry_val(struct pet_data *pd) return 0; } -static int pet_calc_pos(struct pet_data *pd,int tx,int ty,int dir) -{ - int x,y,dx,dy; - int i,k; - - nullpo_retr(0, pd); - - pd->ud.to_x = tx; - pd->ud.to_y = ty; - - if(dir < 0 || dir >= 8) - return 1; - - dx = -dirx[dir]*2; - dy = -diry[dir]*2; - x = tx + dx; - y = ty + dy; - if(!unit_can_reach_pos(&pd->bl,x,y,0)) { - if(dx > 0) x--; - else if(dx < 0) x++; - if(dy > 0) y--; - else if(dy < 0) y++; - if(!unit_can_reach_pos(&pd->bl,x,y,0)) { - for(i=0;i<12;i++) { - k = rand()%8; - dx = -dirx[k]*2; - dy = -diry[k]*2; - x = tx + dx; - y = ty + dy; - if(unit_can_reach_pos(&pd->bl,x,y,0)) - break; - else { - if(dx > 0) x--; - else if(dx < 0) x++; - if(dy > 0) y--; - else if(dy < 0) y++; - if(unit_can_reach_pos(&pd->bl,x,y,0)) - break; - } - } - if(i>=12) { - x = tx; - y = ty; - if(!unit_can_reach_pos(&pd->bl,x,y,0)) - return 1; - } - } - } - pd->ud.to_x = x; - pd->ud.to_y = y; - return 0; -} - int pet_create_egg(struct map_session_data *sd, int item_id) { int pet_id = search_petDB_index(item_id, PET_EGG); @@ -392,7 +339,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet) pd->bl.m = sd->bl.m; pd->bl.x = sd->bl.x; pd->bl.y = sd->bl.y; - pet_calc_pos(pd,sd->bl.x,sd->bl.y,sd->ud.dir); + unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); pd->bl.x = pd->ud.to_x; pd->bl.y = pd->ud.to_y; pd->bl.id = npc_get_new_npc_id(); @@ -920,7 +867,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns if(pd->ud.walktimer != -1 && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3)) return 0; //Already walking to him - pet_calc_pos(pd,sd->bl.x,sd->bl.y,sd->ud.dir); + unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); if(!unit_walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0)) pet_randomwalk(pd,tick); diff --git a/src/map/status.c b/src/map/status.c index c77e0ffcc..0065ad15c 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1247,7 +1247,7 @@ static unsigned short status_base_atk(struct block_list *bl, struct status_data void status_calc_misc(struct block_list *bl, struct status_data *status, int level) { //Non players get the value set, players need to stack with previous bonuses. - if (bl->type != BL_PC) + if( bl->type != BL_PC ) status->batk = status->hit = status->flee = status->def2 = status->mdef2 = @@ -1261,7 +1261,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev status->def2 += status->vit; status->mdef2 += status->int_ + (status->vit>>1); - if (bl->type&battle_config.enable_critical) + if( bl->type&battle_config.enable_critical ) status->cri += status->luk*3 + 10; else status->cri = 0; @@ -2374,6 +2374,31 @@ int status_calc_pc(struct map_session_data* sd,int first) return 0; } +int status_calc_mercenary(struct mercenary_data *md, int first) +{ + struct status_data *status; + struct s_mercenary *merc; + + status = &md->base_status; + merc = &md->mercenary; + + if( first ) + { + memcpy(status, &md->db->status, sizeof(struct status_data)); + status->mode = MD_CANMOVE|MD_CANATTACK; + status->hp = status->max_hp; + status->sp = status->max_sp; + md->battle_status.hp = merc->hp; + md->battle_status.sp = merc->sp; + } + + status_calc_misc(&md->bl, status, md->db->lv); + status_cpy(&md->base_status, status); + status_calc_bl(&md->bl, SCB_ALL); + + return 0; +} + int status_calc_homunculus(struct homun_data *hd, int first) { struct status_data b_status, *status; @@ -2490,30 +2515,30 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct struct map_session_data *sd; int val, skill; - if (!(bl->type&BL_REGEN) || !regen) + if( !(bl->type&BL_REGEN) || !regen ) return; - sd = BL_CAST(BL_PC,bl); + sd = BL_CAST(BL_PC,bl); val = 1 + (status->vit/5) + (status->max_hp/200); - if (sd && sd->hprecov_rate != 100) + if( sd && sd->hprecov_rate != 100 ) val = val*sd->hprecov_rate/100; regen->hp = cap_value(val, 1, SHRT_MAX); val = 1 + (status->int_/6) + (status->max_sp/100); - if(status->int_ >= 120) + if( status->int_ >= 120 ) val += ((status->int_-120)>>1) + 4; - if(sd && sd->sprecov_rate != 100) + if( sd && sd->sprecov_rate != 100 ) val = val*sd->sprecov_rate/100; regen->sp = cap_value(val, 1, SHRT_MAX); - if(sd) + if( sd ) { struct regen_data_sub *sregen; - if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) + if( (skill=pc_checkskill(sd,HP_MEDITATIO)) > 0 ) { val = regen->sp*(100+3*skill)/100; regen->sp = cap_value(val, 1, SHRT_MAX); @@ -2522,14 +2547,14 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct sregen = regen->sregen; val = 0; - if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) + if( (skill=pc_checkskill(sd,SM_RECOVERY)) > 0 ) val += skill*5 + skill*status->max_hp/500; sregen->hp = cap_value(val, 0, SHRT_MAX); val = 0; - if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) + if( (skill=pc_checkskill(sd,MG_SRECOVERY)) > 0 ) val += skill*3 + skill*status->max_sp/500; - if((skill=pc_checkskill(sd,NJ_NINPOU)) > 0) + if( (skill=pc_checkskill(sd,NJ_NINPOU)) > 0 ) val += skill*3 + skill*status->max_sp/500; sregen->sp = cap_value(val, 0, SHRT_MAX); @@ -2537,39 +2562,47 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct sregen = regen->ssregen; val = 0; - if((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) + if( (skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 ) val += skill*4 + skill*status->max_hp/500; - if((skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest) + if( (skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest ) val += skill*30 + skill*status->max_hp/500; sregen->hp = cap_value(val, 0, SHRT_MAX); val = 0; - if((skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest) + if( (skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest ) { val += skill*3 + skill*status->max_sp/500; if ((skill=pc_checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest val += (30+10*skill)*val/100; } - if((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) + if( (skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 ) val += skill*2 + skill*status->max_sp/500; sregen->sp = cap_value(val, 0, SHRT_MAX); } - if(bl->type==BL_HOM) + if( bl->type == BL_HOM ) { struct homun_data *hd = (TBL_HOM*)bl; - if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) + if( (skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0 ) { val = regen->hp*(100+5*skill)/100; regen->hp = cap_value(val, 1, SHRT_MAX); } - if((skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0) + if( (skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0 ) { val = regen->sp*(100+3*skill)/100; regen->sp = cap_value(val, 1, SHRT_MAX); } } + else if( bl->type == BL_MER ) + { + val = (status->max_hp * status->vit / 10000 + 1) * 6; + regen->hp = cap_value(val, 1, SHRT_MAX); + + val = (status->max_sp * (status->int_ + 10) / 750) + 1; + regen->sp = cap_value(val, 1, SHRT_MAX); + } } //Calculates SC related regen rates. @@ -4057,6 +4090,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl) switch (bl->type) { case BL_PC: return &((TBL_PC*)bl)->regen; case BL_HOM: return &((TBL_HOM*)bl)->regen; + case BL_MER: return &((TBL_MER*)bl)->regen; default: return NULL; } @@ -4071,6 +4105,7 @@ struct status_data *status_get_status_data(struct block_list *bl) case BL_MOB: return &((TBL_MOB*)bl)->status; case BL_PET: return &((TBL_PET*)bl)->status; case BL_HOM: return &((TBL_HOM*)bl)->battle_status; + case BL_MER: return &((TBL_MER*)bl)->battle_status; default: return &dummy_status; } @@ -4084,6 +4119,7 @@ struct status_data *status_get_base_status(struct block_list *bl) case BL_MOB: return ((TBL_MOB*)bl)->base_status ? ((TBL_MOB*)bl)->base_status : &((TBL_MOB*)bl)->db->status; case BL_PET: return &((TBL_PET*)bl)->db->status; case BL_HOM: return &((TBL_HOM*)bl)->base_status; + case BL_MER: return &((TBL_MER*)bl)->base_status; default: return NULL; } @@ -4133,6 +4169,10 @@ int status_get_party_id(struct block_list *bl) if (((TBL_HOM*)bl)->master) return ((TBL_HOM*)bl)->master->status.party_id; break; + case BL_MER: + if (((TBL_MER*)bl)->master) + return ((TBL_MER*)bl)->master->status.party_id; + break; case BL_SKILL: return ((TBL_SKILL*)bl)->group->party_id; } diff --git a/src/map/status.h b/src/map/status.h index 8e0ff6f85..8d9940b0f 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -595,9 +595,9 @@ enum scb_flag }; //Define to determine who gets HP/SP consumed on doing skills/etc. [Skotlex] -#define BL_CONSUME (BL_PC|BL_HOM) +#define BL_CONSUME (BL_PC|BL_HOM|BL_MER) //Define to determine who has regen -#define BL_REGEN (BL_PC|BL_HOM) +#define BL_REGEN (BL_PC|BL_HOM|BL_MER) //Basic damage info of a weapon @@ -802,6 +802,7 @@ 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); +int status_calc_mercenary(struct mercenary_data *md, int first); void status_calc_misc(struct block_list *bl, struct status_data *status, int level); void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen); void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc); diff --git a/src/map/unit.c b/src/map/unit.c index 20cd20de6..23789544f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1357,7 +1357,63 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, if (y) *y = tbl->y-dy; return path_search(NULL,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH); } +/*========================================== + * Calculates position of Pet/Mercenary/Homunculus + *------------------------------------------*/ +int unit_calc_pos(struct block_list *bl, int tx, int ty, int dir) +{ + int dx, dy, x, y, i, k; + struct unit_data *ud = unit_bl2ud(bl); + nullpo_retr(0, ud); + + if( dir < 0 || dir > 7 ) + return 1; + ud->to_x = tx; + ud->to_y = ty; + + // 2 cells from Master Position + dx = -dirx[dir] * 2; + dy = -diry[dir] * 2; + x = tx + dx; + y = ty + dy; + + if( !unit_can_reach_pos(bl, x, y, 0) ) + { + if( dx > 0 ) x--; else if( dx < 0 ) x++; + if( dy > 0 ) y--; else if( dy < 0 ) y++; + if( !unit_can_reach_pos(bl, x, y, 0) ) + { + for( i = 0; i < 12; i++ ) + { + k = rand()%8; // Pick a Random Dir + dx = -dirx[k] * 2; + dy = -diry[k] * 2; + x = tx + dx; + y = ty + dy; + if( unit_can_reach_pos(bl, x, y, 0) ) + break; + else + { + if( dx > 0 ) x--; else if( dx < 0 ) x++; + if( dy > 0 ) y--; else if( dy < 0 ) y++; + if( unit_can_reach_pos(bl, x, y, 0) ) + break; + } + } + if( i == 12 ) + { + x = tx; y = tx; // Exactly Master Position + if( !unit_can_reach_pos(bl, x, y, 0) ) + return 1; + } + } + } + ud->to_x = x; + ud->to_y = y; + + return 0; +} /*========================================== * PCの攻撃 (timer関数) diff --git a/src/map/unit.h b/src/map/unit.h index ec2e81c5a..0d8e4535e 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -66,6 +66,7 @@ struct view_data { int unit_walktoxy( struct block_list *bl, short x, short y, int easy); int unit_walktobl( struct block_list *bl, struct block_list *target, int range, int easy); int unit_run(struct block_list *bl); +int unit_calc_pos(struct block_list *bl, int tx, int ty, int dir); // 歩行停止 // typeは以下の組み合わせ : -- cgit v1.2.3-60-g2f50