|
|
发表于 2024-3-5 12:25:13
|
显示全部楼层
-- 脚本说明:
-- 该脚本是一个智能的PVE输出脚本,智能判断状态,智能释放技能。
--
-- 功能:
-- 1,只对怪物有效,对玩家无效,不影响pk等战斗时手动释放技能;
-- 2. 只有进战斗了才执行攻击脚本,在没进战斗的情况下不会主动攻击;
-- 3,在坐骑上且处于移动中时不攻击(不影响在战斗中跑图);
-- 4. 在战中如果想要手动施法,需要提前定义好技能宏或将目标切换成自己或者某个玩家,否则将由脚本自动释放技能,导致无法手动释放技能;
-- 5. 在战斗中,如果当前目标无效(没有目标、目标死亡等)会自动尝试切换最近可攻击目标;
-- 6. 自动开保命技能,智能切换姿态,自动打断目标施法,自动解控;
-- 7. 每次脱战自动范围拾取(需配置范围拾取道具);
-- 8. 室外非战斗状态时角色移动自动上坐骑(需配置坐骑,如不需要该功能不配置坐骑即可);
-- 9. 按住Shift键嘲讽目标,按住Ctrl键释放震荡波(生命低于85%时会自动释放)
--
-- 天赋要求:
-- 防御:必须点出毁灭打击,最好点出震荡波
-- 狂暴:必须点出嗜血,最好点出泰坦之握
-- 武器:无要求
--
-- 作者:吾奶常扇赵子龙
-- 脚本基础配置:
-- 1,解控配置(如果不需要解控,下面的信息配置为空即可)
-- 要自动解控的buf
local controlled_buff = "恐惧,心灵尖啸,恐惧嚎叫,闷棍,瘫痪,破胆怒吼,恐惧术,蛛网喷射,破胆咆哮,利斧乱舞,织网"
-- 用于解控的饰品名称,多个用逗号隔开,没有则不填
local release_control_accessories = ""
-- 用于解控的战袍名称,多个用逗号隔开,没有则不填
local release_control_war_robe = "魔神·『战袍20级』"
-- 用于解控的技能名称,多个用逗号隔开,没有则不填
local release_control_spell = "狂暴之怒"
-- 2. 自动范围拾取道具,配置后每次脱战会自动使用配置的道具
local auto_loot_tool_name = "范围拾取"
-- 3. 在室外非战斗中移动时自动上坐骑(需要瞬发坐骑)
local auto_mount_name = "迅捷幽灵虎(水陆两用)"
-- 4. 战士输出姿态(不支持武器战,没啥输出优势)
-- 0:智能切换姿态,优先使用狂暴姿态输出,血量低到一定程度后自动切换到防御姿态保命,血量回升到一定程度后将再次切换到狂暴姿态
-- 要求:防御必须点出毁灭打击,狂暴必须点出嗜血
-- 1:只使用防御姿态(适用于早期天赋点不够的时候)
-- 要求:必须点出毁灭打击
-- 2:只使用狂暴姿态
-- 要求:必须点出嗜血
local stance_mode = 0
-- 其他配置
-- 1,哪个职业的输出脚本(可以不配置)
-- 当前脚本适用的职业,如:法师、牧师、术士、潜行者、德鲁伊、猎人、萨满、战士、圣骑士、死亡骑士等
local player_class = "战士"
-- 近战职业
local close_combat_characters = "潜行者,德鲁伊,战士,圣骑士,死亡骑士"
-- 2,攻击模式
-- true:每次手动进入战斗后才启用攻击脚本,
-- false:全程启用攻击脚本(只要遇见能攻击的目标就打)
local attack_in_combat = true
-- 3,攻击目标
-- true:只攻击boss
-- false:攻击小怪和boss
local only_attack_boss = false
-- 当只攻击boss时,还想额外攻击的目标,多个目标用逗号分隔
local attack_units = "痛苦女王,蛛魔掘地者,虫群甲虫"
-- ####################################脚本开始###########################################
local Lib = {};
-- 判断指定单位是否是boss,默认判断目标
function Lib.BeeUnitIsBoss(unit)
--"normal" - 普通
--"rare" - 稀有
--"elite" - 精英
--"rareelite" - 稀有精英
--"worldboss" - 首领
return UnitClassification(BeeUnit(unit, "target")) == "worldboss";
end
--获得当前天赋名称(这个函数对于某些sf版本的游戏可能有细微差别,如果判断错误,需要针对指定游戏做下调整)
function Lib.BeeTalentNameEx()
local s;
local m = 0;
-- 获取所有的天府页,然后遍历每页天赋,加点最多的页就是当前天赋
for i = 1, GetNumTalentTabs() do
-- p为当前页天赋加点的点数
local _, _, p = GetTalentTabInfo(i);
if p > m then
m = p;
s = i;
end
end
-- 获取并返回加点最多的那页天赋信息
local n = GetTalentTabInfo(s);
return n
end
local InventorySlotNames = {
[0] = "AMMOSLOT", --弹药
[1] = "HEADSLOT", --头部
[2] = "NECKSLOT", --颈部
[3] = "SHOULDERSLOT", --肩膀
[4] = "SHIRTSLOT", --衬衫
[5] = "CHESTSLOT", --胸部
[6] = "WAISTSLOT", --腰部
[7] = "LEGSSLOT", --腿部
[8] = "FEETSLOT", --脚部
[9] = "WRISTSLOT", --手腕
[10] = "HANDSSLOT", --手
[11] = "FINGER0SLOT", --戒子
[12] = "FINGER1SLOT", --戒子
[13] = "TRINKET0SLOT", --饰品
[14] = "TRINKET1SLOT", --饰品
[15] = "BACKSLOT", --背部
[16] = "MAINHANDSLOT", --主手武器
[17] = "SECONDARYHANDSLOT", --副手武器
[18] = "RANGEDSLOT", --远程武器
[19] = "TABARDSLOT" --战袍
}
-- 获取指定位置的装备名称,
-- index:装备位置,范围:0-19(具体值见上面的InventorySlotNames),
-- unit:要获取的对象,默认为玩家自己
function Lib.GetInventorySlotName(index, unit)
--local slotName = InventorySlotNames[index]
--if not slotName then
-- return nil;
--end
--
-- GetInventorySlotInfo(slotName)
local mainHandLink = GetInventoryItemLink(unit or "player", index)
local name = select(1, GetItemInfo(mainHandLink));
return name;
end
-- 尝试释放技能,成功返回true,失败返回false
-- spell:技能名称
-- gcd:是否需要检查公共CD(默认需要),如果需要检查,那么在公共CD没有结束前将不释放技能(将返回false),某些不受公共CD影响的技能就不需要检查
-- delay:该技能下一次是否需要延迟释放,某些技能为避免重复施法,要在施法成功后加一个延迟时间,意思是下一次需要达到延迟时间后才能继续释放,
-- 比如:Lib.BeeRunSpell("献祭",0,12,"target"),其意思为:"献祭"施放成功后,延时12秒后才能再对目标再次施放"献祭"技能,对其它技能无影响。
-- delayTarget:延迟对象,默认为目标
function Lib.BeeRunSpell(spell, gcd, delay, delayTarget)
if not spell then
return false;
end
gcd = Lib.IF(type(gcd) == "number", gcd, 1)
if BeeSpellCoolDown(spell) <= 0 and (gcd == 0 or BeeGCD() <= 0) then
local success = BeeRun("/cast " .. spell);
if success and type(delay) == "number" then
BeeUnitCastSpellDelay(spell, delay, delayTarget);
end
return success;
end
return false;
end
function Lib.IF(a, b, c)
if (a) then
return b;
else
return c;
end
end
-- 判断当前是否是指定的形态
function Lib.BeeGetShapeshiftFormInfoX(index)
-- index:
-- 战士:1战斗、2防御、3狂暴
-- 德鲁伊:1熊、2海豹、3猫、4旅行、5树、6枭兽
return BeeGetShapeshiftFormInfo(index) == 1;
end
-- ============================ 攻击逻辑 ============================================
-- 开始攻击函数定义
-- 该函数里主要处理一些和职业无关的逻辑
function Lib.Attack()
-- 有动态插入的技能时不执行脚本
-- 在脚本执行期间,无法插入直接释放的技能,需要将要释放的技能提前定义成特殊宏的形式:如:/run BeeSpellFast("/CAST 闪现术","Macro")
-- 然后在脚本执行过程中,如果需要使用动态技能,直接按定义好的宏即可
if BeeCastSpellFast() then
return;
end
-- 职业检查(可选),如果当前职业和配置的职业不一致,不执行攻击脚本
if player_class ~= "" and BeeUnitClassBase("player") ~= player_class then
return;
end
-- 人物死亡或灵魂状态不执行攻击脚本
if UnitIsDeadOrGhost("player") then
return;
end
-- 从神秘的庇难所副本出来后自动重置副本(用于快速刷该副本)
if IsInInstance() == 1 then
BeeSetVariable("player_is_in_instance", 1);
BeeSetVariable("player_in_instance_name", GetRealZoneText());
else
if BeeGetVariable("player_in_instance_name") == "神秘的庇难所" then
BeeRun("/run ResetInstances()");
end
BeeSetVariable("player_is_in_instance", 0);
BeeSetVariable("player_in_instance_name", "");
end
-- 在坐骑上且处于移动中不执行攻击脚本(防止跑图时因为进战斗进行自动攻击导致下马)
if IsMounted() == 1 and GetUnitSpeed("player") > 5 then
return;
end
-- 没进入战斗时不执行攻击脚本
if attack_in_combat and not BeeUnitAffectingCombat() then
-- 如果刚脱战,且配置了范围拾取,则进行一次范围拾取
if BeeGetVariable("zs_combat_is_in_combat") == 1 and auto_loot_tool_name ~= "" then
BeeRun("/use " .. auto_loot_tool_name);
end
BeeSetVariable("zs_combat_is_in_combat", 0);
-- 非战斗状态且人物移动,则尝试自动上坐骑
if auto_mount_name ~= "" and IsMounted() ~= 1 and GetUnitSpeed("player") > 0 and IsOutdoors() then
BeeRun("/use " .. auto_mount_name);
end
return;
end
-- 标记当前处于战斗中,以便处理脱战后的一些逻辑(比如脱战后的范围拾取)
BeeSetVariable("zs_combat_is_in_combat", 1);
-- 目标是自己或玩家时不执行攻击脚本
if BeeUnitTargetIsPlayer("player") or BeeUnitPlayerControlled("target") == 1 then
return;
end
-- 如果当前是近战职业且目标太远,则清除目标,后面将重新选择最近目标
if UnitName("target") and BeeUnitCanAttack("target") == 1 and not BeeUnitIsDead("target") and BeeRange("target") > 8 then
if player_class ~= "" and BeeStringFind(player_class, close_combat_characters) then
local lastClearTargetTime = BeeGetVariable("zs_last_clear_target_time");
local cTime = GetTime();
-- 每0.5秒清一次目标,不能清得太频繁
if lastClearTargetTime == nil or cTime - lastClearTargetTime > 0.5 then
BeeSetVariable("zs_last_clear_target_time", cTime);
BeeRun("/cleartarget");
end
end
end
-- 当目标不可攻击(没有目标或目标无效)时尝试切换最近可攻击的目标
if not UnitName("target") or BeeUnitCanAttack("target") ~= 1 or BeeUnitIsDead("target") then
-- 尝试攻击最近目标
BeeRun("/targetenemy [noharm][dead]");
--BeeAttack(0, 0);
-- 切换目标后还是不能攻击,则不执行攻击脚本
if not UnitName("target") or BeeUnitCanAttack("target") ~= 1 or BeeUnitIsDead("target") then
return;
end
end
-- 目标不是首领(如果配置了只攻击boss的话)不执行攻击脚本
if only_attack_boss and not Lib.BeeUnitIsBoss("target") and (attack_units == "" or not BeeStringFind(UnitName("target"), attack_units)) then
return;
end
-- 如果没有开始自动攻击则开始自动攻击
if not BeeIsCombat() then
BeeAttack(0, 0);
end
-- 解除被控状态
if controlled_buff ~= "" then
-- 检查是否有需要解控的debuff
local buff = BeeUnitBuffList("player");
if BeeStringFind(controlled_buff, buff) then
-- 尝试技能解控(如果配置了)
if release_control_spell ~= "" then
-- 以逗号分隔成多个法术名称
for spell in string.gmatch(release_control_spell, "([^,]+)") do
-- 去掉两侧的空格
spell = string.gsub(spell, "^[%s]*([^%s].*[^%s])[%s]*$", "%1")
if Lib.BeeRunSpell(spell) then
return;
end
end
end
-- 尝试饰品解控(如果配置了)
if release_control_accessories ~= "" then
local name = Lib.GetInventorySlotName(13);
if BeeStringFind(name, release_control_accessories) and GetItemCooldown(name) == 0 then
BeeRun("/use 13");
return;
end
local name = Lib.GetInventorySlotName(14);
if BeeStringFind(name, release_control_accessories) and GetItemCooldown(name) == 0 then
BeeRun("/use 14");
return;
end
end
-- 尝试战袍解控(如果配置了)
if release_control_war_robe ~= "" then
local name = Lib.GetInventorySlotName(19);
if BeeStringFind(name, release_control_war_robe) and GetItemCooldown(name) == 0 then
BeeRun("/use 19");
return;
end
end
end
end
-- 如果是近战,且和目标距离大于15码时不执行攻击脚本
--if player_class ~= "" and BeeStringFind(player_class, close_combat_characters) and BeeRange("target") > 15 then
-- return;
--end
-- 开始执行战士的输出逻辑
Lib.zsAttack();
end
-- 战士具体输出逻辑
-- 天赋如果只加了防御(新人阶段天赋点不够,此时优先加防御天赋),需要将always_tank配置设置为true,这样只使用防御姿态进行输出;
-- 中后期加了狂暴天赋后(至少出了嗜血),可以将always_tank关了(设置为false),这样输出的时候将优先使用狂暴天赋,以便保证最大化输出,当血量低到一定程度后会自动切换到防御姿态
function Lib.zsAttack()
-- 当前血量(百分比)
local health = BeeUnitHealth("player", "%", 0);
-- 当前怒气值
local mana = BeeUnitMana("player", "%");
-- 是否时狂暴姿态
local isBerserk = Lib.BeeGetShapeshiftFormInfoX(3);
-- 是否时防御姿态
local isTank = Lib.BeeGetShapeshiftFormInfoX(2);
-- 目标是否是boss
local isBoss = Lib.BeeUnitIsBoss("target");
-- 是否使用斩杀,该服前期没有升级斩杀技能的时候不建议开启,伤害很低
local useZhanSha = true;
if stance_mode == 1 then
-- 只使用防御姿态
if not isTank then
Lib.BeeRunSpell("防御姿态", 1);
return;
end
elseif stance_mode == 2 then
-- 只使用狂暴姿态
if not isBerserk then
Lib.BeeRunSpell("狂暴姿态", 1);
return;
end
else -- 智能切换姿态
-- 生命底于65%时切换到防御姿态
if health < 65 then
if not isTank then
Lib.BeeRunSpell("防御姿态", 1);
return;
end
else
-- 生命大于65%时,如果不是防御之态也不是狂暴姿态(无姿态或时战斗姿态),则切换到狂暴姿态
if not isTank and not isBerserk then
Lib.BeeRunSpell("狂暴姿态", 1);
return;
end
-- 生命大于65%且当前是防御姿态时,则血量大于80%时再切回狂暴之态(防止频繁切换姿态)
if isTank and health >= 80 then
Lib.BeeRunSpell("狂暴姿态", 1);
return;
end
end
end
-- 没有怒气时使用血型狂暴
if mana <= 0 and BeeSpellCoolDown("血性狂暴") then
Lib.BeeRunSpell("血性狂暴");
end
-- 战斗怒吼(效果不大,不开启)
--if BeePlayerBuffTime("战斗怒吼") <= 0 then
-- Lib.BeeRunSpell("战斗怒吼", 1);
-- return;
--end
-- 挫志怒吼(效果不大,不开启)
--if BeeTargetDeBuffTime("挫志怒吼") <= 0 then
-- Lib.BeeRunSpell("挫志怒吼", 1);
-- return;
--end
-- 生命小于60%、角色种族是牛头人时,释放战争践踏
if health <= 60 and BeeUnitRace("player") == "牛头人" and BeeSpellCoolDown("战争践踏") then
Lib.BeeRunSpell("战争践踏");
end
-- 生命小于50%使用狂怒回复(有激怒buf才能释放)
if health <= 50 and mana >= 15 and BeePlayerBuffTime("激怒") > 0 and BeeIsRun("狂怒回复") and Lib.BeeRunSpell("狂怒回复") then
return;
end
-- 生命小于40%使用盾墙
if health <= 40 and isTank and BeeSpellCoolDown("盾墙") <= 0 then
Lib.BeeRunSpell("盾墙");
end
-- 生命小于30%使用破釜沉舟
if health <= 30 and BeeIsRun("破釜沉舟") and BeeSpellCoolDown("破釜沉舟") <= 0 then
Lib.BeeRunSpell("破釜沉舟");
end
-- 生命值小于20%尝试开饰品(古神的绝望之魂)的减伤护盾
if health <= 20 then
-- 在两个饰品位置查找其名字是不是古神的绝望之魂,是就使用该饰品
local idx = 13;
local name = Lib.GetInventorySlotName(idx);
if not Lib.isJueWangZhiHun(name) then
idx = 14
name = Lib.GetInventorySlotName(idx);
end
if Lib.isJueWangZhiHun(name) and GetItemCooldown(name) == 0 then
BeeRun("/use " .. idx);
end
end
-- 生命值小于15%尝试开破胆怒吼(最后再尝试挽救下)
if health <= 15 and BeeSpellCoolDown("破胆怒吼") then
Lib.BeeRunSpell("破胆怒吼");
end
-- 按住Shift键嘲讽目标
if IsShiftKeyDown() then
if Lib.BeeGetShapeshiftFormInfoX(2) and BeeSpellCoolDown("嘲讽") then
Lib.BeeRunSpell("嘲讽");
return;
end
if mana >= 2 and BeeSpellCoolDown("挑战怒吼") then
Lib.BeeRunSpell("挑战怒吼");
return;
end
end
-- 判断和目标的距离,过远时不输出
if isBerserk then
if IsSpellInRange("嗜血", "target") ~= 1 then
return;
end
elseif isTank then
if IsSpellInRange("毁灭打击", "target") ~= 1 then
return;
end
end
-- 如果目标正在释放可打断技能时打断目标施法
if BeeUnitCastSpellName("target", 1) then
if isBerserk then
if mana >= 7 and BeeSpellCoolDown("拳击") <= 0 then
Lib.BeeRunSpell("拳击");
end
else
if mana >= 7 and BeeSpellCoolDown("盾击") <= 0 then
Lib.BeeRunSpell("盾击");
end
end
end
-- 打boss开爆发技能
if isBoss and mana >= 10 and BeeIsRun("死亡之愿") and BeeSpellCoolDown("死亡之愿") <= 0 then
Lib.BeeRunSpell("死亡之愿");
end
--if isBoss and isBerserk and BeeSpellCoolDown("鲁莽") <= 0 then
-- Lib.BeeRunSpell("鲁莽");
-- return;
--end
-- 释放横扫攻击
if mana >= 30 and isBerserk and BeeIsRun("横扫攻击") and BeePlayerBuffTime("横扫攻击") <= 0 and BeeSpellCoolDown("横扫攻击") <= 0 then
Lib.BeeRunSpell("横扫攻击");
end
-- 释放震荡波(生命低于85%或按住Ctrl键时释放)IsAltKeyDown()
if mana >= 12 and (IsControlKeyDown() or health <= 85) and BeeIsRun("震荡波") and Lib.BeeRunSpell("震荡波") then
return;
end
-- 释放震荡猛击
if mana >= 12 and isBoss and BeeIsRun("震荡猛击") and Lib.BeeRunSpell("震荡猛击") then
return;
end
-- 释放乘胜追击
if isBerserk and BeeIsRun("乘胜追击") and Lib.BeeRunSpell("乘胜追击") then
return;
end
-- 释放嗜血,如果怒气值够,则先放一个顺劈斩
if mana >= 17 and BeeIsRun("嗜血") and BeeSpellCoolDown("嗜血") <= 0 then
if mana >= 34 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("嗜血") then
return;
end
end
if isBerserk then -- 狂暴姿态
-- 释放旋风斩,如果怒气值够,则先放一个顺劈斩
if mana >= 22 and BeeSpellCoolDown("旋风斩") <= 0 then
if mana >= 39 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("旋风斩") then
return;
end
end
-- 释放斩杀,如果怒气值够,则先放一个顺劈斩
if useZhanSha and mana >= 10 and BeeIsRun("斩杀") then
if mana >= 30 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("斩杀") then
return;
end
end
else -- 防御姿态
-- 释放盾牌格挡
if BeeSpellCoolDown("盾牌格挡") then
Lib.BeeRunSpell("盾牌格挡");
end
-- 释放复仇,如果怒气值够,则先放一个顺劈斩
if mana >= 2 and BeeIsRun("复仇") then
if mana >= 19 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("复仇") then
return;
end
end
-- 释放盾牌猛击,如果怒气值够,则先放一个顺劈斩
if mana >= 17 and BeeIsRun("盾牌猛击") then
if mana >= 34 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("盾牌猛击") then
return;
end
end
-- 释放雷霆一击,如果怒气值够,则先放一个顺劈斩
if mana >= 17 and BeeSpellCoolDown("雷霆一击") then
if mana >= 34 then
Lib.BeeRunSpell("顺劈斩");
end
if Lib.BeeRunSpell("雷霆一击") then
return;
end
end
end
-- 释放毁灭打击,如果怒气值够,则先放一个顺劈斩
if mana >= 20 then
Lib.BeeRunSpell("顺劈斩");
end
if mana >= 9 and BeeIsRun("毁灭打击") then
Lib.BeeRunSpell("毁灭打击");
end
end
-- 判断name是否是"古神的绝望之魂"
-- 这个名字字符串中还包含许多其他字符,所以没有办法直接判断
function Lib.isJueWangZhiHun(name)
if not string.find(name, "绝") then
return false;
end
if not string.find(name, "望") then
return false;
end
if not string.find(name, "之") then
return false;
end
if not string.find(name, "魂") then
return false;
end
return true;
end
-- 调用攻击函数,开始攻击
Lib.Attack();
|
|