LUA脚本示例

玩家事件脚本

新玩家欢迎系统
当新玩家首次登录时,自动发送欢迎消息、给予新手礼包,并传送到新手村。

功能特点

  • 检测玩家是否为新角色(等级1且游戏时间少于5分钟)
  • 发送个性化欢迎消息
  • 给予新手装备和金币
  • 自动传送到指定新手区域
完整脚本代码
-- 新玩家欢迎系统 local function OnPlayerLogin(event, player) -- 检查是否为新玩家 local level = player:GetLevel() local playedTime = player:GetTotalPlayedTime() if level == 1 and playedTime < 300 then -- 5分钟内的1级玩家 -- 发送欢迎消息 local playerName = player:GetName() player:SendBroadcastMessage("欢迎来到我们的服务器," .. playerName .. "!") player:SendBroadcastMessage("你已获得新手礼包,祝你游戏愉快!") -- 给予新手礼包 player:AddItem(6948, 1) -- 炉石 player:AddItem(4540, 10) -- 恢复药水 player:AddItem(117, 10) -- 食物 player:ModifyMoney(100000) -- 10金币 -- 传送到新手村(暴风城) player:Teleport(0, -8949.95, -132.493, 83.5312, 0) -- 3秒后发送额外提示 CreateLuaEvent(function() if player:IsInWorld() then player:SendBroadcastMessage("记得查看你的背包,里面有新手礼包哦!") end end, 3000, 1) end end -- 注册玩家登录事件 RegisterPlayerEvent(3, OnPlayerLogin) -- PLAYER_EVENT_ON_LOGIN = 3

使用说明

1. 将此脚本保存为 welcome_system.lua 文件

2. 放置在服务器的 lua_scripts 目录下

3. 重启服务器或重新加载LUA脚本

4. 新创建的1级角色登录时会自动触发欢迎系统

等级奖励系统
玩家升级时自动给予相应的奖励,包括金币、物品和技能点数。

功能特点

  • 监听玩家升级事件
  • 根据等级给予不同奖励
  • 特殊等级(10、20、30等)给予额外奖励
  • 发送升级祝贺消息
完整脚本代码
-- 等级奖励系统 local function OnPlayerLevelUp(event, player, oldLevel) local newLevel = player:GetLevel() local playerName = player:GetName() -- 基础升级奖励 local goldReward = newLevel * 1000 -- 每级1金币 player:ModifyMoney(goldReward) -- 发送升级祝贺 player:SendBroadcastMessage("恭喜升级到 " .. newLevel .. " 级!") player:SendBroadcastMessage("获得奖励:" .. (goldReward/10000) .. " 金币") -- 特殊等级奖励 if newLevel % 10 == 0 then -- 每10级 player:AddItem(6948, 1) -- 额外炉石 player:SendBroadcastMessage("达到 " .. newLevel .. " 级里程碑!获得特殊奖励!") -- 全服公告重要等级 if newLevel >= 60 then SendWorldMessage(playerName .. " 达到了 " .. newLevel .. " 级!让我们祝贺他!") end end -- 满级奖励 if newLevel == 80 then player:AddItem(12345, 1) -- 满级纪念品 player:ModifyMoney(1000000) -- 100金币 SendWorldMessage(playerName .. " 达到了满级80级!真是太厉害了!") end end -- 注册玩家升级事件 RegisterPlayerEvent(13, OnPlayerLevelUp) -- PLAYER_EVENT_ON_LEVEL_CHANGE = 13

使用说明

1. 将脚本保存为 level_reward.lua

2. 可以根据服务器需要调整奖励数量和物品ID

3. 特殊等级的判断条件可以自定义修改

4. 满级等级可以根据服务器版本调整(60、70、80等)

NPC和生物脚本

智能NPC对话系统
创建一个智能NPC,能够根据玩家等级、职业和任务状态提供不同的对话和服务。

功能特点

  • 根据玩家等级提供不同的对话内容
  • 检测玩家职业并给出专业建议
  • 提供任务状态查询功能
  • 动态生成对话选项
