估计阅读时长: 4 分钟

假设我们现在拥有魔兽世界游戏的GM权限,那么我们可以怎样来组织一场有一千个玩家参加的PvP战斗呢?

现在已经可以知道的是,在魔兽世界服务器的数据库上存在有玩家的角色信息表格:characters,里面记录了玩家角色的名字ID,种族,等级,职业,在线状态等,所以我们可以通过下面的sql语句来查询出当前的服务器上在线的玩家:

SELECT  `name`, `level`
FROM `wotlkcharacters`.`characters`
WHERE (online = '1')
ORDER BY `level` DESC
LIMIT 200
;

接着,我们只需要遍历这个查询结果,将对应的name列的玩家角色召唤到同一个地图上就可以让这群玩家进行PvP战斗了。目前作为一个GM可以使用的进行玩家召唤的命令有summon命令,但是目前问题来了,每一次summon我们只能够召唤一个玩家。假若要按照标题中的组织起一场1000个人的战斗,GM会被累死的,所以我们还需要对我们的方法进行改进。

已知在魔兽世界游戏中,可以通过一种称作为插件的工具来实现游戏中的一些自动化工作。那我们就可以在这里来通过编写插件的Lua脚本来实现上面的1000个人的召唤工作。基本的Lua代码如下所示:

local summonTargets = { player_name }

local function BroadcastSummon()
    for _, playerName in ipairs(summonTargets) do
        SendChatMessage(".summon "..playerName, "SAY", nil, nil)
    end
end

SLASH_SUMMONALL1 = "/summonall"
SlashCmdList["SUMMONALL"] = BroadcastSummon

在上面的插件代码中,我们遍历一个存储有玩家名称的数组,然后依次发送传送的消息,最后,将这个功能和游戏中的/summonall命令关联起来,就可以在游戏中进行快捷的调用了。那现在问题来了,我们该如何将玩家的名称列表传递进来呢?有一种方法就是我们通过外部的脚本从数据库中查询出玩家列表,然后拼接成字符串替换进player_name就可以了。我们来试下:

现在,我们借助于R#脚本,将上面的查询实现:

require(graphQL);

imports "mysql" from "graphR";

let world = mysql::open(
    "wlk_develop",
    password = "Xi*OH8HoGRk%?jSgA)p%.t#<*o};=",
    dbname = "wotlkcharacters",
    general = TRUE);
let players = world |> table("characters") ;
let list = players |> where(
       online=1
   )
   |> order_by("level", true)
   |> limit(200)
   |> select(["name","level"])
   ;

list <- list$name;
list <- list |> split(size = 10);
list <- sapply(list, row -> '"' & paste(row, sep = '", "') & '"');

print(list);
print(get_last_sql(players));

let lua_script = `

local function GetPlayers()
    return { 
${list}
    }
end

local function BroadcastSummon()
    for _, playerName in ipairs(GetPlayers()) do
        SendChatMessage(".summon "..playerName, "SAY", nil, nil)
    end
end

SLASH_SUMMONALL1 = "/summonall"
SlashCmdList["SUMMONALL"] = BroadcastSummon

`;

writeLines(lua_script, con = "Interface/AddOns/OutdoorRaidsPvp/OutdoorRaidsPvp.lua");

通过上面的代码,我们生成了一个包含有玩家名称的插件工具。现在,我们来为这个LUA脚本文件编写魔兽世界的插件信息文件,在插件脚本的文件夹中创建一个和文件夹同名的toc文件,文件的内容如下所示:

## Interface: 30300
## Title: Summon |r|cFF0099FF[OutdoorRaidsPvp]|r
## Notes: Summon players for outdoor raid Pvp
## Notes-zhCN: 召唤玩家进行野外Pvp
## Notes-zhTW: 召唤玩家进行野外Pvp
## Version: 1.17.0
## X-Date: August, 2010
## Author: xieguigang
## X-Email: i@xieguigang.me
## X-Website: https://stack.xieguigang.me/
## X-Category: AI_Player

OutdoorRaidsPvp.lua

进入到游戏中,看看我们的插件是否正常的加载了:

可以看见插件已经可以正常的被加载到游戏中了。现在我们进入到游戏中试试对服务器上的玩家进行召唤。在我们的聊天框中输入我们定义的插件命令/summonall,可以看得到,选中的前200个玩家已经全部被召唤到了我们的身边,像热锅上的蚂蚁一样开始相互Pvp了。

谢桂纲
Latest posts by 谢桂纲 (see all)

Attachments

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

博客文章
June 2025
S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930  
  1. […] 在上面的工具调用消息数据结构中,我们可以清楚的看见有需要进行调用的工具名称,以及参数列表。当我们拿到这样子的调用信息后,就可以基于一定的规则找到需要执行的运行时中的函数来完成功能的实现。对于.NET平台上,我们一般是使用自定义属性加反射操作来解析相关的名称绑定结果。在.NET平台上对于这样子的一个根据调用信息来进行运行时解析和调用的方法,可以稍微参考《【Darwinism】Linux平台上的VisualBasic高性能并行计算应用的开发》的反射代码方法。 […]