引言

在《魔兽世界》中,自动化脚本可以帮助玩家完成重复性任务,如打怪、拾取物品、售卖物品等。WRobot是一个可用在私服上的自动化工具,支持使用C#编写自定义脚本。

本文将介绍如何使用C#编写一个的WRobot自动化循环刷本脚本。

1. 环境准备

在开始编写脚本之前,确保你已经安装了WRobot,并熟悉其基本操作。WRobot提供了一个插件系统,允许用户通过C#编写自定义逻辑。

对应版本:魔兽世界-暗影国度 9.27 + WRobot 2.8.0 (大概在国服开10.0的时,国外有了个9版本的私服,就写了这脚本用来刷G,后来刷了100多w也没啥用,游戏也弃了,回归国服继续肝正式服)

2. 创建插件

WRobot插件是一个实现了wManager.Plugin.IPlugin接口的C#类。以下是一个简单的插件模板:

csharp复制代码
using System;
using System.Threading;
using robotManager.Helpful;
using wManager.Wow.Class;
using wManager.Wow.Helpers;
using wManager.Wow.ObjectManager;

public class MyPlugin : wManager.Plugin.IPlugin
{
    private bool isLaunched;

    public void Initialize()
    {
        isLaunched = true;
        Logging.Write("插件已启动");

        // 在这里添加你的逻辑
        while (isLaunched)
        {
            // 执行任务
            Thread.Sleep(1000);
        }
    }

    public void Dispose()
    {
        isLaunched = false;
        Logging.Write("插件已停止");
    }

    public void Settings()
    {
        // 插件设置
    }
}

3. 关键功能实现

Initialize方法中,你可以编写插件的核心逻辑。以下是一些常见的功能实现:

3.1 移动和导航

使用GoToTask.ToPosition方法可以让角色移动到指定位置:

csharp复制代码
wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-786.707f, 6100.32f, 4.649368f));
3.2 与NPC交互

使用GoToTask.ToPositionAndIntecractWithNpc方法可以与指定NPC交互:

csharp复制代码
wManager.Wow.Bot.Tasks.GoToTask.ToPositionAndIntecractWithNpc(new Vector3(-786.707f, 6100.32f, 4.649368f), 89257);

 

以下是完整代码:

