|
|
分享一个土城跑酷活动模板,适合做晚间活动、节日活动、开区娱乐玩法。
功能点:
1. 玩家从起点 NPC 开始计时。
2. 按顺序踩检查点,不能跳点。
3. 超时失败,完成后按耗时发奖励。
4. 检查点之间距离异常时判定为疑似传送作弊。
实际使用时,把 Parkour.onStart 绑到起点 NPC,把 Parkour.onCheckpoint 绑到每个坐标触发器。
-- TuchengParkour.lua
-- 土城跑酷:检查点、计时、超时、防跳点
local VvApi = {}
function VvApi.getPlayerName(player)
return player.name
end
function VvApi.getMapId(player)
return player.mapId or "3"
end
function VvApi.getPos(player)
return player.x or 0, player.y or 0
end
function VvApi.now()
return os.time()
end
function VvApi.getVar(key, default)
_G.__vv_vars = _G.__vv_vars or {}
local v = _G.__vv_vars[key]
if v == nil then return default end
return v
end
function VvApi.setVar(key, value)
_G.__vv_vars = _G.__vv_vars or {}
_G.__vv_vars[key] = value
end
function VvApi.addItem(player, itemName, count)
print("add item", VvApi.getPlayerName(player), itemName, count)
end
function VvApi.sendMsg(player, msg)
print(msg)
end
function VvApi.teleport(player, mapId, x, y)
-- TODO: 替换为传送接口,可用于失败后拉回起点
print("teleport", VvApi.getPlayerName(player), mapId, x, y)
end
local Parkour = {}
Parkour.config = {
mapId = "3", -- 土城地图 ID
timeLimit = 180, -- 180 秒内完成
maxStepDistance = 80, -- 两个检查点之间超过该距离,认为疑似异常
startPos = { x = 330, y = 330 },
checkpoints = {
{ x = 320, y = 300 },
{ x = 350, y = 285 },
{ x = 380, y = 310 },
{ x = 365, y = 350 },
{ x = 335, y = 360 },
},
rewards = {
{ maxTime = 60, item = "跑酷冠军礼包", count = 1 },
{ maxTime = 120, item = "跑酷优秀礼包", count = 1 },
{ maxTime = 180, item = "跑酷参与礼包", count = 1 },
},
}
local function key(name, field)
return "parkour:" .. field .. ":" .. name
end
local function distance(a, b)
local dx = a.x - b.x
local dy = a.y - b.y
return math.sqrt(dx * dx + dy * dy)
end
function Parkour.onStart(player)
if VvApi.getMapId(player) ~= Parkour.config.mapId then
VvApi.sendMsg(player, "请先到土城参加跑酷活动。")
return false
end
local name = VvApi.getPlayerName(player)
VvApi.setVar(key(name, "active"), 1)
VvApi.setVar(key(name, "start"), VvApi.now())
VvApi.setVar(key(name, "next"), 1)
local x, y = VvApi.getPos(player)
VvApi.setVar(key(name, "lastx"), x)
VvApi.setVar(key(name, "lasty"), y)
VvApi.sendMsg(player, "土城跑酷开始,请按顺序踩完所有检查点。")
return true
end
function Parkour.onCheckpoint(player, checkpointIndex)
local name = VvApi.getPlayerName(player)
if VvApi.getVar(key(name, "active"), 0) ~= 1 then
return false
end
local startTime = VvApi.getVar(key(name, "start"), 0)
local usedTime = VvApi.now() - startTime
if usedTime > Parkour.config.timeLimit then
VvApi.setVar(key(name, "active"), 0)
VvApi.teleport(player, Parkour.config.mapId, Parkour.config.startPos.x, Parkour.config.startPos.y)
VvApi.sendMsg(player, "跑酷超时,挑战失败。")
return false
end
local nextIndex = VvApi.getVar(key(name, "next"), 1)
if checkpointIndex ~= nextIndex then
VvApi.sendMsg(player, "检查点顺序错误,请回到正确路线。")
return false
end
local lastPos = {
x = VvApi.getVar(key(name, "lastx"), 0),
y = VvApi.getVar(key(name, "lasty"), 0),
}
local x, y = VvApi.getPos(player)
local nowPos = { x = x, y = y }
if distance(lastPos, nowPos) > Parkour.config.maxStepDistance then
VvApi.setVar(key(name, "active"), 0)
VvApi.sendMsg(player, "移动距离异常,本次跑酷已取消。")
return false
end
VvApi.setVar(key(name, "lastx"), x)
VvApi.setVar(key(name, "lasty"), y)
VvApi.setVar(key(name, "next"), nextIndex + 1)
if nextIndex < #Parkour.config.checkpoints then
VvApi.sendMsg(player, "通过检查点 " .. nextIndex .. "/" .. #Parkour.config.checkpoints)
return true
end
VvApi.setVar(key(name, "active"), 0)
for _, reward in ipairs(Parkour.config.rewards) do
if usedTime <= reward.maxTime then
VvApi.addItem(player, reward.item, reward.count)
break
end
end
VvApi.sendMsg(player, "跑酷完成,用时 " .. usedTime .. " 秒。")
return true
end
return Parkour
|
|