local Filter = class("Filter") Filter.HP_UP_WITH_EQUAL = 1 -- 血量>=value% Filter.HP_UP = 2 -- 血量>value% Filter.HP_LOW_WITH_EQUAL = 3 -- 血量<=value% Filter.HP_LOW = 4 -- 血量= self.value * target.hpMax / 100 end end FilterFactory[Filter.HP_UP] = function (_Filter) _Filter._execute = function (self, target) return target.hp > self.value * target.hpMax / 100 end end FilterFactory[Filter.HP_LOW_WITH_EQUAL] = function (_Filter) _Filter._execute = function (self, target) return target.hp <= self.value * target.hpMax / 100 end end FilterFactory[Filter.HP_LOW] = function (_Filter) _Filter._execute = function (self, target) return target.hp < self.value * target.hpMax / 100 end end FilterFactory[Filter.BUFF_BY_TYPE] = function (_Filter) _Filter._execute = function (self, target) return target:hadBuff(self.value) end end FilterFactory[Filter.BUFF_BY_ID] = function (_Filter) _Filter._execute = function (self, target) return target:hadBuffById(self.value) end end FilterFactory[Filter.CAMP] = function (_Filter) _Filter._execute = function (self, target) local role = self.owner.battle.adv.owner return role:getHerosCamp(role:getProperty("advTeam").heros) == self.value end end FilterFactory[Filter.RANGE] = function (_Filter) _Filter._execute = function (self, target, params) if params and self.owner.blockId and self.owner.roomId and params.blockId and params.roomId then local distance = self.owner.battle.adv:getCurMap():getDistance(self.owner.roomId, self.owner.blockId, params.roomId, params.blockId) return distance ~= -1 and distance <= self.value end return false end end FilterFactory[Filter.CLASSIFY] = function (_Filter) _Filter._execute = function (self, target) return target.isClassify and target:isClassify(self.value) end end FilterFactory[Filter.NO_BUFF_BY_ID] = function (_Filter) _Filter._execute = function (self, target) return not target:hadBuffById(self.value) end end function Filter:ctor(params) self.owner = params.owner self.skill = params.skill self.fType = params.fType -- 筛选类型 self.oType = params.oType -- 主体类型 0:owner 1:trigger 2:releaser self.value = params.value -- 筛选值 if FilterFactory[self.fType] then FilterFactory[self.fType](self) end end function Filter:getTarget(params) local target if self.oType == 0 then target = self.owner end if self.oType == 1 and params.trigger then target = params.trigger end if self.oType == 2 and params.releaser then target = params.releaser end if self.oType == 3 then target = self.owner.battle.player end return target end function Filter:execute(params) local target = self:getTarget(params) if not target then return end return self:_execute(target, params) end -->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> local Passive = class("Passive") -- 每回合触发的使用 afterRound -- 其他触发的使用 triggerPassive Passive.BORN_ONCE = 1 -- 自身出生(翻开所在格子)触发 Passive.ROOM_SHOW = 2 --自身所在房间被展示时,触发1次 Passive.HURT_PERCENT_SELF = 3 --自身,每损失N%生命值,触发1次 Passive.HURT_PERCENT_TEAM = 4 --队友,每损失N%生命值,触发1次 Passive.HP_LOW_SELF = 5 --自身生命值N%时,每回合触发 Passive.HP_UP_TEAM = 8 --敌人生命值>N%时,每回合触发 Passive.SELF_ATK = 9 --自身攻击N次后,触发1次 < discard > Passive.SELF_HURT = 10 --自身受击buff后,触发1次 Passive.TEAM_ATK = 11 --队友攻击N次后,触发1次 < discard > Passive.TEAM_HURT = 12 --队友受击buff后,触发1次 Passive.MONSTER_COUNT_UP = 13 --场上存在N个以上怪物,每回合触发 Passive.MONSTER_COUNT_LOW = 14 --场上存在N个以下怪物,每回合触发 Passive.SELF_DEAD = 15 --自身死亡后,触发1次 Passive.TEAM_DEAD = 16 --队友死亡后,触发1次 Passive.TARGET_SKILL = 17 --目标每使用N次技能,触发1次 Passive.TEAM_SKILL = 18 --队友每使用N次技能,触发1次 Passive.HAVE_MONSTER = 20 --场上拥有指定怪时 回合触发 Passive.SKILL_KILL = 21 --技能击杀怪物时 触发1次 Passive.CLICK_TRAP = 22 --触发陷阱时 触发1次 Passive.DOWN_LAYER = 23 --下层时 触发1次 Passive.ADV_OVER = 24 --结算时 触发1次 Passive.BATTLE_WIN = 25 --战斗胜利x次时 Passive.CLICK_DROP = 26 --拾取drop x次时 Passive.AFTER_ROUND = 27 --经过 x回合时 Passive.GET_BUFF = 28 --获得指定buff Passive.OPEN_BLOCK = 29 --翻开格子 Passive.OPEN_MONSTER = 30 --翻开怪物 Passive.PLAYER_BUFF = 31 --玩家获得buff Passive.PLAYER_BUFF_CLASSIFY = 35 -- 获得指定标签的buff -- 不同的开启条件 local PassiveCondFactory = {} PassiveCondFactory[Passive.HURT_PERCENT_SELF] = function(_Passive) _Passive._trigger = function(self, params) local value = params.value or 1 self.rv = math.floor(self.rv + value) if self.rv >= self.passiveData.value then self.rv = self.rv % self.passiveData.value -- 取余 return true end end _Passive._initDB = function(self, data) self.rv = data.rv or 0 end _Passive._getDB = function(self) return {rv = self.rv} end end PassiveCondFactory[Passive.HURT_PERCENT_TEAM] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.SELF_ATK] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.TEAM_ATK] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.TARGET_SKILL] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.TEAM_SKILL] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.BATTLE_WIN] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.CLICK_DROP] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.AFTER_ROUND] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.OPEN_BLOCK] = PassiveCondFactory[Passive.HURT_PERCENT_SELF] --逻辑相同 PassiveCondFactory[Passive.SELF_HURT] = function(_Passive) _Passive._trigger = function(self, params) local buffId = params.buffId if not buffId then return end local data = csvdb["adv_map_buffCsv"][buffId] if not data then return end if data.classify:sismember(self.passiveData.value, " ") then return true end end end PassiveCondFactory[Passive.TEAM_HURT] = PassiveCondFactory[Passive.SELF_HURT] --逻辑相同 PassiveCondFactory[Passive.ROOM_SHOW] = function(_Passive) _Passive._trigger = function(self, params) local roomId = params.roomId if self.owner.roomId == roomId then return true end end end PassiveCondFactory[Passive.GET_BUFF] = function(_Passive) _Passive._trigger = function(self, params) if self.passiveData.value == params.buffId then return true end end end PassiveCondFactory[Passive.PLAYER_BUFF] = PassiveCondFactory[Passive.GET_BUFF] PassiveCondFactory[Passive.PLAYER_BUFF_CLASSIFY] = function(_Passive) _Passive._trigger = function(self, params) if params.classify:sismember(self.passiveData.value, " ") then return true end end end PassiveCondFactory[Passive.BORN_ONCE] = function(_Passive) _Passive._afterRound = function(self) if not self.owner.lock then self:trigger(Passive.BORN_ONCE) end end end PassiveCondFactory[Passive.HAVE_MONSTER] = function(_Passive) _Passive._afterRound = function(self) for _, player in ipairs(self.owner.battle.player:getTeam(2)) do if player.monsterId == self.passiveData.value then self:trigger(Passive.HAVE_MONSTER) break end end end end PassiveCondFactory[Passive.HP_LOW_SELF] = function(_Passive) _Passive._afterRound = function(self) if self.owner.hp / self.owner.hpMax * 100 < self.passiveData.value then self:trigger(Passive.HP_LOW_SELF) end end end PassiveCondFactory[Passive.HP_LOW_TEAM] = function(_Passive) _Passive._afterRound = function(self) for _, player in ipairs(self.owner:getTeam(2)) do if player.hp / player.hpMax * 100 < self.passiveData.value then self:trigger(Passive.HP_LOW_TEAM, {trigger = player}) end end end end PassiveCondFactory[Passive.HP_UP_SELF] = function(_Passive) _Passive._afterRound = function(self) if self.owner.hp / self.owner.hpMax * 100 > self.passiveData.value then self:trigger(Passive.HP_UP_SELF) end end end PassiveCondFactory[Passive.HP_UP_TEAM] = function(_Passive) _Passive._afterRound = function(self) for _, player in ipairs(self.owner:getTeam(2)) do if player.hp / player.hpMax * 100 > self.passiveData.value then self:trigger(Passive.HP_UP_TEAM, {trigger = player}) end end end end PassiveCondFactory[Passive.MONSTER_COUNT_UP] = function(_Passive) _Passive._afterRound = function(self) local monsters = self.owner.battle.player:getTeam(2) if #monsters > self.passiveData.value then self:trigger(Passive.MONSTER_COUNT_UP) end end end PassiveCondFactory[Passive.MONSTER_COUNT_LOW] = function(_Passive) _Passive._afterRound = function(self) local monsters = self.owner.battle.player:getTeam(2) if #monsters < self.passiveData.value then self:trigger(Passive.MONSTER_COUNT_LOW) end end end function Passive:ctor(owner, data) self.owner = owner self.id = data.id self.level = data.level or 1 self.passiveData = csvdb["adv_map_passiveCsv"][self.id][self.level] self.isDel = false self.round = data.round or 0 --触发剩余回合数 self.count = data.count or self.passiveData.count --触发剩余次数 self.delay = data.delay or self.passiveData.delayRound --触发延迟回合数 if self.passiveData.mapLock == 1 and not self.mapId then self.mapId = self.owner.battle.adv:getCurMap().mapId end self.effects = self.passiveData.effect:toTableArray(true) self.filters = {} if self.passiveData.count < 0 then -- count < 0 无限次触发 self.count = 999 end if PassiveCondFactory[self.passiveData.condition] then PassiveCondFactory[self.passiveData.condition](self) end self:initFilter() if self._initDB then self:_initDB(data) end end function Passive:initFilter() local filterList = self.passiveData.filter:toTableArray(true) for _, fParams in ipairs(filterList) do local filter = Filter.new({owner = self.owner, skill = self, oType = fParams[1], fType = fParams[2], value = fParams[3] }) table.insert(self.filters, filter) end end function Passive:getCondType() return self.passiveData.condition, self.passiveData.value end -- effect 生效篩選 function Passive:canEffect(effType, effValue) if self.owner.lock and effType ~= 3 then -- 锁定的只能触发翻开自己格子的固有技 return end --禁用被动技 local count = self.owner:getDisablePassiveCount() local idx = self.owner:getPassiveIdx(self) if count and idx and (count == 0 or idx <= count) then return end return true end function Passive:effect(triggerPms) local hadEffect = false for _, effect in ipairs(self.effects) do local effType = effect[1] local effValue = effect[2] local otherPms = {} for i = 3, #effect do table.insert(otherPms, effect[i]) end if self:canEffect(effType, effValue) then hadEffect = true self["effect" .. effType](self, effValue, triggerPms, table.unpack(otherPms)) end end if hadEffect then self.owner.battle.adv:pushBackEvent(AdvBackEventType.PassiveEffect, {id = self.id, level = self.level, roomId = self.owner.roomId, blockId = self.owner.blockId}) buglog("Passive", "who: %s effect id: %s", self.owner.monsterId, self.id) end if self.count > 0 then self.count = self.count < 999 and self.count - 1 or self.count self.round = self.passiveData.round end if self.count <= 0 then -- 次数 <= 0 并且一次冒险内不刷新,被动可以直接移除 self.isDel = true end end function Passive:afterRound() if self.isDel or self.owner.isDead or self.owner.lock or self:isHide() then return end if self.round > 0 then --回合触发的 self.round = self.round - 1 end if self.delay > 0 then self.delay = self.delay - 1 end if self._afterRound then self:_afterRound() --有的触发自己检测在这里检查 end end function Passive:afterLayer() if self.passiveData.mapLock == 1 or self.passiveData.floorType == 1 then self.isDel = true end end -- 在当前阶段不可用 小透明 < 不会回合遍历 不会查找遍历 可以删除遍历 可以下层遍历 > function Passive:isHide() if self.isDel then return true end if self.passiveData.mapLock == 1 and self.mapId and self.owner.battle.adv:getCurMap().mapId ~= self.mapId then return true end return false end -- 可以触发 function Passive:canTrigger( ) return self.count > 0 and self.delay <= 0 and not self:isHide() end function Passive:trigger(condType, params) --触发检查 params = params or {} if self.isDel or self.owner.isDead then return end if self:getCondType() ~= condType then return end buglog("Passive", "who: %s trigger id: %s", self.owner.monsterId, self.id) if not self:canTrigger() then return end if self._trigger then if not self:_trigger(params) then return end --检查 end if not self:filter(params) then return end if math.randomInt(1, 100) > self.passiveData.chance then return end if self.round and self.round > 0 then -- cd return end self:effect(params) end function Passive:filter(params) for _, filter in ipairs(self.filters) do if not filter:execute(params) then return end end return true end function Passive:getDB() local db = {} if self._getDB then db = self:_getDB() end db.id = self.id db.level = self.level db.round = self.round db.count = self.count db.delay = self.delay if self.mapId then db.mapId = self.mapId end return db end --默认=0=使用技能, function Passive:effect0(value) self.owner:releaseSkill(value) end --1=自身获得buff function Passive:effect1(value) self.owner:addBuff(value, self.owner) end --2=触发目标获得buff function Passive:effect2(value, triggerPms) local aim = triggerPms.trigger or self.owner.battle.player if aim then aim:addBuff(value, self.owner) end end --3=翻开自己所在格子 function Passive:effect3(value) if not self.owner.roomId or not self.owner.blockId then return end if value == 0 then self.owner.battle.adv:getCurMap():openBlock(self.owner.roomId, self.owner.blockId) elseif value > 0 then self.owner.battle.adv:getCurMap():openBlocksBySize(self.owner.roomId, self.owner.blockId, value) elseif value == -1 then -- 当前房间 self.owner.battle.adv:getCurMap():openBlocksByRoom(self.owner.roomId) elseif value == -2 then -- 当前层 self.owner.battle.adv:getCurMap():openAllBlocks(not self.owner.monsterId) end end --4=逃跑 function Passive:effect4() self.owner.isDead = 1 --跑了 end --5=召唤怪物 function Passive:effect5(monsterId) for _, buff in ipairs(self.owner.battle.player.buffs) do if not buff.isDel and buff:getType() == buff.Buff_NO_PASSIVE_MONSTER then local effect = buff:effect() if effect == 0 or effect == monsterId then return end end end self.owner.battle.adv:getCurMap():addNewMonsterRand(monsterId) self.owner.battle.adv:pushBackEvent(AdvBackEventType.Monster, {id = monsterId}) end --6=给所有场上怪物增加buff 《 限定 怪 id》 function Passive:effect6(value, triggerPms, enemyId) local aims = self.owner.battle.player:getTeam(2) for k , aim in pairs(aims) do if not enemyId or enemyId == 0 or aim.monsterId == enemyId then aim:addBuff(value, self.owner) end end end --7=给自己加一個被動技能 --废弃 -- function Passive:effect7(value) -- self.owner:addPassive({id = value}) -- end --8=获得drop,直接进入背包 function Passive:effect8(dropId) local dropData = csvdb["event_dropCsv"][dropId] if not dropData then skynet.error(string.format("CSVDATA Error adv_map_passive %s effect 8 not id %s in event_drop", self.id, dropId)) end local item = dropData["range"]:randWeight(true) self.owner.battle.adv:award({[item[1]] = item[2]}, {log = {desc = "passive", int1 = self.id}}, {roomId = self.owner.roomId, blockId = self.owner.blockId}) end --9=直接获得item(可在结算触发时使用) function Passive:effect9(itemId, triggerPms, ratio, ratio2, max) local cond = nil if self.passiveData.value == 0 then cond = triggerPms.score elseif self.passiveData.value == 1 then cond = triggerPms.level else return end if not cond then return end self.owner.battle.adv:award({[itemId] = math.floor(math.max(0, math.min(max, cond / ratio * ratio2)))}, {log = {desc = "passive", int1 = self.id}}, {roomId = self.owner.roomId, blockId = self.owner.blockId}) end --10=战斗额外掉落次数 function Passive:effect10(count, triggerPms) if triggerPms.drops then for _, drop in pairs(triggerPms.drops) do drop[2] = drop[2] + math.floor(drop[2] * count) end end end -- 将地图上的A事件替换成B事件 function Passive:effect11(eventTypeF, triggerPms, eventIdF, eventTypeT, eventIdT, count) local change = self.owner.battle.adv:getCurMap():eventChangeToOther(eventTypeF, eventIdF, eventTypeT, eventIdT, count) for _, one in ipairs(change) do self.owner.battle.adv:backBlockChange(one[1].roomId, one[2].blockId) end end -- 在指定地点召唤event项目 function Passive:effect12(eventType, triggerPms, eventId, count, stage) local change = self.owner.battle.adv:getCurMap():layEventToStage(eventType, eventId, count, stage) for _, one in ipairs(change) do self.owner.battle.adv:backBlockChange(one[1].roomId, one[2].blockId) end end -- 移除指定项目 function Passive:effect13(eventType, triggerPms, eventId, count) local exclude = {} if self.owner:is("Enemy") then exclude[self.owner.roomId] = {[self.owner.blockId] = 1} end local change = self.owner.battle.adv:getCurMap():clearEventById(eventType, eventId, count, exclude) for _, one in ipairs(change) do self.owner.battle.adv:backBlockChange(one[1].roomId, one[2].blockId) end end --14=给所有场上怪物增加buff 《 限定 怪 id》 除了自己 function Passive:effect14(value, triggerPms, enemyId) local aims = self.owner.battle.player:getTeam(2) for k , aim in pairs(aims) do if aim ~= self.owner then if not enemyId or enemyId == 0 or aim.monsterId == enemyId then aim:addBuff(value, self.owner) end end end end --15=翻开房间内的count 个怪 并且增加一个buff function Passive:effect15(count, triggerPms, buffId) local roomId = self.owner.roomId if not roomId then return end local enemys = self.owner.battle.adv:getCurMap():openBlocksIsMonsterByRoom(roomId, count) for _, e in ipairs(enemys) do e:addBuff(buffId) end end --16=转变 value 范围内的掉落物 为 id count function Passive:effect16(value, triggerPms, changeType) if not self.owner.roomId or not self.owner.blockId then return end local blocks = self.owner.battle.adv:getCurMap():getBlocksBySize(self.owner.roomId, self.owner.blockId, value) self.owner.battle.adv:blockDropChange(changeType, blocks) end --17=玩家获得buff function Passive:effect17(value, triggerPms) self.owner.battle.player:addBuff(value, self.owner) end return Passive