Esempio n. 1
0
void merc_hom_skillup(struct homun_data *hd,int skillnum)
{
	int i = 0 ;
	nullpo_retv(hd);

	if(hd->homunculus.vaporize)
		return;
	
	i = skillnum - HM_SKILLBASE;
	if(hd->homunculus.skillpts > 0 &&
		hd->homunculus.hskill[i].id &&
		hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
		hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->homunculus.class_)
		)
	{
		hd->homunculus.hskill[i].lv++;
		hd->homunculus.skillpts-- ;
		status_calc_homunculus(hd,0);
		if (hd->master) {
			clif_homskillup(hd->master, skillnum);
			clif_hominfo(hd->master,hd,0);
			clif_homskillinfoblock(hd->master);
		}
	}
}
Esempio n. 2
0
/**
 * Level up an homunculus skill
 * @param hd
 * @param skill_id
 */
void hom_skillup(struct homun_data *hd, uint16 skill_id)
{
	short idx = 0;
	nullpo_retv(hd);

	if (hd->homunculus.vaporize)
		return;

	if ((idx = hom_skill_get_index(skill_id)) < 0)
		return;
	if (hd->homunculus.skillpts > 0 &&
		hd->homunculus.hskill[idx].id &&
		hd->homunculus.hskill[idx].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
		hd->homunculus.hskill[idx].lv < hom_skill_tree_get_max(skill_id, hd->homunculus.class_)
		)
	{
		hd->homunculus.hskill[idx].lv++;
		hd->homunculus.skillpts-- ;
		status_calc_homunculus(hd, SCO_NONE);
		if (hd->master) {
			clif_homskillup(hd->master, skill_id);
			clif_hominfo(hd->master,hd,0);
			clif_homskillinfoblock(hd->master);
		}
	}
}
Esempio n. 3
0
int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
{
	int i, id = 0;
	int j, f = 1;
	int c = 0;

	nullpo_ret(hd);
	/* load previous homunculus form skills first. */
	if( hd->homunculus.prev_class != 0 ) {
		c = hd->homunculus.prev_class - HM_CLASS_BASE;

		for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) {
			if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id )
				continue; //Skill already known.
			if(!battle_config.skillfree) {
				for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) {
					if( hskill_tree[c][i].need[j].id &&
					   merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) {
						f = 0;
						break;
					}
				}
			}
			if ( f )
				hd->homunculus.hskill[id-HM_SKILLBASE].id = id;
		}

		f = 1;
	}

	c = hd->homunculus.class_ - HM_CLASS_BASE;

	for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) {
		if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id )
			continue; //Skill already known.
		j = ( flag_evolve ) ? 10 : hd->homunculus.intimacy;
		if( j < hskill_tree[c][i].intimacylv )
			continue;
		if(!battle_config.skillfree) {
			for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) {
				if( hskill_tree[c][i].need[j].id &&
					merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) {
					f = 0;
					break;
				}
			}
		}
		if ( f )
			hd->homunculus.hskill[id-HM_SKILLBASE].id = id;
	}

	if( hd->master )
		clif_homskillinfoblock(hd->master);
	return 0;
}
Esempio n. 4
0
void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
{
	struct map_session_data *sd = hd->master;
	hd->homunculus.hp = hd->battle_status.hp;
	if (!sd)
		return;
	clif_send_homdata(sd,SP_ACK,0);
	clif_hominfo(sd,hd,1);
	clif_hominfo(sd,hd,0);
	clif_homskillinfoblock(sd);
}
Esempio n. 5
0
/**
* Revive homunculus
* @param hd
* @param hp
* @param sp
*/
void hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
{
	struct map_session_data *sd = hd->master;
	hd->homunculus.hp = hd->battle_status.hp;
	if (!sd)
		return;
	clif_send_homdata(sd,SP_ACK,0);
	clif_hominfo(sd,hd,1);
	clif_hominfo(sd,hd,0);
	clif_homskillinfoblock(sd);
	if (hd->homunculus.class_ == 6052) //eleanor
		sc_start(&hd->bl,&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, -1);
}
Esempio n. 6
0
/**
* Shuffle homunculus status
* @param hd
*/
int hom_shuffle(struct homun_data *hd)
{
	struct map_session_data *sd;
	int lv, i, skillpts;
	unsigned int exp;
	struct s_skill b_skill[MAX_HOMUNSKILL];

	if (!hom_is_active(hd))
		return 0;

	sd = hd->master;
	lv = hd->homunculus.level;
	exp = hd->homunculus.exp;
	memcpy(&b_skill, &hd->homunculus.hskill, sizeof(b_skill));
	skillpts = hd->homunculus.skillpts;
	//Reset values to level 1.
	hom_reset_stats(hd);
	//Level it back up
	for (i = 1; i < lv && hd->exp_next; i++){
		hd->homunculus.exp += hd->exp_next;
		// Should never happen, but who knows
		if( !hom_levelup(hd) ) {
			break;
		}
	}

	if(hd->homunculus.class_ == hd->homunculusDB->evo_class) {
		//Evolved bonuses
		struct s_homunculus *hom = &hd->homunculus;
		struct h_stats *max = &hd->homunculusDB->emax, *min = &hd->homunculusDB->emin;
		hom->max_hp += rnd_value(min->HP, max->HP);
		hom->max_sp += rnd_value(min->SP, max->SP);
		hom->str += 10*rnd_value(min->str, max->str);
		hom->agi += 10*rnd_value(min->agi, max->agi);
		hom->vit += 10*rnd_value(min->vit, max->vit);
		hom->int_+= 10*rnd_value(min->int_,max->int_);
		hom->dex += 10*rnd_value(min->dex, max->dex);
		hom->luk += 10*rnd_value(min->luk, max->luk);
	}

	hd->homunculus.exp = exp;
	memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
	hd->homunculus.skillpts = skillpts;
	clif_homskillinfoblock(sd);
	status_calc_homunculus(hd, SCO_NONE);
	status_percent_heal(&hd->bl, 100, 100);
	clif_specialeffect(&hd->bl,568,AREA);

	return 1;
}
Esempio n. 7
0
/**
 * Receive homunculus data from char server
 * @param account_id : owner account_id of the homon
 * @param sh : homonculus data from char-serv
 * @param flag : does the creation in inter-serv was a success (0:no,1:yes)
 * @return 0:failure, 1:sucess
 */
