浏览代码

- 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://svn.code.sf.net/p/rathena/svn/trunk@13121 54d463be-8e91-2dee-dedb-b68131a5f0ec

zephyrus 16 年之前
父节点
当前提交
d650043597
共有 8 个文件被更改,包括 147 次插入98 次删除
  1. 18 6
      src/map/clif.c
  2. 7 15
      src/map/mercenary.c
  3. 1 1
      src/map/mercenary.h
  4. 2 55
      src/map/pet.c
  5. 59 19
      src/map/status.c
  6. 3 2
      src/map/status.h
  7. 56 0
      src/map/unit.c
  8. 1 0
      src/map/unit.h

+ 18 - 6
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;

+ 7 - 15
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);

+ 1 - 1
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;
 

+ 2 - 55
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);
 

+ 59 - 19
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;
 	}

+ 3 - 2
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);

+ 56 - 0
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‚Ì�UŒ‚ (timerŠÖ�”)

+ 1 - 0
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は以下の組み合わせ :