Skip to content

Commit

Permalink
Mercenary, Regen and Frenzy Improvements (#8185)
Browse files Browse the repository at this point in the history
- When a Mercenary gains a bonus, there will now be an animation
- Mercenary bonuses now last for 5 minutes instead of 10 minutes
- Fixed HP/SP recovery values of Mercenaries (and Elementals)
- Mercenaries now recover HP when walking
- Homunculi no longer recover SP when walking
- Mercenary natural recovery interval is 8s for HP and 6s for SP
- Homunculus natural recovery interval is 2s for HP and 4s for SP
- MER_CRASH now only deals 1 hit and can be cast-cancelled
- Frenzy now drains HP every 10 seconds instead of every 15 in pre-renewal
- Fixed SP cost Mercenary Frenzy (100 -> 200 SP)
- Killing monsters exactly 2 times below you base level now still counts as mercenary kill
- Fixes #8184 
- Fixes #7663
  • Loading branch information
Playtester committed Mar 27, 2024
1 parent ed2d03d commit 1a004f0
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 21 deletions.
11 changes: 6 additions & 5 deletions db/pre-re/skill_db.yml
Expand Up @@ -9641,7 +9641,7 @@ Body:
Hit: Single
HitCount: 1
Duration1: 300000
Duration2: 15000
Duration2: 10000
Requires:
SpCost: 200
Status: Berserk
Expand Down Expand Up @@ -32467,9 +32467,9 @@ Body:
Hit: Single
HitCount: 1
Duration1: 300000
Duration2: 15000
Duration2: 10000
Requires:
SpCost: 100
SpCost: 200
Status: Berserk
- Id: 8207
Name: MA_DOUBLE
Expand Down Expand Up @@ -33068,9 +33068,10 @@ Body:
Type: Weapon
TargetType: Attack
Range: 1
Hit: Multi_Hit
HitCount: 3
Hit: Single
HitCount: 1
Element: Weapon
CastCancel: true
CastTime: 1000
AfterCastActDelay: 2000
Duration2: 5000
Expand Down
5 changes: 5 additions & 0 deletions db/pre-re/status.yml
Expand Up @@ -2712,6 +2712,7 @@ Body:
CalcFlags:
Flee: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2720,6 +2721,7 @@ Body:
CalcFlags:
Watk: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2728,6 +2730,7 @@ Body:
CalcFlags:
MaxHp: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2736,6 +2739,7 @@ Body:
CalcFlags:
MaxSp: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2744,6 +2748,7 @@ Body:
CalcFlags:
Hit: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand Down
5 changes: 3 additions & 2 deletions db/re/skill_db.yml
Expand Up @@ -46490,9 +46490,10 @@ Body:
Type: Weapon
TargetType: Attack
Range: 1
Hit: Multi_Hit
HitCount: 3
Hit: Single
HitCount: 1
Element: Weapon
CastCancel: true
CastTime: 1000
AfterCastActDelay: 2000
Duration2: 4500
Expand Down
5 changes: 5 additions & 0 deletions db/re/status.yml
Expand Up @@ -2822,6 +2822,7 @@ Body:
CalcFlags:
Flee: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2830,6 +2831,7 @@ Body:
CalcFlags:
Watk: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2838,6 +2840,7 @@ Body:
CalcFlags:
MaxHp: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2846,6 +2849,7 @@ Body:
CalcFlags:
MaxSp: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand All @@ -2854,6 +2858,7 @@ Body:
CalcFlags:
Hit: true
Flags:
BlEffect: true
NoDispell: true
NoBanishingBuster: true
NoClearance: true
Expand Down
3 changes: 2 additions & 1 deletion src/map/clif.cpp
Expand Up @@ -6579,7 +6579,8 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,

sd = BL_CAST(BL_PC, bl);

if (!(status_efst_get_bl_type((efst_type)type)&bl->type)) // only send status changes that actually matter to the client
// Check if current bl type is in the returned bitmask and only send status changes that actually matter to the client
if (!(status_efst_get_bl_type(static_cast<efst_type>(type)) & bl->type))
return;

clif_status_change_sub(bl, bl->id, type, flag, tick, val1, val2, val3, ((sd ? (pc_isinvisible(sd) ? SELF : AREA) : AREA_WOS)));
Expand Down
2 changes: 1 addition & 1 deletion src/map/mercenary.cpp
Expand Up @@ -421,7 +421,7 @@ bool mercenary_dead(s_mercenary_data *md) {
void mercenary_killbonus(s_mercenary_data *md) {
std::vector<sc_type> scs = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP };

sc_start(&md->bl,&md->bl, util::vector_random(scs), 100, rnd_value(1, 5), 600000);
sc_start(&md->bl,&md->bl, util::vector_random(scs), 100, rnd_value(1, 5), 300000); //Bonus lasts for 5 minutes
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/map/mob.cpp
Expand Up @@ -3109,8 +3109,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
achievement_update_objective(sd, AG_BATTLE, 1, md->mob_id);
}

// The master or Mercenary can increase the kill count
if (sd->md && src && (src->type == BL_PC || src->type == BL_MER) && mob->lv > sd->status.base_level / 2)
// The master or Mercenary can increase the kill count, if the monster level is greater or equal than half the baselevel of the master
if (sd->md && src && (src->type == BL_PC || src->type == BL_MER) && mob->lv >= sd->status.base_level / 2)
mercenary_kills(sd->md);
}