int hom_recv_data(uint32 account_id, struct s_homunculus *sh, int flag)
{
	struct map_session_data *sd;
	struct homun_data *hd;
	bool created = false;

	sd = map_id2sd(account_id);
	if(!sd)
		return 0;
	if (sd->status.char_id != sh->char_id)
	{
		if (sd->status.hom_id == sh->hom_id)
			sh->char_id = sd->status.char_id; //Correct char id.
		else
			return 0;
	}
	if(!flag) { // Failed to load
		sd->status.hom_id = 0;
		return 0;
	}

	if (!sd->status.hom_id) { //Hom just created.
		sd->status.hom_id = sh->hom_id;
		created = true;
	}
	if (sd->hd) //uh? Overwrite the data.
		memcpy(&sd->hd->homunculus, sh, sizeof(struct s_homunculus));
	else
		hom_alloc(sd, sh);

	hd = sd->hd;
	if (created)
		status_percent_heal(&hd->bl, 100, 100);

	if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL)
	{
		if(map_addblock(&hd->bl))
			return 0;
		clif_spawn(&hd->bl);
		clif_send_homdata(sd,SP_ACK,0);
		clif_hominfo(sd,hd,1);
		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
		clif_homskillinfoblock(sd);
		hom_init_timers(hd);
	}
	return 1;
}
Esempio n. 8
0
int merc_call_homunculus(struct map_session_data *sd)
{
	struct homun_data *hd;

	if( sd->sc.data[SC__GROOMY] )
		return 0;

	if( map[sd->bl.m].flag.ancient )
		return 0; // Cannot call homunculus on Ancient WoE

	if (!sd->status.hom_id) //Create a new homun.
		return merc_create_homunculus_request(sd, HM_CLASS_BASE + rand(0, 7)) ;

	// If homunc not yet loaded, load it
	if (!sd->hd)
		return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);

	hd = sd->hd;

	if (!hd->homunculus.vaporize)
		return 0; //Can't use this if homun wasn't vaporized.

	merc_hom_init_timers(hd);
	hd->homunculus.vaporize = 0;
	if (hd->bl.prev == NULL)
	{	//Spawn him
		hd->bl.x = sd->bl.x;
		hd->bl.y = sd->bl.y;
		hd->bl.m = sd->bl.m;
		map_addblock(&hd->bl);
		clif_spawn(&hd->bl);
		clif_send_homdata(sd,SP_ACK,0);
		clif_hominfo(sd,hd,1);
		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
		clif_homskillinfoblock(sd);
		if (battle_config.slaves_inherit_speed&1)
			status_calc_bl(&hd->bl, SCB_SPEED);
		merc_save(hd); 
	} else
		//Warp him to master.
		unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT);
	return 1;
}
Esempio n. 9
0
/**
 * Make a player spawn a homonculus (call)
 * @param sd
 * @return False:failure, True:sucess
 */