完整脚本代码
-- 智能NPC对话系统 local NPC_ENTRY = 190000 -- 自定义NPC ID -- 职业名称映射 local CLASS_NAMES = { [1] = "战士", [2] = "圣骑士", [3] = "猎人", [4] = "盗贼", [5] = "牧师", [6] = "死亡骑士", [7] = "萨满", [8] = "法师", [9] = "术士", [11] = "德鲁伊" } -- NPC对话处理 local function OnGossipHello(event, player, creature) local level = player:GetLevel() local class = player:GetClass() local className = CLASS_NAMES[class] or "未知职业" -- 清除之前的对话选项 player:GossipClearMenu() -- 根据等级提供不同的欢迎语 local greeting = "" if level < 10 then greeting = "你好,年轻的" .. className .. "!我看得出你刚开始你的冒险之旅。" elseif level < 30 then greeting = "欢迎," .. className .. "!你已经积累了一些经验,继续努力吧!" elseif level < 60 then greeting = "致敬,经验丰富的" .. className .. "!你的实力令人印象深刻。" else greeting = "向你致敬,传奇的" .. className .. "!你的名声已经传遍了整个大陆。" end -- 添加基本对话选项 player:GossipMenuAddItem(0, "查看我的角色信息", 0, 1) player:GossipMenuAddItem(0, "获取职业专属建议", 0, 2) player:GossipMenuAddItem(0, "检查任务状态", 0, 3) -- 高级玩家专属选项 if level >= 60 then player:GossipMenuAddItem(0, "传奇玩家专属奖励", 0, 4) end player:GossipMenuAddItem(0, "再见", 0, 99) -- 发送对话菜单 player:GossipSendMenu(1, creature, greeting) end -- 处理对话选择 local function OnGossipSelect(event, player, creature, sender, intid, code) local level = player:GetLevel() local class = player:GetClass() local className = CLASS_NAMES[class] or "未知职业" if intid == 1 then -- 角色信息 local info = string.format( "角色信息:\\n" .. "名称: %s\\n" .. "等级: %d\\n" .. "职业: %s\\n" .. "金币: %d金 %d银 %d铜", player:GetName(), level, className, player:GetCoinage() / 10000, (player:GetCoinage() % 10000) / 100, player:GetCoinage() % 100 ) player:SendBroadcastMessage(info) elseif intid == 2 then -- 职业建议 local advice = "" if class == 1 then -- 战士 advice = "作为战士,记住你是团队的盾牌。提升你的防御技能和仇恨控制能力。" elseif class == 8 then -- 法师 advice = "法师应该专注于法术强度和法力管理。学会合理使用控制技能。" elseif class == 5 then -- 牧师 advice = "牧师是团队的生命线。平衡治疗和伤害输出,保护好你的队友。" else advice = "继续磨练你的技能,每个职业都有其独特的优势和作用。" end player:SendBroadcastMessage(advice) elseif intid == 3 then -- 任务状态 -- 这里可以添加任务检查逻辑 player:SendBroadcastMessage("任务系统检查完毕,继续你的冒险吧!") elseif intid == 4 and level >= 60 then -- 传奇奖励 player:AddItem(6948, 1) -- 给予特殊物品 player:SendBroadcastMessage("恭喜!你获得了传奇玩家专属奖励!") elseif intid == 99 then -- 再见 player:GossipComplete() return end -- 返回主菜单 OnGossipHello(event, player, creature) end -- 注册事件 RegisterCreatureGossipEvent(NPC_ENTRY, 1, OnGossipHello) RegisterCreatureGossipEvent(NPC_ENTRY, 2, OnGossipSelect)

使用说明

1. 修改 NPC_ENTRY 为你的自定义NPC ID

2. 在数据库中创建对应的NPC

3. 可以根据需要添加更多的对话选项和功能

4. 建议结合数据库查询来实现更复杂的功能

服务器管理脚本

自动公告系统
创建一个自动公告系统,定时发送服务器公告,支持多条消息轮播和特殊事件提醒。

功能特点

  • 支持多条公告消息轮播
  • 可配置公告间隔时间
  • 支持特殊事件公告
  • 自动检测在线玩家数量
