Browse Source

- Added new script command hommutate which changes an Homunculus into an Homunculus S Class. Super special thanks to Xantara for doing the command!
- Added 2 new configs to homunc.conf to set the Max. Level for Homunculus and homunculus.
- Updated homun_exp.txt table with values from Lvl. 99 to 150 for Homnunculus S.
- Updated script_commands.txt with description of the new script command.
- Added Homunculus S Quest. bugreport:5641

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

masao87 13 years ago
parent
commit
78cf7a424e

+ 7 - 1
conf/battle/homunc.conf

@@ -30,10 +30,16 @@ hom_rename: no
 hvan_explosion_intimate: 45000
 
 // Show stat growth to the owner when an Homunculus levels up
-homunculus_show_growth: no
+homunculus_show_growth: yes
 
 // Does autoloot work, when a monster is killed by homunculus only?
 homunculus_autoloot: yes
 
 // Should homunculii Vaporize when Master dies?
 homunculus_auto_vapor: yes
+
+// Max level for regular Homunculus
+homunculus_max_level: 99
+
+// Max level for Homunculus S
+homunculus_S_max_level: 150

+ 51 - 0
db/re/exp_homun.txt

@@ -97,4 +97,55 @@
 2280000
 2660000
 3135000
+3800000
+4124000
+4260000
+4462000
+4527000
+4779000
+4921000
+4984000
+5118000
+5353000
+5438000
+5507000
+5610000
+5776000
+5867000
+6000000
+6116000
+6241000
+6373000
+6498000
+6639000
+6720000
+6907000
+7025000
+7105000
+7264000
+7454000
+7611000
+7688000
+7735000
+7940000
+8020000
+8198000
+8318000
+8376000
+8469000
+8528000
+8573000
+8650000
+8701000
+8769000
+8814000
+8820000
+8826000
+8838000
+8887000
+8905000
+8916000
+8922000
+8966000
+9094000
 0    

+ 13 - 0
doc/script_commands.txt

@@ -5316,6 +5316,19 @@ the homunculus must have above 91000 intimacy with it's owner.
 
 ---------------------------------------
 
+*hommutate {<ID>};
+
+This Command will evolve the current player's Homunculus into the new Homunculus S.
+If it doesn't work, the /swt emotion is shown.
+
+To change a Homunculus into the new Homunculus S,
+the invoking Player must have an evolved Homunculus and it must be at least Level 99.
+
+If the optional parameter <ID> is set, the invoking Players Homunculus will change into the given ID's Homunculus S,
+otherwise the Homunculus will change into an randomly chosen Homunculus S Class.
+
+---------------------------------------
+
 *unitwalk <GID>,<x>,<y>;
 *unitwalk <GID>,<mapid>;
 

+ 236 - 0
npc/re/quests/homu_s.txt

