浏览代码

- Mercenary Packets (Server to Client). Still need a little more info.
- Packet for Mercenary Menu.
- Some other progress as creation but need more code.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13116 54d463be-8e91-2dee-dedb-b68131a5f0ec

zephyrus 16 年之前
父节点
当前提交
1204fd49db
共有 12 个文件被更改,包括 375 次插入36 次删除
  1. 1 1
      db/packet_db.txt
  2. 53 0
      src/char_sql/int_homun.c
  3. 1 1
      src/char_sql/inter.c
  4. 0 1
      src/common/mmo.h
  5. 126 18
      src/map/clif.c
  6. 4 0
      src/map/clif.h
  7. 39 1
      src/map/intif.c
  8. 3 0
      src/map/intif.h
  9. 114 10
      src/map/mercenary.c
  10. 9 2
      src/map/mercenary.h
  11. 23 1
      src/map/status.c
  12. 2 1
      src/map/unit.c

+ 1 - 1
db/packet_db.txt

@@ -930,7 +930,7 @@ packet_ver: 20
 0x029c,66
 0x029d,-1
 0x029e,11
-0x029f,3
+0x029f,3,mermenu,0
 0x02a0,0
 0x02a1,0
 0x02a2,8

+ 53 - 0
src/char_sql/int_homun.c

@@ -292,18 +292,71 @@ static void mapif_parse_homunculus_rename(int fd, int account_id, int char_id, c
 	mapif_homunculus_renamed(fd, account_id, char_id, result, name);
 }
 
+/*==========================================
+ * Mercenary's System
+ *------------------------------------------*/
+bool mapif_mercenary_save(struct s_mercenary* merc)
+{
+	bool flag = true;
+
+	if( merc->mercenary_id == 0 )
+	{ // Create new DB entry
+		if( SQL_ERROR == Sql_Query(sql_handle,
+			"INSERT INTO `mercenary` (`char_id`,`class`,`hp`,`sp`,`kill_counter`,`life_time`) VALUES ('%d','%d','%d','%d','%u','%u')",
+			merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->remain_life_time) )
+		{
+			Sql_ShowDebug(sql_handle);
+			flag = false;
+		}
+		else
+			merc->mercenary_id = (int)Sql_LastInsertId(sql_handle);
+	}
+	else if( SQL_ERROR == Sql_Query(sql_handle,
+		"UPDATE `mercenary` SET `char_id` = '%d', `class` = '%d', `hp` = '%d', `sp` = '%d', `kill_counter` = '%u', `life_time` = '%u' WHERE `mer_id` = '%d'",
+		merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->remain_life_time, merc->mercenary_id) )
+	{ // Update DB entry
+		Sql_ShowDebug(sql_handle);
+		flag = false;
+	}
+
+	return flag;
+}
+
+static void mapif_mercenary_created(int fd, struct s_mercenary *merc, unsigned char flag)
+{
+	int size = sizeof(struct s_mercenary) + 5;
+
+	WFIFOHEAD(fd,size);
+	WFIFOW(fd,0) = 0x3860;
+	WFIFOW(fd,2) = size;
+	WFIFOB(fd,4) = flag;
+	memcpy(WFIFOP(fd,5),merc,sizeof(struct s_mercenary));
+	WFIFOSET(fd,size);
+}
+
+static void mapif_parse_mercenary_create(int fd, struct s_mercenary* merc)
+{
+	bool result = mapif_mercenary_save(merc);
+	mapif_mercenary_created(fd, merc, result);
+}
 
+/*==========================================
+ * Inter Packets
+ *------------------------------------------*/
 int inter_homunculus_parse_frommap(int fd)
 {
 	unsigned short cmd = RFIFOW(fd,0);
 
 	switch( cmd )
 	{
+	// Homunculus Packets
 	case 0x3090: mapif_parse_homunculus_create(fd, (int)RFIFOW(fd,2), (int)RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,8)); break;
 	case 0x3091: mapif_parse_homunculus_load  (fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6)); break;
 	case 0x3092: mapif_parse_homunculus_save  (fd, (int)RFIFOW(fd,2), (int)RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,8)); break;
 	case 0x3093: mapif_parse_homunculus_delete(fd, (int)RFIFOL(fd,2)); break;
 	case 0x3094: mapif_parse_homunculus_rename(fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6), (char*)RFIFOP(fd,10)); break;