using System;
using System.Threading;
using robotManager.Helpful;
using robotManager.Products;
using wManager.Wow.Class;
using wManager.Wow.Helpers;
using wManager.Wow.ObjectManager;
using Timer = robotManager.Helpful.Timer;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using robotManager;
using System.IO;
using robotManager.FiniteStateMachine;
using wManager.Wow.Bot.States;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using wManager.Wow.Bot.Tasks;
using wManager;
using robotManager.Events;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using wManager.Wow.Enums;
using System.Windows;
using System.Text.RegularExpressions;
// using 主要从wrobot中获取wManager 和 robotManager 命名空间
// 一些注释代码是做一些备用功能或备忘录用的
public class Mainasl: wManager.Plugin.IPlugin
{
    private bool isLaunched;
    // ContinentId = 1220    1456
    //return Usefuls.ContinentId == 1456;
    private void test()
    {
        robotManager.Helpful.Mouse.ClickLeft();
        //robotManager.Helpful.Keyboard.PressKey(wManager.Wow.Memory.WowMemory.Memory.WindowHandle, System.Windows.Forms.Keys.);
        //rbotManager.Helpful.XmlSerializer.
    }
    public void Initialize()
    {
        var originStr = "";
        var regStr = @"!\w+\s\d+";
        var resultStr = string.Empty;
        MatchCollection matches = Regex.Matches(originStr, regStr);
        foreach(Match match in matches)
        {
            resultStr = match.Value;
        }
        if(!string.IsNullOrWhiteSpace(resultStr))
        {
            // 输入
        }
        robotManager.Events.ProductEvents.OnProductLoaded += ProductEvents_OnProductLoaded;
        robotManager.Products.Products.LoadProducts("");
        isLaunched = true;
        
        if(Usefuls.AreaId != 7334 && Usefuls.ContinentId != 1456)
        {
            Products.ProductStop();
            Logging.Write("非阿苏纳地图或者非艾萨拉之眼地图,停止WR");
        }
        if(Usefuls.AreaId == 7334)
        {
            if(wManager.Wow.Helpers.Bag.GetContainerNumFreeSlots <= 60) //判断包裹剩余格子
            {
                wManager.Wow.Bot.Tasks.GoToTask.ToPositionAndIntecractWithNpc(new Vector3(-786.707 f, 6100.32 f, 4.649368 f), 89257);
                List < WoWItem > wiList = Bag.GetBagItem();
                List < string > itemSell = new List < string > ();
                List < string > itemNoSell = new List < string > ();
                itemNoSell.Add("炉石");
                itemNoSell.Add("飞行管理员的哨子");
                List < WoWItemQuality > itemQuality = new List < WoWItemQuality > ();
                itemQuality.Add(WoWItemQuality.Artifact);
                itemQuality.Add(WoWItemQuality.Common);
                itemQuality.Add(WoWItemQuality.Epic);
                itemQuality.Add(WoWItemQuality.Heirloom);
                itemQuality.Add(WoWItemQuality.Legendary);
                itemQuality.Add(WoWItemQuality.Poor);
                itemQuality.Add(WoWItemQuality.Rare);
                itemQuality.Add(WoWItemQuality.Uncommon);
                for(int i = 0; i < wiList.Count; i++)
                {
                    itemSell.Add(wiList[i].Name);
                }
                Vendor.SellItems(itemSell, itemNoSell, itemQuality);//卖掉所有东西
                Thread.Sleep(1000 * 3);
            }
            Logging.Write("回到艾萨拉之眼副本门口");
            Lua.LuaDoString("ResetInstances();");
            Logging.Write("重置副本");
            wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-2.174723 f, 5800.943 f, 2.098947 f));
            Logging.Write("进本");
            // 门口模拟按键
            Move.StrafeLeft(Move.MoveAction.PressKey, 100);
            Move.Forward(Move.MoveAction.PressKey, 2000);
        }
        // sell point to 0 - 3
        wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-771.9302 f, 6111.996 f, 51.47897 f));
        wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-606.0879 f, 5991.238 f, 67.36471 f));
        wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-403.6466 f, 5857.353 f, 101.1433 f));
        Thread.Sleep(1000 * 30);
        wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-201.3126 f, 5747.511 f, 135.9531 f));
        //PositionWithoutType = -786.707 ; 6100.32 ; 4.649368 ; "None"
        //PositionRelativeWithoutType = -786.707; 6100.32; 4.649368; "None"
        if(Usefuls.ContinentId == 1220 && wManager.Wow.Helpers.Bag.GetContainerNumFreeSlots <= 2)
        {
            wManager.Wow.Bot.Tasks.GoToTask.ToPositionAndIntecractWithNpc(new Vector3(-786.707 f, 6100.32 f, 4.649368 f), 89257);
            List < WoWItem > wiList = Bag.GetBagItem();
            List < string > itemSell = new List < string > ();
            List < string > itemNoSell = new List < string > ();
            itemNoSell.Add("炉石");
            itemNoSell.Add("飞行管理员的哨子");
            List < WoWItemQuality > itemQuality = new List < WoWItemQuality > ();
            itemQuality.Add(WoWItemQuality.Artifact);
            itemQuality.Add(WoWItemQuality.Common);
            itemQuality.Add(WoWItemQuality.Epic);
            itemQuality.Add(WoWItemQuality.Heirloom);
            itemQuality.Add(WoWItemQuality.Legendary);
            itemQuality.Add(WoWItemQuality.Poor);
            itemQuality.Add(WoWItemQuality.Rare);
            itemQuality.Add(WoWItemQuality.Uncommon);
            for(int i = 0; i < wiList.Count; i++)
            {
                itemSell.Add(wiList[i].Name);
            }
            Vendor.SellItems(itemSell, itemNoSell, itemQuality);
        }
        //  回到坐标  -2.174723 ; 5800.943 ; 2.098947 
        wManager.Wow.Bot.Tasks.GoToTask.ToPosition(new Vector3(-2.174723 f, 5800.943 f, 2.098947 f));
        Logging.Write("111" + Lua.LuaDoString < string > ("GetDungeonDifficulty();"));
        Lua.LuaDoString("SetDungeonDifficulty(2);");
        Move.Forward(Move.MoveAction.PressKey, 3000);
        Move.StrafeLeft(Move.MoveAction.PressKey, 100);
        Write("初始化...");
        // 以下配置是可以在Wrobot工具中配置,也可以在这里写代码直接配置好
        wManagerSetting.CurrentSetting.CloseAfterXMin = 60 * 3; // XX分钟后停止WR
        wManagerSetting.CurrentSetting.LootMobs = true; //拾取
        //被GM传送关闭游戏
        wManagerSetting.CurrentSetting.CloseIfPlayerTeleported = false;
        //目标周围怪物数量
        wManagerSetting.CurrentSetting.MaxUnitsNear = 99;
        //可攻击灰名怪
        wManagerSetting.CurrentSetting.CanAttackUnitsAlreadyInFight = true;
        //可攻击精英怪
        wManagerSetting.CurrentSetting.AttackElite = true;
        //主动攻击敌对玩家
        wManagerSetting.CurrentSetting.AttackBeforeBeingAttacked = false;
        //寻怪搜索范围
        wManagerSetting.CurrentSetting.SearchRadius = 25;
        //避免在玩家附近拾取
        wManagerSetting.CurrentSetting.HarvestAvoidPlayersRadius = 0;
        //远距离拾取41
        wManagerSetting.CurrentSetting.HarvestDuringLongMove = true;
        wManagerSetting.CurrentSetting.Repair = false; // 修理
        wManagerSetting.CurrentSetting.Selling = false; // 售卖
        wManagerSetting.CurrentSetting.HarvestHerbs = false; // 采集
        //wManagerSetting.CurrentSetting.acc
        wManager.wManagerSetting.CurrentSetting.LootChests = true; //拾取
        wManager.wManagerSetting.CurrentSetting.LootChests = true;
        Logging.Stop();
        robotManager.Helpful.Logging.Stop();
        wManagerSetting.CurrentSetting.UseFlyingMount = true;
        wManagerSetting.CurrentSetting.FlyAboveGroundHeight = 60;
        wManagerGlobalSetting.CurrentSetting.Save();
        while(true)
        {
            isLaunched = true;
            GO();
            
            robotManager.Events.LoggingEvents.OnAddLog += delegate(Logging.Log log)
            {
                if(!log.Text.Contains("[ToTown] Unable to reach the vendor, blacklist it 120 minutes (you can disable this NPC in NPC DB tab 'Tools').")) return;
                foreach(var n in NpcDB.ListNpc)
                {
                    n.BlackList(-1);
                }
            };
            robotManager.Events.LoggingEvents.OnAddLog += (robotManager.Helpful.Logging.Log log) =>
            {
                log.Text = string.Empty;
            };
            while(Products.IsStarted)
            {
                try
                {
                    try
                    {
                        if(Usefuls.ContinentId == 1220)
                        {
                            Move.Forward(Move.MoveAction.PressKey, 300); // 运行过程中会有问题,导致角色不动了,用个纠错移动来继续执行脚本。大概率是wow服务器问题
                            Logging.Write("纠错移动");
                        }
                    }
                    catch(Exception)
                    {}
                    Thread.Sleep(1000 * 60 * 2);
                }
                catch(Exception)
                {}
            }
        }
    }
    private void ProductEvents_OnProductLoaded(string str)
        {
            throw new NotImplementedException();
        }
        // 其实判断装备好坏是个很难的问题,涉及到很多代码,不想写了,毕竟刷本是用来刷G的
        //private void EventsLuaWithArgs_OnEventsLuaWithArgs(string eventName, List<string> args)
        //{
        //    if (eventName == "CHAT_MSG_LOOT") // 监听物品拾取事件
        //    {
        //        string lootMessage = args.FirstOrDefault();
        //        if (lootMessage != null)
        //        {
        //            // 解析物品链接
        //            string itemLink = Lua.LuaDoString<string>(lootMessage);
        //            if (!string.IsNullOrEmpty(itemLink))
        //            {
        //                // 判断拾取的物品是否为装备
        //                if (ItemsManager.GetItemType(itemLink) == WoWItemType.Armor ||
        //                    ItemsManager.GetItemType(itemLink) == WoWItemType.Weapon)
        //                {
        //                    // 比较装备,判断是否更好
        //                    if (IsBetterEquipment(itemLink))
        //                    {
        //                        // 装备物品
        //                        EquipItem(itemLink);
        //                    }
        //                }
        //            }
        //        }
        //    }
        //}
    public static bool IsWorldFrame()
        {
            string cmd = "return WorldFrame:IsVisible();";
            Logging.Write(Lua.LuaDoString < string > (cmd));
            return Lua.LuaDoString < bool > (cmd);
            Lua.LuaDoString("WorldFrame:Click()");
            Lua.LuaDoString("print('[WorldFrame错误点击]');");
            Logging.Write("[WorldFrame错误点击]");
        }
        //private bool IsBetterEquipment(string itemLink)
        //{
        //    // 获取角色当前装备的同一部位的物品
        //    WoWItem equippedItem = ObjectManager.Me.Inventory.GetItemBySlot(itemLink.GetInventorySlot());
        //    // 比较物品的属性来判断是否更好
        //    if (equippedItem != null)
        //    {
        //        WoWItem newItem = new WoWItem(itemLink);
        //        newItem.GetItemInfo.
        //        return newItem.GetTotalStatValue() > equippedItem.GetTotalStatValue();
        //    }
        //    return true; // 如果当前部位没有装备,直接判断为更好
        //}
        //private void EquipItem(string itemLink)
        //{
        //    Lua.LuaDoString("UseContainerItem(" + itemLink.GetBagIndex() + ", " + itemLink.GetBagSlot() + ")");
        //}
    public static void ShaoTaGaoDi(int EntryId)
    {
        EventsLuaWithArgs.OnEventsLuaWithArgs += EventsLuaWithArgs_OnEventsLuaWithArgs;
        if(Lua.LuaDoString < string > ("local status = GetBattlefieldStatus(1)\r\nif status == \"active\" then\r\n  return \"0\" ") == "0")
        {}
        if(ObjectManager.GetObjectWoWUnit().Count(o => o.IsValid && !o.IsDead) < 10)
        {}
        var target = ObjectManager.GetNearestWoWGameObject(ObjectManager.GetWoWGameObjectByEntry(EntryId));
        if(target.IsValid)
        {
            MovementManager.MoveTo(target.Position);
            wManager.Wow.Bot.Tasks.GoToTask.ToPositionAndIntecractWithGameObject(target.Position, EntryId);
        }
    }
    private static void EventsLuaWithArgs_OnEventsLuaWithArgs(LuaEventsId id, List < string > args)
    {
        throw new NotImplementedException();
    }
    public void GO()
    {
        Products.ProductStop();
        Products.ProductStart();
        //Move.Forward(Move.MoveAction.PressKey, 5000);  // 
    }
    public void Write(string text)
    {
        Logging.Write(text);
        Lua.LuaDoString("print('" + text + "');");
    }
    public void Dispose()
    {
        isLaunched = false;
    }
    public void Settings()
    {}
}