@@ -0,0 +1,236 @@
+//===== rAthena Script ======================================= 
+//= Homunculus S Quest
+//===== By: ================================================== 
+//= Masao
+//===== Current Version: ===================================== 
+//= 1.0
+//===== Compatible With: ===================================== 
+//= rAthena SVN
+//===== Description: ========================================= 
+//= Evolves an Homunculus which is at least Level 99 to the
+//= new Homunculus S Class.
+//===== Additional Comments: ================================= 
+//= 1.0 First Version. The actual changing dialog is currently
+//=     customized. [Masao]
+//============================================================ 
+
+job3_gen01,12,44,4	script	Viorel#job3_gen01	542,{
+
+	if((Class != Job_Genetic) && (Class != Job_Genetic_T) && (Class != Job_Baby_Genetic)){
+		mes "[Viorel]";
+		mes "^FF4800Homunculus^000000 research requires a lot of time and funding.";
+		mes "However, I believe passion is the most important factor.";
+		next;
+		switch(select("End conversation.:What are you talking about?:Why are you always standing there?")) {
+		case 1:
+			mes "[Viorel]";
+			mes "So long~!";
+			close;
+		case 2:
+			mes "[Viorel]";
+			mes "You see, ^006400Alchemists^000000 have an inquisitive nature.";
+			mes "People like me, especially, even think of creating life itself.";
+			next;
+			mes "[Viorel]";
+			mes "You'd have to research ^FF4800Homunculus^000000 to understand.";
+			mes "Now, if you'll excuse me~!";
+			close;
+		case 3:
+			emotion 4,0;
+			mes "[Viorel]";
+			mes "What, is it so strange to see an Alchemist in their own lab?";
+			mes "How so?";
+			close;
+		}
+	}
+	mes "[Viorel]";
+	mes "Hello "+strcharinfo(0)+",";
+	mes "what can I do for an fellow Alchemist like you?";
+	next;
+	switch(select("I want to evolve my Homunculus:About Homunculus S:Cancel")){
+	case 1:
+		mes "[Viorel]";
+		if(!getskilllv("AM_BIOETHICS")){
+			mes "I'm sorry but you must know the Skill Bioethics! Otherwise I can't let your Homunculus evolve into an Homunculus S.";
+			close;
+		}
+		if(gethominfo(1) < 6009){
+			mes "I'm sorry but you must have an evolved Homunculus, otherwise you can't let it evolve to the new Homunculus S.";
+			close;
+		}
+		if(gethominfo(6) < 99){
+			mes "I'm sorry but to evolve your Homunculus to the next level it must be Level 99!";
+			mes "Come back after you've trained your Homunculus a little bit more.";
+			close;
+		}
+		if(gethominfo(1) == 6048 || gethominfo(1) == 6049 || gethominfo(1) == 6050 || gethominfo(1) == 6051 || gethominfo(1) == 6052){
+			mes "Your Homunculus S looks great!";
+			mes "I hope you wil experience many great adventures with it!";
+			close;
+		}
+		mes "Great, it seems like you're all ready to get your Homunculus to the next level!";
+		next;
+		mes "[Viorel]";
+		mes "Now if you want to you can either directly change your Homunculus to an new random Homunculus S Form or you can donate a little fee";
+		mes "of 50'000 zeny to the Alchemist Guild and for this you'll be able to change your Homunculus into your desired Homunculus S Class!";
+		mes "So, what do you think?";
+		next;
+		switch(Select("I want to Donate:I don't want to Donate:Cancel")){
+		case 1:
+			if(Zeny < 50000){
+				mes "[Viorel]";
+				mes "Haha, nice try my friend! But you don't even have the 50'000 zeny to donate!";
+				mes "Come back if you have the zeny, thanks.";
+				close;
+			}
+			mes "[Viorel]";
+			mes "Allright, now please tell me which Homunculus you'd like to have:";
+			next;
+			switch(select("Eira:Bayeri:Sera:Dieter:Elanor:Cancel")){
+			case 1:
+				mes "[Viorel]";
+				mes "Ok, it's all set! Now just give me a moment!";
+				next;
+				mes "[Viorel]";
+				mes "Abra...";
+				next;
+				mes "[Viorel]";
+				mes "Kadabra...";
+				next;
+				mes "[Viorel]";
+				mes "Simsala!";
+				mes "...";
+				mes "Oh sorry.. wrong game!";
+				next;
+				mes "[Viorel]";
+				mes "Here you go! Your new Homunculus S!";
+				hommutate 6048;
+				set Zeny,Zeny - 50000;
+				close;
+			case 2:
+				mes "[Viorel]";
+				mes "Ok, it's all set! Now just give me a moment!";
+				next;
+				mes "[Viorel]";
+				mes "Abra...";
+				next;
+				mes "[Viorel]";
+				mes "Kadabra...";
+				next;
+				mes "[Viorel]";
+				mes "Simsala!";
+				mes "...";
+				mes "Oh sorry.. wrong game!";
+				next;
+				mes "[Viorel]";
+				mes "Here you go! Your new Homunculus S!";
+				hommutate 6049;
+				set Zeny,Zeny - 50000;
+				close;
+			case 3:
+				mes "[Viorel]";
+				mes "Ok, it's all set! Now just give me a moment!";
+				next;
+				mes "[Viorel]";
+				mes "Abra...";
+				next;
+				mes "[Viorel]";
+				mes "Kadabra...";
+				next;
+				mes "[Viorel]";
+				mes "Simsala!";
+				mes "...";
+				mes "Oh sorry.. wrong game!";
+				next;
+				mes "[Viorel]";
+				mes "Here you go! Your new Homunculus S!";
+				hommutate 6050;
+				set Zeny,Zeny - 50000;
+				close;
+			case 4:
+				mes "[Viorel]";
+				mes "Ok, it's all set! Now just give me a moment!";
+				next;
+				mes "[Viorel]";
+				mes "Abra...";
+				next;
+				mes "[Viorel]";
+				mes "Kadabra...";
+				next;
+				mes "[Viorel]";
+				mes "Simsala!";
+				mes "...";
+				mes "Oh sorry.. wrong game!";
+				next;
+				mes "[Viorel]";
+				mes "Here you go! Your new Homunculus S!";
+				hommutate 6051;
+				set Zeny,Zeny - 50000;
+				close;
+			case 5:
+				mes "[Viorel]";
+				mes "Ok, it's all set! Now just give me a moment!";
+				next;
+				mes "[Viorel]";
+				mes "Abra...";
+				next;
+				mes "[Viorel]";
+				mes "Kadabra...";
+				next;
+				mes "[Viorel]";
+				mes "Simsala!";
+				mes "...";
+				mes "Oh sorry.. wrong game!";
+				next;
+				mes "[Viorel]";
+				mes "Here you go! Your new Homunculus S!";
+				hommutate 6052;
+				set Zeny,Zeny - 50000;
+				close;
+			case 6:
+				mes "[Viorel]";
+				mes "So long~!";
+				close;
+			}
+		case 2:
+			mes "[Viorel]";
+			mes "Ok, it's all set! Now just give me a moment!";
+			next;
+			mes "[Viorel]";
+			mes "Abra...";
+			next;
+			mes "[Viorel]";
+			mes "Kadabra...";
+			next;
+			mes "[Viorel]";
+			mes "Simsala!";
+			mes "...";
+			mes "Oh sorry.. wrong game!";
+			next;
+			mes "[Viorel]";
+			mes "Here you go! Your new Homunculus S!";
+			hommutate;
+			close;
+		case 3:
+			mes "[Viorel]";
+			mes "So long~!";
+			close;
+		}
+	case 2:
+		mes "[Viorel]";
+		mes "The Homunculus S are the new and improved Versions of the current Homunculus you know.";
+		mes "These new Homunculus have been made since the Monsters in our World keep getting stronger and stronger";
+		mes "and our current loyal Homunculus are just not able to keep up with them anymore so they can't";
+		mes "protect their Masters anymore!";
+		next;
+		mes "[Viorel]";
+		mes "But since we're Alchemists and we don't want to abandon our precious Homunculus we found a Way to improve their";
+		mes "skills and strength in order to keep them by our side and joining us once more in battle!";
+		mes "Isn't that great?";
+		close;
+	case 3:
+		mes "[Viorel]";
+		mes "So long~!";
+		close;
+	}
+}