+	// Mercenary Packets
+	case 0x3070: mapif_parse_mercenary_create(fd, (struct s_mercenary*)RFIFOP(fd,8)); break;
 	default:
 		return 0;
 	}

+ 1 - 1
src/char_sql/inter.c

@@ -51,7 +51,7 @@ int inter_recv_packet_length[] = {
 	 5, 9, 0, 0,  0, 0, 0, 0,  7, 6,10,10, 10,-1,  0, 0,	// 3040-
 	-1,-1,10,10,  0,-1, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3050-  Auction System [Zephyrus]
 	 6,-1,10, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-  Quest system [Kevin]
-	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3070-
+	-1, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3070-  Mercenary packets [Zephyrus]
 	48,14,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3080-
 	-1,10,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3090-  Homunculus packets [albator]
 };

+ 0 - 1
src/common/mmo.h

@@ -108,7 +108,6 @@
 #define MC_SKILLBASE 8201
 #define MAX_MERCSKILL 37
 #define MAX_MERCENARY_CLASS 30
-#define MAX_MERCENARY_SKILL 4
 
 enum item_types {
 	IT_HEALING = 0,

+ 126 - 18
src/map/clif.c

@@ -1122,14 +1122,14 @@ int clif_homskillinfoblock(struct map_session_data *sd)
 	WFIFOW(fd,0)=0x235;
 	for ( i = 0; i < MAX_HOMUNSKILL; i++){
 		if( (id = hd->homunculus.hskill[i].id) != 0 ){
-			j = id - HM_SKILLBASE ;
-			WFIFOW(fd,len  ) = id ;
-			WFIFOW(fd,len+2) = skill_get_inf(id) ;
-			WFIFOW(fd,len+4) = 0 ;
-			WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv ;
-			WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv) ;
-			WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv) ;
-			safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH) ;
+			j = id - HM_SKILLBASE;
+			WFIFOW(fd,len  ) = id;
+			WFIFOW(fd,len+2) = skill_get_inf(id);
+			WFIFOW(fd,len+4) = 0;
+			WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv;
+			WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv);
+			WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv);
+			safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH);
 			WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < merc_skill_tree_get_max(id, hd->homunculus.class_))?1:0;
 			len+=37;
 		}
@@ -11272,20 +11272,23 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
 	unit_walktoxy(&sd->hd->bl, sd->bl.x,sd->bl.y-1, 4);
 }
 
-void clif_parse_HomMoveTo(int fd,struct map_session_data *sd)
+void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
 {
-	short x,y,cmd;
-
-	if(!merc_is_hom_active(sd->hd))
-		return;
+	int id = RFIFOL(fd,2); // Mercenary or Homunculus
+	struct block_list *bl = NULL;
+	short x, y, cmd;
 
 	cmd = RFIFOW(fd,0);
-	x = RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]) * 4 +
-		(RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 1) >> 6);
-	y = ((RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]+1) & 0x3f) << 4) +
-		(RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 2) >> 4);
+	x = RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]) * 4 + (RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 1) >> 6);
+	y = ((RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]+1) & 0x3f) << 4) + (RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 2) >> 4);
+
+	if( sd->md && sd->md->bl.id == id )
+		bl = &sd->md->bl; // Moving Mercenary
+	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),x,y,4);
+	unit_walktoxy(bl, x, y, 4);
 }
 
 void clif_parse_HomAttack(int fd,struct map_session_data *sd)
@@ -12334,6 +12337,110 @@ void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool act
 	WFIFOSET(fd, 7);
 }
 
