bayuMIR/Mirserver/Mir200/Envir/QuestDiary/游戏功能/A0_通用类/MainLineTask.lua
2026-06-21 21:55:53 +08:00

440 lines
No EOL
14 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

MainLineTaskOBJ = {}
MainLineTaskOBJ._name = "MainLineTaskOBJ"
MainLineTaskOBJ.STATUS_WAIT_VISIT = 0
MainLineTaskOBJ.STATUS_DOING = 1
MainLineTaskOBJ.STATUS_FINISH = 9
MainLineTaskOBJ.cfg = {
[1] = {
id = 1,
next = 2,
enabled = true,
title = "[主线]了解首充",
desc = "了解首充后前往任意地图击杀任意怪物5只。",
doingDesc = "前往任意地图击杀任意怪物。",
rewardText = "经验100万、金币5000",
visit = { type = "module", keys = { "ShouChongOBJ" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "money", "经验", 1000000 }, { "money", "金币", 5000 } },
},
[2] = {
id = 2,
next = 3,
enabled = true,
title = "[主线]拜访渡劫天尊",
desc = "拜访渡劫天尊后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "经验100万、金币10000",
visit = { type = "npc", ids = { 6 }, scripts = { "转生" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "money", "经验", 1000000 }, { "money", "金币", 10000 } },
},
[3] = {
id = 3,
next = 4,
enabled = true,
title = "[主线]拜访神兽淬体",
desc = "拜访神兽淬体后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "神兽之血*50、神兽之骨*50",
visit = { type = "npc", ids = { 5 }, scripts = { "神兽淬体" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "item", "神兽之血", 50, 0 }, { "item", "神兽之骨", 50, 0 } },
},
[4] = {
id = 4,
next = 5,
enabled = true,
title = "[主线]拜访紫金仙人",
desc = "拜访紫金仙人后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "经验100万、千年玄石*50、金币10000",
visit = { type = "npc", ids = { 189 }, scripts = { "紫金葫芦" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "money", "经验", 1000000 }, { "item", "千年玄石", 50, 0 }, { "money", "金币", 10000 } },
},
[5] = {
id = 5,
next = 6,
enabled = true,
title = "[主线]了解绝学NPC",
desc = "了解绝学NPC后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "灵石*50、武林秘籍*1",
visit = { type = "npc", ids = { 12 }, scripts = { "绝学修炼" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "item", "灵石", 50, 0 }, { "item", "武林秘籍", 1, 0 } },
},
[6] = {
id = 6,
next = 7,
enabled = true,
title = "[主线]拜访幸运仙子",
desc = "拜访幸运仙子后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "经验100万、金币10000",
visit = { type = "npc", ids = { 11 }, scripts = { "幸运项链" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "money", "经验", 1000000 }, { "money", "金币", 10000 } },
},
[7] = {
id = 7,
next = 8,
enabled = true,
title = "[主线]前往装备重铸",
desc = "前往装备重铸后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "经验100万、金币10000",
visit = { type = "npc", ids = { 10 }, scripts = { "装备重铸" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "money", "经验", 1000000 }, { "money", "金币", 10000 } },
},
[8] = {
id = 8,
next = 9,
enabled = true,
title = "[主线]前往武器升级",
desc = "前往武器升级后前往任意地图击杀怪物5只。",
doingDesc = "前往任意地图击杀怪物。",
rewardText = "黑铁矿石*4、金币10000",
visit = { type = "npc", ids = { 13 }, scripts = { "武器升级" } },
target = { type = "kill_mon", count = 5, map = "*", mon = "*" },
rewards = { { "item", "黑铁矿石", 4, 0 }, { "money", "金币", 10000 } },
},
[9] = {
id = 9,
next = nil,
enabled = true,
title = "[主线]任务结束",
desc = "主线任务已完成。",
doingDesc = "主线任务已完成。",
rewardText = "",
visit = nil,
target = nil,
rewards = {},
finish = true,
},
}
function MainLineTaskOBJ:getTask(id)
return self.cfg[tonumber(id or 1)]
end
function MainLineTaskOBJ:setTask(id, cfg)
if not id or not cfg then
return false
end
cfg.id = tonumber(id)
self.cfg[tonumber(id)] = cfg
return true
end
function MainLineTaskOBJ:deleteTask(id)
id = tonumber(id)
if not id then
return false
end
self.cfg[id] = nil
return true
end
function MainLineTaskOBJ:getValidTask(id)
id = tonumber(id)
if not id then
return nil
end
local task = self:getTask(id)
local guard = 0
while task and task.enabled == false and task.next and guard < 100 do
task = self:getTask(task.next)
guard = guard + 1
end
return task
end
function MainLineTaskOBJ:getTaskId(actor)
local id = Player.getint(actor, VarCfg.Player.int["主线任务ID"]) or 0
if id <= 0 then
id = 1
self:setState(actor, id, self.STATUS_WAIT_VISIT, 0)
end
local task = self:getValidTask(id)
if task and task.id ~= id then
id = task.id
local status = task.finish and self.STATUS_FINISH or self.STATUS_WAIT_VISIT
self:setState(actor, id, status, 0)
elseif not task then
id = 9
self:setState(actor, id, self.STATUS_FINISH, 0)
end
return id
end
function MainLineTaskOBJ:getStatus(actor)
return Player.getint(actor, VarCfg.Player.int["主线任务状态"]) or self.STATUS_WAIT_VISIT
end
function MainLineTaskOBJ:getProgress(actor)
return Player.getint(actor, VarCfg.Player.int["主线任务进度"]) or 0
end
function MainLineTaskOBJ:setState(actor, id, status, progress)
Player.setint(actor, VarCfg.Player.int["主线任务ID"], id)
Player.setint(actor, VarCfg.Player.int["主线任务状态"], status)
Player.setint(actor, VarCfg.Player.int["主线任务进度"], progress or 0)
end
function MainLineTaskOBJ:contains(list, value)
if not list then
return false
end
for _, v in ipairs(list) do
if tostring(v) == tostring(value) then
return true
end
end
return false
end
function MainLineTaskOBJ:visitMatched(task, visitKey, npcID, sScript)
if not task or not task.visit then
return false
end
local visit = task.visit
if visit.type == "module" then
return self:contains(visit.keys, visitKey)
end
if visit.type == "npc" then
return self:contains(visit.ids, npcID) or self:contains(visit.scripts, sScript)
end
return false
end
function MainLineTaskOBJ:getRewardView(task)
local itemRewards = {}
local moneyRewards = {}
for _, reward in ipairs((task and task.rewards) or {}) do
local rtype = reward[1]
local name = reward[2]
local num = tonumber(reward[3]) or 0
local bind = tonumber(reward[4]) or 0
if name and num > 0 then
if rtype == "item" then
table.insert(itemRewards, { name = name, count = num, bind = bind, type = rtype })
elseif rtype == "money" then
table.insert(itemRewards, { name = name, count = num, bind = 0, type = rtype })
table.insert(moneyRewards, { name = name, count = num })
end
end
end
return itemRewards, moneyRewards
end
function MainLineTaskOBJ:getTaskView(actor)
local id = self:getTaskId(actor)
local task = self:getValidTask(id)
if not task then
task = self.cfg[9]
id = 9
self:setState(actor, id, self.STATUS_FINISH, 0)
end
local status = self:getStatus(actor)
local progress = self:getProgress(actor)
local target = task and task.target or nil
local need = target and target.count or 0
if task and task.finish then
status = self.STATUS_FINISH
progress = 0
need = 0
end
local statusText = "待拜访"
local desc = task and task.desc or ""
if status == self.STATUS_DOING then
statusText = "进行中"
desc = task.doingDesc or desc
elseif status == self.STATUS_FINISH or (task and task.finish) then
statusText = "已完成"
desc = task.desc or "主线任务已完成。"
end
local rewardItems, rewardMoneys = self:getRewardView(task)
return {
id = task and task.id or id,
title = task and task.title or "[主线]任务",
desc = desc,
status = status,
statusText = statusText,
progress = progress,
need = need,
rewardText = task and task.rewardText or "",
rewardItems = rewardItems,
rewardMoneys = rewardMoneys,
finish = task and task.finish and true or false,
}
end
function MainLineTaskOBJ:sync(actor)
if not isnotnull(actor) then
return
end
if self:tryCompleteReady(actor) then
return
end
Message:SubLink(actor, self._name .. "_sync", self:getTaskView(actor))
end
function MainLineTaskOBJ:startTask(actor, task)
self:setState(actor, task.id, self.STATUS_DOING, 0)
Func.sendmsg9(actor, string.format("[主线任务]:#70|已接取:%s", task.title))
self:sync(actor)
end
function MainLineTaskOBJ:onVisit(actor, visitKey)
local id = self:getTaskId(actor)
local task = self:getValidTask(id)
if not task or task.finish or self:getStatus(actor) ~= self.STATUS_WAIT_VISIT then
self:sync(actor)
return
end
if self:visitMatched(task, visitKey, nil, nil) then
self:startTask(actor, task)
else
self:sync(actor)
end
end
function MainLineTaskOBJ:onVisitNpc(actor, npcID, sScript)
local id = self:getTaskId(actor)
local task = self:getValidTask(id)
if not task or task.finish or self:getStatus(actor) ~= self.STATUS_WAIT_VISIT then
self:sync(actor)
return
end
if self:visitMatched(task, nil, npcID, sScript) then
self:startTask(actor, task)
else
self:sync(actor)
end
end
function MainLineTaskOBJ:giveItemRewards(actor, items)
if #items <= 0 then
return
end
local itemStrs = {}
for _, item in ipairs(items) do
table.insert(itemStrs, string.format("%s#%s#%s", item[1], item[2], item[3] or 0))
end
gives(actor, table.concat(itemStrs, "&"), "主线任务")
end
function MainLineTaskOBJ:giveRewards(actor, rewards)
local items = {}
for _, reward in ipairs(rewards or {}) do
local rtype = reward[1]
local name = reward[2]
local num = tonumber(reward[3]) or 0
local bind = tonumber(reward[4]) or 0
if rtype == "money" then
local moneyId = ConstCfg.sysMoney[name]
if moneyId and num > 0 then
changemoney(actor, moneyId, "+", num, "主线任务", true)
end
elseif rtype == "item" and name and num > 0 then
table.insert(items, { name, num, bind })
end
end
self:giveItemRewards(actor, items)
end
function MainLineTaskOBJ:completeTask(actor, task)
self:giveRewards(actor, task.rewards)
Func.sendmsg9(actor, string.format("[主线任务]:#70|完成%s奖励已发放。", task.title))
local nextTask = self:getValidTask(task.next)
if nextTask then
if nextTask.finish then
self:setState(actor, nextTask.id, self.STATUS_FINISH, 0)
else
self:setState(actor, nextTask.id, self.STATUS_WAIT_VISIT, 0)
end
else
self:setState(actor, 9, self.STATUS_FINISH, 0)
end
self:sync(actor)
end
function MainLineTaskOBJ:tryCompleteReady(actor)
if self:getStatus(actor) ~= self.STATUS_DOING then
return false
end
local id = self:getTaskId(actor)
local task = self:getValidTask(id)
if not task or not task.target or task.target.type ~= "kill_mon" then
return false
end
local need = tonumber(task.target.count) or 0
if need > 0 and self:getProgress(actor) >= need then
Player.setint(actor, VarCfg.Player.int["主线任务进度"], need)
self:completeTask(actor, task)
return true
end
return false
end
function MainLineTaskOBJ:onKillMon(actor, mon, itype, kill, monName, mapID)
if self:getStatus(actor) ~= self.STATUS_DOING then
return
end
local id = self:getTaskId(actor)
local task = self:getValidTask(id)
if not task or not task.target or task.target.type ~= "kill_mon" then
return
end
local target = task.target
if target.map and target.map ~= "*" and tostring(target.map) ~= tostring(mapID) then
return
end
if target.mon and target.mon ~= "*" and tostring(target.mon) ~= tostring(monName) then
return
end
local need = tonumber(target.count) or 0
local progress = self:getProgress(actor) + 1
if progress >= need then
Player.setint(actor, VarCfg.Player.int["主线任务进度"], need)
self:completeTask(actor, task)
else
Player.setint(actor, VarCfg.Player.int["主线任务进度"], progress)
self:sync(actor)
end
end
GameEvent.add(EventCfg.onLogin, function(actor)
MainLineTaskOBJ:sync(actor)
end, MainLineTaskOBJ)
GameEvent.add(EventCfg.onqfloadend, function(actor)
MainLineTaskOBJ:sync(actor)
end, MainLineTaskOBJ)
GameEvent.add(EventCfg.onKillMon, function(actor, mon, itype, kill, monName, mapID)
MainLineTaskOBJ:onKillMon(actor, mon, itype, kill, monName, mapID)
end, MainLineTaskOBJ)
MainLineTaskOBJ.allowFunc = { "query", "visit" }
function MainLineTaskOBJ:query(actor)
self:sync(actor)
end
function MainLineTaskOBJ:visit(actor, p1, p2, p3, data)
local visitKey = p1
if type(data) == "table" then
visitKey = data[1] or data.visitKey or visitKey
end
if visitKey then
self:onVisit(actor, visitKey)
else
self:sync(actor)
end
end
return MainLineTaskOBJ