清华西游记吧 关注:139贴子:1,462

mushclient 学习贴

只看楼主收藏回复

mushclient如此高大上,但是由于门槛较高,很多人都是望而却步,包括我自己也是。
早在2012年之前,wena就游说过我很多次体验一下mushclient
每次我都哼哼哈哈的答应的很好听,
完了继续优化改善我那一塌糊涂无可救药的zmud721
至到wena当wiz,升做admin,到现在消无声息,好几年时间一晃就过去了
至到2015年我实在是忍受不了zmud462无故弹窗报错,又不告知是什么地方有错
再加上确实是无聊,嗯,一定是太无聊了,
才下定决心啃啃mush这块硬骨头
下面记录一下我学习mushclient的体会
本人基础很差,不过好在脸皮厚,也不怕行家笑话
希望我写出来的一些粗浅经验,可以帮助其他也想学习mushclient的小伙伴


1楼2015-01-19 21:48回复
    安装mushclient跳过不提,新出的mushclient是绿色版,不需要安装,解压缩就能运行,免费软件,也没有注册或者破解的麻烦,老毛子真的是可以。
    运行mush之后的第一件事情就是新建游戏,如下图:

    World:这里我填的是大米的id,不同的大米填不同的id,这个字符串是可以在脚本里面用WorldName()获取的,可以用于做来多id公用机器的判断入口。
    这个字符串会显示在mush的界面上,如下图:

    mud 服务器的地址和ip就不必说了

    另外一个需要设置的地方就是Connecting
    Name:可填可不填,填在这里的字符串可以在脚本里面用函数GetOption获取到,我前面用了WorldName()获得id,这里也就没用到了。
    Password:和上面的Name一样,可以脚本里面获取到。在登录id的时候,可以从这里获取密码,而不需要把密码写在触发里面,对多id公用的机器还是很有用的。
    Connect:这里可以设置连接后自动登录的语句,不过功能很简单,我没有使用。
    好了,填完上面的几个参数,就能连接上thu xyj了。
    这一部分没什么难度,看看就会


    2楼2015-01-19 22:01
    回复
      登录到游戏画面,第一个要做的事情,肯定是做自动登录,
      不然每次都输入gb,n,id,passwd,多麻烦啊,是吧
      点菜单“Game”->"Configure"->"Triggers",活着直接键盘输入ctrl+shift+8
      mush支持很多键盘快捷方式,开始用总记不住,用多了慢慢就记得一些了。
      现在Triggers这一栏还是空白的,点下面的Add添加一个触发

      Enable,勾上就启用这一句触发,不勾上就不启用,好理解
      Regular expression :启用正则表达式。启用吧,用mushclient必须得会点正则表达式
      Send:内容和目标。我选择的是send to Script,内容是一个函数CommonLib.Loginset()
      意思是用语法函数来执行命令
      Group:和zmud的class类似,可以用EnableGroup()这个函数来启用和不启用某一个group的东西


      3楼2015-01-19 22:12
      回复
        开始举点实例说明mushclient的方便之处
        在zmud上面,检查身上的物品,筐里面的物品,篮子里面的物品,是一个很烦人的事情
        我在721下写了很多关于检查物品的语句,实在是非常繁琐


        一大堆%ismember,#if 时间长了,自己都不记得以前写的是些啥
        在mushclient上发现实现这个功能是如此轻松:
        mush支持多行匹配,能一次搞定。如下:
        你身上带着下列这些东西(负重 11%):
        一百一十五棵人参(Ren shen)
        十六棵灵芝(Ling zhi)
        十粒金丹(Jin dan)
        三十一两银子(Silver)
        □樟木盾(Zhangmu dun)
        □黄金战甲(Huangjin zhanjia)
        □死神的魔爪(Deathtouch)
        一百一十九两黄金(Gold)
        八十五文钱(Coin)
        □宣花斧(Xuanhua fu)
        宣花斧(Xuanhua fu)
        二架时空穿梭器(Chuansuo qi)
        三尖两刃枪(Sanliang spear)
        三尖两刃枪(Sanliang spear)
        水晶腰牌(Yao pai)
        竹筐(Kuang)
        传送卷轴(Teleport scroll)
        □兽皮披风(Shoupi pifeng)
        □五彩天衣(Tian yi)
        □细编翠竹花篮(Hua lan)
        □佛宝舍利子(Tooth)
        钢枪(Oracle)
        □钢护腕(Icestorm)

        勾选上REgular Expression ,然后勾上Multi-line
        你身上带着下列这些东西\(负重\s*(\d+)%\):\n(?:^.{2}(.*)\((.*)\)\n)*\z
        翻译一下:\n是换行 \s 是空格,^是匹配一行的开始,$匹配行末 *表示0个或者多个
        你身上带着下列这些东西(负重 11%): 这一行用下面的匹配
        你身上带着下列这些东西\(负重\s*(\d+)%\):\n
        ----用(\d+)来获取到11,\n换一行
        一百一十五棵人参(Ren shen)
        □黄金战甲(Huangjin zhanjia)
        (?:^.{2}(.*)\((.*)\)\n)*\z
        ----^匹配一行开始 .{2}匹配2个空格或者□ (.*)获取第一个数据\(和\)匹配'('和')',第一个(.*)获取括号内的数据,\n换行。整句前面加上(?: 后面加上)*,说明匹配0个或者多个这样的数据 \z我不能确切的知道是什么意思,mushclient的帮助上这么用,我也跟着用。^_*
        这样%1获得了11,%2获得了"一百一十五棵人参",%3获得了"Ren shen"
        后面持续的行,%2继续获得"黄金战甲",%2继续获得Huangjin zhanjia
        一直到出现不匹配的行,也就是"i"命令结束
        数据全部获取到,脚本相对就容易了,
        CommonLib.GetItemNum(AllItemInfo.InBody,"%2",string.lower("%3"))
        大概的功能是将获取到的物品id和数量整理一下,放到
        最终将结果存在AllItemInfo.InBody这个table里面:AllItemInfo.InBody这个table里面,如下:
        huangjin zhanjia = 1
        hua lan = 1
        silver = 31
        kuang = 1
        shoupi pifeng = 1
        gold = 119
        deathtouch = 1
        chuansuo qi = 2
        coin = 85
        oracle = 1
        zhangmu dun = 1
        icestorm = 1
        yao pai = 1
        tian yi = 1
        jin dan = 1
        teleport scroll = 1
        ren shen = 115
        ling zhi = 16
        tooth = 1
        sanliang spear = 2
        xuanhua fu = 2
        要想知道自己身上有多少人参,只需要用AllItemInfo.InBody["ren shen"]就行了
        btw:AllItemInfo.InBody 和AllItemInfo["InBody"]是一个意思
        获取筐或者花篮里面的物品,只用改一句触发就ok了
        这是一个编制精细的竹筐,用来装一些杂物。\n里面有:\n(?:\s{6}(.*)\((.*)\)\n)*\z
        这是一只精美的套层绢底雕花缎边细编翠竹花篮。\n类型.*\n里面有:\n(?:\s{6}(.*)\((.*)\)\n)*\z


        5楼2015-01-19 22:51
        回复(2)

          看了上面的正则表达式配多行触发,要想获得这个3 3 2是不是很轻松了呢?
          不过2个星期前,我刚开始用mush的时候还不会多行触发,用的是非常笨拙的方式

          触发只有一句,重点在脚本上:
          function GambleInfo.GambleJudgeNum(judgenum) 摘抄如下:
          if judgenum==1 then string_judge="根据耳力判断骰子是:"
          elseif judgenum==2 then string_judge="根据眼力判断骰子是:"
          elseif judgenum==3 then string_judge="又补道:现在开盘。"
          end
          for i=GetLinesInBufferCount(),GetLinesInBufferCount()-500,-1 do
          if GetLineInfo(i,1)==string_judge then
          GameListenNum=i
          end
          if GameListenNum > 0 then break end
          end
          上面的脚本for i=GetLinesInBufferCount(),GetLinesInBufferCount()-500,-1 do
          意思是从服务器发过来的数据开始朝前查最多500行,
          if GetLineInfo(i,1)==string_judge then
          GameListenNum=i
          end
          如果发现哪一行和需要匹配的字符串相同,记录行号。然后分析紧跟着的后面的几行的数据
          匹配的字符串对应听的骰子,看的骰子和庄家报的盘
          local NumberTable={"   "," ● ","●  ","  ●","● ●"}
          每行的骰子有5个不同的数据,对应0,1,1,1,2
          下面计算第一个骰子是多少
          GameNum1=0
          for j=1,3 do
          local str2=string.sub(GetLineInfo(GameListenNum+1+j,1),3,8)
          for i=1,#NumberTable do
          if str2==NumberTable[i] then
          GameNumber=i
          break
          end
          end
          GameNum1=GameNum1+GambleInfo.GambleStringToNum(GameNumber)
          end
          最开始写的脚本了,大概是从每行计算一个数出来,三个数相加
          比如三点就是1+1+1
          二点就是0+2+0


          6楼2015-01-19 23:14
          回复
            继续,已精


            IP属地:天津7楼2015-01-20 08:43
            回复
              继续实例:
              在thu挂机,无人值守的情况下,id总是会碰到不可预料的问题导致正常运行的任务流程中断,比如碰到拦路怪,网络卡顿导致命令过多,走路到一半断线重连等等。所以要想无人值守,最必要的一个工作就是能让发呆的id回到能飞的地方,重新开始找点事情做。有钱的主,比如当wiz以前的cksh,尝试飞一下,飞不动就用穿梭器搞定,简单粗暴,有钱就是如此任性;大部分人都做不到如此任性,普通青年都是是带个pillow,不能飞就cast chuqiao,到地府去睡觉,从红楼梦出来;我在721下实现的更加复杂,所以问题也更多。比如:chuqiao之前得判断是否还有法力吧?没法力了是不是得mingsi一下?万一是在安全期发呆,不允许冥思,还得走开一步?等等等等,是如此的烦人。我最讨厌看到的就是挂机几个月不管,偶尔去瞄一眼,发现有个id在安全期发呆,内力法力食物饮水精神气血全部为0,身上啥都没有,还不知道是哪里出的问题。虽然最近1,2年没有碰到这种情况了,但是碰到也很头疼。
              闲话少说,mush得益于强大的lua语法,所有不能飞的地方,都能直接走出来。对,就是走出来,就这么简单。
              hao的展室 -
              老玩家的展室。
              这里唯一的出口是 out。
              天上人间 元昊的蜡像(Hao npc)
              id发呆之后,先确定自己所在的位置:

              这个工作不难,就是把房间名称存在CommonVar.RoomName
              剩下的就是读数据,走出来


              函数fWalkToCross(),从table读取到tWalkToCross["hao的展厅"] = "out;e;#7 d",然后用Execute执行,就走到了十字街头,要走到麻将房、赌博房或者货堆发呆,也就容易了。
              所有需要走出来的地方,只需要完善table就行了。


              8楼2015-01-20 20:51
              回复
                最后1个麻烦在要记录所有不能飞的房间名字,如果有重复的,还得区分。zmud里可以调用数据库。。


                IP属地:英国9楼2015-01-21 05:53
                收起回复
                  正则表达式没看懂。。。
                  一百一十五棵人参(Ren shen) 不是分别提取一百一十五棵人参 和ren shen
                  那数量怎么出来的


                  IP属地:英国10楼2015-01-21 06:31
                  收起回复
                    有mushclient中文手册吗?


                    IP属地:北京11楼2015-01-21 23:14
                    收起回复
                      看了1星期的mushclient...
                      mapper部分都没搞出来
                      还是回721算了。。。最少不需要写代码。。


                      IP属地:英国13楼2015-01-24 19:28
                      回复
                        调试了一个周末,基本上可以在mush上半手动半自动的跑一下李靖任务,目前还只是slowwalk。
                        主要的问题在于把zmud上的遍历地图移植到mush上面来,像changan,chechi这种比较单纯的地图已经能顺利的跑完。但是有特殊地点的比如龙宫,雪山,长安西,还得慢慢调试
                        搭了一个门派的框架,准备适应各门派和id的扩展
                        faction = {
                        jjf = {
                        Spells = "baguazhou",
                        Force="lengquan-force",
                        weapon1="sanliang spear",
                        weapon2="xuanhua fu",
                        weapon3="xuanhua fu",
                        LearnSkill={"force","parry","dodge","lengquan-force","spells","axe","unarmed"},
                        LianSkill={"bawang-qiang","yanxing-steps","sanban-axe","changquan"},
                        EnableSkill = "enable axe sanban-axe;enable spear bawang-qiang;enable parry bawang-qiang;enable dodge yanxing-steps"
                        },
                        psd = {},
                        moon = {},
                        }
                        function faction.jjf.mieyaopfm(str)
                        local ename = str
                        if (not task.buffer.lianhua ) and (idclass.spells=="buddhism") then
                        Send("cast lianhua");
                        end
                        Execute("unwield all");
                        if (task.PfmTimes or 0 ) < 5 then
                        Execute("enable axe sanban-axe;enable parry sanban-axe;wield xuanhua fu;wielddagger")
                        Send("perform sanban on "..ename)
                        else
                        if idclass.oracle then Send("wield oracle") end
                        Execute("wield sanliang spear;enable parry bawang-qiang;wielddagger")
                        Send("perform bawangshanggong on "..ename)
                        end
                        if idclass.spells == "buddhism" then
                        task.buffer.lianhua = false
                        Send("buff")
                        end
                        Send("wear all")
                        end


                        14楼2015-01-25 22:30
                        回复
                          在mush上挂了一天,晚上回来发现在舍利塔里面发呆
                          于是增加了舍利塔的随机走路,也不知道有用没有。
                          得等到下次进舍利塔的时候观察观察
                          walkout = {
                          }
                          function walkout:SheLiTaOut()
                          setdog(200)
                          EnableGroup("walkout",true)
                          self.DirList = nil
                          Execute("unset brief_all;unset brief")
                          Send("look")
                          Send("follow check walkout script NextStep")
                          end
                          --[[ 碗子山 -
                          ]]
                          function walkout:GetRoomName(str)
                          self.room = str
                          end
                          function walkout:NextStep()
                          local out
                          if self.room == "囚洞" and not self.DirList then
                          out = "zuan"
                          else
                          out = math.random(1,#self.DirList)
                          print(out)
                          out = self.DirList[out]
                          print(out)
                          for k,v in pairs(self.DirList) do
                          print(self.room,v)
                          if self.room == "舍利塔" and v == "westdown" then
                          out = "wd"
                          break
                          end
                          end
                          end
                          print("out is "..out)
                          if out == "wd" then
                          Send(out)
                          EnableGroup("walkout",false)
                          Execute("timeout")
                          else
                          Send(out)
                          DoAfter(0.1,"follow check walkout script NextStep")
                          end
                          end
                          --[[
                          这里明显的出口是 southeast、eastdown 和 southdown。
                          ^\s+这里.*的出(.*)。$
                          ]]
                          function walkout:SetExit(str)
                          local str = string.gsub(str,"口是 ","");
                          str = string.gsub(str,"路","");
                          str = string.gsub(str," 和 ","|");
                          str = string.gsub(str,"、","|");
                          self.DirList = split(str,"|");
                          end


                          15楼2015-01-26 20:55
                          回复
                            分享下editplus的正则表达式便利性
                            ["0000"] = 0,
                            ["0001"] = 1,
                            ["0010"] = 2,
                            ["0011"] = 3,
                            ["0100"] = 4,
                            ["0101"] = 5,
                            ["0110"] = 6,
                            ["0111"] = 7,
                            ["1000"] = 8,
                            ["1001"] = 9,
                            ["1010"] = a,
                            ["1011"] = b,
                            ["1100"] = c,
                            ["1101"] = d,
                            ["1110"] = e,
                            ["1111"] = f,
                            想把后面的0,1,2,3,4,5...分别加上“”,挨个手写会很烦
                            在editplus上ctrl+h,叫出替换选项

                            Find what 用= (.),匹配,并获取一个单字符,Replace用 = "\1", \1表示获取的第一个数据。如果有多个匹配和用\2 \3 \4等来表示。类似于mush和zmud的%1 %2 %3 %4
                            鼠标点两下,就变成下面这样了
                            ["0000"] = "0",
                            ["0001"] = "1",
                            ["0010"] = "2",
                            ["0011"] = "3",
                            ["0100"] = "4",
                            ["0101"] = "5",
                            ["0110"] = "6",
                            ["0111"] = "7",
                            ["1000"] = "8",
                            ["1001"] = "9",
                            ["1010"] = "a",
                            ["1011"] = "b",
                            ["1100"] = "c",
                            ["1101"] = "d",
                            ["1110"] = "e",
                            ["1111"] = "f",
                            当然,用于更多数据输入的时候会更体现其方便性
                            每天写一点,搞得像记流水账了,也确实没啥好写的,mush机器写到现在,基本上都是工作量了。现在机器应该能全自动做李靖任务,灭妖间隙去打坐冥思,自动学习技能写了一半还没有开始调试。剩下守城、开封任务和如来任务,都只是工作量和调试的问题。
                            这两天学习了一下mush的自带函数GetLineInfo和GetStyleInfo,这个周末整理一下,写下mush下log法官字库的方法。纯属技术交流,不存在商业行为,应该不违反叶子坑或者鸽子王们没有公示的《关于禁止法官机器的若干规定》的种种说法
                            同时再次感谢wena同学,虽然他可能不会再回来玩,也不会看到这个帖子了。


                            16楼2015-01-28 20:45
                            回复
                              能求数据库吗?


                              IP属地:北京来自iPhone客户端18楼2015-02-02 14:13
                              回复