Compare commits

...

7 Commits

Author SHA1 Message Date
Aleos
03dfba0dd8
Update src/map/pc.cpp
Co-authored-by: munkrej <schmunk@posteo.de>
2023-03-28 08:10:36 -04:00
Aleos
c8e44d2b68
Merge branch 'master' into hotfix/issue7111 2023-03-28 08:09:59 -04:00
Aleos
1c02e5b253
Merge branch 'master' into hotfix/issue7111 2022-12-09 14:54:30 -05:00
aleos
b9aa1344e6 Fixes autobonuses not clearing on unequip 2022-12-07 10:31:31 -05:00
aleos
bb8d09dfca Fixes an issue with reloading the item database
* Fixes an issue where players prior autobonuses were not properly recalculated when reloading the item database.
2022-08-25 11:31:20 -04:00
aleos
920b57965c Resolves an issue with random crashes
* Reverts the order of combos after parsing of equipment.
* Moves the equipment bonuses to the very end of all equipment, combo, card, and random option parsing.
2022-08-02 13:26:42 -04:00
aleos
658d64abba Fixes some item bonuses not applying from combos
* Fixes #7111.
* Resolves an issue where combo items were not properly giving their bonuses if it applied to worn equipment.
Thanks to @Badarosk0!
2022-07-18 13:18:32 -04:00
4 changed files with 118 additions and 92 deletions

View File

@ -4761,7 +4761,7 @@ void itemdb_reload(void) {
pc_setinventorydata(sd); pc_setinventorydata(sd);
pc_check_available_item(sd, ITMCHK_ALL); // Check for invalid(ated) items. pc_check_available_item(sd, ITMCHK_ALL); // Check for invalid(ated) items.
pc_load_combo(sd); // Check to see if new combos are available pc_load_combo(sd); // Check to see if new combos are available
status_calc_pc(sd, SCO_FORCE); // status_calc_pc(sd, SCO_FORCE|SCO_ITEM_RELOAD); //
} }
mapit_free(iter); mapit_free(iter);
} }

View File