完整脚本代码
-- 自动公告系统 local ANNOUNCEMENT_INTERVAL = 300000 -- 5分钟 = 300000毫秒 -- 公告消息列表 local ANNOUNCEMENTS = { "欢迎来到我们的服务器!请遵守服务器规则。", "记得定期保存你的角色数据,避免意外损失。", "加入我们的QQ群获取最新资讯和活动信息!", "服务器每天凌晨4点进行维护,请提前下线。", "发现BUG请及时反馈给管理员,感谢您的支持!" } -- 当前公告索引 local currentAnnouncementIndex = 1 -- 发送公告函数 local function SendAnnouncement() local playerCount = GetPlayerCount() if playerCount > 0 then local message = ANNOUNCEMENTS[currentAnnouncementIndex] local fullMessage = string.format( "[服务器公告] %s (当前在线: %d人)", message, playerCount ) SendWorldMessage(fullMessage) -- 移动到下一条公告 currentAnnouncementIndex = currentAnnouncementIndex + 1 if currentAnnouncementIndex > #ANNOUNCEMENTS then currentAnnouncementIndex = 1 end end end -- 启动公告系统 local function StartAnnouncementSystem() -- 立即发送第一条公告 SendAnnouncement() -- 创建定时器 CreateLuaEvent(SendAnnouncement, ANNOUNCEMENT_INTERVAL, 0) print("自动公告系统已启动,间隔时间: " .. (ANNOUNCEMENT_INTERVAL/1000) .. "秒") end -- 服务器启动时初始化公告系统 local function OnServerStartup() -- 延迟30秒后启动公告系统,确保服务器完全启动 CreateLuaEvent(StartAnnouncementSystem, 30000, 1) end -- 注册服务器启动事件 RegisterServerEvent(33, OnServerStartup) -- SERVER_EVENT_ON_STARTUP = 33

使用说明

1. 修改 ANNOUNCEMENTS 数组添加你的公告内容

2. 调整 ANNOUNCEMENT_INTERVAL 设置公告间隔

3. 可以添加更多的公告类型和条件判断

4. 建议在服务器启动脚本中加载此模块

物品和装备脚本

自定义物品使用效果
创建自定义物品的使用效果,包括传送卷轴、经验药水、属性增强药剂等特殊功能物品。

功能特点

  • 支持多种物品类型的自定义效果
  • 包含冷却时间和使用限制
  • 支持随机效果和概率触发
  • 完整的错误处理和用户提示
