summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/clif.c24
-rw-r--r--src/map/mercenary.c22
-rw-r--r--src/map/mercenary.h2
-rw-r--r--src/map/pet.c57
-rw-r--r--src/map/status.c78
-rw-r--r--src/map/status.h5
-rw-r--r--src/map/unit.c56
-rw-r--r--src/map/unit.h1
8 files changed, 147 insertions, 98 deletions
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は以下の組み合わせ :