mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
Added HealRotation HOT methodology (Heal Override Target) and load/save/delete capabilities
This commit is contained in:
parent
e75a53b775
commit
6e11128cbc
@ -1,5 +1,9 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 04/08/2016 ==
|
||||
Uleat: Added Heal Rotation HOTs (Heal Override Targets) that can be set for proactive healing (default HR behavior is reactive)
|
||||
Uleat: Added the ability to save/load/delete Heal Rotations based on targeted member - load is automatic when ^hrcreate is used on a bot that has a saved HR entry
|
||||
|
||||
== 04/07/2016 ==
|
||||
Uleat: Rework of eq_dictionary to facilitate inventory work
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9096
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9003
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9005
|
||||
#else
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||
#endif
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
9001|2016_03_24_bots_command_settings.sql|SHOW TABLES LIKE 'bot_command_settings'|empty|
|
||||
9002|2016_03_24_bots_command_rules.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CommandSpellRank'|empty|
|
||||
9003|2016_04_05_bots_pet_spell_id_field.sql|SHOW COLUMNS FROM `bot_pets` LIKE 'pet_id'|not_empty|
|
||||
9004|2016_04_07_bots_heal_override_target.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'healrotationclearhot'|empty|
|
||||
9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
INSERT INTO `bot_command_settings` VALUES
|
||||
('healrotationclearhot', 0, 'hrclearhot'),
|
||||
('healrotationsethot', 0, 'hrsethot');
|
||||
@ -0,0 +1,41 @@
|
||||
CREATE TABLE `bot_heal_rotations` (
|
||||
`heal_rotation_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`interval` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`fast_heals` INT(3) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`adaptive_targeting` INT(3) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`casting_override` INT(3) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`safe_hp_base` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`safe_hp_cloth` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`safe_hp_leather` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`safe_hp_chain` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`safe_hp_plate` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`critical_hp_base` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`critical_hp_cloth` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`critical_hp_leather` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`critical_hp_chain` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`critical_hp_plate` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`heal_rotation_index`),
|
||||
CONSTRAINT `FK_bot_heal_rotations` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE `bot_heal_rotation_members` (
|
||||
`member_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`heal_rotation_index` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`member_index`),
|
||||
CONSTRAINT `FK_bot_heal_rotation_members_1` FOREIGN KEY (`heal_rotation_index`) REFERENCES `bot_heal_rotations` (`heal_rotation_index`),
|
||||
CONSTRAINT `FK_bot_heal_rotation_members_2` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE `bot_heal_rotation_targets` (
|
||||
`target_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`heal_rotation_index` INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`target_name` varchar(64) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`target_index`),
|
||||
CONSTRAINT `FK_bot_heal_rotation_targets` FOREIGN KEY (`heal_rotation_index`) REFERENCES `bot_heal_rotations` (`heal_rotation_index`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
INSERT INTO `bot_command_settings` VALUES
|
||||
('healrotationdelete', 0, 'hrdelete'),
|
||||
('healrotationsave', 0, 'hrsave');
|
||||
21
zone/bot.cpp
21
zone/bot.cpp
@ -1597,6 +1597,25 @@ bool Bot::DeleteBot()
|
||||
if (!bot_owner)
|
||||
return false;
|
||||
|
||||
if (!botdb.DeleteHealRotation(GetBotID())) {
|
||||
bot_owner->Message(13, "%s", BotDatabase::fail::DeleteHealRotation());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `bot_id` = '%u'", GetBotID());
|
||||
auto results = botdb.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
bot_owner->Message(13, "Failed to delete heal rotation member '%s'", GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `target_name` LIKE '%s'", GetCleanName());
|
||||
results = botdb.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
bot_owner->Message(13, "Failed to delete heal rotation target '%s'", GetCleanName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DeletePet()) {
|
||||
bot_owner->Message(13, "Failed to delete pet for '%s'", GetCleanName());
|
||||
return false;
|
||||
@ -8358,7 +8377,7 @@ bool Bot::IsMyHealRotationSet()
|
||||
{
|
||||
if (!IsHealRotationMember())
|
||||
return false;
|
||||
if (!m_member_of_heal_rotation->IsActive())
|
||||
if (!m_member_of_heal_rotation->IsActive() && !m_member_of_heal_rotation->IsHOTActive())
|
||||
return false;
|
||||
if (!m_member_of_heal_rotation->CastingReady())
|
||||
return false;
|
||||
|
||||
@ -1370,13 +1370,17 @@ int bot_command_init(void)
|
||||
bot_command_add("healrotationadjustsafe", "Adjusts the safe HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_safe) ||
|
||||
bot_command_add("healrotationcastingoverride", "Enables or disables casting overrides within the heal rotation instance", 0, bot_subcommand_heal_rotation_casting_override) ||
|
||||
bot_command_add("healrotationchangeinterval", "Changes casting interval between members within the heal rotation instance", 0, bot_subcommand_heal_rotation_change_interval) ||
|
||||
bot_command_add("healrotationclearhot", "Clears the HOT of a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_hot) ||
|
||||
bot_command_add("healrotationcleartargets", "Removes all targets from a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_targets) ||
|
||||
bot_command_add("healrotationcreate", "Creates a bot heal rotation instance and designates a leader", 0, bot_subcommand_heal_rotation_create) ||
|
||||
bot_command_add("healrotationdelete", "Deletes a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_delete) ||
|
||||
bot_command_add("healrotationfastheals", "Enables or disables fast heals within the heal rotation instance", 0, bot_subcommand_heal_rotation_fast_heals) ||
|
||||
bot_command_add("healrotationlist", "Reports heal rotation instance(s) information", 0, bot_subcommand_heal_rotation_list) ||
|
||||
bot_command_add("healrotationremovemember", "Removes a bot from a heal rotation instance", 0, bot_subcommand_heal_rotation_remove_member) ||
|
||||
bot_command_add("healrotationremovetarget", "Removes target from a heal rotations instance", 0, bot_subcommand_heal_rotation_remove_target) ||
|
||||
bot_command_add("healrotationresetlimits", "Resets all Class Armor Type HP limit criteria in a heal rotation to its default value", 0, bot_subcommand_heal_rotation_reset_limits) ||
|
||||
bot_command_add("healrotationsave", "Saves a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_save) ||
|
||||
bot_command_add("healrotationsethot", "Sets the HOT in a heal rotation instance", 0, bot_subcommand_heal_rotation_set_hot) ||
|
||||
bot_command_add("healrotationstart", "Starts a heal rotation", 0, bot_subcommand_heal_rotation_start) ||
|
||||
bot_command_add("healrotationstop", "Stops a heal rotation", 0, bot_subcommand_heal_rotation_stop) ||
|
||||
bot_command_add("help", "List available commands and their description - specify partial command as argument to search", 0, bot_command_help) ||
|
||||
@ -3064,13 +3068,17 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep)
|
||||
subcommand_list.push_back("healrotationadjustsafe");
|
||||
subcommand_list.push_back("healrotationcastoverride");
|
||||
subcommand_list.push_back("healrotationchangeinterval");
|
||||
subcommand_list.push_back("healrotationclearhot");
|
||||
subcommand_list.push_back("healrotationcleartargets");
|
||||
subcommand_list.push_back("healrotationcreate");
|
||||
subcommand_list.push_back("healrotationdelete");
|
||||
subcommand_list.push_back("healrotationfastheals");
|
||||
subcommand_list.push_back("healrotationlist");
|
||||
subcommand_list.push_back("healrotationremovemember");
|
||||
subcommand_list.push_back("healrotationremovetarget");
|
||||
subcommand_list.push_back("healrotationresetlimits");
|
||||
subcommand_list.push_back("healrotationsave");
|
||||
subcommand_list.push_back("healrotationsethot");
|
||||
subcommand_list.push_back("healrotationstart");
|
||||
subcommand_list.push_back("healrotationstop");
|
||||
/* VS2012 code - end */
|
||||
@ -3078,8 +3086,9 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep)
|
||||
/* VS2013 code
|
||||
const std::list<const char*> subcommand_list = {
|
||||
"healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe",
|
||||
"healrotationcastoverride", "healrotationchangeinterval", "healrotationcleartargets", "healrotationcreate", "healrotationfastheals",
|
||||
"healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationresetlimits", "healrotationstart", "healrotationstop"
|
||||
"healrotationcastoverride", "healrotationchangeinterval", "healrotationclearhot", "healrotationcleartargets", "healrotationcreate",
|
||||
"healrotationdelete", "healrotationfastheals", "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationsave",
|
||||
"healrotationresetlimits", "healrotationsethot", "healrotationstart", "healrotationstop"
|
||||
};
|
||||
*/
|
||||
|
||||
@ -6132,10 +6141,10 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se
|
||||
else if (!critical_arg.compare("-"))
|
||||
critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) - HP_RATIO_DELTA;
|
||||
|
||||
if (critical_ratio > SAFE_HP_RATIO_BASE)
|
||||
critical_ratio = SAFE_HP_RATIO_BASE;
|
||||
if (critical_ratio < CRITICAL_HP_RATIO_BASE)
|
||||
critical_ratio = CRITICAL_HP_RATIO_BASE;
|
||||
if (critical_ratio > SAFE_HP_RATIO_ABS)
|
||||
critical_ratio = SAFE_HP_RATIO_ABS;
|
||||
if (critical_ratio < CRITICAL_HP_RATIO_ABS)
|
||||
critical_ratio = CRITICAL_HP_RATIO_ABS;
|
||||
|
||||
if (!(*current_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(armor_type_value, critical_ratio)) {
|
||||
c->Message(m_fail, "Critical value %3.1f%%(%u) exceeds safe value %3.1f%%(%u) for %s's Heal Rotation",
|
||||
@ -6198,10 +6207,10 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep)
|
||||
else if (!safe_arg.compare("-"))
|
||||
safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) - HP_RATIO_DELTA;
|
||||
|
||||
if (safe_ratio > SAFE_HP_RATIO_BASE)
|
||||
safe_ratio = SAFE_HP_RATIO_BASE;
|
||||
if (safe_ratio < CRITICAL_HP_RATIO_BASE)
|
||||
safe_ratio = CRITICAL_HP_RATIO_BASE;
|
||||
if (safe_ratio > SAFE_HP_RATIO_ABS)
|
||||
safe_ratio = SAFE_HP_RATIO_ABS;
|
||||
if (safe_ratio < CRITICAL_HP_RATIO_ABS)
|
||||
safe_ratio = CRITICAL_HP_RATIO_ABS;
|
||||
|
||||
if (!(*current_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(armor_type_value, safe_ratio)) {
|
||||
c->Message(m_fail, "Safe value %3.1f%%(%u) does not exceed critical value %3.1f%%(%u) for %s's Heal Rotation",
|
||||
@ -6256,13 +6265,13 @@ void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *s
|
||||
hr_casting_override = true;
|
||||
}
|
||||
else if (casting_override_arg.compare("off")) {
|
||||
c->Message(m_action, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName());
|
||||
c->Message(m_action, "Casting override is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
(*current_member->MemberOfHealRotation())->SetCastingOverride(hr_casting_override);
|
||||
|
||||
c->Message(m_action, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName());
|
||||
c->Message(m_action, "Casting override is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep)
|
||||
@ -6323,6 +6332,42 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se
|
||||
c->Message(m_action, "Casting interval is now '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_hot", sep->arg[0], "healrotationclearhot"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(m_usage, "usage: (<target_member>) %s ([member_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]);
|
||||
if (sbl.empty())
|
||||
MyBots::PopulateSBL_ByTargetedBot(c, sbl);
|
||||
if (sbl.empty()) {
|
||||
c->Message(m_fail, "You must <target> or [name] a current member as a bot that you own to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_member = sbl.front();
|
||||
if (!current_member) {
|
||||
c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_member->IsHealRotationMember()) {
|
||||
c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(*current_member->MemberOfHealRotation())->ClearHOTTarget()) {
|
||||
c->Message(m_fail, "Failed to clear %s's Heal Rotation HOT", current_member->GetCleanName());
|
||||
}
|
||||
|
||||
c->Message(m_action, "Succeeded in clearing %s's Heal Rotation HOT", current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_targets", sep->arg[0], "healrotationcleartargets"))
|
||||
@ -6437,8 +6482,115 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep)
|
||||
c->Message(m_fail, "Failed to add %s as a current member to a new Heal Rotation", creator_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<uint32> member_list;
|
||||
std::list<std::string> target_list;
|
||||
bool load_flag = false;
|
||||
bool member_fail = false;
|
||||
bool target_fail = false;
|
||||
|
||||
if (!botdb.LoadHealRotation(creator_member, member_list, target_list, load_flag, member_fail, target_fail))
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotation());
|
||||
|
||||
c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName());
|
||||
if (!load_flag) {
|
||||
c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!member_fail) {
|
||||
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
|
||||
for (auto member_iter : member_list) {
|
||||
if (!member_iter || member_iter == creator_member->GetBotID())
|
||||
continue;
|
||||
|
||||
bool member_found = false;
|
||||
for (auto bot_iter : sbl) {
|
||||
if (bot_iter->GetBotID() != member_iter)
|
||||
continue;
|
||||
|
||||
if (!bot_iter->JoinHealRotationMemberPool(creator_member->MemberOfHealRotation()))
|
||||
c->Message(m_fail, "Failed to add member '%s'", bot_iter->GetCleanName());
|
||||
member_found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!member_found)
|
||||
c->Message(m_fail, "Could not locate member with bot id '%u'", member_iter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotationMembers());
|
||||
}
|
||||
|
||||
if (!target_fail) {
|
||||
for (auto target_iter : target_list) {
|
||||
if (target_iter.empty())
|
||||
continue;
|
||||
|
||||
auto target_mob = entity_list.GetMob(target_iter.c_str());
|
||||
if (!target_mob) {
|
||||
c->Message(m_fail, "Could not locate target '%s'", target_iter.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!target_mob->JoinHealRotationTargetPool(creator_member->MemberOfHealRotation()))
|
||||
c->Message(m_fail, "Failed to add target '%s'", target_mob->GetCleanName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotationTargets());
|
||||
}
|
||||
|
||||
c->Message(m_action, "Successfully loaded %s's Heal Rotation", creator_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_delete", sep->arg[0], "healrotationdelete"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(m_usage, "usage: (<target_member>) %s ([option: all]) ([member_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
bool all_flag = false;
|
||||
int name_arg = 1;
|
||||
if (!strcasecmp(sep->arg[1], "all")) {
|
||||
all_flag = true;
|
||||
name_arg = 2;
|
||||
}
|
||||
|
||||
if (all_flag) {
|
||||
if (botdb.DeleteAllHealRotations(c->CharacterID()))
|
||||
c->Message(m_action, "Succeeded in deleting all heal rotations");
|
||||
else
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::DeleteAllHealRotations());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[name_arg]);
|
||||
if (sbl.empty())
|
||||
MyBots::PopulateSBL_ByTargetedBot(c, sbl);
|
||||
if (sbl.empty()) {
|
||||
c->Message(m_fail, "You must <target> or [name] a current member as a bot that you own to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_member = sbl.front();
|
||||
if (!current_member) {
|
||||
c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!botdb.DeleteHealRotation(current_member->GetBotID())) {
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::DeleteHealRotation());
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(m_action, "Succeeded in deleting %s's heal rotation", current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep)
|
||||
@ -6529,6 +6681,8 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep)
|
||||
c->Message(m_message, "Fast heals: '%s'", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")));
|
||||
c->Message(m_message, "Adaptive targeting: '%s'", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")));
|
||||
c->Message(m_message, "Casting override: '%s'", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")));
|
||||
c->Message(m_message, "HOT state: %s", (((*current_member->MemberOfHealRotation())->IsHOTActive()) ? ("active") : ("inactive")));
|
||||
c->Message(m_message, "HOT target: %s", (((*current_member->MemberOfHealRotation())->HOTTarget()) ? ((*current_member->MemberOfHealRotation())->HOTTarget()->GetCleanName()) : ("null")));
|
||||
|
||||
c->Message(m_message, "Base hp limits - critical: %3.1f%%, safe: %3.1f%%",
|
||||
(*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN),
|
||||
@ -6687,6 +6841,97 @@ void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep)
|
||||
c->Message(m_action, "Class Armor Type HP limit criteria has been set to default values for %s's Heal Rotation", current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_save", sep->arg[0], "healrotationsave"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(m_usage, "usage: (<target_member>) %s ([member_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]);
|
||||
if (sbl.empty())
|
||||
MyBots::PopulateSBL_ByTargetedBot(c, sbl);
|
||||
if (sbl.empty()) {
|
||||
c->Message(m_fail, "You must <target> or [name] a current member as a bot that you own to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_member = sbl.front();
|
||||
if (!current_member) {
|
||||
c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_member->IsHealRotationMember()) {
|
||||
c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
bool member_fail = false;
|
||||
bool target_fail = false;
|
||||
if (!botdb.SaveHealRotation(current_member, member_fail, target_fail)) {
|
||||
c->Message(m_fail, "%s", BotDatabase::fail::SaveHealRotation());
|
||||
return;
|
||||
}
|
||||
if (member_fail)
|
||||
c->Message(m_fail, "Failed to save heal rotation members");
|
||||
if (target_fail)
|
||||
c->Message(m_fail, "Failed to save heal rotation targets");
|
||||
|
||||
c->Message(m_action, "Succeeded in saving %s's heal rotation", current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_set_hot", sep->arg[0], "healrotationsethot"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(m_usage, "usage: (<target_member>) %s [heal_override_target_name] ([member_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]);
|
||||
if (sbl.empty())
|
||||
MyBots::PopulateSBL_ByTargetedBot(c, sbl);
|
||||
if (sbl.empty()) {
|
||||
c->Message(m_fail, "You must <target> or [name] a current member as a bot that you own to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_member = sbl.front();
|
||||
if (!current_member) {
|
||||
c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_member->IsHealRotationMember()) {
|
||||
c->Message(m_fail, "%s is not a member of a Heal Rotation", current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
auto hot_target = entity_list.GetMob(sep->arg[1]);
|
||||
if (!hot_target) {
|
||||
c->Message(m_fail, "No target exists by the name '%s'", sep->arg[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(*current_member->MemberOfHealRotation())->IsTargetInPool(hot_target)) {
|
||||
c->Message(m_fail, "%s is not a target in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(*current_member->MemberOfHealRotation())->SetHOTTarget(hot_target)) {
|
||||
c->Message(m_fail, "Failed to set %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(m_action, "Succeeded in setting %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName());
|
||||
}
|
||||
|
||||
void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_start", sep->arg[0], "healrotationstart"))
|
||||
|
||||
@ -633,13 +633,17 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se
|
||||
void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep);
|
||||
void bot_subcommand_inventory_give(Client *c, const Seperator *sep);
|
||||
|
||||
@ -2407,6 +2407,284 @@ bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 group_id, std::list<uint
|
||||
}
|
||||
|
||||
|
||||
/* Bot heal rotation functions */
|
||||
bool BotDatabase::LoadHealRotationIDByBotID(const uint32 bot_id, uint32& hr_index)
|
||||
{
|
||||
if (!bot_id)
|
||||
return false;
|
||||
|
||||
query = StringFormat("SELECT `heal_rotation_index` FROM `bot_heal_rotations` WHERE `bot_id` = '%u' LIMIT 1", bot_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
auto row = results.begin();
|
||||
hr_index = atoi(row[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadHealRotation(Bot* hr_member, std::list<uint32>& member_list, std::list<std::string>& target_list, bool& load_flag, bool& member_fail, bool& target_fail)
|
||||
{
|
||||
if (!hr_member)
|
||||
return false;
|
||||
|
||||
uint32 hr_index = 0;
|
||||
if (!LoadHealRotationIDByBotID(hr_member->GetBotID(), hr_index))
|
||||
return false;
|
||||
if (!hr_index)
|
||||
return true;
|
||||
|
||||
if (!hr_member->IsHealRotationMember())
|
||||
return false;
|
||||
|
||||
query = StringFormat(
|
||||
"SELECT "
|
||||
" `interval`,"
|
||||
" `fast_heals`,"
|
||||
" `adaptive_targeting`,"
|
||||
" `casting_override`,"
|
||||
" `safe_hp_base`,"
|
||||
" `safe_hp_cloth`,"
|
||||
" `safe_hp_leather`,"
|
||||
" `safe_hp_chain`,"
|
||||
" `safe_hp_plate`,"
|
||||
" `critical_hp_base`,"
|
||||
" `critical_hp_cloth`,"
|
||||
" `critical_hp_leather`,"
|
||||
" `critical_hp_chain`,"
|
||||
" `critical_hp_plate`"
|
||||
" FROM `bot_heal_rotations`"
|
||||
" WHERE `heal_rotation_index` = '%u'"
|
||||
" LIMIT 1",
|
||||
hr_index
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
auto row = results.begin();
|
||||
(*hr_member->MemberOfHealRotation())->SetIntervalS((uint32)atoi(row[0]));
|
||||
(*hr_member->MemberOfHealRotation())->SetFastHeals((bool)atoi(row[1]));
|
||||
(*hr_member->MemberOfHealRotation())->SetAdaptiveTargeting((bool)atoi(row[2]));
|
||||
(*hr_member->MemberOfHealRotation())->SetCastingOverride((bool)atoi(row[3]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[4]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH, atof(row[5]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER, atof(row[6]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN, atof(row[7]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE, atof(row[8]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[9]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH, atof(row[10]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER, atof(row[11]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN, atof(row[12]));
|
||||
(*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE, atof(row[13]));
|
||||
|
||||
load_flag = true;
|
||||
|
||||
if (!LoadHealRotationMembers(hr_index, member_list))
|
||||
member_fail = true;
|
||||
|
||||
if (!LoadHealRotationTargets(hr_index, target_list))
|
||||
target_fail = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadHealRotationMembers(const uint32 hr_index, std::list<uint32>& member_list)
|
||||
{
|
||||
if (!hr_index)
|
||||
return false;
|
||||
|
||||
query = StringFormat("SELECT `bot_id` FROM `bot_heal_rotation_members` WHERE `heal_rotation_index` = '%u'", hr_index);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
for (auto row : results) {
|
||||
if (row[0])
|
||||
member_list.push_back(atoi(row[0]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadHealRotationTargets(const uint32 hr_index, std::list<std::string>& target_list)
|
||||
{
|
||||
if (!hr_index)
|
||||
return false;
|
||||
|
||||
query = StringFormat("SELECT `target_name` FROM `bot_heal_rotation_targets` WHERE `heal_rotation_index` = '%u'", hr_index);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
if (!results.RowCount())
|
||||
return true;
|
||||
|
||||
for (auto row : results) {
|
||||
if (row[0])
|
||||
target_list.push_back(row[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveHealRotation(Bot* hr_member, bool& member_fail, bool& target_fail)
|
||||
{
|
||||
if (!hr_member)
|
||||
return false;
|
||||
|
||||
if (!DeleteHealRotation(hr_member->GetBotID()))
|
||||
return false;
|
||||
|
||||
if (!hr_member->IsHealRotationMember())
|
||||
return false;
|
||||
|
||||
query = StringFormat(
|
||||
"INSERT INTO `bot_heal_rotations` ("
|
||||
"`bot_id`,"
|
||||
" `interval`,"
|
||||
" `fast_heals`,"
|
||||
" `adaptive_targeting`,"
|
||||
" `casting_override`,"
|
||||
" `safe_hp_base`,"
|
||||
" `safe_hp_cloth`,"
|
||||
" `safe_hp_leather`,"
|
||||
" `safe_hp_chain`,"
|
||||
" `safe_hp_plate`,"
|
||||
" `critical_hp_base`,"
|
||||
" `critical_hp_cloth`,"
|
||||
" `critical_hp_leather`,"
|
||||
" `critical_hp_chain`,"
|
||||
" `critical_hp_plate`"
|
||||
")"
|
||||
" VALUES ("
|
||||
"'%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%u',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f',"
|
||||
" '%f'"
|
||||
")",
|
||||
hr_member->GetBotID(),
|
||||
((*hr_member->MemberOfHealRotation())->IntervalS()),
|
||||
((*hr_member->MemberOfHealRotation())->FastHeals()),
|
||||
((*hr_member->MemberOfHealRotation())->AdaptiveTargeting()),
|
||||
((*hr_member->MemberOfHealRotation())->CastingOverride()),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN)),
|
||||
((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE))
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
uint32 hr_index = results.LastInsertedID();
|
||||
if (!hr_index)
|
||||
return false;
|
||||
|
||||
std::list<Bot*>* member_list = (*hr_member->MemberOfHealRotation())->MemberList();
|
||||
|
||||
for (auto member_iter : *member_list) {
|
||||
if (!member_iter)
|
||||
continue;
|
||||
|
||||
query = StringFormat("INSERT INTO `bot_heal_rotation_members` (`heal_rotation_index`, `bot_id`) VALUES ('%u', '%u')", hr_index, member_iter->GetBotID());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
member_fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Mob*>* target_list = (*hr_member->MemberOfHealRotation())->TargetList();
|
||||
|
||||
for (auto target_iter : *target_list) {
|
||||
if (!target_iter)
|
||||
continue;
|
||||
|
||||
query = StringFormat("INSERT INTO `bot_heal_rotation_targets` (`heal_rotation_index`, `target_name`) VALUES ('%u', '%s')", hr_index, target_iter->GetCleanName());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
target_fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::DeleteHealRotation(const uint32 creator_id)
|
||||
{
|
||||
if (!creator_id)
|
||||
return false;
|
||||
|
||||
uint32 hr_index = 0;
|
||||
if (!LoadHealRotationIDByBotID(creator_id, hr_index))
|
||||
return false;
|
||||
if (!hr_index)
|
||||
return true;
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `heal_rotation_index` = '%u'", hr_index);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `heal_rotation_index` = '%u'", hr_index);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
query = StringFormat("DELETE FROM `bot_heal_rotations` WHERE `heal_rotation_index` = '%u'", hr_index);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::DeleteAllHealRotations(const uint32 owner_id)
|
||||
{
|
||||
if (!owner_id)
|
||||
return false;
|
||||
|
||||
query = StringFormat("SELECT `bot_id` FROM `bot_heal_rotations` WHERE `bot_id` IN (SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u')", owner_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
for (auto row : results) {
|
||||
if (!row[0])
|
||||
continue;
|
||||
|
||||
DeleteHealRotation(atoi(row[0]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Bot miscellaneous functions */
|
||||
|
||||
|
||||
@ -2495,6 +2773,15 @@ const char* BotDatabase::fail::LoadBotGroupsListByOwnerID() { return "Failed to
|
||||
/* fail::Bot group functions */
|
||||
const char* BotDatabase::fail::LoadGroupedBotsByGroupID() { return "Failed to load grouped bots by group id"; }
|
||||
|
||||
/* fail::Bot heal rotation functions */
|
||||
const char* BotDatabase::fail::LoadHealRotationIDByBotID() { return "Failed to load heal rotation id by bot id"; }
|
||||
const char* BotDatabase::fail::LoadHealRotation() { return "Failed to load heal rotation"; }
|
||||
const char* BotDatabase::fail::LoadHealRotationMembers() { return "Failed to load heal rotation members"; }
|
||||
const char* BotDatabase::fail::LoadHealRotationTargets() { return "Failed to load heal rotation targets"; }
|
||||
const char* BotDatabase::fail::SaveHealRotation() { return "Failed to save heal rotation"; }
|
||||
const char* BotDatabase::fail::DeleteHealRotation() { return "Failed to delete heal rotation"; }
|
||||
const char* BotDatabase::fail::DeleteAllHealRotations() { return "Failed to delete all heal rotations"; }
|
||||
|
||||
/* fail::Bot miscellaneous functions */
|
||||
|
||||
#endif // BOTS
|
||||
|
||||
@ -167,6 +167,17 @@ public:
|
||||
bool LoadGroupedBotsByGroupID(const uint32 group_id, std::list<uint32>& group_list);
|
||||
|
||||
|
||||
/* Bot heal rotation functions */
|
||||
bool LoadHealRotationIDByBotID(const uint32 bot_id, uint32& hr_index);
|
||||
|
||||
bool LoadHealRotation(Bot* hr_member, std::list<uint32>& member_list, std::list<std::string>& target_list, bool& load_flag, bool& member_fail, bool& target_fail);
|
||||
bool LoadHealRotationMembers(const uint32 hr_index, std::list<uint32>& member_list);
|
||||
bool LoadHealRotationTargets(const uint32 hr_index, std::list<std::string>& target_list);
|
||||
bool SaveHealRotation(Bot* hr_member, bool& member_fail, bool& target_fail);
|
||||
bool DeleteHealRotation(const uint32 creator_id);
|
||||
|
||||
bool DeleteAllHealRotations(const uint32 owner_id);
|
||||
|
||||
/* Bot miscellaneous functions */
|
||||
|
||||
|
||||
@ -257,6 +268,15 @@ public:
|
||||
/* fail::Bot group functions */
|
||||
static const char* LoadGroupedBotsByGroupID();
|
||||
|
||||
/* fail::Bot heal rotation functions */
|
||||
static const char* LoadHealRotationIDByBotID();
|
||||
static const char* LoadHealRotation();
|
||||
static const char* LoadHealRotationMembers();
|
||||
static const char* LoadHealRotationTargets();
|
||||
static const char* SaveHealRotation();
|
||||
static const char* DeleteHealRotation();
|
||||
static const char* DeleteAllHealRotations();
|
||||
|
||||
/* fail::Bot miscellaneous functions */
|
||||
};
|
||||
|
||||
|
||||
@ -25,10 +25,10 @@
|
||||
#define SAFE_HP_RATIO_CHAIN 80.0f
|
||||
#define SAFE_HP_RATIO_PLATE 75.0f
|
||||
|
||||
#define CRITICAL_HP_RATIO_CLOTH 30.0f
|
||||
#define CRITICAL_HP_RATIO_LEATHER 25.0f
|
||||
#define CRITICAL_HP_RATIO_CHAIN 15.0f
|
||||
#define CRITICAL_HP_RATIO_PLATE 10.0f
|
||||
#define CRITICAL_HP_RATIO_CLOTH 45.0f
|
||||
#define CRITICAL_HP_RATIO_LEATHER 40.0f
|
||||
#define CRITICAL_HP_RATIO_CHAIN 35.0f
|
||||
#define CRITICAL_HP_RATIO_PLATE 30.0f
|
||||
|
||||
HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals, bool adaptive_targeting, bool casting_override)
|
||||
{
|
||||
@ -51,6 +51,9 @@ HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals,
|
||||
m_is_active = false;
|
||||
|
||||
m_consumed = false;
|
||||
|
||||
m_hot_target = nullptr;
|
||||
m_hot_active = false;
|
||||
}
|
||||
|
||||
void HealRotation::SetIntervalMS(uint32 interval_ms)
|
||||
@ -143,6 +146,11 @@ bool HealRotation::RemoveTargetFromPool(Mob* hr_target)
|
||||
if (target_iter != hr_target)
|
||||
continue;
|
||||
|
||||
if (m_hot_target == hr_target) {
|
||||
m_hot_target = nullptr;
|
||||
m_hot_active = false;
|
||||
}
|
||||
|
||||
m_target_healing_stats_2.erase(hr_target);
|
||||
m_target_healing_stats_1.erase(hr_target);
|
||||
m_target_pool.remove(hr_target);
|
||||
@ -172,6 +180,8 @@ bool HealRotation::ClearMemberPool()
|
||||
|
||||
bool HealRotation::ClearTargetPool()
|
||||
{
|
||||
m_hot_target = nullptr;
|
||||
m_hot_active = false;
|
||||
m_is_active = false;
|
||||
|
||||
auto clear_list = m_target_pool;
|
||||
@ -184,11 +194,32 @@ bool HealRotation::ClearTargetPool()
|
||||
return m_target_pool.empty();
|
||||
}
|
||||
|
||||
bool HealRotation::SetHOTTarget(Mob* hot_target)
|
||||
{
|
||||
if (!hot_target || !IsTargetInPool(hot_target))
|
||||
return false;
|
||||
|
||||
m_hot_target = hot_target;
|
||||
m_hot_active = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealRotation::ClearHOTTarget()
|
||||
{
|
||||
m_hot_target = nullptr;
|
||||
m_hot_active = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealRotation::Start()
|
||||
{
|
||||
m_is_active = false;
|
||||
if (m_member_pool.empty() || m_target_pool.empty())
|
||||
if (m_member_pool.empty() || m_target_pool.empty()) {
|
||||
validate_hot();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_cycle_pool = m_member_pool;
|
||||
m_is_active = true;
|
||||
@ -207,7 +238,7 @@ bool HealRotation::Stop()
|
||||
|
||||
Bot* HealRotation::CastingMember()
|
||||
{
|
||||
if (!m_is_active)
|
||||
if (!m_is_active && !m_hot_active)
|
||||
return nullptr;
|
||||
|
||||
if (m_cycle_pool.empty()) {
|
||||
@ -222,6 +253,9 @@ Bot* HealRotation::CastingMember()
|
||||
|
||||
bool HealRotation::PokeCastingTarget()
|
||||
{
|
||||
if (m_hot_target && m_hot_active)
|
||||
return true;
|
||||
|
||||
if (!m_is_active)
|
||||
return false;
|
||||
|
||||
@ -248,6 +282,9 @@ bool HealRotation::PokeCastingTarget()
|
||||
|
||||
Mob* HealRotation::CastingTarget()
|
||||
{
|
||||
if (m_hot_target && m_hot_active)
|
||||
return m_hot_target;
|
||||
|
||||
if (!m_is_active)
|
||||
return nullptr;
|
||||
if (!m_active_heal_target)
|
||||
@ -304,6 +341,16 @@ bool HealRotation::IsTargetInPool(Mob* hr_target)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HealRotation::IsHOTTarget(Mob* hot_target)
|
||||
{
|
||||
if (!hot_target)
|
||||
return false;
|
||||
if (m_hot_target != hot_target)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealRotation::SetMemberIsCasting(Bot* hr_member, bool flag)
|
||||
{
|
||||
if (!hr_member)
|
||||
@ -444,7 +491,7 @@ bool HealRotation::SetArmorTypeSafeHPRatio(uint8 armor_type, float hp_ratio)
|
||||
{
|
||||
if (armor_type >= ARMOR_TYPE_COUNT)
|
||||
return false;
|
||||
if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE)
|
||||
if (hp_ratio < CRITICAL_HP_RATIO_ABS || hp_ratio > SAFE_HP_RATIO_ABS)
|
||||
return false;
|
||||
if (hp_ratio < m_critical_hp_ratio[armor_type])
|
||||
return false;
|
||||
@ -458,7 +505,7 @@ bool HealRotation::SetArmorTypeCriticalHPRatio(uint8 armor_type, float hp_ratio)
|
||||
{
|
||||
if (armor_type >= ARMOR_TYPE_COUNT)
|
||||
return false;
|
||||
if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE)
|
||||
if (hp_ratio < CRITICAL_HP_RATIO_ABS || hp_ratio > SAFE_HP_RATIO_ABS)
|
||||
return false;
|
||||
if (hp_ratio > m_safe_hp_ratio[armor_type])
|
||||
return false;
|
||||
@ -863,6 +910,19 @@ void HealRotation::bias_targets()
|
||||
#endif
|
||||
}
|
||||
|
||||
void HealRotation::validate_hot()
|
||||
{
|
||||
if (!m_hot_target) {
|
||||
m_hot_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsTargetInPool(m_hot_target)) {
|
||||
m_hot_target = nullptr;
|
||||
m_hot_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsHealRotationMemberClass(uint8 class_id)
|
||||
{
|
||||
switch (class_id) {
|
||||
|
||||
@ -35,8 +35,11 @@
|
||||
#define HEALING_STATS_RESET_INTERVAL 60000
|
||||
#define HEALING_STATS_RESET_INTERVAL_S 60
|
||||
|
||||
#define SAFE_HP_RATIO_ABS 100.0f
|
||||
#define SAFE_HP_RATIO_BASE 95.0f
|
||||
#define CRITICAL_HP_RATIO_BASE 10.0f
|
||||
|
||||
#define CRITICAL_HP_RATIO_ABS 0.0f
|
||||
#define CRITICAL_HP_RATIO_BASE 30.0f
|
||||
|
||||
struct HealingStats
|
||||
{
|
||||
@ -49,7 +52,7 @@ class HealRotation
|
||||
{
|
||||
public:
|
||||
HealRotation(Bot* hr_creator, uint32 interval_ms = CASTING_CYCLE_DEFAULT_INTERVAL, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
|
||||
HealRotation(HealRotation* allocator_shunt) {};
|
||||
HealRotation(HealRotation* allocator_shunt) {}; // use should be limited to the shared_ptr<HealRotation> memory allocation call
|
||||
|
||||
void SetIntervalMS(uint32 interval_ms);
|
||||
void SetIntervalS(uint32 interval_s);
|
||||
@ -72,10 +75,15 @@ public:
|
||||
bool ClearMemberPool();
|
||||
bool ClearTargetPool();
|
||||
|
||||
Mob* HOTTarget() { return m_hot_target; }
|
||||
bool SetHOTTarget(Mob* hot_target);
|
||||
bool ClearHOTTarget();
|
||||
|
||||
bool Start();
|
||||
bool Stop();
|
||||
|
||||
bool IsActive() { return m_is_active; }
|
||||
bool IsHOTActive() { return m_hot_active; }
|
||||
bool CastingReady() { return (Timer::GetCurrentTime() >= m_next_cast_time_ms); }
|
||||
Bot* CastingMember();
|
||||
bool PokeCastingTarget();
|
||||
@ -88,6 +96,7 @@ public:
|
||||
|
||||
bool IsMemberInPool(Bot* hr_member);
|
||||
bool IsTargetInPool(Mob* hr_target);
|
||||
bool IsHOTTarget(Mob* hot_target);
|
||||
|
||||
void SetMemberIsCasting(Bot* hr_member, bool flag = true);
|
||||
bool MemberIsCasting(Bot* hr_member);
|
||||
@ -114,6 +123,7 @@ private:
|
||||
void cycle_refresh();
|
||||
bool healable_target(bool use_class_at = true, bool critical_only = false);
|
||||
void bias_targets();
|
||||
void validate_hot();
|
||||
|
||||
uint32 m_creation_time_ms;
|
||||
uint32 m_last_heal_time_ms;
|
||||
@ -131,6 +141,9 @@ private:
|
||||
|
||||
bool m_consumed;
|
||||
|
||||
Mob* m_hot_target;
|
||||
bool m_hot_active;
|
||||
|
||||
std::list<Bot*> m_member_pool;
|
||||
std::list<Bot*> m_cycle_pool;
|
||||
std::list<Mob*> m_target_pool;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user