mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
Bot Rework
This commit is contained in:
@@ -131,6 +131,8 @@ static std::map<uint8, std::string> class_names = {
|
||||
#define ARMOR_TYPE_LAST ARMOR_TYPE_PLATE
|
||||
#define ARMOR_TYPE_COUNT 5
|
||||
|
||||
#define BOT_CLASS_BASE_ID_PREFIX 3000
|
||||
|
||||
|
||||
const char* GetClassIDName(uint8 class_id, uint8 level = 0);
|
||||
|
||||
|
||||
@@ -161,6 +161,346 @@ ADD COLUMN `extra_haste` mediumint(8) NOT NULL DEFAULT 0 AFTER `wis`;
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_spells_entries`
|
||||
CHANGE COLUMN `spellid` `spell_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_spells_id`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9046,
|
||||
.description = "2024_05_18_bot_settings.sql",
|
||||
.check = "SHOW TABLES LIKE 'bot_settings'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `bot_settings` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`char_id` INT UNSIGNED NOT NULL,
|
||||
`bot_id` INT UNSIGNED NOT NULL,
|
||||
`setting_id` INT UNSIGNED NOT NULL,
|
||||
`setting_type` INT UNSIGNED NOT NULL,
|
||||
`value` INT UNSIGNED NOT NULL,
|
||||
`category_name` VARCHAR(64) NULL DEFAULT '',
|
||||
`setting_name` VARCHAR(64) NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
)
|
||||
COLLATE='utf8mb4_general_ci';
|
||||
|
||||
INSERT INTO bot_settings SELECT NULL, 0, bd.`bot_id`, 0, 0, bd.`expansion_bitmask`, 'BaseSetting', 'ExpansionBitmask' FROM bot_data bd
|
||||
JOIN rule_values rv
|
||||
WHERE rv.rule_name LIKE 'Bots:BotExpansionSettings'
|
||||
AND bd.expansion_bitmask != rv.rule_value;
|
||||
|
||||
INSERT INTO bot_settings SELECT NULL, 0, `bot_id`, 1, 0, `show_helm`, 'BaseSetting', 'ShowHelm' FROM bot_data WHERE `show_helm` != 1;
|
||||
INSERT INTO bot_settings SELECT NULL, 0, `bot_id`, 2, 0, `follow_distance`, 'BaseSetting', 'FollowDistance' FROM bot_data WHERE `follow_distance` != 184;
|
||||
|
||||
INSERT INTO bot_settings
|
||||
SELECT NULL, 0, `bot_id`, 3, 0, `stop_melee_level`, 'BaseSetting', 'StopMeleeLevel'
|
||||
FROM (
|
||||
SELECT `bot_id`,
|
||||
(CASE
|
||||
WHEN (`class` IN (2, 6, 10, 11, 12, 13, 14)) THEN 13
|
||||
ELSE 255
|
||||
END) AS `sml`,
|
||||
`stop_melee_level`
|
||||
FROM bot_data
|
||||
) AS `subquery`
|
||||
WHERE `sml` != `stop_melee_level`;
|
||||
|
||||
INSERT INTO bot_settings SELECT NULL, 0, `bot_id`, 4, 0, `enforce_spell_settings`, 'BaseSetting', 'EnforceSpellSettings' FROM bot_data WHERE `enforce_spell_settings` != 0;
|
||||
INSERT INTO bot_settings SELECT NULL, 0, `bot_id`, 5, 0, `archery_setting`, 'BaseSetting', 'RangedSetting' FROM bot_data WHERE `archery_setting` != 0;
|
||||
|
||||
INSERT INTO bot_settings
|
||||
SELECT NULL, 0, `bot_id`, 8, 0, `caster_range`, 'BaseSetting', 'CasterRange'
|
||||
FROM (
|
||||
SELECT `bot_id`,
|
||||
(CASE
|
||||
WHEN (`class` IN (1, 7, 19, 16)) THEN 0
|
||||
WHEN `class` = 8 THEN 0
|
||||
ELSE 90
|
||||
END) AS `casterRange`,
|
||||
`caster_range`
|
||||
FROM bot_data
|
||||
) AS `subquery`
|
||||
WHERE `casterRange` != `caster_range`;
|
||||
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `show_helm`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `follow_distance`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `stop_melee_level`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `expansion_bitmask`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `enforce_spell_settings`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `archery_setting`;
|
||||
ALTER TABLE `bot_data`
|
||||
DROP COLUMN `caster_range`;
|
||||
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'bh' WHERE `bot_command`='behindmob';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'bs|settings' WHERE `bot_command`='botsettings';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|ranged|toggleranged|btr') ELSE 'ranged|toggleranged|btr' END WHERE `bot_command`='bottoggleranged' AND `aliases` NOT LIKE '%ranged|toggleranged|btr%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|cr') ELSE 'cr' END WHERE `bot_command`='casterrange' AND `aliases` NOT LIKE '%cr%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'copy' WHERE `bot_command`='copysettings';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'default' WHERE `bot_command`='defaultsettings';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|enforce') ELSE 'enforce' END WHERE `bot_command`='enforcespellsettings' AND `aliases` NOT LIKE '%enforce%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|ib') ELSE 'ib' END WHERE `bot_command`='illusionblock' AND `aliases` NOT LIKE '%ib%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|ig') ELSE 'invgive|ig' END WHERE `bot_command`='inventorygive' AND `aliases` NOT LIKE '%ig%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|il') ELSE 'invlist|il' END WHERE `bot_command`='inventorylist' AND `aliases` NOT LIKE '%il%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|ir') ELSE 'invremove|ir' END WHERE `bot_command`='inventoryremove' AND `aliases` NOT LIKE '%ir%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|iw') ELSE 'invwindow|iw' END WHERE `bot_command`='inventorywindow' AND `aliases` NOT LIKE '%iw%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|iu') ELSE 'iu' END WHERE `bot_command`='itemuse' AND `aliases` NOT LIKE '%iu%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'mmr' WHERE `bot_command`='maxmeleerange';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|pp') ELSE 'pp' END WHERE `bot_command`='pickpocket' AND `aliases` NOT LIKE '%pp%';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'sithp' WHERE `bot_command`='sithppercent';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'sitcombat' WHERE `bot_command`='sitincombat';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'sitmana' WHERE `bot_command`='sitmanapercent';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'aggrochecks' WHERE `bot_command`='spellaggrochecks';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'delays' WHERE `bot_command`='spelldelays';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'engagedpriority' WHERE `bot_command`='spellengagedpriority';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'holds' WHERE `bot_command`='spellholds';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'idlepriority' WHERE `bot_command`='spellidlepriority';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'maxhp' WHERE `bot_command`='spellmaxhppct';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'maxmana' WHERE `bot_command`='spellmaxmanapct';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'maxthresholds' WHERE `bot_command`='spellmaxthresholds';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'minhp' WHERE `bot_command`='spellminhppct';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'minmana' WHERE `bot_command`='spellminmanapct';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'minthresholds' WHERE `bot_command`='spellminthresholds';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'pursuepriority' WHERE `bot_command`='spellpursuepriority';
|
||||
UPDATE `bot_command_settings` SET `aliases`= 'targetcount' WHERE `bot_command`='spelltargetcount';
|
||||
UPDATE `bot_command_settings` SET `aliases`= CASE WHEN LENGTH(`aliases`) > 0 THEN CONCAT(`aliases`, '|vc') ELSE 'vc' END WHERE `bot_command`='viewcombos' AND `aliases` NOT LIKE '%vc%';
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9047,
|
||||
.description = "2024_05_18_bot_update_spell_types.sql",
|
||||
.check = "SELECT * FROM `bot_spells_entries` WHERE `type` > 21",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
UPDATE `bot_spells_entries` SET `type` = 0 WHERE `type` = 1;
|
||||
UPDATE `bot_spells_entries` SET `type` = 1 WHERE `type` = 2;
|
||||
UPDATE `bot_spells_entries` SET `type` = 2 WHERE `type` = 4;
|
||||
UPDATE `bot_spells_entries` SET `type` = 3 WHERE `type` = 8;
|
||||
UPDATE `bot_spells_entries` SET `type` = 4 WHERE `type` = 16;
|
||||
UPDATE `bot_spells_entries` SET `type` = 5 WHERE `type` = 32;
|
||||
UPDATE `bot_spells_entries` SET `type` = 6 WHERE `type` = 64;
|
||||
UPDATE `bot_spells_entries` SET `type` = 7 WHERE `type` = 128;
|
||||
UPDATE `bot_spells_entries` SET `type` = 8 WHERE `type` = 256;
|
||||
UPDATE `bot_spells_entries` SET `type` = 9 WHERE `type` = 512;
|
||||
UPDATE `bot_spells_entries` SET `type` = 10 WHERE `type` = 1024;
|
||||
UPDATE `bot_spells_entries` SET `type` = 11 WHERE `type` = 2048;
|
||||
UPDATE `bot_spells_entries` SET `type` = 12 WHERE `type` = 4096;
|
||||
UPDATE `bot_spells_entries` SET `type` = 13 WHERE `type` = 8192;
|
||||
UPDATE `bot_spells_entries` SET `type` = 14 WHERE `type` = 16384;
|
||||
UPDATE `bot_spells_entries` SET `type` = 15 WHERE `type` = 32768;
|
||||
UPDATE `bot_spells_entries` SET `type` = 16 WHERE `type` = 65536;
|
||||
UPDATE `bot_spells_entries` SET `type` = 17 WHERE `type` = 131072;
|
||||
UPDATE `bot_spells_entries` SET `type` = 18 WHERE `type` = 262144;
|
||||
UPDATE `bot_spells_entries` SET `type` = 19 WHERE `type` = 524288;
|
||||
UPDATE `bot_spells_entries` SET `type` = 20 WHERE `type` = 1048576;
|
||||
UPDATE `bot_spells_entries` SET `type` = 21 WHERE `type` = 2097152;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9048,
|
||||
.description = "2024_05_18_bot_fear_spell_type.sql",
|
||||
.check = "SELECT * FROM `bot_spells_entries` where `type` = 22",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
UPDATE bot_spells_entries b, spells_new s
|
||||
SET b.`type` = 22
|
||||
WHERE b.spellid = s.id
|
||||
AND (
|
||||
s.`effectid1` = 23 OR
|
||||
s.`effectid2` = 23 OR
|
||||
s.`effectid3` = 23 OR
|
||||
s.`effectid4` = 23 OR
|
||||
s.`effectid5` = 23 OR
|
||||
s.`effectid6` = 23 OR
|
||||
s.`effectid7` = 23 OR
|
||||
s.`effectid8` = 23 OR
|
||||
s.`effectid9` = 23 OR
|
||||
s.`effectid10` = 23 OR
|
||||
s.`effectid11` = 23 OR
|
||||
s.`effectid12` = 23
|
||||
);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9049,
|
||||
.description = "2024_05_18_correct_bot_spell_entries_types.sql",
|
||||
.check = "SELECT * FROM `bot_spells_entries` where `npc_spells_id` = 3002 AND `spellid` = 14312",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
-- Class fixes
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3002 WHERE b.`spellid` = 14312;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3002 WHERE b.`spellid` = 14313;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3002 WHERE b.`spellid` = 14314;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3005 WHERE b.`spellid` = 15186;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3005 WHERE b.`spellid` = 15187;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3005 WHERE b.`spellid` = 15188;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14446;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14447;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14467;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14468;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14469;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3003 WHERE b.`spellid` = 14955;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3003 WHERE b.`spellid` = 14956;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14387;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14388;
|
||||
UPDATE bot_spells_entries b SET b.`npc_spells_id` = 3006 WHERE b.`spellid` = 14389;
|
||||
|
||||
-- Minlevel fixes
|
||||
UPDATE bot_spells_entries SET `minlevel` = 34 WHERE `spellid` = 1445 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 2 WHERE `spellid` = 229 AND `npc_spells_id` = 3011;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 13 WHERE `spellid` = 333 AND `npc_spells_id` = 3013;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 29 WHERE `spellid` = 106 AND `npc_spells_id` = 3013;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 38 WHERE `spellid` = 754 AND `npc_spells_id` = 3010;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 58 WHERE `spellid` = 2589 AND `npc_spells_id` = 3003;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 67 WHERE `spellid` = 5305 AND `npc_spells_id` = 3004;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14267 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14268 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14269 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 23 WHERE `spellid` = 738 AND `npc_spells_id` = 3008;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 51 WHERE `spellid` = 1751 AND `npc_spells_id` = 3008;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 7 WHERE `spellid` = 734 AND `npc_spells_id` = 3008;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 5 WHERE `spellid` = 717 AND `npc_spells_id` = 3008;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 15186 AND `npc_spells_id` = 3005;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 15187 AND `npc_spells_id` = 3005;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 15188 AND `npc_spells_id` = 3005;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 80 WHERE `spellid` = 14446 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 80 WHERE `spellid` = 14447 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14467 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14468 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 79 WHERE `spellid` = 14469 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14955 AND `npc_spells_id` = 3003;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14956 AND `npc_spells_id` = 3003;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 78 WHERE `spellid` = 14387 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14388 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14389 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14312 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14313 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `minlevel` = 77 WHERE `spellid` = 14314 AND `npc_spells_id` = 3002;
|
||||
|
||||
-- Maxlevel fixes
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 83 WHERE `spellid` = 14267 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 83 WHERE `spellid` = 14268 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 83 WHERE `spellid` = 14269 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 84 WHERE `spellid` = 14446 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 84 WHERE `spellid` = 14447 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 84 WHERE `spellid` = 14467 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 84 WHERE `spellid` = 14468 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 84 WHERE `spellid` = 14469 AND `npc_spells_id` = 3006;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 81 WHERE `spellid` = 14312 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 81 WHERE `spellid` = 14313 AND `npc_spells_id` = 3002;
|
||||
UPDATE bot_spells_entries SET `maxlevel` = 81 WHERE `spellid` = 14314 AND `npc_spells_id` = 3002;
|
||||
|
||||
-- Type fixes
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 201;
|
||||
UPDATE bot_spells_entries SET `type` = 17 WHERE `spellid` = 752;
|
||||
UPDATE bot_spells_entries SET `type` = 17 WHERE `spellid` = 2117;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 2542;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 2544;
|
||||
UPDATE bot_spells_entries SET `type` = 6 WHERE `spellid` = 2115;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 1403;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 1405;
|
||||
UPDATE bot_spells_entries SET `type` = 9 WHERE `spellid` = 289;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 294;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 302;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 521;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 185;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 450;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 186;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 4074;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 195;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 1712;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 1703;
|
||||
UPDATE bot_spells_entries SET `type` = 17 WHERE `spellid` = 3229;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 3345;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 5509;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 6826;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 270;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 281;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 505;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 526;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 110;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 506;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 162;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 111;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 507;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 527;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 163;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 112;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 1588;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1573;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1592;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1577;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1578;
|
||||
UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 1576;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 3386;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 3387;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 4900;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 3395;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 5394;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 5392;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 6827;
|
||||
UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 5416;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1437;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 1436;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 5348;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 8008;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 2571;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 370;
|
||||
UPDATE bot_spells_entries SET `type` = 17 WHERE `spellid` = 1741;
|
||||
UPDATE bot_spells_entries SET `type` = 17 WHERE `spellid` = 1296;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 270;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 2634;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 2942;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 3462;
|
||||
UPDATE bot_spells_entries SET `type` = 13 WHERE `spellid` = 6828;
|
||||
UPDATE bot_spells_entries SET `type` = 4 WHERE `spellid` = 14312;
|
||||
UPDATE bot_spells_entries SET `type` = 4 WHERE `spellid` = 14313;
|
||||
UPDATE bot_spells_entries SET `type` = 4 WHERE `spellid` = 14314;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 18392;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 18393;
|
||||
UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 18394;
|
||||
UPDATE bot_spells_entries SET `type` = 10 WHERE `spellid` = 15186;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 15187;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 15188;
|
||||
UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 14446;
|
||||
UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 14447;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 14467;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 14468;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 14469;
|
||||
UPDATE bot_spells_entries SET `type` = 0 WHERE `spellid` = 14267;
|
||||
UPDATE bot_spells_entries SET `type` = 0 WHERE `spellid` = 14268;
|
||||
UPDATE bot_spells_entries SET `type` = 0 WHERE `spellid` = 14269;
|
||||
UPDATE bot_spells_entries SET `type` = 10 WHERE `spellid` = 14955;
|
||||
UPDATE bot_spells_entries SET `type` = 10 WHERE `spellid` = 14956;
|
||||
UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 14387;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 14388;
|
||||
UPDATE bot_spells_entries SET `type` = 3 WHERE `spellid` = 14389;
|
||||
UPDATE bot_spells_entries SET `type` = 4 WHERE `spellid` = 10436;
|
||||
|
||||
-- UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 3440; -- Ro's Illumination [#3440] from DoT [#8] to Debuff [#14] [Should be 0]
|
||||
-- UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 303; -- Whirl till you hurl [#303] from Nuke [#0] to Debuff [#14] [Should be 0]
|
||||
-- UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 619; -- Dyn's Dizzying Draught [#619] from Nuke [#0] to Debuff [#14] [Should be 0]
|
||||
|
||||
-- UPDATE bot_spells_entries SET `type` = 14 WHERE `spellid` = 74; -- Mana Sieve [#74] from Nuke [#0] to Debuff [#14]
|
||||
-- UPDATE bot_spells_entries SET `type` = 6 WHERE `spellid` = 1686; -- Theft of Thought [#1686] from Nuke [#0] to Lifetap [#6]
|
||||
|
||||
-- UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 3694; -- Stoicism [#3694] from In-Combat Buff [#10] to Regular Heal [#1]
|
||||
-- UPDATE bot_spells_entries SET `type` = 1 WHERE `spellid` = 4899; -- Breath of Trushar [#4899] from In-Combat Buff [#10] to Regular Heal [#1]
|
||||
|
||||
-- UPDATE bot_spells_entries SET `type` = 7 WHERE `spellid` = 738; -- Selo's Consonant Chain [#738] from Slow [#13] to Snare [#7]
|
||||
-- UPDATE bot_spells_entries SET `type` = 7 WHERE `spellid` = 1751; -- Largo's Assonant Binding [#1751] from Slow [#13] to Snare [#7]
|
||||
-- UPDATE bot_spells_entries SET `type` = 8 WHERE `spellid` = 1748; -- Angstlich's Assonance [#1748] from Slow [#13] to DoT [#8]
|
||||
-- UPDATE bot_spells_entries SET `type` = 7 WHERE `spellid` = 738; -- Selo's Consonant Chain [#738] from Slow [#13] to Snare [#7]
|
||||
-- UPDATE bot_spells_entries SET `type` = 7 WHERE `spellid` = 1751; -- Largo's Assonant Binding [#1751] from Slow [#13] to Snare [#7]
|
||||
-- UPDATE bot_spells_entries SET `type` = 7 WHERE `spellid` = 738; -- Selo's Consonant Chain [#738] from Slow [#13] to Snare [#7]
|
||||
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
|
||||
@@ -415,6 +415,7 @@ namespace DatabaseSchema {
|
||||
"bot_pet_buffs",
|
||||
"bot_pet_inventories",
|
||||
"bot_pets",
|
||||
"bot_settings",
|
||||
"bot_spell_casting_chances",
|
||||
"bot_spell_settings",
|
||||
"bot_spells_entries",
|
||||
|
||||
+15
-1
@@ -142,6 +142,13 @@ namespace Logs {
|
||||
EqTime,
|
||||
Corpses,
|
||||
XTargets,
|
||||
BotSettings,
|
||||
BotPreChecks,
|
||||
BotHoldChecks,
|
||||
BotDelayChecks,
|
||||
BotThresholdChecks,
|
||||
BotSpellTypeChecks,
|
||||
TestDebug,
|
||||
MaxCategoryID /* Don't Remove this */
|
||||
};
|
||||
|
||||
@@ -242,7 +249,14 @@ namespace Logs {
|
||||
"Zoning",
|
||||
"EqTime",
|
||||
"Corpses",
|
||||
"XTargets"
|
||||
"XTargets",
|
||||
"Bot Settings",
|
||||
"Bot Pre Checks",
|
||||
"Bot Hold Checks",
|
||||
"Bot Delay Checks",
|
||||
"Bot Threshold Checks",
|
||||
"Bot Spell Type Checks",
|
||||
"Test Debug"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -844,6 +844,76 @@
|
||||
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotSettings(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotSettings))\
|
||||
OutF(LogSys, Logs::General, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotSettingsDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotSettings))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotPreChecks(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotPreChecks))\
|
||||
OutF(LogSys, Logs::General, Logs::BotPreChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotPreChecksDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotPreChecks))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotPreChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotHoldChecks(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotHoldChecks))\
|
||||
OutF(LogSys, Logs::General, Logs::BotHoldChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotHoldChecksDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotHoldChecks))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotHoldChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotDelayChecks(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotDelayChecks))\
|
||||
OutF(LogSys, Logs::General, Logs::BotDelayChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotDelayChecksDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotDelayChecks))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotDelayChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotThresholdChecks(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotThresholdChecks))\
|
||||
OutF(LogSys, Logs::General, Logs::BotThresholdChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotThresholdChecksDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotThresholdChecks))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotThresholdChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotSpellTypeChecks(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::BotSpellTypeChecks))\
|
||||
OutF(LogSys, Logs::General, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogBotSpellTypeChecksDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::BotSpellTypeChecks))\
|
||||
OutF(LogSys, Logs::Detail, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogTestDebug(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::General, Logs::TestDebug))\
|
||||
OutF(LogSys, Logs::General, Logs::TestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define LogTestDebugDetail(message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(Logs::Detail, Logs::TestDebug))\
|
||||
OutF(LogSys, Logs::Detail, Logs::TestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define Log(debug_level, log_category, message, ...) do {\
|
||||
if (LogSys.IsLogEnabled(debug_level, log_category))\
|
||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||
|
||||
@@ -64,13 +64,6 @@ public:
|
||||
int16_t poison;
|
||||
int16_t disease;
|
||||
int16_t corruption;
|
||||
uint32_t show_helm;
|
||||
uint32_t follow_distance;
|
||||
uint8_t stop_melee_level;
|
||||
int32_t expansion_bitmask;
|
||||
uint8_t enforce_spell_settings;
|
||||
uint8_t archery_setting;
|
||||
uint32_t caster_range;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -126,13 +119,6 @@ public:
|
||||
"poison",
|
||||
"disease",
|
||||
"corruption",
|
||||
"show_helm",
|
||||
"follow_distance",
|
||||
"stop_melee_level",
|
||||
"expansion_bitmask",
|
||||
"enforce_spell_settings",
|
||||
"archery_setting",
|
||||
"caster_range",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -184,13 +170,6 @@ public:
|
||||
"poison",
|
||||
"disease",
|
||||
"corruption",
|
||||
"show_helm",
|
||||
"follow_distance",
|
||||
"stop_melee_level",
|
||||
"expansion_bitmask",
|
||||
"enforce_spell_settings",
|
||||
"archery_setting",
|
||||
"caster_range",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -276,13 +255,7 @@ public:
|
||||
e.poison = 0;
|
||||
e.disease = 0;
|
||||
e.corruption = 0;
|
||||
e.show_helm = 0;
|
||||
e.follow_distance = 200;
|
||||
e.stop_melee_level = 255;
|
||||
e.expansion_bitmask = -1;
|
||||
e.enforce_spell_settings = 0;
|
||||
e.archery_setting = 0;
|
||||
e.caster_range = 300;
|
||||
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -364,13 +337,6 @@ public:
|
||||
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
|
||||
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
|
||||
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
|
||||
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
|
||||
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
|
||||
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
|
||||
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
|
||||
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -448,13 +414,6 @@ public:
|
||||
v.push_back(columns[42] + " = " + std::to_string(e.poison));
|
||||
v.push_back(columns[43] + " = " + std::to_string(e.disease));
|
||||
v.push_back(columns[44] + " = " + std::to_string(e.corruption));
|
||||
v.push_back(columns[45] + " = " + std::to_string(e.show_helm));
|
||||
v.push_back(columns[46] + " = " + std::to_string(e.follow_distance));
|
||||
v.push_back(columns[47] + " = " + std::to_string(e.stop_melee_level));
|
||||
v.push_back(columns[48] + " = " + std::to_string(e.expansion_bitmask));
|
||||
v.push_back(columns[49] + " = " + std::to_string(e.enforce_spell_settings));
|
||||
v.push_back(columns[50] + " = " + std::to_string(e.archery_setting));
|
||||
v.push_back(columns[51] + " = " + std::to_string(e.caster_range));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -521,13 +480,6 @@ public:
|
||||
v.push_back(std::to_string(e.poison));
|
||||
v.push_back(std::to_string(e.disease));
|
||||
v.push_back(std::to_string(e.corruption));
|
||||
v.push_back(std::to_string(e.show_helm));
|
||||
v.push_back(std::to_string(e.follow_distance));
|
||||
v.push_back(std::to_string(e.stop_melee_level));
|
||||
v.push_back(std::to_string(e.expansion_bitmask));
|
||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||
v.push_back(std::to_string(e.archery_setting));
|
||||
v.push_back(std::to_string(e.caster_range));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -602,13 +554,6 @@ public:
|
||||
v.push_back(std::to_string(e.poison));
|
||||
v.push_back(std::to_string(e.disease));
|
||||
v.push_back(std::to_string(e.corruption));
|
||||
v.push_back(std::to_string(e.show_helm));
|
||||
v.push_back(std::to_string(e.follow_distance));
|
||||
v.push_back(std::to_string(e.stop_melee_level));
|
||||
v.push_back(std::to_string(e.expansion_bitmask));
|
||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||
v.push_back(std::to_string(e.archery_setting));
|
||||
v.push_back(std::to_string(e.caster_range));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -687,13 +632,6 @@ public:
|
||||
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
|
||||
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
|
||||
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
|
||||
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
|
||||
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
|
||||
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
|
||||
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
|
||||
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -763,13 +701,6 @@ public:
|
||||
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
|
||||
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
|
||||
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
|
||||
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
|
||||
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
|
||||
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
|
||||
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
|
||||
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
|
||||
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
|
||||
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -889,13 +820,6 @@ public:
|
||||
v.push_back(std::to_string(e.poison));
|
||||
v.push_back(std::to_string(e.disease));
|
||||
v.push_back(std::to_string(e.corruption));
|
||||
v.push_back(std::to_string(e.show_helm));
|
||||
v.push_back(std::to_string(e.follow_distance));
|
||||
v.push_back(std::to_string(e.stop_melee_level));
|
||||
v.push_back(std::to_string(e.expansion_bitmask));
|
||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||
v.push_back(std::to_string(e.archery_setting));
|
||||
v.push_back(std::to_string(e.caster_range));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -963,13 +887,6 @@ public:
|
||||
v.push_back(std::to_string(e.poison));
|
||||
v.push_back(std::to_string(e.disease));
|
||||
v.push_back(std::to_string(e.corruption));
|
||||
v.push_back(std::to_string(e.show_helm));
|
||||
v.push_back(std::to_string(e.follow_distance));
|
||||
v.push_back(std::to_string(e.stop_melee_level));
|
||||
v.push_back(std::to_string(e.expansion_bitmask));
|
||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||
v.push_back(std::to_string(e.archery_setting));
|
||||
v.push_back(std::to_string(e.caster_range));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H
|
||||
#define EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseBotSettingsRepository {
|
||||
public:
|
||||
struct BotSettings {
|
||||
uint32_t id;
|
||||
uint32_t char_id;
|
||||
uint32_t bot_id;
|
||||
uint16_t setting_id;
|
||||
uint8_t setting_type;
|
||||
int32_t value;
|
||||
std::string category_name;
|
||||
std::string setting_name;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"bot_id",
|
||||
"setting_id",
|
||||
"setting_type",
|
||||
"value",
|
||||
"category_name",
|
||||
"setting_name",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"bot_id",
|
||||
"setting_id",
|
||||
"setting_type",
|
||||
"value",
|
||||
"category_name",
|
||||
"setting_name",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("bot_settings");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static BotSettings NewEntity()
|
||||
{
|
||||
BotSettings e{};
|
||||
|
||||
e.id = 0;
|
||||
e.char_id = 0;
|
||||
e.bot_id = 0;
|
||||
e.setting_id = 0;
|
||||
e.setting_type = 0;
|
||||
e.value = 0;
|
||||
e.category_name = "";
|
||||
e.setting_name = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static BotSettings GetBotSettings(
|
||||
const std::vector<BotSettings> &bot_settingss,
|
||||
int bot_settings_id
|
||||
)
|
||||
{
|
||||
for (auto &bot_settings : bot_settingss) {
|
||||
if (bot_settings.id == bot_settings_id) {
|
||||
return bot_settings;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static BotSettings FindOne(
|
||||
Database& db,
|
||||
int bot_settings_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
bot_settings_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
BotSettings e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.bot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.setting_id = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.setting_type = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.value = row[5] ? static_cast<int32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.category_name = row[6] ? row[6] : "";
|
||||
e.setting_name = row[7] ? row[7] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int bot_settings_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
bot_settings_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const BotSettings &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.bot_id));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.setting_id));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.setting_type));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.value));
|
||||
v.push_back(columns[6] + " = '" + Strings::Escape(e.category_name) + "'");
|
||||
v.push_back(columns[7] + " = '" + Strings::Escape(e.setting_name) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.bot_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static BotSettings InsertOne(
|
||||
Database& db,
|
||||
BotSettings e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.setting_id));
|
||||
v.push_back(std::to_string(e.setting_type));
|
||||
v.push_back(std::to_string(e.value));
|
||||
v.push_back("'" + Strings::Escape(e.category_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.setting_name) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<BotSettings> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.setting_id));
|
||||
v.push_back(std::to_string(e.setting_type));
|
||||
v.push_back(std::to_string(e.value));
|
||||
v.push_back("'" + Strings::Escape(e.category_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.setting_name) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<BotSettings> All(Database& db)
|
||||
{
|
||||
std::vector<BotSettings> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotSettings e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.bot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.setting_id = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.setting_type = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.value = row[5] ? static_cast<int32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.category_name = row[6] ? row[6] : "";
|
||||
e.setting_name = row[7] ? row[7] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<BotSettings> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<BotSettings> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotSettings e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.bot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.setting_id = row[3] ? static_cast<uint16_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.setting_type = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.value = row[5] ? static_cast<int32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.category_name = row[6] ? row[6] : "";
|
||||
e.setting_name = row[7] ? row[7] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const BotSettings &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.setting_id));
|
||||
v.push_back(std::to_string(e.setting_type));
|
||||
v.push_back(std::to_string(e.value));
|
||||
v.push_back("'" + Strings::Escape(e.category_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.setting_name) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<BotSettings> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.setting_id));
|
||||
v.push_back(std::to_string(e.setting_type));
|
||||
v.push_back(std::to_string(e.value));
|
||||
v.push_back("'" + Strings::Escape(e.category_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.setting_name) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H
|
||||
@@ -44,46 +44,6 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static bool SaveAllHelmAppearances(Database& db, const uint32 owner_id, const bool show_flag)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{}` SET `show_helm` = {} WHERE `owner_id` = {}",
|
||||
TableName(),
|
||||
show_flag ? 1 : 0,
|
||||
owner_id
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
static bool ToggleAllHelmAppearances(Database& db, const uint32 owner_id)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{}` SET `show_helm` = (`show_helm` XOR '1') WHERE `owner_id` = {}",
|
||||
TableName(),
|
||||
owner_id
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
|
||||
static bool SaveAllFollowDistances(Database& db, const uint32 owner_id, const uint32 follow_distance)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE `{}` SET `follow_distance` = {} WHERE `owner_id` = {}",
|
||||
TableName(),
|
||||
follow_distance,
|
||||
owner_id
|
||||
)
|
||||
);
|
||||
|
||||
return results.Success();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BOT_DATA_REPOSITORY_H
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_BOT_SETTINGS_REPOSITORY_H
|
||||
#define EQEMU_BOT_SETTINGS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_bot_settings_repository.h"
|
||||
|
||||
class BotSettingsRepository: public BaseBotSettingsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* BotSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* BotSettingsRepository::GetWhereNeverExpires()
|
||||
* BotSettingsRepository::GetWhereXAndY()
|
||||
* BotSettingsRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BOT_SETTINGS_REPOSITORY_H
|
||||
@@ -381,6 +381,9 @@ RULE_BOOL(Map, MobZVisualDebug, false, "Displays spell effects determining wheth
|
||||
RULE_BOOL(Map, MobPathingVisualDebug, false, "Displays nodes in pathing points in realtime to help with visual debugging")
|
||||
RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20, "At runtime in SendTo: maximum change in Z to allow the BestZ code to apply")
|
||||
RULE_INT(Map, FindBestZHeightAdjust, 1, "Adds this to the current Z before seeking the best Z position")
|
||||
RULE_BOOL(Map, CheckForLoSCheat, false, "Runs predefined zone checks to check for LoS cheating through doors and such.")
|
||||
RULE_BOOL(Map, EnableLoSCheatExemptions, false, "Enables exemptions for the LoS Cheat check.")
|
||||
RULE_REAL(Map, RangeCheckForLoSCheat, 20.0, "Default 20.0. Range to check if one is within range of a door.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Pathing)
|
||||
@@ -753,6 +756,7 @@ RULE_INT(Bots, CommandSpellRank, 1, "Filters bot command spells by rank. 1, 2 an
|
||||
RULE_INT(Bots, CreationLimit, 150, "Number of bots that each account can create")
|
||||
RULE_BOOL(Bots, FinishBuffing, false, "Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat")
|
||||
RULE_BOOL(Bots, GroupBuffing, false, "Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB")
|
||||
RULE_BOOL(Bots, RaidBuffing, false, "Bots will cast single target buffs as raid buffs, default is false for single. Does not make single target buffs work for MGB")
|
||||
RULE_INT(Bots, HealRotationMaxMembers, 24, "Maximum number of heal rotation members")
|
||||
RULE_INT(Bots, HealRotationMaxTargets, 12, "Maximum number of heal rotation targets")
|
||||
RULE_REAL(Bots, ManaRegen, 2.0, "Adjust mana regen. Acts as a final multiplier, stacks with Rule Character:ManaRegenMultiplier.")
|
||||
@@ -782,6 +786,91 @@ RULE_BOOL(Bots, CanClickMageEpicV1, true, "Whether or not bots are allowed to cl
|
||||
RULE_BOOL(Bots, BotsIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
|
||||
RULE_INT(Bots, BotsHasteCap, 100, "Haste cap for non-v3(over haste) haste")
|
||||
RULE_INT(Bots, BotsHastev3Cap, 25, "Haste cap for v3(over haste) haste")
|
||||
RULE_BOOL(Bots, CrossRaidBuffingAndHealing, true, "If True, bots will be able to cast on all raid members rather than just their raid group members. Default true.")
|
||||
RULE_BOOL(Bots, CanCastIllusionsOnPets, false, "If True, bots will be able to cast spells that have an illusion effect on pets. Default false.")
|
||||
RULE_BOOL(Bots, CanCastPetOnlyOnOthersPets, false, "If True, bots will be able to cast pet only spells on other's pets. Default false.")
|
||||
RULE_BOOL(Bots, RequirePetAffinity, true, "If True, bots will be need to have the Pet Affinity AA to allow their pets to be hit with group spells.")
|
||||
RULE_INT(Bots, SpellResistLimit, 150, "150 Default. This is the resist cap where bots will refuse to cast spells on enemies due to a high resist chance.")
|
||||
RULE_INT(Bots, StunCastChanceIfCasting, 50, "50 Default. Chance for non-Paladins to cast a stun spell if the target is casting.")
|
||||
RULE_INT(Bots, StunCastChanceNormal, 15, "15 Default. Chance for non-Paladins to cast a stun spell on the target.")
|
||||
RULE_INT(Bots, StunCastChancePaladins, 75, "75 Default. Chance for Paladins to cast a stun spell if the target is casting.")
|
||||
RULE_INT(Bots, PercentChanceToCastNuke, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastHeal, 90, "The chance for a bot to attempt to cast the given spell type in combat. Default 90%.")
|
||||
RULE_INT(Bots, PercentChanceToCastRoot, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastBuff, 90, "The chance for a bot to attempt to cast the given spell type in combat. Default 90%.")
|
||||
RULE_INT(Bots, PercentChanceToCastEscape, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastLifetap, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastSnare, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastDOT, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastDispel, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastInCombatBuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastMez, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastSlow, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastDebuff, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastCure, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastHateRedux, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastFear, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.")
|
||||
RULE_INT(Bots, PercentChanceToCastOtherType, 90, "The chance for a bot to attempt to cast the remaining spell types in combat. Default 0-%.")
|
||||
RULE_INT(Bots, MinDelayBetweenInCombatCastAttempts, 250, "The minimum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 500ms.")
|
||||
RULE_INT(Bots, MaxDelayBetweenInCombatCastAttempts, 2000, "The maximum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 2000ms.")
|
||||
RULE_INT(Bots, MinDelayBetweenOutCombatCastAttempts, 125, "The minimum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 200ms.")
|
||||
RULE_INT(Bots, MaxDelayBetweenOutCombatCastAttempts, 500, "The maximum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 500ms.")
|
||||
RULE_INT(Bots, MezChance, 35, "35 Default. Chance for a bot to attempt to Mez a target after validating it is eligible.")
|
||||
RULE_INT(Bots, AEMezChance, 35, "35 Default. Chance for a bot to attempt to AE Mez targets after validating they are eligible.")
|
||||
RULE_INT(Bots, MezSuccessDelay, 3500, "3500 (3.5 sec) Default. Delay between successful Mez attempts.")
|
||||
RULE_INT(Bots, AEMezSuccessDelay, 5000, "5000 (5 sec) Default. Delay between successful AEMez attempts.")
|
||||
RULE_INT(Bots, MezFailDelay, 2000, "2000 (2 sec) Default. Delay between failed Mez attempts.")
|
||||
RULE_INT(Bots, MezAEFailDelay, 4000, "4000 (4 sec) Default. Delay between failed AEMez attempts.")
|
||||
RULE_INT(Bots, MinGroupHealTargets, 3, "Minimum number of targets in valid range that are required for a group heal to cast. Default 3.")
|
||||
RULE_INT(Bots, MinGroupCureTargets, 3, "Minimum number of targets in valid range that are required for a cure heal to cast. Default 3.")
|
||||
RULE_INT(Bots, MinTargetsForAESpell, 3, "Minimum number of targets in valid range that are required for an AE spell to cast. Default 3.")
|
||||
RULE_INT(Bots, MinTargetsForGroupSpell, 3, "Minimum number of targets in valid range that are required for an group spell to cast. Default 3.")
|
||||
RULE_BOOL(Bots, AllowBuffingHealingFamiliars, false, "Determines if bots are allowed to buff and heal familiars. Default false.")
|
||||
RULE_BOOL(Bots, RunSpellTypeChecksOnSpawn, false, "This will run a serious of checks on spell types and output errors to LogBotSpellTypeChecks")
|
||||
RULE_BOOL(Bots, AllowMagicianEpicPet, false, "If enabled, magician bots can summon their epic pets following the rules AllowMagicianEpicPetLevel")
|
||||
RULE_INT(Bots, AllowMagicianEpicPetLevel, 50, "If AllowMagicianEpicPet is enabled, bots can start using their epic pets at this level")
|
||||
RULE_INT(Bots, RequiredMagicianEpicPetItemID, 28034, "If AllowMagicianEpicPet is enabled and this is set, bots will be required to have this item ID equipped to cast their epic. Takes in to account AllowMagicianEpicPetLevel as well. Set to 0 to disable requirement")
|
||||
RULE_STRING(Bots, EpicPetSpellName, "", "'teleport_zone' in the spell to be cast for epic pets. This must be in their spell list to cast.")
|
||||
RULE_BOOL(Bots, AllowSpellPulling, true, "If enabled bots will use a spell to pull when within range. Uses PullSpellID.")
|
||||
RULE_INT(Bots, PullSpellID, 5225, "Default 5225 - Throw Stone. Spell that will be cast to pull by bots")
|
||||
RULE_BOOL(Bots, AllowBotEquipAnyClassGear, false, "Allows Bots to wear Equipment even if their class is not valid")
|
||||
RULE_BOOL(Bots, BotArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
|
||||
RULE_BOOL(Bots, BotThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
|
||||
RULE_INT(Bots, StackSizeMin, 100, "100 Default. -1 to disable and use default max stack size. Minimum stack size to give a bot (Arrows/Throwing).")
|
||||
RULE_INT(Bots, HasOrMayGetAggroThreshold, 90, "90 Default. Percent threshold of total hate where bots will stop casting spells that generate hate if they are set to try to not pull aggro via spells.")
|
||||
RULE_BOOL(Bots, UseFlatNormalMeleeRange, false, "False Default. If true, bots melee distance will be a flat distance set by Bots:NormalMeleeRangeDistance.")
|
||||
RULE_REAL(Bots, NormalMeleeRangeDistance, 0.75, "Multiplier of the max melee range at which a bot will stand in melee combat. 0.75 Recommended, max melee for all abilities to land.")
|
||||
RULE_REAL(Bots, PercentMinMeleeDistance, 0.60, "Multiplier of the max melee range - Minimum distance from target a bot will stand while in melee combat before trying to adjust. 0.60 Recommended.")
|
||||
RULE_REAL(Bots, MaxDistanceForMelee, 20, "Maximum distance bots will stand for melee. Default 20 to allow all special attacks to land.")
|
||||
RULE_REAL(Bots, TauntNormalMeleeRangeDistance, 0.50, "Multiplier of the max melee range at which a taunting bot will stand in melee combat. 0.50 Recommended, closer than others .")
|
||||
RULE_REAL(Bots, PercentTauntMinMeleeDistance, 0.25, "Multiplier of max melee range - Minimum distance from target a taunting bot will stand while in melee combat before trying to adjust. 0.25 Recommended.")
|
||||
RULE_REAL(Bots, PercentMaxMeleeRangeDistance, 0.95, "Multiplier of the max melee range at which a bot will stand in melee combat. 0.95 Recommended, max melee while disabling special attacks/taunt.")
|
||||
RULE_REAL(Bots, PercentMinMaxMeleeRangeDistance, 0.75, "Multiplier of the closest max melee range at which a bot will stand in melee combat before trying to adjust. 0.75 Recommended, max melee while disabling special attacks/taunt.")
|
||||
RULE_BOOL(Bots, CastersStayJustOutOfMeleeRange, true, "True Default. If true, caster bots will stay just out of melee range. Otherwise they use Bots:PercentMinCasterRangeDistance.")
|
||||
RULE_REAL(Bots, PercentMinCasterRangeDistance, 0.60, "Multiplier of the closest caster range at which a bot will stand while casting before trying to adjust. 0.60 Recommended.")
|
||||
RULE_BOOL(Bots, TauntingBotsFollowTopHate, true, "True Default. If true, bots that are taunting will attempt to stick with whoever currently is top hate.")
|
||||
RULE_REAL(Bots, DistanceTauntingBotsStickMainHate, 25.00, "If TauntingBotsFollowTopHate is enabled, this is the distance bots will try to stick to whoever currently is Top Hate.")
|
||||
RULE_BOOL(Bots, DisableSpecialAbilitiesAtMaxMelee, false, "False Default. If true, when bots are at max melee distance, special abilities including taunt will be disabled.")
|
||||
RULE_INT(Bots, MinJitterTimer, 500, "Minimum ms between bot movement jitter checks.")
|
||||
RULE_INT(Bots, MaxJitterTimer, 2500, "Maximum ms between bot movement jitter checks. Set to 0 to disable timer checks.")
|
||||
RULE_BOOL(Bots, PreventBotCampOnFD, true, "True Default. If true, players will not be able to camp bots while feign death.")
|
||||
RULE_BOOL(Bots, PreventBotSpawnOnFD, true, "True Default. If true, players will not be able to spawn bots while feign death.")
|
||||
RULE_BOOL(Bots, PreventBotSpawnOnEngaged, true, "True Default. If true, players will not be able to spawn bots while you, your group or raid are engaged.")
|
||||
RULE_BOOL(Bots, PreventBotCampOnEngaged, true, "True Default. If true, players will not be able to camp bots while you, your group or raid are engaged.")
|
||||
RULE_BOOL(Bots, CopySettingsOwnBotsOnly, true, "Determines whether a bot you are copying settings from must be a bot you own or not, default true.")
|
||||
RULE_BOOL(Bots, AllowCopySettingsAnon, true, "If player's are allowed to copy settings of bots owned by anonymous players.")
|
||||
RULE_BOOL(Bots, AllowCharmedPetBuffs, true, "Whether or not bots are allowed to cast buff charmed pets, default true.")
|
||||
RULE_BOOL(Bots, AllowCharmedPetHeals, true, "Whether or not bots are allowed to cast heal charmed pets, default true.")
|
||||
RULE_BOOL(Bots, AllowCharmedPetCures, true, "Whether or not bots are allowed to cast cure charmed pets, default true.")
|
||||
RULE_BOOL(Bots, ShowResistMessagesToOwner, true, "Default True. If enabled, when a bot's spell is resisted it will send a spell failure to their owner.")
|
||||
RULE_BOOL(Bots, BotBuffLevelRestrictions, true, "Buffs will not land on low level bots like live players")
|
||||
RULE_BOOL(Bots, BotsUseLiveBlockedMessage, false, "Setting whether detailed spell block messages should be used for bots as players do on the live servers")
|
||||
RULE_BOOL(Bots, BotSoftDeletes, true, "When bots are deleted, they are only soft deleted")
|
||||
RULE_INT(Bots, MinStatusToBypassSpawnLimit, 100, "Minimum status to bypass the anti-spam system")
|
||||
RULE_INT(Bots, StatusSpawnLimit, 120, "Minimum status to bypass spawn limit. Default 120.")
|
||||
RULE_INT(Bots, MinStatusToBypassCreateLimit, 100, "Minimum status to bypass the anti-spam system")
|
||||
RULE_INT(Bots, StatusCreateLimit, 120, "Minimum status to bypass spawn limit. Default 120.")
|
||||
RULE_BOOL(Bots, BardsAnnounceCasts, false, "This determines whether or not Bard bots will announce that they're casting songs (Buffs, Heals, Nukes, Slows, etc.) they will always announce Mez.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Chat)
|
||||
@@ -1007,6 +1096,30 @@ RULE_CATEGORY_END()
|
||||
RULE_CATEGORY(Command)
|
||||
RULE_BOOL(Command, DyeCommandRequiresDyes, false, "Enable this to require a Prismatic Dye (32557) each time someone uses #dye.")
|
||||
RULE_BOOL(Command, HideMeCommandDisablesTells, true, "Disable this to allow tells to be received when using #hideme.")
|
||||
RULE_INT(Command, MaxHelpLineLength, 53, "Maximum length of a line before splitting it in to new lines for DiaWind. Default 53.")
|
||||
RULE_STRING(Command, DescriptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, DescriptionHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, AltDescriptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, NoteColor, "dark_orange", "Color for command help windows")
|
||||
RULE_STRING(Command, NoteHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, AltNoteColor, "dark_orange", "Color for command help windows")
|
||||
RULE_STRING(Command, ExampleColor, "goldenrod", "Color for command help windows")
|
||||
RULE_STRING(Command, ExampleHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, SubExampleColor, "slate_blue", "Color for command help windows")
|
||||
RULE_STRING(Command, AltExampleColor, "goldenrod", "Color for command help windows")
|
||||
RULE_STRING(Command, SubAltExampleColor, "goldenrod", "Color for command help windows")
|
||||
RULE_STRING(Command, OptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, OptionHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, SubOptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, AltOptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, SubAltOptionColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, ActionableColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, ActionableHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, AltActionableColor, "light_grey", "Color for command help windows")
|
||||
RULE_STRING(Command, HeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, SecondaryHeaderColor, "slate_blue", "Color for command help windows")
|
||||
RULE_STRING(Command, AltHeaderColor, "indian_red", "Color for command help windows")
|
||||
RULE_STRING(Command, FillerLineColor, "dark_grey", "Color for command help windows")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Doors)
|
||||
|
||||
+770
-25
@@ -125,9 +125,26 @@ bool IsMesmerizeSpell(uint16 spell_id)
|
||||
return IsEffectInSpell(spell_id, SE_Mez);
|
||||
}
|
||||
|
||||
bool SpellBreaksMez(uint16 spell_id)
|
||||
{
|
||||
if (IsDetrimentalSpell(spell_id) && IsAnyDamageSpell(spell_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsStunSpell(uint16 spell_id)
|
||||
{
|
||||
return IsEffectInSpell(spell_id, SE_Stun);
|
||||
if (IsEffectInSpell(spell_id, SE_Stun)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsEffectInSpell(spell_id, SE_SpinTarget)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSummonSpell(uint16 spell_id)
|
||||
@@ -164,13 +181,7 @@ bool IsDamageSpell(uint16 spell_id)
|
||||
const auto effect_id = spell.effect_id[i];
|
||||
if (
|
||||
spell.base_value[i] < 0 &&
|
||||
(
|
||||
effect_id == SE_CurrentHPOnce ||
|
||||
(
|
||||
effect_id == SE_CurrentHP &&
|
||||
spell.buff_duration < 1
|
||||
)
|
||||
)
|
||||
(effect_id == SE_CurrentHPOnce || effect_id == SE_CurrentHP)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -179,6 +190,62 @@ bool IsDamageSpell(uint16 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAnyDamageSpell(uint16 spell_id)
|
||||
{
|
||||
if (IsLifetapSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
const auto effect_id = spell.effect_id[i];
|
||||
if (
|
||||
spell.base_value[i] < 0 &&
|
||||
(
|
||||
effect_id == SE_CurrentHPOnce ||
|
||||
(
|
||||
effect_id == SE_CurrentHP &&
|
||||
spell.buff_duration < 1
|
||||
)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsDamageOverTimeSpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsLifetapSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
if (spell.good_effect || !spell.buff_duration_formula) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
const auto effect_id = spell.effect_id[i];
|
||||
if (
|
||||
spell.base_value[i] < 0 &&
|
||||
effect_id == SE_CurrentHP &&
|
||||
spell.buff_duration > 1
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFearSpell(uint16 spell_id)
|
||||
{
|
||||
@@ -409,7 +476,8 @@ bool IsSummonPetSpell(uint16 spell_id)
|
||||
return (
|
||||
IsEffectInSpell(spell_id, SE_SummonPet) ||
|
||||
IsEffectInSpell(spell_id, SE_SummonBSTPet) ||
|
||||
IsEffectInSpell(spell_id, SE_Familiar)
|
||||
IsEffectInSpell(spell_id, SE_Familiar) ||
|
||||
IsEffectInSpell(spell_id, SE_NecPet)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -560,12 +628,11 @@ bool IsPBAENukeSpell(uint16 spell_id)
|
||||
|
||||
if (
|
||||
IsPureNukeSpell(spell_id) &&
|
||||
spell.aoe_range > 0 &&
|
||||
spell.target_type == ST_AECaster
|
||||
!IsTargetRequiredForSpell(spell_id)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -588,6 +655,137 @@ bool IsAERainNukeSpell(uint16 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAnyNukeOrStunSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsSelfConversionSpell(spell_id) || IsEscapeSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
IsPBAENukeSpell(spell_id) ||
|
||||
IsAERainNukeSpell(spell_id) ||
|
||||
IsPureNukeSpell(spell_id) ||
|
||||
IsStunSpell(spell_id) ||
|
||||
(IsDamageSpell(spell_id) && !IsDamageOverTimeSpell(spell_id))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAnyAESpell(uint16 spell_id) {
|
||||
//if (
|
||||
// spells[spell_id].target_type == ST_Target ||
|
||||
// spells[spell_id].target_type == ST_Self ||
|
||||
// spells[spell_id].target_type == ST_Animal ||
|
||||
// spells[spell_id].target_type == ST_Undead ||
|
||||
// spells[spell_id].target_type == ST_Summoned ||
|
||||
// spells[spell_id].target_type == ST_Tap ||
|
||||
// spells[spell_id].target_type == ST_Pet ||
|
||||
// spells[spell_id].target_type == ST_Corpse ||
|
||||
// spells[spell_id].target_type == ST_Plant ||
|
||||
// spells[spell_id].target_type == ST_Giant ||
|
||||
// spells[spell_id].target_type == ST_Dragon ||
|
||||
// spells[spell_id].target_type == ST_HateList ||
|
||||
// spells[spell_id].target_type == ST_LDoNChest_Cursed ||
|
||||
// spells[spell_id].target_type == ST_Muramite ||
|
||||
// spells[spell_id].target_type == ST_SummonedPet ||
|
||||
// spells[spell_id].target_type == ST_TargetsTarget ||
|
||||
// spells[spell_id].target_type == ST_PetMaster //||
|
||||
// //spells[spell_id].target_type == ST_AEBard //TODO needed?
|
||||
//) {
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (IsAESpell(spell_id) || IsPBAENukeSpell(spell_id) || IsPBAESpell(spell_id) || IsAERainSpell(spell_id) || IsAERainNukeSpell(spell_id) || IsAEDurationSpell(spell_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAESpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (spells[spell_id].target_type) {
|
||||
case ST_TargetOptional:
|
||||
case ST_GroupTeleport :
|
||||
case ST_Target:
|
||||
case ST_Self:
|
||||
case ST_Animal:
|
||||
case ST_Undead:
|
||||
case ST_Summoned:
|
||||
case ST_Tap:
|
||||
case ST_Pet:
|
||||
case ST_Corpse:
|
||||
case ST_Plant:
|
||||
case ST_Giant:
|
||||
case ST_Dragon:
|
||||
case ST_LDoNChest_Cursed:
|
||||
case ST_Muramite:
|
||||
case ST_SummonedPet:
|
||||
case ST_GroupNoPets:
|
||||
case ST_Group:
|
||||
case ST_GroupClientAndPet:
|
||||
case ST_TargetsTarget:
|
||||
case ST_PetMaster:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
spells[spell_id].aoe_range > 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsPBAESpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
if (
|
||||
spell.aoe_range > 0 &&
|
||||
spell.target_type == ST_AECaster
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAERainSpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& spell = spells[spell_id];
|
||||
|
||||
if (
|
||||
spell.aoe_range > 0 &&
|
||||
spell.aoe_duration > 1000
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsPartialResistableSpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
@@ -644,7 +842,9 @@ bool IsGroupSpell(uint16 spell_id)
|
||||
return (
|
||||
spell.target_type == ST_AEBard ||
|
||||
spell.target_type == ST_Group ||
|
||||
spell.target_type == ST_GroupTeleport
|
||||
spell.target_type == ST_GroupTeleport ||
|
||||
spell.target_type == ST_GroupNoPets ||
|
||||
spell.target_type == ST_GroupClientAndPet
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1265,6 +1465,7 @@ bool IsCompleteHealSpell(uint16 spell_id)
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool IsFastHealSpell(uint16 spell_id)
|
||||
@@ -1386,20 +1587,61 @@ bool IsRegularSingleTargetHealSpell(uint16 spell_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsRegularGroupHealSpell(uint16 spell_id)
|
||||
bool IsRegularPetHealSpell(uint16 spell_id)
|
||||
{
|
||||
spell_id = (
|
||||
IsEffectInSpell(spell_id, SE_CurrentHP) ?
|
||||
spell_id :
|
||||
GetSpellTriggerSpellID(spell_id, SE_CurrentHP)
|
||||
);
|
||||
);
|
||||
|
||||
if (!spell_id) {
|
||||
spell_id = (
|
||||
IsEffectInSpell(spell_id, SE_CurrentHPOnce) ?
|
||||
spell_id :
|
||||
GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce)
|
||||
);
|
||||
}
|
||||
|
||||
if (spell_id) {
|
||||
if (
|
||||
spells[spell_id].target_type == ST_Pet &&
|
||||
!IsCompleteHealSpell(spell_id) &&
|
||||
!IsHealOverTimeSpell(spell_id) &&
|
||||
!IsGroupSpell(spell_id)
|
||||
) {
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if (
|
||||
spells[spell_id].base_value[i] > 0 &&
|
||||
spells[spell_id].buff_duration == 0 &&
|
||||
(
|
||||
spells[spell_id].effect_id[i] == SE_CurrentHP ||
|
||||
spells[spell_id].effect_id[i] == SE_CurrentHPOnce
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsRegularGroupHealSpell(uint16 spell_id)
|
||||
{
|
||||
spell_id = (
|
||||
IsEffectInSpell(spell_id, SE_CurrentHP) ?
|
||||
spell_id :
|
||||
GetSpellTriggerSpellID(spell_id, SE_CurrentHP)
|
||||
);
|
||||
|
||||
if (!spell_id) {
|
||||
spell_id = (
|
||||
IsEffectInSpell(spell_id, SE_CurrentHPOnce) ?
|
||||
spell_id :
|
||||
GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce)
|
||||
);
|
||||
}
|
||||
|
||||
if (spell_id) {
|
||||
@@ -1415,8 +1657,8 @@ bool IsRegularGroupHealSpell(uint16 spell_id)
|
||||
(
|
||||
spells[spell_id].effect_id[i] == SE_CurrentHP ||
|
||||
spells[spell_id].effect_id[i] == SE_CurrentHPOnce
|
||||
)
|
||||
) {
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1429,9 +1671,14 @@ bool IsRegularGroupHealSpell(uint16 spell_id)
|
||||
bool IsGroupCompleteHealSpell(uint16 spell_id)
|
||||
{
|
||||
if (
|
||||
IsGroupSpell(spell_id) &&
|
||||
IsCompleteHealSpell(spell_id)
|
||||
) {
|
||||
(
|
||||
spell_id == SPELL_COMPLETE_HEAL ||
|
||||
IsEffectInSpell(spell_id, SE_CompleteHeal) ||
|
||||
IsPercentalHealSpell(spell_id) ||
|
||||
GetSpellTriggerSpellID(spell_id, SE_CompleteHeal)
|
||||
) &&
|
||||
IsGroupSpell(spell_id)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1441,9 +1688,92 @@ bool IsGroupCompleteHealSpell(uint16 spell_id)
|
||||
bool IsGroupHealOverTimeSpell(uint16 spell_id)
|
||||
{
|
||||
if (
|
||||
IsGroupSpell(spell_id) &&
|
||||
IsHealOverTimeSpell(spell_id) &&
|
||||
spells[spell_id].buff_duration < 10
|
||||
(
|
||||
IsEffectInSpell(spell_id, SE_HealOverTime) ||
|
||||
GetSpellTriggerSpellID(spell_id, SE_HealOverTime)
|
||||
) &&
|
||||
IsGroupSpell(spell_id)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAnyHealSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spell_id == SPELL_NATURES_RECOVERY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//spell_id != SPELL_ADRENALINE_SWELL &&
|
||||
//spell_id != SPELL_ADRENALINE_SWELL_RK2 &&
|
||||
//spell_id != SPELL_ADRENALINE_SWELL_RK3 &&
|
||||
if (
|
||||
IsHealOverTimeSpell(spell_id) ||
|
||||
IsGroupHealOverTimeSpell(spell_id) ||
|
||||
IsFastHealSpell(spell_id) ||
|
||||
IsVeryFastHealSpell(spell_id) ||
|
||||
IsRegularSingleTargetHealSpell(spell_id) ||
|
||||
IsRegularGroupHealSpell(spell_id) ||
|
||||
IsCompleteHealSpell(spell_id) ||
|
||||
IsGroupCompleteHealSpell(spell_id) ||
|
||||
IsRegularPetHealSpell(spell_id)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAnyBuffSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
spell_id == SPELL_NATURES_RECOVERY ||
|
||||
IsBuffSpell(spell_id) &&
|
||||
IsBeneficialSpell(spell_id) &&
|
||||
!IsBardSong(spell_id) &&
|
||||
!IsEscapeSpell(spell_id) &&
|
||||
(!IsSummonPetSpell(spell_id) && !IsEffectInSpell(spell_id, SE_TemporaryPets))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool IsDispelSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
IsEffectInSpell(spell_id, SE_CancelMagic) ||
|
||||
IsEffectInSpell(spell_id, SE_DispelBeneficial) ||
|
||||
IsEffectInSpell(spell_id, SE_DispelBeneficial)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsEscapeSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
IsInvulnerabilitySpell(spell_id) ||
|
||||
IsEffectInSpell(spell_id, SE_FeignDeath) ||
|
||||
IsEffectInSpell(spell_id, SE_DeathSave) ||
|
||||
IsEffectInSpell(spell_id, SE_Destroy) ||
|
||||
(IsEffectInSpell(spell_id, SE_WipeHateList) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_WipeHateList)] > 0)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -1464,7 +1794,8 @@ bool IsDebuffSpell(uint16 spell_id)
|
||||
IsEffectInSpell(spell_id, SE_CancelMagic) ||
|
||||
IsEffectInSpell(spell_id, SE_MovementSpeed) ||
|
||||
IsFearSpell(spell_id) ||
|
||||
IsEffectInSpell(spell_id, SE_InstantHate)
|
||||
IsEffectInSpell(spell_id, SE_InstantHate) ||
|
||||
IsEffectInSpell(spell_id, SE_TossUp)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -1472,6 +1803,22 @@ bool IsDebuffSpell(uint16 spell_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsHateReduxSpell(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
(IsEffectInSpell(spell_id, SE_InstantHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] < 0) ||
|
||||
(IsEffectInSpell(spell_id, SE_Hate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] < 0) ||
|
||||
(IsEffectInSpell(spell_id, SE_ReduceHate) && spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_ReduceHate)] < 0)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsResistDebuffSpell(uint16 spell_id)
|
||||
{
|
||||
if (
|
||||
@@ -2383,7 +2730,7 @@ bool AegolismStackingIsSymbolSpell(uint16 spell_id) {
|
||||
|
||||
if ((i < 2 && spells[spell_id].effect_id[i] != SE_CHA) ||
|
||||
i > 3 && spells[spell_id].effect_id[i] != SE_Blank) {
|
||||
return 0;;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i == 2 && spells[spell_id].effect_id[i] == SE_TotalHP) {
|
||||
@@ -2430,3 +2777,401 @@ bool AegolismStackingIsArmorClassSpell(uint16 spell_id) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8 SpellEffectsCount(uint16 spell_id) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
int8 i = 0;
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if (!IsBlankSpellEffect(spell_id, i)) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
bool IsLichSpell(uint16 spell_id)
|
||||
{
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
GetSpellTargetType(spell_id) == ST_Self &&
|
||||
IsEffectInSpell(spell_id, SE_CurrentMana) &&
|
||||
IsEffectInSpell(spell_id, SE_CurrentHP) &&
|
||||
spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentMana)] > 0 &&
|
||||
spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentHP)] < 0 &&
|
||||
spells[spell_id].buff_duration > 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BOT_SPELL_TYPES_DETRIMENTAL(uint16 spellType, uint8 cls) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::Lifetap:
|
||||
case BotSpellTypes::Snare:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::Mez:
|
||||
case BotSpellTypes::Charm:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::HateRedux:
|
||||
case BotSpellTypes::Fear:
|
||||
case BotSpellTypes::Stun:
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::AEMez:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
return true;
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
if (cls == Class::ShadowKnight) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BOT_SPELL_TYPES_BENEFICIAL(uint16 spellType, uint8 cls) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
case BotSpellTypes::Buff:
|
||||
case BotSpellTypes::Cure:
|
||||
case BotSpellTypes::GroupCures:
|
||||
case BotSpellTypes::DamageShields:
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
case BotSpellTypes::Pet:
|
||||
case BotSpellTypes::PetBuffs:
|
||||
case BotSpellTypes::PreCombatBuff:
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
case BotSpellTypes::Resurrect:
|
||||
return true;
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
if (cls == Class::ShadowKnight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BOT_SPELL_TYPES_OTHER_BENEFICIAL(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
case BotSpellTypes::Buff:
|
||||
case BotSpellTypes::Cure:
|
||||
case BotSpellTypes::GroupCures:
|
||||
case BotSpellTypes::DamageShields:
|
||||
case BotSpellTypes::PetBuffs:
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BOT_SPELL_TYPES_INNATE(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::Charm:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::Lifetap:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::Stun:
|
||||
case BotSpellTypes::AEMez:
|
||||
case BotSpellTypes::Mez:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsBotSpellType(uint16 spellType) {
|
||||
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType) && BOT_SPELL_TYPES_BENEFICIAL(spellType) && BOT_SPELL_TYPES_INNATE(spellType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAEBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::AEMez:
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::AERoot:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsGroupBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::GroupCures:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsGroupTargetOnlyBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::GroupCures:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsPetBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::PetBuffs:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsClientBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
case BotSpellTypes::Buff:
|
||||
case BotSpellTypes::Cure:
|
||||
case BotSpellTypes::GroupCures:
|
||||
case BotSpellTypes::DamageShields:
|
||||
case BotSpellTypes::PetBuffs:
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsHealBotSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls) {
|
||||
if (IsAEBotSpellType(spellType)) { // These gather their own targets later
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
return false;
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
if (cls && cls == Class::ShadowKnight) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Escape:
|
||||
if (cls == Class::ShadowKnight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
case BotSpellTypes::Pet:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValidSpellAndLoS(uint32 spell_id, bool hasLoS) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasLoS && IsTargetRequiredForSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsInstantHealSpell(uint32 spell_id) {
|
||||
if (IsRegularSingleTargetHealSpell(spell_id) || IsRegularGroupHealSpell(spell_id) || IsRegularPetHealSpell(spell_id) || IsRegularGroupHealSpell(spell_id) || spell_id == SPELL_COMPLETE_HEAL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsResurrectSpell(uint16 spell_id)
|
||||
{
|
||||
return IsEffectInSpell(spell_id, SE_Revive);
|
||||
}
|
||||
|
||||
bool RequiresStackCheck(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+97
-3
@@ -213,6 +213,10 @@
|
||||
#define SPELL_BLOODTHIRST 8476
|
||||
#define SPELL_AMPLIFICATION 2603
|
||||
#define SPELL_DIVINE_REZ 2738
|
||||
#define SPELL_NATURES_RECOVERY 2520
|
||||
#define SPELL_ADRENALINE_SWELL 14445
|
||||
#define SPELL_ADRENALINE_SWELL_RK2 14446
|
||||
#define SPELL_ADRENALINE_SWELL_RK3 14447
|
||||
|
||||
// discipline IDs.
|
||||
#define DISC_UNHOLY_AURA 4520
|
||||
@@ -647,14 +651,84 @@ enum SpellTypes : uint32
|
||||
SpellType_PreCombatBuffSong = (1 << 21)
|
||||
};
|
||||
|
||||
const uint32 SPELL_TYPE_MIN = (SpellType_Nuke << 1) - 1;
|
||||
const uint32 SPELL_TYPE_MAX = (SpellType_PreCombatBuffSong << 1) - 1;
|
||||
const uint32 SPELL_TYPE_ANY = 0xFFFFFFFF;
|
||||
namespace BotSpellTypes
|
||||
{
|
||||
constexpr uint16 Nuke = 0;
|
||||
constexpr uint16 RegularHeal = 1;
|
||||
constexpr uint16 Root = 2;
|
||||
constexpr uint16 Buff = 3;
|
||||
constexpr uint16 Escape = 4;
|
||||
constexpr uint16 Pet = 5;
|
||||
constexpr uint16 Lifetap = 6;
|
||||
constexpr uint16 Snare = 7;
|
||||
constexpr uint16 DOT = 8;
|
||||
constexpr uint16 Dispel = 9;
|
||||
constexpr uint16 InCombatBuff = 10;
|
||||
constexpr uint16 Mez = 11;
|
||||
constexpr uint16 Charm = 12;
|
||||
constexpr uint16 Slow = 13;
|
||||
constexpr uint16 Debuff = 14;
|
||||
constexpr uint16 Cure = 15;
|
||||
constexpr uint16 Resurrect = 16;
|
||||
constexpr uint16 HateRedux = 17;
|
||||
constexpr uint16 InCombatBuffSong = 18;
|
||||
constexpr uint16 OutOfCombatBuffSong = 19;
|
||||
constexpr uint16 PreCombatBuff = 20;
|
||||
constexpr uint16 PreCombatBuffSong = 21;
|
||||
constexpr uint16 Fear = 22;
|
||||
constexpr uint16 Stun = 23;
|
||||
constexpr uint16 GroupCures = 24;
|
||||
constexpr uint16 CompleteHeal = 25;
|
||||
constexpr uint16 FastHeals = 26;
|
||||
constexpr uint16 VeryFastHeals = 27;
|
||||
constexpr uint16 GroupHeals = 28;
|
||||
constexpr uint16 GroupCompleteHeals = 29;
|
||||
constexpr uint16 GroupHoTHeals = 30;
|
||||
constexpr uint16 HoTHeals = 31;
|
||||
constexpr uint16 AENukes = 32;
|
||||
constexpr uint16 AERains = 33;
|
||||
constexpr uint16 AEMez = 34;
|
||||
constexpr uint16 AEStun = 35;
|
||||
constexpr uint16 AEDebuff = 36;
|
||||
constexpr uint16 AESlow = 37;
|
||||
constexpr uint16 AESnare = 38;
|
||||
constexpr uint16 AEFear = 39;
|
||||
constexpr uint16 AEDispel = 40;
|
||||
constexpr uint16 AERoot = 41;
|
||||
constexpr uint16 AEDoT = 42;
|
||||
constexpr uint16 AELifetap = 43;
|
||||
constexpr uint16 PBAENuke = 44;
|
||||
constexpr uint16 PetBuffs = 45;
|
||||
constexpr uint16 PetRegularHeals = 46;
|
||||
constexpr uint16 PetCompleteHeals = 47;
|
||||
constexpr uint16 PetFastHeals = 48;
|
||||
constexpr uint16 PetVeryFastHeals = 49;
|
||||
constexpr uint16 PetHoTHeals = 50;
|
||||
constexpr uint16 DamageShields = 51;
|
||||
constexpr uint16 ResistBuffs = 52;
|
||||
|
||||
constexpr uint16 START = BotSpellTypes::Nuke; // Do not remove or change this
|
||||
constexpr uint16 END = BotSpellTypes::ResistBuffs; // Do not remove this, increment as needed
|
||||
}
|
||||
|
||||
const uint32 SPELL_TYPES_DETRIMENTAL = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow);
|
||||
const uint32 SPELL_TYPES_BENEFICIAL = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong | SpellType_PreCombatBuff | SpellType_PreCombatBuffSong);
|
||||
const uint32 SPELL_TYPES_INNATE = (SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root);
|
||||
|
||||
bool BOT_SPELL_TYPES_DETRIMENTAL (uint16 spellType, uint8 cls = 0);
|
||||
bool BOT_SPELL_TYPES_BENEFICIAL (uint16 spellType, uint8 cls = 0);
|
||||
bool BOT_SPELL_TYPES_OTHER_BENEFICIAL(uint16 spellType);
|
||||
bool BOT_SPELL_TYPES_INNATE (uint16 spellType);
|
||||
bool IsBotSpellType (uint16 spellType);
|
||||
bool IsAEBotSpellType(uint16 spellType);
|
||||
bool IsGroupBotSpellType(uint16 spellType);
|
||||
bool IsGroupTargetOnlyBotSpellType(uint16 spellType);
|
||||
bool IsPetBotSpellType(uint16 spellType);
|
||||
bool IsClientBotSpellType(uint16 spellType);
|
||||
bool IsHealBotSpellType(uint16 spellType);
|
||||
bool SpellTypeRequiresLoS(uint16 spellType, uint16 cls = 0);
|
||||
bool SpellTypeRequiresTarget(uint16 spellType, uint16 cls = 0);
|
||||
|
||||
// These should not be used to determine spell category..
|
||||
// They are a graphical affects (effects?) index only
|
||||
// TODO: import sai list
|
||||
@@ -1503,6 +1577,7 @@ bool IsTargetableAESpell(uint16 spell_id);
|
||||
bool IsSacrificeSpell(uint16 spell_id);
|
||||
bool IsLifetapSpell(uint16 spell_id);
|
||||
bool IsMesmerizeSpell(uint16 spell_id);
|
||||
bool SpellBreaksMez(uint16 spell_id);
|
||||
bool IsStunSpell(uint16 spell_id);
|
||||
bool IsSlowSpell(uint16 spell_id);
|
||||
bool IsHasteSpell(uint16 spell_id);
|
||||
@@ -1536,6 +1611,11 @@ bool IsPureNukeSpell(uint16 spell_id);
|
||||
bool IsAENukeSpell(uint16 spell_id);
|
||||
bool IsPBAENukeSpell(uint16 spell_id);
|
||||
bool IsAERainNukeSpell(uint16 spell_id);
|
||||
bool IsAnyNukeOrStunSpell(uint16 spell_id);
|
||||
bool IsAnyAESpell(uint16 spell_id);
|
||||
bool IsAESpell(uint16 spell_id);
|
||||
bool IsPBAESpell(uint16 spell_id);
|
||||
bool IsAERainSpell(uint16 spell_id);
|
||||
bool IsPartialResistableSpell(uint16 spell_id);
|
||||
bool IsResistableSpell(uint16 spell_id);
|
||||
bool IsGroupSpell(uint16 spell_id);
|
||||
@@ -1545,8 +1625,11 @@ bool IsEffectInSpell(uint16 spell_id, int effect_id);
|
||||
uint16 GetSpellTriggerSpellID(uint16 spell_id, int effect_id);
|
||||
bool IsBlankSpellEffect(uint16 spell_id, int effect_index);
|
||||
bool IsValidSpell(uint32 spell_id);
|
||||
bool IsValidSpellAndLoS(uint32 spell_id, bool hasLoS = true);
|
||||
bool IsSummonSpell(uint16 spell_id);
|
||||
bool IsDamageSpell(uint16 spell_id);
|
||||
bool IsAnyDamageSpell(uint16 spell_id);
|
||||
bool IsDamageOverTimeSpell(uint16 spell_i);
|
||||
bool IsFearSpell(uint16 spell_id);
|
||||
bool IsCureSpell(uint16 spell_id);
|
||||
bool IsHarmTouchSpell(uint16 spell_id);
|
||||
@@ -1585,10 +1668,16 @@ bool IsCompleteHealSpell(uint16 spell_id);
|
||||
bool IsFastHealSpell(uint16 spell_id);
|
||||
bool IsVeryFastHealSpell(uint16 spell_id);
|
||||
bool IsRegularSingleTargetHealSpell(uint16 spell_id);
|
||||
bool IsRegularPetHealSpell(uint16 spell_id);
|
||||
bool IsRegularGroupHealSpell(uint16 spell_id);
|
||||
bool IsGroupCompleteHealSpell(uint16 spell_id);
|
||||
bool IsGroupHealOverTimeSpell(uint16 spell_id);
|
||||
bool IsAnyHealSpell(uint16 spell_id);
|
||||
bool IsAnyBuffSpell(uint16 spell_id);
|
||||
bool IsDispelSpell(uint16 spell_id);
|
||||
bool IsEscapeSpell(uint16 spell_id);
|
||||
bool IsDebuffSpell(uint16 spell_id);
|
||||
bool IsHateReduxSpell(uint16 spell_id);
|
||||
bool IsResistDebuffSpell(uint16 spell_id);
|
||||
bool IsSelfConversionSpell(uint16 spell_id);
|
||||
bool IsBuffSpell(uint16 spell_id);
|
||||
@@ -1628,5 +1717,10 @@ bool IsCastRestrictedSpell(uint16 spell_id);
|
||||
bool IsAegolismSpell(uint16 spell_id);
|
||||
bool AegolismStackingIsSymbolSpell(uint16 spell_id);
|
||||
bool AegolismStackingIsArmorClassSpell(uint16 spell_id);
|
||||
int8 SpellEffectsCount(uint16 spell_id);
|
||||
bool IsLichSpell(uint16 spell_id);
|
||||
bool IsInstantHealSpell(uint32 spell_id);
|
||||
bool IsResurrectSpell(uint16 spell_id);
|
||||
bool RequiresStackCheck(uint16 spellType);
|
||||
|
||||
#endif
|
||||
|
||||
+119
@@ -1278,6 +1278,39 @@ bool Mob::CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarge
|
||||
return zone->zonemap->CheckLoS(posWatcher, posTarget);
|
||||
}
|
||||
|
||||
bool Mob::CheckPositioningLosFN(Mob* other, float posX, float posY, float posZ) {
|
||||
if (zone->zonemap == nullptr) {
|
||||
//not sure what the best return is on error
|
||||
//should make this a database variable, but im lazy today
|
||||
#ifdef LOS_DEFAULT_CAN_SEE
|
||||
return(true);
|
||||
#else
|
||||
return(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!other) {
|
||||
return(true);
|
||||
}
|
||||
glm::vec3 myloc;
|
||||
glm::vec3 oloc;
|
||||
|
||||
#define LOS_DEFAULT_HEIGHT 6.0f
|
||||
|
||||
oloc.x = other->GetX();
|
||||
oloc.y = other->GetY();
|
||||
oloc.z = other->GetZ() + (other->GetSize() == 0.0 ? LOS_DEFAULT_HEIGHT : other->GetSize()) / 2 * SEE_POSITION;
|
||||
|
||||
myloc.x = posX;
|
||||
myloc.y = posY;
|
||||
myloc.z = posZ + (GetSize() == 0.0 ? LOS_DEFAULT_HEIGHT : GetSize()) / 2 * HEAD_POSITION;
|
||||
|
||||
#if LOSDEBUG>=5
|
||||
LogDebug("LOS from ([{}], [{}], [{}]) to ([{}], [{}], [{}]) sizes: ([{}], [{}])", myloc.x, myloc.y, myloc.z, oloc.x, oloc.y, oloc.z, GetSize(), mobSize);
|
||||
#endif
|
||||
return zone->zonemap->CheckLoS(myloc, oloc);
|
||||
}
|
||||
|
||||
//offensive spell aggro
|
||||
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool is_proc)
|
||||
{
|
||||
@@ -1659,3 +1692,89 @@ void Mob::RogueEvade(Mob *other)
|
||||
return;
|
||||
}
|
||||
|
||||
bool Mob::DoLosChecks(Mob* who, Mob* other) {
|
||||
if (!who->CheckLosFN(other) || !who->CheckWaterLoS(other)) {
|
||||
if (who->CheckLosCheatExempt(who, other)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CheckLosCheat(who, other)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Mob::CheckLosCheat(Mob* who, Mob* other) {
|
||||
if (RuleB(Map, CheckForLoSCheat)) {
|
||||
auto& door_list = entity_list.GetDoorsList();
|
||||
for (auto itr : door_list) {
|
||||
Doors* door = itr.second;
|
||||
if (door && !door->IsDoorOpen() && (door->GetTriggerType() == 255 || door->GetLockpick() != 0 || door->GetKeyItem() != 0 || door->GetNoKeyring() != 0)) {
|
||||
if (DistanceNoZ(who->GetPosition(), door->GetPosition()) <= 50) {
|
||||
auto who_to_door = DistanceNoZ(who->GetPosition(), door->GetPosition());
|
||||
auto other_to_door = DistanceNoZ(other->GetPosition(), door->GetPosition());
|
||||
auto who_to_other = DistanceNoZ(who->GetPosition(), other->GetPosition());
|
||||
auto distance_difference = who_to_other - (who_to_door + other_to_door);
|
||||
if (distance_difference >= (-1 * RuleR(Maps, RangeCheckForLoSCheat)) && distance_difference <= RuleR(Maps, RangeCheckForLoSCheat)) {
|
||||
LogTestDebug("CheckLosCheat failed at Door [{}], TriggerType [{}], GetLockpick [{}], GetKeyItem [{}], GetNoKeyring [{}]", door->GetDoorID(), door->GetTriggerType(), door->GetLockpick(), door->GetKeyItem(), door->GetNoKeyring()); //deleteme
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (RuleB(Map, CheckForLoSCheat)) {
|
||||
// uint8 zone_id = zone->GetZoneID();
|
||||
// // ZoneID, target XYZ, my range from target
|
||||
// //float zone_basic_checks[] = { 6, 36 };
|
||||
// //float zone_basic_x_coord[] = { -295, -179.908 };
|
||||
// //float zone_basic_y_coord[] = { -18, -630.708 };
|
||||
// //float zone_basic_y_coord[] = { 50.97, -69.971 };
|
||||
// //float zone_basic_range_check[] = { 21, 10 };
|
||||
// //if door and target infront, fail
|
||||
// //if door and target behind, fail
|
||||
//
|
||||
// if (zone_id == 103) {
|
||||
// Doors* door_to_check = entity_list.FindDoor(8);
|
||||
// TestDebug("Entered LoSCheat for ZoneID: [{}]", zone_id); //deleteme
|
||||
// glm::vec4 who_check; who_check.x = 1202; who_check.y = 559; who_check.z = -158.94;
|
||||
// glm::vec4 other_check; other_check.x = 1291; other_check.y = 559; other_check.z = -158.19;
|
||||
// float my_distance = DistanceNoZ(who->GetPosition(), who_check);
|
||||
// float tar_distance = DistanceNoZ(other->GetPosition(), other_check);
|
||||
// float my_range = 16;
|
||||
// float tar_range = 75;
|
||||
// if (my_distance <= my_range && tar_distance <= tar_range && !quest_manager.isdooropen(8)) {
|
||||
// TestDebug("Door is NOT open"); //deleteme
|
||||
// TestDebug("LoSCheat failed"); //deleteme
|
||||
// return false;
|
||||
// }
|
||||
// TestDebug("LoS Check for ZoneID: [{}] was [{}] units for [{}], [{}] units for [{}]", zone_id, my_distance, who->GetCleanName(), tar_distance, other->GetCleanName()); //deleteme
|
||||
// }
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Mob::CheckLosCheatExempt(Mob* who, Mob* other) {
|
||||
if (RuleB(Map, EnableLoSCheatExemptions)) {
|
||||
glm::vec4 exempt_check_who;
|
||||
glm::vec4 exempt_check_other;
|
||||
/* This is an exmaple of how to configure exemptions for LoS checks.
|
||||
if (zone->GetZoneID() == 222) { //PoEarthB
|
||||
exempt_check_who.x = 2051; exempt_check_who.y = 407; exempt_check_who.z = -219; //Middle of councilman spawns
|
||||
//check to be sure the player and the target are in the pit to PoEarthB
|
||||
//if the player is inside the cove they cannot be higher than the ceiling (no exploiting from uptop)
|
||||
//otherwise they can pass LoS checks even if they don't have true LoS
|
||||
if (who->GetZ() <= -171 && other->GetZ() <= -171 && DistanceNoZ(other->GetPosition(), exempt_check_who) <= 800 && DistanceNoZ(who->GetPosition(), exempt_check_who) <= 800) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+6
-1
@@ -1246,7 +1246,12 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!weapon_item->IsClassEquipable(GetClass())) {
|
||||
if (!weapon_item->IsClassEquipable(GetClass()) &&
|
||||
(
|
||||
!IsBot() ||
|
||||
(IsBot() && !RuleB(Bots, AllowBotEquipAnyClassGear))
|
||||
)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+3230
-1020
File diff suppressed because it is too large
Load Diff
+256
-82
@@ -42,6 +42,9 @@ constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500; // as DSq value (50 uni
|
||||
|
||||
constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds
|
||||
|
||||
constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MIN = 1500; // 1.5 seconds
|
||||
constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MAX = 3000; // 3 seconds
|
||||
|
||||
constexpr uint32 MAG_EPIC_1_0 = 28034;
|
||||
|
||||
extern WorldServer worldserver;
|
||||
@@ -49,6 +52,13 @@ extern WorldServer worldserver;
|
||||
constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
|
||||
constexpr int NegativeItemReuse = -1; // Unlinked timer for items
|
||||
|
||||
constexpr uint8 SumWater = 1;
|
||||
constexpr uint8 SumFire = 2;
|
||||
constexpr uint8 SumAir = 3;
|
||||
constexpr uint8 SumEarth = 4;
|
||||
constexpr uint8 MonsterSum = 5;
|
||||
constexpr uint8 SumMageMultiElement = 6;
|
||||
|
||||
// nHSND negative Healer/Slower/Nuker/Doter
|
||||
// pH positive Healer
|
||||
// pS positive Slower
|
||||
@@ -87,6 +97,58 @@ enum BotCastingChanceConditional : uint8
|
||||
cntHSND = 16
|
||||
};
|
||||
|
||||
namespace BotSettingCategories { // Update GetBotSpellCategoryName as needed
|
||||
constexpr uint8 BaseSetting = 0;
|
||||
constexpr uint8 SpellHold = 1;
|
||||
constexpr uint8 SpellDelay = 2;
|
||||
constexpr uint8 SpellMinThreshold = 3;
|
||||
constexpr uint8 SpellMaxThreshold = 4;
|
||||
constexpr uint8 SpellTypeAggroCheck = 5;
|
||||
constexpr uint8 SpellTypeMinManaPct = 6;
|
||||
constexpr uint8 SpellTypeMaxManaPct = 7;
|
||||
constexpr uint8 SpellTypeMinHPPct = 8;
|
||||
constexpr uint8 SpellTypeMaxHPPct = 9;
|
||||
constexpr uint8 SpellTypeIdlePriority = 10;
|
||||
constexpr uint8 SpellTypeEngagedPriority = 11;
|
||||
constexpr uint8 SpellTypePursuePriority = 12;
|
||||
constexpr uint8 SpellTypeAEOrGroupTargetCount = 13;
|
||||
constexpr uint8 SpellTypeRecastDelay = 14;
|
||||
|
||||
constexpr uint16 START = BotSettingCategories::BaseSetting;
|
||||
constexpr uint16 START_NO_BASE = BotSettingCategories::SpellHold;
|
||||
constexpr uint16 START_CLIENT = BotSettingCategories::SpellHold;
|
||||
constexpr uint16 END_CLIENT = BotSettingCategories::SpellMaxThreshold;
|
||||
constexpr uint16 END = BotSettingCategories::SpellTypeAEOrGroupTargetCount; // Increment as needed
|
||||
};
|
||||
|
||||
namespace BotPriorityCategories { // Update GetBotSpellCategoryName as needed
|
||||
constexpr uint8 Idle = 0;
|
||||
constexpr uint8 Engaged = 1;
|
||||
constexpr uint8 Pursue = 2;
|
||||
|
||||
constexpr uint16 START = BotPriorityCategories::Idle;
|
||||
constexpr uint16 END = BotPriorityCategories::Pursue; // Increment as needed
|
||||
};
|
||||
|
||||
namespace BotBaseSettings {
|
||||
constexpr uint16 ExpansionBitmask = 0;
|
||||
constexpr uint16 ShowHelm = 1;
|
||||
constexpr uint16 FollowDistance = 2;
|
||||
constexpr uint16 StopMeleeLevel = 3;
|
||||
constexpr uint16 EnforceSpellSettings = 4;
|
||||
constexpr uint16 RangedSetting = 5;
|
||||
constexpr uint16 PetSetTypeSetting = 6;
|
||||
constexpr uint16 BehindMob = 7;
|
||||
constexpr uint16 CasterRange = 8;
|
||||
constexpr uint16 IllusionBlock = 9;
|
||||
constexpr uint16 MaxMeleeRange = 10;
|
||||
constexpr uint16 MedInCombat = 11;
|
||||
constexpr uint16 HPWhenToMed = 12;
|
||||
constexpr uint16 ManaWhenToMed = 13;
|
||||
|
||||
constexpr uint16 START = BotBaseSettings::ShowHelm; // Everything above this cannot be copied, changed or viewed by players
|
||||
constexpr uint16 END = BotBaseSettings::ManaWhenToMed; // Increment as needed
|
||||
};
|
||||
|
||||
class Bot : public NPC {
|
||||
friend class Mob;
|
||||
@@ -128,7 +190,7 @@ public:
|
||||
|
||||
// Class Constructors
|
||||
Bot(NPCType *npcTypeData, Client* botOwner);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData, int32 expansion_bitmask);
|
||||
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData);
|
||||
|
||||
//abstract virtual override function implementations requird by base abstract class
|
||||
bool Death(Mob* killer_mob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, KilledByTypes killed_by = KilledByTypes::Killed_NPC, bool is_buff_tic = false) override;
|
||||
@@ -199,8 +261,8 @@ public:
|
||||
void Camp(bool save_to_database = true);
|
||||
void SetTarget(Mob* mob) override;
|
||||
void Zone();
|
||||
bool IsArcheryRange(Mob* target);
|
||||
void ChangeBotArcherWeapons(bool isArcher);
|
||||
bool IsAtRange(Mob* target);
|
||||
void ChangeBotRangedWeapons(bool isRanged);
|
||||
void Sit();
|
||||
void Stand();
|
||||
bool IsSitting() const override;
|
||||
@@ -228,7 +290,7 @@ public:
|
||||
uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid);
|
||||
bool GetNeedsCured(Mob *tar);
|
||||
bool GetNeedsHateRedux(Mob *tar);
|
||||
bool HasOrMayGetAggro();
|
||||
bool HasOrMayGetAggro(bool SitAggro, uint32 spell_id = 0);
|
||||
void SetDefaultBotStance();
|
||||
void SetSurname(std::string_view bot_surname);
|
||||
void SetTitle(std::string_view bot_title);
|
||||
@@ -327,18 +389,20 @@ public:
|
||||
void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
|
||||
|
||||
// AI Methods
|
||||
bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes);
|
||||
bool AICastSpell(Mob* tar, uint8 iChance, uint16 spellType);
|
||||
bool AttemptAICastSpell(uint16 spellType);
|
||||
bool AI_EngagedCastCheck() override;
|
||||
bool AI_PursueCastCheck() override;
|
||||
bool AI_IdleCastCheck() override;
|
||||
bool AIHealRotation(Mob* tar, bool useFastHeals);
|
||||
bool GetPauseAI() const { return _pauseAI; }
|
||||
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
|
||||
uint8 GetStopMeleeLevel() const { return _stopMeleeLevel; }
|
||||
void SetStopMeleeLevel(uint8 level);
|
||||
bool IsCommandedSpell() const { return _commandedSpell; }
|
||||
void SetCommandedSpell(bool value) { _commandedSpell = value; }
|
||||
|
||||
void SetGuardMode();
|
||||
void SetHoldMode();
|
||||
uint32 GetBotCasterRange() const { return m_bot_caster_range; }
|
||||
|
||||
bool IsValidSpellRange(uint16 spell_id, Mob const* tar);
|
||||
|
||||
// Bot AI Methods
|
||||
@@ -377,6 +441,97 @@ public:
|
||||
inline bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
||||
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override
|
||||
{ return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); }
|
||||
void DoAttackRounds(Mob* target, int hand);
|
||||
|
||||
std::vector<Mob*> GatherGroupSpellTargets(Mob* target = nullptr, bool noClients = false, bool noBots = false);
|
||||
std::vector<Mob*> GatherSpellTargets(bool entireRaid = false, bool noClients = false, bool noBots = false, bool noPets = false);
|
||||
|
||||
bool PrecastChecks(Mob* tar, uint16 spellType);
|
||||
bool CastChecks(uint16 spellid, Mob* tar, uint16 spellType, bool doPrechecks = false, bool AECheck = false);
|
||||
bool CanCastSpellType(uint16 spellType, uint16 spellid, Mob* tar);
|
||||
bool BotHasEnoughMana(uint16 spell_id);
|
||||
bool IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spellid);
|
||||
bool DoResistCheck(Mob* target, uint16 spellid, int32 resist_limit);
|
||||
bool DoResistCheckBySpellType(Mob* tar, uint16 spellid, uint16 spellType);
|
||||
bool IsValidTargetType(uint16 spellid, int targetType, uint8 bodyType);
|
||||
bool IsMobEngagedByAnyone(Mob* tar);
|
||||
void SetBotSetting(uint8 settingType, uint16 botSetting, int settingValue);
|
||||
void CopySettings(Bot* to, uint8 settingType, uint16 spellType = UINT16_MAX);
|
||||
void CopyBotSpellSettings(Bot* to);
|
||||
void ResetBotSpellSettings();
|
||||
int GetBotBaseSetting(uint16 botSetting);
|
||||
int GetDefaultBotBaseSetting(uint16 botSetting);
|
||||
void SetBotBaseSetting(uint16 botSetting, int settingValue);
|
||||
void LoadDefaultBotSettings();
|
||||
void SetBotSpellRecastTimer(uint16 spellType, Mob* spelltar, bool preCast = false);
|
||||
BotSpell GetSpellByHealType(uint16 spellType, Mob* tar);
|
||||
|
||||
std::string GetBotSpellCategoryName(uint8 setting_type);
|
||||
std::string GetBotSettingCategoryName(uint8 setting_type);
|
||||
|
||||
int GetDefaultSetting(uint16 settingCategory, uint16 settingType);
|
||||
uint16 GetDefaultSpellTypePriority(uint16 spellType, uint8 priorityType, uint8 botClass);
|
||||
uint16 GetDefaultSpellTypeIdlePriority(uint16 spellType, uint8 botClass);
|
||||
uint16 GetDefaultSpellTypeEngagedPriority(uint16 spellType, uint8 botClass);
|
||||
uint16 GetDefaultSpellTypePursuePriority(uint16 spellType, uint8 botClass);
|
||||
uint16 GetDefaultSpellTypeResistLimit(uint16 spellType);
|
||||
bool GetDefaultSpellTypeAggroCheck(uint16 spellType);
|
||||
uint8 GetDefaultSpellTypeMinManaLimit(uint16 spellType);
|
||||
uint8 GetDefaultSpellTypeMaxManaLimit(uint16 spellType);
|
||||
uint8 GetDefaultSpellTypeMinHPLimit(uint16 spellType);
|
||||
uint8 GetDefaultSpellTypeMaxHPLimit(uint16 spellType);
|
||||
uint16 GetDefaultSpellTypeAEOrGroupTargetCount(uint16 spellType);
|
||||
|
||||
int GetSetting(uint16 settingCategory, uint16 settingType);
|
||||
uint16 GetSpellTypePriority(uint16 spellType, uint8 priorityType);
|
||||
void SetSpellTypePriority(uint16 spellType, uint8 priorityType, uint16 priority);
|
||||
inline uint16 GetSpellTypeResistLimit(uint16 spellType) const { return _spellSettings[spellType].resistLimit; }
|
||||
void SetSpellTypeResistLimit(uint16 spellType, uint16 resistLimit);
|
||||
inline bool GetSpellTypeAggroCheck(uint16 spellType) const { return _spellSettings[spellType].aggroCheck; }
|
||||
void SetSpellTypeAggroCheck(uint16 spellType, bool AggroCheck);
|
||||
inline uint8 GetSpellTypeMinManaLimit(uint16 spellType) const { return _spellSettings[spellType].minManaPct; }
|
||||
inline uint8 GetSpellTypeMaxManaLimit(uint16 spellType) const { return _spellSettings[spellType].maxManaPct; }
|
||||
void SetSpellTypeMinManaLimit(uint16 spellType, uint8 manaLimit);
|
||||
void SetSpellTypeMaxManaLimit(uint16 spellType, uint8 manaLimit);
|
||||
inline uint8 GetSpellTypeMinHPLimit(uint16 spellType) const { return _spellSettings[spellType].minHPPct; }
|
||||
inline uint8 GetSpellTypeMaxHPLimit(uint16 spellType) const { return _spellSettings[spellType].maxHPPct; }
|
||||
void SetSpellTypeMinHPLimit(uint16 spellType, uint8 hpLimit);
|
||||
void SetSpellTypeMaxHPLimit(uint16 spellType, uint8 hpLimit);
|
||||
inline uint16 GetSpellTypeAEOrGroupTargetCount(uint16 spellType) const { return _spellSettings[spellType].AEOrGroupTargetCount; }
|
||||
void SetSpellTypeAEOrGroupTargetCount(uint16 spellType, uint16 targetCount);
|
||||
|
||||
bool GetShowHelm() const { return _showHelm; }
|
||||
void SetShowHelm(bool showHelm) { _showHelm = showHelm; }
|
||||
bool GetBehindMob() const { return _behindMobStatus; }
|
||||
void SetBehindMob(bool value) { _behindMobStatus = value; }
|
||||
bool GetMaxMeleeRange() const { return _maxMeleeRangeStatus; }
|
||||
void SetMaxMeleeRange(bool value) { _maxMeleeRangeStatus = value; }
|
||||
uint8 GetStopMeleeLevel() const { return _stopMeleeLevel; }
|
||||
void SetStopMeleeLevel(uint8 level) { _stopMeleeLevel = level; }
|
||||
uint32 GetBotCasterRange() const { return _casterRange; }
|
||||
void SetBotCasterRange(uint32 casterRange) { _casterRange = casterRange; }
|
||||
bool GetMedInCombat() const { return _medInCombat; }
|
||||
void SetMedInCombat(bool value) { _medInCombat = value; }
|
||||
uint8 GetHPWhenToMed() const { return _HPWhenToMed; }
|
||||
void SetHPWhenToMed(uint8 value) { _HPWhenToMed = value; }
|
||||
uint8 GetManaWhenToMed() const { return _ManaWhenToMed; }
|
||||
void SetManaWhenToMed(uint8 value) { _ManaWhenToMed = value; }
|
||||
void SetHasLoS(bool hasLoS) { _hasLoS = hasLoS; }
|
||||
bool HasLoS() const { return _hasLoS; }
|
||||
|
||||
bool IsInGroupOrRaid(bool announce = false);
|
||||
void SendSpellTypesWindow(Client* c, std::string arg0, std::string arg1, std::string arg2, bool helpPrompt = false);
|
||||
|
||||
std::list<BotSpellTypeOrder> GetSpellTypesPrioritized(uint8 priorityType);
|
||||
uint16 GetSpellListSpellType(uint16 spellType);
|
||||
bool IsValidSpellTypeBySpellID(uint16 spellType, uint16 spellid);
|
||||
inline uint16 GetCastedSpellType() const { return _castedSpellType; }
|
||||
void SetCastedSpellType(uint16 spellType);
|
||||
|
||||
bool HasValidAETarget(Bot* botCaster, uint16 spellid, uint16 spellType, Mob* tar);
|
||||
|
||||
void CheckBotSpells();
|
||||
|
||||
|
||||
[[nodiscard]] int GetMaxBuffSlots() const final { return EQ::spells::LONG_BUFFS; }
|
||||
[[nodiscard]] int GetMaxSongSlots() const final { return EQ::spells::SHORT_BUFFS; }
|
||||
@@ -423,33 +578,36 @@ public:
|
||||
ProcessBotGroupAdd(Group* group, Raid* raid, Client* client = nullptr, bool new_raid = false, bool initial = false);
|
||||
|
||||
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect);
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType);
|
||||
static std::list<BotSpell> GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType);
|
||||
static std::list<BotSpell_wPriority> GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint32 spellType);
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spellType, int spellEffect);
|
||||
static std::list<BotSpell> GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, uint16 spellType, int spellEffect, SpellTargetType targetType);
|
||||
static std::list<BotSpell> GetBotSpellsBySpellType(Bot* botCaster, uint16 spellType);
|
||||
static std::list<BotSpell_wPriority> GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint16 spellType, Mob* tar, bool AE = false);
|
||||
|
||||
static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType);
|
||||
static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForPercentageHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster);
|
||||
static BotSpell GetFirstBotSpellForSingleTargetHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupHealOverTime(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupCompleteHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForGroupHeal(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForMagicBasedSlow(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster);
|
||||
static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType);
|
||||
static BotSpell GetBestBotSpellForVeryFastHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForPercentageHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetFirstBotSpellForSingleTargetHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForGroupHealOverTime(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForGroupCompleteHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
static BotSpell GetBestBotSpellForGroupHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal);
|
||||
|
||||
static Mob* GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell);
|
||||
static BotSpell GetBestBotSpellForMez(Bot* botCaster);
|
||||
static BotSpell GetBestBotMagicianPetSpell(Bot* botCaster);
|
||||
static Mob* GetFirstIncomingMobToMez(Bot* botCaster, int16 spellid, uint16 spellType, bool AE = false);
|
||||
bool IsValidMezTarget(Mob* owner, Mob* npc, uint16 spellid);
|
||||
static BotSpell GetBestBotSpellForMez(Bot* botCaster, uint16 spellType = BotSpellTypes::Mez);
|
||||
static BotSpell GetBestBotMagicianPetSpell(Bot* botCaster, uint16 spellType = BotSpellTypes::Mez);
|
||||
static std::string GetBotMagicianPetType(Bot* botCaster);
|
||||
static BotSpell GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType targetType);
|
||||
static BotSpell GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType);
|
||||
static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
|
||||
static BotSpell GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
|
||||
static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* target, uint16 spellType);
|
||||
static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target, uint16 spellType);
|
||||
static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target);
|
||||
static BotSpell GetBestBotSpellForNukeByBodyType(Bot* botCaster, uint8 bodyType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
|
||||
static BotSpell GetBestBotSpellForRez(Bot* botCaster, Mob* target, uint16 spellType);
|
||||
static BotSpell GetBestBotSpellForCharm(Bot* botCaster, Mob* target, uint16 spellType);
|
||||
|
||||
static NPCType *CreateDefaultNPCTypeStructForBot(
|
||||
const std::string& botName,
|
||||
@@ -472,12 +630,11 @@ public:
|
||||
uint32 GetBotOwnerCharacterID() const { return _botOwnerCharacterID; }
|
||||
uint32 GetBotSpellID() const { return npc_spells_id; }
|
||||
Mob* GetBotOwner() { return this->_botOwner; }
|
||||
uint32 GetBotArcheryRange();
|
||||
uint32 GetBotRangedValue();
|
||||
EQ::ItemInstance* GetBotItem(uint16 slot_id);
|
||||
bool GetSpawnStatus() { return _spawnStatus; }
|
||||
uint8 GetPetChooserID() { return _petChooserID; }
|
||||
bool IsPetChooser() { return _petChooser; }
|
||||
bool IsBotArcher() { return m_bot_archery_setting; }
|
||||
bool IsBotRanged() { return _botRangedSetting; }
|
||||
bool IsBotCharmer() { return _botCharmer; }
|
||||
bool IsBot() const override { return true; }
|
||||
bool IsOfClientBot() const override { return true; }
|
||||
@@ -485,8 +642,7 @@ public:
|
||||
|
||||
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
||||
uint8 GetBotStance() { return _botStance; }
|
||||
uint8 GetChanceToCastBySpellType(uint32 spellType);
|
||||
bool GetBotEnforceSpellSetting() { return m_enforce_spell_settings; }
|
||||
uint8 GetChanceToCastBySpellType(uint16 spellType);
|
||||
float GetBotCasterMaxRange(float melee_distance_max);
|
||||
bool IsGroupHealer() const { return m_CastingRoles.GroupHealer; }
|
||||
bool IsGroupSlower() const { return m_CastingRoles.GroupSlower; }
|
||||
@@ -527,8 +683,6 @@ public:
|
||||
|
||||
std::shared_ptr<HealRotation>* MemberOfHealRotation() { return &m_member_of_heal_rotation; }
|
||||
|
||||
bool GetAltOutOfCombatBehavior() const { return _altoutofcombatbehavior;}
|
||||
bool GetShowHelm() const { return _showhelm; }
|
||||
inline int32 GetSTR() const override { return STR; }
|
||||
inline int32 GetSTA() const override { return STA; }
|
||||
inline int32 GetDEX() const override { return DEX; }
|
||||
@@ -600,13 +754,11 @@ public:
|
||||
void SetBotSpellID(uint32 newSpellID);
|
||||
void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
|
||||
void SetPetChooserID(uint8 id) { _petChooserID = id; }
|
||||
void SetBotArcherySetting(bool bot_archer_setting, bool save = false);
|
||||
void SetBotRangedSetting(bool botRangedSetting) { _botRangedSetting = botRangedSetting; }
|
||||
void SetBotCharmer(bool c) { _botCharmer = c; }
|
||||
void SetPetChooser(bool p) { _petChooser = p; }
|
||||
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
||||
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == Class::Ranger ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
||||
void SetBotStance(uint8 stance_id) { _botStance = Stance::IsValid(stance_id) ? stance_id : Stance::Passive; }
|
||||
void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; }
|
||||
uint32 GetSpellRecastTimer(uint16 spell_id = 0);
|
||||
bool CheckSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetSpellRecastRemainingTime(uint16 spell_id = 0);
|
||||
@@ -624,8 +776,6 @@ public:
|
||||
void ClearSpellRecastTimer(uint16 spell_id = 0);
|
||||
uint32 GetItemReuseRemainingTime(uint32 item_id = 0);
|
||||
void ClearExpiredTimers();
|
||||
void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
|
||||
void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
|
||||
void SetBeardColor(uint8 value) { beardcolor = value; }
|
||||
void SetBeard(uint8 value) { beard = value; }
|
||||
void SetEyeColor1(uint8 value) { eyecolor1 = value; }
|
||||
@@ -639,7 +789,7 @@ public:
|
||||
bool DyeArmor(int16 slot_id, uint32 rgb, bool all_flag = false, bool save_flag = true);
|
||||
|
||||
int GetExpansionBitmask();
|
||||
void SetExpansionBitmask(int expansion_bitmask, bool save = true);
|
||||
void SetExpansionBitmask(int expansionBitmask);
|
||||
|
||||
void ListBotSpells(uint8 min_level);
|
||||
|
||||
@@ -651,15 +801,12 @@ public:
|
||||
void ListBotSpellSettings();
|
||||
void LoadBotSpellSettings();
|
||||
bool UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs);
|
||||
void SetBotEnforceSpellSetting(bool enforcespellsettings, bool save = false);
|
||||
bool GetBotEnforceSpellSetting() const { return m_enforce_spell_settings; }
|
||||
void SetBotEnforceSpellSetting(bool enforceSpellSettings);
|
||||
bool GetBotEnforceSpellSetting() { return _enforceSpellSettings; }
|
||||
|
||||
// Class Destructors
|
||||
~Bot() override;
|
||||
|
||||
// Publicized protected functions
|
||||
void BotRangedAttack(Mob* other);
|
||||
|
||||
// Publicized private functions
|
||||
static NPCType *FillNPCTypeStruct(
|
||||
uint32 botSpellsID,
|
||||
@@ -750,24 +897,11 @@ public:
|
||||
|
||||
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][Stance::AEBurn][cntHSND];
|
||||
|
||||
bool BotCastMez(Mob* tar, uint8 botLevel, bool checked_los, BotSpell& botSpell, Raid* raid);
|
||||
bool BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, Raid* raid);
|
||||
bool BotCastRoot(Mob* tar, uint8 botLevel, uint32 iSpellTypes, BotSpell& botSpell, const bool& checked_los);
|
||||
bool BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass);
|
||||
bool BotCastEscape(Mob*& tar, uint8 botClass, BotSpell& botSpell, uint32 iSpellTypes);
|
||||
bool BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los);
|
||||
bool BotCastDispel(Mob* tar, BotSpell& botSpell, uint32 iSpellTypes, const bool& checked_los);
|
||||
bool BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell);
|
||||
bool BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass);
|
||||
bool BotCastLifetap(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes);
|
||||
bool BotCastSnare(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes);
|
||||
bool BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const bool& checked_los);
|
||||
bool BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los, Raid* raid);
|
||||
bool BotCastDebuff(Mob* tar, uint8 botLevel, BotSpell& botSpell, bool checked_los);
|
||||
bool BotCastCure(Mob* tar, uint8 botClass, BotSpell& botSpell, Raid* raid);
|
||||
bool BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpell);
|
||||
bool BotCastCombatSong(Mob* tar, uint8 botLevel);
|
||||
bool BotCastSong(Mob* tar, uint8 botLevel);
|
||||
bool BotCastMez(Mob* tar, uint8 botClass, BotSpell& botSpell, uint16 spellType);
|
||||
bool BotCastHeal(Mob* tar, uint8 botClass, BotSpell& botSpell, uint16 spellType);
|
||||
bool BotCastNuke(Mob* tar, uint8 botClass, BotSpell& botSpell, uint16 spellType);
|
||||
bool BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell, uint16 spellType);
|
||||
bool BotCastCure(Mob* tar, uint8 botClass, BotSpell& botSpell, uint16 spellType);
|
||||
|
||||
bool CheckIfIncapacitated();
|
||||
bool IsAIProcessValid(const Client* bot_owner, const Group* bot_group, const Raid* raid);
|
||||
@@ -796,39 +930,65 @@ public:
|
||||
const Mob* tar,
|
||||
const EQ::ItemInstance* const& p_item,
|
||||
const EQ::ItemInstance* const& s_item,
|
||||
bool behind_mob,
|
||||
bool behindMob,
|
||||
bool backstab_weapon,
|
||||
float& melee_distance_max,
|
||||
float& melee_distance
|
||||
) const;
|
||||
float& melee_distance,
|
||||
float& melee_distance_min,
|
||||
uint8 stopMeleeLevel
|
||||
);
|
||||
|
||||
// Combat Checks
|
||||
void SetBerserkState();
|
||||
bool CheckIfCasting(float fm_distance);
|
||||
void HealRotationChecks();
|
||||
void CheckCombatRange(Mob* tar, float tar_distance, bool& atCombatRange, const EQ::ItemInstance*& p_item, const EQ::ItemInstance*& s_item);
|
||||
void CheckCombatRange(
|
||||
Mob* tar,
|
||||
float tar_distance,
|
||||
bool& atCombatRange,
|
||||
bool& behindMob,
|
||||
const EQ::ItemInstance*& p_item,
|
||||
const EQ::ItemInstance*& s_item,
|
||||
float& melee_distance_min,
|
||||
float& melee_distance_max,
|
||||
float& melee_distance,
|
||||
uint8 stopMeleeLevel
|
||||
);
|
||||
bool GetCombatJitterFlag() { return m_combat_jitter_flag; }
|
||||
void SetCombatJitterFlag(bool flag = true) { m_combat_jitter_flag = flag; }
|
||||
bool GetCombatOutOfRangeJitterFlag() { return m_combat_out_of_range_jitter_flag; }
|
||||
void SetCombatOutOfRangeJitterFlag(bool flag = true) { m_combat_out_of_range_jitter_flag = flag; }
|
||||
void SetCombatJitter();
|
||||
void SetCombatOutOfRangeJitter();
|
||||
void DoCombatPositioning(Mob* tar, glm::vec3 Goal, bool stopMeleeLevel, float tar_distance, float melee_distance_min, float melee_distance, float melee_distance_max, bool behindMob);
|
||||
void DoFaceCheckWithJitter(Mob* tar);
|
||||
void DoFaceCheckNoJitter(Mob* tar);
|
||||
void RunToGoalWithJitter(glm::vec3 Goal);
|
||||
bool RequiresLoSForPositioning();
|
||||
bool HasRequiredLoSForPositioning(Mob* tar);
|
||||
|
||||
// Try Combat Methods
|
||||
bool TryEvade(Mob* tar);
|
||||
bool TryFacingTarget(Mob* tar);
|
||||
bool TryRangedAttack(Mob* tar);
|
||||
bool TryClassAttacks(Mob* tar);
|
||||
bool TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item);
|
||||
bool TrySecondaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* s_item);
|
||||
bool TryPursueTarget(float leash_distance, glm::vec3& Goal);
|
||||
bool TryMeditate();
|
||||
bool TryAutoDefend(Client* bot_owner, float leash_distance);
|
||||
bool TryIdleChecks(float fm_distance);
|
||||
bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal);
|
||||
bool TryBardMovementCasts();
|
||||
void SetRangerCombatWeapon(bool atArcheryRange);
|
||||
void BotRangedAttack(Mob* other, bool CanDoubleAttack = false);
|
||||
bool CheckDoubleRangedAttack();
|
||||
|
||||
// Public "Refactor" Methods
|
||||
static bool CheckSpawnConditions(Client* c);
|
||||
|
||||
inline bool CommandedDoSpellCast(int32 i, Mob* tar, int32 mana_cost) { return AIDoSpellCast(i, tar, mana_cost); }
|
||||
|
||||
protected:
|
||||
void BotMeditate(bool isSitting);
|
||||
bool CheckBotDoubleAttack(bool Triple = false);
|
||||
bool CheckTripleAttack();
|
||||
void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client);
|
||||
bool AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = nullptr) override;
|
||||
|
||||
@@ -849,9 +1009,7 @@ private:
|
||||
uint32 _botOwnerCharacterID;
|
||||
bool _spawnStatus;
|
||||
Mob* _botOwner;
|
||||
bool m_bot_archery_setting;
|
||||
bool _botCharmer;
|
||||
bool _petChooser;
|
||||
uint8 _petChooserID;
|
||||
bool berserk;
|
||||
EQ::InventoryProfile m_inv;
|
||||
@@ -876,9 +1034,15 @@ private:
|
||||
int32 max_end;
|
||||
int32 end_regen;
|
||||
|
||||
Timer m_evade_timer; // can be moved to pTimers at some point
|
||||
Timer m_rogue_evade_timer; // Rogue evade timer
|
||||
Timer m_monk_evade_timer; // Monk evade FD timer
|
||||
Timer m_auto_defend_timer;
|
||||
Timer auto_save_timer;
|
||||
|
||||
Timer m_combat_jitter_timer;
|
||||
bool m_combat_jitter_flag;
|
||||
bool m_combat_out_of_range_jitter_flag;
|
||||
|
||||
bool m_dirtyautohaters;
|
||||
bool m_guard_flag;
|
||||
bool m_hold_flag;
|
||||
@@ -888,7 +1052,7 @@ private:
|
||||
bool m_pulling_flag;
|
||||
bool m_returning_flag;
|
||||
bool is_using_item_click;
|
||||
uint32 m_bot_caster_range;
|
||||
|
||||
BotCastingRoles m_CastingRoles;
|
||||
|
||||
std::map<uint16, BotSpellSetting> bot_spell_settings;
|
||||
@@ -896,12 +1060,22 @@ private:
|
||||
std::shared_ptr<HealRotation> m_member_of_heal_rotation;
|
||||
|
||||
InspectMessage_Struct _botInspectMessage;
|
||||
bool _altoutofcombatbehavior;
|
||||
bool _showhelm;
|
||||
bool _pauseAI;
|
||||
|
||||
int _expansionBitmask;
|
||||
bool _enforceSpellSettings;
|
||||
bool _showHelm;
|
||||
bool _botRangedSetting;
|
||||
uint8 _stopMeleeLevel;
|
||||
int m_expansion_bitmask;
|
||||
bool m_enforce_spell_settings;
|
||||
uint32 _casterRange;
|
||||
bool _behindMobStatus;
|
||||
bool _maxMeleeRangeStatus;
|
||||
bool _medInCombat;
|
||||
uint8 _HPWhenToMed;
|
||||
uint8 _ManaWhenToMed;
|
||||
uint16 _castedSpellType;
|
||||
bool _hasLoS;
|
||||
bool _commandedSpell;
|
||||
|
||||
// Private "base stats" Members
|
||||
int32 _baseMR;
|
||||
|
||||
+186
-43
@@ -1249,8 +1249,8 @@ int bot_command_init(void)
|
||||
bot_command_add("actionable", "Lists actionable command arguments and use descriptions", AccountStatus::Player, bot_command_actionable) ||
|
||||
bot_command_add("aggressive", "Orders a bot to use a aggressive discipline", AccountStatus::Player, bot_command_aggressive) ||
|
||||
bot_command_add("applypoison", "Applies cursor-held poison to a rogue bot's weapon", AccountStatus::Player, bot_command_apply_poison) ||
|
||||
bot_command_add("applypotion", "Applies cursor-held potion to a bot's effects", AccountStatus::Player, bot_command_apply_potion) ||
|
||||
bot_command_add("attack", "Orders bots to attack a designated target", AccountStatus::Player, bot_command_attack) ||
|
||||
bot_command_add("behindmob", "Toggles whether or not your bot tries to stay behind a mob", AccountStatus::Player, bot_command_behind_mob) ||
|
||||
bot_command_add("bindaffinity", "Orders a bot to attempt an affinity binding", AccountStatus::Player, bot_command_bind_affinity) ||
|
||||
bot_command_add("bot", "Lists the available bot management [subcommands]", AccountStatus::Player, bot_command_bot) ||
|
||||
bot_command_add("botappearance", "Lists the available bot appearance [subcommands]", AccountStatus::Player, bot_command_appearance) ||
|
||||
@@ -1270,8 +1270,8 @@ int bot_command_init(void)
|
||||
bot_command_add("botheritage", "Changes the Drakkin heritage of a bot", AccountStatus::Player, bot_command_heritage) ||
|
||||
bot_command_add("botinspectmessage", "Changes the inspect message of a bot", AccountStatus::Player, bot_command_inspect_message) ||
|
||||
bot_command_add("botlist", "Lists the bots that you own", AccountStatus::Player, bot_command_list_bots) ||
|
||||
bot_command_add("botoutofcombat", "Toggles your bot between standard and out-of-combat spell/skill use - if any specialized behaviors exist", AccountStatus::Player, bot_command_out_of_combat) ||
|
||||
bot_command_add("botreport", "Orders a bot to report its readiness", AccountStatus::Player, bot_command_report) ||
|
||||
bot_command_add("botsettings", "Lists settings related to spell types and bot combat", AccountStatus::Player, bot_command_bot_settings) ||
|
||||
bot_command_add("botspawn", "Spawns a created bot", AccountStatus::Player, bot_command_spawn) ||
|
||||
bot_command_add("botstance", "Changes the stance of a bot", AccountStatus::Player, bot_command_stance) ||
|
||||
bot_command_add("botstopmeleelevel", "Sets the level a caster or spell-casting fighter bot will stop melee combat", AccountStatus::Player, bot_command_stop_melee_level) ||
|
||||
@@ -1279,16 +1279,20 @@ int bot_command_init(void)
|
||||
bot_command_add("botsummon", "Summons bot(s) to your location", AccountStatus::Player, bot_command_summon) ||
|
||||
bot_command_add("botsurname", "Sets a bots surname (last name)", AccountStatus::Player, bot_command_surname) ||
|
||||
bot_command_add("bottattoo", "Changes the Drakkin tattoo of a bot", AccountStatus::Player, bot_command_tattoo) ||
|
||||
bot_command_add("bottogglearcher", "Toggles a archer bot between melee and ranged weapon use", AccountStatus::Player, bot_command_toggle_archer) ||
|
||||
bot_command_add("bottogglehelm", "Toggles the helm visibility of a bot between shown and hidden", AccountStatus::Player, bot_command_toggle_helm) ||
|
||||
bot_command_add("bottoggleranged", "Toggles a ranged bot between melee and ranged weapon use", AccountStatus::Player, bot_command_toggle_ranged) ||
|
||||
bot_command_add("bottitle", "Sets a bots title", AccountStatus::Player, bot_command_title) ||
|
||||
bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", AccountStatus::Player, bot_command_update) ||
|
||||
bot_command_add("botwoad", "Changes the Barbarian woad of a bot", AccountStatus::Player, bot_command_woad) ||
|
||||
bot_command_add("cast", "Tells the first found specified bot to cast the given spell type", AccountStatus::Player, bot_command_cast) ||
|
||||
bot_command_add("casterrange", "Controls the range casters will try to stay away from a mob (if too far, they will skip spells that are out-of-range)", AccountStatus::Player, bot_command_caster_range) ||
|
||||
bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) ||
|
||||
bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_circle) ||
|
||||
bot_command_add("classracelist", "Lists the classes and races and their appropriate IDs", AccountStatus::Player, bot_command_class_race_list) ||
|
||||
bot_command_add("clickitem", "Orders your targeted bot to click the item in the provided inventory slot.", AccountStatus::Player, bot_command_click_item) ||
|
||||
bot_command_add("copysettings", "Copies settings from one bot to another", AccountStatus::Player, bot_command_copy_settings) ||
|
||||
bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) ||
|
||||
bot_command_add("defaultsettings", "Restores a bot back to default settings", AccountStatus::Player, bot_command_default_settings) ||
|
||||
bot_command_add("defensive", "Orders a bot to use a defensive discipline", AccountStatus::Player, bot_command_defensive) ||
|
||||
bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_depart) ||
|
||||
bot_command_add("enforcespellsettings", "Toggles your Bot to cast only spells in their spell settings list.", AccountStatus::Player, bot_command_enforce_spell_list) ||
|
||||
@@ -1320,6 +1324,7 @@ int bot_command_init(void)
|
||||
bot_command_add("help", "List available commands and their description - specify partial command as argument to search", AccountStatus::Player, bot_command_help) ||
|
||||
bot_command_add("hold", "Prevents a bot from attacking until released", AccountStatus::Player, bot_command_hold) ||
|
||||
bot_command_add("identify", "Orders a bot to cast an item identification spell", AccountStatus::Player, bot_command_identify) ||
|
||||
bot_command_add("illusionblock", "Control whether or not illusion effects will land on the bot if casted by another player or bot", AccountStatus::Player, bot_command_illusion_block) ||
|
||||
bot_command_add("inventory", "Lists the available bot inventory [subcommands]", AccountStatus::Player, bot_command_inventory) ||
|
||||
bot_command_add("inventorygive", "Gives the item on your cursor to a bot", AccountStatus::Player, bot_command_inventory_give) ||
|
||||
bot_command_add("inventorylist", "Lists all items in a bot's inventory", AccountStatus::Player, bot_command_inventory_list) ||
|
||||
@@ -1329,6 +1334,7 @@ int bot_command_init(void)
|
||||
bot_command_add("itemuse", "Elicits a report from spawned bots that can use the item on your cursor (option 'empty' yields only empty slots)", AccountStatus::Player, bot_command_item_use) ||
|
||||
bot_command_add("levitation", "Orders a bot to cast a levitation spell", AccountStatus::Player, bot_command_levitation) ||
|
||||
bot_command_add("lull", "Orders a bot to cast a pacification spell", AccountStatus::Player, bot_command_lull) ||
|
||||
bot_command_add("maxmeleerange", "Toggles whether your bot is at max melee range or not. This will disable all special abilities, including taunt.", AccountStatus::Player, bot_command_max_melee_range) ||
|
||||
bot_command_add("mesmerize", "Orders a bot to cast a mesmerization spell", AccountStatus::Player, bot_command_mesmerize) ||
|
||||
bot_command_add("movementspeed", "Orders a bot to cast a movement speed enhancement spell", AccountStatus::Player, bot_command_movement_speed) ||
|
||||
bot_command_add("owneroption", "Sets options available to bot owners", AccountStatus::Player, bot_command_owner_option) ||
|
||||
@@ -1346,7 +1352,23 @@ int bot_command_init(void)
|
||||
bot_command_add("resurrect", "Orders a bot to resurrect a player's (players') corpse(s)", AccountStatus::Player, bot_command_resurrect) ||
|
||||
bot_command_add("rune", "Orders a bot to cast a rune of protection", AccountStatus::Player, bot_command_rune) ||
|
||||
bot_command_add("sendhome", "Orders a bot to open a magical doorway home", AccountStatus::Player, bot_command_send_home) ||
|
||||
bot_command_add("size", "Orders a bot to change a player's size", AccountStatus::Player, bot_command_size) ||
|
||||
bot_command_add("sithppercent", "HP threshold for a bot to start sitting in combat if allowed", AccountStatus::Player, bot_command_sit_hp_percent) ||
|
||||
bot_command_add("sitincombat", "Toggles whether or a not a bot will attempt to med or sit to heal in combat", AccountStatus::Player, bot_command_sit_in_combat) ||
|
||||
bot_command_add("sitmanapercent", "Mana threshold for a bot to start sitting in combat if allowed", AccountStatus::Player, bot_command_sit_mana_percent) ||
|
||||
bot_command_add("size", "Orders a bot to change a player's size", AccountStatus::Player, bot_command_size) ||
|
||||
bot_command_add("spellaggrochecks", "Toggles whether or not bots will cast a spell type if they think it will get them aggro", AccountStatus::Player, bot_command_spell_aggro_checks) ||
|
||||
bot_command_add("spellengagedpriority", "Controls the order of casts by spell type when engaged in combat", AccountStatus::Player, bot_command_spell_engaged_priority) ||
|
||||
bot_command_add("spelldelays", "Controls the delay between casts for a specific spell type", AccountStatus::Player, bot_command_spell_delays) ||
|
||||
bot_command_add("spellholds", "Controls whether a bot holds the specified spell type or not", AccountStatus::Player, bot_command_spell_holds) ||
|
||||
bot_command_add("spellidlepriority", "Controls the order of casts by spell type when out of combat", AccountStatus::Player, bot_command_spell_idle_priority) ||
|
||||
bot_command_add("spellmaxhppct", "Controls at what HP percent a bot will stop casting different spell types", AccountStatus::Player, bot_command_spell_max_hp_pct) ||
|
||||
bot_command_add("spellmaxmanapct", "Controls at what mana percent a bot will stop casting different spell types", AccountStatus::Player, bot_command_spell_max_mana_pct) ||
|
||||
bot_command_add("spellmaxthresholds", "Controls the minimum target HP threshold for a spell to be cast for a specific type", AccountStatus::Player, bot_command_spell_max_thresholds) ||
|
||||
bot_command_add("spellminhppct", "Controls at what HP percent a bot will start casting different spell types", AccountStatus::Player, bot_command_spell_min_hp_pct) ||
|
||||
bot_command_add("spellminmanapct", "Controls at what mana percent a bot will start casting different spell types", AccountStatus::Player, bot_command_spell_min_mana_pct) ||
|
||||
bot_command_add("spellminthresholds", "Controls the maximum target HP threshold for a spell to be cast for a specific type", AccountStatus::Player, bot_command_spell_min_thresholds) ||
|
||||
bot_command_add("spellpursuepriority", "Controls the order of casts by spell type when pursuing in combat", AccountStatus::Player, bot_command_spell_pursue_priority) ||
|
||||
bot_command_add("spelltargetcount", "Sets the required target amount for group/AE spells by spell type", AccountStatus::Player, bot_command_spell_target_count) ||
|
||||
bot_command_add("spellinfo", "Opens a dialogue window with spell info", AccountStatus::Player, bot_spell_info_dialogue_window) ||
|
||||
bot_command_add("spells", "Lists all Spells learned by the Bot.", AccountStatus::Player, bot_command_spell_list) ||
|
||||
bot_command_add("spellsettings", "Lists a bot's spell setting entries", AccountStatus::Player, bot_command_spell_settings_list) ||
|
||||
@@ -1360,7 +1382,7 @@ int bot_command_init(void)
|
||||
bot_command_add("timer", "Checks or clears timers of the chosen type.", AccountStatus::GMMgmt, bot_command_timer) ||
|
||||
bot_command_add("track", "Orders a capable bot to track enemies", AccountStatus::Player, bot_command_track) ||
|
||||
bot_command_add("viewcombos", "Views bot race class combinations", AccountStatus::Player, bot_command_view_combos) ||
|
||||
bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing)
|
||||
bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing)
|
||||
) {
|
||||
bot_command_deinit();
|
||||
return -1;
|
||||
@@ -1613,7 +1635,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
bot_owner->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"'{}' is an invalid name. You may only use characters 'A-Z' or 'a-z'. Mixed case {} allowed.",
|
||||
"'{}' is an invalid name. You may only use characters 'A-Z' or 'a-z' and it must be between 4 and 15 characters. Mixed case {} allowed.",
|
||||
bot_name, RuleB(Bots, AllowCamelCaseNames) ? "is" : "is not"
|
||||
).c_str()
|
||||
);
|
||||
@@ -1625,7 +1647,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
bot_owner->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Failed to query name availability for '{}'.",
|
||||
"'{}' is already in use or an invalid name.",
|
||||
bot_name
|
||||
).c_str()
|
||||
);
|
||||
@@ -1806,40 +1828,6 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
||||
return bot_id;
|
||||
}
|
||||
|
||||
void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot)
|
||||
{
|
||||
if (!bot_owner || !my_bot)
|
||||
return;
|
||||
|
||||
switch (my_bot->GetClass()) {
|
||||
case Class::Warrior:
|
||||
case Class::Cleric:
|
||||
case Class::Paladin:
|
||||
case Class::Ranger:
|
||||
case Class::ShadowKnight:
|
||||
case Class::Druid:
|
||||
case Class::Monk:
|
||||
bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName());
|
||||
break;
|
||||
case Class::Bard:
|
||||
bot_owner->Message(Chat::White, "%s will %s use out-of-combat behavior for bard songs", my_bot->GetCleanName(), ((my_bot->GetAltOutOfCombatBehavior()) ? ("now") : ("no longer")));
|
||||
break;
|
||||
case Class::Rogue:
|
||||
case Class::Shaman:
|
||||
case Class::Necromancer:
|
||||
case Class::Wizard:
|
||||
case Class::Magician:
|
||||
case Class::Enchanter:
|
||||
case Class::Beastlord:
|
||||
case Class::Berserker:
|
||||
bot_owner->Message(Chat::White, "%s has no out-of-combat behavior defined", my_bot->GetCleanName());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
bot_owner->Message(Chat::White, "Undefined bot class for %s", my_bot->GetCleanName());
|
||||
}
|
||||
}
|
||||
|
||||
int helper_bot_follow_option_chain(Client* bot_owner)
|
||||
{
|
||||
if (!bot_owner) {
|
||||
@@ -2085,8 +2073,11 @@ void helper_send_available_subcommands(Client *bot_owner, const char* command_si
|
||||
bot_owner->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"^{} - {}",
|
||||
subcommand_iter,
|
||||
"{} - {}",
|
||||
Saylink::Silent(
|
||||
fmt::format("^{} help", subcommand_iter),
|
||||
fmt::format("^{}", subcommand_iter)
|
||||
),
|
||||
find_iter != bot_command_list.end() ? find_iter->second->desc : "No Description"
|
||||
).c_str()
|
||||
);
|
||||
@@ -2126,18 +2117,152 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bot::SendSpellTypesWindow(Client* c, std::string arg0, std::string arg1, std::string arg2, bool helpPrompt) {
|
||||
if (helpPrompt) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {}, {}, {} for a list of spell types by ID",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid 0-19", arg0)
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid 20-39", arg0)
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid 40+", arg0)
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {}, {}, {} for a list of spell types by short name",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname 0-19", arg0)
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname 20-39", arg0)
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname 40+", arg0)
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 minCount = 0;
|
||||
uint8 maxCount = 0;
|
||||
|
||||
if (BotSpellTypes::END <= 19) {
|
||||
minCount = BotSpellTypes::START;
|
||||
maxCount = BotSpellTypes::END;
|
||||
}
|
||||
else if (!arg2.compare("0-19")) {
|
||||
minCount = BotSpellTypes::START;
|
||||
maxCount = 19;
|
||||
}
|
||||
else if (!arg2.compare("20-39")) {
|
||||
minCount = std::min(static_cast<uint8_t>(20), static_cast<uint8_t>(BotSpellTypes::END));
|
||||
maxCount = std::min(static_cast<uint8_t>(39), static_cast<uint8_t>(BotSpellTypes::END));
|
||||
}
|
||||
else if (!arg2.compare("40+")) {
|
||||
minCount = std::min(static_cast<uint8_t>(40), static_cast<uint8_t>(BotSpellTypes::END));
|
||||
maxCount = BotSpellTypes::END;
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::Yellow, "You must choose a valid range option");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string& indian_red = "indian_red";
|
||||
const std::string& gold = "gold";
|
||||
const std::string& slate_blue = "slate_blue";
|
||||
const std::string& forest_green = "forest_green";
|
||||
const std::string& goldenrod = "goldenrod";
|
||||
|
||||
std::string fillerLine = "-----------";
|
||||
std::string spellTypeField = "Spell Type";
|
||||
std::string pluralS = "s";
|
||||
std::string idField = "ID";
|
||||
std::string shortnameField = "Short Name";
|
||||
|
||||
std::string popup_text = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(goldenrod, spellTypeField)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(goldenrod, idField) : DialogueWindow::ColorMessage(goldenrod, shortnameField))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(gold, fillerLine)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(gold, fillerLine)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = minCount; i <= maxCount; ++i) {
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
DialogueWindow::ColorMessage(forest_green, c->GetSpellTypeNameByID(i)),
|
||||
DialogueWindow::ColorMessage(forest_green, pluralS)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(slate_blue, std::to_string(i)) : DialogueWindow::ColorMessage(slate_blue, c->GetSpellTypeShortNameByID(i)))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient("Spell Types", popup_text.c_str());
|
||||
}
|
||||
|
||||
|
||||
#include "bot_commands/actionable.cpp"
|
||||
#include "bot_commands/aggressive.cpp"
|
||||
#include "bot_commands/appearance.cpp"
|
||||
#include "bot_commands/apply_poison.cpp"
|
||||
#include "bot_commands/apply_potion.cpp"
|
||||
#include "bot_commands/attack.cpp"
|
||||
#include "bot_commands/behind_mob.cpp"
|
||||
#include "bot_commands/bind_affinity.cpp"
|
||||
#include "bot_commands/bot.cpp"
|
||||
#include "bot_commands/bot_settings.cpp"
|
||||
#include "bot_commands/cast.cpp"
|
||||
#include "bot_commands/caster_range.cpp"
|
||||
#include "bot_commands/charm.cpp"
|
||||
#include "bot_commands/class_race_list.cpp"
|
||||
#include "bot_commands/click_item.cpp"
|
||||
#include "bot_commands/copy_settings.cpp"
|
||||
#include "bot_commands/cure.cpp"
|
||||
#include "bot_commands/default_settings.cpp"
|
||||
#include "bot_commands/defensive.cpp"
|
||||
#include "bot_commands/depart.cpp"
|
||||
#include "bot_commands/escape.cpp"
|
||||
@@ -2148,11 +2273,13 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
|
||||
#include "bot_commands/help.cpp"
|
||||
#include "bot_commands/hold.cpp"
|
||||
#include "bot_commands/identify.cpp"
|
||||
#include "bot_commands/illusion_block.cpp"
|
||||
#include "bot_commands/inventory.cpp"
|
||||
#include "bot_commands/invisibility.cpp"
|
||||
#include "bot_commands/item_use.cpp"
|
||||
#include "bot_commands/levitation.cpp"
|
||||
#include "bot_commands/lull.cpp"
|
||||
#include "bot_commands/max_melee_range.cpp"
|
||||
#include "bot_commands/mesmerize.cpp"
|
||||
#include "bot_commands/movement_speed.cpp"
|
||||
#include "bot_commands/name.cpp"
|
||||
@@ -2167,8 +2294,24 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
|
||||
#include "bot_commands/resurrect.cpp"
|
||||
#include "bot_commands/rune.cpp"
|
||||
#include "bot_commands/send_home.cpp"
|
||||
#include "bot_commands/sit_hp_percent.cpp"
|
||||
#include "bot_commands/sit_in_combat.cpp"
|
||||
#include "bot_commands/sit_mana_percent.cpp"
|
||||
#include "bot_commands/size.cpp"
|
||||
#include "bot_commands/spell.cpp"
|
||||
#include "bot_commands/spell_aggro_checks.cpp"
|
||||
#include "bot_commands/spell_delays.cpp"
|
||||
#include "bot_commands/spell_engaged_priority.cpp"
|
||||
#include "bot_commands/spell_holds.cpp"
|
||||
#include "bot_commands/spell_idle_priority.cpp"
|
||||
#include "bot_commands/spell_max_hp_pct.cpp"
|
||||
#include "bot_commands/spell_max_mana_pct.cpp"
|
||||
#include "bot_commands/spell_max_thresholds.cpp"
|
||||
#include "bot_commands/spell_min_hp_pct.cpp"
|
||||
#include "bot_commands/spell_min_mana_pct.cpp"
|
||||
#include "bot_commands/spell_min_thresholds.cpp"
|
||||
#include "bot_commands/spell_pursue_priority.cpp"
|
||||
#include "bot_commands/spell_target_count.cpp"
|
||||
#include "bot_commands/summon.cpp"
|
||||
#include "bot_commands/summon_corpse.cpp"
|
||||
#include "bot_commands/suspend.cpp"
|
||||
|
||||
+60
-7
@@ -666,6 +666,27 @@ namespace MyBots
|
||||
UniquifySBL(sbl);
|
||||
}
|
||||
}
|
||||
|
||||
static void PopulateSBL_ByAtMMR(Client* bot_owner, std::list<Bot*>& sbl, bool clear_list = true) {
|
||||
if (clear_list) {
|
||||
sbl.clear();
|
||||
}
|
||||
|
||||
if (!bot_owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto selectable_bot_list = entity_list.GetBotsByBotOwnerCharacterID(bot_owner->CharacterID());
|
||||
for (auto bot_iter : selectable_bot_list) {
|
||||
if (!bot_iter->GetMaxMeleeRange()) {
|
||||
continue;
|
||||
}
|
||||
sbl.push_back(bot_iter);
|
||||
}
|
||||
if (!clear_list) {
|
||||
UniquifySBL(sbl);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace ActionableTarget
|
||||
@@ -875,6 +896,7 @@ namespace ActionableBots
|
||||
ABT_HealRotation,
|
||||
ABT_HealRotationMembers,
|
||||
ABT_HealRotationTargets,
|
||||
ABT_MMR,
|
||||
ABT_Class,
|
||||
ABT_Race,
|
||||
ABT_Spawned,
|
||||
@@ -892,6 +914,7 @@ namespace ActionableBots
|
||||
ABM_HealRotation = (1 << (ABT_HealRotation - 1)),
|
||||
ABM_HealRotationMembers = (1 << (ABT_HealRotationMembers - 1)),
|
||||
ABM_HealRotationTargets = (1 << (ABT_HealRotationTargets - 1)),
|
||||
ABM_MMR = (1 << (ABT_MMR - 1)),
|
||||
ABM_Class = (1 << (ABT_Class - 1)),
|
||||
ABM_Race = (1 << (ABT_Race - 1)),
|
||||
ABM_Spawned = (1 << (ABT_Spawned - 1)),
|
||||
@@ -899,8 +922,8 @@ namespace ActionableBots
|
||||
ABM_Spawned_All = (3 << (ABT_Spawned - 1)),
|
||||
ABM_NoFilter = ~0,
|
||||
// grouped values
|
||||
ABM_Type1 = (ABM_Target | ABM_ByName | ABM_OwnerGroup | ABM_OwnerRaid | ABM_TargetGroup | ABM_NamesGroup | ABM_HealRotationTargets | ABM_Spawned | ABM_Class | ABM_Race),
|
||||
ABM_Type2 = (ABM_ByName | ABM_OwnerGroup | ABM_OwnerRaid | ABM_NamesGroup | ABM_HealRotation | ABM_Spawned | ABM_Class | ABM_Race)
|
||||
ABM_Type1 = (ABM_Target | ABM_ByName | ABM_OwnerGroup | ABM_OwnerRaid | ABM_TargetGroup | ABM_NamesGroup | ABM_HealRotationTargets | ABM_Spawned | ABM_MMR | ABM_Class | ABM_Race),
|
||||
ABM_Type2 = (ABM_ByName | ABM_OwnerGroup | ABM_OwnerRaid | ABM_NamesGroup | ABM_HealRotation | ABM_Spawned | ABM_MMR | ABM_Class | ABM_Race)
|
||||
};
|
||||
|
||||
// Populates 'sbl'
|
||||
@@ -941,6 +964,9 @@ namespace ActionableBots
|
||||
else if (!ab_type_arg.compare("healrotationtargets")) {
|
||||
ab_type = ABT_HealRotationTargets;
|
||||
}
|
||||
else if (!ab_type_arg.compare("mmr")) {
|
||||
ab_type = ABT_MMR;
|
||||
}
|
||||
else if (!ab_type_arg.compare("byclass")) {
|
||||
ab_type = ABT_Class;
|
||||
}
|
||||
@@ -1004,6 +1030,11 @@ namespace ActionableBots
|
||||
MyBots::PopulateSBL_ByHealRotationTargets(bot_owner, sbl, name, clear_list);
|
||||
}
|
||||
break;
|
||||
case ABT_MMR:
|
||||
if (ab_mask & ABM_MMR) {
|
||||
MyBots::PopulateSBL_ByAtMMR(bot_owner, sbl, clear_list);
|
||||
}
|
||||
break;
|
||||
case ABT_Class:
|
||||
if (ab_mask & ABM_Class) {
|
||||
MyBots::PopulateSBL_BySpawnedBotsClass(bot_owner, sbl, classrace, clear_list);
|
||||
@@ -1256,9 +1287,9 @@ namespace ActionableBots
|
||||
sbl.remove_if([min_level](const Bot* l) { return (l->GetLevel() < min_level); });
|
||||
}
|
||||
|
||||
static void Filter_ByArcher(Client* bot_owner, std::list<Bot*>& sbl) {
|
||||
static void Filter_ByRanged(Client* bot_owner, std::list<Bot*>& sbl) {
|
||||
sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); });
|
||||
sbl.remove_if([bot_owner](Bot* l) { return (!l->IsBotArcher()); });
|
||||
sbl.remove_if([bot_owner](Bot* l) { return (!l->IsBotRanged()); });
|
||||
}
|
||||
|
||||
static void Filter_ByHighestSkill(Client* bot_owner, std::list<Bot*>& sbl, EQ::skills::SkillType skill_type, float& skill_value) {
|
||||
@@ -1637,12 +1668,18 @@ void bot_command_aggressive(Client *c, const Seperator *sep);
|
||||
void bot_command_apply_poison(Client *c, const Seperator *sep);
|
||||
void bot_command_apply_potion(Client* c, const Seperator* sep);
|
||||
void bot_command_attack(Client *c, const Seperator *sep);
|
||||
void bot_command_behind_mob(Client* c, const Seperator* sep);
|
||||
void bot_command_bind_affinity(Client *c, const Seperator *sep);
|
||||
void bot_command_bot(Client *c, const Seperator *sep);
|
||||
void bot_command_bot_settings(Client* c, const Seperator* sep);
|
||||
void bot_command_cast(Client* c, const Seperator* sep);
|
||||
void bot_command_caster_range(Client* c, const Seperator* sep);
|
||||
void bot_command_charm(Client *c, const Seperator *sep);
|
||||
void bot_command_class_race_list(Client* c, const Seperator* sep);
|
||||
void bot_command_click_item(Client* c, const Seperator* sep);
|
||||
void bot_command_copy_settings(Client* c, const Seperator* sep);
|
||||
void bot_command_cure(Client *c, const Seperator *sep);
|
||||
void bot_command_default_settings(Client* c, const Seperator* sep);
|
||||
void bot_command_defensive(Client *c, const Seperator *sep);
|
||||
void bot_command_depart(Client *c, const Seperator *sep);
|
||||
void bot_command_escape(Client *c, const Seperator *sep);
|
||||
@@ -1653,11 +1690,13 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep);
|
||||
void bot_command_help(Client *c, const Seperator *sep);
|
||||
void bot_command_hold(Client *c, const Seperator *sep);
|
||||
void bot_command_identify(Client *c, const Seperator *sep);
|
||||
void bot_command_illusion_block(Client* c, const Seperator* sep);
|
||||
void bot_command_inventory(Client *c, const Seperator *sep);
|
||||
void bot_command_invisibility(Client *c, const Seperator *sep);
|
||||
void bot_command_item_use(Client *c, const Seperator *sep);
|
||||
void bot_command_levitation(Client *c, const Seperator *sep);
|
||||
void bot_command_lull(Client *c, const Seperator *sep);
|
||||
void bot_command_max_melee_range(Client* c, const Seperator* sep);
|
||||
void bot_command_mesmerize(Client *c, const Seperator *sep);
|
||||
void bot_command_movement_speed(Client *c, const Seperator *sep);
|
||||
void bot_command_owner_option(Client *c, const Seperator *sep);
|
||||
@@ -1671,7 +1710,23 @@ void bot_command_resistance(Client *c, const Seperator *sep);
|
||||
void bot_command_resurrect(Client *c, const Seperator *sep);
|
||||
void bot_command_rune(Client *c, const Seperator *sep);
|
||||
void bot_command_send_home(Client *c, const Seperator *sep);
|
||||
void bot_command_sit_hp_percent(Client* c, const Seperator* sep);
|
||||
void bot_command_sit_in_combat(Client* c, const Seperator* sep);
|
||||
void bot_command_sit_mana_percent(Client* c, const Seperator* sep);
|
||||
void bot_command_size(Client *c, const Seperator *sep);
|
||||
void bot_command_spell_aggro_checks(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_delays(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_engaged_priority(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_holds(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_idle_priority(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_max_thresholds(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_min_thresholds(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_pursue_priority(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_target_count(Client* c, const Seperator* sep);
|
||||
void bot_command_spell_list(Client* c, const Seperator *sep);
|
||||
void bot_command_spell_settings_add(Client* c, const Seperator *sep);
|
||||
void bot_command_spell_settings_delete(Client* c, const Seperator *sep);
|
||||
@@ -1706,7 +1761,6 @@ void bot_command_hairstyle(Client *c, const Seperator *sep);
|
||||
void bot_command_heritage(Client *c, const Seperator *sep);
|
||||
void bot_command_inspect_message(Client *c, const Seperator *sep);
|
||||
void bot_command_list_bots(Client *c, const Seperator *sep);
|
||||
void bot_command_out_of_combat(Client *c, const Seperator *sep);
|
||||
void bot_command_report(Client *c, const Seperator *sep);
|
||||
void bot_command_spawn(Client *c, const Seperator *sep);
|
||||
void bot_command_stance(Client *c, const Seperator *sep);
|
||||
@@ -1716,8 +1770,8 @@ void bot_command_summon(Client *c, const Seperator *sep);
|
||||
void bot_command_surname(Client *c, const Seperator *sep);
|
||||
void bot_command_tattoo(Client *c, const Seperator *sep);
|
||||
void bot_command_title(Client *c, const Seperator *sep);
|
||||
void bot_command_toggle_archer(Client *c, const Seperator *sep);
|
||||
void bot_command_toggle_helm(Client *c, const Seperator *sep);
|
||||
void bot_command_toggle_ranged(Client* c, const Seperator* sep);
|
||||
void bot_command_update(Client *c, const Seperator *sep);
|
||||
void bot_command_woad(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -1757,7 +1811,6 @@ bool helper_bot_appearance_fail(Client *bot_owner, Bot *my_bot, BCEnum::AFType f
|
||||
void helper_bot_appearance_form_final(Client *bot_owner, Bot *my_bot);
|
||||
void helper_bot_appearance_form_update(Bot *my_bot);
|
||||
uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_class, uint16 bot_race, uint8 bot_gender);
|
||||
void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot);
|
||||
int helper_bot_follow_option_chain(Client *bot_owner);
|
||||
bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, bool annouce_cast = true, uint32* dont_root_before = nullptr);
|
||||
bool helper_command_disabled(Client *bot_owner, bool rule_value, const char *command);
|
||||
|
||||
@@ -3,22 +3,61 @@
|
||||
void bot_command_actionable(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_actionable", sep->arg[0], "actionable")) {
|
||||
c->Message(Chat::White, "note: Lists actionable command arguments and use descriptions");
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(Chat::White, "Actionable command arguments:");
|
||||
c->Message(Chat::White, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument");
|
||||
c->Message(Chat::White, "byname [name] - selects single bot by name");
|
||||
c->Message(Chat::White, "ownergroup - selects all bots in the owner's group");
|
||||
c->Message(Chat::White, "ownerraid - selects all bots in the owner's raid");
|
||||
c->Message(Chat::White, "targetgroup - selects all bots in target's group");
|
||||
c->Message(Chat::White, "namesgroup [name] - selects all bots in name's group");
|
||||
c->Message(Chat::White, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member");
|
||||
c->Message(Chat::White, "healrotationmembers [name] - selects all member bots of a heal rotation where name is a member");
|
||||
c->Message(Chat::White, "healrotationtargets [name] - selects all target bots of a heal rotation where name is a member");
|
||||
c->Message(Chat::White, "byclass - selects all bots of the chosen class");
|
||||
c->Message(Chat::White, "byrace - selects all bots of the chosen rsce");
|
||||
c->Message(Chat::White, "spawned - selects all spawned bots");
|
||||
c->Message(Chat::White, "all - selects all spawned bots .. argument use indicates en masse database updating");
|
||||
c->Message(Chat::White, "You may only select your bots as actionable");
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Lists actionable command arguments and use descriptions."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"[target] - uses the command on the target. Some commands will default to target if no actionable is selected.",
|
||||
"[byname] [name] - selects a bot by name their name.",
|
||||
"[ownergroup] - selects all bots in the owner's group.",
|
||||
"[ownerraid] - selects all bots in the owner's raid.",
|
||||
"[targetgroup] - selects all bots in the target's group.",
|
||||
"[namesgroup] [name] - selects all bots in [name]'s group.",
|
||||
"[healrotation] [name] - selects all member and target bots of a heal rotation where [name] is a member.",
|
||||
"[healrotationmembers] [name] - selects all member bots of a heal rotation where [name] is a member.",
|
||||
"[healrotationtargets] [name] - selects all target bots of a heal rotation where [name] is a member.",
|
||||
"[mmr] - selects all bots that are currently at max melee range.",
|
||||
"[byclass] - selects all bots of the chosen class.",
|
||||
"[byrace] - selects all bots of the chosen race.",
|
||||
"[spawned] - selects all spawned bots.",
|
||||
"[all] - selects all spawned bots.",
|
||||
"<br>",
|
||||
"You may only select your bots as actionable"
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format = { };
|
||||
std::vector<std::string> examples_one = { };
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three = { };
|
||||
|
||||
std::vector<std::string> actionables = { };
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,32 +7,26 @@ void bot_command_aggressive(Client* c, const Seperator* sep)
|
||||
helper_command_alias_fail(c, "bot_command_aggressive", sep->arg[0], "aggressive")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))",
|
||||
sep->arg[0]
|
||||
);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Orders a bot to use a aggressive discipline");
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string class_race_arg = sep->arg[1];
|
||||
bool class_race_check = false;
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
int ab_arg = 1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(
|
||||
c,
|
||||
sep->arg[1],
|
||||
sbl,
|
||||
ab_mask,
|
||||
!class_race_check ? sep->arg[2] : nullptr,
|
||||
class_race_check ? atoi(sep->arg[2]) : 0
|
||||
) == ActionableBots::ABT_None) {
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ void bot_command_dye_armor(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
|
||||
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))",
|
||||
sep->arg[0]
|
||||
).c_str()
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ void bot_command_apply_poison(Client* c, const Seperator* sep)
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: <rogue_bot_target> %s", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Applies cursor-held poison to a rogue bot's weapon");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,17 @@ void bot_command_attack(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_attack", sep->arg[0], "attack")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Orders bots to attack a designated target");
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type2;
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type2;
|
||||
Mob* target_mob = ActionableTarget::AsSingle_ByAttackable(c);
|
||||
|
||||
if (!target_mob) {
|
||||
|
||||
c->Message(Chat::White, "You must <target> an enemy to use this command");
|
||||
@@ -26,11 +29,13 @@ void bot_command_attack(Client *c, const Seperator *sep)
|
||||
|
||||
std::string class_race_arg(sep->arg[1]);
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, ab_arg.c_str(), sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_behind_mob(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_behind_mob", sep->arg[0], "behindmob")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots will stay behind the mob during combat."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set Monks to stay behind the mob:",
|
||||
fmt::format(
|
||||
"{} 1 byclass 7",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the behind mob status for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} stay behind mobs.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetBehindMob() ? "will" : "will not"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetBehindMob(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} stay behind mobs.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetBehindMob() ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots {} stay behind mobs.",
|
||||
success_count,
|
||||
typeValue ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep)
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: (<friendly_target>) %s", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Orders a bot to attempt an affinity binding", sep->arg[0]);
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_BindAffinity);
|
||||
return;
|
||||
}
|
||||
|
||||
+212
-161
@@ -18,7 +18,7 @@ void bot_command_bot(Client *c, const Seperator *sep)
|
||||
subcommand_list.push_back("botstance");
|
||||
subcommand_list.push_back("botstopmeleelevel");
|
||||
subcommand_list.push_back("botsummon");
|
||||
subcommand_list.push_back("bottogglearcher");
|
||||
subcommand_list.push_back("bottoggleranged");
|
||||
subcommand_list.push_back("bottogglehelm");
|
||||
subcommand_list.push_back("botupdate");
|
||||
|
||||
@@ -33,7 +33,7 @@ void bot_command_camp(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_camp", sep->arg[0], "botcamp"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
@@ -452,8 +452,8 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_follow_distance", sep->arg[0], "botfollowdistance"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [set [1 to %i]] [distance] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0], BOT_FOLLOW_DISTANCE_DEFAULT_MAX);
|
||||
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -464,7 +464,7 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
|
||||
|
||||
if (!strcasecmp(sep->arg[1], "set")) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A numeric [distance] is required to use this command");
|
||||
c->Message(Chat::White, "A numeric [distance] is required to use this command. [1 to %i]", BOT_FOLLOW_DISTANCE_DEFAULT_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -492,22 +492,15 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
|
||||
continue;
|
||||
|
||||
bot_iter->SetFollowDistance(bfd);
|
||||
if (ab_type != ActionableBots::ABT_All && !database.botdb.SaveFollowDistance(bot_iter->GetBotID(), bfd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
++bot_count;
|
||||
}
|
||||
|
||||
if (ab_type == ActionableBots::ABT_All) {
|
||||
if (!database.botdb.SaveAllFollowDistances(c->CharacterID(), bfd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(Chat::White, "%s all of your bot follow distances", set_flag ? "Set" : "Cleared");
|
||||
c->Message(Chat::White, "%s all of your bot follow distances to %i", set_flag ? "Set" : "Cleared", bfd);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "%s %i of your spawned bot follow distances", (set_flag ? "Set" : "Cleared"), bot_count);
|
||||
c->Message(Chat::White, "%s %i of your spawned bot follow distances to %i", (set_flag ? "Set" : "Cleared"), bot_count, bfd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +509,7 @@ void bot_command_inspect_message(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_inspect_message", sep->arg[0], "botinspectmessage"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "Notes:");
|
||||
if (c->ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
||||
c->Message(Chat::White, "- Self-inspect and type your bot's inspect message");
|
||||
@@ -764,75 +757,31 @@ void bot_command_list_bots(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_out_of_combat(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_out_of_combat", sep->arg[0], "botoutofcombat"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
bool behavior_state = false;
|
||||
bool toggle_behavior = true;
|
||||
int ab_arg = 1;
|
||||
if (!arg1.compare("on")) {
|
||||
behavior_state = true;
|
||||
toggle_behavior = false;
|
||||
ab_arg = 2;
|
||||
}
|
||||
else if (!arg1.compare("off")) {
|
||||
toggle_behavior = false;
|
||||
ab_arg = 2;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None)
|
||||
return;
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter)
|
||||
continue;
|
||||
|
||||
if (toggle_behavior)
|
||||
bot_iter->SetAltOutOfCombatBehavior(!bot_iter->GetAltOutOfCombatBehavior());
|
||||
else
|
||||
bot_iter->SetAltOutOfCombatBehavior(behavior_state);
|
||||
|
||||
helper_bot_out_of_combat(c, bot_iter);
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_report(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_report", sep->arg[0], "botreport"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string ab_type_arg = sep->arg[1];
|
||||
if (ab_type_arg.empty()) {
|
||||
auto t = c->GetTarget();
|
||||
if (t && t->IsClient()) {
|
||||
if (t->CastToClient() == c) {
|
||||
ab_type_arg = "ownergroup";
|
||||
} else {
|
||||
ab_type_arg = "targetgroup";
|
||||
}
|
||||
} else {
|
||||
ab_type_arg = "spawned";
|
||||
}
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, ab_type_arg, sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter)
|
||||
@@ -1062,65 +1011,74 @@ void bot_command_spawn(Client *c, const Seperator *sep)
|
||||
|
||||
void bot_command_stance(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_stance", sep->arg[0], "botstance"))
|
||||
if (helper_command_alias_fail(c, "bot_command_stance", sep->arg[0], "botstance")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [current | value: 1-9] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [current | value: 1-9] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Value: {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({})",
|
||||
"Value: {} ({}), {} ({}), {} ({})",
|
||||
Stance::Passive,
|
||||
Stance::GetName(Stance::Passive),
|
||||
Stance::Balanced,
|
||||
Stance::GetName(Stance::Balanced),
|
||||
Stance::Efficient,
|
||||
Stance::GetName(Stance::Efficient),
|
||||
Stance::Reactive,
|
||||
Stance::GetName(Stance::Reactive),
|
||||
Stance::Aggressive,
|
||||
Stance::GetName(Stance::Aggressive),
|
||||
Stance::Assist,
|
||||
Stance::GetName(Stance::Assist),
|
||||
Stance::Burn,
|
||||
Stance::GetName(Stance::Burn),
|
||||
Stance::Efficient2,
|
||||
Stance::GetName(Stance::Efficient2),
|
||||
Stance::AEBurn,
|
||||
Stance::GetName(Stance::AEBurn)
|
||||
Stance::GetName(Stance::Aggressive)
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
||||
|
||||
bool current_flag = false;
|
||||
uint8 bst = Stance::Unknown;
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
if (!strcasecmp(sep->arg[1], "current"))
|
||||
current_flag = true;
|
||||
else if (sep->IsNumber(1)) {
|
||||
bst = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
|
||||
if (!Stance::IsValid(bst)) {
|
||||
bst = Stance::Unknown;
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 value = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
++ab_arg;
|
||||
value = atoi(sep->arg[1]);
|
||||
if (value < 0 || value > 300) {
|
||||
c->Message(Chat::White, "You must enter a value within the range of 0 - 300.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_flag && bst == Stance::Unknown) {
|
||||
c->Message(Chat::White, "A [current] argument or valid numeric [value] is required to use this command");
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None)
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_check && (value == Stance::Unknown || (value != Stance::Passive && value != Stance::Balanced && value != Stance::Aggressive))) {
|
||||
c->Message(Chat::White, "A [current] argument or valid numeric [value] is required to use this command");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter)
|
||||
continue;
|
||||
|
||||
if (!current_flag) {
|
||||
bot_iter->SetBotStance(bst);
|
||||
if (!current_check) {
|
||||
bot_iter->SetBotStance(value);
|
||||
bot_iter->Save();
|
||||
}
|
||||
|
||||
@@ -1135,50 +1093,138 @@ void bot_command_stance(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_stop_melee_level(Client *c, const Seperator *sep)
|
||||
void bot_command_stop_melee_level(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_stop_melee_level", sep->arg[0], "botstopmeleelevel"))
|
||||
if (helper_command_alias_fail(c, "bot_command_stop_melee_level", sep->arg[0], "botstopmeleelevel")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: <target_bot> %s [current | reset | sync | value: 0-255]", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [current | reset | sync | value: 0-255] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Only caster or hybrid class bots may be modified");
|
||||
c->Message(Chat::White, "note: Use [reset] to set stop melee level to server rule");
|
||||
c->Message(Chat::White, "note: Use [sync] to set stop melee level to current bot level");
|
||||
return;
|
||||
}
|
||||
|
||||
auto my_bot = ActionableBots::AsTarget_ByBot(c);
|
||||
if (!my_bot) {
|
||||
c->Message(Chat::White, "You must <target> a bot that you own to use this command");
|
||||
return;
|
||||
}
|
||||
if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) {
|
||||
c->Message(Chat::White, "You must <target> a caster or hybrid class bot to use this command");
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
uint8 sml = RuleI(Bots, CasterStopMeleeLevel);
|
||||
bool sync_sml = false;
|
||||
bool reset_sml = false;
|
||||
bool current_check = false;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
ab_arg = 2;
|
||||
sml = Strings::ToInt(sep->arg[1]);
|
||||
if (sml <= 0 || sml > 255) {
|
||||
c->Message(Chat::White, "You must provide a value between 0-255.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "sync")) {
|
||||
sml = my_bot->GetLevel();
|
||||
ab_arg = 2;
|
||||
sync_sml = true;
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "current")) {
|
||||
c->Message(Chat::White, "My current melee stop level is %u", my_bot->GetStopMeleeLevel());
|
||||
else if (!arg1.compare("current")) {
|
||||
ab_arg = 2;
|
||||
current_check = true;
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "reset")) {
|
||||
ab_arg = 2;
|
||||
reset_sml = true;
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "reset")) {
|
||||
c->Message(Chat::White, "A [current] or [reset] argument, or numeric [value] is required to use this command");
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
// [reset] falls through with initialization value
|
||||
|
||||
my_bot->SetStopMeleeLevel(sml);
|
||||
database.botdb.SaveStopMeleeLevel(my_bot->GetBotID(), sml);
|
||||
sbl.remove(nullptr);
|
||||
|
||||
c->Message(Chat::White, "Successfully set stop melee level for %s to %u", my_bot->GetCleanName(), sml);
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
|
||||
for (auto my_bot : sbl) {
|
||||
if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} says, 'This command only works on caster or hybrid classes.'",
|
||||
my_bot->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
|
||||
if (sync_sml) {
|
||||
sml = my_bot->GetLevel();
|
||||
}
|
||||
|
||||
if (reset_sml) {
|
||||
sml = my_bot->GetDefaultBotBaseSetting(BotBaseSettings::StopMeleeLevel);
|
||||
}
|
||||
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} says, 'My current stop melee level is {}.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetStopMeleeLevel()
|
||||
).c_str()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
my_bot->SetStopMeleeLevel(sml);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} says, 'My stop melee level was {} to {}.'",
|
||||
first_found->GetCleanName(),
|
||||
reset_sml ? "reset" : "set",
|
||||
sml
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} of your bots {} their stop melee{}'", // level to {}.
|
||||
success_count,
|
||||
reset_sml ? "reset" : "set",
|
||||
fmt::format("{}", reset_sml ? "." : fmt::format(" level to {}.", sml).c_str()).c_str(),
|
||||
sml
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_summon(Client *c, const Seperator *sep)
|
||||
@@ -1188,19 +1234,24 @@ void bot_command_summon(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string class_race_arg = sep->arg[1];
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1245,34 +1296,44 @@ void bot_command_summon(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void bot_command_toggle_archer(Client *c, const Seperator *sep)
|
||||
void bot_command_toggle_ranged(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_toggle_archer", sep->arg[0], "bottogglearcher")) {
|
||||
if (helper_command_alias_fail(c, "bot_command_toggle_ranged", sep->arg[0], "bottoggleranged")) {
|
||||
return;
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Toggles a ranged bot between melee and ranged weapon use");
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
bool archer_state = false;
|
||||
bool toggle_archer = true;
|
||||
bool ranged_state = false;
|
||||
bool toggle_ranged = true;
|
||||
int ab_arg = 1;
|
||||
if (!arg1.compare("on")) {
|
||||
archer_state = true;
|
||||
toggle_archer = false;
|
||||
ab_arg = 2;
|
||||
ranged_state = true;
|
||||
toggle_ranged = false;
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("off")) {
|
||||
toggle_archer = false;
|
||||
ab_arg = 2;
|
||||
toggle_ranged = false;
|
||||
++ab_arg;
|
||||
}
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) {
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1281,17 +1342,18 @@ void bot_command_toggle_archer(Client *c, const Seperator *sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (toggle_archer) {
|
||||
bot_iter->SetBotArcherySetting(!bot_iter->IsBotArcher(), true);
|
||||
if (bot_iter->GetBotRangedValue() < RuleI(Combat, MinRangedAttackDist)) {
|
||||
c->Message(Chat::Yellow, "%s does not have proper weapons or ammo to be at range.", bot_iter->GetCleanName());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (toggle_ranged) {
|
||||
bot_iter->SetBotRangedSetting(!bot_iter->IsBotRanged());
|
||||
}
|
||||
else {
|
||||
bot_iter->SetBotArcherySetting(archer_state, true);
|
||||
}
|
||||
bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher());
|
||||
|
||||
if (bot_iter->GetClass() == Class::Ranger && bot_iter->GetLevel() >= 61) {
|
||||
bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher());
|
||||
bot_iter->SetBotRangedSetting(ranged_state);
|
||||
}
|
||||
bot_iter->ChangeBotRangedWeapons(bot_iter->IsBotRanged());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1300,7 +1362,7 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_toggle_helm", sep->arg[0], "bottogglehelm"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -1313,11 +1375,11 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
|
||||
if (!arg1.compare("on")) {
|
||||
helm_state = true;
|
||||
toggle_helm = false;
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("off")) {
|
||||
toggle_helm = false;
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
@@ -1336,9 +1398,6 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
|
||||
bot_iter->SetShowHelm(helm_state);
|
||||
|
||||
if (ab_type != ActionableBots::ABT_All) {
|
||||
if (!database.botdb.SaveHelmAppearance(bot_iter->GetBotID(), bot_iter->GetShowHelm())) {
|
||||
return;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||
SpawnAppearance_Struct* saptr = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||
@@ -1355,13 +1414,6 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
if (ab_type == ActionableBots::ABT_All) {
|
||||
if (toggle_helm) {
|
||||
database.botdb.ToggleAllHelmAppearances(c->CharacterID());
|
||||
}
|
||||
else {
|
||||
database.botdb.SaveAllHelmAppearances(c->CharacterID(), helm_state);
|
||||
}
|
||||
|
||||
c->Message(Chat::White, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared"));
|
||||
}
|
||||
else {
|
||||
@@ -1439,7 +1491,6 @@ void bot_command_update(Client *c, const Seperator *sep)
|
||||
if (!bot_iter || bot_iter->IsEngaged() || bot_iter->GetLevel() == c->GetLevel())
|
||||
continue;
|
||||
|
||||
bot_iter->SetPetChooser(false);
|
||||
bot_iter->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
|
||||
bot_iter->SendAppearancePacket(AppearanceType::WhoLevel, bot_iter->GetLevel(), true, true);
|
||||
++bot_count;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_bot_settings(Client* c, const Seperator* sep)
|
||||
{
|
||||
std::list<const char*> subcommand_list;
|
||||
subcommand_list.push_back("behindmob");
|
||||
subcommand_list.push_back("casterrange");
|
||||
subcommand_list.push_back("copysettings");
|
||||
subcommand_list.push_back("defaultsettings");
|
||||
subcommand_list.push_back("enforcespelllist");
|
||||
subcommand_list.push_back("follow");
|
||||
subcommand_list.push_back("followdistance");
|
||||
subcommand_list.push_back("illusionblock");
|
||||
subcommand_list.push_back("maxmeleerange");
|
||||
subcommand_list.push_back("owneroption");
|
||||
subcommand_list.push_back("petsettype");
|
||||
subcommand_list.push_back("sithppercent");
|
||||
subcommand_list.push_back("sitincombat");
|
||||
subcommand_list.push_back("sitmanapercent");
|
||||
subcommand_list.push_back("sithppercent");
|
||||
subcommand_list.push_back("spellaggrocheck");
|
||||
subcommand_list.push_back("spelldelays");
|
||||
subcommand_list.push_back("spellengagedpriority");
|
||||
subcommand_list.push_back("spellholds");
|
||||
subcommand_list.push_back("spellidlepriority");
|
||||
subcommand_list.push_back("spellmaxhppct");
|
||||
subcommand_list.push_back("spellmaxmanapct");
|
||||
subcommand_list.push_back("spellmaxthresholds");
|
||||
subcommand_list.push_back("spellminhppct");
|
||||
subcommand_list.push_back("spellminmanapct");
|
||||
subcommand_list.push_back("spellminthresholds");
|
||||
subcommand_list.push_back("spellpursuepriority");
|
||||
subcommand_list.push_back("spelltargetcount");
|
||||
subcommand_list.push_back("spelllist");
|
||||
subcommand_list.push_back("stance");
|
||||
subcommand_list.push_back("togglehelm");
|
||||
subcommand_list.push_back("bottoggleranged");
|
||||
|
||||
if (helper_command_alias_fail(c, "bot_command_bot_settings", sep->arg[0], "botsettings"))
|
||||
return;
|
||||
|
||||
helper_send_available_subcommands(c, "botsettings", subcommand_list);
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_cast(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Commands bots to force cast a specific spell type, ignoring all settings (holds, delays, thresholds, etc)"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- This will interrupt any spell currently being cast by bots told to use the command.",
|
||||
"- Bots will still check to see if they have the spell in their spell list, whether the target is immune, spell is allowed and all other sanity checks for spells"
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To tell everyone to Nuke the target:",
|
||||
fmt::format(
|
||||
"{} {} spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Nuke
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To tell all Enchanters to slow the target:",
|
||||
fmt::format(
|
||||
"{} {} byclass {}",
|
||||
sep->arg[0],
|
||||
Class::Enchanter,
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Slow)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} byclass {}",
|
||||
sep->arg[0],
|
||||
Class::Enchanter,
|
||||
BotSpellTypes::Slow
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To tell Clrbot to resurrect the targeted corpse:",
|
||||
fmt::format(
|
||||
"{} {} byname Clrbot",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Resurrect)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} byname Clrbot",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Resurrect
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 2;
|
||||
uint16 spellType = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
spellType == BotSpellTypes::PetBuffs ||
|
||||
spellType == BotSpellTypes::PetCompleteHeals ||
|
||||
spellType == BotSpellTypes::PetFastHeals ||
|
||||
spellType == BotSpellTypes::PetHoTHeals ||
|
||||
spellType == BotSpellTypes::PetRegularHeals ||
|
||||
spellType == BotSpellTypes::PetVeryFastHeals
|
||||
) {
|
||||
c->Message(Chat::Yellow, "Pet type heals and buffs are not supported, use the regular spell type.");
|
||||
return;
|
||||
}
|
||||
|
||||
Mob* tar = c->GetTarget();
|
||||
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme
|
||||
if (spellType != BotSpellTypes::Escape && spellType != BotSpellTypes::Pet) {
|
||||
if (!tar) {
|
||||
c->Message(Chat::Yellow, "You need a target for that.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType) && !c->IsAttackAllowed(tar)) {
|
||||
c->Message(Chat::Yellow, "You cannot attack [%s].", tar->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_BENEFICIAL(spellType)) {
|
||||
if (!tar->IsOfClientBot() && !(tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot())) {
|
||||
c->Message(Chat::Yellow, "[%s] is an invalid target.", tar->GetCleanName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Stun:
|
||||
case BotSpellTypes::AEStun:
|
||||
if (tar->GetSpecialAbility(SpecialAbility::StunImmunity)) {
|
||||
c->Message(Chat::Yellow, "[%s] is immune to stuns.", tar->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case BotSpellTypes::Resurrect:
|
||||
if (!tar->IsCorpse() || !tar->CastToCorpse()->IsPlayerCorpse()) {
|
||||
c->Message(Chat::Yellow, "[%s] is an invalid target. I can only resurrect player corpses.", tar->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
BotSpell botSpell;
|
||||
botSpell.SpellId = 0;
|
||||
botSpell.SpellIndex = 0;
|
||||
botSpell.ManaCost = 0;
|
||||
bool isSuccess = false;
|
||||
uint16 successCount = 0;
|
||||
Bot* firstFound = nullptr;
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter->IsInGroupOrRaid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO bot rewrite -
|
||||
FIX: Snares, Group Cures, OOC Song, Precombat, HateRedux, Fear/AE Fear
|
||||
ICB (SK) casting hate on friendly but not hostile?
|
||||
NEED TO CHECK: precombat, AE Dispel, AE Lifetap
|
||||
DO I NEED A PBAE CHECK???
|
||||
*/
|
||||
if (bot_iter->GetHoldFlag() || bot_iter->GetAppearance() == eaDead || bot_iter->IsFeared() || bot_iter->IsStunned() || bot_iter->IsMezzed() || bot_iter->DivineAura() || bot_iter->GetHP() < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Mob* newTar = tar;
|
||||
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
|
||||
if (!SpellTypeRequiresTarget(spellType, bot_iter->GetClass())) {
|
||||
newTar = bot_iter;
|
||||
}
|
||||
|
||||
if (!newTar) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType, bot_iter->GetClass()) && !bot_iter->IsAttackAllowed(newTar)) {
|
||||
bot_iter->BotGroupSay(
|
||||
bot_iter,
|
||||
fmt::format(
|
||||
"I cannot attack [{}].",
|
||||
newTar->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
|
||||
|
||||
bot_iter->SetCommandedSpell(true);
|
||||
|
||||
if (bot_iter->AICastSpell(newTar, 100, spellType)) {
|
||||
if (!firstFound) {
|
||||
firstFound = bot_iter;
|
||||
}
|
||||
|
||||
isSuccess = true;
|
||||
++successCount;
|
||||
}
|
||||
|
||||
bot_iter->SetCommandedSpell(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isSuccess) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"No bots are capable of casting [{}] on {}.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
tar ? tar->GetCleanName() : "your target"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message( Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} {} [{}]{}",
|
||||
((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())),
|
||||
((successCount == 1 && firstFound) ? "casted" : "of your bots casted"),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
tar ? (fmt::format(" on {}.", tar->GetCleanName()).c_str()) : "."
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [current | value: 0 - 300] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [current | value: 0 - 300] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Can only be used for Casters or Hybrids.");
|
||||
c->Message(Chat::White, "note: Use [current] to check the current setting.");
|
||||
c->Message(Chat::White, "note: Set the value to the minimum distance you want your bot to try to remain from its target.");
|
||||
@@ -15,6 +15,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
c->Message(Chat::White, "note: This is set to (90) units by default.");
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
@@ -23,7 +24,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
uint32 crange = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
crange = atoi(sep->arg[1]);
|
||||
if (crange < 0 || crange > 300) {
|
||||
c->Message(Chat::White, "You must enter a value within the range of 0 - 300.");
|
||||
@@ -31,7 +32,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
@@ -78,8 +79,6 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
|
||||
else {
|
||||
my_bot->SetBotCasterRange(crange);
|
||||
++success_count;
|
||||
|
||||
database.botdb.SaveBotCasterRange(my_bot->GetBotID(), crange);
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_class_race_list(Client* c, const Seperator* sep)
|
||||
{
|
||||
const std::string class_substrs[17] = {
|
||||
"",
|
||||
"WAR", "CLR", "PAL", "RNG",
|
||||
"SHD", "DRU", "MNK", "BRD",
|
||||
"ROG", "SHM", "NEC", "WIZ",
|
||||
"MAG", "ENC", "BST", "BER"
|
||||
};
|
||||
|
||||
const std::string race_substrs[17] = {
|
||||
"",
|
||||
"HUM", "BAR", "ERU", "ELF",
|
||||
"HIE", "DEF", "HEF", "DWF",
|
||||
"TRL", "OGR", "HFL", "GNM",
|
||||
"IKS", "VAH", "FRG", "DRK"
|
||||
};
|
||||
|
||||
const uint16 race_values[17] = {
|
||||
Race::Doug,
|
||||
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf,
|
||||
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf,
|
||||
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome,
|
||||
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin
|
||||
};
|
||||
|
||||
std::string window_text;
|
||||
std::string message_separator;
|
||||
int object_count = 0;
|
||||
const int object_max = 4;
|
||||
|
||||
window_text.append(
|
||||
fmt::format(
|
||||
"<c \"#EDDA74\">Classes{}<c \"#357EC7\">",
|
||||
DialogueWindow::Break()
|
||||
)
|
||||
);
|
||||
|
||||
window_text.append(
|
||||
fmt::format(
|
||||
"<c \"#D4A017\">--------------------------------------------------------------------<c \"#357EC7\">",
|
||||
DialogueWindow::Break()
|
||||
)
|
||||
);
|
||||
|
||||
window_text.append(DialogueWindow::Break());
|
||||
|
||||
message_separator = " ";
|
||||
object_count = 0;
|
||||
for (int i = 0; i <= 15; ++i) {
|
||||
window_text.append(message_separator);
|
||||
|
||||
if (object_count >= object_max) {
|
||||
window_text.append(DialogueWindow::Break());
|
||||
object_count = 0;
|
||||
}
|
||||
|
||||
window_text.append(
|
||||
fmt::format("{} ({})",
|
||||
class_substrs[i + 1],
|
||||
(i + 1)
|
||||
)
|
||||
);
|
||||
|
||||
++object_count;
|
||||
message_separator = ", ";
|
||||
}
|
||||
|
||||
window_text.append(DialogueWindow::Break(2));
|
||||
|
||||
window_text.append(
|
||||
fmt::format(
|
||||
"<c \"#EDDA74\">Races{}<c \"#357EC7\">",
|
||||
DialogueWindow::Break()
|
||||
)
|
||||
);
|
||||
|
||||
window_text.append(
|
||||
fmt::format(
|
||||
"<c \"#D4A017\">--------------------------------------------------------------------<c \"#357EC7\">",
|
||||
DialogueWindow::Break()
|
||||
)
|
||||
);
|
||||
|
||||
window_text.append(DialogueWindow::Break());
|
||||
|
||||
message_separator = " ";
|
||||
object_count = 0;
|
||||
for (int i = 0; i <= 15; ++i) {
|
||||
window_text.append(message_separator);
|
||||
|
||||
if (object_count >= object_max) {
|
||||
window_text.append(DialogueWindow::Break());
|
||||
object_count = 0;
|
||||
}
|
||||
|
||||
window_text.append(
|
||||
fmt::format("{} ({})",
|
||||
race_substrs[i + 1],
|
||||
race_values[i + 1]
|
||||
)
|
||||
);
|
||||
|
||||
++object_count;
|
||||
message_separator = ", ";
|
||||
}
|
||||
|
||||
c->SendPopupToClient("Bot Creation Options", window_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ void bot_command_click_item(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: <slot id> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s <slot id> ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "This will cause the selected bots to click the item in the given slot ID.");
|
||||
c->Message(Chat::White, "Use ^invlist to see their items along with slot IDs.");
|
||||
return;
|
||||
@@ -25,7 +25,7 @@ void bot_command_click_item(Client* c, const Seperator* sep)
|
||||
uint32 slot_id = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
slot_id = atoi(sep->arg[1]);
|
||||
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
|
||||
c->Message(Chat::Yellow, "You must specify a valid inventory slot from 0 to 22. Use %s help for more information", sep->arg[0]);
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_copy_settings(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_copy_settings", sep->arg[0], "copysettings")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Copies settings from one bot to another bot"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [from] [to] [option]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To copy all settings from BotA to BotB:",
|
||||
fmt::format(
|
||||
"{} BotA BotB all",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To copy only Nuke spelltypesettings from BotA to BotB:",
|
||||
fmt::format(
|
||||
"{} BotA BotB spelltypesettings {}",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} BotA BotB spelltypesettings {}",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
};
|
||||
std::vector<std::string> examples_three = { };
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid",
|
||||
"targetgroup, namesgroup, healrotationtargets",
|
||||
"mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all, misc, spellsettings, spelltypesettings",
|
||||
"holds, delays, minthresholds, maxthresholds",
|
||||
"minmanapct, maxmanapct, minhppct, maxhppct",
|
||||
"idlepriority, engagedpriority, pursuepriority",
|
||||
"aggrochecks, targetcounts"
|
||||
};
|
||||
std::vector<std::string> options_one =
|
||||
{
|
||||
"[spellsettings] will copy ^spellsettings options",
|
||||
"[spelltypesettings] copies all spell type settings",
|
||||
"[all] copies all settings"
|
||||
};
|
||||
std::vector<std::string> options_two =
|
||||
{
|
||||
"[misc] copies all miscellaneous options such as:",
|
||||
"- ^showhelm, ^followd, ^stopmeleelevel",
|
||||
"- ^enforcespellsettings, ^bottoggleranged, ^petsettype",
|
||||
"- ^behindmob, ^casterrange, ^illusionblock",
|
||||
"- ^sitincombat, ^sithppercent and ^sitmanapercent",
|
||||
|
||||
};
|
||||
std::vector<std::string> options_three =
|
||||
{
|
||||
"The remaining options copy that specific type"
|
||||
};
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 2;
|
||||
bool validOption = false;
|
||||
uint16 spellType = UINT16_MAX;
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all",
|
||||
"misc"
|
||||
"spellsettings",
|
||||
"spelltypesettings",
|
||||
"holds",
|
||||
"delays",
|
||||
"minthresholds",
|
||||
"maxthresholds",
|
||||
"aggrochecks",
|
||||
"minmanapct",
|
||||
"maxmanapct",
|
||||
"minhppct",
|
||||
"maxhppct",
|
||||
"idlepriority",
|
||||
"engagedpriority",
|
||||
"pursuepriority",
|
||||
"targetcounts"
|
||||
};
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (sep->arg[3] == options[i]) {
|
||||
if (options[i] != "all" && options[i] != "misc" && options[i] != "spellsettings") {
|
||||
|
||||
if (sep->IsNumber(4) || c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX) {
|
||||
if (sep->IsNumber(4)) {
|
||||
spellType = atoi(sep->arg[4]);
|
||||
}
|
||||
|
||||
if (c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(sep->arg[4]);
|
||||
}
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (
|
||||
(options[i] == "all" || options[i] == "misc" || options[i] == "spellsettings") &&
|
||||
((sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX))
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
validOption = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!validOption) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto from = entity_list.GetBotByBotName(sep->arg[1]);
|
||||
|
||||
if (!from) {
|
||||
c->Message(Chat::Yellow, "Could not find %s.", sep->arg[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from->IsBot()) {
|
||||
c->Message(Chat::Yellow, "%s is not a bot.", from->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from->GetOwner()) {
|
||||
c->Message(Chat::Yellow, "Could not find %s's owner.", from->GetCleanName());
|
||||
}
|
||||
|
||||
if (RuleB(Bots, CopySettingsOwnBotsOnly) && from->GetOwner() != c) {
|
||||
c->Message(Chat::Yellow, "You name a bot you own to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RuleB(Bots, AllowCopySettingsAnon) && from->GetOwner() != c && from->GetOwner()->CastToClient()->GetAnon()) {
|
||||
c->Message(Chat::Yellow, "You name a bot you own to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto to = ActionableBots::AsNamed_ByBot(c, sep->arg[2]);
|
||||
|
||||
if (!to) {
|
||||
c->Message(Chat::Yellow, "Could not find %s.", sep->arg[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!to->IsBot()) {
|
||||
c->Message(Chat::Yellow, "%s is not a bot.", to->GetCleanName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!to->GetOwner()) {
|
||||
c->Message(Chat::Yellow, "Could not find %s's owner.", to->GetCleanName());
|
||||
}
|
||||
|
||||
if (to->GetOwner() != c) {
|
||||
c->Message(Chat::Yellow, "You must name a spawned bot that you own to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (to == from) {
|
||||
c->Message(Chat::Yellow, "You cannot copy to the same bot that you're copying from.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string output = "";
|
||||
|
||||
if (!strcasecmp(sep->arg[3], "misc")) {
|
||||
from->CopySettings(to, BotSettingCategories::BaseSetting);
|
||||
output = "Miscellaneous";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "holds")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellHold);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "delays")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellDelay);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "minthresholds")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellMinThreshold);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "maxthresholds")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellMaxThreshold);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "aggrochecks")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeAggroCheck);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "minmanapct")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMinManaPct);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "maxmanapct")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMaxManaPct);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "minhppct")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMinHPPct);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "maxhppct")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMaxHPPct);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "idlepriority")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeIdlePriority);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "engagedpriority")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeEngagedPriority);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "pursuepriority")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypePursuePriority);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "targetcounts")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
|
||||
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeAEOrGroupTargetCount);
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "spellsettings")) {
|
||||
from->CopyBotSpellSettings(to);
|
||||
output = "^spellsettings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "spelltypesettings")) {
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
|
||||
output = "spell type";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[3], "all")) {
|
||||
from->CopySettings(to, BotSettingCategories::BaseSetting);
|
||||
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
|
||||
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
|
||||
from->CopyBotSpellSettings(to);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{}'s{}{} settings were copied to {}.",
|
||||
from->GetCleanName(),
|
||||
(
|
||||
spellType != UINT16_MAX ?
|
||||
fmt::format(" [{}] ",
|
||||
c->GetSpellTypeNameByID(spellType)
|
||||
)
|
||||
: " "
|
||||
),
|
||||
output,
|
||||
to->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,473 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_default_settings(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_default_settings", sep->arg[0], "defaultsettings")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Restores a bot's setting(s) to defaults"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [option] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To restore delays for Clerics:",
|
||||
fmt::format(
|
||||
"{} delays byclass 2",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To restore only Snare delays for BotA:",
|
||||
fmt::format(
|
||||
"{} delays {} byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} delays {} byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three = { };
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all, misc, spellsettings, spelltypesettings, holds, delays, minthresholds, maxthresholds minmanapct, maxmanapct, minhppct, maxhppct, idlepriority, engagedpriority, pursuepriority, aggrocheck, targetcounts"
|
||||
};
|
||||
std::vector<std::string> options_one =
|
||||
{
|
||||
"[spellsettings] will restore ^spellsettings options",
|
||||
"[spelltypesettings] restores all spell type settings",
|
||||
"[all] restores all settings"
|
||||
};
|
||||
std::vector<std::string> options_two =
|
||||
{
|
||||
"[misc] restores all miscellaneous options such as:",
|
||||
"- ^showhelm, ^followd, ^stopmeleelevel",
|
||||
"- ^enforcespellsettings, ^bottoggleranged, ^petsettype",
|
||||
"- ^behindmob, ^casterrange, ^illusionblock",
|
||||
"- ^sitincombat, ^sithppercent and ^sitmanapercent",
|
||||
|
||||
};
|
||||
std::vector<std::string> options_three =
|
||||
{
|
||||
"The remaining options restore that specific type"
|
||||
};
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 2;
|
||||
bool validOption = false;
|
||||
uint16 spellType = UINT16_MAX;
|
||||
std::vector<std::string> options =
|
||||
{
|
||||
"all",
|
||||
"misc"
|
||||
"spellsettings",
|
||||
"spelltypesettings",
|
||||
"holds",
|
||||
"delays",
|
||||
"minthresholds",
|
||||
"maxthresholds",
|
||||
"aggrocheck",
|
||||
"minmanapct",
|
||||
"maxmanapct",
|
||||
"minhppct",
|
||||
"maxhppct",
|
||||
"idlepriority",
|
||||
"engagedpriority",
|
||||
"pursuepriority",
|
||||
"targetcounts"
|
||||
};
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (sep->arg[1] == options[i]) {
|
||||
if (options[i] != "all" && options[i] != "misc" && options[i] != "spellsettings") {
|
||||
|
||||
if (sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX) {
|
||||
if (sep->IsNumber(2)) {
|
||||
spellType = atoi(sep->arg[2]);
|
||||
}
|
||||
|
||||
if (c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(sep->arg[2]);
|
||||
}
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++ab_arg;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
(options[i] == "all" || options[i] == "misc" || options[i] == "spellsettings") &&
|
||||
((sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX))
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
validOption = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!validOption) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
std::string output = "";
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
|
||||
if (!strcasecmp(sep->arg[1], "misc")) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i));
|
||||
output = "miscellanous settings";
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "holds")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellHold(spellType, my_bot->GetDefaultSpellHold(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "hold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "delays")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "delay settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minthresholds")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellMinThreshold(spellType, my_bot->GetDefaultSpellMinThreshold(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "minimum threshold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxthresholds")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellMaxThreshold(spellType, my_bot->GetDefaultSpellMaxThreshold(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "maximum threshold settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "aggrochecks")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeAggroCheck(spellType, my_bot->GetDefaultSpellTypeAggroCheck(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "aggro check settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minmanapct")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMinManaLimit(spellType, my_bot->GetDefaultSpellTypeMinManaLimit(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "min mana settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxmanapct")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMaxManaLimit(spellType, my_bot->GetDefaultSpellTypeMaxManaLimit(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "max mana settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "minhppct")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMinHPLimit(spellType, my_bot->GetDefaultSpellTypeMinHPLimit(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "min hp settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "maxhppct")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypeMaxHPLimit(spellType, my_bot->GetDefaultSpellTypeMaxHPLimit(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "max hp settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "idlepriority")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetClass()));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
|
||||
}
|
||||
}
|
||||
|
||||
output = "idle priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "engagedpriority")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetClass()));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
|
||||
}
|
||||
}
|
||||
|
||||
output = "engaged priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "pursuepriority")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetClass()));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
|
||||
}
|
||||
}
|
||||
|
||||
output = "pursue priority settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "targetcounts")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "ae/group count settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "spellsettings")) {
|
||||
my_bot->ResetBotSpellSettings();
|
||||
output = "^spellsettings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "spelltypesettings")) {
|
||||
if (spellType != UINT16_MAX) {
|
||||
my_bot->SetSpellHold(spellType, my_bot->GetDefaultSpellHold(spellType));
|
||||
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
|
||||
my_bot->SetSpellMinThreshold(spellType, my_bot->GetDefaultSpellMinThreshold(spellType));
|
||||
my_bot->SetSpellMaxThreshold(spellType, my_bot->GetDefaultSpellMaxThreshold(spellType));
|
||||
my_bot->SetSpellTypeAggroCheck(spellType, my_bot->GetDefaultSpellTypeAggroCheck(spellType));
|
||||
my_bot->SetSpellTypeMinManaLimit(spellType, my_bot->GetDefaultSpellTypeMinManaLimit(spellType));
|
||||
my_bot->SetSpellTypeMaxManaLimit(spellType, my_bot->GetDefaultSpellTypeMaxManaLimit(spellType));
|
||||
my_bot->SetSpellTypeMinHPLimit(spellType, my_bot->GetDefaultSpellTypeMinHPLimit(spellType));
|
||||
my_bot->SetSpellTypeMaxHPLimit(spellType, my_bot->GetDefaultSpellTypeMaxHPLimit(spellType));
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spellType, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spellType));
|
||||
}
|
||||
else {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
|
||||
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
|
||||
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
|
||||
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
|
||||
}
|
||||
}
|
||||
|
||||
output = "spell type settings";
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "all")) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i));
|
||||
}
|
||||
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
|
||||
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
|
||||
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
|
||||
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
|
||||
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
|
||||
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
|
||||
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
|
||||
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
|
||||
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
|
||||
};
|
||||
|
||||
my_bot->ResetBotSpellSettings();
|
||||
|
||||
output = "settings";
|
||||
|
||||
}
|
||||
|
||||
++success_count;
|
||||
}
|
||||
|
||||
if (success_count == 1) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, '{}{} were restored.'",
|
||||
first_found->GetCleanName(),
|
||||
(
|
||||
spellType != UINT16_MAX ?
|
||||
fmt::format("My [{}] ",
|
||||
c->GetSpellTypeNameByID(spellType)
|
||||
)
|
||||
: "My "
|
||||
),
|
||||
output
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bot's{}{} were restored.",
|
||||
success_count,
|
||||
(
|
||||
spellType != UINT16_MAX ?
|
||||
fmt::format(" [{}] ",
|
||||
c->GetSpellTypeNameByID(spellType)
|
||||
)
|
||||
: " "
|
||||
),
|
||||
output
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,22 +6,27 @@ void bot_command_defensive(Client *c, const Seperator *sep)
|
||||
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_defensive", sep->arg[0], "defensive"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string class_race_arg = sep->arg[1];
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
int success_count = 0;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_follow(Client *c, const Seperator *sep)
|
||||
void bot_command_follow(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_follow", sep->arg[0], "follow"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | ownerraid | namesgroup | mmr | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s chain", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
@@ -26,13 +26,22 @@ void bot_command_follow(Client *c, const Seperator *sep)
|
||||
}
|
||||
else if (!optional_arg.compare("reset")) {
|
||||
reset = true;
|
||||
ab_arg = 2;
|
||||
name_arg = 3;
|
||||
++ab_arg;
|
||||
++name_arg ;
|
||||
}
|
||||
else {
|
||||
target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single);
|
||||
//target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single);
|
||||
target_mob = c->GetTarget();
|
||||
if (!target_mob) {
|
||||
c->Message(Chat::White, "You must <target> a friendly mob to use this command");
|
||||
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
|
||||
return;
|
||||
}
|
||||
else if (!target_mob->IsBot() && !target_mob->IsClient()) {
|
||||
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
|
||||
return;
|
||||
}
|
||||
else if ((target_mob->GetGroup() && target_mob->GetGroup() != c->GetGroup()) || (target_mob->GetRaid() && target_mob->GetRaid() != c->GetRaid())) {
|
||||
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -51,29 +60,54 @@ void bot_command_follow(Client *c, const Seperator *sep)
|
||||
sbl.remove(nullptr);
|
||||
for (auto bot_iter : sbl) {
|
||||
bot_iter->WipeHateList();
|
||||
auto my_group = bot_iter->GetGroup();
|
||||
if (my_group) {
|
||||
if (reset) {
|
||||
if (!my_group->GetLeader() || my_group->GetLeader() == bot_iter)
|
||||
bot_iter->SetFollowID(c->GetID());
|
||||
else
|
||||
bot_iter->SetFollowID(my_group->GetLeader()->GetID());
|
||||
|
||||
bot_iter->SetManualFollow(false);
|
||||
}
|
||||
else {
|
||||
if (bot_iter == target_mob)
|
||||
bot_iter->SetFollowID(c->GetID());
|
||||
else
|
||||
bot_iter->SetFollowID(target_mob->GetID());
|
||||
|
||||
bot_iter->SetManualFollow(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!bot_iter->GetGroup() && !bot_iter->GetRaid()) {
|
||||
bot_iter->SetFollowID(0);
|
||||
bot_iter->SetManualFollow(false);
|
||||
}
|
||||
else {
|
||||
if (reset) {
|
||||
bot_iter->SetFollowID(c->GetID());
|
||||
bot_iter->SetManualFollow(false);
|
||||
}
|
||||
else {
|
||||
if (target_mob->IsGrouped() || target_mob->IsRaidGrouped()) {
|
||||
bot_iter->SetFollowID(target_mob->GetID());
|
||||
bot_iter->SetManualFollow(true);
|
||||
}
|
||||
else if (bot_iter == target_mob) {
|
||||
bot_iter->SetFollowID(c->GetID());
|
||||
bot_iter->SetManualFollow(true);
|
||||
}
|
||||
else {
|
||||
bot_iter->SetFollowID(0);
|
||||
bot_iter->SetManualFollow(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
//auto my_group = bot_iter->GetGroup();
|
||||
//if (my_group) {
|
||||
// if (reset) {
|
||||
// if (!my_group->GetLeader() || my_group->GetLeader() == bot_iter)
|
||||
// bot_iter->SetFollowID(c->GetID());
|
||||
// else
|
||||
// bot_iter->SetFollowID(my_group->GetLeader()->GetID());
|
||||
//
|
||||
// bot_iter->SetManualFollow(false);
|
||||
// }
|
||||
// else {
|
||||
// if (bot_iter == target_mob)
|
||||
// bot_iter->SetFollowID(c->GetID());
|
||||
// else
|
||||
// bot_iter->SetFollowID(target_mob->GetID());
|
||||
//
|
||||
// bot_iter->SetManualFollow(true);
|
||||
// }
|
||||
//}
|
||||
//else {
|
||||
// bot_iter->SetFollowID(0);
|
||||
// bot_iter->SetManualFollow(false);
|
||||
//}
|
||||
if (!bot_iter->GetPet())
|
||||
continue;
|
||||
|
||||
@@ -81,31 +115,37 @@ void bot_command_follow(Client *c, const Seperator *sep)
|
||||
bot_iter->GetPet()->SetFollowID(bot_iter->GetID());
|
||||
}
|
||||
|
||||
Mob* follow_mob = nullptr;
|
||||
if (sbl.size() == 1) {
|
||||
Mob* follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
|
||||
Bot::BotGroupSay(
|
||||
sbl.front(),
|
||||
follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Following {}.",
|
||||
follow_mob ? follow_mob->GetCleanName() : "no one"
|
||||
follow_mob ? follow_mob->GetCleanName() : "you"
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (reset) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} of your bots are following their default assignments.",
|
||||
"{} of your bots are following you.",
|
||||
sbl.size()
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!sbl.empty()) {
|
||||
follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} of your bots are following {}.",
|
||||
sbl.size(),
|
||||
target_mob->GetCleanName()
|
||||
follow_mob ? follow_mob->GetCleanName() : "you"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ void bot_command_guard(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
|
||||
@@ -20,8 +20,8 @@ void bot_command_guard(Client *c, const Seperator *sep)
|
||||
if (!clear_arg.compare("clear")) {
|
||||
|
||||
clear = true;
|
||||
ab_arg = 2;
|
||||
name_arg = 3;
|
||||
++ab_arg;
|
||||
++name_arg;
|
||||
}
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
|
||||
@@ -7,7 +7,7 @@ void bot_command_hold(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
|
||||
@@ -20,8 +20,8 @@ void bot_command_hold(Client *c, const Seperator *sep)
|
||||
if (!clear_arg.compare("clear")) {
|
||||
|
||||
clear = true;
|
||||
ab_arg = 2;
|
||||
name_arg = 3;
|
||||
++ab_arg;
|
||||
++name_arg;
|
||||
}
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_illusion_block(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_illusion_block", sep->arg[0], "illusionblock")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots will block the illusion effects of spells cast by players or bots."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set BotA to block illusions:",
|
||||
fmt::format(
|
||||
"{} 1 byname BotA",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the illusion block status for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} block illusions.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetIllusionBlock() ? "will" : "will not"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetIllusionBlock(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} block illusions.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetIllusionBlock() ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots {} block illusions.",
|
||||
success_count,
|
||||
typeValue ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,9 +217,18 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
|
||||
}
|
||||
|
||||
const auto* itm = inst->GetItem();
|
||||
EQ::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
||||
linker.SetItemInst(inst);
|
||||
|
||||
if (inst && itm && c->CheckLoreConflict(itm)) {
|
||||
c->MessageString(Chat::White, PICK_LORE);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You cannot pick up {} because it is a lore item you already possess.",
|
||||
linker.GenerateLink()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -233,7 +242,13 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
c->MessageString(Chat::White, PICK_LORE);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You cannot pick up {} because it is a lore item you already possess.",
|
||||
linker.GenerateLink()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -247,7 +262,7 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
|
||||
slot_id == EQ::invslot::slotRange ||
|
||||
slot_id == EQ::invslot::slotAmmo
|
||||
) {
|
||||
my_bot->SetBotArcherySetting(false, true);
|
||||
my_bot->SetBotRangedSetting(false);
|
||||
}
|
||||
|
||||
my_bot->RemoveBotItemBySlot(slot_id);
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_max_melee_range(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_max_melee_range", sep->arg[0], "maxmeleerange")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots will stay at max melee range during combat."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set BotA to stay at max melee range:",
|
||||
fmt::format(
|
||||
"{} 1 byname BotA",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the max melee range status for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} stay at max melee range.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetMaxMeleeRange() ? "will" : "will not"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetMaxMeleeRange(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} stay at max melee range.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetMaxMeleeRange() ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots {} stay at max melee range.",
|
||||
success_count,
|
||||
typeValue ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,42 +2,40 @@
|
||||
|
||||
void bot_command_mesmerize(Client *c, const Seperator *sep)
|
||||
{
|
||||
bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Mesmerize];
|
||||
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Mesmerize) || helper_command_alias_fail(c, "bot_command_mesmerize", sep->arg[0], "mesmerize"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s", sep->arg[0]);
|
||||
helper_send_usage_required_bots(c, BCEnum::SpT_Mesmerize);
|
||||
return;
|
||||
}
|
||||
|
||||
ActionableTarget::Types actionable_targets;
|
||||
Bot* my_bot = nullptr;
|
||||
bool isSuccess = false;
|
||||
std::list<Bot*> sbl;
|
||||
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
|
||||
|
||||
for (auto list_iter : *local_list) {
|
||||
auto local_entry = list_iter;
|
||||
if (helper_spell_check_fail(local_entry))
|
||||
continue;
|
||||
for (auto bot_iter : sbl) {
|
||||
std::list<BotSpell_wPriority> botSpellList = bot_iter->GetPrioritizedBotSpellsBySpellType(bot_iter, BotSpellTypes::Mez, c->GetTarget(), IsAEBotSpellType(BotSpellTypes::Mez));
|
||||
|
||||
auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY);
|
||||
if (!target_mob)
|
||||
continue;
|
||||
for (const auto& s : botSpellList) {
|
||||
if (!IsValidSpell(s.SpellId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spells[local_entry->spell_id].max_value[EFFECTIDTOINDEX(1)] < target_mob->GetLevel())
|
||||
continue;
|
||||
if (!bot_iter->IsInGroupOrRaid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob);
|
||||
if (!my_bot)
|
||||
continue;
|
||||
if (!bot_iter->CastChecks(s.SpellId, c->GetTarget(), BotSpellTypes::Mez, false, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 dont_root_before = 0;
|
||||
if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before))
|
||||
target_mob->SetDontRootMeBefore(dont_root_before);
|
||||
|
||||
break;
|
||||
if (bot_iter->CommandedDoSpellCast(s.SpellIndex, c->GetTarget(), s.ManaCost)) {
|
||||
bot_iter->BotGroupSay(bot_iter, "Casting %s [%s] on %s.", GetSpellName(s.SpellId), bot_iter->GetSpellTypeNameByID(BotSpellTypes::Mez), c->GetTarget()->GetCleanName());
|
||||
isSuccess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
helper_no_available_bots(c, my_bot);
|
||||
if (!isSuccess) {
|
||||
helper_no_available_bots(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ void bot_command_pet_get_lost(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_pet_get_lost", sep->arg[0], "petgetlost"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
@@ -98,7 +98,8 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_pet_set_type", sep->arg[0], "petsettype"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [type: water | fire | air | earth | monster] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [type: auto | water | fire | air | earth | monster | epic] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "if set to 'auto', bots will choose their own pet type");
|
||||
c->Message(Chat::White, "requires one of the following bot classes:");
|
||||
c->Message(Chat::White, "Magician(1)");
|
||||
return;
|
||||
@@ -109,29 +110,41 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
|
||||
|
||||
uint8 pet_type = 255;
|
||||
uint8 level_req = 255;
|
||||
if (!pet_arg.compare("water")) {
|
||||
if (!pet_arg.compare("auto")) {
|
||||
pet_type = 0;
|
||||
level_req = 1;
|
||||
}
|
||||
else if (!pet_arg.compare("fire")) {
|
||||
else if (!pet_arg.compare("water")) {
|
||||
pet_type = 1;
|
||||
level_req = 1;
|
||||
}
|
||||
else if (!pet_arg.compare("fire")) {
|
||||
pet_type = 2;
|
||||
level_req = 3;
|
||||
}
|
||||
else if (!pet_arg.compare("air")) {
|
||||
pet_type = 2;
|
||||
pet_type = 3;
|
||||
level_req = 4;
|
||||
}
|
||||
else if (!pet_arg.compare("earth")) {
|
||||
pet_type = 3;
|
||||
pet_type = 4;
|
||||
level_req = 5;
|
||||
}
|
||||
else if (!pet_arg.compare("monster")) {
|
||||
pet_type = 4;
|
||||
pet_type = 5;
|
||||
level_req = 30;
|
||||
}
|
||||
else if (!pet_arg.compare("epic")) {
|
||||
pet_type = 6;
|
||||
if (!RuleB(Bots, AllowMagicianEpicPet)) {
|
||||
c->Message(Chat::Yellow, "Epic pets are currently disabled for bots.");
|
||||
return;
|
||||
}
|
||||
level_req = RuleI(Bots,AllowMagicianEpicPetLevel);
|
||||
}
|
||||
|
||||
if (pet_type == 255) {
|
||||
c->Message(Chat::White, "You must specify a pet [type: water | fire | air | earth | monster]");
|
||||
c->Message(Chat::White, "You must specify a pet [type: auto | water | fire | air | earth | monster | epic]");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,7 +170,23 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
|
||||
if (!bot_iter)
|
||||
continue;
|
||||
|
||||
bot_iter->SetPetChooser(true);
|
||||
if (RuleI(Bots, RequiredMagicianEpicPetItemID) > 0) {
|
||||
bool has_item = bot_iter->HasBotItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) != INVALID_INDEX;
|
||||
|
||||
if (!has_item) {
|
||||
c->Message(
|
||||
Chat::Say,
|
||||
fmt::format(
|
||||
"{} says, 'I require {} to cast an epic pet which I do not currently possess.'",
|
||||
bot_iter->GetCleanName(),
|
||||
(database.GetItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) ? database.CreateItemLink(RuleI(Bots, RequiredMagicianEpicPetItemID)) : "an item")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bot_iter->SetPetChooserID(pet_type);
|
||||
if (bot_iter->GetPet()) {
|
||||
auto pet_id = bot_iter->GetPetID();
|
||||
|
||||
@@ -7,15 +7,27 @@ void bot_command_pull(Client *c, const Seperator *sep)
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: <enemy_target> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
int ab_mask = ActionableBots::ABM_OwnerGroup; // existing behavior - need to add c->IsGrouped() check and modify code if different behavior is desired
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
int ab_arg = 1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, "ownergroup", sbl, ab_mask) == ActionableBots::ABT_None) {
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
auto target_mob = ActionableTarget::VerifyEnemy(c, BCEnum::TT_Single);
|
||||
|
||||
@@ -5,7 +5,7 @@ void bot_command_release(Client *c, const Seperator *sep)
|
||||
if (helper_command_alias_fail(c, "bot_command_release", sep->arg[0], "release"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: <any>] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_sit_hp_percent(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_sit_hp_percent", sep->arg[0], "sithppercent")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"HP % threshold when bots will sit in combat if allowed."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set Clerics to sit at 45% HP:",
|
||||
fmt::format(
|
||||
"{} 45 byclass 2",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the HP threshold for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I sit in combat whem at or below [{}%%] HP.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetHPWhenToMed()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetHPWhenToMed(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I will now sit in combat whem at or below [{}%%] HP.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetHPWhenToMed()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots will now sit in combat whem at or below [{}%%] HP.'",
|
||||
success_count,
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_sit_in_combat(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_sit_in_combat", sep->arg[0], "sitincombat")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots will sit in combat to heal or med."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set Clerics to sit in combat:",
|
||||
fmt::format(
|
||||
"{} 1 byclass 2",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the sit in combat state for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} sit in combat.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetMedInCombat() ? "will" : "will not"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetMedInCombat(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I {} sit in combat.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetMedInCombat() ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots {} sit in combat.",
|
||||
success_count,
|
||||
typeValue ? "will now" : "will no longer"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_sit_mana_percent(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_sit_mana_percent", sep->arg[0], "sitmanapercent")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Mana % threshold when bots will sit in combat if allowed."
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set Clerics to sit at 45% mana:",
|
||||
fmt::format(
|
||||
"{} 45 byclass 2",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two = { };
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the mana threshold for all bots:",
|
||||
fmt::format(
|
||||
"{} current spawned",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
int ab_arg = 1;
|
||||
bool current_check = false;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
typeValue = atoi(sep->arg[1]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg1.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I sit in combat whem at or below [{}%%] mana.'",
|
||||
my_bot->GetCleanName(),
|
||||
my_bot->GetManaWhenToMed()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetManaWhenToMed(typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'I will now sit in combat whem at or below [{}%%] mana.'",
|
||||
first_found->GetCleanName(),
|
||||
first_found->GetManaWhenToMed()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots will now sit in combat whem at or below [{}%%] mana.'",
|
||||
success_count,
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,7 +503,7 @@ void bot_spell_info_dialogue_window(Client* c, const Seperator *sep)
|
||||
auto results = database.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT value FROM db_str WHERE id = {} and type = 6 LIMIT 1",
|
||||
spells[spell_id].effect_description_id
|
||||
spells[spell_id].description_id
|
||||
)
|
||||
);
|
||||
|
||||
@@ -557,7 +557,7 @@ void bot_command_enforce_spell_list(Client* c, const Seperator *sep)
|
||||
}
|
||||
|
||||
bool enforce_state = (sep->argnum > 0) ? Strings::ToBool(sep->arg[1]) : !my_bot->GetBotEnforceSpellSetting();
|
||||
my_bot->SetBotEnforceSpellSetting(enforce_state, true);
|
||||
my_bot->SetBotEnforceSpellSetting(enforce_state);
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_aggro_checks(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_aggro_checks", sep->arg[0], "spellaggrochecks")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots will cast a spell type if they think it will get them aggro"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to check aggro on nukes:",
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Nuke
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set Shadowknights to ignore aggro checks on snares:",
|
||||
fmt::format(
|
||||
"{} {} 0 byclass 5",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 0 byclass 5",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current DoT aggro check on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::DOT
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] aggro check is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeAggroCheck(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeAggroCheck(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] aggro check was [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeAggroCheck(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots [{}] their [{}] aggro check.",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_delays(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_delays", sep->arg[0], "spelldelays")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls how long a bot will wait between casts of different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- All pet types are based off the pet's owner's setting",
|
||||
"- Any remaining types use the owner's setting when a pet is the target",
|
||||
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
|
||||
"- e.g., BotA is healing BotB using BotB's settings",
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all Necromancers to an 8s DoT delay:",
|
||||
fmt::format(
|
||||
"{} {} 8000 byclass 11",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 8000 byclass 11",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::DOT
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set all Warriors to receive Fast Heals every 2.5s:",
|
||||
fmt::format(
|
||||
"{} {} 2500 byclass 1",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 2500 byclass 1",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Nuke delay on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Nuke
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 1 || typeValue > 60000) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 1-60000 (1ms to 60s).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] spell delay is currently [{}] seconds.'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellDelay(spellType) / 1000.00
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellDelay(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] spell delay was set to [{}] seconds.'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellDelay(spellType) / 1000.00
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] spell delay to [{}] seconds.",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue / 1000.00
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_engaged_priority(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_engaged_priority", sep->arg[0], "spellengagedpriority")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Sets the order of spell casts when engaged in combat by spell type"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"-Setting a spell type to 0 will prevent that type from being cast.",
|
||||
"-If 2 or more are set to the same priority they will sort by spell type ID."
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all Shaman to cast slows first:",
|
||||
fmt::format(
|
||||
"{} {} 1 byclass 10",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Slow)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 1 byclass 10",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Slow
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set all bots to not cast snares:",
|
||||
fmt::format(
|
||||
"{} {} 0 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 0 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current engaged priority of dispels on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Dispel)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Dispel
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] engaged cast priority is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Engaged)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] engaged cast priority was set to [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Engaged)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] engaged cast priority to [{}].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_holds(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_holds", sep->arg[0], "spellholds")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Toggles whether or not bots can cast or receive certain spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- All pet types are based off the pet's owner's setting",
|
||||
"- Any remaining types use the owner's setting when a pet is the target",
|
||||
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
|
||||
"- e.g., BotA is healing BotB using BotB's settings",
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to hold DoTs:",
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::DOT
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To check the current DoT settings on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::DOT
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three = { };
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] spell hold is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellHold(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellHold(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] spell hold was [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellHold(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots [{}] their [{}] spell hold.",
|
||||
success_count,
|
||||
typeValue ? "enabled" : "disabled",
|
||||
c->GetSpellTypeNameByID(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_idle_priority(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_idle_priority", sep->arg[0], "spellidlepriority")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Sets the order of spell casts when not in combat by spell type"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"-Setting a spell type to 0 will prevent that type from being cast.",
|
||||
"-If 2 or more are set to the same priority they will sort by spell type ID."
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all Clerics to cast fast heals third:",
|
||||
fmt::format(
|
||||
"{} {} 3 byclass 2",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 3 byclass 2",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set all bots to not cast cures:",
|
||||
fmt::format(
|
||||
"{} {} 0 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Cure)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 0 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Cure
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current idle priority of buffs on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Buff)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Buff
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] idle cast priority is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Idle)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] idle cast priority was set to [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Idle)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] idle cast priority to [{}].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_max_hp_pct", sep->arg[0], "spellmaxhppct")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what health percentage a bot will start casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to start snaring when their health is at or below 100% HP:",
|
||||
fmt::format(
|
||||
"{} {} 100 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set BotA to start casting fast heals at 30% HP:",
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Stun max HP percent on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Stun
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum HP is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeMaxHPLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeMaxHPLimit(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum HP was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeMaxHPLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] maximum HP to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_max_mana_pct", sep->arg[0], "spellmaxmanapct")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what mana percentage a bot will stop casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to start snaring when their mana is at or below 100% HP:",
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set BotA to start casting fast heals at 30% mana:",
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Stun max mana percent on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Stun
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum mana is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeMaxManaLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeMaxManaLimit(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum mana was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeMaxManaLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] maximum mana to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_max_thresholds(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_max_thresholds", sep->arg[0], "spellmaxthresholds")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what target HP % the bot will start casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- All pet types are based off the pet's owner's setting",
|
||||
"- Any remaining types use the owner's setting when a pet is the target",
|
||||
"- All Heals, Cures, Buffs (DS and resists included)",
|
||||
"are based off the target's setting, not the caster",
|
||||
"- e.g., BotA is healing BotB using BotB's settings",
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to start snaring at 99%:",
|
||||
fmt::format(
|
||||
"{} {} 99 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 99 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set bot Enchbot to start casting Debuffs at 99%:",
|
||||
fmt::format(
|
||||
"{} {} 99 byname Enchbot",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 99 byname Enchbot",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Debuff
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Nuke max threshold on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Nuke
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum threshold is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellMaxThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellMaxThreshold(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] maximum threshold was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellMaxThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] maximum threshold to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_min_hp_pct", sep->arg[0], "spellminhppct")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what health percentage a bot will stop casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to stop snaring when their health is below 10% HP:",
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set BotA to stop casting fast heals at 30% HP:",
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Stun min HP percent on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Stun
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum HP is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeMinHPLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeMinHPLimit(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum HP was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeMinHPLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] minimum HP to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_min_mana_pct", sep->arg[0], "spellminmanapct")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what mana percentage a bot will stop casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to stop snaring when their mana is below 10% HP:",
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Snare
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set BotA to stop casting fast heals at 30% mana:",
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 30 byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Stun min mana percent on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Stun
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum mana is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeMinManaLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeMinManaLimit(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum mana was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeMinManaLimit(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] minimum mana to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_min_thresholds(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_min_thresholds", sep->arg[0], "spellminthresholds")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Controls at what target HP % the bot will stop casting different spell types"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- All pet types are based off the pet's owner's setting",
|
||||
"- Any remaining types use the owner's setting when a pet is the target",
|
||||
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
|
||||
"- e.g., BotA is healing BotB using BotB's settings",
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to stop debuffing at 10%:",
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 10 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Debuff
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set all Druids to stop casting DoTs at 15%:",
|
||||
fmt::format(
|
||||
"{} {} 15 byclass 6",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 15 byclass 6",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::DOT
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current Fast Heal min threshold on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid",
|
||||
"targetgroup, namesgroup, healrotationtargets",
|
||||
"mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum threshold is currently [{}%%].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellMinThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellMinThreshold(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] minimum threshold was set to [{}%%].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellMinThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] minimum threshold to [{}%%].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_pursue_priority(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_pursue_priority", sep->arg[0], "spellpursuepriority")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Sets the order of spell casts when the mob is fleeing in combat by spell type"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- Setting a spell type to 0 will prevent that type from being cast.",
|
||||
"- If 2 or more are set to the same priority they will sort by spell type ID."
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to cast nukes first:",
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 1 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::FastHeals
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set all Shaman to not cast cures:",
|
||||
fmt::format(
|
||||
"{} {} 0 byclass 10",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Cure)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 0 byclass 10",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Cure
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current pursue priority of buffs on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Buff)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::Buff
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] pursue cast priority is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Pursue)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] pursue cast priority was set to [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Pursue)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] pursue cast priority to [{}].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_spell_target_count(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_spell_target_count", sep->arg[0], "spelltargetcount")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Decides how many eligible targets are required for an AE or group spell to cast by spell type"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes = { };
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [Type Shortname] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
),
|
||||
fmt::format(
|
||||
"{} [Type ID] [value] [actionable]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To set all bots to AEMez with 5 or more targets:",
|
||||
fmt::format(
|
||||
"{} {} 5 spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::AEMez)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 5 spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::AEMez
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To set Wizards to require 5 targets for AENukes:",
|
||||
fmt::format(
|
||||
"{} {} 3 byname BotA",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::AENukes)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} 3 byname BotA",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::AENukes
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To check the current AESlow count on all bots:",
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::AESlow)
|
||||
),
|
||||
fmt::format(
|
||||
"{} {} current spawned",
|
||||
sep->arg[0],
|
||||
BotSpellTypes::AESlow
|
||||
)
|
||||
};
|
||||
|
||||
std::vector<std::string> actionables =
|
||||
{
|
||||
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
|
||||
};
|
||||
|
||||
std::vector<std::string> options = { };
|
||||
std::vector<std::string> options_one = { };
|
||||
std::vector<std::string> options_two = { };
|
||||
std::vector<std::string> options_three = { };
|
||||
|
||||
std::string popup_text = c->SendCommandHelpWindow(
|
||||
c,
|
||||
description,
|
||||
notes,
|
||||
example_format,
|
||||
examples_one, examples_two, examples_three,
|
||||
actionables,
|
||||
options,
|
||||
options_one, options_two, options_three
|
||||
);
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
// String/Int type checks
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
|
||||
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 1 || typeValue > 100) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 1-100.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
Bot* first_found = nullptr;
|
||||
int success_count = 0;
|
||||
for (auto my_bot : sbl) {
|
||||
if (!first_found) {
|
||||
first_found = my_bot;
|
||||
}
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] target count is currently [{}].'",
|
||||
my_bot->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
my_bot->GetSpellTypeAEOrGroupTargetCount(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
my_bot->SetSpellTypeAEOrGroupTargetCount(spellType, typeValue);
|
||||
++success_count;
|
||||
}
|
||||
}
|
||||
if (!current_check) {
|
||||
if (success_count == 1 && first_found) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} says, 'My [{}] target count was set to [{}].'",
|
||||
first_found->GetCleanName(),
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
first_found->GetSpellTypeAEOrGroupTargetCount(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"{} of your bots set their [{}] target count to [{}].",
|
||||
success_count,
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
typeValue
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ void bot_command_suspend(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([actionable: <any>] ([actionable_name]))", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
const int ab_mask = ActionableBots::ABM_NoFilter;
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
|
||||
void bot_command_taunt(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt"))
|
||||
return;
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
const int ab_mask = ActionableBots::ABM_Type1;
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
@@ -15,26 +18,30 @@ void bot_command_taunt(Client *c, const Seperator *sep)
|
||||
bool taunt_state = false;
|
||||
bool toggle_taunt = true;
|
||||
int ab_arg = 1;
|
||||
|
||||
if (!arg1.compare("on")) {
|
||||
taunt_state = true;
|
||||
toggle_taunt = false;
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("off")) {
|
||||
toggle_taunt = false;
|
||||
ab_arg = 2;
|
||||
++ab_arg;
|
||||
}
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[(ab_arg + 1)] : nullptr, class_race_check ? atoi(sep->arg[(ab_arg + 1)]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
int taunting_count = 0;
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
void bot_command_timer(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer"))
|
||||
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] [actionable].", sep->arg[0]);
|
||||
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name])).", sep->arg[0]);
|
||||
c->Message(Chat::White, "When setting, you can leave the value blank to use the default for the item or specify a value in ms to set the timer to.");
|
||||
c->Message(Chat::White, "Returns or sets the provided timer(s) for the selected bot(s) or clears the selected timer(s) for the selected bot(s).");
|
||||
return;
|
||||
@@ -88,14 +90,17 @@ void bot_command_timer(Client* c, const Seperator* sep)
|
||||
|
||||
std::string class_race_arg = sep->arg[ab_arg];
|
||||
bool class_race_check = false;
|
||||
|
||||
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
|
||||
class_race_check = true;
|
||||
}
|
||||
|
||||
std::list<Bot*> sbl;
|
||||
|
||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
for (auto my_bot : sbl) {
|
||||
|
||||
+178
-165
@@ -35,6 +35,7 @@
|
||||
#include "../common/repositories/bot_pet_buffs_repository.h"
|
||||
#include "../common/repositories/bot_pet_inventories_repository.h"
|
||||
#include "../common/repositories/bot_spell_casting_chances_repository.h"
|
||||
#include "../common/repositories/bot_settings_repository.h"
|
||||
#include "../common/repositories/bot_stances_repository.h"
|
||||
#include "../common/repositories/bot_timers_repository.h"
|
||||
#include "../common/repositories/character_data_repository.h"
|
||||
@@ -400,28 +401,13 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
||||
e.spells_id,
|
||||
e.time_spawned,
|
||||
e.zone_id,
|
||||
t,
|
||||
e.expansion_bitmask
|
||||
t
|
||||
);
|
||||
|
||||
if (loaded_bot) {
|
||||
loaded_bot->SetSurname(e.last_name);
|
||||
loaded_bot->SetTitle(e.title);
|
||||
loaded_bot->SetSuffix(e.suffix);
|
||||
|
||||
loaded_bot->SetShowHelm(e.show_helm);
|
||||
|
||||
auto bfd = EQ::Clamp(e.follow_distance, static_cast<uint32>(1), BOT_FOLLOW_DISTANCE_DEFAULT_MAX);
|
||||
|
||||
loaded_bot->SetFollowDistance(bfd);
|
||||
|
||||
loaded_bot->SetStopMeleeLevel(e.stop_melee_level);
|
||||
|
||||
loaded_bot->SetBotEnforceSpellSetting(e.enforce_spell_settings);
|
||||
|
||||
loaded_bot->SetBotArcherySetting(e.archery_setting);
|
||||
|
||||
loaded_bot->SetBotCasterRange(e.caster_range);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -476,13 +462,6 @@ bool BotDatabase::SaveNewBot(Bot* b, uint32& bot_id)
|
||||
e.poison = b->GetBasePR();
|
||||
e.disease = b->GetBaseDR();
|
||||
e.corruption = b->GetBaseCorrup();
|
||||
e.show_helm = b->GetShowHelm() ? 1 : 0;
|
||||
e.follow_distance = b->GetFollowDistance();
|
||||
e.stop_melee_level = b->GetStopMeleeLevel();
|
||||
e.expansion_bitmask = b->GetExpansionBitmask();
|
||||
e.enforce_spell_settings = b->GetBotEnforceSpellSetting();
|
||||
e.archery_setting = b->IsBotArcher() ? 1 : 0;
|
||||
e.caster_range = b->GetBotCasterRange();
|
||||
|
||||
e = BotDataRepository::InsertOne(database, e);
|
||||
|
||||
@@ -547,12 +526,6 @@ bool BotDatabase::SaveBot(Bot* b)
|
||||
e.poison = b->GetBasePR();
|
||||
e.disease = b->GetBaseDR();
|
||||
e.corruption = b->GetBaseCorrup();
|
||||
e.show_helm = b->GetShowHelm() ? 1 : 0;
|
||||
e.follow_distance = b->GetFollowDistance();
|
||||
e.stop_melee_level = b->GetStopMeleeLevel();
|
||||
e.expansion_bitmask = b->GetExpansionBitmask();
|
||||
e.enforce_spell_settings = b->GetBotEnforceSpellSetting();
|
||||
e.archery_setting = b->IsBotArcher() ? 1 : 0;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
@@ -868,7 +841,7 @@ bool BotDatabase::SaveTimers(Bot* b)
|
||||
std::vector<BotTimersRepository::BotTimers> l;
|
||||
|
||||
if (!v.empty()) {
|
||||
for (auto & bot_timer : v) {
|
||||
for (auto& bot_timer : v) {
|
||||
if (bot_timer.timer_value <= Timer::GetCurrentTime()) {
|
||||
continue;
|
||||
}
|
||||
@@ -1670,59 +1643,6 @@ bool BotDatabase::SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_val
|
||||
return BotInventoriesRepository::SaveAllArmorColors(database, owner_id, rgb_value);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveHelmAppearance(const uint32 bot_id, const bool show_flag)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
e.show_helm = show_flag ? 1 : 0;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveAllHelmAppearances(const uint32 owner_id, const bool show_flag)
|
||||
{
|
||||
if (!owner_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BotDataRepository::SaveAllHelmAppearances(database, owner_id, show_flag);
|
||||
}
|
||||
|
||||
bool BotDatabase::ToggleAllHelmAppearances(const uint32 owner_id)
|
||||
{
|
||||
if (!owner_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BotDataRepository::ToggleAllHelmAppearances(database, owner_id);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveFollowDistance(const uint32 bot_id, const uint32 follow_distance)
|
||||
{
|
||||
if (!bot_id || !follow_distance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
e.follow_distance = follow_distance;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveAllFollowDistances(const uint32 owner_id, const uint32 follow_distance)
|
||||
{
|
||||
if (!owner_id || !follow_distance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BotDataRepository::SaveAllFollowDistances(database, owner_id, follow_distance);
|
||||
}
|
||||
|
||||
bool BotDatabase::CreateCloneBot(const uint32 bot_id, const std::string& clone_name, uint32& clone_id)
|
||||
{
|
||||
if (!bot_id || clone_name.empty()) {
|
||||
@@ -1771,19 +1691,6 @@ bool BotDatabase::CreateCloneBotInventory(const uint32 bot_id, const uint32 clon
|
||||
return BotInventoriesRepository::InsertMany(database, l);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveStopMeleeLevel(const uint32 bot_id, const uint8 sml_value)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
e.stop_melee_level = sml_value;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadOwnerOptions(Client* c)
|
||||
{
|
||||
if (!c || !c->CharacterID()) {
|
||||
@@ -2224,74 +2131,6 @@ uint32 BotDatabase::GetRaceClassBitmask(uint32 bot_race)
|
||||
return e.race ? e.classes : 0;
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveExpansionBitmask(const uint32 bot_id, const int expansion_bitmask)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
if (!e.bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.expansion_bitmask = expansion_bitmask;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveEnforceSpellSetting(const uint32 bot_id, const bool enforce_spell_setting)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
if (!e.bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.enforce_spell_settings = enforce_spell_setting ? 1 : 0;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
if (!e.bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.archery_setting = bot_archer_setting ? 1 : 0;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveBotCasterRange(const uint32 bot_id, const uint32 bot_caster_range_value)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto e = BotDataRepository::FindOne(database, bot_id);
|
||||
|
||||
if (!e.bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.caster_range = bot_caster_range_value;
|
||||
|
||||
return BotDataRepository::UpdateOne(database, e);
|
||||
}
|
||||
|
||||
const uint8 BotDatabase::GetBotClassByID(const uint32 bot_id)
|
||||
{
|
||||
const auto& e = BotDataRepository::FindOne(database, bot_id);
|
||||
@@ -2322,7 +2161,7 @@ std::vector<uint32> BotDatabase::GetBotIDsByCharacterID(const uint32 character_i
|
||||
class_id
|
||||
) :
|
||||
""
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -2360,3 +2199,177 @@ const int BotDatabase::GetBotExtraHasteByID(const uint32 bot_id)
|
||||
|
||||
return e.bot_id ? e.extra_haste : 0;
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadBotSettings(Mob* m)
|
||||
{
|
||||
if (!m) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m->IsOfClientBot()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 mobID = (m->IsClient() ? m->CastToClient()->CharacterID() : m->CastToBot()->GetBotID());
|
||||
|
||||
std::string query = "";
|
||||
|
||||
if (m->IsClient()) {
|
||||
query = fmt::format("`char_id` = {}", mobID);
|
||||
}
|
||||
else {
|
||||
query = fmt::format("`bot_id` = {}", mobID);
|
||||
}
|
||||
|
||||
const auto& l = BotSettingsRepository::GetWhere(database, query);
|
||||
|
||||
if (l.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
LogBotSettings("[{}] says, 'Loading {} [{}] - setting to [{}]."
|
||||
, m->GetCleanName()
|
||||
, (e.setting_type == BotSettingCategories::BaseSetting ? m->CastToBot()->GetBotSettingCategoryName(e.setting_id) : m->CastToBot()->GetBotSpellCategoryName(e.setting_id))
|
||||
, e.setting_id
|
||||
, e.value
|
||||
); //deleteme
|
||||
|
||||
m->SetBotSetting(e.setting_type, e.setting_id, e.value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveBotSettings(Mob* m)
|
||||
{
|
||||
if (!m) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m->IsOfClientBot()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 botID = (m->IsClient() ? 0 : m->CastToBot()->GetBotID());
|
||||
uint32 charID = (m->IsClient() ? m->CastToClient()->CharacterID() : 0);
|
||||
|
||||
std::string query = "";
|
||||
|
||||
if (m->IsClient()) {
|
||||
query = fmt::format("`char_id` = {}", charID);
|
||||
}
|
||||
else {
|
||||
query = fmt::format("`bot_id` = {}", botID);
|
||||
}
|
||||
|
||||
BotSettingsRepository::DeleteWhere(database, query);
|
||||
|
||||
std::vector<BotSettingsRepository::BotSettings> v;
|
||||
|
||||
if (m->IsBot()) {
|
||||
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
|
||||
if (m->CastToBot()->GetBotBaseSetting(i) != m->CastToBot()->GetDefaultBotBaseSetting(i)) {
|
||||
auto e = BotSettingsRepository::BotSettings{
|
||||
.char_id = charID,
|
||||
.bot_id = botID,
|
||||
.setting_id = static_cast<uint16_t>(i),
|
||||
.setting_type = static_cast<uint8_t>(BotSettingCategories::BaseSetting),
|
||||
.value = static_cast<int32_t>(m->CastToBot()->GetBotBaseSetting(i)),
|
||||
.category_name = m->CastToBot()->GetBotSpellCategoryName(BotSettingCategories::BaseSetting),
|
||||
.setting_name = m->CastToBot()->GetBotSettingCategoryName(i)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->CastToBot()->GetBotSettingCategoryName(i), i, e.value, m->CastToBot()->GetDefaultBotBaseSetting(i)); //deleteme
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16 i = BotSettingCategories::START_NO_BASE; i <= BotSettingCategories::END; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
if (m->CastToBot()->GetSetting(i, x) != m->CastToBot()->GetDefaultSetting(i, x)) {
|
||||
auto e = BotSettingsRepository::BotSettings{
|
||||
.char_id = charID,
|
||||
.bot_id = botID,
|
||||
.setting_id = static_cast<uint16_t>(x),
|
||||
.setting_type = static_cast<uint8_t>(i),
|
||||
.value = m->CastToBot()->GetSetting(i, x),
|
||||
.category_name = m->CastToBot()->GetBotSpellCategoryName(i),
|
||||
.setting_name = m->CastToBot()->GetSpellTypeNameByID(x)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->CastToBot()->GetBotSpellCategoryName(i), m->GetSpellTypeNameByID(x), x, e.value, m->CastToBot()->GetDefaultSetting(i, x)); //deleteme
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m->IsClient()) {
|
||||
if (m->CastToClient()->GetDefaultBotSettings(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock) != m->GetIllusionBlock()) { // Only illusion block supported
|
||||
auto e = BotSettingsRepository::BotSettings{
|
||||
.char_id = charID,
|
||||
.bot_id = botID,
|
||||
.setting_id = static_cast<uint16_t>(BotBaseSettings::IllusionBlock),
|
||||
.setting_type = static_cast<uint8_t>(BotSettingCategories::BaseSetting),
|
||||
.value = m->GetIllusionBlock(),
|
||||
.category_name = m->CastToBot()->GetBotSpellCategoryName(BotSettingCategories::BaseSetting),
|
||||
.setting_name = m->CastToBot()->GetBotSettingCategoryName(BotBaseSettings::IllusionBlock)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->CastToBot()->GetBotSettingCategoryName(BotBaseSettings::IllusionBlock), BotBaseSettings::IllusionBlock, e.value, m->GetIllusionBlock()); //deleteme
|
||||
}
|
||||
|
||||
for (uint16 i = BotSettingCategories::START_CLIENT; i <= BotSettingCategories::END_CLIENT; ++i) {
|
||||
for (uint16 x = BotSpellTypes::START; x <= BotSpellTypes::END; ++x) {
|
||||
LogBotSettings("{} says, 'Checking {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->CastToBot()->GetBotSpellCategoryName(i), m->CastToBot()->GetSpellTypeNameByID(x), x, m->CastToClient()->GetBotSetting(i, x), m->CastToClient()->GetDefaultBotSettings(i, x)); //deleteme
|
||||
if (IsClientBotSpellType(x) && m->CastToClient()->GetBotSetting(i, x) != m->CastToClient()->GetDefaultBotSettings(i, x)) {
|
||||
auto e = BotSettingsRepository::BotSettings{
|
||||
.char_id = charID,
|
||||
.bot_id = botID,
|
||||
.setting_id = static_cast<uint16_t>(x),
|
||||
.setting_type = static_cast<uint8_t>(i),
|
||||
.value = m->CastToClient()->GetBotSetting(i, x),
|
||||
.category_name = m->CastToBot()->GetBotSpellCategoryName(i),
|
||||
.setting_name = m->CastToBot()->GetSpellTypeNameByID(x)
|
||||
};
|
||||
|
||||
v.emplace_back(e);
|
||||
|
||||
LogBotSettings("{} says, 'Saving {} {} [{}] - set to [{}] default [{}].'", m->GetCleanName(), m->CastToBot()->GetBotSpellCategoryName(i), m->CastToBot()->GetSpellTypeNameByID(x), x, e.value, m->CastToClient()->GetDefaultBotSettings(i, x)); //deleteme
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!v.empty()) {
|
||||
const int inserted = BotSettingsRepository::ReplaceMany(database, v);
|
||||
|
||||
if (!inserted) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::DeleteBotSettings(const uint32 bot_id)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BotSettingsRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`bot_id` = {}",
|
||||
bot_id
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-23
@@ -88,10 +88,6 @@ public:
|
||||
|
||||
bool SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, const uint32 color);
|
||||
|
||||
bool SaveExpansionBitmask(const uint32 bot_id, const int expansion_bitmask);
|
||||
bool SaveEnforceSpellSetting(const uint32 bot_id, const bool enforce_spell_setting);
|
||||
|
||||
|
||||
/* Bot pet functions */
|
||||
bool LoadPetIndex(const uint32 bot_id, uint32& pet_index);
|
||||
bool LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id);
|
||||
@@ -120,26 +116,16 @@ public:
|
||||
bool SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slot_id, const uint32 rgb_value);
|
||||
bool SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_value);
|
||||
|
||||
bool SaveHelmAppearance(const uint32 bot_id, const bool show_flag = true);
|
||||
bool SaveAllHelmAppearances(const uint32 owner_id, const bool show_flag = true);
|
||||
|
||||
bool ToggleAllHelmAppearances(const uint32 owner_id);
|
||||
|
||||
bool SaveFollowDistance(const uint32 bot_id, const uint32 follow_distance);
|
||||
bool SaveAllFollowDistances(const uint32 owner_id, const uint32 follow_distance);
|
||||
|
||||
bool CreateCloneBot(const uint32 bot_id, const std::string& clone_name, uint32& clone_id);
|
||||
bool CreateCloneBotInventory(const uint32 bot_id, const uint32 clone_id);
|
||||
|
||||
bool SaveStopMeleeLevel(const uint32 bot_id, const uint8 sml_value);
|
||||
|
||||
bool SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting);
|
||||
|
||||
bool LoadOwnerOptions(Client *owner);
|
||||
bool SaveOwnerOption(const uint32 owner_id, size_t type, const bool flag);
|
||||
bool SaveOwnerOption(const uint32 owner_id, const std::pair<size_t, size_t> type, const std::pair<bool, bool> flag);
|
||||
|
||||
bool SaveBotCasterRange(const uint32 bot_id, const uint32 bot_caster_range_value);
|
||||
bool LoadBotSettings(Mob* m);
|
||||
bool SaveBotSettings(Mob* m);
|
||||
bool DeleteBotSettings(const uint32 bot_id);
|
||||
|
||||
/* Bot group functions */
|
||||
bool LoadGroupedBotsByGroupID(const uint32 owner_id, const uint32 group_id, std::list<uint32>& group_list);
|
||||
@@ -210,12 +196,6 @@ public:
|
||||
static const char* SaveAllInspectMessages();
|
||||
static const char* SaveAllArmorColorBySlot();
|
||||
static const char* SaveAllArmorColors();
|
||||
static const char* SaveAllHelmAppearances();
|
||||
static const char* ToggleAllHelmAppearances();
|
||||
static const char* SaveFollowDistance();
|
||||
static const char* SaveAllFollowDistances();
|
||||
static const char* SaveStopMeleeLevel();
|
||||
static const char* SaveBotCasterRange();
|
||||
|
||||
/* fail::Bot heal rotation functions */
|
||||
static const char* LoadHealRotation();
|
||||
|
||||
@@ -92,4 +92,9 @@ struct BotTimer_Struct {
|
||||
uint32 item_id;
|
||||
};
|
||||
|
||||
struct BotSpellTypeOrder {
|
||||
uint16 spellType;
|
||||
uint16 priority;
|
||||
};
|
||||
|
||||
#endif // BOT_STRUCTS
|
||||
|
||||
+1664
-2121
File diff suppressed because it is too large
Load Diff
+267
-8
@@ -51,6 +51,7 @@ extern volatile bool RunLoops;
|
||||
#include "water_map.h"
|
||||
#include "bot_command.h"
|
||||
#include "string_ids.h"
|
||||
#include "dialogue_window.h"
|
||||
|
||||
#include "guild_mgr.h"
|
||||
#include "quest_parser_collection.h"
|
||||
@@ -775,6 +776,8 @@ bool Client::Save(uint8 iCommitNow) {
|
||||
|
||||
database.SaveCharacterEXPModifier(this);
|
||||
|
||||
database.botdb.SaveBotSettings(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5871,7 +5874,7 @@ void Client::SuspendMinion(int value)
|
||||
{
|
||||
m_suspendedminion.SpellID = SpellID;
|
||||
|
||||
m_suspendedminion.HP = CurrentPet->GetHP();;
|
||||
m_suspendedminion.HP = CurrentPet->GetHP();
|
||||
|
||||
m_suspendedminion.Mana = CurrentPet->GetMana();
|
||||
m_suspendedminion.petpower = CurrentPet->GetPetPower();
|
||||
@@ -12896,11 +12899,11 @@ void Client::AddMoneyToPPWithOverflow(uint64 copper, bool update_client)
|
||||
SaveCurrency();
|
||||
|
||||
LogDebug("Client::AddMoneyToPPWithOverflow() [{}] should have: plat:[{}] gold:[{}] silver:[{}] copper:[{}]",
|
||||
GetName(),
|
||||
m_pp.platinum,
|
||||
m_pp.gold,
|
||||
m_pp.silver,
|
||||
m_pp.copper
|
||||
GetName(),
|
||||
m_pp.platinum,
|
||||
m_pp.gold,
|
||||
m_pp.silver,
|
||||
m_pp.copper
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13056,8 +13059,8 @@ void Client::ClientToNpcAggroProcess()
|
||||
{
|
||||
if (zone->CanDoCombat() && !GetFeigned() && m_client_npc_aggro_scan_timer.Check()) {
|
||||
int npc_scan_count = 0;
|
||||
for (auto &close_mob: GetCloseMobList()) {
|
||||
Mob *mob = close_mob.second;
|
||||
for (auto& close_mob : GetCloseMobList()) {
|
||||
Mob* mob = close_mob.second;
|
||||
if (!mob) {
|
||||
continue;
|
||||
}
|
||||
@@ -13075,3 +13078,259 @@ void Client::ClientToNpcAggroProcess()
|
||||
LogAggro("Checking Reverse Aggro (client->npc) scanned_npcs ([{}])", npc_scan_count);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::LoadDefaultBotSettings() {
|
||||
// Only illusion block supported currently
|
||||
SetBotSetting(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock, GetDefaultBotSettings(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock));
|
||||
LogBotSettingsDetail("{} says, 'Setting default {} [{}] to [{}]'", GetCleanName(), CastToBot()->GetBotSettingCategoryName(BotBaseSettings::IllusionBlock), BotBaseSettings::IllusionBlock, GetDefaultBotSettings(BotSettingCategories::BaseSetting, BotBaseSettings::IllusionBlock)); //deleteme
|
||||
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
BotSpellSettings_Struct t;
|
||||
|
||||
t.spellType = i;
|
||||
t.shortName = GetSpellTypeShortNameByID(i);
|
||||
t.name = GetSpellTypeNameByID(i);
|
||||
t.hold = GetDefaultSpellHold(i);
|
||||
t.delay = GetDefaultSpellDelay(i);
|
||||
t.minThreshold = GetDefaultSpellMinThreshold(i);
|
||||
t.maxThreshold = GetDefaultSpellMaxThreshold(i);
|
||||
|
||||
_spellSettings.push_back(t);
|
||||
|
||||
LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}]'", GetCleanName(), t.name, t.shortName, t.spellType); //deleteme
|
||||
LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), GetDefaultSpellHold(i), GetDefaultSpellDelay(i), GetDefaultSpellMinThreshold(i), GetDefaultSpellMaxThreshold(i)); //deleteme
|
||||
}
|
||||
}
|
||||
|
||||
int Client::GetDefaultBotSettings(uint8 settingType, uint16 botSetting) {
|
||||
switch (settingType) {
|
||||
case BotSettingCategories::BaseSetting:
|
||||
return false;
|
||||
case BotSettingCategories::SpellHold:
|
||||
return GetDefaultSpellHold(botSetting);
|
||||
case BotSettingCategories::SpellDelay:
|
||||
return GetDefaultSpellDelay(botSetting);
|
||||
case BotSettingCategories::SpellMinThreshold:
|
||||
return GetDefaultSpellMinThreshold(botSetting);
|
||||
case BotSettingCategories::SpellMaxThreshold:
|
||||
return GetDefaultSpellMaxThreshold(botSetting);
|
||||
}
|
||||
}
|
||||
|
||||
int Client::GetBotSetting(uint8 settingType, uint16 botSetting) {
|
||||
switch (settingType) {
|
||||
case BotSettingCategories::SpellHold:
|
||||
return GetSpellHold(botSetting);
|
||||
case BotSettingCategories::SpellDelay:
|
||||
return GetSpellDelay(botSetting);
|
||||
case BotSettingCategories::SpellMinThreshold:
|
||||
return GetSpellMinThreshold(botSetting);
|
||||
case BotSettingCategories::SpellMaxThreshold:
|
||||
return GetSpellMaxThreshold(botSetting);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetBotSetting(uint8 settingType, uint16 botSetting, uint32 settingValue) {
|
||||
switch (settingType) {
|
||||
case BotSettingCategories::BaseSetting:
|
||||
SetBaseSetting(botSetting, settingValue);
|
||||
break;
|
||||
case BotSettingCategories::SpellHold:
|
||||
SetSpellHold(botSetting, settingValue);
|
||||
break;
|
||||
case BotSettingCategories::SpellDelay:
|
||||
SetSpellDelay(botSetting, settingValue);
|
||||
break;
|
||||
case BotSettingCategories::SpellMinThreshold:
|
||||
SetSpellMinThreshold(botSetting, settingValue);
|
||||
break;
|
||||
case BotSettingCategories::SpellMaxThreshold:
|
||||
SetSpellMaxThreshold(botSetting, settingValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Client::SendCommandHelpWindow(
|
||||
Client* c,
|
||||
std::vector<std::string> description,
|
||||
std::vector<std::string> notes,
|
||||
std::vector<std::string> example_format,
|
||||
std::vector<std::string> examples_one, std::vector<std::string> examples_two, std::vector<std::string> examples_three,
|
||||
std::vector<std::string> actionables,
|
||||
std::vector<std::string> options,
|
||||
std::vector<std::string> options_one, std::vector<std::string> options_two, std::vector<std::string> options_three
|
||||
) {
|
||||
|
||||
unsigned stringLength = 0;
|
||||
unsigned currentPlace = 0;
|
||||
uint16 maxLength = RuleI(Command, MaxHelpLineLength); //character length of a line before splitting in to multiple lines
|
||||
const std::string& description_color = RuleS(Command, DescriptionColor);
|
||||
const std::string& description_header_color = RuleS(Command, DescriptionHeaderColor);
|
||||
const std::string& alt_description_color = RuleS(Command, AltDescriptionColor);
|
||||
const std::string& note_color = RuleS(Command, NoteColor);
|
||||
const std::string& note_header_color = RuleS(Command, NoteHeaderColor);
|
||||
const std::string& alt_note_color = RuleS(Command, AltNoteColor);
|
||||
const std::string& example_color = RuleS(Command, ExampleColor);
|
||||
const std::string& example_header_color = RuleS(Command, ExampleHeaderColor);
|
||||
const std::string& sub_example_color = RuleS(Command, SubExampleColor);
|
||||
const std::string& alt_example_color = RuleS(Command, AltExampleColor);
|
||||
const std::string& sub_alt_example_color = RuleS(Command, SubAltExampleColor);
|
||||
const std::string& option_color = RuleS(Command, OptionColor);
|
||||
const std::string& option_header_color = RuleS(Command, OptionHeaderColor);
|
||||
const std::string& sub_option_color = RuleS(Command, SubOptionColor);
|
||||
const std::string& alt_option_color = RuleS(Command, AltOptionColor);
|
||||
const std::string& sub_alt_option_color = RuleS(Command, SubAltOptionColor);
|
||||
const std::string& actionable_color = RuleS(Command, ActionableColor);
|
||||
const std::string& actionable_header_color = RuleS(Command, ActionableHeaderColor);
|
||||
const std::string& alt_actionable_color = RuleS(Command, AltActionableColor);
|
||||
const std::string& header_color = RuleS(Command, HeaderColor);
|
||||
const std::string& secondary_header_color = RuleS(Command, SecondaryHeaderColor);
|
||||
const std::string& alt_header_color = RuleS(Command, AltHeaderColor);
|
||||
const std::string& filler_line_color = RuleS(Command, FillerLineColor);
|
||||
|
||||
|
||||
|
||||
std::string fillerLine = "--------------------------------------------------------------------";
|
||||
std::string fillerDia = DialogueWindow::TableRow(DialogueWindow::TableCell(fmt::format("{}", DialogueWindow::ColorMessage(filler_line_color, fillerLine))));
|
||||
std::string breakLine = DialogueWindow::Break();
|
||||
std::string indent = " ";
|
||||
std::string bullet = "- ";
|
||||
std::string popup_text = "";
|
||||
|
||||
/*
|
||||
maxLength is how long you want lines to be before splitting them. This will look for the last space before the count and split there so words are not split mid sentence
|
||||
Any SplitCommandHelpText can be be have the first string from a vector differ in color from the next strings by setting secondColor to true and assigning a color.
|
||||
ex: SplitCommandHelpText(examples_one, example_color, maxLength, true, alt_example_color)
|
||||
- This will make the first string from examples_one vector be the color of example_color and all following strings the color of alt_example_color
|
||||
ex: SplitCommandHelpText(examples_one, example_color, maxLength)
|
||||
- This will apply the color example_color to everything in examples_one vector
|
||||
*/
|
||||
|
||||
if (!description.empty()) {
|
||||
popup_text += GetCommandHelpHeader(description_header_color, "[Description]");
|
||||
popup_text += SplitCommandHelpText(description, description_color, maxLength, true, alt_description_color);
|
||||
}
|
||||
|
||||
if (!notes.empty()) {
|
||||
popup_text += breakLine;
|
||||
popup_text += breakLine;
|
||||
popup_text += GetCommandHelpHeader(note_header_color, "[Notes]");
|
||||
popup_text += SplitCommandHelpText(notes, note_color, maxLength, true, alt_note_color);
|
||||
}
|
||||
|
||||
if (!example_format.empty()) {
|
||||
popup_text += fillerDia;
|
||||
popup_text += GetCommandHelpHeader(example_header_color, "[Examples]");
|
||||
popup_text += SplitCommandHelpText(example_format, example_color, maxLength, true, alt_example_color);
|
||||
}
|
||||
|
||||
if (!examples_one.empty()) {
|
||||
popup_text += breakLine;
|
||||
popup_text += breakLine;
|
||||
popup_text += SplitCommandHelpText(examples_one, sub_example_color, maxLength, true, sub_alt_example_color);
|
||||
}
|
||||
|
||||
if (!examples_two.empty()) {
|
||||
popup_text += SplitCommandHelpText(examples_two, sub_example_color, maxLength, true, sub_alt_example_color);
|
||||
}
|
||||
|
||||
if (!examples_three.empty()) {
|
||||
popup_text += SplitCommandHelpText(examples_three, sub_example_color, maxLength, true, sub_alt_example_color);
|
||||
}
|
||||
|
||||
if (!options.empty()) {
|
||||
popup_text += fillerDia;
|
||||
popup_text += GetCommandHelpHeader(option_header_color, "[Options]");
|
||||
popup_text += SplitCommandHelpText(options, option_color, maxLength, true, alt_option_color);
|
||||
}
|
||||
|
||||
if (!options_one.empty()) {
|
||||
popup_text += breakLine;
|
||||
popup_text += breakLine;
|
||||
popup_text += SplitCommandHelpText(options_one, sub_option_color, maxLength, true, sub_alt_option_color);
|
||||
}
|
||||
|
||||
if (!options_two.empty()) {
|
||||
popup_text += SplitCommandHelpText(options_two, sub_option_color, maxLength, true, sub_alt_option_color);
|
||||
}
|
||||
|
||||
if (!options_three.empty()) {
|
||||
popup_text += SplitCommandHelpText(options_three, secondary_header_color, maxLength, true, sub_alt_option_color);
|
||||
}
|
||||
|
||||
if (!actionables.empty()) {
|
||||
popup_text += fillerDia;
|
||||
popup_text += GetCommandHelpHeader(actionable_header_color, "[Actionables]");
|
||||
popup_text += SplitCommandHelpText(actionables, actionable_color, maxLength, true, alt_actionable_color);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
return popup_text;
|
||||
}
|
||||
|
||||
std::string Client::GetCommandHelpHeader(std::string color, std::string header) {
|
||||
std::string returnText = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(color, header)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return returnText;
|
||||
}
|
||||
|
||||
std::string Client::SplitCommandHelpText(std::vector<std::string> msg, std::string color, uint16 maxLength, bool secondColor, std::string secondaryColor) {
|
||||
std::string returnText;
|
||||
|
||||
for (int i = 0; i < msg.size(); i++) {
|
||||
std::vector<std::string> msg_split;
|
||||
int stringLength = msg[i].length() + 1;
|
||||
int endCount = 0;
|
||||
int newCount = 0;
|
||||
int splitCount = 0;
|
||||
|
||||
for (int x = 0; x < stringLength; x = endCount) {
|
||||
endCount = std::min(int(stringLength), (int(x) + std::min(int(stringLength), int(maxLength))));
|
||||
|
||||
if ((stringLength - (x + 1)) > maxLength) {
|
||||
for (int y = endCount; y >= x; --y) {
|
||||
if (msg[i][y] == ' ') {
|
||||
splitCount = y - x;
|
||||
msg_split.emplace_back(msg[i].substr(x, splitCount));
|
||||
endCount = y + 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (y == x) {
|
||||
msg_split.emplace_back(msg[i].substr(x, maxLength));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg_split.emplace_back(msg[i].substr(x, (stringLength - 1) - x));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& s : msg_split) {
|
||||
returnText += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(((secondColor && i == 0) ? color : secondaryColor), s)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return returnText;
|
||||
}
|
||||
|
||||
@@ -1250,6 +1250,20 @@ public:
|
||||
PendingTranslocate_Struct PendingTranslocateData;
|
||||
void SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID);
|
||||
|
||||
// Help Window
|
||||
std::string SendCommandHelpWindow(
|
||||
Client* c,
|
||||
std::vector<std::string> description,
|
||||
std::vector<std::string> notes,
|
||||
std::vector<std::string> example_format,
|
||||
std::vector<std::string> examples_one, std::vector<std::string> examples_two, std::vector<std::string> examples_three,
|
||||
std::vector<std::string> actionables,
|
||||
std::vector<std::string> options,
|
||||
std::vector<std::string> options_one, std::vector<std::string> options_two, std::vector<std::string> options_three
|
||||
);
|
||||
std::string GetCommandHelpHeader(std::string color, std::string header);
|
||||
std::string SplitCommandHelpText(std::vector<std::string> msg, std::string color, uint16 maxLength, bool secondColor = false, std::string secondaryColor = "");
|
||||
|
||||
// Task System Methods
|
||||
void LoadClientTaskState();
|
||||
void RemoveClientTaskState();
|
||||
@@ -2219,11 +2233,29 @@ public:
|
||||
void CampAllBots(uint8 class_id = Class::None);
|
||||
void SpawnRaidBotsOnConnect(Raid* raid);
|
||||
|
||||
void LoadDefaultBotSettings();
|
||||
int GetDefaultBotSettings(uint8 settingType, uint16 botSetting);
|
||||
int GetBotSetting(uint8 settingType, uint16 botSetting);
|
||||
void SetBotSetting(uint8 settingType, uint16 botSetting, uint32 settingValue);
|
||||
|
||||
private:
|
||||
bool bot_owner_options[_booCount];
|
||||
bool m_bot_pulling;
|
||||
bool m_bot_precombat;
|
||||
|
||||
uint8 fast_heal_threshold;
|
||||
uint8 heal_threshold;
|
||||
uint8 complete_heal_threshold;
|
||||
uint8 hot_heal_threshold;
|
||||
uint32 fast_heal_delay;
|
||||
uint32 heal_delay;
|
||||
uint32 complete_heal_delay;
|
||||
uint32 hot_heal_delay;
|
||||
uint32 cure_delay;
|
||||
uint8 cure_min_threshold;
|
||||
uint8 cure_threshold;
|
||||
bool illusion_block;
|
||||
|
||||
bool CanTradeFVNoDropItem();
|
||||
void SendMobPositions();
|
||||
void PlayerTradeEventLog(Trade *t, Trade *t2);
|
||||
|
||||
@@ -19,6 +19,10 @@ uint32 Client::GetBotCreationLimit(uint8 class_id)
|
||||
{
|
||||
uint32 bot_creation_limit = RuleI(Bots, CreationLimit);
|
||||
|
||||
if (Admin() >= RuleI(Bots, MinStatusToBypassCreateLimit)) {
|
||||
return RuleI(Bots, MinStatusToBypassCreateLimit);
|
||||
}
|
||||
|
||||
const auto bucket_name = fmt::format(
|
||||
"bot_creation_limit{}",
|
||||
(
|
||||
@@ -67,6 +71,10 @@ int Client::GetBotSpawnLimit(uint8 class_id)
|
||||
{
|
||||
int bot_spawn_limit = RuleI(Bots, SpawnLimit);
|
||||
|
||||
if (Admin() >= RuleI(Bots, MinStatusToBypassSpawnLimit)) {
|
||||
return RuleI(Bots, MinStatusToBypassSpawnLimit);
|
||||
}
|
||||
|
||||
const auto bucket_name = fmt::format(
|
||||
"bot_spawn_limit{}",
|
||||
(
|
||||
|
||||
@@ -812,7 +812,7 @@ int32 Client::CalcSTR()
|
||||
|
||||
int32 Client::CalcSTA()
|
||||
{
|
||||
int32 val = m_pp.STA + itembonuses.STA + spellbonuses.STA + CalcAlcoholPhysicalEffect();;
|
||||
int32 val = m_pp.STA + itembonuses.STA + spellbonuses.STA + CalcAlcoholPhysicalEffect();
|
||||
int32 mod = aabonuses.STA;
|
||||
STA = val + mod;
|
||||
if (STA < 1) {
|
||||
@@ -827,7 +827,7 @@ int32 Client::CalcSTA()
|
||||
|
||||
int32 Client::CalcAGI()
|
||||
{
|
||||
int32 val = m_pp.AGI + itembonuses.AGI + spellbonuses.AGI - CalcAlcoholPhysicalEffect();;
|
||||
int32 val = m_pp.AGI + itembonuses.AGI + spellbonuses.AGI - CalcAlcoholPhysicalEffect();
|
||||
int32 mod = aabonuses.AGI;
|
||||
int32 str = GetSTR();
|
||||
//Encumbered penalty
|
||||
@@ -852,7 +852,7 @@ int32 Client::CalcAGI()
|
||||
|
||||
int32 Client::CalcDEX()
|
||||
{
|
||||
int32 val = m_pp.DEX + itembonuses.DEX + spellbonuses.DEX - CalcAlcoholPhysicalEffect();;
|
||||
int32 val = m_pp.DEX + itembonuses.DEX + spellbonuses.DEX - CalcAlcoholPhysicalEffect();
|
||||
int32 mod = aabonuses.DEX;
|
||||
DEX = val + mod;
|
||||
if (DEX < 1) {
|
||||
|
||||
+11
-2
@@ -412,7 +412,7 @@ void MapOpcodes()
|
||||
ConnectedOpcodes[OP_TributeUpdate] = &Client::Handle_OP_TributeUpdate;
|
||||
ConnectedOpcodes[OP_VetClaimRequest] = &Client::Handle_OP_VetClaimRequest;
|
||||
ConnectedOpcodes[OP_VoiceMacroIn] = &Client::Handle_OP_VoiceMacroIn;
|
||||
ConnectedOpcodes[OP_UpdateAura] = &Client::Handle_OP_UpdateAura;;
|
||||
ConnectedOpcodes[OP_UpdateAura] = &Client::Handle_OP_UpdateAura;
|
||||
ConnectedOpcodes[OP_WearChange] = &Client::Handle_OP_WearChange;
|
||||
ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest;
|
||||
ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore;
|
||||
@@ -666,6 +666,10 @@ void Client::CompleteConnect()
|
||||
for (int x1 = 0; x1 < EFFECT_COUNT; x1++) {
|
||||
switch (spell.effect_id[x1]) {
|
||||
case SE_Illusion: {
|
||||
if (GetIllusionBlock()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (buffs[j1].persistant_buff) {
|
||||
Mob *caster = entity_list.GetMobID(buffs[j1].casterid);
|
||||
ApplySpellEffectIllusion(spell.id, caster, j1, spell.base_value[x1], spell.limit_value[x1], spell.max_value[x1]);
|
||||
@@ -1483,6 +1487,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
LogError("Error loading AA points for [{}]", GetName());
|
||||
}
|
||||
|
||||
/* Load Bots */
|
||||
|
||||
LoadDefaultBotSettings();
|
||||
|
||||
database.botdb.LoadBotSettings(this);
|
||||
|
||||
if (SPDAT_RECORDS > 0) {
|
||||
for (uint32 z = 0; z < EQ::spells::SPELL_GEM_COUNT; z++) {
|
||||
if (m_pp.mem_spells[z] >= (uint32)SPDAT_RECORDS)
|
||||
@@ -1579,7 +1589,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
LFG = false;
|
||||
}
|
||||
|
||||
/* Load Bots */
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
database.botdb.LoadOwnerOptions(this);
|
||||
// TODO: mod below function for loading spawned botgroups
|
||||
|
||||
@@ -147,6 +147,7 @@ int command_init(void)
|
||||
command_add("help", "[Search Criteria] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) ||
|
||||
command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", AccountStatus::GMImpossible, command_hotfix) ||
|
||||
command_add("hp", "Refresh your HP bar from the server.", AccountStatus::Player, command_hp) ||
|
||||
command_add("illusionblock", "Controls whether or not illusion effects will land on you when cast by other players or bots", AccountStatus::Player, command_illusion_block) ||
|
||||
command_add("instance", "Modify Instances", AccountStatus::GMMgmt, command_instance) ||
|
||||
command_add("interrogateinv", "use [help] argument for available options", AccountStatus::Player, command_interrogateinv) ||
|
||||
command_add("interrupt", "[Message ID] [Color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) ||
|
||||
@@ -217,6 +218,10 @@ int command_init(void)
|
||||
command_add("spawn", "[name] [race] [level] [material] [hp] [gender] [class] [priweapon] [secweapon] [merchantid] - Spawn an NPC", AccountStatus::Steward, command_spawn) ||
|
||||
command_add("spawneditmass", "[Search Criteria] [Edit Option] [Edit Value] [Apply] Mass editing spawn command (Apply is optional, 0 = False, 1 = True, default is False)", AccountStatus::GMLeadAdmin, command_spawneditmass) ||
|
||||
command_add("spawnfix", "Find targeted NPC in database based on its X/Y/heading and update the database to make it spawn at your current location/heading.", AccountStatus::GMAreas, command_spawnfix) ||
|
||||
command_add("spelldelays", "Controls the delay between casts for a specific spell type", AccountStatus::Player, command_spell_delays) ||
|
||||
command_add("spellholds", "Controls whether a bot holds the specified spell type or not", AccountStatus::Player, command_spell_holds) ||
|
||||
command_add("spellmaxthresholds", "Controls the minimum target HP threshold for a spell to be cast for a specific type", AccountStatus::Player, command_spell_max_thresholds) ||
|
||||
command_add("spellminthresholds", "Controls the maximum target HP threshold for a spell to be cast for a specific type", AccountStatus::Player, command_spell_min_thresholds) ||
|
||||
command_add("stun", "[duration] - Stuns you or your target for duration", AccountStatus::GMAdmin, command_stun) ||
|
||||
command_add("summon", "[Character Name] - Summons your corpse, NPC, or player target, or by character name if specified", AccountStatus::QuestTroupe, command_summon) ||
|
||||
command_add("summonburiedplayercorpse", "Summons the target's oldest buried corpse, if any exist.", AccountStatus::GMAdmin, command_summonburiedplayercorpse) ||
|
||||
@@ -841,6 +846,7 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/grid.cpp"
|
||||
#include "gm_commands/guild.cpp"
|
||||
#include "gm_commands/hp.cpp"
|
||||
#include "gm_commands/illusion_block.cpp"
|
||||
#include "gm_commands/instance.cpp"
|
||||
#include "gm_commands/interrogateinv.cpp"
|
||||
#include "gm_commands/interrupt.cpp"
|
||||
@@ -909,6 +915,10 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/spawn.cpp"
|
||||
#include "gm_commands/spawneditmass.cpp"
|
||||
#include "gm_commands/spawnfix.cpp"
|
||||
#include "gm_commands/spell_delays.cpp"
|
||||
#include "gm_commands/spell_holds.cpp"
|
||||
#include "gm_commands/spell_max_thresholds.cpp"
|
||||
#include "gm_commands/spell_min_thresholds.cpp"
|
||||
#include "gm_commands/faction_association.cpp"
|
||||
#include "gm_commands/stun.cpp"
|
||||
#include "gm_commands/summon.cpp"
|
||||
|
||||
@@ -100,6 +100,7 @@ void command_guild(Client *c, const Seperator *sep);
|
||||
void command_help(Client *c, const Seperator *sep);
|
||||
void command_hotfix(Client *c, const Seperator *sep);
|
||||
void command_hp(Client *c, const Seperator *sep);
|
||||
void command_illusion_block(Client* c, const Seperator* sep);
|
||||
void command_instance(Client *c, const Seperator *sep);
|
||||
void command_interrogateinv(Client *c, const Seperator *sep);
|
||||
void command_interrupt(Client *c, const Seperator *sep);
|
||||
@@ -170,6 +171,10 @@ void command_shutdown(Client *c, const Seperator *sep);
|
||||
void command_spawn(Client *c, const Seperator *sep);
|
||||
void command_spawneditmass(Client *c, const Seperator *sep);
|
||||
void command_spawnfix(Client *c, const Seperator *sep);
|
||||
void command_spell_delays(Client* c, const Seperator* sep);
|
||||
void command_spell_holds(Client* c, const Seperator* sep);
|
||||
void command_spell_max_thresholds(Client* c, const Seperator* sep);
|
||||
void command_spell_min_thresholds(Client* c, const Seperator* sep);
|
||||
void command_stun(Client *c, const Seperator *sep);
|
||||
void command_summon(Client *c, const Seperator *sep);
|
||||
void command_summonburiedplayercorpse(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -2953,6 +2953,7 @@ void EntityList::ScanCloseMobs(Mob *scanning_mob)
|
||||
|
||||
for (auto &e : mob_list) {
|
||||
auto mob = e.second;
|
||||
|
||||
if (mob->GetID() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+1
-1
@@ -628,7 +628,7 @@ private:
|
||||
Client* GetBotOwnerByBotID(const uint32 bot_id);
|
||||
std::list<Bot*> GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID);
|
||||
|
||||
bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate
|
||||
bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 spellType); // TODO: Evaluate this closesly in hopes to eliminate
|
||||
void ShowSpawnWindow(Client* client, int Distance, bool NamedOnly); // TODO: Implement ShowSpawnWindow in the bot class but it needs entity list stuff
|
||||
|
||||
void ScanCloseClientMobs(std::unordered_map<uint16, Mob*>& close_mobs, Mob* scanning_mob);
|
||||
|
||||
@@ -1004,6 +1004,7 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
}
|
||||
} else {
|
||||
SetHP(CalcMaxHP()); // Why not, lets give them a free heal
|
||||
SetMana(CalcMaxMana());
|
||||
}
|
||||
|
||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "../client.h"
|
||||
|
||||
void command_illusion_block(Client* c, const Seperator* sep)
|
||||
{
|
||||
int arguments = sep->argnum;
|
||||
if (!arguments || !strcasecmp(sep->arg[1], "help")) {
|
||||
c->Message(Chat::White, "usage: #illusionblock [help | current | value].");
|
||||
c->Message(Chat::White, "note: Used to control whether or not illusion effects will land on you.");
|
||||
c->Message(Chat::White, "note: A value of 0 is disabled (Allow Illusions), 1 is enabled (Block Illusions).");
|
||||
c->Message(Chat::White, "note: Use [current] to check the current setting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
int setStatus = atoi(sep->arg[1]);
|
||||
if (setStatus == 0 || setStatus == 1) {
|
||||
c->SetIllusionBlock(setStatus);
|
||||
c->Message(Chat::White, "Your Illusion Block has been %s.", (setStatus ? "enabled" : "disabled"));
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "You must enter 0 for disabled or 1 for enabled.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(sep->arg[1], "current")) {
|
||||
c->Message(Chat::White, "You're currently %s illusions.", (c->GetIllusionBlock() ? "blocking" : "allowing"));
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
#include "../command.h"
|
||||
|
||||
void command_spell_delays(Client* c, const Seperator* sep)
|
||||
{
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments) {
|
||||
const bool is_help = !strcasecmp(sep->arg[1], "help");
|
||||
|
||||
if (is_help) {
|
||||
c->Message(Chat::White, "usage: %s [spelltype ID | spelltype Shortname] [current | value: 0-1].", sep->arg[0]);
|
||||
c->Message(Chat::White, "example: [%s 15 4000] or [%s cures 4000] would allow bots to cast cures on you every 4 seconds.", sep->arg[0], sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Use [current] to check your current setting.");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"note: Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
const std::string& color_red = "red_1";
|
||||
const std::string& color_blue = "royal_blue";
|
||||
const std::string& color_green = "forest_green";
|
||||
const std::string& bright_green = "green";
|
||||
const std::string& bright_red = "red";
|
||||
const std::string& heroic_color = "gold";
|
||||
|
||||
std::string fillerLine = "-----------";
|
||||
std::string spellTypeField = "Spell Type";
|
||||
std::string pluralS = "s";
|
||||
std::string idField = "ID";
|
||||
std::string shortnameField = "Short Name";
|
||||
|
||||
std::string popup_text = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(bright_green, spellTypeField)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(bright_green, idField) : DialogueWindow::ColorMessage(bright_green, shortnameField))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
if (!IsClientBotSpellType(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
DialogueWindow::ColorMessage(color_green, c->GetSpellTypeNameByID(i)),
|
||||
DialogueWindow::ColorMessage(color_green, pluralS)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(color_blue, std::to_string(i)) : DialogueWindow::ColorMessage(color_blue, c->GetSpellTypeShortNameByID(i)))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient("Spell Types", popup_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 1 || typeValue > 60000) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 1-60000 (1ms to 60s).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your current {} delay is {} seconds.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellDelay(spellType) / 1000.00
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->SetSpellDelay(spellType, typeValue);
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your {} delay was set to {} seconds.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellDelay(spellType) / 1000.00
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
#include "../command.h"
|
||||
|
||||
void command_spell_holds(Client *c, const Seperator *sep)
|
||||
{
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments) {
|
||||
const bool is_help = !strcasecmp(sep->arg[1], "help");
|
||||
|
||||
if (is_help) {
|
||||
c->Message(Chat::White, "usage: %s [spelltype ID | spelltype Shortname] [current | value: 0-1].", sep->arg[0]);
|
||||
c->Message(Chat::White, "example: [%s 15 1] or [%s cures 1] would prevent bots from casting cures on you.", sep->arg[0], sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Use [current] to check your current setting.");
|
||||
c->Message(Chat::White, "note: Set to 0 to unhold the given spell type.");
|
||||
c->Message(Chat::White, "note: Set to 1 to hold the given spell type.");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"note: Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
const std::string& color_red = "red_1";
|
||||
const std::string& color_blue = "royal_blue";
|
||||
const std::string& color_green = "forest_green";
|
||||
const std::string& bright_green = "green";
|
||||
const std::string& bright_red = "red";
|
||||
const std::string& heroic_color = "gold";
|
||||
|
||||
std::string fillerLine = "-----------";
|
||||
std::string spellTypeField = "Spell Type";
|
||||
std::string pluralS = "s";
|
||||
std::string idField = "ID";
|
||||
std::string shortnameField = "Short Name";
|
||||
|
||||
std::string popup_text = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(bright_green, spellTypeField)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(bright_green, idField) : DialogueWindow::ColorMessage(bright_green, shortnameField))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
if (!IsClientBotSpellType(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
DialogueWindow::ColorMessage(color_green, c->GetSpellTypeNameByID(i)),
|
||||
DialogueWindow::ColorMessage(color_green, pluralS)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(color_blue, std::to_string(i)) : DialogueWindow::ColorMessage(color_blue, c->GetSpellTypeShortNameByID(i)))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient("Spell Types", popup_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/Disable/Current checks
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 1) {
|
||||
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your current Hold {}s status is {}.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellHold(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->SetSpellHold(spellType, typeValue);
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your Hold {}s status was {}.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellHold(spellType) ? "enabled" : "disabled"
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "../command.h"
|
||||
|
||||
void command_spell_max_thresholds(Client* c, const Seperator* sep)
|
||||
{
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments) {
|
||||
const bool is_help = !strcasecmp(sep->arg[1], "help");
|
||||
|
||||
if (is_help) {
|
||||
c->Message(Chat::White, "usage: %s [spelltype ID | spelltype Shortname] [current | value: 0-1].", sep->arg[0]);
|
||||
c->Message(Chat::White, "example: [%s 15 95] or [%s cures 95] would allow bots to cast cures on you when you are under 95%% health.", sep->arg[0], sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Use [current] to check your current setting.");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"note: Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
const std::string& color_red = "red_1";
|
||||
const std::string& color_blue = "royal_blue";
|
||||
const std::string& color_green = "forest_green";
|
||||
const std::string& bright_green = "green";
|
||||
const std::string& bright_red = "red";
|
||||
const std::string& heroic_color = "gold";
|
||||
|
||||
std::string fillerLine = "-----------";
|
||||
std::string spellTypeField = "Spell Type";
|
||||
std::string pluralS = "s";
|
||||
std::string idField = "ID";
|
||||
std::string shortnameField = "Short Name";
|
||||
|
||||
std::string popup_text = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(bright_green, spellTypeField)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(bright_green, idField) : DialogueWindow::ColorMessage(bright_green, shortnameField))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
if (!IsClientBotSpellType(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
DialogueWindow::ColorMessage(color_green, c->GetSpellTypeNameByID(i)),
|
||||
DialogueWindow::ColorMessage(color_green, pluralS)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(color_blue, std::to_string(i)) : DialogueWindow::ColorMessage(color_blue, c->GetSpellTypeShortNameByID(i)))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient("Spell Types", popup_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/Disable/Current checks
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 150) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-150 (0%% to 150%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your current max threshold for {}s is {}%%.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellMaxThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->SetSpellMaxThreshold(spellType, typeValue);
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your max threshold for {}s was set to {}%%.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellMaxThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "../command.h"
|
||||
|
||||
void command_spell_min_thresholds(Client* c, const Seperator* sep)
|
||||
{
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments) {
|
||||
const bool is_help = !strcasecmp(sep->arg[1], "help");
|
||||
|
||||
if (is_help) {
|
||||
c->Message(Chat::White, "usage: %s [spelltype ID | spelltype Shortname] [current | value: 0-1].", sep->arg[0]);
|
||||
c->Message(Chat::White, "example: [%s 15 15] or [%s cures 15] would prevent bots from casting cures on you when you are under 15%% health.", sep->arg[0], sep->arg[0]);
|
||||
c->Message(Chat::White, "note: Use [current] to check your current setting.");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"note: Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
|
||||
if (!arg1.compare("listid") || !arg1.compare("listname")) {
|
||||
const std::string& color_red = "red_1";
|
||||
const std::string& color_blue = "royal_blue";
|
||||
const std::string& color_green = "forest_green";
|
||||
const std::string& bright_green = "green";
|
||||
const std::string& bright_red = "red";
|
||||
const std::string& heroic_color = "gold";
|
||||
|
||||
std::string fillerLine = "-----------";
|
||||
std::string spellTypeField = "Spell Type";
|
||||
std::string pluralS = "s";
|
||||
std::string idField = "ID";
|
||||
std::string shortnameField = "Short Name";
|
||||
|
||||
std::string popup_text = DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(bright_green, spellTypeField)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(bright_green, idField) : DialogueWindow::ColorMessage(bright_green, shortnameField))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
DialogueWindow::ColorMessage(heroic_color, fillerLine)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
if (!IsClientBotSpellType(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
popup_text += DialogueWindow::TableRow(
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}{}",
|
||||
DialogueWindow::ColorMessage(color_green, c->GetSpellTypeNameByID(i)),
|
||||
DialogueWindow::ColorMessage(color_green, pluralS)
|
||||
)
|
||||
) +
|
||||
DialogueWindow::TableCell(
|
||||
fmt::format(
|
||||
"{}",
|
||||
(!arg1.compare("listid") ? DialogueWindow::ColorMessage(color_blue, std::to_string(i)) : DialogueWindow::ColorMessage(color_blue, c->GetSpellTypeShortNameByID(i)))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
popup_text = DialogueWindow::Table(popup_text);
|
||||
|
||||
c->SendPopupToClient("Spell Types", popup_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool current_check = false;
|
||||
uint16 spellType = 0;
|
||||
uint32 typeValue = 0;
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
spellType = atoi(sep->arg[1]);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
|
||||
spellType = c->GetSpellTypeIDByShortName(arg1);
|
||||
|
||||
if (!IsClientBotSpellType(spellType)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You must choose a valid spell type. Use {} for a list of spell types by ID or {} for a list of spell types by short name.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listid", sep->arg[0])
|
||||
),
|
||||
Saylink::Silent(
|
||||
fmt::format("{} listname", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/Disable/Current checks
|
||||
if (sep->IsNumber(2)) {
|
||||
typeValue = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
if (typeValue < 0 || typeValue > 150) {
|
||||
c->Message(Chat::Yellow, "You must enter a value between 0-150 (0%% to 150%% of health).");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!arg2.compare("current")) {
|
||||
++ab_arg;
|
||||
current_check = true;
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Incorrect argument, use {} for information regarding this command.",
|
||||
Saylink::Silent(
|
||||
fmt::format("{} help", sep->arg[0])
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_check) {
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your current min threshold for {}s is {}%%.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellMinThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->SetSpellMinThreshold(spellType, typeValue);
|
||||
c->Message(
|
||||
Chat::Green,
|
||||
fmt::format(
|
||||
"Your min threshold for {}s was set to {}%%.",
|
||||
c->GetSpellTypeNameByID(spellType),
|
||||
c->GetSpellMinThreshold(spellType)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -105,11 +105,6 @@ void Lua_Bot::SetExpansionBitmask(int expansion_bitmask) {
|
||||
self->SetExpansionBitmask(expansion_bitmask);
|
||||
}
|
||||
|
||||
void Lua_Bot::SetExpansionBitmask(int expansion_bitmask, bool save) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetExpansionBitmask(expansion_bitmask, save);
|
||||
}
|
||||
|
||||
bool Lua_Bot::ReloadBotDataBuckets() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return DataBucket::GetDataBuckets(self);
|
||||
@@ -762,7 +757,6 @@ luabind::scope lua_register_bot() {
|
||||
.def("SetBucket", (void(Lua_Bot::*)(std::string,std::string))&Lua_Bot::SetBucket)
|
||||
.def("SetBucket", (void(Lua_Bot::*)(std::string,std::string,std::string))&Lua_Bot::SetBucket)
|
||||
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask)
|
||||
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask)
|
||||
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetDisciplineReuseTimer)
|
||||
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetDisciplineReuseTimer)
|
||||
.def("SetItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::SetItemReuseTimer)
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
void ReloadBotSpellSettings();
|
||||
void RemoveBotItem(uint32 item_id);
|
||||
void SetExpansionBitmask(int expansion_bitmask);
|
||||
void SetExpansionBitmask(int expansion_bitmask, bool save);
|
||||
void Signal(int signal_id);
|
||||
bool HasBotSpellEntry(uint16 spellid);
|
||||
void SendPayload(int payload_id);
|
||||
|
||||
+2
-2
@@ -1500,7 +1500,7 @@ bool Merc::AI_IdleCastCheck() {
|
||||
|
||||
bool EntityList::Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint32 iSpellTypes) {
|
||||
|
||||
if((iSpellTypes & SPELL_TYPES_DETRIMENTAL) != 0) {
|
||||
if (BOT_SPELL_TYPES_DETRIMENTAL(iSpellTypes)) {
|
||||
//according to live, you can buff and heal through walls...
|
||||
//now with PCs, this only applies if you can TARGET the target, but
|
||||
// according to Rogean, Live NPCs will just cast through walls/floors, no problem..
|
||||
@@ -1569,7 +1569,7 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon
|
||||
|
||||
float dist2 = 0;
|
||||
|
||||
if (mercSpell.type & SpellType_Escape) {
|
||||
if (mercSpell.type == SpellType_Escape) {
|
||||
dist2 = 0;
|
||||
} else
|
||||
dist2 = DistanceSquared(m_Position, tar->GetPosition());
|
||||
|
||||
+822
-3
@@ -1692,6 +1692,11 @@ void Mob::StopMoving()
|
||||
|
||||
void Mob::StopMoving(float new_heading)
|
||||
{
|
||||
if (IsBot()) {
|
||||
CastToBot()->SetCombatJitterFlag(false);
|
||||
CastToBot()->SetCombatOutOfRangeJitterFlag(false);
|
||||
}
|
||||
|
||||
StopNavigation();
|
||||
RotateTo(new_heading);
|
||||
|
||||
@@ -4664,7 +4669,7 @@ bool Mob::CanThisClassDoubleAttack(void) const
|
||||
|
||||
bool Mob::CanThisClassTripleAttack() const
|
||||
{
|
||||
if (!IsClient()) {
|
||||
if (!IsOfClientBot()) {
|
||||
return false; // When they added the real triple attack skill, mobs lost the ability to triple
|
||||
} else {
|
||||
if (RuleB(Combat, ClassicTripleAttack)) {
|
||||
@@ -4678,7 +4683,12 @@ bool Mob::CanThisClassTripleAttack() const
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return CastToClient()->HasSkill(EQ::skills::SkillTripleAttack);
|
||||
if (IsClient()) {
|
||||
return CastToClient()->HasSkill(EQ::skills::SkillTripleAttack);
|
||||
}
|
||||
else {
|
||||
return GetSkill(EQ::skills::SkillTripleAttack) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4812,6 +4822,88 @@ bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, fl
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Mob::PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behindOnly, bool frontOnly, bool bypassLoS) {
|
||||
bool Result = false;
|
||||
|
||||
if (target) {
|
||||
float look_heading = 0;
|
||||
|
||||
min_distance = min_distance;
|
||||
max_distance = max_distance;
|
||||
float tempX = 0;
|
||||
float tempY = 0;
|
||||
float tempZ = target->GetZ();
|
||||
float bestZ = 0;
|
||||
auto offset = GetZOffset();
|
||||
const float tarX = target->GetX();
|
||||
const float tarY = target->GetY();
|
||||
float tar_distance = 0;
|
||||
|
||||
glm::vec3 temp_z_Position;
|
||||
glm::vec4 temp_m_Position;
|
||||
|
||||
const uint16 maxIterationsAllowed = 50;
|
||||
uint16 counter = 0;
|
||||
//LogTestDebug("Plotting for {} - Min: [{}] - Max: [{}] - BehindMob: [{}] - Taunt [{}] -- LosReq [{}]", GetCleanName(), min_distance, max_distance, behindOnly, frontOnly, bypassLoS ? "bypassed" : CastToBot()->RequiresLoSForPositioning() ? "true" : "false"); //deleteme
|
||||
while (counter < maxIterationsAllowed) {
|
||||
tempX = tarX + zone->random.Real(-max_distance, max_distance);
|
||||
tempY = tarY + zone->random.Real(-max_distance, max_distance);
|
||||
|
||||
temp_z_Position.x = tempX;
|
||||
temp_z_Position.y = tempY;
|
||||
temp_z_Position.z = tempZ;
|
||||
bestZ = GetFixedZ(temp_z_Position);
|
||||
|
||||
if (bestZ != BEST_Z_INVALID) {
|
||||
tempZ = bestZ;
|
||||
}
|
||||
else {
|
||||
//LogTestDebug("{} - Plot Failed GetFixedZ - Try #[{}].", GetCleanName(), (counter + 1)); //deleteme
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
|
||||
temp_m_Position.x = tempX;
|
||||
temp_m_Position.y = tempY;
|
||||
temp_m_Position.z = tempZ;
|
||||
//tar_distance = DistanceNoZ(target->GetPosition(), temp_m_Position);
|
||||
tar_distance = Distance(target->GetPosition(), temp_m_Position);
|
||||
|
||||
if (tar_distance > max_distance || tar_distance < min_distance) {
|
||||
//LogTestDebug("{} - Plot Failed Distance - Try #[{}]. Target LOCs XYZ - [{}], [{}], [{}] - Temp LOCs [{}], [{}], [{}] - Distance between = [{}] - Melee Distance = [{}] - Difference = [{}]", GetCleanName(), (counter + 1), target->GetX(), target->GetY(), target->GetZ(), tempX, tempY, tempZ, tar_distance, max_distance, (tar_distance / max_distance));
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
if (frontOnly && !InFrontMob(target, tempX, tempY)) {
|
||||
//LogTestDebug("{} - Plot Failed frontOnly - Try #[{}]. Target LOCs XYZ - [{}], [{}], [{}] - Temp LOCs [{}], [{}], [{}] - Distance between = [{}] - Melee Distance = [{}] - Difference = [{}]", GetCleanName(), (counter + 1), target->GetX(), target->GetY(), target->GetZ(), tempX, tempY, tempZ, tar_distance, max_distance, (tar_distance / max_distance));
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
else if (behindOnly && !BehindMob(target, tempX, tempY)) {
|
||||
//LogTestDebug("{} - Plot Failed BehindMob - Try #[{}]. Target LOCs XYZ - [{}], [{}], [{}] - Temp LOCs [{}], [{}], [{}] - Distance between = [{}] - Melee Distance = [{}] - Difference = [{}]", GetCleanName(), (counter + 1), target->GetX(), target->GetY(), target->GetZ(), tempX, tempY, tempZ, tar_distance, max_distance, (tar_distance / max_distance));
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
if (!bypassLoS && CastToBot()->RequiresLoSForPositioning() && !CheckPositioningLosFN(target, tempX, tempY, tempZ)) {
|
||||
//LogTestDebug("{} - Plot Failed LoS - Try #[{}]. Target LOCs XYZ - [{}], [{}], [{}] - Temp LOCs [{}], [{}], [{}] - Distance between = [{}] - Melee Distance = [{}] - Difference = [{}]", GetCleanName(), (counter + 1), target->GetX(), target->GetY(), target->GetZ(), tempX, tempY, tempZ, tar_distance, max_distance, (tar_distance / max_distance));
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
//LogTestDebug("{} - Plot PASSED! - Try #[{}]. Target LOCs XYZ - [{}], [{}], [{}] - Temp LOCs [{}], [{}], [{}] - Distance between = [{}] - Melee Distance = [{}] - Difference = [{}]", GetCleanName(), (counter + 1), target->GetX(), target->GetY(), target->GetZ(), tempX, tempY, tempZ, tar_distance, max_distance, (tar_distance / max_distance));
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Result) {
|
||||
x_dest = tempX;
|
||||
y_dest = tempY;
|
||||
z_dest = tempZ;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Mob::HateSummon() {
|
||||
// check if mob has ability to summon
|
||||
// 97% is the offical % that summoning starts on live, not 94
|
||||
@@ -8574,8 +8666,9 @@ bool Mob::HasBotAttackFlag(Mob* tar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const uint16 scan_close_mobs_timer_moving = 6000; // 6 seconds
|
||||
const uint16 scan_close_mobs_timer_idle = 60000; // 60 seconds
|
||||
const uint16 scan_close_mobs_timer_idle = 60000; // 60 seconds
|
||||
|
||||
// If the moving timer triggers, lets see if we are moving or idle to restart the appropriate dynamic timer
|
||||
void Mob::CheckScanCloseMobsMovingTimer()
|
||||
@@ -8604,6 +8697,732 @@ void Mob::CheckScanCloseMobsMovingTimer()
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Mob::GetSpellTypeIDByShortName(std::string spellTypeString) {
|
||||
|
||||
for (int i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
if (!Strings::ToLower(spellTypeString).compare(GetSpellTypeShortNameByID(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return UINT16_MAX;
|
||||
}
|
||||
|
||||
std::string Mob::GetSpellTypeNameByID(uint16 spellType) {
|
||||
std::string spellTypeName = "null";
|
||||
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Nuke:
|
||||
spellTypeName = "Nuke";
|
||||
break;
|
||||
case BotSpellTypes::RegularHeal:
|
||||
spellTypeName = "Regular Heal";
|
||||
break;
|
||||
case BotSpellTypes::Root:
|
||||
spellTypeName = "Root";
|
||||
break;
|
||||
case BotSpellTypes::Buff:
|
||||
spellTypeName = "Buff";
|
||||
break;
|
||||
case BotSpellTypes::Escape:
|
||||
spellTypeName = "Escape";
|
||||
break;
|
||||
case BotSpellTypes::Pet:
|
||||
spellTypeName = "Pet";
|
||||
break;
|
||||
case BotSpellTypes::Lifetap:
|
||||
spellTypeName = "Lifetap";
|
||||
break;
|
||||
case BotSpellTypes::Snare:
|
||||
spellTypeName = "Snare";
|
||||
break;
|
||||
case BotSpellTypes::DOT:
|
||||
spellTypeName = "DoT";
|
||||
break;
|
||||
case BotSpellTypes::Dispel:
|
||||
spellTypeName = "Dispel";
|
||||
break;
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
spellTypeName = "In-Combat Buff";
|
||||
break;
|
||||
case BotSpellTypes::Mez:
|
||||
spellTypeName = "Mez";
|
||||
break;
|
||||
case BotSpellTypes::Charm:
|
||||
spellTypeName = "Charm";
|
||||
break;
|
||||
case BotSpellTypes::Slow:
|
||||
spellTypeName = "Slow";
|
||||
break;
|
||||
case BotSpellTypes::Debuff:
|
||||
spellTypeName = "Debuff";
|
||||
break;
|
||||
case BotSpellTypes::Cure:
|
||||
spellTypeName = "Cure";
|
||||
break;
|
||||
case BotSpellTypes::GroupCures:
|
||||
spellTypeName = "Group Cure";
|
||||
break;
|
||||
case BotSpellTypes::Resurrect:
|
||||
spellTypeName = "Resurrect";
|
||||
break;
|
||||
case BotSpellTypes::HateRedux:
|
||||
spellTypeName = "Hate Reduction";
|
||||
break;
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
spellTypeName = "In-Combat Buff Song";
|
||||
break;
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
spellTypeName = "Out-of-Combat Buff Song";
|
||||
break;
|
||||
case BotSpellTypes::PreCombatBuff:
|
||||
spellTypeName = "Pre-Combat Buff";
|
||||
break;
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
spellTypeName = "Pre-Combat Buff Song";
|
||||
break;
|
||||
case BotSpellTypes::Fear:
|
||||
spellTypeName = "Fear";
|
||||
break;
|
||||
case BotSpellTypes::Stun:
|
||||
spellTypeName = "Stun";
|
||||
break;
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
spellTypeName = "Complete Heal";
|
||||
break;
|
||||
case BotSpellTypes::FastHeals:
|
||||
spellTypeName = "Fast Heal";
|
||||
break;
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
spellTypeName = "Very Fast Heal";
|
||||
break;
|
||||
case BotSpellTypes::GroupHeals:
|
||||
spellTypeName = "Group Heal";
|
||||
break;
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
spellTypeName = "Group Complete Heal";
|
||||
break;
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
spellTypeName = "Group HoT Heal";
|
||||
break;
|
||||
case BotSpellTypes::HoTHeals:
|
||||
spellTypeName = "HoT Heal";
|
||||
break;
|
||||
case BotSpellTypes::AENukes:
|
||||
spellTypeName = "AE Nuke";
|
||||
break;
|
||||
case BotSpellTypes::AERains:
|
||||
spellTypeName = "AE Rain";
|
||||
break;
|
||||
case BotSpellTypes::AEMez:
|
||||
spellTypeName = "AE Mez";
|
||||
break;
|
||||
case BotSpellTypes::AEStun:
|
||||
spellTypeName = "AE Stun";
|
||||
break;
|
||||
case BotSpellTypes::AEDebuff:
|
||||
spellTypeName = "AE Debuff";
|
||||
break;
|
||||
case BotSpellTypes::AESlow:
|
||||
spellTypeName = "AE Slow";
|
||||
break;
|
||||
case BotSpellTypes::AESnare:
|
||||
spellTypeName = "AE Snare";
|
||||
break;
|
||||
case BotSpellTypes::AEFear:
|
||||
spellTypeName = "AE Fear";
|
||||
break;
|
||||
case BotSpellTypes::AEDispel:
|
||||
spellTypeName = "AE Dispel";
|
||||
break;
|
||||
case BotSpellTypes::AERoot:
|
||||
spellTypeName = "AE Root";
|
||||
break;
|
||||
case BotSpellTypes::AEDoT:
|
||||
spellTypeName = "AE DoT";
|
||||
break;
|
||||
case BotSpellTypes::AELifetap:
|
||||
spellTypeName = "AE Lifetap";
|
||||
break;
|
||||
case BotSpellTypes::PBAENuke:
|
||||
spellTypeName = "PBAE Nuke";
|
||||
break;
|
||||
case BotSpellTypes::PetBuffs:
|
||||
spellTypeName = "Pet Buff";
|
||||
break;
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
spellTypeName = "Pet Regular Heal";
|
||||
break;
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
spellTypeName = "Pet Complete Heal";
|
||||
break;
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
spellTypeName = "Pet Fast Heal";
|
||||
break;
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
spellTypeName = "Pet Very Fast Heal";
|
||||
break;
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
spellTypeName = "Pet HoT Heal";
|
||||
break;
|
||||
case BotSpellTypes::DamageShields:
|
||||
spellTypeName = "Damage Shield";
|
||||
break;
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
spellTypeName = "Resist Buff";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return spellTypeName;
|
||||
}
|
||||
|
||||
std::string Mob::GetSpellTypeShortNameByID(uint16 spellType) {
|
||||
std::string spellTypeName = "null";
|
||||
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Nuke:
|
||||
spellTypeName = "nukes";
|
||||
break;
|
||||
case BotSpellTypes::RegularHeal:
|
||||
spellTypeName = "regularheals";
|
||||
break;
|
||||
case BotSpellTypes::Root:
|
||||
spellTypeName = "roots";
|
||||
break;
|
||||
case BotSpellTypes::Buff:
|
||||
spellTypeName = "buffs";
|
||||
break;
|
||||
case BotSpellTypes::Escape:
|
||||
spellTypeName = "escapes";
|
||||
break;
|
||||
case BotSpellTypes::Pet:
|
||||
spellTypeName = "pets";
|
||||
break;
|
||||
case BotSpellTypes::Lifetap:
|
||||
spellTypeName = "lifetaps";
|
||||
break;
|
||||
case BotSpellTypes::Snare:
|
||||
spellTypeName = "snares";
|
||||
break;
|
||||
case BotSpellTypes::DOT:
|
||||
spellTypeName = "dots";
|
||||
break;
|
||||
case BotSpellTypes::Dispel:
|
||||
spellTypeName = "dispels";
|
||||
break;
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
spellTypeName = "incombatbuffs";
|
||||
break;
|
||||
case BotSpellTypes::Mez:
|
||||
spellTypeName = "mez";
|
||||
break;
|
||||
case BotSpellTypes::Charm:
|
||||
spellTypeName = "charms";
|
||||
break;
|
||||
case BotSpellTypes::Slow:
|
||||
spellTypeName = "slows";
|
||||
break;
|
||||
case BotSpellTypes::Debuff:
|
||||
spellTypeName = "debuffs";
|
||||
break;
|
||||
case BotSpellTypes::Cure:
|
||||
spellTypeName = "cures";
|
||||
break;
|
||||
case BotSpellTypes::GroupCures:
|
||||
spellTypeName = "groupcures";
|
||||
break;
|
||||
case BotSpellTypes::Resurrect:
|
||||
spellTypeName = "resurrect";
|
||||
break;
|
||||
case BotSpellTypes::HateRedux:
|
||||
spellTypeName = "hateredux";
|
||||
break;
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
spellTypeName = "incombatbuffsongs";
|
||||
break;
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
spellTypeName = "outofcombatbuffsongs";
|
||||
break;
|
||||
case BotSpellTypes::PreCombatBuff:
|
||||
spellTypeName = "precombatbuffs";
|
||||
break;
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
spellTypeName = "precombatbuffsongs";
|
||||
break;
|
||||
case BotSpellTypes::Fear:
|
||||
spellTypeName = "fears";
|
||||
break;
|
||||
case BotSpellTypes::Stun:
|
||||
spellTypeName = "stuns";
|
||||
break;
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
spellTypeName = "completeheals";
|
||||
break;
|
||||
case BotSpellTypes::FastHeals:
|
||||
spellTypeName = "fastheals";
|
||||
break;
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
spellTypeName = "veryfastheals";
|
||||
break;
|
||||
case BotSpellTypes::GroupHeals:
|
||||
spellTypeName = "groupheals";
|
||||
break;
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
spellTypeName = "groupcompleteheals";
|
||||
break;
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
spellTypeName = "grouphotheals";
|
||||
break;
|
||||
case BotSpellTypes::HoTHeals:
|
||||
spellTypeName = "hotheals";
|
||||
break;
|
||||
case BotSpellTypes::AENukes:
|
||||
spellTypeName = "aenukes";
|
||||
break;
|
||||
case BotSpellTypes::AERains:
|
||||
spellTypeName = "aerains";
|
||||
break;
|
||||
case BotSpellTypes::AEMez:
|
||||
spellTypeName = "aemez";
|
||||
break;
|
||||
case BotSpellTypes::AEStun:
|
||||
spellTypeName = "aestuns";
|
||||
break;
|
||||
case BotSpellTypes::AEDebuff:
|
||||
spellTypeName = "aedebuffs";
|
||||
break;
|
||||
case BotSpellTypes::AESlow:
|
||||
spellTypeName = "aeslows";
|
||||
break;
|
||||
case BotSpellTypes::AESnare:
|
||||
spellTypeName = "aesnares";
|
||||
break;
|
||||
case BotSpellTypes::AEFear:
|
||||
spellTypeName = "aefears";
|
||||
break;
|
||||
case BotSpellTypes::AEDispel:
|
||||
spellTypeName = "aedispels";
|
||||
break;
|
||||
case BotSpellTypes::AERoot:
|
||||
spellTypeName = "aeroots";
|
||||
break;
|
||||
case BotSpellTypes::AEDoT:
|
||||
spellTypeName = "aedots";
|
||||
break;
|
||||
case BotSpellTypes::AELifetap:
|
||||
spellTypeName = "aelifetaps";
|
||||
break;
|
||||
case BotSpellTypes::PBAENuke:
|
||||
spellTypeName = "pbaenukes";
|
||||
break;
|
||||
case BotSpellTypes::PetBuffs:
|
||||
spellTypeName = "petbuffs";
|
||||
break;
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
spellTypeName = "petregularheals";
|
||||
break;
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
spellTypeName = "petcompleteheals";
|
||||
break;
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
spellTypeName = "petfastheals";
|
||||
break;
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
spellTypeName = "petveryfastheals";
|
||||
break;
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
spellTypeName = "pethotheals";
|
||||
break;
|
||||
case BotSpellTypes::DamageShields:
|
||||
spellTypeName = "damageshields";
|
||||
break;
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
spellTypeName = "resistbuffs";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return spellTypeName;
|
||||
}
|
||||
|
||||
bool Mob::GetDefaultSpellHold(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::AEMez:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::Fear:
|
||||
return true;
|
||||
case BotSpellTypes::Snare:
|
||||
if (GetClass() == Class::Wizard) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
if (GetClass() == Class::Bard) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Mob::GetDefaultSpellDelay(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
return 1500;
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
return 2500;
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
return 4000;
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::Snare:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::Stun:
|
||||
return 6000;
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
return 8000;
|
||||
case BotSpellTypes::Fear:
|
||||
case BotSpellTypes::AEFear:
|
||||
return 15000;
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
return 22000;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 Mob::GetDefaultSpellMinThreshold(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::AEDispel:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::Slow:
|
||||
return 20;
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::DOT:
|
||||
return 35;
|
||||
case BotSpellTypes::Charm:
|
||||
return 50;
|
||||
case BotSpellTypes::Mez:
|
||||
case BotSpellTypes::AEMez:
|
||||
return 85;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 Mob::GetDefaultSpellMaxThreshold(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Escape:
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
case BotSpellTypes::PetVeryFastHeals:
|
||||
return 25;
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::Lifetap:
|
||||
case BotSpellTypes::FastHeals:
|
||||
case BotSpellTypes::PetFastHeals:
|
||||
return 40;
|
||||
case BotSpellTypes::GroupHeals:
|
||||
case BotSpellTypes::RegularHeal:
|
||||
case BotSpellTypes::PetRegularHeals:
|
||||
return 60;
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
case BotSpellTypes::GroupCompleteHeals:
|
||||
case BotSpellTypes::PetCompleteHeals:
|
||||
return 80;
|
||||
case BotSpellTypes::AENukes:
|
||||
case BotSpellTypes::AERains:
|
||||
case BotSpellTypes::PBAENuke:
|
||||
case BotSpellTypes::AEStun:
|
||||
case BotSpellTypes::Nuke:
|
||||
case BotSpellTypes::AEDoT:
|
||||
case BotSpellTypes::DOT:
|
||||
case BotSpellTypes::AERoot:
|
||||
case BotSpellTypes::Root:
|
||||
case BotSpellTypes::AESlow:
|
||||
case BotSpellTypes::Slow:
|
||||
case BotSpellTypes::AESnare:
|
||||
case BotSpellTypes::Snare:
|
||||
case BotSpellTypes::AEFear:
|
||||
case BotSpellTypes::Fear:
|
||||
case BotSpellTypes::Dispel:
|
||||
case BotSpellTypes::AEDebuff:
|
||||
case BotSpellTypes::Debuff:
|
||||
case BotSpellTypes::Stun:
|
||||
return 99;
|
||||
case BotSpellTypes::Buff:
|
||||
case BotSpellTypes::Charm:
|
||||
case BotSpellTypes::Cure:
|
||||
case BotSpellTypes::DamageShields:
|
||||
case BotSpellTypes::HateRedux:
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
case BotSpellTypes::Mez:
|
||||
case BotSpellTypes::AEMez:
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
case BotSpellTypes::Pet:
|
||||
case BotSpellTypes::PetBuffs:
|
||||
case BotSpellTypes::PreCombatBuff:
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
case BotSpellTypes::ResistBuffs:
|
||||
case BotSpellTypes::Resurrect:
|
||||
return 100;
|
||||
case BotSpellTypes::GroupHoTHeals:
|
||||
case BotSpellTypes::HoTHeals:
|
||||
case BotSpellTypes::PetHoTHeals:
|
||||
if (GetClass() == Class::Necromancer || GetClass() == Class::Shaman) {
|
||||
return 60;
|
||||
}
|
||||
else {
|
||||
return 90;
|
||||
}
|
||||
default:
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::SetSpellHold(uint16 spellType, bool holdStatus) {
|
||||
_spellSettings[spellType].hold = holdStatus;
|
||||
}
|
||||
|
||||
void Mob::SetSpellDelay(uint16 spellType, uint16 delayValue) {
|
||||
_spellSettings[spellType].delay = delayValue;
|
||||
}
|
||||
|
||||
void Mob::SetSpellMinThreshold(uint16 spellType, uint8 thresholdValue) {
|
||||
_spellSettings[spellType].minThreshold = thresholdValue;
|
||||
}
|
||||
|
||||
void Mob::SetSpellMaxThreshold(uint16 spellType, uint8 thresholdValue) {
|
||||
_spellSettings[spellType].maxThreshold = thresholdValue;
|
||||
}
|
||||
|
||||
void Mob::SetSpellTypeRecastTimer(uint16 spellType, uint32 recastTime) {
|
||||
_spellSettings[spellType].recastTimer.Start(recastTime);
|
||||
LogBotDelayChecksDetail("{} says, 'My {} Delay was to {} seconds.'"
|
||||
, GetCleanName()
|
||||
, GetSpellTypeNameByID(spellType)
|
||||
, (recastTime / 1000.00)
|
||||
); //deleteme
|
||||
}
|
||||
|
||||
void Mob::StartBotSpellTimers() {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
_spellSettings[i].recastTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::DisableBotSpellTimers() {
|
||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||
_spellSettings[i].recastTimer.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::GetUltimateSpellHold(uint16 spellType, Mob* tar) {
|
||||
if (!tar) {
|
||||
return GetSpellHold(spellType);
|
||||
}
|
||||
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
return tar->GetOwner()->GetSpellHold(GetPetSpellType(spellType));
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_OTHER_BENEFICIAL(spellType) && tar->IsOfClientBot()) {
|
||||
return tar->GetSpellHold(spellType);
|
||||
}
|
||||
|
||||
return GetSpellHold(spellType);
|
||||
}
|
||||
|
||||
uint16 Mob::GetUltimateSpellDelay(uint16 spellType, Mob* tar) {
|
||||
if (!tar) {
|
||||
return GetSpellDelay(spellType);
|
||||
}
|
||||
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
return tar->GetOwner()->GetSpellDelay(GetPetSpellType(spellType));
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_OTHER_BENEFICIAL(spellType) && tar->IsOfClientBot()) {
|
||||
return tar->GetSpellDelay(spellType);
|
||||
}
|
||||
|
||||
return GetSpellDelay(spellType);
|
||||
}
|
||||
|
||||
bool Mob::GetUltimateSpellDelayCheck(uint16 spellType, Mob* tar) {
|
||||
if (!tar) {
|
||||
return SpellTypeRecastCheck(spellType);
|
||||
}
|
||||
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
return tar->GetOwner()->SpellTypeRecastCheck(GetPetSpellType(spellType));
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_OTHER_BENEFICIAL(spellType) && tar->IsOfClientBot()) {
|
||||
return tar->SpellTypeRecastCheck(spellType);
|
||||
}
|
||||
|
||||
return SpellTypeRecastCheck(spellType);
|
||||
}
|
||||
|
||||
uint8 Mob::GetUltimateSpellMinThreshold(uint16 spellType, Mob* tar) {
|
||||
if (!tar) {
|
||||
return GetSpellMinThreshold(spellType);
|
||||
}
|
||||
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
return tar->GetOwner()->GetSpellMinThreshold(GetPetSpellType(spellType));
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_OTHER_BENEFICIAL(spellType) && tar->IsOfClientBot()) {
|
||||
return tar->GetSpellMinThreshold(spellType);
|
||||
}
|
||||
|
||||
return GetSpellMinThreshold(spellType);
|
||||
}
|
||||
|
||||
uint8 Mob::GetUltimateSpellMaxThreshold(uint16 spellType, Mob* tar) {
|
||||
if (!tar) {
|
||||
return GetSpellMaxThreshold(spellType);
|
||||
}
|
||||
|
||||
if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot()) {
|
||||
return tar->GetOwner()->GetSpellMaxThreshold(GetPetSpellType(spellType));
|
||||
}
|
||||
|
||||
if (BOT_SPELL_TYPES_OTHER_BENEFICIAL(spellType) && tar->IsOfClientBot()) {
|
||||
return tar->GetSpellMaxThreshold(spellType);
|
||||
}
|
||||
|
||||
return GetSpellMaxThreshold(spellType);
|
||||
}
|
||||
|
||||
uint16 Mob::GetPetSpellType(uint16 spellType) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::VeryFastHeals:
|
||||
return BotSpellTypes::PetVeryFastHeals;
|
||||
case BotSpellTypes::FastHeals:
|
||||
return BotSpellTypes::PetFastHeals;
|
||||
case BotSpellTypes::RegularHeal:
|
||||
return BotSpellTypes::PetRegularHeals;
|
||||
case BotSpellTypes::CompleteHeal:
|
||||
return BotSpellTypes::PetCompleteHeals;
|
||||
case BotSpellTypes::HoTHeals:
|
||||
return BotSpellTypes::PetHoTHeals;
|
||||
case BotSpellTypes::Buff:
|
||||
return BotSpellTypes::PetBuffs;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return spellType;
|
||||
}
|
||||
|
||||
uint8 Mob::GetHPRatioForSpellType(uint16 spellType, Mob* tar) {
|
||||
switch (spellType) {
|
||||
case BotSpellTypes::Escape:
|
||||
case BotSpellTypes::HateRedux:
|
||||
case BotSpellTypes::InCombatBuff:
|
||||
case BotSpellTypes::InCombatBuffSong:
|
||||
case BotSpellTypes::AELifetap:
|
||||
case BotSpellTypes::Lifetap:
|
||||
case BotSpellTypes::OutOfCombatBuffSong:
|
||||
case BotSpellTypes::Pet:
|
||||
case BotSpellTypes::PreCombatBuff:
|
||||
case BotSpellTypes::PreCombatBuffSong:
|
||||
return GetHPRatio();
|
||||
default:
|
||||
return tar->GetHPRatio();
|
||||
}
|
||||
|
||||
return tar->GetHPRatio();
|
||||
}
|
||||
|
||||
void Mob::SetBotSetting(uint8 settingType, uint16 botSetting, int settingValue) {
|
||||
if (!IsOfClientBot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
CastToClient()->SetBotSetting(settingType, botSetting, settingValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsBot()) {
|
||||
CastToBot()->SetBotSetting(settingType, botSetting, settingValue);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Mob::SetBaseSetting(uint16 baseSetting, int settingValue) {
|
||||
switch (baseSetting) {
|
||||
case BotBaseSettings::IllusionBlock:
|
||||
SetIllusionBlock(settingValue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::TargetValidation(Mob* other) {
|
||||
if (!other || GetAppearance() == eaDead) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<uint16, Mob *> &Mob::GetCloseMobList(float distance)
|
||||
{
|
||||
return entity_list.GetCloseMobList(this, distance);
|
||||
|
||||
+103
@@ -93,6 +93,28 @@ struct AppearanceStruct {
|
||||
uint8 texture = UINT8_MAX;
|
||||
};
|
||||
|
||||
struct BotSpellSettings_Struct
|
||||
{
|
||||
uint16 spellType; // type ID of bot category
|
||||
std::string shortName; // type short name of bot category
|
||||
std::string name; // type name of bot category
|
||||
bool hold; // 0 = allow spell type, 1 = hold spell type
|
||||
uint16 delay; // delay between casts of spell type, 1ms-60,000ms
|
||||
uint8 minThreshold; // minimum target health threshold to allow casting of spell type
|
||||
uint8 maxThreshold; // maximum target health threshold to allow casting of spell type
|
||||
uint16 resistLimit; // resist limit to skip spell type
|
||||
bool aggroCheck; // whether or not to check for possible aggro before casting
|
||||
uint8 minManaPct; // lower mana percentage limit to allow spell cast
|
||||
uint8 maxManaPct; // upper mana percentage limit to allow spell cast
|
||||
uint8 minHPPct; // lower HP percentage limit to allow spell cast
|
||||
uint8 maxHPPct; // upper HP percentage limit to allow spell cast
|
||||
uint16 idlePriority; // idle priority of the spell type
|
||||
uint16 engagedPriority; // engaged priority of the spell type
|
||||
uint16 pursuePriority; // pursue priority of the spell type
|
||||
uint16 AEOrGroupTargetCount; // require target count to cast an AE or Group spell type
|
||||
Timer recastTimer; // recast timer based off delay
|
||||
};
|
||||
|
||||
class DataBucketKey;
|
||||
class Mob : public Entity {
|
||||
public:
|
||||
@@ -208,6 +230,8 @@ public:
|
||||
// Bot attack flag
|
||||
Timer bot_attack_flag_timer;
|
||||
|
||||
std::vector<BotSpellSettings_Struct> _spellSettings;
|
||||
|
||||
//Somewhat sorted: needs documenting!
|
||||
|
||||
//Attack
|
||||
@@ -403,6 +427,51 @@ public:
|
||||
virtual bool CheckFizzle(uint16 spell_id);
|
||||
virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
|
||||
virtual bool IsImmuneToBotSpell(uint16 spell_id, Mob* caster);
|
||||
|
||||
inline bool SpellTypeRecastCheck(uint16 spellType) { return (IsClient() ? true : _spellSettings[spellType].recastTimer.GetRemainingTime() > 0 ? false : true); }
|
||||
|
||||
uint16 GetSpellTypeIDByShortName(std::string spellTypeString);
|
||||
|
||||
std::string GetSpellTypeNameByID(uint16 spellType);
|
||||
std::string GetSpellTypeShortNameByID(uint16 spellType);
|
||||
|
||||
bool GetDefaultSpellHold(uint16 spellType);
|
||||
uint16 GetDefaultSpellDelay(uint16 spellType);
|
||||
uint8 GetDefaultSpellMinThreshold(uint16 spellType);
|
||||
uint8 GetDefaultSpellMaxThreshold(uint16 spellType);
|
||||
|
||||
inline bool GetSpellHold(uint16 spellType) const { return _spellSettings[spellType].hold; }
|
||||
void SetSpellHold(uint16 spellType, bool holdStatus);
|
||||
inline uint16 GetSpellDelay(uint16 spellType) const { return _spellSettings[spellType].delay; }
|
||||
void SetSpellDelay(uint16 spellType, uint16 delayValue);
|
||||
inline uint8 GetSpellMinThreshold(uint16 spellType) const { return _spellSettings[spellType].minThreshold; }
|
||||
void SetSpellMinThreshold(uint16 spellType, uint8 thresholdValue);
|
||||
inline uint8 GetSpellMaxThreshold(uint16 spellType) const { return _spellSettings[spellType].maxThreshold; }
|
||||
void SetSpellMaxThreshold(uint16 spellType, uint8 thresholdValue);
|
||||
|
||||
inline uint16 GetSpellTypeRecastTimer(uint16 spellType) { return _spellSettings[spellType].recastTimer.GetRemainingTime(); }
|
||||
void SetSpellTypeRecastTimer(uint16 spellType, uint32 recastTime);
|
||||
|
||||
uint8 GetHPRatioForSpellType(uint16 spellType, Mob* tar);
|
||||
bool GetUltimateSpellHold(uint16 spellType, Mob* tar);
|
||||
uint16 GetUltimateSpellDelay(uint16 spellType, Mob* tar);
|
||||
bool GetUltimateSpellDelayCheck(uint16 spellType, Mob* tar);
|
||||
uint8 GetUltimateSpellMinThreshold(uint16 spellType, Mob* tar);
|
||||
uint8 GetUltimateSpellMaxThreshold(uint16 spellType, Mob* tar);
|
||||
|
||||
uint16 GetPetSpellType(uint16 spellType);
|
||||
|
||||
void DisableBotSpellTimers();
|
||||
void StartBotSpellTimers();
|
||||
|
||||
void SetBotSetting(uint8 settingType, uint16 botSetting, int settingValue);
|
||||
void SetBaseSetting(uint16 baseSetting, int settingValue);
|
||||
|
||||
void SetIllusionBlock(bool value) { _illusionBlock = value; }
|
||||
bool GetIllusionBlock() const { return _illusionBlock; }
|
||||
|
||||
virtual float GetAOERange(uint16 spell_id);
|
||||
void InterruptSpell(uint16 spellid = SPELL_UNKNOWN);
|
||||
void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN);
|
||||
@@ -791,6 +860,11 @@ public:
|
||||
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
|
||||
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
|
||||
virtual bool CheckWaterLoS(Mob* m);
|
||||
bool CheckPositioningLosFN(Mob* other, float posX, float posY, float posZ);
|
||||
bool CheckLosCheat(Mob* who, Mob* other);
|
||||
bool CheckLosCheatExempt(Mob* who, Mob* other);
|
||||
bool DoLosChecks(Mob* who, Mob* other);
|
||||
bool TargetValidation(Mob* other);
|
||||
inline void SetLastLosState(bool value) { last_los_check = value; }
|
||||
inline bool CheckLastLosState() const { return last_los_check; }
|
||||
std::string GetMobDescription();
|
||||
@@ -854,6 +928,7 @@ public:
|
||||
void ShowStats(Client* client);
|
||||
void ShowBuffs(Client* c);
|
||||
bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc = true);
|
||||
bool PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behindOnly = false, bool frontOnly = false, bool bypassLoS = false);
|
||||
virtual int GetKillExpMod() const { return 100; }
|
||||
|
||||
// aura functions
|
||||
@@ -1252,13 +1327,30 @@ public:
|
||||
|
||||
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
||||
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
||||
inline uint32 DontGroupHealMeBefore() const { return pDontGroupHealMeBefore; }
|
||||
inline uint32 DontGroupHoTHealMeBefore() const { return pDontGroupHoTHealMeBefore; }
|
||||
inline uint32 DontRegularHealMeBefore() const { return pDontRegularHealMeBefore; }
|
||||
inline uint32 DontVeryFastHealMeBefore() const { return pDontVeryFastHealMeBefore; }
|
||||
inline uint32 DontFastHealMeBefore() const { return pDontFastHealMeBefore; }
|
||||
inline uint32 DontCompleteHealMeBefore() const { return pDontCompleteHealMeBefore; }
|
||||
inline uint32 DontGroupCompleteHealMeBefore() const { return pDontGroupCompleteHealMeBefore; }
|
||||
inline uint32 DontHotHealMeBefore() const { return pDontHotHealMeBefore; }
|
||||
inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; }
|
||||
inline uint32 DontDotMeBefore() const { return pDontDotMeBefore; }
|
||||
inline uint32 DontRootMeBefore() const { return pDontRootMeBefore; }
|
||||
inline uint32 DontSnareMeBefore() const { return pDontSnareMeBefore; }
|
||||
inline uint32 DontCureMeBefore() const { return pDontCureMeBefore; }
|
||||
|
||||
void SetDontRootMeBefore(uint32 time) { pDontRootMeBefore = time; }
|
||||
void SetDontHealMeBefore(uint32 time) { pDontHealMeBefore = time; }
|
||||
void SetDontGroupHealMeBefore(uint32 time) { pDontGroupHealMeBefore = time; }
|
||||
void SetDontGroupHoTHealMeBefore(uint32 time) { pDontGroupHoTHealMeBefore = time; }
|
||||
void SetDontRegularHealMeBefore(uint32 time) { pDontRegularHealMeBefore = time; }
|
||||
void SetDontVeryFastHealMeBefore(uint32 time) { pDontVeryFastHealMeBefore = time; }
|
||||
void SetDontFastHealMeBefore(uint32 time) { pDontFastHealMeBefore = time; }
|
||||
void SetDontCompleteHealMeBefore(uint32 time) { pDontCompleteHealMeBefore = time; }
|
||||
void SetDontGroupCompleteHealMeBefore(uint32 time) { pDontGroupCompleteHealMeBefore = time; }
|
||||
void SetDontHotHealMeBefore(uint32 time) { pDontHotHealMeBefore = time; }
|
||||
void SetDontBuffMeBefore(uint32 time) { pDontBuffMeBefore = time; }
|
||||
void SetDontDotMeBefore(uint32 time) { pDontDotMeBefore = time; }
|
||||
void SetDontSnareMeBefore(uint32 time) { pDontSnareMeBefore = time; }
|
||||
@@ -1858,6 +1950,14 @@ protected:
|
||||
bool pause_timer_complete;
|
||||
bool DistractedFromGrid;
|
||||
uint32 pDontHealMeBefore;
|
||||
uint32 pDontGroupHealMeBefore;
|
||||
uint32 pDontGroupHoTHealMeBefore;
|
||||
uint32 pDontRegularHealMeBefore;
|
||||
uint32 pDontVeryFastHealMeBefore;
|
||||
uint32 pDontFastHealMeBefore;
|
||||
uint32 pDontCompleteHealMeBefore;
|
||||
uint32 pDontGroupCompleteHealMeBefore;
|
||||
uint32 pDontHotHealMeBefore;
|
||||
uint32 pDontBuffMeBefore;
|
||||
uint32 pDontDotMeBefore;
|
||||
uint32 pDontRootMeBefore;
|
||||
@@ -1880,6 +1980,9 @@ protected:
|
||||
//bot attack flags
|
||||
std::vector<uint32> bot_attack_flags;
|
||||
|
||||
//bot related settings
|
||||
bool _illusionBlock;
|
||||
|
||||
glm::vec3 m_TargetRing;
|
||||
|
||||
GravityBehavior flymode;
|
||||
|
||||
@@ -425,11 +425,6 @@ void Perl_Bot_SetExpansionBitmask(Bot* self, int expansion_bitmask)
|
||||
self->SetExpansionBitmask(expansion_bitmask);
|
||||
}
|
||||
|
||||
void Perl_Bot_SetExpansionBitmask(Bot* self, int expansion_bitmask, bool save)
|
||||
{
|
||||
self->SetExpansionBitmask(expansion_bitmask, save);
|
||||
}
|
||||
|
||||
void Perl_Bot_SetSpellDuration(Bot* self, int spell_id)
|
||||
{
|
||||
self->SetSpellDuration(spell_id);
|
||||
@@ -716,7 +711,6 @@ void perl_register_bot()
|
||||
package.add("SendPayload", (void(*)(Bot*, int, std::string))&Perl_Bot_SendPayload);
|
||||
package.add("SendSpellAnim", &Perl_Bot_SendSpellAnim);
|
||||
package.add("SetExpansionBitmask", (void(*)(Bot*, int))&Perl_Bot_SetExpansionBitmask);
|
||||
package.add("SetExpansionBitmask", (void(*)(Bot*, int, bool))&Perl_Bot_SetExpansionBitmask);
|
||||
package.add("SetDisciplineReuseTimer", (void(*)(Bot*, uint16))&Perl_Bot_SetDisciplineReuseTimer);
|
||||
package.add("SetDisciplineReuseTimer", (void(*)(Bot*, uint16, uint32))&Perl_Bot_SetDisciplineReuseTimer);
|
||||
package.add("SetItemReuseTimer", (void(*)(Bot*, uint32))&Perl_Bot_SetItemReuseTimer);
|
||||
|
||||
@@ -1144,7 +1144,7 @@ void Perl_Client_SetStartZone(Client* self, uint32 zone_id, float x, float y, fl
|
||||
|
||||
void Perl_Client_KeyRingAdd(Client* self, uint32 item_id) // @categories Account and Character, Inventory and Items
|
||||
{
|
||||
self->KeyRingAdd(item_id);;
|
||||
self->KeyRingAdd(item_id);
|
||||
}
|
||||
|
||||
bool Perl_Client_KeyRingCheck(Client* self, uint32 item_id) // @categories Account and Character, Inventory and Items
|
||||
@@ -1154,7 +1154,7 @@ bool Perl_Client_KeyRingCheck(Client* self, uint32 item_id) // @categories Accou
|
||||
|
||||
void Perl_Client_AddPVPPoints(Client* self, uint32 points) // @categories Currency and Points
|
||||
{
|
||||
self->AddPVPPoints(points);;
|
||||
self->AddPVPPoints(points);
|
||||
}
|
||||
|
||||
void Perl_Client_AddCrystals(Client* self, uint32 radiant_count, uint32 ebon_count) // @categories Currency and Points
|
||||
|
||||
+1
-1
@@ -892,7 +892,7 @@ void perl_register_npc()
|
||||
package.add("IsGuarding", &Perl_NPC_IsGuarding);
|
||||
package.add("IsLDoNLocked", &Perl_NPC_IsLDoNLocked);
|
||||
package.add("IsLDoNTrapped", &Perl_NPC_IsLDoNTrapped);
|
||||
package.add("IsLDoNTrapDetected", &Perl_NPC_IsLDoNTrapDetected);;
|
||||
package.add("IsLDoNTrapDetected", &Perl_NPC_IsLDoNTrapDetected);
|
||||
package.add("IsOnHatelist", &Perl_NPC_IsOnHatelist);
|
||||
package.add("IsRaidTarget", &Perl_NPC_IsRaidTarget);
|
||||
package.add("IsRareSpawn", &Perl_NPC_IsRareSpawn);
|
||||
|
||||
+1
-1
@@ -2857,7 +2857,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level
|
||||
initiator->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} has invalid characters. You can use only the A-Z, a-z and _ characters in a bot name.",
|
||||
"{} has invalid characters. You can use only the A-Z, a-z and _ characters in a bot name and it must be between 4 and 15 characters long.",
|
||||
new_bot->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
|
||||
@@ -1483,6 +1483,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Illusion: race %d", effect_value);
|
||||
#endif
|
||||
if (caster && caster->IsOfClientBot() && GetIllusionBlock()) {
|
||||
break;
|
||||
}
|
||||
|
||||
ApplySpellEffectIllusion(spell_id, caster, buffslot, spells[spell_id].base_value[i], spells[spell_id].limit_value[i], spells[spell_id].max_value[i]);
|
||||
break;
|
||||
}
|
||||
@@ -1492,6 +1496,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Illusion Copy");
|
||||
#endif
|
||||
if (caster && caster->IsOfClientBot() && GetIllusionBlock()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(caster && caster->GetTarget()){
|
||||
SendIllusionPacket
|
||||
(
|
||||
@@ -10660,7 +10668,7 @@ int Mob::GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier)
|
||||
|
||||
if (id == "caster_level") { return buffs[slot].casterlevel; }
|
||||
else if (id == "spell_id") { return buffs[slot].spellid; }
|
||||
else if (id == "caster_id") { return buffs[slot].spellid;; }
|
||||
else if (id == "caster_id") { return buffs[slot].spellid; }
|
||||
else if (id == "ticsremaining") { return buffs[slot].ticsremaining; }
|
||||
else if (id == "counters") { return buffs[slot].counters; }
|
||||
else if (id == "hit_number") { return buffs[slot].hit_number; }
|
||||
|
||||
+197
-6
@@ -466,7 +466,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
CastedSpellFinished(spell_id, target_id, slot, mana_cost, item_slot, resist_adjust); //
|
||||
return true;
|
||||
}
|
||||
|
||||
// ok we know it has a cast time so we can start the timer now
|
||||
spellend_timer.Start(cast_time);
|
||||
|
||||
@@ -1273,6 +1272,17 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
|
||||
EQApplicationPacket *outapp = nullptr;
|
||||
uint16 message_other;
|
||||
bool bard_song_mode = false; //has the bard song gone to auto repeat mode
|
||||
|
||||
if (IsBot()) {
|
||||
CastToBot()->SetCastedSpellType(UINT16_MAX);
|
||||
}
|
||||
|
||||
if (IsBot() && IsValidSpell(spellid)) {
|
||||
if (CastToBot()->CheckSpellRecastTimer(spellid)) {
|
||||
CastToBot()->ClearSpellRecastTimer(spellid);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsValidSpell(spellid)) {
|
||||
if (bardsong) {
|
||||
spellid = bardsong;
|
||||
@@ -2074,7 +2084,17 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
|
||||
}
|
||||
case ST_Pet:
|
||||
{
|
||||
spell_target = GetPet();
|
||||
if (
|
||||
!(
|
||||
IsBot() &&
|
||||
spell_target &&
|
||||
spell_target->GetOwner() != this &&
|
||||
RuleB(Bots, CanCastPetOnlyOnOthersPets)
|
||||
)
|
||||
) {
|
||||
|
||||
spell_target = GetPet();
|
||||
}
|
||||
if(!spell_target)
|
||||
{
|
||||
LogSpells("Spell [{}] canceled: invalid target (no pet)", spell_id);
|
||||
@@ -2821,6 +2841,13 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsBot() && !isproc && !IsFromTriggeredSpell(slot, inventory_slot) && IsValidSpell(spell_id)) {
|
||||
if (spells[spell_id].recast_time > 1000 && !spells[spell_id].is_discipline) {
|
||||
CastToBot()->SetSpellRecastTimer(spell_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Set Recast Timer on item clicks, including augmenets.
|
||||
*/
|
||||
@@ -3412,12 +3439,17 @@ bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id)
|
||||
bool can_cast = true;
|
||||
|
||||
// NON GM clients might be restricted by rule setting
|
||||
if (caster->IsClient()) {
|
||||
if (caster->IsOfClientBot()) {
|
||||
if (IsClient()) { // Only restrict client on client for this rule
|
||||
if (RuleB(Spells, BuffLevelRestrictions)) {
|
||||
check_for_restrictions = true;
|
||||
}
|
||||
}
|
||||
else if (IsBot()) {
|
||||
if (RuleB(Bots, BotBuffLevelRestrictions)) {
|
||||
check_for_restrictions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// NPCS might be restricted by rule setting
|
||||
else if (RuleB(Spells, NPCBuffLevelRestrictions)) {
|
||||
@@ -3564,6 +3596,19 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
);
|
||||
}
|
||||
|
||||
if (caster->IsBot() && RuleB(Bots, BotsUseLiveBlockedMessage) && caster->GetClass() != Class::Bard) {
|
||||
caster->GetOwner()->Message(
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"{}'s {} did not take hold on {}. (Blocked by {}.)",
|
||||
caster->GetCleanName(),
|
||||
spells[spell_id].name,
|
||||
GetName(),
|
||||
spells[curbuf.spellid].name
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
std::function<std::string()> f = [&]() {
|
||||
return fmt::format(
|
||||
"{} {}",
|
||||
@@ -3758,9 +3803,15 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(curbuf.spellid == spellid)
|
||||
return(-1); //do not recast a buff we already have on, we recast fast enough that we dont need to refresh our buffs
|
||||
|
||||
if (IsBot() && (GetClass() == Class::Bard) && curbuf.spellid == spellid && curbuf.ticsremaining == 0 && curbuf.casterid == GetID()) {
|
||||
LogAI("Bard check for song, spell [{}] has [{}] ticks remaining.", spellid, curbuf.ticsremaining);
|
||||
firstfree = i;
|
||||
return firstfree;
|
||||
}
|
||||
else {
|
||||
if (curbuf.spellid == spellid)
|
||||
return(-1); //do not recast a buff we already have on, we recast fast enough that we dont need to refresh our buffs
|
||||
}
|
||||
// there's a buff in this slot
|
||||
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level, nullptr, nullptr, i);
|
||||
if(ret == 1) {
|
||||
@@ -4406,6 +4457,18 @@ bool Mob::SpellOnTarget(
|
||||
} else {
|
||||
MessageString(Chat::SpellFailure, TARGET_RESISTED, spells[spell_id].name);
|
||||
spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name);
|
||||
|
||||
if (IsBot() && RuleB(Bots, ShowResistMessagesToOwner)) {
|
||||
CastToBot()->GetBotOwner()->Message
|
||||
(Chat::SpellFailure,
|
||||
fmt::format(
|
||||
"{} resisted {}'s spell: {}.",
|
||||
spelltar->GetCleanName(),
|
||||
GetCleanName(),
|
||||
spells[spell_id].name
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (spelltar->IsAIControlled()) {
|
||||
@@ -4624,6 +4687,14 @@ bool Mob::SpellOnTarget(
|
||||
|
||||
LogSpells("Cast of [{}] by [{}] on [{}] complete successfully", spell_id, GetName(), spelltar->GetName());
|
||||
|
||||
if (IsBot() && (CastToBot()->GetCastedSpellType() != UINT16_MAX)) {
|
||||
if (!CastToBot()->IsCommandedSpell()) {
|
||||
CastToBot()->SetBotSpellRecastTimer(CastToBot()->GetCastedSpellType(), spelltar);
|
||||
}
|
||||
|
||||
CastToBot()->SetCastedSpellType(UINT16_MAX);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7426,3 +7497,123 @@ bool Mob::CheckWaterLoS(Mob* m)
|
||||
zone->watermap->InLiquid(m->GetPosition())
|
||||
);
|
||||
}
|
||||
|
||||
bool Mob::IsImmuneToBotSpell(uint16 spell_id, Mob* caster)
|
||||
{
|
||||
int effect_index;
|
||||
|
||||
if (caster == nullptr)
|
||||
return(false);
|
||||
|
||||
//TODO: this function loops through the effect list for
|
||||
//this spell like 10 times, this could easily be consolidated
|
||||
//into one loop through with a switch statement.
|
||||
|
||||
LogSpells("Checking to see if we are immune to spell [{}] cast by [{}]", spell_id, caster->GetName());
|
||||
|
||||
if (!IsValidSpell(spell_id))
|
||||
return true;
|
||||
|
||||
if (IsBeneficialSpell(spell_id) && (caster->GetNPCTypeID())) //then skip the rest, stop NPCs aggroing each other with buff spells. 2013-03-05
|
||||
return false;
|
||||
|
||||
if (IsMesmerizeSpell(spell_id))
|
||||
{
|
||||
if (GetSpecialAbility(SpecialAbility::MesmerizeImmunity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check max level for spell
|
||||
effect_index = GetSpellEffectIndex(spell_id, SE_Mez);
|
||||
assert(effect_index >= 0);
|
||||
// NPCs get to ignore the max level
|
||||
if ((GetLevel() > spells[spell_id].max_value[effect_index]) &&
|
||||
(!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// slow and haste spells
|
||||
if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// client vs client fear
|
||||
if (IsEffectInSpell(spell_id, SE_Fear))
|
||||
{
|
||||
effect_index = GetSpellEffectIndex(spell_id, SE_Fear);
|
||||
if (GetSpecialAbility(SpecialAbility::FearImmunity)) {
|
||||
return true;
|
||||
}
|
||||
else if (IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false))
|
||||
{
|
||||
LogSpells("Clients cannot fear eachother!");
|
||||
caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up
|
||||
return true;
|
||||
}
|
||||
else if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (CheckAATimer(aaTimerWarcry))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsCharmSpell(spell_id))
|
||||
{
|
||||
if (GetSpecialAbility(SpecialAbility::CharmImmunity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this == caster)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//let npcs cast whatever charm on anyone
|
||||
if (!caster->IsNPC())
|
||||
{
|
||||
// check level limit of charm spell
|
||||
effect_index = GetSpellEffectIndex(spell_id, SE_Charm);
|
||||
assert(effect_index >= 0);
|
||||
if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
IsEffectInSpell(spell_id, SE_Root) ||
|
||||
IsEffectInSpell(spell_id, SE_MovementSpeed)
|
||||
)
|
||||
{
|
||||
if (GetSpecialAbility(SpecialAbility::SnareImmunity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLifetapSpell(spell_id))
|
||||
{
|
||||
if (this == caster)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSacrificeSpell(spell_id))
|
||||
{
|
||||
if (this == caster)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user