LUACN论坛

 找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
热搜: YJWOW MagicStone BoL
楼主: 艺海小田

处理角色转身的逻辑

[复制链接]
 楼主| 发表于 2025-10-7 09:57:00 | 显示全部楼层
lbabey 发表于 2025-10-6 12:42 AM
1.你的代码里,哪部分判断了 面对目标?
2.用AI随便改了下,和子龙的除了延长了个时间,有什么区别呢?
...

if TurnR == nil 与 if not _G.TurnR 的区别分析这两个条件判断在Lua中看似功能相似,但实际上存在一些重要差异。下面我将详细分析它们的区别:
1. 判断方式差异
  • if TurnR == nil:这是直接比较变量TurnR是否等于nil值。这种比较方式严格检查变量是否为nil


  • if not _G.TurnR:这是使用逻辑非运算符not来判断_G.TurnR的真假值。在Lua中,not会将任何非false和非nil的值转换为false,将false和nil转换为true




2. 作用域差异
  • TurnR == nil检查的是当前作用域中的局部变量TurnR。如果TurnR未在当前作用域定义,Lua会尝试在更高层级的作用域查找,最终可能访问全局变量TurnR。
  • _G.TurnR明确指定访问全局变量表中的TurnR项。_G是Lua的全局环境表,所有全局变量都存储在其中



3. 真值处理差异
  • == nil只对nil值返回true,其他所有值(包括false、0、空字符串等)都会返回false。

  • not _G.TurnR会对nil和false都返回true,而对其他所有值(包括0、空字符串等)返回false。
  • 在Lua中,只有nil和false被视为假值,其他所有值都被视为真值。

4. 代码示例中的实际区别在提供的代码示例中,两个版本的实现有以下关键区别:
  • 子龙版本使用TurnR == nil检查,可能检查局部或全局变量
  • 我这个版本明确使用_G.TurnR访问全局变量,并通过not进行判断
  • 我这个版本添加了函数存在性检查(BeeGetVariable and BeeGetVariable("tm"))
  • 我这个版本调整了时间阈值从0.1秒到0.5秒,当然子龙的版本我也测试过,时间阈值从0.1秒到0.5秒再到1秒,但子龙版本一直原地转圈,停止运行bee依旧一直转圈。
  • 我这个版本明确将创建的Frame赋值给_G.TurnR
5.不管黑猫白猫,能解决问题就是好猫。当然并不是说子龙大佬不好,子龙的确是大佬,这个咱得承认。我个人感觉咱们这个论坛既然是交流,就应该实诚一点,没必要藏藏掖掖的,大家都贡献点智慧,咱们的代码才能更完善,交流才会有真正的价值。其实有看过关于伸手费调整那个论坛文章,大佬们长远考虑是对的,因为有人拿咱们的代码商业化。这个说实话,咱们基础小白纯粹为了学习,还真没那个防范能力,个人感觉,诚心交流,大家共同提高,自私点说,咱个人能提高了,权当交个智商税吧

点评