+/*==========================================
+ * Mercenary System
+ *==========================================*/
+void clif_mercenary_info(struct map_session_data *sd)
+{
+	int fd;
+	struct mercenary_data *md;
+	struct status_data *status;
+
+	if( sd == NULL || (md = sd->md) == NULL )
+		return;
+
+	fd = sd->fd;
+	status = &md->battle_status;
+
+	WFIFOHEAD(fd,72);
+	WFIFOW(fd,0) = 0x029b;
+	WFIFOL(fd,2) = md->bl.id;
+	WFIFOW(fd,6) = cap_value(status->rhw.atk2+status->batk, 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,16) = status->mdef;
+	WFIFOW(fd,18) = status->flee;
+	WFIFOW(fd,20) = status->amotion;
+	safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH);
+	WFIFOW(fd,46) = md->db->lv;
+	WFIFOL(fd,48) = status->hp;
+	WFIFOL(fd,52) = status->max_hp;
+	WFIFOL(fd,56) = status->sp;
+	WFIFOL(fd,60) = status->max_sp;
+	WFIFOL(fd,64) = 0; // Expiration Time
+	WFIFOW(fd,68) = 0; // No documentation (Guild Rank?)
+	WFIFOW(fd,70) = 0; // Times Summoned	
+	WFIFOSET(fd,72);
+}
+
+void clif_mercenary_skillblock(struct map_session_data *sd)
+{
+	struct mercenary_data *md;
+	int fd, i, len = 4, id, j;
+
+	if( sd == NULL || (md = sd->md) == NULL )
+		return;
+	
+	fd = sd->fd;
+	WFIFOHEAD(fd,4+37*MAX_MERCSKILL);
+	WFIFOW(fd,0) = 0x029d;
+	for( i = 0; i < MAX_MERCSKILL; i++ )
+	{
+		if( (id = md->db->skill[i].id) == 0 )
+			continue;
+		j = id - MC_SKILLBASE;
+		WFIFOW(fd,len) = id;
+		WFIFOW(fd,len+2) = skill_get_inf(id);
+		WFIFOW(fd,len+4) = 0;
+		WFIFOW(fd,len+6) = md->db->skill[j].lv;
+		WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[j].lv);
+		WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[j].lv);
+		safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH);
+		WFIFOB(fd,len+36) = 0; // Skillable for Mercenary?
+		len += 37;
+	}
+
+	WFIFOW(fd,2) = len;
+	WFIFOSET(fd,len);
+}
+
+void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
+{
+	struct mercenary_data *md;
+	int fd;
+	if( sd == NULL || (md = sd->md) == NULL )
+		return;
+
+	fd = sd->fd;
+	WFIFOHEAD(fd,8);
+	WFIFOW(fd,0) = 0x02a2;
+	WFIFOW(fd,2) = type;
+	switch( type )
+	{
+		case SP_HP:
+			WFIFOL(fd,4) = md->battle_status.hp;
+			break;
+		case SP_MAXHP:
+			WFIFOL(fd,4) = md->battle_status.max_hp;
+			break;
+		case SP_SP:
+			WFIFOL(fd,4) = md->battle_status.sp;
+			break;
+		case SP_MAXSP:
+			WFIFOL(fd,4) = md->battle_status.max_sp;
+			break;
+	}
+	WFIFOSET(fd,8);
+}
+
+void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
+{
+	int option = RFIFOB(fd,2);
+	if( sd->md == NULL )
+		return;
+}
 
 /*==========================================
  * ƒpƒPƒbƒgƒfƒoƒbƒO
@@ -12780,6 +12887,7 @@ static int packetdb_readdb(void)
 		{clif_parse_cashshop_buy,"cashshopbuy"},
 		{clif_parse_ViewPlayerEquip,"viewplayerequip"},
 		{clif_parse_EquipTick,"equiptickbox"},
+		{clif_parse_mercenary_action,"mermenu"},
 		{NULL,NULL}
 	};
 

+ 4 - 0
src/map/clif.h

@@ -439,4 +439,8 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd);
 // ADOPTION
 void clif_Adopt_reply(struct map_session_data *sd, int type);
 
+// MERCENARIES
+void clif_mercenary_info(struct map_session_data *sd);
+void clif_mercenary_skillblock(struct map_session_data *sd);
+
 #endif /* _CLIF_H_ */

