TC官方合作论坛

 找回密码
 立即注册
查看: 3352|回复: 24

[讨论] 讨论一下TC多线程使用大漠或天使插件问题[已反馈问题结果]

[复制链接]
发表于 2013-12-5 23:59:54 | 显示全部楼层 |阅读模式

马上加入TC

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 perock 于 2013-12-10 15:48 编辑

小弟目前使用大漠+TC开发一游戏挂机,现有一点问题百思不得其解,外挂中使用三个线程:
线程1,负责监视血值变化,血值突然减少就立即使用随机,这个线程中主要是做ocr文字,然后判断血值,如果为真才会去按键,这个线程必须有。
线程2,用于监视地点和做一些挂机前的初始工作,比如修理装备,买材料等。这线程也是循环做判断,特定条件才会按键,也是必须的。
线程3,打怪与捡物品,这线程中就有频繁操作按键与鼠标,这个线程也是必须。

以上三线程中都使用大漠后台鼠标与键盘、找字、找图等功能。并且三个线程中使用一个大漠实例对象。
问题出来了,三个线程启动后,线程3打怪偶尔会停止运行(代码不执行了,没任何debug输出,不知何原因),这也只是偶尔出现,无固定时间,有时运行10分钟就停了,有时20分钟停了。
因目前tc并不能查询线程状态,所以只是推测线程是不是崩溃了。

看过大漠chm中讲过,多线程中键鼠可能冲突,所以我尽可能的减少了不同线程的键鼠操作,当心键鼠冲突引起线程停止。
我用了许多方法去测试了,包括怀疑是不是多线程键鼠操作冲突,插件bug,tc线程bug等,所以我尽量避免多线程操作鼠标键盘。
其实,以上三线程同时操作键鼠的机率不大,比如线程1不可能频繁去按键,因为被人杀也少遇到,所以线程1只会频繁去做ocr
线程2中与线程3也不会键鼠冲突,因为线程2只会在回城后执行一系列键鼠操作,而线程3中判断了当前地点是不是打怪地点,如果否就不会执行键鼠操作,如此,也不会出现键鼠冲突问题。

其次,怀疑大漠插件内部问题,造成tc线程崩溃而停止。这个没法测试,只能看看论坛朋友们有无遇到过。
最后,tc线程bug这个问题,估计不成立,因为tc仅仅调了winapi启动线程而已。


以前所述均在无逻辑问题前提下讨论的,比如线程未同步去修改某些数据啊,死循环啊,线程被其它线程暂停啊,都没有这样问题。

回复

