MainLineTaskOBJ = {} MainLineTaskOBJ._name = "MainLineTaskOBJ" MainLineTaskOBJ.STATUS_WAIT_VISIT = 0 MainLineTaskOBJ.STATUS_DOING = 1 MainLineTaskOBJ.STATUS_FINISH = 9 MainLineTaskOBJ.cfg = Func.require("cfg_主线任务") local function appendCfgValue(list, value) if value == nil or value == "" or tonumber(value) == 0 then return end table.insert(list, value) end local function normalizeTaskCfg(cfg) for id, task in pairs(cfg or {}) do task.id = tonumber(task.id or id) or id if not task.visit and task.visit_type and task.visit_type ~= "" then local visit = { type = task.visit_type } if visit.type == "module" then visit.keys = {} appendCfgValue(visit.keys, task.visit_keys_1) if #visit.keys <= 0 and task.ShouChongOBJ ~= nil then table.insert(visit.keys, "ShouChongOBJ") end if #visit.keys <= 0 and task.visit_open and task.visit_open ~= "" then table.insert(visit.keys, string.gsub(task.visit_open, "_main$", "")) end if task.visit_open and task.visit_open ~= "" then visit.open = task.visit_open end elseif visit.type == "npc" then visit.ids = {} appendCfgValue(visit.ids, task.visit_ids_1) visit.scripts = {} appendCfgValue(visit.scripts, task.visit_scripts_1) end task.visit = visit end if not task.target and task.target_type and task.target_type ~= "" then task.target = { type = task.target_type, count = tonumber(task.target_count) or 0, map = task.target_map, mon = task.target_mon, } end if not task.rewards then task.rewards = {} for _, reward in ipairs(task.reward or {}) do table.insert(task.rewards, { reward.type, reward.name, tonumber(reward.num) or 0, tonumber(reward.bind) or 0, }) end end end return cfg end MainLineTaskOBJ.cfg = normalizeTaskCfg(MainLineTaskOBJ.cfg) 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", "route" } function MainLineTaskOBJ:query(actor) self:sync(actor) end function MainLineTaskOBJ:route(actor) if not isnotnull(actor) then return end if self:getStatus(actor) ~= self.STATUS_WAIT_VISIT then return end local id = self:getTaskId(actor) local task = self:getValidTask(id) if not task or task.finish or not task.visit then return end local visit = task.visit if visit.type == "module" and visit.open then Message:SubLink(actor, visit.open) return end if visit.type == "npc" and visit.ids and visit.ids[1] then opennpcshowex(actor, tonumber(visit.ids[1]), 6, 2) end 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