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:
parent
ee5ba2d889
commit
f8cd4aa8c7
@ -877,9 +877,9 @@ Body:
|
||||
.@i = getpetinfo(PETINFO_INTIMATE);
|
||||
|
||||
if (.@i >= PET_INTIMATE_LOYAL) {
|
||||
autobonus "{ bonus2 bSubEle,Ele_Neutral,2; heal 100,0; }",100,5000,BF_SHORT|BF_NORMAL;
|
||||
petautobonus "{ bonus2 bSubEle,Ele_Neutral,2; heal 100,0; }",100,5000,BF_SHORT|BF_NORMAL;
|
||||
} else if (.@i >= PET_INTIMATE_CORDIAL) {
|
||||
autobonus "{ bonus2 bSubEle,Ele_Neutral,2; heal 100,0; }",100,3000,BF_SHORT|BF_NORMAL;
|
||||
petautobonus "{ bonus2 bSubEle,Ele_Neutral,2; heal 100,0; }",100,3000,BF_SHORT|BF_NORMAL;
|
||||
}
|
||||
- Mob: MEDUSA
|
||||
TameItem: Splendid_Mirror
|
||||
@ -1511,15 +1511,15 @@ Body:
|
||||
if (.@i >= PET_INTIMATE_LOYAL) {
|
||||
bonus bCritical,6;
|
||||
bonus bHit,6;
|
||||
autobonus "{ bonus2 bHPRegenRate,500,1000; bonus2 bSPRegenRate,20,1000; }",30,5000,BF_WEAPON|BF_SHORT;
|
||||
petautobonus "{ bonus2 bHPRegenRate,500,1000; bonus2 bSPRegenRate,20,1000; }",30,5000,BF_WEAPON|BF_SHORT;
|
||||
} else if (.@i >= PET_INTIMATE_CORDIAL) {
|
||||
bonus bCritical,5;
|
||||
bonus bHit,5;
|
||||
autobonus "{ bonus2 bHPRegenRate,400,1000; bonus2 bSPRegenRate,10,1000; }",30,5000,BF_WEAPON|BF_SHORT;
|
||||
petautobonus "{ bonus2 bHPRegenRate,400,1000; bonus2 bSPRegenRate,10,1000; }",30,5000,BF_WEAPON|BF_SHORT;
|
||||
} else if (.@i >= PET_INTIMATE_NEUTRAL) {
|
||||
bonus bCritical,4;
|
||||
bonus bHit,4;
|
||||
autobonus "{ bonus2 bHPRegenRate,300,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
petautobonus "{ bonus2 bHPRegenRate,300,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
} else {
|
||||
bonus bCritical,3;
|
||||
bonus bHit,3;
|
||||
@ -1667,11 +1667,11 @@ Body:
|
||||
if (.@i >= PET_INTIMATE_LOYAL) {
|
||||
bonus bCritical,5;
|
||||
bonus bHit,5;
|
||||
autobonus "{ bonus2 bHPRegenRate,400,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
petautobonus "{ bonus2 bHPRegenRate,400,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
} else if (.@i >= PET_INTIMATE_CORDIAL) {
|
||||
bonus bCritical,4;
|
||||
bonus bHit,4;
|
||||
autobonus "{ bonus2 bHPRegenRate,300,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
petautobonus "{ bonus2 bHPRegenRate,300,1000; }",20,5000,BF_WEAPON|BF_SHORT;
|
||||
} else if (.@i >= PET_INTIMATE_NEUTRAL) {
|
||||
bonus bCritical,3;
|
||||
bonus bHit,3;
|
||||
@ -1780,10 +1780,10 @@ Body:
|
||||
|
||||
if (.@i >= PET_INTIMATE_LOYAL) {
|
||||
bonus bMaxSP,150;
|
||||
autobonus "{ bonus2 bSPRegenRate,40,1000; }",30,5000,BF_MAGIC;
|
||||
petautobonus "{ bonus2 bSPRegenRate,40,1000; }",30,5000,BF_MAGIC;
|
||||
} else if (.@i >= PET_INTIMATE_CORDIAL) {
|
||||
bonus bMaxSP,150;
|
||||
autobonus "{ bonus2 bSPRegenRate,30,1000; }",30,5000,BF_MAGIC;
|
||||
petautobonus "{ bonus2 bSPRegenRate,30,1000; }",30,5000,BF_MAGIC;
|
||||
} else if (.@i >= PET_INTIMATE_NEUTRAL) {
|
||||
bonus bMaxSP,100;
|
||||
} else {
|
||||
|
@ -6176,9 +6176,7 @@ kind in 'doc/item_bonus.txt'.
|
||||
*autobonus3 <bonus script>,<rate>,<duration>,<skill id>,{<other script>};
|
||||
*autobonus3 <bonus script>,<rate>,<duration>,"<skill name>",{<other script>};
|
||||
|
||||
These commands are meant to be used in item scripts. They will probably work
|
||||
outside item scripts, but the bonus will not persist for long. They, as
|
||||
expected, refer only to an invoking character.
|
||||
These commands are meant to be used in item scripts only! See 'petautobonus' for pet usage.
|
||||
|
||||
What these commands do is 'attach' a script to the player which will get
|
||||
executed on attack (or when attacked in the case of autobonus2).
|
||||
@ -10313,6 +10311,15 @@ Value of 'rate' is between 1 and 100. 100 = 100%
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*petautobonus <bonus script>,<rate>,<duration>{,<flag>,{<other script>}};
|
||||
*petautobonus2 <bonus script>,<rate>,<duration>{,<flag>,{<other script>}};
|
||||
*petautobonus3 <bonus script>,<rate>,<duration>,<skill id>,{<other script>};
|
||||
*petautobonus3 <bonus script>,<rate>,<duration>,"<skill name>",{<other script>};
|
||||
|
||||
See 'autobonus' for more details.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
===========================
|
||||
|11.- Homunculus commands.|
|
||||
===========================
|
||||
|
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();
|
||||
}
|
||||
|
@ -144,6 +144,42 @@ public:
|
||||
|
||||
extern PetDatabase pet_db;
|
||||
|
||||
TIMER_FUNC(pet_endautobonus);
|
||||
|
||||
/// Pet AutoBonus bonus struct
|
||||
struct s_petautobonus {
|
||||
int16 rate;
|
||||
uint16 atk_type;
|
||||
std::string bonus_script, other_script;
|
||||
t_tick duration;
|
||||
int32 timer;
|
||||
|
||||
~s_petautobonus() {
|
||||
if (this->timer != INVALID_TIMER) {
|
||||
delete_timer(this->timer, pet_endautobonus);
|
||||
this->timer = INVALID_TIMER;
|
||||
}
|
||||
|
||||
this->bonus_script.clear();
|
||||
this->other_script.clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// Pet Autobonus database wrapper
|
||||
struct s_pet_autobonus_wrapper {
|
||||
script_code *script;
|
||||
|
||||
~s_pet_autobonus_wrapper() {
|
||||
if (this->script != nullptr) {
|
||||
script_free_code(this->script);
|
||||
this->script = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern std::unordered_map<std::string, std::shared_ptr<s_pet_autobonus_wrapper>> pet_autobonuses;
|
||||
|
||||
struct pet_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud;
|
||||
@ -165,6 +201,7 @@ struct pet_data {
|
||||
struct pet_skill_attack* a_skill;
|
||||
struct pet_skill_support* s_skill;
|
||||
struct pet_loot* loot;
|
||||
std::vector<std::shared_ptr<s_petautobonus>> autobonus, autobonus2, autobonus3;
|
||||
|
||||
int masterteleport_timer;
|
||||
struct map_session_data *master;
|
||||
@ -220,6 +257,10 @@ void pet_clear_support_bonuses(struct map_session_data *sd);
|
||||
#define pet_stop_walking(pd, type) unit_stop_walking(&(pd)->bl, type)
|
||||
#define pet_stop_attack(pd) unit_stop_attack(&(pd)->bl)
|
||||
|
||||
bool pet_addautobonus(std::vector<std::shared_ptr<s_petautobonus>> &bonus, const std::string &script, int16 rate, uint32 dur, uint16 atk_type, const std::string &other_script, bool onskill);
|
||||
void pet_exeautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_petautobonus>> *bonus, std::shared_ptr<s_petautobonus> &autobonus);
|
||||
void pet_delautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_petautobonus>> &bonus, bool restore);
|
||||
|
||||
void do_init_pet(void);
|
||||
void do_final_pet(void);
|
||||
|
||||
|
@ -4613,6 +4613,27 @@ void script_add_autobonus(const char *autobonus)
|
||||
}
|
||||
}
|
||||
|
||||
void script_run_petautobonus(const std::string &autobonus, map_session_data &sd) {
|
||||
std::shared_ptr<s_pet_autobonus_wrapper> script = util::umap_find(pet_autobonuses, autobonus);
|
||||
|
||||
if (script != nullptr) {
|
||||
run_script(script->script, 0, sd.bl.id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void script_add_petautobonus(const std::string &autobonus) {
|
||||
if (util::umap_find(pet_autobonuses, autobonus) == nullptr) {
|
||||
script_code *script = parse_script(autobonus.c_str(), "petautobonus", 0, 0);
|
||||
|
||||
if (script != nullptr) {
|
||||
std::shared_ptr<s_pet_autobonus_wrapper> bonus = std::make_shared<s_pet_autobonus_wrapper>();
|
||||
|
||||
bonus->script = script;
|
||||
|
||||
pet_autobonuses.emplace(autobonus, bonus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// resets a temporary character array variable to given value
|
||||
void script_cleararray_pc( struct map_session_data* sd, const char* varname ){
|
||||
@ -10065,6 +10086,96 @@ BUILDIN_FUNC(autobonus3)
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(petautobonus) {
|
||||
map_session_data *sd;
|
||||
|
||||
if (!script_rid2sd(sd))
|
||||
return SCRIPT_CMD_FAILURE; // No player attached
|
||||
|
||||
const char *command = script_getfuncname(st);
|
||||
|
||||
if (sd->pd == nullptr) {
|
||||
ShowError("buildin_%s: Requires an active pet.\n", command);
|
||||
return SCRIPT_CMD_FAILURE; // No pet attached to player
|
||||
}
|
||||
|
||||
std::string bonus_script = script_getstr(st, 2);
|
||||
int16 rate = script_getnum(st, 3);
|
||||
uint32 dur = script_getnum(st, 4);
|
||||
|
||||
if (!rate || !dur || bonus_script.empty())
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
|
||||
uint16 atk_type = 0;
|
||||
std::string other_script = {};
|
||||
bool bonus2 = false;
|
||||
|
||||
if (strcmpi(command, "petautobonus2") == 0)
|
||||
bonus2 = true;
|
||||
|
||||
if (script_hasdata(st, 5))
|
||||
atk_type = script_getnum(st, 5);
|
||||
if (script_hasdata(st, 6))
|
||||
other_script = script_getstr(st, 6);
|
||||
|
||||
if (pet_addautobonus(bonus2 ? sd->pd->autobonus2 : sd->pd->autobonus, bonus_script, rate, dur, atk_type, other_script, false)) {
|
||||
script_add_petautobonus(bonus_script);
|
||||
if (!other_script.empty())
|
||||
script_add_petautobonus(other_script);
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(petautobonus3) {
|
||||
map_session_data *sd;
|
||||
|
||||
if (!script_rid2sd(sd))
|
||||
return SCRIPT_CMD_SUCCESS; // No player attached
|
||||
|
||||
if (sd->pd == nullptr) {
|
||||
ShowError("buildin_petautobonus3: Requires an active pet.\n");
|
||||
return SCRIPT_CMD_FAILURE; // No pet attached to player
|
||||
}
|
||||
|
||||
std::string bonus_script = script_getstr(st, 2);
|
||||
int16 rate = script_getnum(st, 3);
|
||||
uint32 dur = script_getnum(st, 4);
|
||||
|
||||
if (!rate || !dur || bonus_script.empty())
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
uint16 skill_id = 0;
|
||||
std::string other_script = {};
|
||||
|
||||
if (script_isstring(st, 5)) {
|
||||
const char *name = script_getstr(st, 5);
|
||||
|
||||
if (!(skill_id = skill_name2id(name))) {
|
||||
ShowError("buildin_petautobonus3: Invalid skill name %s passed to item bonus. Skipping.\n", name);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
} else {
|
||||
skill_id = script_getnum(st, 5);
|
||||
|
||||
if (!skill_get_index(skill_id)) {
|
||||
ShowError("buildin_petautobonus3: Invalid skill ID %d passed to item bonus. Skipping.\n", skill_id);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (script_hasdata(st, 6))
|
||||
other_script = script_getstr(st, 6);
|
||||
|
||||
if (pet_addautobonus(sd->pd->autobonus3, bonus_script, rate, dur, skill_id, other_script, true)) {
|
||||
script_add_petautobonus(bonus_script);
|
||||
if (!other_script.empty())
|
||||
script_add_petautobonus(other_script);
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/// Changes the level of a player skill.
|
||||
/// <flag> defaults to 1
|
||||
/// <flag>=0 : set the level of the skill
|
||||
@ -26578,6 +26689,9 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(autobonus,"sii??"),
|
||||
BUILDIN_DEF(autobonus2,"sii??"),
|
||||
BUILDIN_DEF(autobonus3,"siiv?"),
|
||||
BUILDIN_DEF(petautobonus,"sii??"),
|
||||
BUILDIN_DEF2(petautobonus,"petautobonus2","sii??"),
|
||||
BUILDIN_DEF(petautobonus3,"siiv?"),
|
||||
BUILDIN_DEF(skill,"vi?"),
|
||||
BUILDIN_DEF2(skill,"addtoskill","vi?"), // [Valaris]
|
||||
BUILDIN_DEF(guildskill,"vi"),
|
||||
|
@ -2169,6 +2169,7 @@ void script_free_state(struct script_state* st);
|
||||
struct DBMap* script_get_label_db(void);
|
||||
struct DBMap* script_get_userfunc_db(void);
|
||||
void script_run_autobonus(const char *autobonus, struct map_session_data *sd, unsigned int pos);
|
||||
void script_run_petautobonus(const std::string &autobonus, map_session_data &sd);
|
||||
|
||||
const char* script_get_constant_str(const char* prefix, int64 value);
|
||||
bool script_get_parameter(const char* name, int64* value);
|
||||
|
@ -2360,21 +2360,38 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
}
|
||||
}
|
||||
|
||||
//Autobonus when attacking
|
||||
if( sd && !sd->autobonus.empty() )
|
||||
{
|
||||
for(auto &it : sd->autobonus) {
|
||||
if( it == nullptr ){
|
||||
// Check for player and pet autobonuses when attacking
|
||||
if (sd != nullptr) {
|
||||
// Player
|
||||
if (!sd->autobonus.empty()) {
|
||||
for (auto &it : sd->autobonus) {
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (!(((it->atk_type) & attack_type) & BF_WEAPONMASK &&
|
||||
((it->atk_type) & attack_type) & BF_RANGEMASK &&
|
||||
((it->atk_type) & attack_type) & BF_SKILLMASK))
|
||||
continue; // one or more trigger conditions were not fulfilled
|
||||
|
||||
pc_exeautobonus(*sd, &sd->autobonus, it);
|
||||
}
|
||||
}
|
||||
|
||||
if (rnd()%1000 >= it->rate)
|
||||
// Pet
|
||||
if (sd->pd != nullptr && !sd->pd->autobonus.empty()) {
|
||||
for (auto &it : sd->pd->autobonus) {
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (!(((it->atk_type)&attack_type)&BF_WEAPONMASK &&
|
||||
((it->atk_type)&attack_type)&BF_RANGEMASK &&
|
||||
((it->atk_type)&attack_type)&BF_SKILLMASK))
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (!(((it->atk_type) & attack_type) & BF_WEAPONMASK &&
|
||||
((it->atk_type) & attack_type) & BF_RANGEMASK &&
|
||||
((it->atk_type) & attack_type) & BF_SKILLMASK))
|
||||
continue; // one or more trigger conditions were not fulfilled
|
||||
pc_exeautobonus(*sd, &sd->autobonus, it);
|
||||
|
||||
pet_exeautobonus(*sd, &sd->pd->autobonus, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2461,18 +2478,37 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
|
||||
sd->state.autocast = 0;
|
||||
}
|
||||
|
||||
if( sd && !sd->autobonus3.empty() ) {
|
||||
// Check for player and pet autobonuses when being attacked by skill_id
|
||||
if (sd != nullptr) {
|
||||
// Player
|
||||
if (!sd->autobonus3.empty()) {
|
||||
for (auto &it : sd->autobonus3) {
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (rnd()%1000 >= it->rate)
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (it->atk_type != skill_id)
|
||||
continue;
|
||||
|
||||
pc_exeautobonus(*sd, &sd->autobonus3, it);
|
||||
}
|
||||
}
|
||||
|
||||
// Pet
|
||||
if (sd->pd != nullptr && !sd->pd->autobonus3.empty()) {
|
||||
for (auto &it : sd->pd->autobonus3) {
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (it->atk_type != skill_id)
|
||||
continue;
|
||||
|
||||
pet_exeautobonus(*sd, &sd->pd->autobonus3, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2690,20 +2726,38 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
|
||||
}
|
||||
}
|
||||
|
||||
//Autobonus when attacked
|
||||
if( dstsd && !status_isdead(bl) && !dstsd->autobonus2.empty() && !(skill_id && skill_get_nk(skill_id, NK_NODAMAGE)) ) {
|
||||
// Check for player and pet autobonuses when attacked
|
||||
if (dstsd != nullptr && !status_isdead(bl) && !(skill_id && skill_get_nk(skill_id, NK_NODAMAGE))) {
|
||||
// Player
|
||||
if (!dstsd->autobonus2.empty()) {
|
||||
for (auto &it : dstsd->autobonus2) {
|
||||
if( it == nullptr ){
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (!(((it->atk_type) & attack_type) & BF_WEAPONMASK &&
|
||||
((it->atk_type) & attack_type) & BF_RANGEMASK &&
|
||||
((it->atk_type) & attack_type) & BF_SKILLMASK))
|
||||
continue; // one or more trigger conditions were not fulfilled
|
||||
|
||||
pc_exeautobonus(*dstsd, &dstsd->autobonus2, it);
|
||||
}
|
||||
}
|
||||
|
||||
if (rnd()%1000 >= it->rate)
|
||||
// Pet
|
||||
if (dstsd->pd != nullptr && !dstsd->pd->autobonus2.empty()) {
|
||||
for (auto &it : dstsd->pd->autobonus2) {
|
||||
if (it == nullptr)
|
||||
continue;
|
||||
if (!(((it->atk_type)&attack_type)&BF_WEAPONMASK &&
|
||||
((it->atk_type)&attack_type)&BF_RANGEMASK &&
|
||||
((it->atk_type)&attack_type)&BF_SKILLMASK))
|
||||
if (rnd_value(0, 1000) >= it->rate)
|
||||
continue;
|
||||
if (!(((it->atk_type) & attack_type) & BF_WEAPONMASK &&
|
||||
((it->atk_type) & attack_type) & BF_RANGEMASK &&
|
||||
((it->atk_type) & attack_type) & BF_SKILLMASK))
|
||||
continue; // one or more trigger conditions were not fulfilled
|
||||
pc_exeautobonus(*dstsd, &dstsd->autobonus2, it);
|
||||
|
||||
pet_exeautobonus(*dstsd, &dstsd->pd->autobonus2, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3641,6 +3641,12 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
|
||||
pc_delautobonus(*sd, sd->autobonus2, true);
|
||||
pc_delautobonus(*sd, sd->autobonus3, true);
|
||||
|
||||
if (sd->pd != nullptr) {
|
||||
pet_delautobonus(*sd, sd->pd->autobonus, true);
|
||||
pet_delautobonus(*sd, sd->pd->autobonus2, true);
|
||||
pet_delautobonus(*sd, sd->pd->autobonus3, true);
|
||||
}
|
||||
|
||||
// Parse equipment
|
||||
for (i = 0; i < EQI_MAX; i++) {
|
||||
current_equip_item_index = index = sd->equip_index[i]; // We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
|
||||
|
@ -3464,6 +3464,10 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
struct pet_data *pd = (struct pet_data*)bl;
|
||||
struct map_session_data *sd = pd->master;
|
||||
|
||||
pet_delautobonus(*sd, pd->autobonus, false);
|
||||
pet_delautobonus(*sd, pd->autobonus2, false);
|
||||
pet_delautobonus(*sd, pd->autobonus3, false);
|
||||
|
||||
pet_hungry_timer_delete(pd);
|
||||
pet_clear_support_bonuses(sd);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user