+ 39 - 1
src/map/intif.c

@@ -38,7 +38,7 @@ static const int packet_len_table[]={
 	 9, 9,-1,14,  0, 0, 0, 0, -1,74,-1,11, 11,-1,  0, 0, //0x3840
 	-1,-1, 7, 7,  7,11, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3850  Auctions [Zephyrus]
 	-1,11,11, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3860  Quests [Kevin]
-	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
+	-1, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3870  Mercenaries [Zephyrus]
 	11,-1, 7, 3,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3880
 	-1,-1, 7, 3,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3890  Homunculus [albator]
 };
@@ -1864,6 +1864,41 @@ static void intif_parse_Auction_message(int fd)
 
 #endif
 
+/*==========================================
+ * Mercenary's System
+ *------------------------------------------*/
+int intif_mercenary_create(struct s_mercenary *merc)
+{
+	int size = sizeof(struct s_mercenary) + 4;
+
+	if( CheckForCharServer() )
+		return 0;
+
+	WFIFOHEAD(inter_fd,size);
+	WFIFOW(inter_fd,0) = 0x3070;
+	WFIFOW(inter_fd,2) = size;
+	memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary));
+	WFIFOSET(inter_fd,size);
+	return 0;
+}
+
+int intif_parse_mercenary_create(int fd)
+{
+	int len = RFIFOW(fd,2) - 5;
+	if( sizeof(struct s_mercenary) != len )
+	{
+		if( battle_config.etc_log )
+			ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_homunculus), len);
+		return 0;
+	}
+
+	merc_data_received((struct s_mercenary*)RFIFOP(fd,9), RFIFOB(fd,8));
+	return 0;
+}
+
+
+
+
 //-----------------------------------------------------------------
 // inter serverからの通信
 // エラーがあれば0(false)を返すこと
@@ -1952,6 +1987,9 @@ int intif_parse(int fd)
 	case 0x3854:	intif_parse_Auction_message(fd); break;
 	case 0x3855:	intif_parse_Auction_bid(fd); break;
 #endif
+// Mercenary System
+	case 0x3870:	intif_parse_mercenary_create(fd); break;
+
 	case 0x3880:	intif_parse_CreatePet(fd); break;
 	case 0x3881:	intif_parse_RecvPetData(fd); break;
 	case 0x3882:	intif_parse_SavePetOk(fd); break;

+ 3 - 0
src/map/intif.h

@@ -77,6 +77,9 @@ int intif_request_questlog(struct map_session_data * sd);
 int intif_quest_delete(int char_id, int quest_id);
 int intif_quest_add(int char_id, struct quest * qd);
 
+// MERCENARY SYSTEM
+int intif_mercenary_create(struct s_mercenary *merc);
+
 #ifndef TXT_ONLY
 // MAIL SYSTEM
 int intif_Mail_requestinbox(int char_id, unsigned char flag);

+ 114 - 10
src/map/mercenary.c

@@ -45,11 +45,115 @@
  *------------------------------------------*/
 struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database
 
-int merc_create(struct map_session_data *sd, int class_)
+int merc_search_index(int class_)
 {
+	int i;
+	ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_);
+	return (i == MAX_MERCENARY_CLASS)?-1:i;
+}
+
+bool merc_class(int class_)
+{
+	return (bool)(merc_search_index(class_) < 0);
+}
+
+struct view_data * merc_get_viewdata(int class_)
+{
+	int i = merc_search_index(class_);
+	if( i < 0 )
+		return 0;
+
+	return &mercenary_db[i].vd;
+}
+
+int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
+{
+	struct s_mercenary merc;
+	struct s_mercenary_db *db;
+	int i;
+	nullpo_retr(1,sd);
+
+	if( (i = merc_search_index(class_)) < 0 )
+		return 0;
+
+	db = &mercenary_db[i];
+	memset(&merc,0,sizeof(struct s_mercenary));
+
+	merc.char_id = sd->status.char_id;
+	merc.class_ = class_;
+	merc.hp = db->status.max_hp;
+	merc.sp = db->status.max_sp;
+	merc.remain_life_time = lifetime;
+
+	// Request Char Server to create this mercenary
+	intif_mercenary_create(&merc);
+
 	return 1;
 }
 
