local Passive = require "adv.AdvPassive" local AdvCommon = require "adv.AdvCommon" local AdvMap = require "adv.AdvMap" local Buff = require "adv.AdvBuff" local Adv = class("Adv") local AdvTask = import(".AdvTask") --任务相关数据搞出去 AdvTask.bind(Adv) function Adv:ctor(owner) assert(owner, "Adv instance must have owner(role)") self.owner = owner self.maps = {} self.shopStatus = {} self.battle = nil self.backEvents = {} --发给客户端的事件组 self.advTask = self.owner:getProperty("advTask") self.advMTask = self.owner:getProperty("advMTask") self.advTaskChange = false -- 任务改变才更新 end function Adv:mylog(contents) contents = contents or {} if contents["cint1"] or contents["cint2"] or contents["cint3"] then print("advLog error log have cint1 or cint2 or cint3 ", debug.traceback()) end contents["cint1"] = self.chapterId contents["cint2"] = self.level self.owner:mylog("adv_action", contents) end --初始化adv 信息 function Adv:initByInfo() local advInfo = self.owner:getProperty("advInfo") if not next(advInfo) then return end --还没有 开始新地图 self.chapterId = advInfo.chapterId self.level = advInfo.level or 1 self.round = advInfo.round or 0 self.score = advInfo.score or {} self.isRelay = advInfo.isRelay self.lastEnemyId = advInfo.lastEId or 1 self.mapStack = advInfo.mstack or {} self.lchoose = advInfo.lch or {} self.waitArtifact = advInfo.waitAF self.cacheUnlock = advInfo.cacheUnlock or {} self.shopStatus = advInfo.shopStatus or {} self.support = advInfo.support or {} self.logid = advInfo.logid or "auto" self.maps = {} for id, map in ipairs(advInfo.maps or {}) do self.maps[id] = AdvMap.new(self, id, map) end self:initBattle(advInfo) end -- 找出level 是否存在中继层 function Adv:isHaveRelay(level, chapterId, force) level = level or self.level chapterId = chapterId or self.chapterId if level == 1 and not force then return end local campsiteCsv = csvdb["adv_chapter_campsiteCsv"][chapterId] for _, campsite in ipairs(campsiteCsv) do if campsite.floor == level then return campsite end end return nil end -- 随机新的地图 function Adv:initByChapter(params) local chapterId = params.chapterId local level = params.level local isToNext = params.isToNext local notNotify = params.notNotify local isRelay = params.isRelay local isEnter = params.isEnter local support = params.support local debugMapId = params.debugMapId if not self.chapterId then -- 开始新的章节 self.chapterId = chapterId self:checkAchievement(Adv.AchievType.StartBattle, 1) elseif chapterId ~= self.chapterId then -- 正常不会出现 return end self.level = level or 1 self.round = 0 self.score = self.score or {} self.lastEnemyId = 1 self.mapStack = {1} -- 最后一个为当前的地图 self.lchoose = self.lchoose or {} self.cacheUnlock = self.cacheUnlock or {} self.shopStatus = self.shopStatus or {} self.support = self.support or {} if self.battle then self.battle:overBattle() end self.battle = nil -- 清掉 老的 battle self.logid = self.owner:getActionUcode() if isEnter then -- 把 支援效果初始化为易用用的形式 self:initSupport(support or {}) self.owner:setProperty("advLimit", {}) -- 清掉 Limit end -- 随机出地图 local mapId, relayData if debugMapId and csvdb["mapCsv"][debugMapId] then mapId = debugMapId end if not mapId then if isRelay then relayData = self:isHaveRelay(level, chapterId) if relayData then mapId = relayData.map else isRelay = false mapId = self:randomMapId(chapterId, level) end else mapId = self:randomMapId(chapterId, level) end end self.isRelay = isRelay local isNewRelay = false if self.isRelay then -- 中继层 local advRelay = self.owner:getProperty("advRelay") local chapter = self:isEndless() and -1 or self.chapterId if not (advRelay[chapter] or {})[self.level] then isNewRelay = true end end if self.level == 1 or self.isRelay then self:supplyPotion() end self.maps = {} self.maps[1] = AdvMap.new(self, 1, mapId, isEnter, isNewRelay) self:initBattle(nil, isToNext) self:initLayerTask() self:checkTask(Adv.TaskType.Arrive) self:checkAdvUnlock(1, self.level) -- 中继进入奖励 if relayData and isEnter then self:awardRelay(relayData, notNotify) end if not notNotify then self:saveDB(notNotify) end end function Adv:passAdvRelay() local advRelay = self.owner:getProperty("advRelay") local chapter = self:isEndless() and -1 or self.chapterId if not (advRelay[chapter] or {})[self.level] then advRelay[chapter] = advRelay[chapter] or {} advRelay[chapter][self.level] = 1 self.owner:updateProperty({field = "advRelay", value = advRelay}) local relayData = self:isHaveRelay() if relayData and relayData.award ~= "" then self:pushBackEvent(AdvBackEventType.RelayReward, {items = self:award(relayData.award:toNumMap(), {log = {desc = "relayReward"}})}) end end end function Adv:clear() self.chapterId = nil self.level = nil self.score = {} self.round = 0 self.lastEnemyId = 1 self.mapStack = {} self.lchoose = {} self.maps = {} self.battle = nil self.waitArtifact = nil self.isRelay = nil self.cacheUnlock = {} self.shopStatus = {} self.support = {} end function Adv:saveDB(notNotify) local advInfo, advTeam = {}, self.owner:getProperty("advTeam") if self:isRunning() then advInfo.chapterId = self.chapterId advInfo.level = self.level advInfo.round = self.round advInfo.score = self.score advInfo.isRelay = self.isRelay advInfo.lastEId = self.lastEnemyId advInfo.mstack = self.mapStack advInfo.lch = self.lchoose advInfo.waitAF = self.waitArtifact advInfo.cacheUnlock = self.cacheUnlock advInfo.shopStatus = self.shopStatus advInfo.support = self.support advInfo.logid = self.logid advInfo.maps = {} self.battle:saveDB(advInfo) for id , map in ipairs(self.maps) do advInfo.maps[id] = map:getDB() end advTeam.player = self.battle.player:getDB() else advTeam.player = nil end self:updateTask(notNotify) self:updateAchievement(notNotify) self.owner:updateProperties({advInfo = advInfo, advTeam = advTeam}, notNotify) end function Adv:awardRelay(relayData, notNotify) local gift = {} if relayData.artifact > 0 then local pool = {} for id, temp in pairs(csvdb["adv_artifactCsv"]) do if not self:isHaveArtifact(id) and self.owner:isArtifactOpen(id, self:isEndless()) then table.insert(pool, id) end end for i = 1, math.min(relayData.artifact, #pool) do local idx = math.randomInt(1, #pool) gift[pool[idx]] = 1 table.remove(pool, idx) end end if relayData.point > 0 then gift[ItemId.AdvPoint] = relayData.point end if relayData.otherAward ~= "" then for dropId, count in pairs(relayData.otherAward:toNumMap()) do for i = 1, count do local dropData = csvdb["event_dropCsv"][dropId] if dropData then local item = dropData["range"]:randWeight(true) gift[item[1]] = (gift[item[1]] or 0) + item[2] else skynet.error(string.format("[ERROR]: event_dropCsv no id %s, adv_chapter_campsite", dropId)) end end end end self:award(gift, {notNotify = notNotify, log = {desc = "relayEnter", int1 = self.chapterId, int2 = self.level}}) end function Adv:initSupport(supports) self.support = {} local supportEffect = {} -- 获得道具 1=道具id=道具数量 supportEffect[1] = function(_, itemId, num) self.support[1] = self.support[1] or {} self.support[1][itemId] = (self.support[1][itemId] or 0) + num end -- 获得mapbuff 2=mapbuffid supportEffect[2] = function(_, buffId) self.support[2] = self.support[2] or {} table.insert(self.support[2], buffId) end -- 获得mappassive 3=mappassive supportEffect[3] = function(_, passiveId) self.support[3] = self.support[3] or {} table.insert(self.support[3], passiveId) end -- 首层额外刷新 4=类型=id=数量(类型1=choose/2=building/3=click/4=drop/5=shop) supportEffect[4] = function(_, etype, id, num) self.support[4] = self.support[4] or {} self.support[4][etype] = self.support[4][etype] or {} self.support[4][etype][id] = (self.support[4][etype][id] or 0) + num end -- 每层额外刷新 5=类型=id=数量(类型1=choose/2=building/3=click/4=drop/5=shop) supportEffect[5] = function(_, etype, id, num) self.support[5] = self.support[5] or {} self.support[5][etype] = self.support[5][etype] or {} self.support[5][etype][id] = (self.support[5][etype][id] or 0) + num end -- 获得随机神器 6=数量 supportEffect[6] = function(_, num) self.support[6] = (self.support[6] or 0) + num end -- 获得3选1神器 7=选择次数(连续选择,每次选择重新随机) supportEffect[7] = function(_, num) self.support[7] = (self.support[7] or 0) + num end for _, supportId in ipairs(supports) do local supportData = csvdb["adv_supportCsv"][supportId] for _, effect in ipairs(supportData.effect:toArray()) do local cur = effect:toArray(true, "=") if supportEffect[cur[1]] then supportEffect[cur[1]](table.unpack(cur)) end end end end function Adv:activeSomeSupport() -- 奖励物品 if self.support[1] then self:award(self.support[1], {log = {desc = "support"}}) self.support[1] = nil end -- 加buff if self.support[2] then for _, buffId in ipairs(self.support[2]) do self.battle.player:addBuff(buffId) end self.support[2] = nil end --加被动技 if self.support[3] then for _, passiveId in ipairs(self.support[3]) do self.battle.player:addPassive({id = passiveId}) end self.support[3] = nil end -- 加随机神器 if self.support[6] then local pool = {} for id, temp in pairs(csvdb["adv_artifactCsv"]) do if not self:isHaveArtifact(id) and self.owner:isArtifactOpen(id, self:isEndless()) then table.insert(pool, id) end end for i = 1, math.min(self.support[6], #pool) do local idx = math.randomInt(1, #pool) self:award({[pool[idx]] = 1}, {log = {desc = "support"}}) table.remove(pool, idx) end self.support[6] = nil end self:supportChooseArtifact() end function Adv:supportChooseArtifact() -- 加 三选一 神器 if self.support[7] then if self.support[7] > 0 then self:waitChooseArtifact() end self.support[7] = self.support[7] - 1 if self.support[7] <= 0 then self.support[7] = nil end end end function Adv:supportFirstLayerAddEvent() if self.support[4] then local temp = self.support[4] self.support[4] = nil return temp end end function Adv:supportEveryLayerAddEvent() return self.support[5] end function Adv:isRunning() if self.chapterId then return true end return false end -- 强制结束 逻辑和adv内部无关 function Adv:forceOver(notNotify, force) if self:isRunning() or force then local advTeam = self.owner:getProperty("advTeam") advTeam.player = nil local advPotionCsv = csvdb["adv_potionCsv"] local potionBag = self.owner:getProperty("potionBag") local reward = self.owner:getProperty("advItems"):toNumMap() for itemId, count in pairs(reward) do if advPotionCsv[itemId] then potionBag[itemId] = (potionBag[itemId] or 0) + count else reward[itemId] = math.ceil(count * globalCsv.adv_fail_reward_ratio / 100) -- 奖励相当于失败 end end self.owner:award(reward, {log = {desc = "advOver", int1 = self.chapterId}, notNotify = notNotify}) self:clear() self.owner:updateProperties({ advInfo = {}, advTeam = advTeam, advItems = "", advAFGet = {}, advAFWear = {}, potionBag = potionBag, }, notNotify) end end -- 1=抵达x层;2=通关x层;3=完成指定事件;4=完成指定连锁事件 function Adv:checkAdvUnlock(utype, value) if not self.chapterId then return end local chapter = self.chapterId % 100 local reward = {} for id, data in pairs(csvdb["adv_unlockCsv"]) do if data.chapterid == chapter and data.type == utype and value == data.value then --0=立即获得;1=结算时获得 if data.time == 0 then reward[data.itemid] = 1 elseif data.time == 1 then table.insert(self.cacheUnlock, data.itemid) end end end if next(reward) then self.owner:award(reward, {log = {desc = "advUnlock", int1 = self.chapterId}}) end end function Adv:clearAdvUnlockCache() local reward = {} for _, itemId in ipairs(self.cacheUnlock) do reward[itemId] = 1 end if next(reward) then self.owner:award(reward, {log = {desc = "advUnlock", int1 = self.chapterId}}) end self.cacheUnlock = {} end function Adv:initBattle(info, isToNext) self.battle = require("adv.AdvBattle").new(self) -- 支援效果生效一些 self:activeSomeSupport() -- 不是中继层 加上 层 和 地图的buff和被动 if not self.isRelay then self.battle:initMapEffect() end if isToNext then self.battle.player:afterLayer() -- 玩家的buff 清理一下 end for _, passiveC in ipairs(self.cachePassiveEvent or {}) do self.battle:triggerPassive(passiveC[1], passiveC[2]) end self.cachePassiveEvent = {} -- after init battle for idx, map in pairs(self.maps) do map:initBattleAfter() end --下层 if not info and isToNext then self.battle.player:attrChangeCondBuffCheck(1) end -- 初始化 if not info then self.battle:newBattle() else self.battle:loadBattle(info) end end function Adv:triggerPassive(condType, params) self.cachePassiveEvent = self.cachePassiveEvent or {} if not self.battle then table.insert(self.cachePassiveEvent, {condType, params}) else self.battle:triggerPassive(condType, params) end end function Adv:getCurMap() return self.maps[self.mapStack[#self.mapStack]] end function Adv:getCurMapIdx() return self.mapStack[#self.mapStack] end function Adv:getRoom(roomId, mapIdx) mapIdx = mapIdx or self:getCurMapIdx() local map = self.maps[mapIdx] if map then return map.rooms[roomId] end end function Adv:getBlock(roomId, blockId, mapIdx) local room = self:getRoom(roomId, mapIdx) if room then return room.blocks[blockId] end end function Adv:isHaveArtifact(id) return self.owner:getProperty("advAFGet")[id] end function Adv:awardArtifact(id, params) if self:isHaveArtifact(id) then return end self.owner:changeUpdates({{type = "advAFGet", field = id, value = 1}}, params.notNotify) self:checkAchievement(Adv.AchievType.GetMWeapon, 1, id) if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] then print("awardArtifact error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = self.chapterId log["cint2"] = self.level log["cint3"] = id self.owner:mylog("in_artifact", log) else print("awardArtifact no log ", debug.traceback()) end if not params.isChoose then self:pushBackEvent(AdvBackEventType.Artifact, {id = id}) end end function Adv:addArtifactEffect(effect) for _, eff in ipairs(effect:toArray()) do local etype, id = table.unpack(eff:toArray(true, "=")) if etype == 1 then self.battle.player:addPassive({id = id}) elseif etype == 2 then self.battle.player:addBuff(id) end end end function Adv:delArtifactEffect(effect) for _, eff in ipairs(effect:toArray()) do local etype, id = table.unpack(eff:toArray(true, "=")) if etype == 1 then self.battle.player:delPassiveById(id) elseif etype == 2 then self.battle.player:delBuffById(id) end end end function Adv:wearArtifact(slot, id) local advAFGet = self.owner:getProperty("advAFGet") local advAFWear = self.owner:getProperty("advAFWear") if id == -1 then if not advAFWear[slot] then return end else if not advAFGet[id] then return end end local curWear = {} for _, _id in pairs(advAFWear) do curWear[_id] = 1 end if curWear[id] then return end if advAFWear[slot] then local oldData = csvdb["adv_artifactCsv"][advAFWear[slot]][advAFGet[advAFWear[slot]]] self:delArtifactEffect(oldData.effect) if oldData.comboId ~= 0 then local comboData = csvdb["adv_artifact_comboCsv"][oldData.comboId] if comboData then local isHaveCombo = true for _, _id in ipairs(comboData.artifactid:toArray(true)) do if not curWear[_id] then isHaveCombo = false break end end if isHaveCombo then self:delArtifactEffect(comboData.effect) end end end curWear[advAFWear[slot]] = nil end if id ~= -1 then curWear[id] = 1 local newData = csvdb["adv_artifactCsv"][id][advAFGet[id]] self:addArtifactEffect(newData.effect) if newData.comboId ~= 0 then local comboData = csvdb["adv_artifact_comboCsv"][newData.comboId] if comboData then local isHaveCombo = true for _, _id in ipairs(comboData.artifactid:toArray(true)) do if not curWear[_id] then isHaveCombo = false break end end if isHaveCombo then self:addArtifactEffect(comboData.effect) end end end else id = nil end self:mylog({desc = "wearArtifact", int1 = id}) self.owner:log("mission_pick_equip", { mission_threadid = self.chapterId, -- 大地图ID mission_threadname = (csvdb["adv_chapterCsv"][self.chapterId] or {})["chapter"] or "auto", -- 大地图名称 mission_id = self.level, -- 关卡ID mission_pick_equip_type = 1, --神器操作类型:1:装备,2:卸下 mission_pick_equip_id = id, --神器ID mission_pick_equip_lv = advAFGet[id], --神器等级 mission_sequenceid = self.logid, -- 本次拾荒ID,用于关联一次拾荒产生多条不同类型的日志 }) self.owner:changeUpdates({{type = "advAFWear", field = slot, value = id}}) return true end -- 是否穿着指定神器 function Adv:isWearAF(id) local advAFWear = self.owner:getProperty("advAFWear") for _, _id in pairs(advAFWear) do if _id == id then return true end end return false end --是否激活指定神器套装 function Adv:haveComboAF(id) local advAFGet = self.owner:getProperty("advAFGet") local advAFWear = self.owner:getProperty("advAFWear") local curWear = {} for _, _id in pairs(advAFWear) do curWear[_id] = 1 end for _, _id in pairs(advAFWear) do local afData = csvdb["adv_artifactCsv"][_id][advAFGet[_id]] if afData.comboId == id then local comboData = csvdb["adv_artifact_comboCsv"][afData.comboId] if comboData then for _, _id2 in ipairs(comboData.artifactid:toArray(true)) do if not curWear[_id2] then return false end end return true end return false end end return false end function Adv:artifactLevelUp(id, level) level = level or 1 local advAFGet = self.owner:getProperty("advAFGet") if not advAFGet[id] then return end local advAFWear = self.owner:getProperty("advAFWear") local curWear = {} for _, _id in pairs(advAFWear) do curWear[_id] = 1 end local newLv = advAFGet[id] for i = 1, level do if not self.owner:isArtifactOpen(id, self:isEndless(), newLv + 1) then break end newLv = newLv + 1 end if newLv == advAFGet[id] then return end self:mylog({desc = "artifactLevelUp", int1 = id, int2 = level}) local status = 0 if curWear[id] then -- 穿着呢 local oldData = csvdb["adv_artifactCsv"][id][advAFGet[id]] local newData = csvdb["adv_artifactCsv"][id][newLv] self:delArtifactEffect(oldData.effect) self:addArtifactEffect(newData.effect) status = 1 end self.owner:changeUpdates({{type = "advAFGet", field = id, value = newLv}}) self:checkAchievement(Adv.AchievType.MWeaponLv, 1, id, newLv) return status end function Adv:waitChooseArtifact() local chooses = {} local pool = {} local count = 3 --需要多少个 for id, temp in pairs(csvdb["adv_artifactCsv"]) do if not self:isHaveArtifact(id) and self.owner:isArtifactOpen(id, self:isEndless()) then table.insert(pool, id) end end if #pool == 0 then self:award({[ItemId.AdvPoint] = 48}, {log = {desc = "chooseArtifact"}}) else for i = 1, math.min(count, #pool) do local idx = math.randomInt(1, #pool) table.insert(chooses, pool[idx]) table.remove(pool, idx) end self.waitArtifact = chooses self:backChooseArtifact() end end function Adv:isWaitChooseArtifact() return self.waitArtifact end function Adv:chooseArtifact(index) if not self.waitArtifact or not self.waitArtifact[index] then return end self:award({[self.waitArtifact[index]] = 1}, {log = {desc = "chooseArtifact"}, isChoose = true}) self:mylog({desc = "chooseArtifact", int1 = self.waitArtifact[index]}) self.waitArtifact = nil -- 支援效果继续选择 self:supportChooseArtifact() return true end function Adv:isEndless() return AdvCommon.isEndless(self.chapterId) end function Adv:getCurFloorData() local chapter = self.chapterId % 100 return (csvdb["adv_chapter_floorCsv"][self.chapterId] or {})[self.level] end --关卡结束 function Adv:over(success, rewardRatio, overType) if success then rewardRatio = rewardRatio or 100 overType = overType or 0 else rewardRatio = rewardRatio or globalCsv.adv_fail_reward_ratio overType = overType or -1 end local chapterData = csvdb["adv_chapterCsv"][self.chapterId] -- 扣除的东西给积分 local addScore = 0 for itemId, count in pairs(self.owner:getProperty("advItems"):toNumMap()) do local itemCsv = csvdb["itemCsv"][itemId] if not itemCsv then print("ERROR: no itemId in ItemCsv : ", itemId) elseif itemCsv.type == ItemType.AdvItem then addScore = addScore + count * itemCsv.advScore end end self:scoreChange(AdvScoreType.ItemBack, addScore) local score = self.owner:fixAdvScoreChange(self:getScore()) local scoreInfo = self.score local scoreReward = math.floor(score / chapterData.scoreAward) self.owner:award({[ItemId.OldCoin] = scoreReward}, {log = {desc = "advOver", int1 = self.chapterId}}) -- 被动技会影响奖励 self.battle.player:triggerPassive(Passive.ADV_OVER, {score = score, level = self.level}) local reward = {} local advPotionCsv = csvdb["adv_potionCsv"] local potionBag = self.owner:getProperty("potionBag") for itemId, count in pairs(self.owner:getProperty("advItems"):toNumMap()) do local itemCsv = csvdb["itemCsv"][itemId] if advPotionCsv[itemId] then potionBag[itemId] = (potionBag[itemId] or 0) + count elseif not itemCsv then print("ERROR: no itemId in ItemCsv : ", itemId) elseif itemCsv.type ~= ItemType.AdvItem then reward[itemId] = math.ceil(count * rewardRatio / 100) end end reward = self.owner:award(reward, {log = {desc = "advOver", int1 = self.chapterId}}) local backAdvCount if not self:isEndless() then backAdvCount = math.floor((chapterData.limitlevel - self.level) / globalCsv.adv_daily_count_back_radio) * globalCsv.adv_daily_count_back_radio self.owner:changeAdvCount(-backAdvCount) end if success then self.owner:checkTaskEnter("AdvPass", {id = self.chapterId, level = self.level, score = score}) if not self:isEndless() and self.level >= chapterData.limitlevel then self.owner:checkTaskEnter("AdvAllPass", {id = self.chapterId}) end end local roleId = self.owner:getProperty("id") local oldMaxScore = tonum(redisproxy:zscore(self.owner:getAdvRankKey(), roleId)) if score > oldMaxScore then local team = self.owner:getProperty("advTeam") local curInfo = { name = self.owner:getProperty("name"), headId = self.owner:getProperty("headId"), lv = self.owner:getProperty("level"), batteV = self.owner:getTeamBattleValue(team.heros), chapter = self.chapterId, format = self.owner:getTeamHerosInfo(team).heros, } redisproxy:pipelining(function (red) red:zadd(self.owner:getAdvRankKey(), score, roleId) --更新分数 red:hset(RANK_ADV_INFO, roleId, MsgPack.pack(curInfo)) end) end -- 通关的时候要把引导步骤设定到成就引导 if not self.owner:checkOverGuide(57) then self.owner:saveGuide(57,1,true) end self:clearAdvUnlockCache() self:mylog({desc = "over", short1 = success and 1 or 0, int1 = overType}) local team = self.owner:getProperty("advTeam") local player = {} local attrs = self.owner:getTeamBattleInfo(team).heros for attrName, _ in pairs(AdvAttsEnum) do for _, hero in pairs(attrs) do player[attrName] = (player[attrName] or 0) + hero[attrName] end player[attrName] = player[attrName] * (globalCsv.adv_battle_attr_ratio[attrName] or 1) end local battleV = 1 * player["hp"] + 2 * player["atk"] + 1.25 * player["def"] + 0.226 * player["hit"] + 0.26 * player["miss"] local heroList = {team.leader, team.leader2} for _, hid in pairs(team.heros) do if hid ~= team.leader and hid ~= team.leader2 then heroList[#heroList + 1] = hid end end self.owner:log("mission_pick", { mission_threadid = self.chapterId, -- 大地图ID mission_threadname = (csvdb["adv_chapterCsv"][self.chapterId] or {})["chapter"] or "auto", -- 大地图名称 mission_id = self.level, -- 关卡ID mission_herolist = heroList, -- 英雄ID列表,[111, 222, 333, 444, 555] 前两个为队长、副队长 mission_heroscore = battleV, -- 编队总评分 mission_teamlv = 0, -- 编队等级 mission_recscore = csvdb["adv_chapter_campsiteCsv"][self.chapterId][1].recommendValue, -- 关卡推荐评分 mission_floor_bef = 0, -- 进入前关卡层数 mission_floor_aft = self.level, -- 结束时关卡层数 mission_team_status = {HP = team.player.hp, SP = team.player.sp}, -- 队伍状态,{"HP":100, "SP":100, "curse":7} mission_result = success and 1 or (team.player.hp > 0 and 3 or 2), -- 战斗结果(0-无效,1-胜利,2-血量耗尽退出,3,主动退出) mission_reward = reward, -- 获得奖励,[{"id":101,"num":10},{"id":102,"num":20},{"id":103,"num":30}] mission_integral_bef = 0, -- 进入前积分 mission_integral_aft = score, -- 完成后积分 mission_cleartype = 1, -- 1正常通关;2代理拾荒 mission_sequenceid = self.logid, -- 本次拾荒ID,用于关联一次拾荒产生多条不同类型的日志 }) local chapterId = self.chapterId self:clear() self.owner:checkTaskEnter("AdvScore", {score = score}) self.owner:updateProperties({ advItems = "", advAFGet = {}, advAFWear = {}, potionBag = potionBag, }) self:pushBackEvent(AdvBackEventType.End, { success = success, score = score, scoreInfo = scoreInfo, reward = reward, type = overType, scoreAward = scoreReward, chapterId = chapterId, backAdvCount = backAdvCount, }) end function Adv:exit() self:over(false) self:saveDB() end function Adv:randomMapId(chapterId, level) local chapterData = csvdb["adv_chapterCsv"][chapterId] if not chapterData then error("chapterId " .. chapterId .. " dont exist!") return end if AdvCommon.isEndless(chapterId) then level = AdvCommon.getEndlessDataLv(chapterId, level) else if level > chapterData.limitlevel then error("level overflow!") return end end --随出地图Id local raw_pool = chapterData.mapid:toArray(true, "=") local lastMapIds = {} for id, map in ipairs(self.maps or {}) do lastMapIds[map.mapId] = 1 end local pool = {} for _, mapId in ipairs(raw_pool) do local temp = csvdb["mapCsv"][mapId] if temp and not lastMapIds[mapId] then if AdvCommon.checkIsIn(level, temp.leveltype, temp.levellimit) then pool[mapId] = {showup = temp.showup} end end end if not next(pool) then error("mapIds is empty!") return end return math.randWeight(pool, "showup") end -- log long1 字段被征用!!! -- 在冒险中获得的物品都发放在冒险背包内 function Adv:award(gift, params, backRewardParams) params = params or {} local tgift = {} if type(gift) == "string" then for _, one in pairs(gift:toTableArray(true)) do tgift[one[1]] = (tgift[one[1]] or 0) + one[2] end else tgift = gift end local items = self.owner:getProperty("advItems") local oldItems = items local autoUse = {} for itemId, count in pairs(tgift) do if count > 0 and self.battle.player then local buffAdd = self.battle.player:getRewardChange(itemId) count = math.floor(math.max(0, (count + buffAdd[0]) * (1 + buffAdd[1]))) --附加 buff 的影响 self:checkTask(Adv.TaskType.Item, count, itemId) self:checkAchievement(Adv.AchievType.GetItem, count, itemId) end tgift[itemId] = count if globalCsv.adv_auto_useItem[itemId] and count > 0 then autoUse[itemId] = count else local transId = globalCsv.adv_item_potion[itemId] or itemId local origin = items:getv(transId, 0) local nums = origin + count if csvdb["adv_artifactCsv"][itemId] then -- 获得神器 self:awardArtifact(itemId, params) if not self.owner:checkOverGuide(55) then self.owner:saveGuide(55,1,true) end else if nums <= 0 then items = items:delk(transId) nums = 0 else items = items:setv(transId, nums) end if itemId == 16 and not self.owner:checkOverGuide(51,4) then self.owner:saveGuide(51,4) end if params.log then local log = clone(params.log) if log["cint1"] or log["cint2"] or log["cint3"] or log["long1"] then print("addAdvItem error log have cint1 or cint2 or cint3 ", debug.traceback()) end log["cint1"] = itemId log["cint2"] = math.abs(count) log["cint3"] = self.chapterId log["long1"] = self.level if count >= 0 then self.owner:mylog("in_adv", log) else self.owner:mylog("out_adv", log) end else print("addAdvItem no log ", debug.traceback()) end end end end if items ~= oldItems then self.owner:updateProperty({field = "advItems", value = items, notNotify = params.notNotify}) end if tgift[ItemId.OldCoin] then self.battle.player:attrChangeCondBuffCheck(0) end if backRewardParams then self:backReward(tgift, backRewardParams) end if next(autoUse) then for itemId, count in pairs(autoUse) do self:useItem(itemId, count) end self:backUse(autoUse, 1) end return tgift end function Adv:useItem(itemId, count, target) local itemData = csvdb["adv_itemCsv"][itemId] if not itemData then return end if itemData["function"] == 0 or itemData["function"] == 2 then count = 1 end if itemId == 5020 then self.owner:finishGuide(53) end self:checkAchievement(self.AchievType.UseItem, count, itemId) self:mylog({desc = "useItem", int1 = itemId, int2 = count}) self.owner:log("mission_pick_use", { mission_threadid = self.chapterId, -- 大地图ID mission_threadname = (csvdb["adv_chapterCsv"][self.chapterId] or {})["chapter"] or "auto", -- 大地图名称 mission_id = self.level, -- 关卡ID item_id = itemId, -- 道具ID mission_pick_use_num = count, -- 道具使用量 mission_sequenceid = self.logid, -- 本次拾荒ID,用于关联一次拾荒产生多条不同类型的日志 }) for i = 1, count do self:doActive(itemData.effect, target) -- target end end -- 消耗物品 优先冒险背包 --check 只是检查够不够 function Adv:cost(item, params, check) local items = self.owner:getProperty("advItems") local potionCsv = csvdb["adv_potionCsv"] local less = {} local advCost = {} for itemId, count in pairs(item) do advCost[itemId] = - math.min(items:getv(itemId, 0), count) if advCost[itemId] == 0 then advCost[itemId] = nil end local last = items:getv(itemId, 0) - count if last < 0 then less[itemId] = -last end if potionCsv[itemId] and last < 0 then -- 只能使用冒险背包里的药水 return end end if next(less) and not self.owner:checkItemEnough(less) then return end --不够 if check then return true end self:award(advCost, params) if next(less) then self.owner:costItems(less, params) end return true end -- 补满冒险背包药剂,从药剂背包扣除药水放到冒险背包 function Adv:supplyPotion() local potionCsv = csvdb["adv_potionCsv"] local potionBag = self.owner:getProperty("potionBag") local advItems = self.owner:getProperty("advItems") local dishTree = self.owner.dinerData:getProperty("dishTree") for potionId, set in pairs(potionCsv) do local count = potionBag[potionId] or 0 if count > 0 then local max = set[dishTree:getv(potionId,1)].limit local old = advItems:getv(potionId,0) local need = max - old if need < count then advItems = advItems:setv(potionId,max) potionBag[potionId] = count - need else advItems = advItems:setv(potionId,old + count) potionBag[potionId] = nil end end end self.owner:updateProperties({ advItems = advItems, potionBag = potionBag, }) end --事件点击处理 local function clickOut(self, room, block, params, isExit) if self:getCurMap():checkOver() then --检查是否可以出去了 if isExit then self:over(true) return true end if #self.mapStack > 1 then -- 处于夹层中 self:backLayer(-1) local oldMapIdx = self:getCurMapIdx() table.remove(self.mapStack) --退出夹层 self.battle:iLayerChange(oldMapIdx) else --处于底层 local advPass = self.owner:getProperty("advPass") if self:isEndless() then -- 刷新最高层 if self.owner:getProperty("advElM") < self.level then self.owner:updateProperty({field = "advElM", value = self.level}) end else if self.level > (advPass[self.chapterId] or 0) then self.owner:changeUpdates({{type = "advPass", field = self.chapterId, value = self.level}}) if (self.level >= csvdb["adv_chapterCsv"][self.chapterId].limitlevel) then --关卡结束 self.owner:checkTaskEnter("AdvPassFirst", {id = self.chapterId}) end end end self:checkAchievement(Adv.AchievType.OverWin, 1, self.level) self:checkAdvUnlock(2, self.level) local curFloorData = self:getCurFloorData() if not self.isRelay then self:scoreChange(AdvScoreType.Level, curFloorData.advScore) --增加层级加分 end if not self:isEndless() and (self.level >= csvdb["adv_chapterCsv"][self.chapterId].limitlevel) then --关卡结束 self:passAdvRelay() self:over(true) else self.battle.player:triggerPassive(Passive.DOWN_LAYER) if curFloorData then self:award({[ItemId.AdvPoint] = curFloorData.exp}, {log = {desc = "passReward", int1 = self.chapterId, int2 = self.level}}, {}) end self:backNext() --下一关 local isHaveRelay = self:isHaveRelay(self.level) if isHaveRelay and not self.isRelay then self:initByChapter({ chapterId = self.chapterId, level = self.level, isToNext = true, notNotify = true, isRelay = true, }) else self:mylog({desc = "pass"}) self:initByChapter({ chapterId = self.chapterId, level = self.level + 1, isToNext = true, notNotify = true, }) end end end return true end end local function clickExit(self, room, block, params) return clickOut(self, room, block, params, true) end --战斗 普通攻击 local function clickMonster(self, room, block, params) self.battle:battleBegin(room.roomId, block.blockId, params) return true end local function chooseCommon(self, room, block, chooseData, choose, tag) if not choose then return end if not chooseData or not chooseData["button".. choose .."cond"] then return end local conds = chooseData["button".. choose .."cond"]:toTableArray(true) local checkCond = { -- 没有条件 [0] = function() return true end, -- 拥有道具 [1] = function(_, itemId, count) if self:cost({[itemId] = count}, {log = {desc = "chooseEvent", key1 = tag, int1 = chooseData.id}}, true) then return true end end, -- xx角色(todo 队长) [2] = function(_, heroType) for slot, heroId in pairs(self.owner:getProperty("advTeam").heros) do local hero = self.owner.heros[heroId] if hero and hero:getProperty("type") == heroType then return true end end end, --消灭所有怪 [3] = function() for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:isMonster() then return end end end return true end, --制定属性 [4] = function(_, attrType, value) if (self.battle.player[AttsEnumEx[attrType]] or 0) >= value then return true end end, -- 提交一个物品 [5] = function (_, itemId, count) if self:cost({[itemId] = count}, {log = {desc = "chooseEvent", key1 = tag, int1 = chooseData.id}}) then self:backCost({[itemId] = count}) return true end end, -- sp 到达指定值 [6] = function(_, value) if self.battle.player.sp >= value then self.battle.player:changeSp(-value) return true end end, --7=拥有指定buff指定层数 [7] = function(_, buffId, layer) local buff = self.battle.player:getBuffById(buffId) if buff and buff:getLayer() >= layer then return true end end, --8=拥有x神器 [8] = function(_, artifactId) return self:isHaveArtifact(artifactId) end, -- 9 = 生命值大于x% [9] = function (_, value) local cost = value / 100 * self.battle.player.hpMax if self.battle.player.hp > cost then self.battle.player:hurt(cost, nil, {hurtType = 6, buffId = -1}) return true end end, -- 10 = 未获得x神器 [10] = function(_, artifactId) return not self:isHaveArtifact(artifactId) end, -- 11 = 地图上没有指定id 的怪 [11] = function(_, monsterId) for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:isMonster() then if not monsterId then return false end if block.event.id == monsterId then return false end end end end return true end, -- 12 = 地图上没有指定id 的建筑 [12] = function(_, buildId) for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:isBuild() then if not buildId then return false end if block.event.id == buildId then return false end end end end return true end, -- 13 = 地图上没有指定的 选择点 [13] = function(_, chooseId) for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:isChoose() then if not chooseId then return false end if block.event.id == chooseId then return false end end end end return true end, } for _, cond in ipairs(conds) do assert(not cond[1] or checkCond[cond[1]], "error cond, event_" .. (tag or "choose") .. "Csv id :" .. block.event.id) if cond[1] and not checkCond[cond[1]](table.unpack(cond)) then return end end local clearBlock = chooseData.keep ~= 1 local effects = chooseData["button".. choose .."effect"]:toTableArray(true) for _, effect in ipairs(effects) do local doEffect = { [1] = function() -- 获得某道具N个 local count = effect[3] or 1 local reward = {} for i = 1, count do local dropData = csvdb["event_dropCsv"][effect[2]] if dropData then local item = dropData["range"]:randWeight(true) reward[item[1]] = (reward[item[1]] or 0) + item[2] else skynet.error(string.format("[ERROR]: event_dropCsv no id %s in %s id: %s", effect[2], tag, chooseData.id)) end end self:award(reward, {log = {desc = "chooseEvent", key1 = tag, int1 = chooseData.id}}, {roomId = room.roomId, blockId = block.blockId}) end, [2] = function() --获得冒险buff local layer = effect[3] or 1 for i = 1, layer do self.battle.player:addBuff(effect[2]) end end, [3] = function() --发现怪物 self:getCurMap():addNewMonsterRand(effect[2], {room, block}) self:pushBackEvent(AdvBackEventType.Monster, {id = effect[2]}) clearBlock = false end, [4] = function() --无事发生 end, [5] = function() --5=属性枚举=数值;直接增加玩家属性 local attr if effect[3] == 0 then attr = "sp" else attr = AttsEnumEx[effect[3]] if not AdvAttsEnum[attr] then return end end self.battle.player:addBaseAttr(attr, effect[4], effect[2]) end, [6] = function() -- 商店 block:updateEvent({ etype = AdvEventType.Trader, id = effect[2] }) self:pushBackEvent(AdvBackEventType.Trader, {id = effect[2]}) clearBlock = false end, [7] = function() -- 建筑 block:updateEvent({ etype = AdvEventType.Build, id = effect[2] }) clearBlock = false end, [8] = function() -- 选择 block:updateEvent({ etype = AdvEventType.Choose, id = effect[2] }) clearBlock = false end, [9] = function() -- click block:updateEvent({ etype = AdvEventType.Click, id = effect[2] }) clearBlock = false end, [10] = function() -- 陷阱 block:updateEvent({ etype = AdvEventType.Trap, id = effect[2] }) clearBlock = false end, [11] = function() -- 获得神器 self:waitChooseArtifact() --等待获取神器 end, [12] = function() -- buffId local targers = self.battle.player:getTeam(2, nil, nil, true) for _, target in pairs(targers) do target:addBuff(effect[2]) end end, [13] = function() -- 显示地图 self:getCurMap():showMap() self:backMapShow() end, [14] = function() -- 指定地块召唤 指定类型的id local change = self:getCurMap():layEventToStage(effect[2], effect[3], effect[4], effect[5]) for _, one in ipairs(change) do if one[1].roomId == room.roomId and one[2].blockId == block.blockId then clearBlock = false else self:backBlockChange(one[1].roomId, one[2].blockId) end end end, [15] = function() -- 移除指定事件 local change = self:getCurMap():clearEventById(effect[2], effect[3], effect[4]) for _, one in ipairs(change) do if one[1].roomId == room.roomId and one[2].blockId == block.blockId then clearBlock = false else self:backBlockChange(one[1].roomId, one[2].blockId) end end end, [16] = function() -- 指定事件转移 local change = self:getCurMap():eventChangeToOther(effect[2], effect[3], effect[4], effect[5], effect[6]) for _, one in ipairs(change) do if one[1].roomId == room.roomId and one[2].blockId == block.blockId then clearBlock = false else self:backBlockChange(one[1].roomId, one[2].blockId) end end end, } assert(doEffect[effect[1]], "error effect, event_" .. (tag or "choose") .. "Csv id :" .. (block.event and block.event.id or 0) .. "effect " .. effect[1]) doEffect[effect[1]]() end self:scoreChange(AdvScoreType.Event, chooseData.advScore) --增加加分 return true, clearBlock end local function clickChoose(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_chooseCsv"][block.event.id] local oldId = block.event.id local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "choose") if not status then return end self:checkAdvUnlock(3, oldId) self:checkTask(Adv.TaskType.Choose, 1, oldId) self:checkAchievement(Adv.AchievType.Choose, 1, oldId) self:checkAchievement(Adv.AchievType.ChooseBySelect, 1, oldId, choose) if clearBlock then block:clear() end return true end local function clickLinkChoose(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_linkchooseCsv"][block.event.id] local lcId = block.event.id local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "link") if not status then return end -- 完成统计次数 local idx = lcId % 10 if idx == 9 or not csvdb["event_linkchooseCsv"][lcId + 1] then --全部完成 local startId = math.floor(lcId / 10) * 10 + 1 self.lchoose[startId] = (self.lchoose[startId] or 0) + 1 self:checkAchievement(Adv.AchievType.LinkChoose, 1, startId) self:checkAchievement(Adv.AchievType.FinishStoryId, 1, chooseData.storyid) self:checkTask(Adv.TaskType.FinishStoryId, 1, chooseData.storyid) local advStoryB = self.owner:getProperty("advStoryB") advStoryB[chooseData.storyid] = (advStoryB[chooseData.storyid] or 0) + 1 self.owner:setProperty("advStoryB", advStoryB) local storyData = csvdb["event_linkchoose_storyCsv"][chooseData.storyid] self:checkAchievement(Adv.AchievType.StorryDone, 1, storyData[1].chapter) -- 检查故事对应章节 self:scoreChange(AdvScoreType.Story, storyData[1].advScore) --增加加分 self:checkAdvUnlock(4, startId) self.lchoose.cur = self.lchoose.cur or {} table.insert(self.lchoose.cur, {lcId, choose}) self:pushBackEvent(AdvBackEventType.LinkChooseOver, self.lchoose.cur) self.lchoose.cur = nil else self.lchoose.ing = lcId + 1 --后面会出现后继事件 self.lchoose.cur = self.lchoose.cur or {} table.insert(self.lchoose.cur, {lcId, choose}) end if clearBlock then block:clear() end return true end local function clickDrop(self, room, block, params) local reward = {} if not block.event.item then return end if not self.battle or not self.battle.player then return end self.battle.player:triggerPassive(Passive.CLICK_DROP) local reward = self:award({[block.event.item[1]] = block.event.item[2]}, {log = {desc = "clickDrop"}}, {roomId = room.roomId, blockId = block.blockId}) if block.event.item[1] == 5020 and not self.owner:checkOverGuide(53,2) then self.owner:saveGuide(53,2) end block:clear() return true end local function clickTrader(self, room, block, params) local buyId = params.id local traderData = csvdb["event_traderCsv"][block.event.id] if not traderData then return false, 1 end -- 偷偷改表了 if not block.event.shop or not block.event.shop[buyId] then return false, 2 end if (block.event.status or ""):getv(buyId, 0) == 1 then return false, 3 end -- 买过了 local buyCount = #((block.event.status or ""):toArray()) if traderData.purchasetime ~= 0 and traderData.purchasetime <= buyCount then return false, 4 end local goodsData = csvdb["event_trader_goodsCsv"][block.event.shop[buyId][1]] if not goodsData then return false, 5 end local costCount = math.ceil(goodsData.price * (block.event.shop[buyId][2] or 100) / 100) if not self:cost({[goodsData.currency] = costCount}, {log = {desc = "clickTrader", int1 = block.event.id}}) then return false, 6 end --不够 self:backCost({[goodsData.currency] = costCount}) self:award({[goodsData.item] = goodsData.num}, {log = {desc = "clickTrader", int1 = block.event.id}}, {}) if goodsData.restrict == 1 then self.shopStatus[goodsData.goods] = (self.shopStatus[goodsData.goods] or 0) + 1 elseif goodsData.restrict == 2 then local advShop = self.owner:getProperty("advShop") advShop[goodsData.goods] = (advShop[goodsData.goods] or 0) + 1 self.owner:updateProperty({field = "advShop", value = advShop}) end block.event.status = block.event.status:setv(buyId, 1) buyCount = buyCount + 1 self:checkTask(Adv.TaskType.Shop, 1, block.event.id) self:checkAchievement(Adv.AchievType.Shop, 1, block.event.id) if (traderData.purchasetime ~= 0 and traderData.purchasetime <= buyCount) or #block.event.shop <= buyCount then block:clear() end return true end local function clickBuild(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_buildingCsv"][block.event.id] local oldId = block.event.id local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "build") if not status then return end local isMine = false -- 是不是宝藏怪 for _, mid in ipairs(globalCsv.adv_egg_treasureLayer_id) do if mid == oldId then isMine = true break end end if isMine then local advMine = self.owner:getProperty("advMine") advMine[2] = advMine[2] or {} local mineCo2 = advMine[2].co or {} if chooseData.limit ~= 0 then mineCo2[oldId] = (mineCo2[oldId] or 0) + 1 end advMine[2].co = mineCo2 self.owner:setProperty("advMine", advMine) self.owner:checkTaskEnter("AdvMineLayer") end self:checkTask(Adv.TaskType.Build, 1, oldId) self:checkAchievement(Adv.AchievType.Build, 1, oldId) self:checkAchievement(Adv.AchievType.BuildBySelect, 1, oldId, choose) if clearBlock then block:clear() end return true end local function clickClick(self, room, block, params) local clickData = csvdb["event_clickCsv"][block.event.id] local oldId = block.event.id if not clickData then return end local clearBlock = true local doEffect = { [1] = function() -- 技能 for _, skillId in ipairs(clickData.effect:toArray(true, "=")) do self.battle.player:releaseSkill(skillId) end end, [2] = function() -- dropId local reward = {} for _, dropId in ipairs(clickData.effect:toArray(true, "=")) do local item = csvdb["event_dropCsv"][dropId]["range"]:randWeight(true) reward[item[1]] = (reward[item[1]] or 0) + item[2] end self:award(reward, {log = {desc = "clickClick", int1 = block.event.id}}, {roomId = room.roomId, blockId = block.blockId}) end, [3] = function() for _, buffId in ipairs(clickData.effect:toArray(true, "=")) do self.battle.player:addBuff(buffId) end end, } assert(doEffect[clickData.type], "error effect, event_clickCsv id :" .. block.event.id) doEffect[clickData.type]() self:checkTask(Adv.TaskType.Click, 1, oldId) if clearBlock then block:clear() end return true end local function clickLayer(self, room, block, params) local oldMapIdx = self:getCurMapIdx() self:backLayer(1) if block.event.mapIdx then table.insert(self.mapStack, block.event.mapIdx) --进入夹层 else --生成夹层 local mapId = csvdb["event_layerCsv"][block.event.id].effect local mapIdx = #self.maps + 1 block.event.mapIdx = mapIdx table.insert(self.mapStack, mapIdx) self.maps[mapIdx] = AdvMap.new(self, mapIdx, mapId) self.battle:initMapEnemys(mapIdx, true) self.battle:initMapEffect(true) self.maps[mapIdx]:initBattleAfter() self:checkAchievement(Adv.AchievType.EnterILayer, 1, mapId) end self.battle:iLayerChange(oldMapIdx) return true end local eventCallFunc = { [AdvEventType.Out] = clickOut, [AdvEventType.InOut] = clickOut, [AdvEventType.Exit] = clickExit, [AdvEventType.BOSS] = clickMonster, [AdvEventType.Monster] = clickMonster, [AdvEventType.Choose] = clickChoose, [AdvEventType.LinkChoose] = clickLinkChoose, [AdvEventType.Drop] = clickDrop, [AdvEventType.Trader] = clickTrader, [AdvEventType.Build] = clickBuild, [AdvEventType.Click] = clickClick, [AdvEventType.Layer] = clickLayer, } --点击处理 roomId, blockId --params 某些事件需要的客户端传递的参数 function Adv:clickBlock(roomId, blockId, params) local map = self:getCurMap() local room = self:getRoom(roomId) local block = self:getBlock(roomId, blockId) if not block then return end local status, errorCode = false, nil local clickEvent = false local function checkAroundBlocks(ignoreGuard) local canOpen = false --如果未开放是否可以开放 for _, one in ipairs(map:getAroundBlocks(room, block)) do local _room, _block = one[1], one[2] if not ignoreGuard and _block:isGuard() then if _block:isMonster() then local enemy = self.battle:getEnemy(_room.roomId, _block.blockId) if not enemy:hadBuff(Buff.DONT_DEFEND) and not self.battle.player:hadBuff(Buff.SNEAK) then return false end else return false end elseif _block:isWalk() then canOpen = true end end return canOpen end if not block.isOpen then if self.isRelay or checkAroundBlocks() then --开放 self:getCurMap():openBlock(roomId, blockId, true, true) status = true end else clickEvent = true --点了空地 if not block.event then return end if block:isHinder() then if not checkAroundBlocks(true) then return end end --可点击的事件 if not room.isBossRoom or block:isBoss() then if eventCallFunc[block.event.etype] then status, errorCode = eventCallFunc[block:getEventType()](self, room, block, params) end end end local needChange = true if clickEvent and block.event then if block:getEventType() == AdvEventType.Out or block:getEventType() == AdvEventType.InOut or block:getEventType() == AdvEventType.Layer or block:getEventType() == AdvEventType.Exit then needChange = false end end if status and needChange then --出去了就不计算回合了 self:backBlockChange(roomId, blockId) self:afterRound() end self:saveDB() return status, errorCode end function Adv:doActive(activeId, target) local activeData = csvdb["adv_activeCsv"][activeId] if not activeData then return end local targers = {} -- 筛选对象 if activeData.usetype == 1 then -- 自己 elseif activeData.usetype == 2 then -- 敌人 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if block:isBoss() then return end local enemy = self.battle:getEnemy(target.roomId, target.blockId) if not enemy then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if block:isMonster() and not block:isBoss() then local e = self.battle:getEnemy(block.room.roomId, block.blockId) if e then table.insert(targers, e) end end end elseif activeData.usetype == 3 then -- 地板 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if block:isBoss() then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if not block:isBoss() then table.insert(targers, block) end end elseif activeData.usetype == 4 then -- 没有目标 全体成员 elseif activeData.usetype == 5 then -- 空地板 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if not block.isOpen or block:getEventType() then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if not block:isBoss() then table.insert(targers, block) end end end local doActiveEffect = {} -- 1=map_buff_id:为范围内所有目标附加mapbuff doActiveEffect[1] = function(_, buffId) if not next(targers) then if activeData.usetype == 1 then table.insert(targers, self.battle.player) elseif activeData.usetype == 4 then targers = self.battle.player:getTeam(2) else return end end for _, target in ipairs(targers) do if target.class.__cname == "AdvBlock" then target = self.battle:getEnemy(target.room.roomId, target.blockId) end if target then target:addBuff(buffId, self.battle.player) end end return true end -- 2=trader_id:召唤商人 doActiveEffect[2] = function(_, traderId) for _, target in ipairs(targers) do if target.isOpen and not target:getEventType() then target:updateEvent({ etype = AdvEventType.Trader, id = traderId, }) self:backBlockChange(target.room.roomId, target.blockId) self:pushBackEvent(AdvBackEventType.Trader, {id = traderId}) end end return true end -- 3=monster_id:替换怪物,仅使用方式为2时生效 doActiveEffect[3] = function(_, monsterId) for _, target in ipairs(targers) do if not target.lock and not target.isDead then self:getCurMap():addNewMonsterRand(monsterId, {self:getRoom(target.roomId), self:getBlock(target.roomId, target.blockId)}) self:backBlockChange(target.roomId, target.blockId) self:pushBackEvent(AdvBackEventType.Monster, {id = monsterId}) end end return true end -- 4:显示本层 doActiveEffect[4] = function(_) self:getCurMap():showMap() self:backMapShow() return true end -- 5:放逐目标 doActiveEffect[5] = function(_) for _, target in ipairs(targers) do if not target.lock and not target.isDead then target:kill() self:backBlockChange(target.roomId, target.blockId) end end return true end -- 6=陷阱id:移除陷阱,不填写id则移除所有陷阱 doActiveEffect[6] = function(_, trapId) if not next(targers) and activeData.usetype == 4 then -- 全屏 for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:getEventType() == AdvEventType.Trap then block:updateEvent(nil) self:backBlockChange(block.room.roomId, block.blockId) end end end else for _ , target in ipairs(targers) do if target:getEventType() == AdvEventType.Trap then target:updateEvent(nil) self:backBlockChange(target.room.roomId, target.blockId) end end end return true end -- 7=道具燃烧效果 doActiveEffect[7] = function(_) for _ , target in ipairs(targers) do if target:getEventType() == AdvEventType.Drop then target:updateEvent(nil) self:backBlockChange(target.room.roomId, target.blockId) end end return true end -- 8:翻开范围内的方格 doActiveEffect[8] = function(_) for _ , target in ipairs(targers) do self:getCurMap():openBlock(target.room.roomId, target.blockId, true) end return true end -- 9: 给玩家增加buff doActiveEffect[9] = function(_, buffId) self.battle.player:addBuff(buffId, self.battle.player) return true end --10: 立刻结算 按比例返还 doActiveEffect[10] = function(_, rewardRatio) self:over(true, rewardRatio, 1) return true end --11: 随机提升一个未满级神器等级,配置提升等级 doActiveEffect[11] = function(_, level) local advAFGet = self.owner:getProperty("advAFGet") local pool = {} for id_, lv in pairs(advAFGet) do if self.owner:isArtifactOpen(id_, self:isEndless(), lv + 1) then table.insert(pool, id_) end end if #pool > 0 then local idx = math.randomInt(1, #pool) self:artifactLevelUp(pool[idx], level) end return true end doActiveEffect[12] = function(_, vtype, attrType, value) local attr if attrType == 0 then attr = "sp" else attr = AttsEnumEx[attrType] if not AdvAttsEnum[attr] then return end end self.battle.player:addBaseAttr(attr, value, vtype) return true end for _, effect in ipairs(activeData.effect:toArray()) do local cur = effect:toArray(true, "=") if doActiveEffect[cur[1]] then if not doActiveEffect[cur[1]](table.unpack(cur)) then return end end end return true end -- 地图上物品变化 function Adv:mapItemChange(ctype) local blocks = {} for roomId, room in pairs(self:getCurMap().rooms) do for blockId, block in pairs(room.blocks) do table.insert(blocks, block) end end self:blockDropChange(ctype, blocks) end function Adv:blockDropChange(ctype, blocks) local clist = csvdb["transform_itemCsv"][ctype] if clist then for _, block in ipairs(blocks) do if block:getEventType() == AdvEventType.Drop and block.event.item then local id = block.event.item[1] local count = block.event.item[2] local changeTo = nil if clist[id] then changeTo = {clist[id].toId, math.ceil(count * clist[id].num)} elseif clist[-1] then changeTo = {clist[-1].toId, math.ceil(count * clist[-1].num)} end if changeTo and changeTo[1] ~= 0 and changeTo[2] ~= 0 then block.event.item = changeTo self:backBlockChange(block.room.roomId, block.blockId, ctype) end end end end end --敌人死亡 function Adv:enemyDead(enemy, escape) local roomId, blockId = enemy.roomId, enemy.blockId local map = self:getCurMap() local room = self:getRoom(roomId) local block = self:getBlock(roomId, blockId) if not block then return end --死了以后掉东西 if block:isMonster() then --处理死亡 if block:isBoss() then room.isBossRoom = false end if escape then block:clear() else local enemyId = block.event.id local monsterData = csvdb["event_monsterCsv"][enemyId] if block:isBoss() then self:scoreChange(AdvScoreType.KillBoss, monsterData.advScore) else self:scoreChange(AdvScoreType.Kill, monsterData.advScore) end -- local changeV = self.battle.player:addExp(monsterData.exp) -- self:backDead(enemyId, changeV) self:backDead(enemyId) local isMine = false -- 是不是宝藏怪 for _, mid in ipairs(globalCsv.adv_egg_treasureMonster_id) do if mid == enemyId then isMine = true break end end if isMine then local advMine = self.owner:getProperty("advMine") advMine[1] = advMine[1] or {} advMine[2] = advMine[2] or {} local mineCo = advMine[1].co or {} local mineCo2 = advMine[2].co or {} local mineCh = advMine[2].ch or globalCsv.adv_egg_treasureLayer_showup if monsterData.limit ~= 0 then mineCo[enemyId] = (mineCo[enemyId] or 0) + 1 end local had = false if math.randomInt(1, 100) <= mineCh then -- 刷出来了 local mpool = {} for _, mid in ipairs(globalCsv.adv_egg_treasureLayer_id) do local layer = csvdb["event_buildingCsv"][mid] if (not mineCo2[mid] or layer.limit == 0 or mineCo2[mid] < layer.limit) and layer.showup > 0 then mpool[mid] = {layer.showup} end end if next(mpool) then local cId = math.randWeight(mpool, 1) block:updateEvent({ etype = AdvEventType.Build, id = cId }) had = true end end if had then mineCh = nil else block:clear() mineCh = math.min(mineCh + globalCsv.adv_egg_treasureLayer_showup_add, 100) end local drops = {} for _, dropId in ipairs(monsterData.dropid:toArray(true, "=")) do local dropData = csvdb["event_dropCsv"][dropId] if dropData then local cur = dropData["range"]:randWeight(true) if cur and cur[1] ~= 0 then drops[#drops + 1] = cur end end end local blocks = self:getCurMap():getEmptyBlocks(roomId, blockId, #drops) for _i, cblock in ipairs(blocks) do cblock:updateEvent({ etype = AdvEventType.Drop, item = drops[_i] }) if cblock ~= block then self:backBlockChange(cblock.room.roomId, cblock.blockId) end end advMine[1].co = mineCo advMine[2].co = mineCo2 advMine[2].ch = mineCh self.owner:setProperty("advMine", advMine) self.owner:checkTaskEnter("AdvMineKill") else local toClick = enemy:hadBuff(Buff.CHANGE_DROP_TO_CLICK) if toClick then toClick = toClick:effect() end local changItem = enemy:hadBuff(Buff.CHANGE_DROP) if changItem then changItem = table.pack(changItem:effect()) end local addMult = 0 local dropBuff = enemy:hadBuff(Buff.DROP_BUFF_BY_ENEMY) -- 根据敌人数量变化个数 if dropBuff then local team = enemy:getTeam(1, true) addMult = addMult + 0.2 * #team end local dropIds = monsterData.dropid:toArray(true, "=") local drops = {} local cCcount = 0 -- 需要改变为click 的个数 for _, dropId in ipairs(dropIds) do local dropData = csvdb["event_dropCsv"][dropId] if dropData then local cur = dropData["range"]:randWeight(true) if cur and cur[1] ~= 0 then if toClick then cCcount = cCcount + 1 else local item = changItem and changItem or cur item[2] = math.floor(item[2] * (1 + addMult)) drops[#drops + 1] = item end end end end -- 这些奖励可能会有被动加成 self.battle.player:triggerPassive(Passive.BATTLE_WIN, {drops = drops}) -- 自身带的掉落是不会被改变的 也不会被加成 if block.event.item and block.event.item[1] ~= 0 then table.insert(drops, 1, block.event.item) end -- 清空当前的格子 block:clear() -- 掉落走一波 local blocks = self:getCurMap():getEmptyBlocks(roomId, blockId, #drops) for _i, cblock in ipairs(blocks) do cblock:updateEvent({ etype = AdvEventType.Drop, item = drops[_i] }) if cblock ~= block then self:backBlockChange(cblock.room.roomId, cblock.blockId) end end -- 转换的click走一波 local blocks = self:getCurMap():getEmptyBlocks(roomId, blockId, cCcount) for _i, cblock in ipairs(blocks) do cblock:updateEvent({ etype = AdvEventType.Click, id = clickId }) if cblock ~= block then self:backBlockChange(cblock.room.roomId, cblock.blockId) end end end self:checkTask(Adv.TaskType.Kill, 1, enemyId) self:checkTask(Adv.TaskType.KillAll) self:checkAchievement(Adv.AchievType.Kill, 1, enemyId) self:checkAchievement(Adv.AchievType.KillHadBuff, 1, enemy) self:checkAchievement(Adv.AchievType.KillWithBuff, 1) self:checkAchievement(Adv.AchievType.KillNoBuff, 1) self:checkAchievement(Adv.AchievType.KillWithMWeapon, 1) self:checkAchievement(Adv.AchievType.KillWithAMWeapon, 1) if monsterData.type == 2 then self:checkTask(Adv.TaskType.KillBoss, 1, enemyId) self:checkAchievement(Adv.AchievType.KillBoss, 1, enemyId) self:checkAchievement(Adv.AchievType.KillBossWithBuff, 1) self:checkAchievement(Adv.AchievType.KillBossNoBuff, 1) self:checkAchievement(Adv.AchievType.KillBossWithMWeapon, 1) self:checkAchievement(Adv.AchievType.KillBossWithAMWeapon, 1) self.owner:checkTaskEnter("AdvKillBoss") elseif monsterData.type == 3 then self:checkTask(Adv.TaskType.KillElite, 1, enemyId) end end end self:backBlockChange(roomId, blockId) end function Adv:pushBackEvent(btype, params) table.insert(self.backEvents, {btype = btype, params = params}) end --[=[ tag 1 自动拾取 --]=] function Adv:backReward(items, params) params = params or {} self:pushBackEvent(AdvBackEventType.Reward, {items = items, roomId = params.roomId, blockId = params.blockId, tag = params.tag}) end -- if is player enemyId is nil function Adv:backSkill(enemyId, skillId, receiver) self:pushBackEvent(AdvBackEventType.Skill, {enemyId = enemyId, skillId = skillId, receiver = receiver}) end function Adv:backNext() self:pushBackEvent(AdvBackEventType.Next, {}) end function Adv:backBlockChange(roomId, blockId, itemChangeType) self:pushBackEvent(AdvBackEventType.BlockChange, {roomId = roomId, blockId = blockId, itemChangeType = itemChangeType}) end function Adv:backDead(enemyId) self:pushBackEvent(AdvBackEventType.Dead, {enemyId = enemyId}) end function Adv:backTrap() self:pushBackEvent(AdvBackEventType.Trap, {}) end function Adv:backLayer(status) self:pushBackEvent(AdvBackEventType.Layer, {status = status}) end function Adv:backMapShow() self:pushBackEvent(AdvBackEventType.MapShow, {}) end function Adv:backChooseArtifact() self:pushBackEvent(AdvBackEventType.ChooseArtifact, {}) end function Adv:backCost(items) self:pushBackEvent(AdvBackEventType.Cost, {items = items}) end --[=[ tag 1 自动使用 --]=] function Adv:backUse(items, tag) self:pushBackEvent(AdvBackEventType.Use, {items = items, tag = tag}) end function Adv:scoreChange(scoreType, score) self.score[scoreType] = self.score[scoreType] or 0 self.score[scoreType] = self.score[scoreType] + score end function Adv:getScore() local allScore = 0 for _, score in pairs(self.score) do allScore = allScore + math.floor(score) end return allScore end function Adv:popBackEvents() local events = self.backEvents self.backEvents = {} return events end --回合事件处理 function Adv:afterRound() self.round = self.round + 1 if self.battle then self.battle:afterRound() end end return Adv