Fixed homunculus cooldown and aftercast delays (#8508)

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Daegaladh 2024-07-27 16:07:54 +02:00 committed by GitHub
parent 3cc32b6727
commit 3908b0e9ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 130 additions and 102 deletions

View File

@ -17,10 +17,18 @@
// 0x10: They display luk/3+1 instead of their actual critical in the
// stat window (by default they don't crit)
// 0x20: Their Min-Matk is always the same as their max
// 0x40: Skill re-use delay is reset when they are vaporized.
// 0x80: Skill re-use delay is reset when they are warped (by skill or item) with player.
hom_setting: 0x3D
// Should the cooldown or aftercast delay of homunculi skills be reset when
// the homunculus is vaporized?
// Default on official servers: yes for Pre-renewal, no for Renewal
//hom_delay_reset_vaporize: no
// Should the cooldown or aftercast delay of homunculi skills be reset when
// warping or changing maps?
// Default on official servers: yes for Pre-renewal, no for Renewal
//hom_delay_reset_warp: no
// The rate a homunculus will get friendly by feeding it. (Note 2)
homunculus_friendly_rate: 100

View File

@ -30730,6 +30730,7 @@ Body:
Hit: Single
HitCount: 1
AfterCastActDelay: 2000
AfterCastWalkDelay: 1000
Requires:
SpCost:
- Level: 1
@ -30757,6 +30758,7 @@ Body:
HitCount: 1
SplashArea: -1
AfterCastActDelay: 35000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 40000
@ -30794,6 +30796,14 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay:
- Level: 1
Time: 600000
- Level: 2
Time: 900000
- Level: 3
Time: 1200000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -30801,13 +30811,6 @@ Body:
Time: 180000
- Level: 3
Time: 300000
Duration2:
- Level: 1
Time: 600000
- Level: 2
Time: 900000
- Level: 3
Time: 1200000
Requires:
SpCost: 100
Status: Change
@ -30819,7 +30822,8 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
Duration2: 1000
AfterCastActDelay: 1000
AfterCastWalkDelay: 1000
Requires:
SpCost: 10
- Id: 8006
@ -30831,6 +30835,7 @@ Body:
NoDamage: true
Hit: Single
AfterCastActDelay: 30000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 40000
@ -30869,6 +30874,14 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay:
- Level: 1
Time: 300000
- Level: 2
Time: 600000
- Level: 3
Time: 900000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -30876,13 +30889,6 @@ Body:
Time: 180000
- Level: 3
Time: 300000
Duration2:
- Level: 1
Time: 300000
- Level: 2
Time: 600000
- Level: 3
Time: 900000
Requires:
SpCost: 120
Status: Bloodlust
@ -30905,7 +30911,6 @@ Body:
Count: -2
- Level: 5
Count: -3
AfterCastWalkDelay: 2000
Requires:
SpCost:
- Level: 1
@ -30926,6 +30931,18 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay:
- Level: 1
Time: 60000
- Level: 2
Time: 70000
- Level: 3
Time: 80000
- Level: 4
Time: 90000
- Level: 5
Time: 120000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -30937,17 +30954,6 @@ Body:
Time: 45000
- Level: 5
Time: 40000
Duration2:
- Level: 1
Time: 60000
- Level: 2
Time: 70000
- Level: 3
Time: 80000
- Level: 4
Time: 90000
- Level: 5
Time: 120000
Requires:
SpCost:
- Level: 1
@ -30971,6 +30977,18 @@ Body:
NoDamage: true
Hit: Single
CastCancel: true
AfterCastActDelay:
- Level: 1
Time: 60000
- Level: 2
Time: 70000
- Level: 3
Time: 80000
- Level: 4
Time: 90000
- Level: 5
Time: 120000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -30982,17 +31000,6 @@ Body:
Time: 45000
- Level: 5
Time: 40000
Duration2:
- Level: 1
Time: 60000
- Level: 2
Time: 70000
- Level: 3
Time: 80000
- Level: 4
Time: 90000
- Level: 5
Time: 120000
Requires:
SpCost:
- Level: 1
@ -31015,7 +31022,6 @@ Body:
Range: 15
Hit: Single
HitCount: 1
AfterCastActDelay: 1000
Requires:
SpCost: 1
- Id: 8013
@ -31037,17 +31043,6 @@ Body:
Count: 4
- Level: 5
Count: 5
AfterCastActDelay:
- Level: 1
Time: 2000
- Level: 2
Time: 2200
- Level: 3
Time: 2400
- Level: 4
Time: 2600
- Level: 5
Time: 2800
Requires:
SpCost:
- Level: 1
@ -31068,8 +31063,7 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay: 3000
AfterCastWalkDelay: 3000
AfterCastWalkDelay: 1500
Requires:
SpCost: 40
- Id: 8015
@ -31093,7 +31087,6 @@ Body:
HitCount: 1
Element: Weapon
SplashArea: 4
AfterCastWalkDelay: 1000
Requires:
SpCost: 1
- Id: 8018

View File

@ -43021,7 +43021,8 @@ Body:
Range: 9
Hit: Single
HitCount: 1
AfterCastActDelay: 2000
AfterCastWalkDelay: 1000
Cooldown: 20000
Requires:
SpCost:
- Level: 1
@ -43048,7 +43049,7 @@ Body:
Hit: Single
HitCount: 1
SplashArea: -1
AfterCastActDelay: 35000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 40000
@ -43060,6 +43061,7 @@ Body:
Time: 25000
- Level: 5
Time: 20000
Cooldown: 35000
Requires:
SpCost:
- Level: 1
@ -43086,6 +43088,7 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -43093,7 +43096,7 @@ Body:
Time: 180000
- Level: 3
Time: 300000
Duration2:
Cooldown:
- Level: 1
Time: 600000
- Level: 2
@ -43111,7 +43114,8 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
Duration2: 1000
AfterCastWalkDelay: 1000
Cooldown: 1000
Requires:
SpCost: 10
- Id: 8006
@ -43122,7 +43126,7 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay: 30000
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 40000
@ -43134,6 +43138,7 @@ Body:
Time: 25000
- Level: 5
Time: 20000
Cooldown: 30000
Requires:
SpCost:
- Level: 1
@ -43161,6 +43166,7 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -43168,7 +43174,7 @@ Body:
Time: 180000
- Level: 3
Time: 300000
Duration2:
Cooldown:
- Level: 1
Time: 300000
- Level: 2
@ -43197,7 +43203,7 @@ Body:
Count: -2
- Level: 5
Count: -3
AfterCastWalkDelay: 2000
Cooldown: 2000
Requires:
SpCost:
- Level: 1
@ -43218,6 +43224,7 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -43229,7 +43236,7 @@ Body:
Time: 45000
- Level: 5
Time: 40000
Duration2:
Cooldown:
- Level: 1
Time: 60000
- Level: 2
@ -43263,6 +43270,7 @@ Body:
NoDamage: true
Hit: Single
CastCancel: true
AfterCastWalkDelay: 1000
Duration1:
- Level: 1
Time: 60000
@ -43274,7 +43282,7 @@ Body:
Time: 45000
- Level: 5
Time: 40000
Duration2:
Cooldown:
- Level: 1
Time: 60000
- Level: 2
@ -43307,7 +43315,7 @@ Body:
Range: 15
Hit: Single
HitCount: 1
AfterCastActDelay: 1000
Cooldown: 1000
Requires:
SpCost: 1
- Id: 8013
@ -43329,7 +43337,7 @@ Body:
Count: 4
- Level: 5
Count: 5
AfterCastActDelay:
Cooldown:
- Level: 1
Time: 2000
- Level: 2
@ -43360,8 +43368,8 @@ Body:
DamageFlags:
NoDamage: true
Hit: Single
AfterCastActDelay: 3000
AfterCastWalkDelay: 3000
AfterCastWalkDelay: 1500
Cooldown: 3000
Requires:
SpCost: 40
- Id: 8015
@ -43385,7 +43393,8 @@ Body:
HitCount: 1
Element: Weapon
SplashArea: 4
AfterCastWalkDelay: 1000
AfterCastActDelay: 5000
CoolDown: 1000
Requires:
SpCost: 1
- Id: 8018

View File

@ -11529,6 +11529,13 @@ static const struct _battle_data {
#endif
{ "synchronize_damage", &battle_config.synchronize_damage, 0, 0, 1, },
{ "item_stacking", &battle_config.item_stacking, 1, 0, 1, },
#ifdef RENEWAL
{ "hom_delay_reset_vaporize", &battle_config.hom_delay_reset_vaporize, 0, 0, 1, },
{ "hom_delay_reset_warp", &battle_config.hom_delay_reset_warp, 0, 0, 1, },
#else
{ "hom_delay_reset_vaporize", &battle_config.hom_delay_reset_vaporize, 1, 0, 1, },
{ "hom_delay_reset_warp", &battle_config.hom_delay_reset_warp, 1, 0, 1, },
#endif
#include <custom/battle_config_init.inc>
};

View File

@ -762,6 +762,8 @@ struct Battle_Config
int instance_allow_reconnect;
int synchronize_damage;
int item_stacking;
int hom_delay_reset_vaporize;
int hom_delay_reset_warp;
#include <custom/battle_config_struct.inc>
};