+int merc_data_received(struct s_mercenary *merc, bool flag)
+{
+	struct map_session_data *sd;
+	struct mercenary_data *md;
+	struct s_mercenary_db *db;
+	int i = merc_search_index(merc->class_);
+
+	if( (sd = map_charid2sd(merc->char_id)) == NULL )
+		return 0;
+	if( !flag || i < 0 )
+	{ // Not created - loaded - DB info
+		sd->status.mer_id = 0;
+		return 0;
+	}
+
+	sd->status.mer_id = merc->mercenary_id;
+	db = &mercenary_db[i];
+
+	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();
+
+		md->master = sd;
+		md->db = db;
+		memcpy(&md->mercenary, merc, sizeof(struct s_mercenary));
+		status_set_viewdata(&md->bl, md->mercenary.class_);
+		status_change_init(&md->bl);
+		unit_dataset(&md->bl);
+		md->ud.dir = sd->ud.dir;
+
+		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;
+
+		map_addiddb(&md->bl);
+		// status_calc_mercenary(md,1);
+	}
+	else
+		memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary));
+
+	md = sd->md;
+	if( md && md->bl.prev == NULL && sd->bl.prev != NULL )
+	{
+		map_addblock(&md->bl);
+		clif_spawn(&md->bl);
+		clif_mercenary_info(sd);
+		clif_mercenary_skillblock(sd);
+		// init timers
+	}
+
+	return 1;
+}
+
+
 /*==========================================
  * Homunculus's System
  *------------------------------------------*/
@@ -936,6 +1040,8 @@ int read_mercenarydb(void)
 		db->lv = atoi(str[3]);
 
 		status = &db->status;
+		db->vd.class_ = db->class_;
+
 		status->max_hp = atoi(str[4]);
 		status->max_sp = atoi(str[5]);
 		status->rhw.range = atoi(str[6]);
@@ -1025,20 +1131,18 @@ int read_mercenary_skilldb(void)
 			ShowError("read_mercenary_skilldb : Class not found in mercenary_db for skill entry, line %d.\n", k);
 			continue;
 		}
-
-		db = &mercenary_db[i];
+		
 		skillid = atoi(str[1]);
-		skilllv = atoi(str[2]);
-
-		ARR_FIND(0, MAX_MERCENARY_SKILL, i, db->skill[i].id == 0 || db->skill[i].id == skillid);
-		if( i == MAX_MERCENARY_SKILL )
+		if( skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL )
 		{
-			ShowError("read_mercenary_skilldb : No more free skill slots for Class %d, line %d.\n", class_, k);
+			ShowError("read_mercenary_skilldb : Skill out of range, line %d.\n", k);
 			continue;
 		}
-		if( db->skill[i].id == skillid )
-			ShowError("read_mercenary_skilldb : Duplicate Skill for Class %d, line %d. Overwriting...\n", class_, k);
 
+		db = &mercenary_db[i];
+		skilllv = atoi(str[2]);
+
+		i = skillid - MC_SKILLBASE;
 		db->skill[i].id = skillid;
 		db->skill[i].lv = skilllv;
 		j++;

+ 9 - 2
src/map/mercenary.h

@@ -16,9 +16,10 @@ struct s_mercenary_db {
 	unsigned short lv;
 	short range2, range3;
 	struct status_data status;
+	struct view_data vd;
 	struct {
 		unsigned short id, lv;
-	} skill[MAX_MERCENARY_SKILL];
+	} skill[MAX_MERCSKILL];
 };
 
 extern struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS];
