Homunculus Fixes
Applied a new check for Homunculus S reshuffling and leveling -> When the Homunculus S is below the define battle config "homunculus_S_growth_level", it uses its previous class' growth rates which helps prevent imbalanced Homunculus - If it has no previous class (command made), it will default to 6001 (Lif) Fixed Eleanor's skills - All skills which use spirit spheres now check for them prior - SONIC_CLAW now deletes the spirit spheres Fixed Eleanor obtaining spirit spheres for either FIghting or Grapple mode - She is suppose to have a 50% chance to gain a spirit sphere when attacking in FIghting Mode and a 50% chance when being hit in Grapple Mode (according to Warp Portal) Fixed packet dump errors - http://rathena.org/board/tracker/issue-8217-map-server-error-when-login-character/
This commit is contained in:
@@ -43,3 +43,9 @@ homunculus_max_level: 99
|
||||
|
||||
// Max level for Homunculus S
|
||||
homunculus_S_max_level: 150
|
||||
|
||||
// Growth level for Homunculus S
|
||||
// This is the level at which homunculus S can use their growth tables
|
||||
// Without this, a shuffle causes all levels of a Homunculus S to use their
|
||||
// growth tables, causing imbalanced stats
|
||||
homunculus_S_growth_level: 99
|
||||
|
||||
@@ -1157,9 +1157,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
|
||||
if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 )
|
||||
pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
|
||||
if (sc->data[SC_STYLE_CHANGE]) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,bl); //when being hit
|
||||
if (hd && (rnd()%100<(status_get_lv(bl)/2)) ) hom_addspiritball(hd, 10); //add a sphere
|
||||
if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,bl); // We add a sphere for when the Homunculus is being hit
|
||||
if (hd && (rnd()%100<50) ) hom_addspiritball(hd, 10); // According to WarpPortal, this is a flat 50% chance
|
||||
}
|
||||
|
||||
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
@@ -1220,9 +1220,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
sc_start(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1));
|
||||
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
|
||||
status_change_spread(src, bl);
|
||||
if (sc->data[SC_STYLE_CHANGE]) {
|
||||
if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING) {
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,src); //when attacking
|
||||
if (hd && (rnd()%100<(20+status_get_lv(bl)/5)) ) hom_addspiritball(hd, 10);
|
||||
if (hd && (rnd()%100<50) ) hom_addspiritball(hd, 10); // According to WarpPortal, this is a flat 50% chance
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7235,6 +7235,7 @@ static const struct _battle_data {
|
||||
{ "drop_rateincrease", &battle_config.drop_rateincrease, 0, 0, 1, },
|
||||
{ "feature.banking", &battle_config.feature_banking, 1, 0, 1, },
|
||||
{ "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, },
|
||||
{ "homunculus_S_growth_level", &battle_config.hom_S_growth_level, 99, 0, MAX_LEVEL, },
|
||||
};
|
||||
#ifndef STATS_OPT_OUT
|
||||
/**
|
||||
|
||||
@@ -462,6 +462,7 @@ extern struct Battle_Config
|
||||
int client_limit_unit_lv;
|
||||
int hom_max_level;
|
||||
int hom_S_max_level;
|
||||
int hom_S_growth_level;
|
||||
|
||||
// [BattleGround Settings]
|
||||
int bg_update_interval;
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
/* for clif_clearunit_delayed */
|
||||
static struct eri *delay_clearunit_ers;
|
||||
|
||||
#define DUMP_UNKNOWN_PACKET
|
||||
#define DUMP_INVALID_PACKET
|
||||
//#define DUMP_UNKNOWN_PACKET
|
||||
//#define DUMP_INVALID_PACKET
|
||||
|
||||
struct Clif_Config {
|
||||
int packet_db_ver; //Preferred packet version.
|
||||
|
||||
@@ -312,7 +312,7 @@ void merc_hom_skillup(struct homun_data *hd,uint16 skill_id)
|
||||
int merc_hom_levelup(struct homun_data *hd)
|
||||
{
|
||||
struct s_homunculus *hom;
|
||||
struct h_stats *min, *max;
|
||||
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;
|
||||
@@ -322,6 +322,21 @@ int merc_hom_levelup(struct homun_data *hd)
|
||||
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 = search_homunculusDB_index(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)
|
||||
@@ -335,8 +350,10 @@ int merc_hom_levelup(struct homun_data *hd)
|
||||
hom->exp -= hd->exp_next ;
|
||||
hd->exp_next = hexptbl[hom->level - 1] ;
|
||||
|
||||
max = &hd->homunculusDB->gmax;
|
||||
min = &hd->homunculusDB->gmin;
|
||||
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);
|
||||
@@ -1022,7 +1039,7 @@ int merc_hom_shuffle(struct homun_data *hd)
|
||||
for (i = 1; i < lv && hd->exp_next; i++){
|
||||
hd->homunculus.exp += hd->exp_next;
|
||||
// Should never happen, but who knows
|
||||
if( !merc_hom_levelup(hd) ){
|
||||
if( !merc_hom_levelup(hd) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,22 +679,28 @@ bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd)
|
||||
if(hd->sc.data[SC_GOLDENE_FERSE]) return true;
|
||||
break;
|
||||
case MH_TINDER_BREAKER: //must be in grappling mode
|
||||
if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING)) return true;
|
||||
if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING)
|
||||
|| !hd->homunculus.spiritball) return true;
|
||||
break;
|
||||
case MH_SONIC_CRAW: //must be in fighting mode
|
||||
if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING)) return true;
|
||||
if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING)
|
||||
|| !hd->homunculus.spiritball) return true;
|
||||
break;
|
||||
case MH_SILVERVEIN_RUSH:
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SONIC_CRAW)) return true;
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SONIC_CRAW)
|
||||
|| hd->homunculus.spiritball < 2) return true;
|
||||
break;
|
||||
case MH_MIDNIGHT_FRENZY:
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SILVERVEIN_RUSH)) return true;
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SILVERVEIN_RUSH)
|
||||
|| !hd->homunculus.spiritball) return true;
|
||||
break;
|
||||
case MH_CBC:
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_TINDER_BREAKER)) return true;
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_TINDER_BREAKER)
|
||||
|| !hd->homunculus.spiritball) return true;
|
||||
break;
|
||||
case MH_EQC:
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_CBC)) return true;
|
||||
if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_CBC)
|
||||
|| !hd->homunculus.spiritball) return true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5003,15 +5009,19 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
|
||||
case MH_STAHL_HORN:
|
||||
case MH_NEEDLE_OF_PARALYZE:
|
||||
case MH_SONIC_CRAW:
|
||||
skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
break;
|
||||
case MH_MIDNIGHT_FRENZY:
|
||||
case MH_SILVERVEIN_RUSH:
|
||||
case MH_SONIC_CRAW:
|
||||
{
|
||||
TBL_HOM *hd = BL_CAST(BL_HOM,src);
|
||||
hom_delspiritball(hd,skill_id==MH_SILVERVEIN_RUSH?1:2,0);
|
||||
short remove_sphere = (skill_id==MH_SILVERVEIN_RUSH?1:2);
|
||||
|
||||
if(skill_id == MH_SONIC_CRAW)
|
||||
remove_sphere = hd->homunculus.spiritball;
|
||||
skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
|
||||
hom_delspiritball(hd,remove_sphere,0);
|
||||
}
|
||||
break;
|
||||
case MH_TINDER_BREAKER:
|
||||
|
||||
Reference in New Issue
Block a user