View File

@ -289,7 +289,7 @@ int hom_vaporize(map_session_data *sd, int flag)
//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) {
if (battle_config.hom_delay_reset_vaporize) {
hd->blockskill.clear();
hd->blockskill.shrink_to_fit();
}

View File

@ -168,8 +168,6 @@ enum homun_setting : uint8 {
HOMSET_COPY_SPEED = 0x08, /// Copy their master's speed on spawn/map-change
HOMSET_DISPLAY_LUK = 0x10, /// They display luk/3+1 instead of their actual critical in the stat window, by default they don't crit
HOMSET_SAME_MATK = 0x20, /// Their Min-Matk is always the same as their max
HOMSET_RESET_REUSESKILL_VAPORIZED = 0x40, /// Skill re-use delay is reset when they are vaporized.
HOMSET_RESET_REUSESKILL_TELEPORTED = 0x80, /// Skill re-use delay is reset when they are warped (by skill or item) with player.
};
enum e_homun_grade : uint8 {

View File

@ -7008,6 +7008,11 @@ enum e_setpos pc_setpos(map_session_data* sd, unsigned short mapindex, int x, in
if( hom_is_active(sd->hd) )
{
if (battle_config.hom_delay_reset_warp) {
sd->hd->blockskill.clear();
sd->hd->blockskill.shrink_to_fit();
}
sd->hd->bl.m = m;
sd->hd->bl.x = sd->hd->ud.to_x = x;
sd->hd->bl.y = sd->hd->ud.to_y = y;

View File

@ -1014,8 +1014,10 @@ bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv)
if (sc && !sc->count)
sc = nullptr;
if (util::vector_exists(hd->blockskill, skill_id))
if (util::vector_exists(hd->blockskill, skill_id)) {
clif_skill_fail(*sd, skill_id, USESKILL_FAIL_SKILLINTERVAL);
return true;
}
switch(skill_id) {
case HFLI_SBR44:
@ -1120,9 +1122,16 @@ bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv)
* @return true: Skill cannot be used, false: otherwise
*/
bool skill_isNotOk_mercenary( uint16 skill_id, s_mercenary_data& md ){
if (util::vector_exists(md.blockskill, skill_id))
map_session_data* sd = md.master;
if (sd == nullptr)
return true;
if (util::vector_exists(md.blockskill, skill_id)) {
clif_skill_fail(*sd, skill_id, USESKILL_FAIL_SKILLINTERVAL);
return true;
}
if( md.master != nullptr ){
return skill_isNotOk( skill_id, *md.master );
}else{
@ -7342,8 +7351,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
ret = skill_castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon
if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv))
ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
return ret;
}
break;
@ -9330,10 +9337,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
}
if (sd->hd && battle_config.hom_setting&HOMSET_RESET_REUSESKILL_TELEPORTED) {
sd->hd->blockskill.clear();
sd->hd->blockskill.shrink_to_fit();
}
if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 )
{
@ -10675,11 +10678,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case HAMI_CASTLE: //[orn]
if (src != bl && rnd()%100 < 20 * skill_lv) {
if (src != bl && rnd_chance(20 * skill_lv, 100)) {
int x = src->x, y = src->y;
if (hd)
skill_blockhomun_start(hd,skill_id,skill_get_time2(skill_id,skill_lv));
// Move source
if (unit_movepos(src,bl->x,bl->y,0,0)) {
clif_skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc
@ -10726,8 +10727,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case MH_GOLDENE_FERSE:
clif_skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_time2(skill_id,skill_lv));
break;
case NPC_DRAGONFEAR:
@ -12356,15 +12355,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
for (i = 0; i < ARRAYLENGTH(scs); i++)
if (tsc->getSCE(scs[i])) status_change_end(bl, scs[i]);
}
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
}
break;
case MH_OVERED_BOOST:
if (hd && battle_get_master(src)) {
sc_start(src, battle_get_master(src), type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
}
break;
case MH_GRANITIC_ARMOR:
@ -12373,7 +12369,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
struct block_list *s_bl = battle_get_master(src);
if(s_bl) sc_start2(src, s_bl, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv)); //start on master
sc_start2(src, bl, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv));
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
}
break;
case MH_LIGHT_OF_REGENE: //self
@ -12381,7 +12376,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
struct block_list *s_bl = battle_get_master(src);
if(s_bl) sc_start(src, s_bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
sc_start2(src, src, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv));
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
}
break;
case MH_STYLE_CHANGE:
@ -12407,21 +12401,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif_skill_nodamage(src,master_bl,skill_id,skill_lv,1);
sc_start(src, master_bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
}
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
} break;
case MH_PAIN_KILLER:
bl = battle_get_master(src);
if (bl != nullptr)
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
break;
case MH_MAGMA_FLOW:
sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
break;
case MH_SUMMON_LEGION: {
int summons[5] = {MOBID_S_HORNET, MOBID_S_GIANT_HORNET, MOBID_S_GIANT_HORNET, MOBID_S_LUCIOLA_VESPA, MOBID_S_LUCIOLA_VESPA};
@ -12448,8 +12435,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sc_start4(&sum_md->bl,&sum_md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000);
}
}
if (hd)
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
}
break;
@ -13398,10 +13383,25 @@ TIMER_FUNC(skill_castend_id){
if (!sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id, ud->skill_lv))
ud->canact_tick = i64max(tick + skill_delayfix(src, ud->skill_id, ud->skill_lv), ud->canact_tick - SECURITY_CASTTIME);
if (sd) { //Cooldown application
int cooldown = pc_get_skillcooldown(sd,ud->skill_id, ud->skill_lv); // Increases/Decreases cooldown of a skill by item/card bonuses.
if(cooldown) skill_blockpc_start(sd, ud->skill_id, cooldown);
// Cooldown application
switch (src->type) {
case BL_PC:{
// Increases/Decreases cooldown of a skill by item/card bonuses.
int cooldown = pc_get_skillcooldown(sd, ud->skill_id, ud->skill_lv);
if (cooldown > 0)
skill_blockpc_start(sd, ud->skill_id, cooldown);
} break;
case BL_HOM:{
homun_data& hd = reinterpret_cast<homun_data&>(*src);
#ifdef RENEWAL
skill_blockhomun_start(&hd, ud->skill_id, skill_get_cooldown(ud->skill_id, ud->skill_lv));
#else
skill_blockhomun_start(&hd, ud->skill_id, skill_get_delay(ud->skill_id, ud->skill_lv));
#endif
} break;
}
if( battle_config.display_status_timers && sd )
clif_status_change(src, EFST_POSTDELAY, 1, skill_delayfix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
if( sd )
@ -23069,6 +23069,9 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) //[
hd->blockskill.push_back(skill_id);
if (battle_config.display_status_timers)
clif_skill_cooldown(*hd->master, skill_id, tick);
return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skill_id);
}
@ -23101,6 +23104,9 @@ int skill_blockmerc_start(s_mercenary_data *md, uint16 skill_id, int tick)
md->blockskill.push_back(skill_id);
if (battle_config.display_status_timers)
clif_skill_cooldown(*md->master, skill_id, tick);
return add_timer(gettick() + tick, skill_blockmerc_end, md->bl.id, skill_id);
}
/**