使用道具 举报

 楼主| 发表于 2013-12-6 00:01:36 | 显示全部楼层
  1. function 打怪与寻路()
  2.     bossIsDaed = true
  3.     hadKillBoss = false
  4.     x,y
  5.     while(true)
  6.         
  7.         if(新武尊辅助.获取当前地点() != "玛雅一层")
  8.             return 0
  9.         endif
  10.         
  11.         debug.print("开始换地方")               
  12.         新武尊辅助.停止挂机()
  13.         新武尊辅助.更换地点()
  14.         
  15. 打开辅助:  
  16.         //查找辅助窗口是否打开? 没有则打开
  17.         if(dm.FindStr(0,0,w,h,"挂机","43.89.98-0.0.0",1.0,x,y) == -1)
  18.             dm.MoveTo(辅助x+10,辅助y+10)
  19.             if(辅助x <= 0 && 辅助y <= 0)
  20.                 debug.print("辅助坐标有错")
  21.             endif
  22.             help.sleep(200)
  23.             dm.LeftClick()
  24.             help.sleep(200)
  25.         endif
  26.         
  27.         加载附近怪x,加载附近怪y
  28.         //如果没找到,说明tab页不是挂机页,则要点击挂机页
  29.         if (dm.FindStr(0,0,w,h,"加载附近怪","43.89.98-0.0.0",1.0,加载附近怪x,加载附近怪y) == -1)                    
  30.             if(dm.FindStr(0,0,w,h,"挂机","43.89.98-0.0.0",1.0,x,y) == -1)
  31.                 debug.print("未找到挂机-打开辅助")
  32.                 goto 打开辅助
  33.                 help.sleep(200)
  34.             endif
  35.             
  36.             dm.MoveTo(x+10,y+10)
  37.             help.sleep(200)
  38.             dm.LeftClick()
  39.             debug.print("加载附近怪")
  40.             if(dm.FindStr(0,0,w,h,"加载附近怪","43.89.98-0.0.0",1.0,x,y) == -1)
  41.                 debug.print("加载附近怪-打开辅助")
  42.                 goto 打开辅助
  43.             endif
  44.             dm.MoveTo(x+10,y+10)
  45.             
  46.             help.sleep(200)
  47.             dm.LeftClick()
  48.             help.sleep(200)
  49.             a = x
  50.             b = y
  51.         else
  52.             
  53.             dm.MoveTo(加载附近怪x+10,加载附近怪y+10)
  54.             help.sleep(200)
  55.             dm.LeftClick()
  56.             help.sleep(300)
  57.             a = 加载附近怪x
  58.             b = 加载附近怪y
  59.         endif
  60.         
  61. aa:
  62.         debug.print("while 查怪")
  63.         while(dm.FindStr(0,0,w,h,"猛犸教主|奴玛教主|重装使者|妖月金刚|邪恶蛇蝎|妖月血魔","0.0.100-0.0.0",1.0,x,y) != -1)
  64.             新武尊辅助.启动Z键()
  65.             debug.print("进入while查怪")
  66.             help.sleep(300)
  67.             if(dm.FindStr(0,0,w,h,"加载附近怪","43.89.98-0.0.0",1.0,x,y) == -1)
  68.                 debug.print("查怪 - 转到打开辅助")
  69.                 goto 打开辅助
  70.             endif
  71.             dm.MoveTo(x+10,y+10)
  72.             debug.print("点击加载附近怪 x"&x &"y"&y)
  73.             help.sleep(200)
  74.             dm.LeftClick()
  75.             help.sleep(200)
  76.             hadKillBoss = true
  77.             findBossTime = system.gettickcount()
  78.         endwhile
  79.         
  80.         if(x>0 && y>0)
  81.             goto aa
  82.         endif   
  83.         
  84.         if(type.int(findBossTime+50000) <= type.int(system.gettickcount()) )
  85.             debug.print("超时未找到怪,随机飞")
  86.             新武尊辅助.active()
  87.             dm.KeyPress(keys.VK_6)
  88.             help.sleep(1000)
  89.         endif
  90.         
  91.         if (hadKillBoss == true)
  92.             debug.print("关闭所有窗口")
  93.             新武尊辅助.关闭所有打开的窗口()
  94.             新武尊辅助.停止挂机()
  95.             新武尊辅助.拾取物品()
  96.         endif
  97.         hadKillBoss = false
  98.         
  99.     endwhile
  100. endfunction
复制代码


这是线程3中的代码,欢迎大家指点一下。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-12-6 00:03:53 | 显示全部楼层
  1. function 监视血值()
  2.     x,y,lastHp
  3.     t = edit.gettext("edtUseRndHP")
  4.    
  5.     if (dm.FindStr(0,0,302,122,"辅助","43.89.98-0.0.0",1.0,x,y) == -1)
  6.         help.messagebox("没有找到'辅助'!")
  7.         return 0
  8.     endif
  9.    
  10.     while(true)
  11.         s = dm.Ocr(x-27,y-45,x+69,y-31,"0.0.100-0.0.0",1.0)
  12.         if(s == "")
  13.             //help.messagebox("血值出错")
  14.             debug.print("血值出错")
  15.         endif
  16.         pos = str.findstr(s,"/")
  17.         curHp = type.int(str.strsub(s,0,pos))
  18.         sumHp = type.int(str.strsub(s,pos+1,str.strleng(s)))
  19.         
  20.         if(curHp < sumHp * HP百分比)
  21.             NeedPickHP = true
  22.         else
  23.             NeedPickHP = false
  24.         endif
  25.         if (curHp + 一次性掉血 < lastHp)
  26.             新武尊辅助.active()
  27.             
  28.             dm.KeyPress(keys.VK_6)   
  29.             
  30.             if(combo.gettext("ComboBox0") == "矿洞挖矿")
  31.                 help.sleep(1000)
  32.                 dm.KeyPress(keys.VK_Z)
  33.             endif
  34.             
  35.         endif
  36.         help.sleep(200)
  37.         lastHp = curHp
  38.     endwhile
  39. endfunction
复制代码


这是线程1,监视血值变化的线程代码,欢迎大家指正。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-12-6 00:06:21 | 显示全部楼层
  1. function 初始化监视()
  2.     while(true)
  3.         s = 新武尊辅助.获取当前地点()
  4.         if(s == "沙漠土城")
  5.             新武尊辅助.修理装备()
  6.             新武尊辅助.购买令牌()
  7.             token = edit.gettext("edtTokenLoc")
  8.             新武尊辅助.active()
  9.             dm.KeyPress(keys.TransKey(token))
  10.             help.sleep(1000)
  11.         endif
  12.         help.sleep(1000)
  13.     endwhile   
  14. endfunction
