diff --git a/AUTHORS b/AUTHORS index 863ae8379de..6091cd9f5d4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -71,6 +71,7 @@ jaBote jaBote jaBote Jackson +jasonch <31005928+jasonch35@users.noreply.github.com> Jedzkie Jenkijo Jesusaves diff --git a/CHANGELOG.md b/CHANGELOG.md index 253babcfb50..116bff14e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -303,6 +303,19 @@ All these changes only affect Renewal. Pre-renewal is unchanged. - Damage formula changed - Auto Blitz Beat no longer splits the damage among multiple targets +## [v2024.05] `May 2024` + +### Changed + +- Implemented official ATK % calculation for `BS_OVERTHRUST` in pre-renewal. Party members only receive 5% ATK bonus. (#3293) + +### Fixed + +- Fixed a missing initialization of the (m)atk/(m)def modifiers, resulting into 0 or 1 damage. (#3293, related to #3290) +- Fixed an incorrect call of `clif->updatestatus()` to non-player objects in relation to atk/def percent bonuses. (#3294, related to #3290) +- Fixed a failure on SCs from skills that don't have a `StatusChange` entry in their skill db entries after a `@reloadskilldb`, such as the spirit skills. (#3296, issue #3295) +- Fixed a compiler warning due to a missing case label when `SECURE_NPCTIMEOUT` is enabled. (#3297, issue #3197) + ## [v2024.04] `April 2024` ### Added diff --git a/doc/constants_pre-re.md b/doc/constants_pre-re.md index 0ffa1de8c91..1d7a989e4e7 100644 --- a/doc/constants_pre-re.md +++ b/doc/constants_pre-re.md @@ -4880,7 +4880,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202404000 +- `HERCULES_VERSION`: 202405000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/doc/constants_re.md b/doc/constants_re.md index 1df151f05c6..90b7329501b 100644 --- a/doc/constants_re.md +++ b/doc/constants_re.md @@ -4878,7 +4878,7 @@ ### Server defines - `PACKETVER`: 20190530 -- `HERCULES_VERSION`: 202404000 +- `HERCULES_VERSION`: 202405000 - `MAX_LEVEL`: 175 - `MAX_STORAGE`: 600 - `MAX_GUILD_STORAGE`: 500 diff --git a/src/config/core.h b/src/config/core.h index 30e62a20f5f..844549af1e9 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -22,7 +22,7 @@ #define CONFIG_CORE_H /// Hercules version. From tag vYYYY.MM(+PPP) -> YYYYMMPPP -#define HERCULES_VERSION 202404000 +#define HERCULES_VERSION 202405000 /// Max number of items on @autolootid list #define AUTOLOOTITEM_SIZE 10 diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 10528e797e1..e3fc633d86f 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3903,6 +3903,7 @@ ACMD(reloadmobdb) ACMD(reloadskilldb) { skill->reload(); + status->load_sc_type(); homun->reload_skill(); elemental->reload_skilldb(); mercenary->read_skilldb(); diff --git a/src/map/npc.c b/src/map/npc.c index 59501209e0e..0ea39b855f8 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -313,7 +313,8 @@ static int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t dat case NPCT_MENU: timeout = NPC_SECURE_TIMEOUT_MENU; break; - //case NPCT_WAIT: var starts with this value + case NPCT_WAIT: //var starts with this value + break; } if( DIFF_TICK(tick,sd->npc_idle_tick) > (timeout*1000) ) { diff --git a/src/map/status.c b/src/map/status.c index 3a927ecf7ac..8bcb2d5bb94 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -134,22 +134,8 @@ static void initChangeTables(void) memset(status->dbs->ChangeFlagTable, 0, sizeof(status->dbs->ChangeFlagTable)); memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType)); - // Storing the target job rather than simply SC_SOULLINK simplifies code later on. - skill->dbs->db[skill->get_index(SL_ALCHEMIST)].status_type = (sc_type)MAPID_ALCHEMIST; - skill->dbs->db[skill->get_index(SL_MONK)].status_type = (sc_type)MAPID_MONK; - skill->dbs->db[skill->get_index(SL_STAR)].status_type = (sc_type)MAPID_STAR_GLADIATOR; - skill->dbs->db[skill->get_index(SL_SAGE)].status_type = (sc_type)MAPID_SAGE; - skill->dbs->db[skill->get_index(SL_CRUSADER)].status_type = (sc_type)MAPID_CRUSADER; - skill->dbs->db[skill->get_index(SL_SUPERNOVICE)].status_type = (sc_type)MAPID_SUPER_NOVICE; - skill->dbs->db[skill->get_index(SL_KNIGHT)].status_type = (sc_type)MAPID_KNIGHT; - skill->dbs->db[skill->get_index(SL_WIZARD)].status_type = (sc_type)MAPID_WIZARD; - skill->dbs->db[skill->get_index(SL_PRIEST)].status_type = (sc_type)MAPID_PRIEST; - skill->dbs->db[skill->get_index(SL_BARDDANCER)].status_type = (sc_type)MAPID_BARDDANCER; - skill->dbs->db[skill->get_index(SL_ROGUE)].status_type = (sc_type)MAPID_ROGUE; - skill->dbs->db[skill->get_index(SL_ASSASIN)].status_type = (sc_type)MAPID_ASSASSIN; - skill->dbs->db[skill->get_index(SL_BLACKSMITH)].status_type = (sc_type)MAPID_BLACKSMITH; - skill->dbs->db[skill->get_index(SL_HUNTER)].status_type = (sc_type)MAPID_HUNTER; - skill->dbs->db[skill->get_index(SL_SOULLINKER)].status_type = (sc_type)MAPID_SOUL_LINKER; + status->load_sc_type(); + #undef set_sc_with_vfx } @@ -3086,22 +3072,14 @@ static void status_calc_bl_main(struct block_list *bl, e_scb_flag flag) ; } - if ((flag & SCB_ATK_PERC) != 0) { - int prev_atk_percent = st->atk_percent; + if ((flag & SCB_ATK_PERC) != 0) st->atk_percent = status->calc_atk_percent(bl, sc); - if (prev_atk_percent != st->atk_percent) - clif->updatestatus(sd, SP_ATK1); - } if ((flag & SCB_MATK_PERC) != 0) st->matk_percent = status->calc_matk_percent(bl, sc); - if ((flag & SCB_DEF_PERC) != 0) { - int prev_def_percent = st->def_percent; + if ((flag & SCB_DEF_PERC) != 0) st->def_percent = status->calc_def_percent(bl, sc); - if (prev_def_percent != st->def_percent) - clif->updatestatus(sd, SP_DEF2); - } if ((flag & SCB_MDEF_PERC) != 0) { st->mdef_percent = status->calc_mdef_percent(bl, sc); @@ -3509,6 +3487,8 @@ static void status_calc_bl_(struct block_list *bl, e_scb_flag flag, enum e_statu #endif ) clif->updatestatus(sd,SP_ATK1); + else if (bst.atk_percent != st->atk_percent) + clif->updatestatus(sd, SP_ATK1); if(bst.def != st->def) { clif->updatestatus(sd,SP_DEF1); @@ -3529,7 +3509,10 @@ static void status_calc_bl_(struct block_list *bl, e_scb_flag flag, enum e_statu #ifdef RENEWAL clif->updatestatus(sd,SP_DEF1); #endif + } else if (bst.def_percent != st->def_percent) { + clif->updatestatus(sd,SP_DEF2); } + if(bst.flee2 != st->flee2) clif->updatestatus(sd,SP_FLEE2); if(bst.cri != st->cri) @@ -3898,6 +3881,11 @@ static void status_calc_misc(struct block_list *bl, struct status_data *st, int st->mdef2 += st->int_ + (st->vit >> 1); #endif // RENEWAL + st->atk_percent = 100; + st->matk_percent = 100; + st->def_percent = 100; + st->mdef_percent = 100; + if ( bl->type&battle_config.enable_critical ) st->cri += 10 + (st->luk * 10 / 3); // (every 1 luk = +0.33 critical -> 3 luk = +1 critical) else @@ -8413,13 +8401,18 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl val2 = 20*val1; //Power increase break; case SC_OVERTHRUST: - // val2 holds if it was casted on self (1), or is bonus received from others (0) #ifndef RENEWAL - val3 = 5 * val1; //Power increase + if (val2 == 1) // cast on self + val3 = 5 * val1; //Power increase + else // received cast + val3 = 5; #else // owner: 5, 10, 15, 20, 25 // party: 5, 5, 10, 10, 15 - val3 = (val2 == 1 ? (5 * val1) : (5 + (val1 / 2) * 5)); // Power increase + if (val2 == 1) // cast on self + val3 = 5 * val1; // Power increase + else // received cast + val3 = 5 + (val1 / 2) * 5; // Power increase #endif if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) total_tick += total_tick / 10; @@ -14119,6 +14112,26 @@ static void status_check_job_bonus(int idx, const char *name, int class) } } +static void status_load_sc_type(void) +{ + // Storing the target job rather than simply SC_SOULLINK simplifies code later on. + skill->dbs->db[skill->get_index(SL_ALCHEMIST)].status_type = (sc_type)MAPID_ALCHEMIST; + skill->dbs->db[skill->get_index(SL_MONK)].status_type = (sc_type)MAPID_MONK; + skill->dbs->db[skill->get_index(SL_STAR)].status_type = (sc_type)MAPID_STAR_GLADIATOR; + skill->dbs->db[skill->get_index(SL_SAGE)].status_type = (sc_type)MAPID_SAGE; + skill->dbs->db[skill->get_index(SL_CRUSADER)].status_type = (sc_type)MAPID_CRUSADER; + skill->dbs->db[skill->get_index(SL_SUPERNOVICE)].status_type = (sc_type)MAPID_SUPER_NOVICE; + skill->dbs->db[skill->get_index(SL_KNIGHT)].status_type = (sc_type)MAPID_KNIGHT; + skill->dbs->db[skill->get_index(SL_WIZARD)].status_type = (sc_type)MAPID_WIZARD; + skill->dbs->db[skill->get_index(SL_PRIEST)].status_type = (sc_type)MAPID_PRIEST; + skill->dbs->db[skill->get_index(SL_BARDDANCER)].status_type = (sc_type)MAPID_BARDDANCER; + skill->dbs->db[skill->get_index(SL_ROGUE)].status_type = (sc_type)MAPID_ROGUE; + skill->dbs->db[skill->get_index(SL_ASSASIN)].status_type = (sc_type)MAPID_ASSASSIN; + skill->dbs->db[skill->get_index(SL_BLACKSMITH)].status_type = (sc_type)MAPID_BLACKSMITH; + skill->dbs->db[skill->get_index(SL_HUNTER)].status_type = (sc_type)MAPID_HUNTER; + skill->dbs->db[skill->get_index(SL_SOULLINKER)].status_type = (sc_type)MAPID_SOUL_LINKER; +} + static bool status_readdb_job2(char *fields[], int columns, int current) { int idx, class, i; @@ -14885,6 +14898,7 @@ void status_defaults(void) status->change_start_unknown_sc = status_change_start_unknown_sc; status->display_remove = status_display_remove; status->natural_heal = status_natural_heal; + status->load_sc_type = status_load_sc_type; status->natural_heal_timer = status_natural_heal_timer; status->readdb_job2 = status_readdb_job2; status->readdb_sizefix = status_readdb_sizefix; diff --git a/src/map/status.h b/src/map/status.h index c73969b89b4..c1a30ed817c 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1517,6 +1517,7 @@ struct status_interface { void (*display_remove) (struct map_session_data *sd, enum sc_type type); int (*natural_heal) (struct block_list *bl, va_list args); int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data); + void (*load_sc_type) (void); bool (*readdb_job2) (char *fields[], int columns, int current); bool (*readdb_sizefix) (char *fields[], int columns, int current); bool (*read_scdb_libconfig) (void); diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index fabba238090..9f05793b440 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -9296,6 +9296,8 @@ typedef int (*HPMHOOK_pre_status_natural_heal) (struct block_list **bl, va_list typedef int (*HPMHOOK_post_status_natural_heal) (int retVal___, struct block_list *bl, va_list args); typedef int (*HPMHOOK_pre_status_natural_heal_timer) (int *tid, int64 *tick, int *id, intptr_t *data); typedef int (*HPMHOOK_post_status_natural_heal_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data); +typedef void (*HPMHOOK_pre_status_load_sc_type) (void); +typedef void (*HPMHOOK_post_status_load_sc_type) (void); typedef bool (*HPMHOOK_pre_status_readdb_job2) (char **fields[], int *columns, int *current); typedef bool (*HPMHOOK_post_status_readdb_job2) (bool retVal___, char *fields[], int columns, int current); typedef bool (*HPMHOOK_pre_status_readdb_sizefix) (char **fields[], int *columns, int *current); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 9acc5bc795e..eaba4419a28 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -7212,6 +7212,8 @@ struct { struct HPMHookPoint *HP_status_natural_heal_post; struct HPMHookPoint *HP_status_natural_heal_timer_pre; struct HPMHookPoint *HP_status_natural_heal_timer_post; + struct HPMHookPoint *HP_status_load_sc_type_pre; + struct HPMHookPoint *HP_status_load_sc_type_post; struct HPMHookPoint *HP_status_readdb_job2_pre; struct HPMHookPoint *HP_status_readdb_job2_post; struct HPMHookPoint *HP_status_readdb_sizefix_pre; @@ -14787,6 +14789,8 @@ struct { int HP_status_natural_heal_post; int HP_status_natural_heal_timer_pre; int HP_status_natural_heal_timer_post; + int HP_status_load_sc_type_pre; + int HP_status_load_sc_type_post; int HP_status_readdb_job2_pre; int HP_status_readdb_job2_post; int HP_status_readdb_sizefix_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index a33b781115d..b6b47879c22 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -3685,6 +3685,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->display_remove, HP_status_display_remove) }, { HP_POP(status->natural_heal, HP_status_natural_heal) }, { HP_POP(status->natural_heal_timer, HP_status_natural_heal_timer) }, + { HP_POP(status->load_sc_type, HP_status_load_sc_type) }, { HP_POP(status->readdb_job2, HP_status_readdb_job2) }, { HP_POP(status->readdb_sizefix, HP_status_readdb_sizefix) }, { HP_POP(status->read_scdb_libconfig, HP_status_read_scdb_libconfig) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 6357501e44a..9861cbe91e5 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -96405,6 +96405,32 @@ int HP_status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) { } return retVal___; } +void HP_status_load_sc_type(void) { + int hIndex = 0; + if (HPMHooks.count.HP_status_load_sc_type_pre > 0) { + void (*preHookFunc) (void); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_load_sc_type_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_status_load_sc_type_pre[hIndex].func; + preHookFunc(); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.status.load_sc_type(); + } + if (HPMHooks.count.HP_status_load_sc_type_post > 0) { + void (*postHookFunc) (void); + for (hIndex = 0; hIndex < HPMHooks.count.HP_status_load_sc_type_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_status_load_sc_type_post[hIndex].func; + postHookFunc(); + } + } + return; +} bool HP_status_readdb_job2(char *fields[], int columns, int current) { int hIndex = 0; bool retVal___ = false;