Jelajahi Sumber

* Part A of the Homunculus code.
This only features the structures, status_* and clif_* (packets) and is
not functional yet in any conventional way, but doesn't interfere
with present functionality either.
I would only forget half of this stuff if I tried to do all at once.
Expect the rest somewhen within the upcoming week.
(This is not similar to jA's implementation.)

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

blackhole89 19 tahun lalu
induk
melakukan
752cd268ef
5 mengubah file dengan 259 tambahan dan 0 penghapusan
  1. 5 0
      Changelog-Trunk.txt
  2. 160 0
      src/map/clif.c
  3. 7 0
      src/map/clif.h
  4. 40 0
      src/map/map.h
  5. 47 0
      src/map/status.c

+ 5 - 0
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/21
+	* Part A of the Homunculus code.
+	  This only features the structures, status_* and clif_* (packets) and is
+	  not functional yet in any conventional way, but doesn't interfere
+	  with present functionality either.
+	  Main purpose is helping me to keep my work organized. [blackhole89]
 	* Fixed the "fake" mute status bug. [Zido]
 	* Speed up array size calculation and deletion. [Lance]
 	* Player must learn the skill before doing auto-spell [Lance]

+ 160 - 0
src/map/clif.c

@@ -1362,6 +1362,147 @@ int clif_spawn(struct block_list *bl)
 	}
 	return 0;
 }