Expand Down
31 changes: 21 additions & 10 deletions src/map/status.cpp
Expand Up @@ -5261,16 +5261,16 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct
regen->sp = cap_value(val, 1, SHRT_MAX);
}
} else if( bl->type == BL_MER ) {
val = (status->max_hp * status->vit / 10000 + 1) * 6;
val = static_cast<decltype(val)>((status->max_hp * status->vit / 10000.0 + 1.0) * 6.0);
regen->hp = cap_value(val, 1, SHRT_MAX);

val = (status->max_sp * (status->int_ + 10) / 750) + 1;
val = static_cast<decltype(val)>((status->max_sp * (status->int_ + 10.0) / 750.0) + 1.0);
regen->sp = cap_value(val, 1, SHRT_MAX);
} else if( bl->type == BL_ELEM ) {
val = (status->max_hp * status->vit / 10000 + 1) * 6;
val = static_cast<decltype(val)>((status->max_hp * status->vit / 10000.0 + 1.0) * 6.0);
regen->hp = cap_value(val, 1, SHRT_MAX);

val = (status->max_sp * (status->int_ + 10) / 750) + 1;
val = static_cast<decltype(val)>((status->max_sp * (status->int_ + 10.0) / 750.0) + 1.0);
regen->sp = cap_value(val, 1, SHRT_MAX);
}
}
Expand Down Expand Up @@ -15237,10 +15237,14 @@ static int status_natural_heal(struct block_list* bl, va_list args)

ud = unit_bl2ud(bl);

if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER) {
if (ud && ud->walktimer != INVALID_TIMER) {
flag &= ~(RGN_SHP|RGN_SSP);
if(!regen->state.walk)
//Mercenaries recover HP even while walking
if(bl->type != BL_MER && !regen->state.walk)
flag &= ~RGN_HP;
//Homunculus don't recover SP while walking
if (bl->type == BL_HOM && !regen->state.walk)
flag &= ~RGN_SP;
}

if (flag&(RGN_HP|RGN_SP)) {
Expand All @@ -15256,11 +15260,15 @@ static int status_natural_heal(struct block_list* bl, va_list args)
if (flag&RGN_HP) {
// Interval to next recovery tick
rate = (int)(battle_config.natural_healhp_interval / (regen->rate.hp/100. * multi));
if (ud && ud->walktimer != INVALID_TIMER)
// Half recovery while moving only applies to players with certain traits
if (sd && ud && ud->walktimer != INVALID_TIMER)
rate *= 2;
// Homun HP regen fix (they should regen as if they were sitting (twice as fast)
// Homun HP regen fix (2 seconds instead of 6 seconds)
if(bl->type == BL_HOM)
rate /= 2;
rate /= 3;
// Mercenary HP regen fix (8 seconds instead of 6 seconds)
if (bl->type == BL_MER)
rate = (rate * 4) / 3;

// Our timer system isn't 100% accurate so make sure we use the closest interval
rate -= NATURAL_HEAL_INTERVAL / 2;
Expand All @@ -15281,9 +15289,12 @@ static int status_natural_heal(struct block_list* bl, va_list args)
if(flag&RGN_SP) {
// Interval to next recovery tick
rate = (int)(battle_config.natural_healsp_interval / (regen->rate.sp/100. * multi));
// Homun SP regen fix (they should regen as if they were sitting (twice as fast)
// Homun SP regen fix (4 seconds instead of 8 seconds)
if(bl->type==BL_HOM)
rate /= 2;
// Mercenary SP regen fix (6 seconds instead of 8 seconds)
if (bl->type == BL_MER)
rate = (rate * 3) / 4;
#ifdef RENEWAL
if (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_MONK &&
sc && sc->getSCE(SC_EXPLOSIONSPIRITS) && (!sc->getSCE(SC_SPIRIT) || sc->getSCE(SC_SPIRIT)->val2 != SL_MONK))
Expand Down

0 comments on commit 1a004f0

Please sign in to comment.