@@ -27,14 +28,20 @@ struct mercenary_data {
 	struct block_list bl;
 	struct unit_data ud;
 	struct view_data *vd;
-	struct status_change *base_status, battle_status;
+	struct status_data *base_status, battle_status;
 	struct status_change sc;
 	struct regen_data regen;
 
 	struct s_mercenary_db *db;
 	struct s_mercenary mercenary;
+
+	struct map_session_data *master; // Master of mercenary
 };
 
+bool merc_class(int class_);
+struct view_data * merc_get_viewdata(int class_);
+int merc_data_received(struct s_mercenary *merc, bool flag);
+
 // Homunculus DB Structures
 // ===================================
 

+ 23 - 1
src/map/status.c

@@ -4046,7 +4046,8 @@ int status_get_lv(struct block_list *bl)
 		case BL_MOB: return ((TBL_MOB*)bl)->level;
 		case BL_PET: return ((TBL_PET*)bl)->pet.level;
 		case BL_HOM: return ((TBL_HOM*)bl)->homunculus.level;
-	}		
+		case BL_MER: return ((TBL_MER*)bl)->db->lv;
+	}
 	return 1;
 }
 
@@ -4162,6 +4163,10 @@ int status_get_guild_id(struct block_list *bl)
 	  	if (((TBL_HOM*)bl)->master)
 			return ((TBL_HOM*)bl)->master->status.guild_id;
 		break;
+	case BL_MER:
+		if (((TBL_MER*)bl)->master)
+			return ((TBL_MER*)bl)->master->status.guild_id;
+		break;
 	case BL_NPC:
 	  	if (((TBL_NPC*)bl)->subtype == SCRIPT)
 			return ((TBL_NPC*)bl)->u.scr.guild_id;
@@ -4196,6 +4201,10 @@ int status_get_emblem_id(struct block_list *bl)
 	  	if (((TBL_HOM*)bl)->master)
 			return ((TBL_HOM*)bl)->master->guild_emblem_id;
 		break;
+	case BL_MER:
+	  	if (((TBL_MER*)bl)->master)
+			return ((TBL_MER*)bl)->master->guild_emblem_id;
+		break;
 	case BL_NPC:
 		if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) {
 			struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id);
@@ -4253,6 +4262,7 @@ struct view_data* status_get_viewdata(struct block_list *bl)
 		case BL_PET: return &((TBL_PET*)bl)->vd;
 		case BL_NPC: return ((TBL_NPC*)bl)->vd;
 		case BL_HOM: return ((TBL_HOM*)bl)->vd;
+		case BL_MER: return ((TBL_MER*)bl)->vd;
 	}
 	return NULL;
 }
@@ -4267,6 +4277,8 @@ void status_set_viewdata(struct block_list *bl, int class_)
 		vd = npc_get_viewdata(class_);
 	else if (homdb_checkid(class_))
 		vd = merc_get_hom_viewdata(class_);
+	else if (merc_class(class_))
+		vd = merc_get_viewdata(class_);
 	else
 		vd = NULL;
 
@@ -4365,6 +4377,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
 				ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_);
 		}
 		break;
+	case BL_MER:
+		{
+			struct mercenary_data *md = (struct mercenary_data*)bl;
+			if (vd)
+				md->vd = vd;
+			else
+				ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_);
+		}
+		break;
 	}
 	vd = status_get_viewdata(bl);
 	if (vd && vd->cloth_color && (
@@ -4383,6 +4404,7 @@ struct status_change *status_get_sc(struct block_list *bl)
 	case BL_MOB: return &((TBL_MOB*)bl)->sc;
 	case BL_NPC: return &((TBL_NPC*)bl)->sc;
 	case BL_HOM: return &((TBL_HOM*)bl)->sc;
+	case BL_MER: return &((TBL_MER*)bl)->sc;
 	}
 	return NULL;
 }

+ 2 - 1
src/map/unit.c

@@ -42,7 +42,8 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
 	if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud;
 	if( bl->type == BL_PET) return &((struct pet_data*)bl)->ud;
 	if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud;
-	if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud;	//[orn]
+	if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud;
+	if( bl->type == BL_MER) return &((struct mercenary_data*)bl)->ud;
 	return NULL;
 }