Fixed autobonus on the same equip slot (#6257)
Fixes #2079 Thanks to @LunarSHINING for reporting and testing Thanks to @Tokeiburu for the initial report Thanks to @Atemo and @aleos89 for reviewing
This commit is contained in:
parent
54c2689bbd
commit
df7cccaa56
@ -2760,6 +2760,23 @@ static void pc_bonus_item_drop(std::vector<s_add_drop> &drop, t_itemid nameid, u
|
|||||||
drop.push_back(entry);
|
drop.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_autobonus::~s_autobonus(){
|
||||||
|
if( this->active != INVALID_TIMER ){
|
||||||
|
delete_timer( this->active, pc_endautobonus );
|
||||||
|
this->active = INVALID_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->bonus_script != nullptr ){
|
||||||
|
aFree( this->bonus_script );
|
||||||
|
this->bonus_script = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->other_script != nullptr ){
|
||||||
|
aFree( this->other_script );
|
||||||
|
this->other_script = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add autobonus to player when attacking/attacked
|
* Add autobonus to player when attacking/attacked
|
||||||
* @param bonus: Bonus array
|
* @param bonus: Bonus array
|
||||||
@ -2772,8 +2789,15 @@ static void pc_bonus_item_drop(std::vector<s_add_drop> &drop, t_itemid nameid, u
|
|||||||
* @param onskill: Skill used to trigger autobonus
|
* @param onskill: Skill used to trigger autobonus
|
||||||
* @return True on success or false otherwise
|
* @return True on success or false otherwise
|
||||||
*/
|
*/
|
||||||
bool pc_addautobonus(std::vector<s_autobonus> &bonus, const char *script, short rate, unsigned int dur, uint16 flag, const char *other_script, unsigned int pos, bool onskill)
|
bool pc_addautobonus(std::vector<s_autobonus> &bonus, const char *script, short rate, unsigned int dur, uint16 flag, const char *other_script, unsigned int pos, bool onskill){
|
||||||
{
|
// Check if the same bonus already exists
|
||||||
|
for( s_autobonus& autobonus : bonus ){
|
||||||
|
// Compare based on position and bonus script
|
||||||
|
if( autobonus.pos == pos && strcmp( script, autobonus.bonus_script ) == 0 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bonus.size() == MAX_PC_BONUS) {
|
if (bonus.size() == MAX_PC_BONUS) {
|
||||||
ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", MAX_PC_BONUS);
|
ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", MAX_PC_BONUS);
|
||||||
return false;
|
return false;
|
||||||
@ -2825,9 +2849,7 @@ void pc_delautobonus(struct map_session_data* sd, std::vector<s_autobonus> &bonu
|
|||||||
while( it != bonus.end() ){
|
while( it != bonus.end() ){
|
||||||
s_autobonus b = *it;
|
s_autobonus b = *it;
|
||||||
|
|
||||||
if (b.active != INVALID_TIMER) {
|
if( b.active != INVALID_TIMER && restore && b.bonus_script != nullptr ){
|
||||||
if (restore && (sd->state.autobonus&b.pos) == b.pos) {
|
|
||||||
if (b.bonus_script) {
|
|
||||||
unsigned int equip_pos_idx = 0;
|
unsigned int equip_pos_idx = 0;
|
||||||
|
|
||||||
// Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester]
|
// Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester]
|
||||||
@ -2836,23 +2858,18 @@ void pc_delautobonus(struct map_session_data* sd, std::vector<s_autobonus> &bonu
|
|||||||
equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip;
|
equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((equip_pos_idx&b.pos) == b.pos)
|
if( ( equip_pos_idx&b.pos ) == b.pos ){
|
||||||
script_run_autobonus(b.bonus_script, sd, b.pos);
|
script_run_autobonus(b.bonus_script, sd, b.pos);
|
||||||
|
}else{
|
||||||
|
// Not all required items equipped anymore
|
||||||
|
restore = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( restore ){
|
||||||
it++;
|
it++;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else { // Logout / Unequipped an item with an activated bonus
|
|
||||||
delete_timer(b.active, pc_endautobonus);
|
|
||||||
b.active = INVALID_TIMER;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (b.bonus_script)
|
|
||||||
aFree(b.bonus_script);
|
|
||||||
if (b.other_script)
|
|
||||||
aFree(b.other_script);
|
|
||||||
|
|
||||||
it = bonus.erase(it);
|
it = bonus.erase(it);
|
||||||
}
|
}
|
||||||
@ -2885,7 +2902,6 @@ void pc_exeautobonus(struct map_session_data *sd, std::vector<s_autobonus> *bonu
|
|||||||
}
|
}
|
||||||
|
|
||||||
autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)bonus);
|
autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)bonus);
|
||||||
sd->state.autobonus |= autobonus->pos;
|
|
||||||
status_calc_pc(sd,SCO_FORCE);
|
status_calc_pc(sd,SCO_FORCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2902,7 +2918,6 @@ TIMER_FUNC(pc_endautobonus){
|
|||||||
for( struct s_autobonus& autobonus : *bonus ){
|
for( struct s_autobonus& autobonus : *bonus ){
|
||||||
if( autobonus.active == tid ){
|
if( autobonus.active == tid ){
|
||||||
autobonus.active = INVALID_TIMER;
|
autobonus.active = INVALID_TIMER;
|
||||||
sd->state.autobonus &= ~autobonus.pos;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10785,6 +10800,21 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos,bool equipswit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_deleteautobonus( std::vector<s_autobonus>& bonus, int position ){
|
||||||
|
std::vector<s_autobonus>::iterator it = bonus.begin();
|
||||||
|
|
||||||
|
while( it != bonus.end() ){
|
||||||
|
s_autobonus b = *it;
|
||||||
|
|
||||||
|
if( ( b.pos & position ) != b.pos ){
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = bonus.erase( it );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculate player status on unequip
|
* Recalculate player status on unequip
|
||||||
* @param sd: Player data
|
* @param sd: Player data
|
||||||
@ -10796,8 +10826,9 @@ static void pc_unequipitem_sub(struct map_session_data *sd, int n, int flag) {
|
|||||||
int i, iflag;
|
int i, iflag;
|
||||||
bool status_calc = false;
|
bool status_calc = false;
|
||||||
|
|
||||||
if (sd->state.autobonus&sd->inventory.u.items_inventory[n].equip)
|
pc_deleteautobonus( sd->autobonus, sd->inventory.u.items_inventory[n].equip );
|
||||||
sd->state.autobonus &= ~sd->inventory.u.items_inventory[n].equip; //Check for activated autobonus [Inkfish]
|
pc_deleteautobonus( sd->autobonus2, sd->inventory.u.items_inventory[n].equip );
|
||||||
|
pc_deleteautobonus( sd->autobonus3, sd->inventory.u.items_inventory[n].equip );
|
||||||
|
|
||||||
sd->inventory.u.items_inventory[n].equip = 0;
|
sd->inventory.u.items_inventory[n].equip = 0;
|
||||||
if (!(flag & 4))
|
if (!(flag & 4))
|
||||||
|
@ -240,6 +240,8 @@ struct s_autobonus {
|
|||||||
char *bonus_script, *other_script;
|
char *bonus_script, *other_script;
|
||||||
int active;
|
int active;
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
|
|
||||||
|
~s_autobonus();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Timed bonus 'bonus_script' struct [Cydh]
|
/// Timed bonus 'bonus_script' struct [Cydh]
|
||||||
@ -323,7 +325,6 @@ struct map_session_data {
|
|||||||
t_itemid autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
|
t_itemid autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
|
||||||
unsigned short autoloottype;
|
unsigned short autoloottype;
|
||||||
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
|
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
|
||||||
unsigned int autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
|
|
||||||
unsigned int gmaster_flag : 1;
|
unsigned int gmaster_flag : 1;
|
||||||
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
|
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
|
||||||
unsigned int warping : 1;//states whether you're in the middle of a warp processing
|
unsigned int warping : 1;//states whether you're in the middle of a warp processing
|
||||||
|
@ -9636,9 +9636,6 @@ BUILDIN_FUNC(autobonus)
|
|||||||
else
|
else
|
||||||
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
||||||
|
|
||||||
if((sd->state.autobonus&pos) == pos)
|
|
||||||
return SCRIPT_CMD_SUCCESS;
|
|
||||||
|
|
||||||
rate = script_getnum(st,3);
|
rate = script_getnum(st,3);
|
||||||
dur = script_getnum(st,4);
|
dur = script_getnum(st,4);
|
||||||
bonus_script = script_getstr(st,2);
|
bonus_script = script_getstr(st,2);
|
||||||
@ -9676,9 +9673,6 @@ BUILDIN_FUNC(autobonus2)
|
|||||||
else
|
else
|
||||||
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
||||||
|
|
||||||
if((sd->state.autobonus&pos) == pos)
|
|
||||||
return SCRIPT_CMD_SUCCESS;
|
|
||||||
|
|
||||||
rate = script_getnum(st,3);
|
rate = script_getnum(st,3);
|
||||||
dur = script_getnum(st,4);
|
dur = script_getnum(st,4);
|
||||||
bonus_script = script_getstr(st,2);
|
bonus_script = script_getstr(st,2);
|
||||||
@ -9716,9 +9710,6 @@ BUILDIN_FUNC(autobonus3)
|
|||||||
else
|
else
|
||||||
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
pos = sd->inventory.u.items_inventory[current_equip_item_index].equip;
|
||||||
|
|
||||||
if((sd->state.autobonus&pos) == pos)
|
|
||||||
return SCRIPT_CMD_SUCCESS;
|
|
||||||
|
|
||||||
rate = script_getnum(st,3);
|
rate = script_getnum(st,3);
|
||||||
dur = script_getnum(st,4);
|
dur = script_getnum(st,4);
|
||||||
if (script_isstring(st, 5)) {
|
if (script_isstring(st, 5)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user