+ 1 - 0
npc/re/scripts_athena.conf

@@ -214,6 +214,7 @@ npc: npc/re/quests/eden/56-70.txt
 npc: npc/re/quests/eden/71-85.txt
 npc: npc/re/quests/eden/86-90.txt
 npc: npc/re/quests/eden/91-99.txt
+npc: npc/re/quests/homu_s.txt
 // --------------------------------------------------------------
 // --------------------------- Guides ---------------------------
 npc: npc/re/guides/guides_alberta.txt

+ 2 - 0
src/map/battle.c

@@ -5446,6 +5446,8 @@ static const struct _battle_data {
 	{ "feature.atcommand_suggestions",		&battle_config.atcommand_suggestions_enabled,	0,      0,      1				},
 	{ "min_npc_vending_distance",           &battle_config.min_npc_vending_distance,		3,		0,		100				},
 	{ "atcommand_mobinfo_type",				&battle_config.atcommand_mobinfo_type,			0,		0,		1				},
+	{ "homunculus_max_level",               &battle_config.hom_max_level,                   99,     0,      MAX_LEVEL,      },
+	{ "homunculus_S_max_level",             &battle_config.hom_S_max_level,                 150,    0,      MAX_LEVEL,      },
 };
 
 

+ 2 - 0
src/map/battle.h

@@ -455,6 +455,8 @@ extern struct Battle_Config
 	int cashshop_show_points;
 	int mail_show_status;
 	int client_limit_unit_lv;
+	int hom_max_level;
+	int hom_S_max_level;
 
 	// [BattleGround Settings]
 	int bg_update_interval;

+ 8 - 2
src/map/clif.c

@@ -1395,10 +1395,13 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
 {
 	struct status_data *status;
 	unsigned char buf[128];
+	int m_class;
 	
 	nullpo_retv(hd);
 
-	status = &hd->battle_status;
+	status  = &hd->battle_status;
+	m_class = hom_class2mapid(hd->homunculus.class_);
+
 	memset(buf,0,packet_len(0x22e));
 	WBUFW(buf,0)=0x22e;
 	memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH);