完整脚本代码
-- 自定义物品使用效果系统 local CUSTOM_ITEMS = { [190001] = "teleport_scroll", -- 传送卷轴 [190002] = "exp_potion", -- 经验药水 [190003] = "stat_elixir", -- 属性药剂 [190004] = "lucky_box" -- 幸运宝箱 } -- 冷却时间记录 (玩家GUID -> 物品ID -> 过期时间) local itemCooldowns = {} -- 检查冷却时间 local function IsItemOnCooldown(player, itemId, cooldownSeconds) local guid = player:GetGUIDLow() local currentTime = GetCurrTime() if not itemCooldowns[guid] then itemCooldowns[guid] = {} end if itemCooldowns[guid][itemId] and itemCooldowns[guid][itemId] > currentTime then local remaining = itemCooldowns[guid][itemId] - currentTime return true, remaining end -- 设置新的冷却时间 itemCooldowns[guid][itemId] = currentTime + cooldownSeconds return false, 0 end -- 传送卷轴效果 local function UseTeleportScroll(player, item) local onCooldown, remaining = IsItemOnCooldown(player, item:GetEntry(), 300) -- 5分钟冷却 if onCooldown then player:SendBroadcastMessage("传送卷轴冷却中,还需等待 " .. remaining .. " 秒") return false end -- 传送位置列表 local teleportLocations = { {name = "暴风城", map = 0, x = -8949.95, y = -132.493, z = 83.5312}, {name = "奥格瑞玛", map = 1, x = 1676.21, y = -4315.29, z = 61.5243}, {name = "铁炉堡", map = 0, x = -4981.25, y = -881.542, z = 501.66}, {name = "达纳苏斯", map = 1, x = 9947.52, y = 2482.73, z = 1316.21} } -- 随机选择一个位置 local location = teleportLocations[math.random(1, #teleportLocations)] if player:Teleport(location.map, location.x, location.y, location.z, 0) then player:SendBroadcastMessage("传送到 " .. location.name .. " 成功!") return true else player:SendBroadcastMessage("传送失败,请稍后再试") return false end end -- 经验药水效果 local function UseExpPotion(player, item) local level = player:GetLevel() if level >= 80 then player:SendBroadcastMessage("满级角色无法使用经验药水") return false end local onCooldown, remaining = IsItemOnCooldown(player, item:GetEntry(), 3600) -- 1小时冷却 if onCooldown then player:SendBroadcastMessage("经验药水冷却中,还需等待 " .. math.floor(remaining/60) .. " 分钟") return false end -- 根据等级给予不同经验 local expGain = level * 1000 + math.random(500, 1500) player:GiveXP(expGain) player:SendBroadcastMessage("获得 " .. expGain .. " 点经验值!") return true end -- 属性药剂效果 local function UseStatElixir(player, item) local onCooldown, remaining = IsItemOnCooldown(player, item:GetEntry(), 1800) -- 30分钟冷却 if onCooldown then player:SendBroadcastMessage("属性药剂冷却中,还需等待 " .. math.floor(remaining/60) .. " 分钟") return false end -- 随机属性增强效果 (这里需要使用光环或buff系统) local effects = { {spell = 1234, name = "力量增强"}, {spell = 1235, name = "敏捷增强"}, {spell = 1236, name = "智力增强"}, {spell = 1237, name = "耐力增强"} } local effect = effects[math.random(1, #effects)] player:AddAura(effect.spell, player) -- 添加增益效果 player:SendBroadcastMessage("获得 " .. effect.name .. " 效果!持续30分钟") return true end -- 幸运宝箱效果 local function UseLuckyBox(player, item) -- 奖励列表 local rewards = { {type = "item", id = 6948, count = 1, chance = 30, name = "炉石"}, {type = "item", id = 4540, count = 10, chance = 25, name = "恢复药水x10"}, {type = "money", amount = 100000, chance = 20, name = "10金币"}, {type = "exp", amount = 5000, chance = 15, name = "5000经验"}, {type = "item", id = 12345, count = 1, chance = 10, name = "稀有装备"} } -- 随机选择奖励 local roll = math.random(1, 100) local currentChance = 0 for _, reward in ipairs(rewards) do currentChance = currentChance + reward.chance if roll <= currentChance then if reward.type == "item" then player:AddItem(reward.id, reward.count) elseif reward.type == "money" then player:ModifyMoney(reward.amount) elseif reward.type == "exp" then player:GiveXP(reward.amount) end player:SendBroadcastMessage("幸运宝箱开出:" .. reward.name .. "!") return true end end player:SendBroadcastMessage("很遗憾,这次没有获得奖励") return true end -- 物品使用事件处理 local function OnItemUse(event, player, item, target) local itemId = item:GetEntry() local itemType = CUSTOM_ITEMS[itemId] if not itemType then return -- 不是自定义物品 end local success = false if itemType == "teleport_scroll" then success = UseTeleportScroll(player, item) elseif itemType == "exp_potion" then success = UseExpPotion(player, item) elseif itemType == "stat_elixir" then success = UseStatElixir(player, item) elseif itemType == "lucky_box" then success = UseLuckyBox(player, item) end -- 如果使用成功,消耗物品 if success then player:RemoveItem(itemId, 1) end end -- 注册物品使用事件 RegisterPlayerEvent(15, OnItemUse) -- PLAYER_EVENT_ON_USE_ITEM = 15

使用说明

1. 修改 CUSTOM_ITEMS 表添加你的自定义物品ID

2. 在数据库中创建对应的物品模板

3. 可以根据需要调整冷却时间和效果

4. 奖励物品ID需要确保在数据库中存在

副本和团队脚本

智能副本管理系统
创建一个智能副本管理系统,包括难度调整、奖励分配、进度追踪和团队协作功能。

功能特点

  • 根据团队人数和等级自动调整副本难度
  • 智能奖励分配系统
  • 副本进度追踪和统计
  • 团队协作增益效果
  • 副本重置和冷却管理
完整脚本代码
-- 智能副本管理系统 local DUNGEON_MAPS = { [33] = {name = "影牙城堡", minLevel = 18, maxLevel = 25, maxPlayers = 5}, [36] = {name = "死亡矿井", minLevel = 15, maxLevel = 23, maxPlayers = 5}, [43] = {name = "哀嚎洞穴", minLevel = 15, maxLevel = 25, maxPlayers = 5}, [47] = {name = "剃刀沼泽", minLevel = 35, maxLevel = 45, maxPlayers = 5} } -- 副本数据存储 local dungeonData = {} -- 获取副本信息 local function GetDungeonInfo(mapId) return DUNGEON_MAPS[mapId] end -- 计算团队平均等级 local function GetGroupAverageLevel(group) if not group then return 0 end local totalLevel = 0 local memberCount = 0 local members = group:GetMembers() for _, member in pairs(members) do if member:IsInWorld() then totalLevel = totalLevel + member:GetLevel() memberCount = memberCount + 1 end end return memberCount > 0 and math.floor(totalLevel / memberCount) or 0 end -- 调整副本难度 local function AdjustDungeonDifficulty(mapId, group) local dungeonInfo = GetDungeonInfo(mapId) if not dungeonInfo then return end local memberCount = group:GetMembersCount() local avgLevel = GetGroupAverageLevel(group) -- 计算难度系数 local difficultyMultiplier = 1.0 -- 根据人数调整 if memberCount < dungeonInfo.maxPlayers then difficultyMultiplier = difficultyMultiplier * (0.8 + memberCount * 0.05) elseif memberCount > dungeonInfo.maxPlayers then difficultyMultiplier = difficultyMultiplier * (1.0 + (memberCount - dungeonInfo.maxPlayers) * 0.2) end -- 根据等级调整 local levelDiff = avgLevel - dungeonInfo.minLevel if levelDiff > 5 then difficultyMultiplier = difficultyMultiplier * (1.0 + levelDiff * 0.1) end -- 存储副本数据 if not dungeonData[mapId] then dungeonData[mapId] = {} end dungeonData[mapId].difficulty = difficultyMultiplier dungeonData[mapId].groupId = group:GetGUID() dungeonData[mapId].startTime = GetCurrTime() -- 通知团队 local members = group:GetMembers() for _, member in pairs(members) do member:SendBroadcastMessage(string.format( "副本难度已调整: %.1fx (团队%d人, 平均等级%d)", difficultyMultiplier, memberCount, avgLevel )) end end -- 玩家进入副本事件 local function OnPlayerEnterDungeon(event, player) local mapId = player:GetMapId() local dungeonInfo = GetDungeonInfo(mapId) if not dungeonInfo then return end local group = player:GetGroup() if not group then player:SendBroadcastMessage("建议组队进入副本以获得更好的体验!") return end -- 检查等级要求 local playerLevel = player:GetLevel() if playerLevel < dungeonInfo.minLevel then player:SendBroadcastMessage(string.format( "等级过低!建议等级: %d-%d", dungeonInfo.minLevel, dungeonInfo.maxLevel )) elseif playerLevel > dungeonInfo.maxLevel + 10 then player:SendBroadcastMessage("等级过高,经验和奖励将会减少") end -- 调整副本难度 AdjustDungeonDifficulty(mapId, group) -- 给予团队增益 if group:GetMembersCount() >= 3 then local members = group:GetMembers() for _, member in pairs(members) do if member:GetMapId() == mapId then member:AddAura(15366, member) -- 团队精神光环 end end end end -- BOSS死亡事件 local function OnBossKilled(event, creature, killer) if not killer or not killer:IsPlayer() then return end local player = killer:ToPlayer() local mapId = player:GetMapId() local dungeonInfo = GetDungeonInfo(mapId) if not dungeonInfo then return end local group = player:GetGroup() if not group then return end -- 计算奖励 local baseReward = { exp = creature:GetLevel() * 100, money = creature:GetLevel() * 1000 } -- 应用难度系数 local difficulty = dungeonData[mapId] and dungeonData[mapId].difficulty or 1.0 baseReward.exp = math.floor(baseReward.exp * difficulty) baseReward.money = math.floor(baseReward.money * difficulty) -- 分配奖励给团队成员 local members = group:GetMembers() local nearbyMembers = {} for _, member in pairs(members) do if member:GetMapId() == mapId and member:GetDistance(creature) < 100 then table.insert(nearbyMembers, member) end end -- 团队奖励加成 local teamBonus = #nearbyMembers >= 3 and 1.2 or 1.0 for _, member in pairs(nearbyMembers) do local memberExp = math.floor(baseReward.exp * teamBonus) local memberMoney = math.floor(baseReward.money * teamBonus) member:GiveXP(memberExp) member:ModifyMoney(memberMoney) member:SendBroadcastMessage(string.format( "击败BOSS奖励: %d经验, %d铜币 (团队加成: %.0f%%)", memberExp, memberMoney, (teamBonus - 1) * 100 )) -- 随机掉落特殊物品 if math.random(1, 100) <= 20 then -- 20%概率 local rareItems = {12345, 12346, 12347} -- 稀有物品列表 local randomItem = rareItems[math.random(1, #rareItems)] member:AddItem(randomItem, 1) -- 通知全团队 for _, teamMember in pairs(nearbyMembers) do teamMember:SendBroadcastMessage( member:GetName() .. " 获得了稀有物品!" ) end end end end -- 副本完成统计 local function OnDungeonComplete(mapId, group) local dungeonInfo = GetDungeonInfo(mapId) if not dungeonInfo or not dungeonData[mapId] then return end local completionTime = GetCurrTime() - dungeonData[mapId].startTime local minutes = math.floor(completionTime / 60) local seconds = completionTime % 60 local members = group:GetMembers() for _, member in pairs(members) do if member:GetMapId() == mapId then member:SendBroadcastMessage(string.format( "副本 %s 完成!用时: %d分%d秒", dungeonInfo.name, minutes, seconds )) -- 完成奖励 member:AddItem(6948, 1) -- 完成纪念品 member:ModifyMoney(50000) -- 5金币完成奖励 end end -- 清理副本数据 dungeonData[mapId] = nil end -- 注册事件 RegisterPlayerEvent(28, OnPlayerEnterDungeon) -- PLAYER_EVENT_ON_MAP_CHANGE RegisterCreatureEvent(0, 4, OnBossKilled) -- 所有生物死亡事件

使用说明

1. 修改 DUNGEON_MAPS 表添加你的副本地图ID和配置

2. 调整奖励物品ID和数量

3. 可以根据服务器需要修改难度计算公式

4. 建议配合副本重置系统使用

PVP和竞技场脚本

PVP竞技场管理系统
创建一个完整的PVP竞技场系统,包括匹配机制、等级分级、奖励系统和排行榜功能。

功能特点

  • 智能匹配系统,根据等级和技能匹配对手
  • 多种竞技场模式(1v1, 2v2, 3v3)
  • 积分和排名系统
  • 季度奖励和成就系统
  • 观战功能和回放系统
完整脚本代码
-- PVP竞技场管理系统 local ARENA_MAPS = { [559] = {name = "纳格兰竞技场", type = "2v2", minLevel = 70}, [562] = {name = "刀锋山竞技场", type = "3v3", minLevel = 70}, [572] = {name = "废墟之城", type = "5v5", minLevel = 70} } -- 玩家竞技场数据 local arenaPlayers = {} local arenaQueue = {["1v1"] = {}, ["2v2"] = {}, ["3v3"] = {}} local activeMatches = {} -- 初始化玩家竞技场数据 local function InitPlayerArenaData(player) local guid = player:GetGUIDLow() if not arenaPlayers[guid] then arenaPlayers[guid] = { rating = 1500, wins = 0, losses = 0, streak = 0, lastMatch = 0, seasonPoints = 0 } end return arenaPlayers[guid] end -- 计算玩家战斗力 local function CalculatePlayerPower(player) local level = player:GetLevel() local health = player:GetMaxHealth() local mana = player:GetMaxMana() -- 获取装备评分 local gearScore = 0 for slot = 0, 19 do local item = player:GetItemByPos(255, slot) if item then gearScore = gearScore + (item:GetItemLevel() or 0) end end -- 综合战斗力计算 local power = level * 10 + (health / 100) + (mana / 100) + gearScore return math.floor(power) end -- 寻找匹配对手 local function FindArenaMatch(player, arenaType) local playerData = InitPlayerArenaData(player) local playerRating = playerData.rating local playerPower = CalculatePlayerPower(player) local queue = arenaQueue[arenaType] -- 寻找合适的对手 for i, queuedPlayer in ipairs(queue) do if queuedPlayer:IsInWorld() then local opponentData = InitPlayerArenaData(queuedPlayer) local ratingDiff = math.abs(playerRating - opponentData.rating) local powerDiff = math.abs(playerPower - CalculatePlayerPower(queuedPlayer)) -- 匹配条件:等级差距不超过200,战力差距不超过1000 if ratingDiff <= 200 and powerDiff <= 1000 then -- 找到匹配,移除队列中的对手 table.remove(queue, i) return queuedPlayer end else -- 移除离线玩家 table.remove(queue, i) end end return nil end -- 加入竞技场队列 local function JoinArenaQueue(player, arenaType) local playerData = InitPlayerArenaData(player) local currentTime = GetCurrTime() -- 检查冷却时间 if currentTime - playerData.lastMatch < 300 then -- 5分钟冷却 local remaining = 300 - (currentTime - playerData.lastMatch) player:SendBroadcastMessage("竞技场冷却中,还需等待 " .. remaining .. " 秒") return false end -- 检查是否已在队列中 for _, queuedPlayer in ipairs(arenaQueue[arenaType]) do if queuedPlayer:GetGUIDLow() == player:GetGUIDLow() then player:SendBroadcastMessage("你已经在 " .. arenaType .. " 队列中") return false end end -- 尝试寻找匹配 local opponent = FindArenaMatch(player, arenaType) if opponent then -- 找到对手,开始匹配 StartArenaMatch(player, opponent, arenaType) else -- 加入队列等待 table.insert(arenaQueue[arenaType], player) player:SendBroadcastMessage("已加入 " .. arenaType .. " 竞技场队列,等待匹配...") -- 30秒后如果还没匹配到,扩大匹配范围 CreateLuaEvent(function() ExpandMatchmaking(player, arenaType) end, 30000, 1) end return true end -- 扩大匹配范围 local function ExpandMatchmaking(player, arenaType) if not player:IsInWorld() then return end -- 检查玩家是否还在队列中 local inQueue = false for _, queuedPlayer in ipairs(arenaQueue[arenaType]) do if queuedPlayer:GetGUIDLow() == player:GetGUIDLow() then inQueue = true break end end if inQueue then player:SendBroadcastMessage("扩大匹配范围,寻找对手中...") -- 这里可以实现更宽松的匹配条件 end end -- 开始竞技场比赛 local function StartArenaMatch(player1, player2, arenaType) local matchId = GetCurrTime() .. "_" .. player1:GetGUIDLow() .. "_" .. player2:GetGUIDLow() -- 选择竞技场地图 local arenaMapId = 559 -- 默认地图 for mapId, mapData in pairs(ARENA_MAPS) do if mapData.type == arenaType then arenaMapId = mapId break end end -- 传送玩家到竞技场 local arenaCoords = { [559] = {{x = 4055.5, y = 2919.5, z = 13.6}, {x = 4023.5, y = 2887.5, z = 13.6}} } local coords = arenaCoords[arenaMapId] or arenaCoords[559] player1:Teleport(arenaMapId, coords[1].x, coords[1].y, coords[1].z, 0) player2:Teleport(arenaMapId, coords[2].x, coords[2].y, coords[2].z, 0) -- 记录比赛信息 activeMatches[matchId] = { player1 = player1, player2 = player2, arenaType = arenaType, startTime = GetCurrTime(), mapId = arenaMapId } -- 通知玩家 player1:SendBroadcastMessage("竞技场比赛开始!对手: " .. player2:GetName()) player2:SendBroadcastMessage("竞技场比赛开始!对手: " .. player1:GetName()) -- 30秒准备时间 CreateLuaEvent(function() StartArenaCombat(matchId) end, 30000, 1) end -- 开始竞技场战斗 local function StartArenaCombat(matchId) local match = activeMatches[matchId] if not match then return end local player1, player2 = match.player1, match.player2 if player1:IsInWorld() and player2:IsInWorld() then player1:SendBroadcastMessage("战斗开始!") player2:SendBroadcastMessage("战斗开始!") -- 设置10分钟比赛时间限制 CreateLuaEvent(function() EndArenaMatch(matchId, "timeout") end, 600000, 1) else -- 有玩家离线,取消比赛 EndArenaMatch(matchId, "disconnect") end end -- 结束竞技场比赛 local function EndArenaMatch(matchId, result, winner) local match = activeMatches[matchId] if not match then return end local player1, player2 = match.player1, match.player2 local player1Data = InitPlayerArenaData(player1) local player2Data = InitPlayerArenaData(player2) -- 更新比赛记录 player1Data.lastMatch = GetCurrTime() player2Data.lastMatch = GetCurrTime() if result == "win" and winner then local loser = (winner == player1) and player2 or player1 local winnerData = InitPlayerArenaData(winner) local loserData = InitPlayerArenaData(loser) -- 更新胜负记录 winnerData.wins = winnerData.wins + 1 winnerData.streak = winnerData.streak + 1 loserData.losses = loserData.losses + 1 loserData.streak = 0 -- 计算积分变化 local ratingChange = CalculateRatingChange(winnerData.rating, loserData.rating) winnerData.rating = winnerData.rating + ratingChange loserData.rating = math.max(0, loserData.rating - ratingChange) -- 奖励 local seasonPoints = math.floor(ratingChange / 2) winnerData.seasonPoints = winnerData.seasonPoints + seasonPoints -- 通知结果 winner:SendBroadcastMessage("胜利!积分 +" .. ratingChange .. ",赛季点数 +" .. seasonPoints) loser:SendBroadcastMessage("失败!积分 -" .. ratingChange) -- 连胜奖励 if winnerData.streak >= 5 then winner:AddItem(29434, 1) -- 连胜奖励物品 winner:SendBroadcastMessage("连胜 " .. winnerData.streak .. " 场!获得特殊奖励!") end elseif result == "timeout" then player1:SendBroadcastMessage("比赛超时,平局") player2:SendBroadcastMessage("比赛超时,平局") elseif result == "disconnect" then if player1:IsInWorld() then player1:SendBroadcastMessage("对手离线,比赛取消") end if player2:IsInWorld() then player2:SendBroadcastMessage("对手离线,比赛取消") end end -- 传送玩家离开竞技场 if player1:IsInWorld() then player1:Teleport(0, -8949.95, -132.493, 83.5312, 0) -- 暴风城 end if player2:IsInWorld() then player2:Teleport(0, -8949.95, -132.493, 83.5312, 0) -- 暴风城 end -- 清理比赛数据 activeMatches[matchId] = nil end -- 计算积分变化 local function CalculateRatingChange(winnerRating, loserRating) local ratingDiff = loserRating - winnerRating local expectedScore = 1 / (1 + math.pow(10, ratingDiff / 400)) local kFactor = 32 -- K因子 return math.floor(kFactor * (1 - expectedScore)) end -- 玩家死亡事件处理 local function OnPlayerDeath(event, player, killer) -- 检查是否在竞技场中 for matchId, match in pairs(activeMatches) do if match.player1 == player then EndArenaMatch(matchId, "win", match.player2) break elseif match.player2 == player then EndArenaMatch(matchId, "win", match.player1) break end end end -- 显示竞技场排行榜 local function ShowArenaLeaderboard(player) -- 按积分排序 local sortedPlayers = {} for guid, data in pairs(arenaPlayers) do table.insert(sortedPlayers, {guid = guid, data = data}) end table.sort(sortedPlayers, function(a, b) return a.data.rating > b.data.rating end) player:SendBroadcastMessage("=== 竞技场排行榜 ===") for i = 1, math.min(10, #sortedPlayers) do local playerData = sortedPlayers[i] local playerName = "玩家" .. playerData.guid -- 这里需要根据GUID获取玩家名称 player:SendBroadcastMessage(string.format( "%d. %s - 积分: %d (胜: %d, 负: %d)", i, playerName, playerData.data.rating, playerData.data.wins, playerData.data.losses )) end end -- 注册事件 RegisterPlayerEvent(4, OnPlayerDeath) -- PLAYER_EVENT_ON_KILL_PLAYER -- 竞技场命令处理 local function OnPlayerChat(event, player, msg, type, lang) if msg:lower():find("^%.arena") then local args = {} for word in msg:gmatch("%S+") do table.insert(args, word) end if args[2] == "join" and args[3] then JoinArenaQueue(player, args[3]) elseif args[2] == "leave" then -- 离开队列逻辑 player:SendBroadcastMessage("已离开竞技场队列") elseif args[2] == "stats" then local data = InitPlayerArenaData(player) player:SendBroadcastMessage(string.format( "竞技场统计 - 积分: %d, 胜: %d, 负: %d, 连胜: %d", data.rating, data.wins, data.losses, data.streak )) elseif args[2] == "top" then ShowArenaLeaderboard(player) end end end RegisterPlayerEvent(18, OnPlayerChat) -- PLAYER_EVENT_ON_CHAT

使用说明

1. 玩家使用 .arena join 1v1/2v2/3v3 加入队列

2. 使用 .arena stats 查看个人统计

3. 使用 .arena top 查看排行榜

4. 修改 ARENA_MAPS 配置竞技场地图

5. 调整积分计算公式和奖励系统