+/*==========================================
+ * Homunculus [blackhole89]
+ *------------------------------------------
+ */
+// Can somebody tell me why exactly I have commented this lot of stuff out?
+// acknowledge client it has a homunculus
+int clif_homunack(struct map_session_data *sd)
+{
+	struct homun_data *hd = sd->hd;
+
+	nullpo_retr(0, sd);
+	nullpo_retr(0, sd->hd);
+
+	unsigned char buf[64];
+	//memset(buf,0,packet_len_table[0x230]);
+	memset(buf,0,12); //not yet set that stuff
+	WBUFW(buf,0)=0x230;
+	WBUFL(buf,4)=hd->bl.id;
+	ShowError("in clif_homunack~\n");
+	clif_send(buf,/*packet_len_table[0x230]*/12,&sd->bl,SELF);
+
+	return 0;
+}
+
+// homunculus stats et al
+int clif_homuninfo(struct map_session_data *sd)
+{
+	struct homun_data *hd = sd->hd;
+	
+	nullpo_retr(0, sd);
+	nullpo_retr(0, sd->hd);
+
+	unsigned char buf[128];
+	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;
+	WBUFL(buf,59)=hd->exp;
+	WBUFL(buf,63)=hd->exp_next;
+	WBUFW(buf,67)=hd->skillpts;
+	WBUFW(buf,69)=0x21;
+	clif_send(buf,/*packet_len_table[0x22e]*/71,&sd->bl,SELF); 
+}
+
+// like skillinfoblock, just for homunculi.
+int clif_homunskillinfoblock(struct map_session_data *sd)
+{
+	int fd;
+	int i,c,len=4,id, inf2;
+
+	nullpo_retr(0, sd);
+	nullpo_retr(0, sd->hd);
+
+	fd=sd->fd;
+	WFIFOHEAD(fd, 4 * 37 + 4);
+	WFIFOW(fd,0)=0x235;
+	for ( i = c = 0; i < 4; i++){
+		if( (id=sd->hd->hskill[i].id)!=0 ){
+			WFIFOW(fd,len  ) = id;
+			WFIFOW(fd,len+2) = skill_get_inf(id-7300);		// H. skills mapped to 700 and above
+			WFIFOW(fd,len+4) = 0;
+			WFIFOW(fd,len+6) = sd->hd->hskill[i].level;
+			WFIFOW(fd,len+8) = skill_get_sp(id,sd->hd->hskill[i].level);
+			WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->hd->hskill[i].level);
+			strncpy(WFIFOP(fd,len+12), /*merc_skill_get_name(id)*/ "", NAME_LENGTH); // can somebody tell me what exactly that function was good for anyway
+		/*	inf2 = skill_get_inf2(id);
+			if(((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
+				!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL))) ||
+				(battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) )
+				//WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0;
+				WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[i].flag ==0 )? 1:0;
+			else */
+				WFIFOB(fd,len+36) = 1;//0;
+			len+=37;
+			c++;
+		}
+	}
+	WFIFOW(fd,2)=len;
+	WFIFOSET(fd,len);
+
+	return 0;
+}
+
+// Request a Homunculus name change
+void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) {
+	RFIFOHEAD(fd);
+	nullpo_retv(sd);
+	nullpo_retv(sd->hd);
+	memcpy(sd->hd->name,RFIFOP(fd,2),24);
+	clif_homuninfo(sd);
+	clif_charnameack(sd->fd,&sd->hd->bl);
+}
+
+// Somebody who is less lazy than me rename this to ReturnToMaster or something
+void clif_parse_QueryHomunPos(int fd, struct map_session_data *sd) {
+	RFIFOHEAD(fd);
+	nullpo_retv(sd);
+	nullpo_retv(sd->hd);
+	unit_walktoxy(&sd->hd->bl, sd->bl.x,sd->bl.y-1, 0); //move to master
+	//clif_homunposack(sd->hd);
+}
+
+// Request a Homunculus move-to-position
+void clif_parse_HMoveTo(int fd,struct map_session_data *sd) {
+	int x,y,cmd;
+
+	nullpo_retv(sd);
+	nullpo_retv(sd->hd);
+
+	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);
+
+	unit_walktoxy(&sd->hd->bl,x,y,0);
+}
+
+// Request the Homunculus attacking a bl
+void clif_parse_HAttack(int fd,struct map_session_data *sd) {
+	nullpo_retv(sd);
+	nullpo_retv(sd->hd);
+
+	if(sd->hd->bl.id != RFIFOL(fd,2)) return;
+	
+	printf("unit_attack returned: %d\n",unit_attack(&sd->hd->bl,RFIFOL(fd,6),0));
+}
 /*==========================================
  *
  *------------------------------------------
@@ -7728,6 +7869,10 @@ int clif_charnameack (int fd, struct block_list *bl)
 			}
 		}
 		break;
+	//[blackhole89]
+	case BL_HOMUNCULUS:
+		memcpy(WBUFP(buf,6), ((struct homun_data*)bl)->name, NAME_LENGTH);
+		break;
 	case BL_PET:
 		memcpy(WBUFP(buf,6), ((struct pet_data*)bl)->name, NAME_LENGTH);
 		break;
@@ -8165,6 +8310,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		clif_send_petstatus(sd);
 	}
 
+	//homunculus [blackhole89]
+	if(sd->hd && sd->hd->alive) {
+		map_addblock(&sd->hd->bl);
+		clif_spawn(&sd->hd->bl);
+		clif_homunack(sd);
+		clif_homuninfo(sd);
+		clif_homuninfo(sd); //for some reason, at least older clients want this sent twice
+		clif_homunskillinfoblock(sd);
+	}
+
 	if(sd->state.connect_new) {
 		sd->state.connect_new = 0;
 		//Delayed night effect on log-on fix for the glow-issue. Thanks to Larry.
@@ -11648,6 +11803,11 @@ static int packetdb_readdb(void)
 		{clif_parse_FeelSaveOk,"feelsaveok"},
 		{clif_parse_AdoptRequest,"adopt"},
 		{clif_parse_debug,"debug"},
+		//[blackhole89]
+		{clif_parse_ChangeHomunculusName,"changehomunculusname"},
+		{clif_parse_QueryHomunPos,"queryhomunpos"},
+		{clif_parse_HMoveTo,"hmoveto"},
+		{clif_parse_HAttack,"hattack"},
 		{NULL,NULL}
 	};
 

+ 7 - 0
src/map/clif.h

@@ -330,6 +330,13 @@ void clif_parse_ReqFeel(int fd, struct map_session_data *sd, int skilllv);
 void clif_feel_info(struct map_session_data *sd, int feel_level);
 void clif_hate_mob(struct map_session_data *sd, int skilllv,int mob_id);
 void clif_mission_mob(struct map_session_data *sd, unsigned short mob_id, unsigned short progress);
+
+// [blackhole89]
+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);
 #endif
 
 

+ 40 - 0
src/map/map.h

@@ -733,6 +733,8 @@ struct map_session_data {
 	struct pet_data *pd;
 	int pet_hungry_timer;
 
+	struct homun_data *hd;	// [blackhole89]
+
 	struct{
 		int  m; //-1 - none, other: map index corresponding to map name.
 		unsigned short index; //map index
@@ -874,6 +876,7 @@ struct mob_data {
 	struct {
 		int id;
 		int dmg;
+		unsigned char to_homun; //[blackhole89] - determines whether this damage was dealt by homunculus or its master
 	} dmglog[DAMAGELOG_SIZE];
 	struct spawn_data *spawn; //Spawn data.
 	struct item *lootitem;
@@ -903,6 +906,43 @@ struct mob_data {
 	char npc_event[50];
 };
 
+/* [blackhole89] */
+struct homun_data {
+	struct block_list bl;
+	struct unit_data  ud;
+	struct view_data *vd;
+	struct status_change sc;
+
+	char name[NAME_LENGTH];
+	int id;
+	short speed;
+	short class_;
+
+	struct map_session_data *master; //pointer back to its master
+
+	short hunger_rate;
+
+	struct {
+		int id;		//0 = none
+		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;
+};
+
 struct pet_data {
 	struct block_list bl;
 	struct unit_data ud;

+ 47 - 0
src/map/status.c

@@ -2395,6 +2395,8 @@ int status_get_range(struct block_list *bl)
 		return ((struct map_session_data *)bl)->attackrange;
 	if(bl->type==BL_PET)
 		return ((struct pet_data *)bl)->db->range;
+	if(bl->type==BL_HOMUNCULUS)
+		return 1; //[blackhole89]
 	return 0;
 }
 /*==========================================
@@ -2409,6 +2411,8 @@ int status_get_hp(struct block_list *bl)
 		return ((struct mob_data *)bl)->hp;
 	if(bl->type==BL_PC)
 		return ((struct map_session_data *)bl)->status.hp;
+	if(bl->type==BL_HOMUNCULUS)
+		return ((struct homun_data *)bl)->hp;
 	return 1;
 }
 /*==========================================
@@ -2422,6 +2426,8 @@ int status_get_max_hp(struct block_list *bl)
 
 	if(bl->type==BL_PC)
 		return ((struct map_session_data *)bl)->status.max_hp;
+	else if(bl->type==BL_HOMUNCULUS)
+		return ((struct homun_data *)bl)->max_hp; //[blackhole89]
 	else {
 		int max_hp = 1;
 
@@ -2471,6 +2477,8 @@ int status_get_str(struct block_list *bl)
 				str = ((struct pet_data *)bl)->status->str;
 			else
 				str = ((struct pet_data *)bl)->db->str;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			str = ((struct homun_data *)bl)->str;
 		}
 
 		str = status_calc_str(bl,str);
@@ -2505,6 +2513,8 @@ int status_get_agi(struct block_list *bl)
 				agi = ((struct pet_data *)bl)->status->agi;
 			else
 				agi = ((struct pet_data *)bl)->db->agi;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			agi = ((struct homun_data *)bl)->agi;
 		}
 
 		agi = status_calc_agi(bl,agi);
@@ -2538,6 +2548,8 @@ int status_get_vit(struct block_list *bl)
 				vit = ((struct pet_data *)bl)->status->vit;
 			else
 				vit = ((struct pet_data *)bl)->db->vit;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			vit = ((struct homun_data *)bl)->vit;
 		}
 
 		vit = status_calc_vit(bl,vit);
@@ -2571,6 +2583,8 @@ int status_get_int(struct block_list *bl)
 				int_ = ((struct pet_data *)bl)->status->int_;
 			else
 				int_ = ((struct pet_data *)bl)->db->int_;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			int_ = ((struct homun_data *)bl)->int_;
 		}
 
 		int_ = status_calc_int(bl,int_);
@@ -2604,6 +2618,8 @@ int status_get_dex(struct block_list *bl)
 				dex = ((struct pet_data *)bl)->status->dex;
 			else
 				dex = ((struct pet_data *)bl)->db->dex;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			dex = ((struct homun_data *)bl)->dex;
 		}
 
 		dex = status_calc_dex(bl,dex);
@@ -2637,6 +2653,8 @@ int status_get_luk(struct block_list *bl)
 				luk = ((struct pet_data *)bl)->status->luk;
 			else
 				luk = ((struct pet_data *)bl)->db->luk;
+		} else if(bl->type == BL_HOMUNCULUS) { //[blackhole89]
+			luk = ((struct homun_data *)bl)->luk;
 		}
 
 		luk = status_calc_luk(bl,luk);
@@ -2766,6 +2784,9 @@ int status_get_atk(struct block_list *bl)
 			else
 				atk = ((struct pet_data*)bl)->db->atk1;
 		break;
+		case BL_HOMUNCULUS:	//[blackhole89]
+			atk = ((struct homun_data*)bl)->atk;
+			break;
 	}
 	// Absolute, then relative modifiers from status changes (shared between PC and NPC)
 	atk = status_calc_watk(bl,atk);
@@ -2810,6 +2831,9 @@ int status_get_atk2(struct block_list *bl)
 			else
 				atk2 = ((struct pet_data*)bl)->db->atk2;
 		break;
+		case BL_HOMUNCULUS:	//[blackhole89]
+			atk2 = ((struct homun_data*)bl)->atk;
+			break;
 	}		  
 
 	// Absolute, then relative modifiers from status changes (shared between PC and NPC)
@@ -2994,6 +3018,8 @@ int status_get_speed(struct block_list *bl)
 		speed = ((struct pet_data *)bl)->speed;
 	else if(bl->type==BL_NPC)	//Added BL_NPC (Skotlex)
 		speed = ((struct npc_data *)bl)->speed;
+	else if(bl->type==BL_HOMUNCULUS) //[blackhole89]
+		speed = ((struct homun_data *)bl)->speed;
 
 	speed = status_calc_speed(bl,speed);
 
@@ -3023,6 +3049,10 @@ int status_get_adelay(struct block_list *bl)
 			adelay = ((struct pet_data *)bl)->db->adelay;
 			aspd_rate = 100;
 			break;
+		case BL_HOMUNCULUS:
+			adelay = 500;	//temp; this should go into the structure later
+			aspd_rate=100;	//[blackhole89]
+			break;
 		default:
 			adelay=4000;
 			aspd_rate = 100;
@@ -3049,6 +3079,7 @@ int status_get_amotion(struct block_list *bl)
 				aspd_rate -= aspd_rate * 10*((struct mob_data *)bl)->guardian_data->guardup_lv/100; // Strengthen Guardians - custom value +10% ASPD / lv
 		} else if(bl->type==BL_PET)
 			amotion = ((struct pet_data *)bl)->db->amotion;
+		else if(bl->type==BL_HOMUNCULUS) ((struct homun_data *)bl)->amotion;	//[blackhole89]
 
 		aspd_rate = status_calc_aspd_rate(bl,aspd_rate);
 
@@ -3078,6 +3109,7 @@ int status_get_dmotion(struct block_list *bl)
 	}
 	else if(bl->type==BL_PET)
 		ret=((struct pet_data *)bl)->db->dmotion;
+	else if(bl->type==BL_HOMUNCULUS) ((struct homun_data *)bl)->dmotion;	//[blackhole89]
 	else
 		return 2000;
 
@@ -3256,6 +3288,8 @@ int status_get_mode(struct block_list *bl)
 	}
 	if(bl->type==BL_PC)
 		return (MD_CANMOVE|MD_LOOTER|MD_CANATTACK);
+	if(bl->type==BL_HOMUNCULUS)		//[blackhole89]
+		return (MD_CANMOVE|MD_CANATTACK);
 	if(bl->type==BL_PET)
 		return ((struct pet_data *)bl)->db->mode;
 	if (bl->type==BL_SKILL)
@@ -3315,6 +3349,8 @@ struct view_data *status_get_viewdata(struct block_list *bl)
 			return &((TBL_PET*)bl)->vd;
 		case BL_NPC:
 			return ((TBL_NPC*)bl)->vd;
+		case BL_HOMUNCULUS: //[blackhole89]
+			return ((struct homun_data*)bl)->vd;
 	}
 	return NULL;
 }
@@ -3411,6 +3447,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
 				ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_);
 		}
 	break;
+	case BL_HOMUNCULUS:		//[blackhole89]
+		{
+			struct homun_data *hd = (struct homun_data*)bl;
+			if (vd)
+				hd->vd = vd;
+			else if (battle_config.error_log)
+				ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_);
+		}
+		break;
 	}
 	vd = status_get_viewdata(bl);
 	if (vd && vd->cloth_color && (
@@ -3430,6 +3475,8 @@ struct status_change *status_get_sc(struct block_list *bl)
 		return &((TBL_PC*)bl)->sc;
 	case BL_NPC:
 		return &((TBL_NPC*)bl)->sc;
+	case BL_HOMUNCULUS: //[blackhole89]
+		return &((struct homun_data*)bl)->sc;
 	}
 	return NULL;
 }