Implements petautobonus script commands (#7053)
* Fixes #7038. * Implements script commands: petautobonus, petautobonus2, and petautobonus3. * This allows pets to utilize the same autobonus features that players can use without having to check for the equipped item position. Thanks to @EditorFc's suggestion and @Lemongrass3110!
This commit is contained in:
111
src/map/pet.cpp
111
src/map/pet.cpp
@@ -31,6 +31,7 @@
|
||||
|
||||
using namespace rathena;
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<s_pet_autobonus_wrapper>> pet_autobonuses;
|
||||
const t_tick MIN_PETTHINKTIME = 100;
|
||||
|
||||
const std::string PetDatabase::getDefaultLocation(){
|
||||
@@ -2332,6 +2333,113 @@ void pet_evolution(struct map_session_data *sd, int16 pet_id) {
|
||||
clif_inventorylist(sd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add petautobonus to player when attacking/attacked.
|
||||
* @param bonus: Bonus
|
||||
* @param script: Script to execute
|
||||
* @param rate: Success chance
|
||||
* @param dur: Duration
|
||||
* @param flag: Battle flag/skill
|
||||
* @param other_script: Secondary script to execute
|
||||
* @param onskill: Skill used to trigger autobonus
|
||||
* @return True on success or false otherwise
|
||||
*/
|
||||
bool pet_addautobonus(std::vector<std::shared_ptr<s_petautobonus>> &bonus, const std::string &script, int16 rate, uint32 dur, uint16 flag, const std::string &other_script, bool onskill) {
|
||||
if (bonus.size() == MAX_PC_BONUS) {
|
||||
ShowWarning("pet_addautobonus: Reached max (%d) number of petautobonus per pet!\n", MAX_PC_BONUS);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!onskill) {
|
||||
if (!(flag & BF_RANGEMASK))
|
||||
flag |= BF_SHORT | BF_LONG; //No range defined? Use both.
|
||||
if (!(flag & BF_WEAPONMASK))
|
||||
flag |= BF_WEAPON; //No attack type defined? Use weapon.
|
||||
if (!(flag & BF_SKILLMASK)) {
|
||||
if (flag & (BF_MAGIC | BF_MISC))
|
||||
flag |= BF_SKILL; //These two would never trigger without BF_SKILL
|
||||
if (flag & BF_WEAPON)
|
||||
flag |= BF_NORMAL | BF_SKILL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (rate < -10000 || rate > 10000)
|
||||
ShowWarning("pet_addautobonus: Bonus rate %d exceeds -10000~10000 range, capping.\n", rate);
|
||||
|
||||
std::shared_ptr<s_petautobonus> entry = std::make_shared<s_petautobonus>();
|
||||
|
||||
entry->rate = cap_value(rate, -10000, 10000);
|
||||
entry->duration = dur;
|
||||
entry->timer = INVALID_TIMER;
|
||||
entry->atk_type = flag;
|
||||
entry->bonus_script = script;
|
||||
entry->other_script = other_script;
|
||||
|
||||
bonus.push_back(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a petautobonus from player.
|
||||
* @param sd: Player data
|
||||
* @param bonus: Autobonus
|
||||
* @param restore: Run script on clearing or not
|
||||
*/
|
||||
void pet_delautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_petautobonus>> &bonus, bool restore) {
|
||||
std::vector<std::shared_ptr<s_petautobonus>>::iterator it = bonus.begin();
|
||||
|
||||
while (it != bonus.end()) {
|
||||
std::shared_ptr<s_petautobonus> b = *it;
|
||||
|
||||
if (b->timer != INVALID_TIMER && !b->bonus_script.empty() && restore) {
|
||||
script_run_petautobonus(b->bonus_script, sd);
|
||||
|
||||
it = bonus.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute petautobonus on player.
|
||||
* @param sd: Player data
|
||||
* @param bonus: Bonus vector
|
||||
* @param autobonus: Autobonus to run
|
||||
*/
|
||||
void pet_exeautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_petautobonus>> *bonus, std::shared_ptr<s_petautobonus> &autobonus) {
|
||||
if (autobonus->timer != INVALID_TIMER)
|
||||
delete_timer(autobonus->timer, pet_endautobonus);
|
||||
|
||||
if (!autobonus->other_script.empty()) {
|
||||
script_run_petautobonus(autobonus->other_script, sd);
|
||||
}
|
||||
|
||||
autobonus->timer = add_timer(gettick() + autobonus->duration, pet_endautobonus, sd.bl.id, (intptr_t)&bonus);
|
||||
status_calc_pc(&sd, SCO_FORCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove petautobonus timer from player.
|
||||
*/
|
||||
TIMER_FUNC(pet_endautobonus) {
|
||||
map_session_data *sd = map_id2sd(id);
|
||||
std::vector<std::shared_ptr<s_petautobonus>> *bonus = (std::vector<std::shared_ptr<s_petautobonus>> *)data;
|
||||
|
||||
nullpo_ret(sd);
|
||||
nullpo_ret(bonus);
|
||||
|
||||
for (std::shared_ptr<s_petautobonus> autobonus : *bonus) {
|
||||
if (autobonus->timer == tid) {
|
||||
autobonus->timer = INVALID_TIMER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status_calc_pc(sd, SCO_FORCE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize pet data.
|
||||
*/
|
||||
@@ -2349,6 +2457,7 @@ void do_init_pet(void)
|
||||
add_timer_func_list(pet_skill_support_timer, "pet_skill_support_timer"); // [Skotlex]
|
||||
add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris]
|
||||
add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris]
|
||||
add_timer_func_list(pet_endautobonus, "pet_endautobonus");
|
||||
add_timer_interval(gettick()+MIN_PETTHINKTIME,pet_ai_hard,0,0,MIN_PETTHINKTIME);
|
||||
}
|
||||
|
||||
@@ -2360,5 +2469,7 @@ void do_final_pet(void)
|
||||
ers_destroy(item_drop_ers);
|
||||
ers_destroy(item_drop_list_ers);
|
||||
|
||||
pet_autobonuses.clear();
|
||||
|
||||
pet_db.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user