@@ -1434,7 +1437,10 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
 		WBUFW(buf,57)=status->max_sp;
 	}
 	WBUFL(buf,59)=hd->homunculus.exp;
-	WBUFL(buf,63)=hd->exp_next;
+	if( ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) )
+		WBUFL(buf,63)=0;
+	else
+		WBUFL(buf,63)=hd->exp_next;
 	WBUFW(buf,67)=hd->homunculus.skillpts;
 	WBUFW(buf,69)=status_get_range(&hd->bl);
 	clif_send(buf,packet_len(0x22e),&sd->bl,SELF);

+ 81 - 4
src/map/homunculus.c

@@ -56,6 +56,31 @@ struct view_data* merc_get_hom_viewdata(int class_)
 	return NULL;
 }
 
+int hom_class2mapid(int hom_class)
+{
+	switch(hom_class)
+	{
+		// Normal Homunculus
+		case 6001: case 6005:                return MAPID_LIF;
+		case 6002: case 6006:                return MAPID_AMISTR;
+		case 6003: case 6007:                return MAPID_FILIR;
+		case 6004: case 6008:                return MAPID_VANILMIRTH;
+		// Evolved Homunculus
+		case 6009: case 6013:                return MAPID_LIF_E;
+		case 6010: case 6014:                return MAPID_AMISTR_E;
+		case 6011: case 6015:                return MAPID_FILIR_E;
+		case 6012: case 6016:                return MAPID_VANILMIRTH_E;
+		// Homunculus S
+		case 6048:                           return MAPID_EIRA;
+		case 6049:                           return MAPID_BAYERI;
+		case 6050:                           return MAPID_SERA;
+		case 6051:                           return MAPID_DIETER;
+		case 6052:                           return MAPID_ELANOR;
+		
+		default:                             return -1;
+	}
+}
+
 void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
 {
 	clif_hominfo(hd->master,hd,0);
@@ -215,10 +240,13 @@ int merc_hom_levelup(struct homun_data *hd)
 	int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ;
 	int growth_max_hp, growth_max_sp ;
 	char output[256] ;
+	int m_class;
 
-	if (hd->homunculus.level == MAX_LEVEL || !hd->exp_next || hd->homunculus.exp < hd->exp_next)
+	m_class = hom_class2mapid(hd->homunculus.class_);
+
+	if((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level || (m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level || !hd->exp_next || hd->homunculus.exp < hd->exp_next)
 		return 0 ;
-	
+
 	hom = &hd->homunculus;
 	hom->level++ ;
 	if (!(hom->level % 3)) 
@@ -333,13 +361,62 @@ int merc_hom_evolution(struct homun_data *hd)
 	return 1 ;
 }
 
+int hom_mutate(struct homun_data *hd, int homun_id)
+{
+	struct s_homunculus *hom;
+	struct map_session_data *sd;
+	int m_class, m_id;
+	nullpo_ret(hd);
+
+	m_class = hom_class2mapid(hd->homunculus.class_);
+	m_id    = hom_class2mapid(homun_id);
+	
+	if( !m_class&HOM_EVO || !m_id&HOM_S ) {
+		clif_emotion(&hd->bl, E_SWT);
+		return 0;
+	}
+	
+	sd = hd->master;
+	if (!sd)
+		return 0;
+
+	if (!merc_hom_change_class(hd, homun_id)) {
+		ShowError("hom_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id);
+		return 0;
+	}
+
+	unit_remove_map(&hd->bl, CLR_OUTSIGHT);
+	map_addblock(&hd->bl);
+
+	clif_spawn(&hd->bl);
+	clif_emotion(&sd->bl, E_NO1);
+	clif_specialeffect(&hd->bl,568,AREA);
+
+	//status_Calc flag&1 will make current HP/SP be reloaded from hom structure
+	hom = &hd->homunculus;
+	hom->hp = hd->battle_status.hp;
+	hom->sp = hd->battle_status.sp;
+	status_calc_homunculus(hd,1);
+
+	if (!(battle_config.hom_setting&0x2))
+		skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
+	
+	return 1;
+}
+
 int merc_hom_gainexp(struct homun_data *hd,int exp)
 {
+	int m_class;
+
 	if(hd->homunculus.vaporize)
 		return 1;
 
-	if( hd->exp_next == 0 ) {
-		hd->homunculus.exp = 0 ;
+	m_class = hom_class2mapid(hd->homunculus.class_);
+	
+	if( hd->exp_next == 0 || 
+	   ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) ||
+	   ((m_class&HOM_S)   && hd->homunculus.level >= battle_config.hom_S_max_level) ) {
+	  	hd->homunculus.exp = 0;
 		return 0;
 	}
 

+ 30 - 5
src/map/homunculus.h

@@ -47,6 +47,29 @@ struct homun_data {
 	char blockskill[MAX_SKILL];	// [orn]
 };
 
+#define HOM_EVO 0x100 //256
+#define HOM_S 0x200 //512
+
+#define HOM_REG 0x1000 //4096
+
+enum {
+// Normal Homunculus
+	MAPID_LIF = HOM_REG|0x0,
+	MAPID_AMISTR,
+	MAPID_FILIR,
+	MAPID_VANILMIRTH,
+// Evolved Homunulus
+	MAPID_LIF_E = HOM_REG|HOM_EVO|0x0,
+	MAPID_AMISTR_E,
+	MAPID_FILIR_E,
+	MAPID_VANILMIRTH_E,
+// Homunculus S
+	MAPID_EIRA = HOM_S|0x0,
+	MAPID_BAYERI,
+	MAPID_SERA,
+	MAPID_DIETER,
+	MAPID_ELANOR,
+};
 
 #define homdb_checkid(id) (id >=  HM_CLASS_BASE && id <= HM_CLASS_MAX)
 
@@ -55,14 +78,16 @@ struct homun_data {
 int do_init_merc(void);
 int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator
 struct view_data* merc_get_hom_viewdata(int class_);
+int hom_class2mapid(int hom_class);
 void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp);
 int merc_hom_dead(struct homun_data *hd, struct block_list *src);
 void merc_hom_skillup(struct homun_data *hd,int skillnum);
-int merc_hom_calc_skilltree(struct homun_data *hd) ;
-int merc_hom_checkskill(struct homun_data *hd,int skill_id) ;
-int merc_hom_gainexp(struct homun_data *hd,int exp) ;
-int merc_hom_levelup(struct homun_data *hd) ;
-int merc_hom_evolution(struct homun_data *hd) ;
+int merc_hom_calc_skilltree(struct homun_data *hd);
+int merc_hom_checkskill(struct homun_data *hd,int skill_id);
+int merc_hom_gainexp(struct homun_data *hd,int exp);
+int merc_hom_levelup(struct homun_data *hd);
+int merc_hom_evolution(struct homun_data *hd);
+int hom_mutate(struct homun_data *hd,int homun_id);
 void merc_hom_heal(struct homun_data *hd,int hp,int sp);
 int merc_hom_vaporize(struct map_session_data *sd, int flag);
 int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y);

+ 31 - 0
src/map/script.c

@@ -9551,6 +9551,36 @@ BUILDIN_FUNC(homunculus_evolution)
 	return 0;
 }
 
+/*==========================================
+ * [Xantara]
+ *------------------------------------------*/
+BUILDIN_FUNC(homunculus_mutate)
+{
+	int homun_id, m_class, m_id;
+	int homun_array[5] = {6048,6049,6050,6051,6052};
+	TBL_PC *sd;
+
+	sd = script_rid2sd(st);
+	if( sd == NULL )
+		return 0;
+
+	if(script_hasdata(st,2))
+		homun_id = script_getnum(st,2);
+	else
+		homun_id = homun_array[rnd() % 5];
+
+	if(merc_is_hom_active(sd->hd)) {
+		m_class = hom_class2mapid(sd->hd->homunculus.class_);
+		m_id    = hom_class2mapid(homun_id);
+		
+		if ( m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99 )
+			hom_mutate(sd->hd, homun_id);
+		else
+			clif_emotion(&sd->hd->bl, E_SWT);
+	}
+	return 0;
+}
+
 // [Zephyrus]
 BUILDIN_FUNC(homunculus_shuffle)
 {
@@ -16676,6 +16706,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(getvariableofnpc,"rs"),
 	BUILDIN_DEF(warpportal,"iisii"),
 	BUILDIN_DEF2(homunculus_evolution,"homevolution",""),	//[orn]
+	BUILDIN_DEF2(homunculus_mutate,"hommutate","?"),
 	BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""),	//[Zephyrus]
 	BUILDIN_DEF(eaclass,"?"),	//[Skotlex]
 	BUILDIN_DEF(roclass,"i?"),	//[Skotlex]