bool hom_call(struct map_session_data *sd)
{
	struct homun_data *hd;

	if (!sd->status.hom_id) //Create a new homun.
		return hom_create_request(sd, HM_CLASS_BASE + rnd_value(0, 7)) ;

	// If homunc not yet loaded, load it
	if (!sd->hd)
		return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);

	hd = sd->hd;

	if (!hd->homunculus.vaporize)
		return false; //Can't use this if homun wasn't vaporized.

	if (hd->homunculus.vaporize == HOM_ST_MORPH)
		return false; // Can't call homunculus (morph state).

	hom_init_timers(hd);
	hd->homunculus.vaporize = HOM_ST_ACTIVE;
	if (hd->bl.prev == NULL)
	{	//Spawn him
		hd->bl.x = sd->bl.x;
		hd->bl.y = sd->bl.y;
		hd->bl.m = sd->bl.m;
		if(map_addblock(&hd->bl))
			return false;
		clif_spawn(&hd->bl);
		clif_send_homdata(sd,SP_ACK,0);
		clif_hominfo(sd,hd,1);
		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
		clif_homskillinfoblock(sd);
		if (battle_config.slaves_inherit_speed&1)
			status_calc_bl(&hd->bl, SCB_SPEED);
		hom_save(hd);
	} else
		//Warp him to master.
		unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT);
	return true;
}
Esempio n. 10
0
/**
* Calculates homunculus skill tree
* @param hd
* @param flag_envolve
*/
void hom_calc_skilltree(struct homun_data *hd, int flag_evolve)
{
	int i, skill_id = 0;
	int f = 1;
	short c = 0;

	nullpo_retv(hd);

	/* load previous homunculus form skills first. */
	if (hd->homunculus.prev_class != 0 && (c = hom_class2index(hd->homunculus.prev_class)) >= 0) {
		for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) {
			int idx = hom_skill_get_index(skill_id);
			if (idx < 0)
				continue;
			if (hd->homunculus.hskill[idx].id)
				continue; //Skill already known.
			if (!battle_config.skillfree) {
				int j;
				for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
					if (hskill_tree[c][i].need[j].id &&
						hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
					{
						f = 0;
						break;
					}
				}
			}
			if (f)
				hd->homunculus.hskill[idx].id = skill_id;
		}
		f = 1;
	}


	if ((c = hom_class2index(hd->homunculus.class_)) < 0)
		return;

	for (i = 0; i < MAX_SKILL_TREE && (skill_id = hskill_tree[c][i].id) > 0; i++) {
		int intimacy;
		int idx = hom_skill_get_index(skill_id);
		if (idx < 0)
			continue;
		if (hd->homunculus.hskill[idx].id)
			continue; //Skill already known.
		intimacy = (flag_evolve) ? 10 : hd->homunculus.intimacy;
		if (intimacy < hskill_tree[c][i].intimacylv)
			continue;
		if (!battle_config.skillfree) {
			int j;
			for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
				if (hskill_tree[c][i].need[j].id &&
					hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
				{
					f = 0;
					break;
				}
			}
		}
		if (f)
			hd->homunculus.hskill[idx].id = skill_id;
	}

	if (hd->master)
		clif_homskillinfoblock(hd->master);
}
Esempio n. 11
0
/**
* Homunculus leveled up
* @param hd
*/
int hom_levelup(struct homun_data *hd)
{
	struct s_homunculus *hom;
	struct h_stats *min = NULL, *max = NULL;
	int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ;
	int growth_max_hp, growth_max_sp ;
	int m_class;

	if ((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) {
		ShowError("hom_levelup: Invalid class %d. \n", hd->homunculus.class_);
		return 0;
	}

	/// When homunculus is homunculus S, we check to see if we need to apply previous class stats
	if(m_class&HOM_S && hd->homunculus.level < battle_config.hom_S_growth_level) {
		int i;
		if (!hd->homunculus.prev_class) {
			/// We also need to be sure that the previous class exists, otherwise give it something to work with
			hd->homunculus.prev_class = 6001;
		}
		// Give the homunculus the level up stats database it needs
		i = hom_search(hd->homunculus.prev_class,HOMUNCULUS_CLASS);
		if (i < 0) // Nothing should go wrong here, but check anyways
			return 0;
		max = &homunculus_db[i].gmax;
		min = &homunculus_db[i].gmin;
	}

	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))
		hom->skillpts++ ;	//1 skillpoint each 3 base level

	hom->exp -= hd->exp_next ;
	hd->exp_next = hexptbl[hom->level - 1] ;

	if (!max) {
		max  = &hd->homunculusDB->gmax;
		min  = &hd->homunculusDB->gmin;
	}

	growth_max_hp = rnd_value(min->HP, max->HP);
	growth_max_sp = rnd_value(min->SP, max->SP);
	growth_str = rnd_value(min->str, max->str);
	growth_agi = rnd_value(min->agi, max->agi);
	growth_vit = rnd_value(min->vit, max->vit);
	growth_dex = rnd_value(min->dex, max->dex);
	growth_int = rnd_value(min->int_,max->int_);
	growth_luk = rnd_value(min->luk, max->luk);

	//Aegis discards the decimals in the stat growth values!
	growth_str-=growth_str%10;
	growth_agi-=growth_agi%10;
	growth_vit-=growth_vit%10;
	growth_dex-=growth_dex%10;
	growth_int-=growth_int%10;
	growth_luk-=growth_luk%10;

	hom->max_hp += growth_max_hp;
	hom->max_sp += growth_max_sp;
	hom->str += growth_str;
	hom->agi += growth_agi;
	hom->vit += growth_vit;
	hom->dex += growth_dex;
	hom->int_+= growth_int;
	hom->luk += growth_luk;

	APPLY_HOMUN_LEVEL_STATWEIGHT();

	// Needed to update skill list for mutated homunculus so unlocked skills will appear when the needed level is reached.
	status_calc_homunculus(hd,SCO_NONE);
	clif_hominfo(hd->master,hd,0);
	clif_homskillinfoblock(hd->master);

	if ( hd->master && battle_config.homunculus_show_growth ) {
		char output[256] ;
		sprintf(output,
			"Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ",
			growth_max_hp, growth_max_sp,
			growth_str/10.0, growth_agi/10.0, growth_vit/10.0,
			growth_int/10.0, growth_dex/10.0, growth_luk/10.0);
		clif_messagecolor(&hd->master->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
	}
	return 1;
}
Esempio n. 12
0
/**
* Calculates homunculus skill tree
* @param hd
* @param flag_envolve
*/
void hom_calc_skilltree(struct homun_data *hd, bool flag_evolve) {
	uint8 i;
	short c = 0;

	nullpo_retv(hd);

	/* load previous homunculus form skills first. */
	if (hd->homunculus.prev_class != 0 && (c = hom_class2index(hd->homunculus.prev_class)) >= 0) {
		for (i = 0; i < MAX_HOM_SKILL_TREE; i++) {
			uint16 skill_id;
			short idx = -1;
			bool fail = false;
			if (!(skill_id = hskill_tree[c][i].id) || (idx = hom_skill_get_index(skill_id)) == -1)
				continue;
			if (hd->homunculus.hskill[idx].id)
				continue; //Skill already known.
			if (!battle_config.skillfree) {
				uint8 j;
				if (hskill_tree[c][i].need_level > hd->homunculus.level)
					continue;
				for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
					if (hskill_tree[c][i].need[j].id &&
						hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
					{
						fail = true;
						break;
					}
				}
			}
			if (!fail)
				hd->homunculus.hskill[idx].id = skill_id;
		}
	}


	if ((c = hom_class2index(hd->homunculus.class_)) < 0)
		return;

	for (i = 0; i < MAX_HOM_SKILL_TREE; i++) {
		unsigned int intimacy = 0;
		uint16 skill_id;
		short idx = -1;
		bool fail = false;
		if (!(skill_id = hskill_tree[c][i].id) || (idx = hom_skill_get_index(skill_id)) == -1)
			continue;
		if (hd->homunculus.hskill[idx].id)
			continue; //Skill already known.
		intimacy = (flag_evolve) ? 10 : hd->homunculus.intimacy;
		if (intimacy < hskill_tree[c][i].intimacy * 100)
			continue;
		if (!battle_config.skillfree) {
			uint8 j;
			if (hskill_tree[c][i].need_level > hd->homunculus.level)
				continue;
			for (j = 0; j < MAX_HOM_SKILL_REQUIRE; j++) {
				if (hskill_tree[c][i].need[j].id &&
					hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
				{
					fail = true;
					break;
				}
			}
		}
		if (!fail)
			hd->homunculus.hskill[idx].id = skill_id;
	}

	if (hd->master)
		clif_homskillinfoblock(hd->master);
}
Esempio n. 13
0
int merc_hom_levelup(struct homun_data *hd)
{
	struct s_homunculus *hom;
	struct h_stats *min, *max;
	int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ;
	int growth_max_hp, growth_max_sp ;
	char output[256] ;

	if (hd->homunculus.level == hd->homunculusDB->maxlevel || !hd->exp_next || hd->homunculus.exp < hd->exp_next)
		return 0 ;
	
	hom = &hd->homunculus;
	hom->level++ ;

	if ( hom->level > 99 )
	{
		if (!(hom->level % 2))
			hom->skillpts++ ;	//1 skill point for each 2 levels for mutated homunculus.
	}
	else
	{
		if (!(hom->level % 3))
			hom->skillpts++ ;	//1 skill point each 3 levels when below 100.
	}

	hom->exp -= hd->exp_next ;
	hd->exp_next = hexptbl[hom->level - 1] ;
	
	max  = &hd->homunculusDB->gmax;
	min  = &hd->homunculusDB->gmin;

	growth_max_hp = rand(min->HP, max->HP);
	growth_max_sp = rand(min->SP, max->SP);
	growth_str = rand(min->str, max->str);
	growth_agi = rand(min->agi, max->agi);
	growth_vit = rand(min->vit, max->vit);
	growth_dex = rand(min->dex, max->dex);
	growth_int = rand(min->int_,max->int_);
	growth_luk = rand(min->luk, max->luk);

	//Aegis discards the decimals in the stat growth values!
	growth_str-=growth_str%10;
	growth_agi-=growth_agi%10;
	growth_vit-=growth_vit%10;
	growth_dex-=growth_dex%10;
	growth_int-=growth_int%10;
	growth_luk-=growth_luk%10;

	hom->max_hp += growth_max_hp;
	hom->max_sp += growth_max_sp;
	hom->str += growth_str;
	hom->agi += growth_agi;
	hom->vit += growth_vit;
	hom->dex += growth_dex;
	hom->int_+= growth_int;
	hom->luk += growth_luk;

	// Needed to update skill list for mutated homunculus so unlocked skills will appear when the needed level is reached.
	clif_homskillinfoblock(hd->master);
	
	if ( battle_config.homunculus_show_growth ) {
		sprintf(output,
			"Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ",
			growth_max_hp, growth_max_sp,
			growth_str/10.0, growth_agi/10.0, growth_vit/10.0,
			growth_int/10.0, growth_dex/10.0, growth_luk/10.0);
		clif_disp_onlyself(hd->master,output,strlen(output));
	}
	return 1 ;
}