这个转身的具体逻辑如果 TurnR[/backcolor] 这个变量为空, 则 执行事件的处理部分 注册("UI_ERROR_MESSAGE")[/backcolor] 事件,当这个事件 是"你必须面对目标。"[/backcolor] 时 BeeGetVariable("tm")[/back  详情 回复 发表于 2025-10-7 03:06 PM
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-7 10:13:55 | 显示全部楼层
lbabey 发表于 2025-10-5 08:01 PM
1.我给你取消回复仅作者可见了
2.其实用C_Timer的函数更容易解决这个问题,而且对新手更容易看明白

版主, C_Timer 这个函数咋整?请指导下咋调用这个函数?
下面这个是我查到的信息

[color=rgba(0, 0, 0, 0.86)][backcolor=rgba(255, 255, 255, 0.9)]在魔兽世界插件开发中,C_Timer.After(delay, callback) 是一个内置的计时器API,用于在指定的延迟时间后执行回调函数。它的作用类似于其他编程语言中的 setTimeout,但专为魔兽世界的Lua环境优化。

C_Timer.After(delay, callback) 详解
  • [color=rgba(0, 0, 0, 0.86)]功能

    • 在 delay 秒后执行 callback 函数。
    • 适用于一次性延时任务,如技能冷却监控、动作控制(如转身逻辑)。
    • 非阻塞,不会影响游戏主线程的运行。
  • [color=rgba(0, 0, 0, 0.86)]参数

    • delay:延迟时间(秒,支持小数,如 0.1)。
    • callback:回调函数,在延迟结束后执行。
  • [color=rgba(0, 0, 0, 0.86)]特点

    • 轻量级:基于游戏内部的事件队列,比手动 GetTime() + 循环检查更高效。
    • 主线程安全:回调函数在主线程执行,确保与游戏UI兼容。
    • 一次性:仅触发一次回调,适合单次延时任务(如需循环计时,可使用 C_Timer.NewTicker)。



回复 支持 反对

使用道具 举报

发表于 2025-10-7 15:06:24 | 显示全部楼层
本帖最后由 lbabey 于 2025-10-7 03:14 PM 编辑
艺海小田 发表于 2025-10-7 09:57 AM
if TurnR == nil 与 if not _G.TurnR 的区别分析这两个条件判断在Lua中看似功能相似,但实际上存在一些重 ...

这个转身的具体逻辑
如果 TurnR 这个变量为空, 则 执行事件的处理部分
  注册("UI_ERROR_MESSAGE") 事件,发生时则调用Turn这个局部函数
  当这个事件 是"你必须面对目标。"
  BeeGetVariable("tm") 获取这个变量值为0时 ,开始执行转身并设置 变量("tm")为当前时间
  这部分都是赋值给 TurnR 这个全局变量
否则 BeeGetVariable("tm") 获取变量("tm")的值
  如果 这个值 大于0 ,则 比较当前时间 和 这个值记录的时间差值,大于0.1
  执行停止转身
所以需要一直运行。

而我的修改则,直接将停止转身,也放到事件处理部分
  具体是利用CTime函数,开始转身后0.1秒后就停止转身
所以不需要一直运行。


再一个,不要直接将AI的回复,复制过来了。看看教程


回复 支持 反对

使用道具 举报

发表于 2025-10-7 15:26:31 | 显示全部楼层
艺海小田 发表于 2025-10-7 09:35 AM
这个s == "你必须面对目标。" 是核心判断条件,直接检测游戏系统发送的错误消息内容,就是采用的数学逻辑 ...

他停止是转身大于设置的时间,0.1还是1 也好,则停止。
并不是面对了目标就停止
逻辑是如果错误则转身一定时间,如果还有错误则继续转身一定时间,直到不出现错误
也就是说
面对目标则不执行转身一定时间,并不是面对就停止
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-8 23:53:05 | 显示全部楼层
lbabey 发表于 2025-10-7 03:06 PM
这个转身的具体逻辑
如果 TurnR 这个变量为空, 则 执行事件的处理部分
  注册("UI_ERROR_ ...

C_Timer 这个函数我拿到源码了,还是不知道行,不知道还缺啥
回复 支持 反对

使用道具 举报

发表于 2025-10-9 10:04:14 | 显示全部楼层
艺海小田 发表于 2025-10-8 11:53 PM
C_Timer 这个函数我拿到源码了,还是不知道行,不知道还缺啥

C_Timer 函数源码能发一下吗,我似乎是有,但一直运行有问题,怀疑我就没搞对
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-9 11:26:26 | 显示全部楼层
xiaoyao1 发表于 2025-10-9 10:04 AM
C_Timer 函数源码能发一下吗,我似乎是有,但一直运行有问题,怀疑我就没搞对

好的,我直接推荐给你地址,或者你看看咋给你。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-9 11:30:45 | 显示全部楼层
xiaoyao1 发表于 2025-10-9 10:04 AM
C_Timer 函数源码能发一下吗,我似乎是有,但一直运行有问题,怀疑我就没搞对

C_Timer.After 简单研究
https://www.luacn.net/thread-31462-1-1.html
(出处: LUACN论坛)
咱们版主弄的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-9 11:46:22 | 显示全部楼层
xiaoyao1 发表于 2025-10-9 10:04 AM
C_Timer 函数源码能发一下吗,我似乎是有,但一直运行有问题,怀疑我就没搞对

C_Timer介绍
https://www.luacn.net/thread-32285-1-1.html
(出处: LUACN论坛)
子龙大佬的
回复 支持 反对

使用道具 举报

发表于 2025-10-9 17:38:16 | 显示全部楼层
艺海小田 发表于 2025-10-8 11:53 PM
C_Timer 这个函数我拿到源码了,还是不知道行,不知道还缺啥

[Lua] 纯文本查看 复制代码
-------------------------------------------------------
if not C_Timer or C_Timer._version ~= 2 then
    local tinsert = table.insert;
    local tremove = table.remove;
     
    C_Timer = C_Timer or {};
    C_Timer._version = 2;
     
    local TickerPrototype = {};
    local TickerMetatable = {
        __index = TickerPrototype,
        __metatable = true
    };
     
    local waitTable = {};
    local waitFrame = TimerFrame or CreateFrame("Frame", "TimerFrame", UIParent);
    waitFrame:SetScript("OnUpdate", function(self, elapsed)
            local total = #waitTable;
            local i = 1;
             
            while i <= total do
                local ticker = waitTable[i];
                 
                if ticker._cancelled then
                    tremove(waitTable, i);
                    total = total - 1;
                elseif ticker._delay > elapsed then
                    ticker._delay = ticker._delay - elapsed;
                    i = i + 1;
                else
                    ticker._callback(ticker);
                     
                    if ticker._remainingIterations == -1 then
                        ticker._delay = ticker._duration;
                        i = i + 1;
                    elseif ticker._remainingIterations > 1 then
                        ticker._remainingIterations = ticker._remainingIterations - 1;
                        ticker._delay = ticker._duration;
                        i = i + 1;
                    elseif ticker._remainingIterations == 1 then
                        tremove(waitTable, i);
                        total = total - 1;
                    end
                end
            end
             
            if #waitTable == 0 then
                self:Hide();
            end
    end)
     
    local function AddDelayedCall(ticker, oldTicker)
        if oldTicker and type(oldTicker) == "table" then
            ticker = oldTicker;
        end
         
        tinsert(waitTable, ticker);
        waitFrame:Show();
    end
     
    _G.AddDelayedCall = AddDelayedCall;
     
    local function CreateTicker(duration, callback, iterations)
        local ticker = setmetatable({}, TickerMetatable);
        ticker._remainingIterations = iterations or -1;
        ticker._duration = duration;
        ticker._delay = duration;
        ticker._callback = callback;
         
        AddDelayedCall(ticker);
         
        return ticker;
    end
     
    function C_Timer.After(duration, callback)
        AddDelayedCall({
                _remainingIterations = 1,
                _delay = duration,
                _callback = callback
        });
    end
     
    function C_Timer.NewTimer(duration, callback)
        return CreateTicker(duration, callback, 1);
    end
     
    function C_Timer.NewTicker(duration, callback, iterations)
        return CreateTicker(duration, callback, iterations);
    end
     
    function TickerPrototype:Cancel()
        self._cancelled = true;
    end
end
 
local function A()
    print("第一个函数")
    C_Timer.After(2, function()
            print("第二个函数")
            C_Timer.After(2, function()
                    print("第三个函数")
            end)
    end)
end
A()

这个问题以前就问过了,在魔蜂中运行,A()运行后就只打印一行。是啥问题?是因为C_Timer函数必须放到魔蜂函数文件中吗,还是因为运行的魔兽版本的问题?

点评

哎,不想回复, 每次调用 表 不就清空了吗,他为什么会运行,不运行就对了  详情 回复 发表于 2025-10-9 07:06 PM
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

小黑屋|手机版|Archiver|LUACN论坛

GMT+8, 2026-5-31 04:13 AM , Processed in 0.035376 second(s), 33 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表