课时 25 · 任务系统

课时 25 · 任务系统(功能开发实战):实现带进度与奖励的任务流程。示例跑在 996 新三端引擎里,接口按本地官方文档逐个核对。

教程/第四部分 · 功能开发实战更新于 2026-10-073 个小节 教程第 30 / 41 篇 功能实战

本课的代码跑在 996 引擎里,用到的是服务端接口(changeexp、 SetInt 这类),在线运行器里没有这些函数。 每个函数的签名都能在 文档检索 里按名字查到原文。

本课目标

  • 实现带进度与奖励的任务流程。

知识讲解

需求:三环任务「打怪收集材料」——每环杀指定怪物收集指定数量材料,完成后进入下一环,三环完成发放奖励。关键点:进度存储(玩家变量,跨登录保留)、杀怪触发推进进度、完成判定、防重复领取。

进度存储建议:用玩家变量(本地文档 接口 目录中「变量」相关接口)按「任务ID_环数_数量」命名,登录时可恢复;每环完成时写入下一环初始状态,全部完成时清除并标记已领奖。

示例:三环任务(核心)

local TASK = {
    { mon = '红狼', need = 10, reward = '铁矿石' },
    { mon = '灰狼', need = 10, reward = '精铁' },
    { mon = '狼王', need = 5,  reward = '狼王宝箱' },
}

-- 杀怪触发:推进当前环进度
function getexpbykillmon(actor, killer, mon, exp)
    -- 0=玩家变量(接口/变量相关/获取对象int型变量)
    local ring = GetInt(0, actor, 'task_ring') or 1   -- 当前环
    local cfg = TASK[ring]
    if not cfg then return end
    -- nID=1 取对象名称,param3=0 取怪物显示名(接口/对象通用/获取人物_怪物相关信息)
    local monName = getbaseinfo(mon, 1, 0)
    if monName ~= cfg.mon then return end

    local cur = (GetInt(0, actor, 'task_cnt') or 0) + 1
    SetInt(0, actor, 'task_cnt', cur)
    if cur >= cfg.need then
        -- 本环完成
        if ring >= #TASK then
            giveitem(actor, cfg.reward, 1)
            sendmsg(actor, 1, '{"Msg":"任务完成!获得 ' .. cfg.reward .. '","Type":1}')
            SetInt(0, actor, 'task_done', 1)   -- 防重复
        else
            SetInt(0, actor, 'task_ring', ring + 1)
            SetInt(0, actor, 'task_cnt', 0)
            sendmsg(actor, 1, '{"Msg":"进入第 ' .. (ring + 1) .. ' 环","Type":1}')
        end
    end
end

说明:变量读写用 SetInt/GetInt(0=玩家,接口/变量相关);怪物名用 getbaseinfo(mon, 1, 0)(接口/对象通用)。killmon 触发本身也直接给 monName 参数,两条路都行。

练习任务

  • 完成三环任务完整版:① 任务接受入口(NPC 点击触发);② 进度跨登录保存(登录时从存档恢复);③ 已完成任务防重复领取(task_done 判断);④ 每环完成有明确提示。

参考:验收要点

  • 杀怪计数只在目标怪物死亡时 +1;
  • 三环进度连续推进,环间提示正确;
  • 下线重登后进度不丢失;
  • 完成后再次点击任务 NPC 提示「已完成」且不再发奖。
本篇依据
  • 《996 新三端 Lua 开发教学技术手册》课时 25

参数与取值以你本机版本的官方帮助文档为准,不同版本之间有过调整。