复制代码


这是线程2代码, 主要是监视是否回城,这段代码主要是判断地点。当然,这个代码也可以放在线程3中。
回复 支持 反对

使用道具 举报

发表于 2013-12-6 00:14:19 | 显示全部楼层
你代码内有没有使用线程关闭操作?
我写的一个脚本有过这样的问题,线程关闭之后重新开启,开启成功已经返回线程句柄了。
然后就没有然后了,线程就这样开启之后莫名其妙的不执行了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-12-6 00:17:44 | 显示全部楼层
jrflsh 发表于 2013-12-6 00:14
你代码内有没有使用线程关闭操作?
我写的一个脚本有过这样的问题,线程关闭之后重新开启,开启成功已经返 ...

线程统一在外挂停止时执行关闭的,中途没有其它代码去暂停或停止任何线程。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-12-6 00:20:41 | 显示全部楼层
  1. function start_click()
  2.     path=help.getrcpath("rc:dm.dll")
  3.    
  4.     regRet = help.regdll(path,true)
  5.     if (!regRet)
  6.         help.messagebox("注册DLL失败!")
  7.         return 0
  8.     endif
  9.     dm = com("dm.dmsoft") //创建dm对象
  10.     hwnd = dm.GetMousePointWindow()
  11.     if (hwnd <= 0)
  12.         help.messagebox("没有找到游戏窗口")
  13.         return 0
  14.     endif
  15.     //bindRet = dm.BindWindow(hwnd,"gdi","windows","windows",1)
  16.     dmRet = dm.SetWindowState(hwnd,1)
  17.     bindRet = dm.BindWindowEx(hwnd, "gdi", "windows", "windows","dx.public.fake.window.min", 0)
  18.     if (bindRet == 0)
  19.         help.messagebox("bind失败!")
  20.         return 0
  21.     endif
  22.     dm.SetKeypadDelay("windows",50)
  23.     base_path = help.getrcpath("rc:")
  24.     dm_ret = dm.SetPath(base_path)
  25.     dm_ret = dm.SetDict(0,"myDic.txt")
  26.     新武尊辅助.初始基坐标()
  27.     新武尊辅助.初始化变量()
  28.     if(combo.gettext("ComboBox0") == "玛雅一层挂机")
  29.         线程查血 = thread.beginthread("新武尊辅助.监视血值","")
  30.         if(线程查血 == null || 线程查血 <= 0)
  31.             help.messagebox("线程查血 线程未启动成功")
  32.         endif
  33.         线程初始监视 = thread.beginthread("新武尊辅助.初始化监视","")
  34.         if(线程初始监视 == null || 线程初始监视 <= 0)
  35.             help.messagebox("线程初始监视 线程未启动成功")
  36.         endif
  37.         help.sleep(3000)
  38.         线程打怪 = thread.beginthread("新武尊辅助.打怪与寻路","")
  39.         if(线程打怪 == null || 线程打怪 <= 0)
  40.             help.messagebox("线程打怪 线程未启动成功")
  41.         endif
  42.     endif
  43.    
  44.    
  45.     control.enable("start",false)
  46.     control.enable("btnEnd",true)
  47.     statue = true
  48. endfunction
复制代码


这是启动热键所触发的代码,此代码启动线程。
回复 支持 反对

使用道具 举报

发表于 2013-12-6 00:20:59 | 显示全部楼层
那你查查看是不是卡死在哪个循环里面去了
回复 支持 反对

使用道具 举报

发表于 2013-12-6 00:21:13 | 显示全部楼层
不要认为机会不大就代表没机会。
多线程同一对象键鼠操作可以先用临界区或者创建事件试试。

当然有时候也不要想太复杂。
先直接从线程3里面的代码入手。每个入口和出口点都加一下输出语句。当不打怪的时候看看输出语句处于什么位置来大概判断问题所在。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-12-6 00:25:40 | 显示全部楼层
jrflsh 发表于 2013-12-6 00:20
那你查查看是不是卡死在哪个循环里面去了

线程3的while中有print,如果是此处死循环,那么while断点应有断下来,并且调试器应也能输出调试信息。但现在一切都没有。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条

关闭

小黑屋|TC官方合作论坛 (苏ICP备18045623号)

GMT+8, 2024-9-23 11:54 , Processed in 0.037923 second(s), 23 queries .

Powered by 海安简单软件服务部

© 2008-2019 版权所有 保留所有权利

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