Beispiel #1
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);
}
Beispiel #2
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);
}
Beispiel #3
0
int merc_hom_gainexp(struct homun_data *hd,int exp)
{
	if(hd->homunculus.vaporize)
		return 1;

	if( hd->exp_next == 0 ) {
		hd->homunculus.exp = 0 ;
		return 0;
	}

	hd->homunculus.exp += exp;

	if(hd->homunculus.exp < hd->exp_next) {
		clif_hominfo(hd->master,hd,0);
		return 0;
	}

 	//levelup
	do
	{
		merc_hom_levelup(hd) ;
	}
	while(hd->homunculus.exp > hd->exp_next && hd->exp_next != 0 );
		
	if( hd->exp_next == 0 )
		hd->homunculus.exp = 0 ;

	clif_specialeffect(&hd->bl,568,AREA);
	status_calc_homunculus(hd,0);
	status_percent_heal(&hd->bl, 100, 100);
	return 0;
}
Beispiel #4
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);
		}
	}
}
Beispiel #5
0
//Vaporize a character's homun. If flag, HP needs to be 80% or above.
int merc_hom_vaporize(struct map_session_data *sd, int flag)
{
	struct homun_data *hd;

	nullpo_retr(0, sd);

	hd = sd->hd;
	if (!hd || hd->homunculus.vaporize)
		return 0;
	
	if (status_isdead(&hd->bl))
		return 0; //Can't vaporize a dead homun.

	if (flag && status_calc_life(hd->battle_status.hp, hd->battle_status.max_hp)< 80)
		return 0;

	hd->regen.state.block = 3; //Block regen while vaporized.
	//Delete timers when vaporized.
	merc_hom_hungry_timer_delete(hd);
	hd->homunculus.vaporize = 1;
	if(battle_config.hom_setting&0x40)
		memset(hd->blockskill, 0, sizeof(hd->blockskill));
	clif_hominfo(sd, sd->hd, 0);
	merc_save(hd);
	return unit_remove_map(&hd->bl, 0);
}
Beispiel #6
0
/**
* Vaporize a character's homunculus
* @param sd
* @param flag 1: then HP needs to be 80% or above. 2: then set to morph state.
*/
int hom_vaporize(struct map_session_data *sd, int flag)
{
	struct homun_data *hd;

	nullpo_ret(sd);

	hd = sd->hd;
	if (!hd || hd->homunculus.vaporize)
		return 0;

	if (status_isdead(&hd->bl))
		return 0; //Can't vaporize a dead homun.

	if (flag == HOM_ST_REST && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
		return 0;

	hd->regen.state.block = 3; //Block regen while vaporized.
	//Delete timers when vaporized.
	hom_hungry_timer_delete(hd);
	hd->homunculus.vaporize = flag ? flag : HOM_ST_REST;
	if (battle_config.hom_setting&HOMSET_RESET_REUSESKILL_VAPORIZED)
		memset(hd->blockskill, 0, sizeof(hd->blockskill));
	clif_hominfo(sd, sd->hd, 0);
	hom_save(hd);
	return unit_remove_map(&hd->bl, CLR_OUTSIGHT);
}
Beispiel #7
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);
		}
	}
}
Beispiel #8
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;
}
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;
}
Beispiel #10
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;
}
Beispiel #11
0
int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag)
{
	struct homun_data *hd = sd->hd;
	if (!merc_is_hom_active(hd)) return 0;
	if (!flag) {
		clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name
		return 0;
	}
	strncpy(hd->homunculus.name,name,NAME_LENGTH);
	clif_charnameack (0,&hd->bl);
	hd->homunculus.rename_flag = 1;
	clif_hominfo(sd,hd,0);
	return 1;
}
Beispiel #12
0
/**
* Acknowledge change name request from inter-server
* @param sd
* @param name
* @param flag
*/
void hom_change_name_ack(struct map_session_data *sd, char* name, int flag)
{
	struct homun_data *hd = sd->hd;
	if (!hom_is_active(hd))
		return;

	normalize_name(name," ");//bugreport:3032

	if (!flag || name[0] == '\0') {
		clif_displaymessage(sd->fd, msg_txt(sd,280)); // You cannot use this name
		return;
	}
	safestrncpy(hd->homunculus.name,name,NAME_LENGTH);
	clif_charnameack (0,&hd->bl);
	hd->homunculus.rename_flag = 1;
	clif_hominfo(sd,hd,0);
}
Beispiel #13
0
/**
* Add homunculus exp
* @param hd
* @param exp Added EXP
*/
void hom_gainexp(struct homun_data *hd,int exp)
{
	int m_class;

	nullpo_retv(hd);

	if(hd->homunculus.vaporize)
		return;

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

	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;
	}

	hd->homunculus.exp += exp;

	if (hd->homunculus.exp < hd->exp_next) {
		clif_hominfo(hd->master,hd,0);
		return;
	}

 	// Do the levelup(s)
	while( hd->homunculus.exp > hd->exp_next ){
		// Max level reached or error
		if( !hom_levelup(hd) ){
			break;
		}
	}

	if( hd->exp_next == 0 )
		hd->homunculus.exp = 0 ;

	clif_specialeffect(&hd->bl,568,AREA);
	status_calc_homunculus(hd, SCO_NONE);
	status_percent_heal(&hd->bl, 100, 100);
}
Beispiel #14
0
/**
* Delete a homunculus, completely "killing it".
* Emote is the emotion the master should use, send negative to disable.
* @param hd
* @param emote
*/
int hom_delete(struct homun_data *hd, int emote)
{
	struct map_session_data *sd;
	nullpo_ret(hd);
	sd = hd->master;

	if (!sd)
		return unit_free(&hd->bl,CLR_DEAD);

	if (emote >= 0)
		clif_emotion(&sd->bl, emote);

	//This makes it be deleted right away.
	hd->homunculus.intimacy = 0;
	// Send homunculus_dead to client
	hd->homunculus.hp = 0;
	clif_hominfo(sd, hd, 0);
	return unit_remove_map(&hd->bl,CLR_OUTSIGHT);
}
Beispiel #15
0
int merc_hom_gainexp(struct homun_data *hd,int exp)
{
	int m_class;

	if(hd->homunculus.vaporize)
		return 1;

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

	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;
	}

	hd->homunculus.exp += exp;

	if(hd->homunculus.exp < hd->exp_next) {
		clif_hominfo(hd->master,hd,0);
		return 0;
	}

 	//levelup
	do
	{
		merc_hom_levelup(hd) ;
	}
	while(hd->homunculus.exp > hd->exp_next && hd->exp_next != 0 );

	if( hd->exp_next == 0 )
		hd->homunculus.exp = 0 ;

	clif_specialeffect(&hd->bl,568,AREA);
	status_calc_homunculus(hd,0);
	status_percent_heal(&hd->bl, 100, 100);
	return 0;
}
Beispiel #16
0
int merc_hom_gainexp(struct homun_data *hd,int exp)
{
	struct map_session_data *sd;
	struct s_homunculus *hom;
	hom = &hd->homunculus;

	sd = hd->master;

	if(hd->homunculus.vaporize)
		return 1;

	if( hd->exp_next == 0 ) {
		hd->homunculus.exp = 0 ;
		return 0;
	}

	if (sd->sc.data[SC_EXPBOOST])
		exp += exp*((sd->sc.data[SC_EXPBOOST]->val1)/100);

	hd->homunculus.exp += exp;

	if(hd->homunculus.exp < hd->exp_next) {
		clif_hominfo(hd->master,hd,0);
		return 0;
	}

 	//levelup
	do
	{
		merc_hom_levelup(hd) ;
	}
	while(hd->homunculus.exp > hd->exp_next && hd->exp_next != 0 && hom->evomoment == 0 );
		
	if( hd->exp_next == 0 )
		hd->homunculus.exp = 0 ;

	clif_specialeffect(&hd->bl,705,AREA);
	status_calc_homunculus(hd,0);
	status_percent_heal(&hd->bl, 100, 100);
	return 0;
}
Beispiel #17
0
/**
* Update homunculus info to master after healing
* @param hd
*/
void hom_heal(struct homun_data *hd) {
	clif_hominfo(hd->master,hd,0);
}
Beispiel #18
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;
}
Beispiel #19
0
void merc_damage(struct homun_data *hd) {
	clif_hominfo(hd->master,hd,0);
}
Beispiel #20
0
void merc_hom_heal(struct homun_data *hd,int hp,int sp)
{
	clif_hominfo(hd->master,hd,0);
}
Beispiel #21
0
void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
{
	clif_hominfo(hd->master,hd,0);
}
Beispiel #22
0
/**
* Update homunculus info to its master after receiving damage
* @param hd
*/
void hom_damage(struct homun_data *hd) {
	if (hd->master)
		clif_hominfo(hd->master,hd,0);
}