@ -3388,6 +3388,10 @@ void pc_delautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_autobon
// Not all required items equipped anymore // Not all required items equipped anymore
restore = false; restore = false;
} }
} else {
// Not all required items equipped anymore
it = bonus.erase(it);
continue;
} }
if( restore ){ if( restore ){

View File

@ -3732,9 +3732,9 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
memset(&sd->bonus, 0, sizeof(sd->bonus)); memset(&sd->bonus, 0, sizeof(sd->bonus));
// Autobonus // Autobonus
pc_delautobonus(*sd, sd->autobonus, true); pc_delautobonus(*sd, sd->autobonus, (opt & SCO_ITEM_RELOAD) ? false : true);
pc_delautobonus(*sd, sd->autobonus2, true); pc_delautobonus(*sd, sd->autobonus2, (opt & SCO_ITEM_RELOAD) ? false : true);
pc_delautobonus(*sd, sd->autobonus3, true); pc_delautobonus(*sd, sd->autobonus3, (opt & SCO_ITEM_RELOAD) ? false : true);
if (sd->pd != nullptr) { if (sd->pd != nullptr) {
pet_delautobonus(*sd, sd->pd->autobonus, true); pet_delautobonus(*sd, sd->pd->autobonus, true);
@ -3755,8 +3755,6 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
if (!sd->inventory_data[index]) if (!sd->inventory_data[index])
continue; continue;
base_status->def += sd->inventory_data[index]->def;
// Items may be equipped, their effects however are nullified. // Items may be equipped, their effects however are nullified.
if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT)
|| !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { // Execute equip-script on login || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { // Execute equip-script on login
@ -3765,71 +3763,9 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
return 1; return 1;
} }
// Sanitize the refine level in case someone decreased the value inbetween
if (sd->inventory.u.items_inventory[index].refine > MAX_REFINE)
sd->inventory.u.items_inventory[index].refine = MAX_REFINE;
std::shared_ptr<s_refine_level_info> info = refine_db.findCurrentLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
#ifdef RENEWAL
std::shared_ptr<s_enchantgradelevel> enchantgrade_info = nullptr;
if( sd->inventory.u.items_inventory[index].enchantgrade > 0 ){
enchantgrade_info = enchantgrade_db.findCurrentLevelInfo( *sd->inventory_data[index], sd->inventory.u.items_inventory[index] );
}
#endif
if (sd->inventory_data[index]->type == IT_WEAPON) { if (sd->inventory_data[index]->type == IT_WEAPON) {
int wlv = sd->inventory_data[index]->weapon_level;
struct weapon_data *wd;
struct weapon_atk *wa;
if(wlv >= MAX_WEAPON_LEVEL)
wlv = MAX_WEAPON_LEVEL;
if(i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) {
wd = &sd->left_weapon; // Left-hand weapon
wa = &base_status->lhw;
} else {
wd = &sd->right_weapon;
wa = &base_status->rhw;
}
wa->atk += sd->inventory_data[index]->atk;
if( info != nullptr ){
wa->atk2 += info->bonus / 100;
#ifdef RENEWAL
if( enchantgrade_info != nullptr ){
wa->atk2 += ( ( ( info->bonus / 100 ) * enchantgrade_info->bonus ) / 100 );
}
if( wlv == 5 ){
base_status->patk += sd->inventory.u.items_inventory[index].refine * 2;
base_status->smatk += sd->inventory.u.items_inventory[index].refine * 2;
}
#endif
}
#ifdef RENEWAL
if (sd->bonus.weapon_atk_rate)
wa->atk += wa->atk * sd->bonus.weapon_atk_rate / 100;
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = wlv;
// Renewal magic attack refine bonus
if( info != nullptr && sd->weapontype1 != W_BOW ){
wa->matk += info->bonus / 100;
if( enchantgrade_info != nullptr ){
wa->matk += ( ( ( info->bonus / 100 ) * enchantgrade_info->bonus ) / 100 );
}
}
#endif
// Overrefine bonus.
if( info != nullptr ){
wd->overrefine = info->randombonus_max / 100;
}
wa->range += sd->inventory_data[index]->range;
if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
if (wd == &sd->left_weapon) { if (i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) {
sd->state.lr_flag = 1; sd->state.lr_flag = 1;
run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
sd->state.lr_flag = 0; sd->state.lr_flag = 0;
@ -3838,30 +3774,7 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
if (!calculating) // Abort, run_script retriggered this. [Skotlex] if (!calculating) // Abort, run_script retriggered this. [Skotlex]
return 1; return 1;
} }
#ifdef RENEWAL
if (sd->bonus.weapon_matk_rate)
wa->matk += wa->matk * sd->bonus.weapon_matk_rate / 100;
#endif
if(sd->inventory.u.items_inventory[index].card[0] == CARD0_FORGE) { // Forged weapon
wd->star += (sd->inventory.u.items_inventory[index].card[1]>>8);
if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
if(pc_famerank(MakeDWord(sd->inventory.u.items_inventory[index].card[2],sd->inventory.u.items_inventory[index].card[3]) ,MAPID_BLACKSMITH))
wd->star += 10;
if (!wa->ele) // Do not overwrite element from previous bonuses.
wa->ele = (sd->inventory.u.items_inventory[index].card[1]&0x0f);
}
} else if(sd->inventory_data[index]->type == IT_ARMOR) { } else if(sd->inventory_data[index]->type == IT_ARMOR) {
if( info != nullptr ){
refinedef += info->bonus;
#ifdef RENEWAL
if( sd->inventory_data[index]->armor_level == 2 ){
base_status->res += sd->inventory.u.items_inventory[index].refine * 2;
base_status->mres += sd->inventory.u.items_inventory[index].refine * 2;
}
#endif
}
if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
if( i == EQI_HAND_L ) // Shield if( i == EQI_HAND_L ) // Shield
sd->state.lr_flag = 3; sd->state.lr_flag = 3;
@ -4026,6 +3939,114 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
current_equip_opt_index = -1; current_equip_opt_index = -1;
} }
// Give equipment bonuses based on all parsed information.
for (i = 0; i < EQI_MAX; i++) {
index = sd->equip_index[i];
if (index < 0)
continue;
if (i == EQI_AMMO)
continue;
if (pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index))
continue;
if (!sd->inventory_data[index])
continue;
base_status->def += sd->inventory_data[index]->def;
// Sanitize the refine level in case someone decreased the value inbetween
if (sd->inventory.u.items_inventory[index].refine > MAX_REFINE)
sd->inventory.u.items_inventory[index].refine = MAX_REFINE;
std::shared_ptr<s_refine_level_info> info = refine_db.findCurrentLevelInfo(*sd->inventory_data[index], sd->inventory.u.items_inventory[index]);
#ifdef RENEWAL
std::shared_ptr<s_enchantgradelevel> enchantgrade_info = nullptr;
if (sd->inventory.u.items_inventory[index].enchantgrade > 0)
enchantgrade_info = enchantgrade_db.findCurrentLevelInfo(*sd->inventory_data[index], sd->inventory.u.items_inventory[index]);
#endif
if (sd->inventory_data[index]->type == IT_WEAPON) {
uint16 wlv = sd->inventory_data[index]->weapon_level;
weapon_data *wd;
weapon_atk *wa;
if (wlv >= MAX_WEAPON_LEVEL)
wlv = MAX_WEAPON_LEVEL;
if (i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) {
wd = &sd->left_weapon; // Left-hand weapon
wa = &base_status->lhw;
} else {
wd = &sd->right_weapon;
wa = &base_status->rhw;
}
wa->atk += sd->inventory_data[index]->atk;
if (info != nullptr) {
wa->atk2 += info->bonus / 100;
#ifdef RENEWAL
if (enchantgrade_info != nullptr)
wa->atk2 += (((info->bonus / 100) * enchantgrade_info->bonus) / 100);
if (wlv == 5) {
base_status->patk += sd->inventory.u.items_inventory[index].refine * 2;
base_status->smatk += sd->inventory.u.items_inventory[index].refine * 2;
}
#endif
}
#ifdef RENEWAL
if (sd->bonus.weapon_atk_rate)
wa->atk += wa->atk * sd->bonus.weapon_atk_rate / 100;
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = static_cast<uint8>(wlv);
// Renewal magic attack refine bonus
if (info != nullptr && sd->weapontype1 != W_BOW) {
wa->matk += info->bonus / 100;
if (enchantgrade_info != nullptr)
wa->matk += (((info->bonus / 100) * enchantgrade_info->bonus) / 100);
}
#endif
// Overrefine bonus.
if (info != nullptr)
wd->overrefine = info->randombonus_max / 100;
wa->range += sd->inventory_data[index]->range;
#ifdef RENEWAL
if (sd->bonus.weapon_matk_rate)
wa->matk += wa->matk * sd->bonus.weapon_matk_rate / 100;
#endif
if (sd->inventory.u.items_inventory[index].card[0] == CARD0_FORGE) { // Forged weapon
wd->star += (sd->inventory.u.items_inventory[index].card[1] >> 8);
if (wd->star >= 15)
wd->star = 40; // 3 Star Crumbs now give +40 dmg
if (pc_famerank(MakeDWord(sd->inventory.u.items_inventory[index].card[2], sd->inventory.u.items_inventory[index].card[3]), MAPID_BLACKSMITH))
wd->star += 10;
if (!wa->ele) // Do not overwrite element from previous bonuses.
wa->ele = (sd->inventory.u.items_inventory[index].card[1] & 0x0f);
}
} else if (sd->inventory_data[index]->type == IT_ARMOR) {
if (info != nullptr) {
refinedef += info->bonus;
#ifdef RENEWAL
if (sd->inventory_data[index]->armor_level == 2) {
base_status->res += sd->inventory.u.items_inventory[index].refine * 2;
base_status->mres += sd->inventory.u.items_inventory[index].refine * 2;
}
#endif
}
}
}
if (sc->count && sc->getSCE(SC_ITEMSCRIPT)) { if (sc->count && sc->getSCE(SC_ITEMSCRIPT)) {
std::shared_ptr<item_data> data = item_db.find(sc->getSCE(SC_ITEMSCRIPT)->val1); std::shared_ptr<item_data> data = item_db.find(sc->getSCE(SC_ITEMSCRIPT)->val1);

View File

@ -2923,6 +2923,7 @@ enum e_status_calc_opt : uint8 {
SCO_NONE = 0x0, SCO_NONE = 0x0,
SCO_FIRST = 0x1, ///< Trigger the calculations that should take place only onspawn/once, process base status initialization code SCO_FIRST = 0x1, ///< Trigger the calculations that should take place only onspawn/once, process base status initialization code
SCO_FORCE = 0x2, ///< Only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage SCO_FORCE = 0x2, ///< Only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage
SCO_ITEM_RELOAD = 0x4, ///< Triggered when the item database is reloaded to force autobonus types to reset
}; };
/// Flags for status_change_start and status_get_sc_def /// Flags for status_change_start and status_get_sc_def