|
@@ -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,34 +2849,27 @@ 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 (restore && (sd->state.autobonus&b.pos) == b.pos) {
|
|
|
|
- if (b.bonus_script) {
|
|
|
|
- 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]
|
|
|
|
- for (uint8 j = 0; j < EQI_MAX; j++) {
|
|
|
|
- if (sd->equip_index[j] >= 0)
|
|
|
|
- equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((equip_pos_idx&b.pos) == b.pos)
|
|
|
|
- script_run_autobonus(b.bonus_script, sd, b.pos);
|
|
|
|
- }
|
|
|
|
|
|
+ if( b.active != INVALID_TIMER && restore && b.bonus_script != nullptr ){
|
|
|
|
+ unsigned int equip_pos_idx = 0;
|
|
|
|
|
|
- it++;
|
|
|
|
|
|
+ // Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester]
|
|
|
|
+ for (uint8 j = 0; j < EQI_MAX; j++) {
|
|
|
|
+ if (sd->equip_index[j] >= 0)
|
|
|
|
+ equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip;
|
|
|
|
+ }
|
|
|
|
|
|
- continue;
|
|
|
|
- } else { // Logout / Unequipped an item with an activated bonus
|
|
|
|
- delete_timer(b.active, pc_endautobonus);
|
|
|
|
- b.active = INVALID_TIMER;
|
|
|
|
|
|
+ if( ( equip_pos_idx&b.pos ) == b.pos ){
|
|
|
|
+ script_run_autobonus(b.bonus_script, sd, b.pos);
|
|
|
|
+ }else{
|
|
|
|
+ // Not all required items equipped anymore
|
|
|
|
+ restore = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (b.bonus_script)
|
|
|
|
- aFree(b.bonus_script);
|
|
|
|
- if (b.other_script)
|
|
|
|
- aFree(b.other_script);
|
|
|
|
|
|
+ if( restore ){
|
|
|
|
+ it++;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
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)
|
|
|
|
- sd->state.autobonus &= ~sd->inventory.u.items_inventory[n].equip; //Check for activated autobonus [Inkfish]
|
|
|
|
|
|
+ pc_deleteautobonus( sd->autobonus, sd->inventory.u.items_inventory[n].equip );
|
|
|
|
+ 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))
|