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:
Akinari1087
2013-11-11 05:38:48 -07:00
parent 75af62845b
commit 4d61cc0e14
6 changed files with 54 additions and 19 deletions

View File

@@ -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

View File

@@ -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
/**

View File

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

View File

@@ -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.

View File

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

View File

@@ -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: