Skip to content

Commit

Permalink
Homunculus Fixes
Browse files Browse the repository at this point in the history
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/
  • Loading branch information
tgraskemper committed Nov 11, 2013
1 parent 75af628 commit 4d61cc0
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 19 deletions.
6 changes: 6 additions & 0 deletions conf/battle/homunc.conf
Expand Up @@ -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
11 changes: 6 additions & 5 deletions src/map/battle.c
Expand Up @@ -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 )
Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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
/**
Expand Down
1 change: 1 addition & 0 deletions src/map/battle.h
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/map/clif.c
Expand Up @@ -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.
Expand Down
25 changes: 21 additions & 4 deletions src/map/homunculus.c
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
}
Expand Down
26 changes: 18 additions & 8 deletions src/map/skill.c
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 4d61cc0

Please sign in to comment.