local Buff = class("Buff") Buff.HP_CHANGE = 1 --生命变化(每回合生效) Buff.HP_MAX_CHANGE = 2 --生命上限变化(状态) Buff.ATTR_CHANGE = 3 --属性变化(状态) Buff.IMMNUE_ATK = 4 -- 免疫普通攻击 Buff.BACK_HURT = 5 -- 伤害反弹 Buff.HURT_CHANGE = 6 -- 伤害变化 Buff.INJURED_CHANGE = 7 -- 受伤变化 Buff.HURT_TRANSFER = 8 -- 侍宠(转移自己受到的伤害) Buff.HURT_ABSORB = 9 -- 舍身(吸收他人受到的伤害) Buff.CANT_BACK_ATK = 10 -- 无法反击 Buff.IMMNUE_BUFF = 11 -- 免疫buff Buff.CLEAR_BUFF = 12 -- 清除buff Buff.CANT_SKILL = 13 -- 禁止技能 Buff.OPEN_BLOCK = 14 -- 翻开格子(每回合) Buff.SP_CHANGE = 15 -- sp变化(每回合) Buff.HP_CHANGE_NOW = 16 -- 生命变化(每回合生效,立刻生效) Buff.BATTLE_BUFF = 17 -- 切换为战斗中的buff Buff.CHANGE_DROP = 18 -- 转换掉落 Buff.BATTLE_PASSIVE = 19 -- 切换为战斗中的被动技 -- Buff.EXP_ADD = 20 -- 增加exp(每回合) Buff.DONT_DEFEND = 21 -- 不看守地板 -- 怪周围点半可点击 Buff.SHOW_DANGER = 22 -- 扫雷 展示地上怪物和陷阱数量的标记 Buff.SHOW_MONSTER_POS = 23 -- 蓝臂章训练场 感知 Buff.EXP_UP = 24 -- 杀敌经验提高 Buff.DISABLE_BUFF = 25 -- 禁用固有技 Buff.ATTR_CHANGE_COND = 26 --属性变化(状态)有条件 Buff.CHANGE_DROP_TO_CLICK = 27 --掉落转换为click Buff.SP_MAX_CHANGE = 28 -- 魔法上限 Buff.ITEM_GET_UP = 29 -- 获得道具数量增加 Buff.Buff_EFFECT_CHANGE = 30 -- 改变 buff 效果 Buff.Buff_NO_PASSIVE_MONSTER = 31 -- 地图被动刷新不出来怪物 Buff.SNEAK = 32 --潜行 Buff.DROP_BUFF_BY_ENEMY = 33 -- 怪物掉落加成 -- 怪物使用 Buff.GET_PASSIVE = 34 -- 获得 passive -- 结束失效 Buff.OBSTACLE_CHANGE = 35 -- 看守类型改变 -- 怪物使用 2 - 1 Buff.DISABLE_AURA = 36 -- 禁用光环 Buff.GET_AURA = 37 -- 获得光环 Buff.OBSTACLE_PLUS = 38 -- 周围8格不能点击 --角色一些属性的变化 local function commonAttr(_Buff, attrName) _Buff._init = function(self) --初始化变化值 self.owner:reSetAttr(attrName) end _Buff._effectValue = function(self) return self.buffData.effectValue1, self:doEffectChange(self.buffData.effectValue2) * self.layer, attrName end _Buff._overlay = function(self) self.owner:reSetAttr(attrName) end _Buff._uncover = function(self) self.owner:reSetAttr(attrName) end _Buff._endBuff = function(self, data) self.owner:reSetAttr(attrName) end _Buff._effectChange = function(self) self.owner:reSetAttr(attrName) end end local function commonAttCond(_Buff, attrName) _Buff._init = function(self) --初始化变化值 self:_reSetAttr() end _Buff._overlay = function(self) self:_reSetAttr() end _Buff._uncover = function(self) self:_reSetAttr() end _Buff._reSetAttr = function(self) if attrName == "hp" then self.owner:reSetHpMax() else self.owner:reSetAttr(attrName) end end _Buff._calculate = function(self) local effectCount = 0 if self.buffData.effectValue4 == 0 then effectCount = self.owner.battle.adv.owner:getProperty("advItems"):getv(ItemId.OldCoin, 0) / tonumber(self.buffData.effectValue5) elseif self.buffData.effectValue4 == 1 then effectCount = self.owner.battle.adv.level elseif self.buffData.effectValue4 == 2 then local buff = self.owner.battle.player:getBuffById(tonumber(self.buffData.effectValue5)) if buff then effectCount = buff.layer end elseif self.buffData.effectValue4 == 3 then local classify = tonumber(self.buffData.effectValue5) -- 怪标签 local enemy = self.owner.battle.player:getTeam(2) for _, one in pairs(enemy) do if one.isClassify and one:isClassify(classify) then effectCount = effectCount + 1 end end elseif self.buffData.effectValue4 == 4 then local eventType = tonumber(self.buffData.effectValue5) -- event 类型 effectCount = #self.owner.battle.adv:getCurMap():getEventTypeAllMap(eventType) end return self.buffData.effectValue2 * effectCount end _Buff.getEffectBy = function(self) local cond = nil if self.buffData.effectValue4 == 2 or self.buffData.effectValue4 == 3 or self.buffData.effectValue4 == 4 then cond = tonumber(self.buffData.effectValue5) end return self.buffData.effectValue4, attrName, cond end _Buff._effectValue = function(self) return self.buffData.effectValue1, self:_calculate() * self.layer, attrName end _Buff._endBuff = function(self, data) self:_reSetAttr() end end local BuffFactory = { [Buff.HP_CHANGE] = function(_Buff) _Buff._init = function(self) --初始化变化值 self._changeV = self:_calculate() end _Buff._overlay = function(self) self._changeV = (self._changeV or 0) + self:_calculate() end _Buff._uncover = function(self) self._changeV = self._changeV - self._changeV / (self.layer + 1) end _Buff._calculate = function(self) local curValue = 0 if self.buffData.effectValue1 == 0 then --固定值 curValue = self.buffData.effectValue2 elseif self.buffData.effectValue1 == 1 then local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} curValue = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 / 100 end if curValue < 0 then if self.release then curValue = -self.release:getHurtValue(-curValue) end end return curValue end _Buff._initDB = function(self, data) self._changeV = data.cv end _Buff._afterRound = function(self) local value = self:effect() if value > 0 then self.owner:recover(value, self.release) elseif value < 0 then self.owner:hurt(-value, self.release, {hurtType = self.buffData.effectValue5 == "1" and 6 or 2, buffId = self.id}) end end _Buff._effectValue = function(self) return self:doEffectChange(self._changeV) end _Buff._getDB = function(self) return {cv = self._changeV} end end, [Buff.HP_MAX_CHANGE] = function(_Buff) _Buff._init = function(self) --初始化变化值 self._changeV = self:_calculate() local old = self.owner.hpMax self.owner:reSetHpMax() self:_addHpByMax(old) end _Buff._overlay = function(self) self._changeV = (self._changeV or 0) + self:_calculate() local old = self.owner.hpMax self.owner:reSetHpMax() self:_addHpByMax(old) end _Buff._uncover = function(self) self._changeV = self._changeV - self._changeV / (self.layer + 1) self.owner:reSetHpMax() end _Buff._calculate = function(self) local curValue = 0 if self.buffData.effectValue1 == 0 then --固定值 curValue = self.buffData.effectValue2 elseif self.buffData.effectValue1 == 1 then local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} curValue = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 / 100 end return curValue end _Buff._effectValue = function(self) return self:doEffectChange(self._changeV) end _Buff._addHpByMax = function(self, old) if self.buffData.effectValue5 == "1" then local change = self.owner.hpMax - old if change > 0 then self.owner:recover(change, self.release) -- 防止release不存在,地图点buff end end end _Buff._endBuff = function(self) self.owner:reSetHpMax() end _Buff._effectChange = function(self) self.owner:reSetHpMax() end _Buff._initDB = function(self, data) self._changeV = data.cv end _Buff._getDB = function(self) return {cv = self._changeV} end end, [Buff.ATTR_CHANGE] = function(_Buff) local attrName = AttsEnumEx[_Buff.buffData.effectValue3] commonAttr(_Buff, attrName) end, [Buff.ATTR_CHANGE_COND] = function(_Buff) local attrName = AttsEnumEx[_Buff.buffData.effectValue3] commonAttCond(_Buff, attrName) end, [Buff.CHANGE_DROP_TO_CLICK] = function(_Buff) _Buff._effectValue = function(self) -- id return self.buffData.effectValue1 end end, [Buff.IMMNUE_BUFF] = function(_Buff) _Buff._canEffect = function(self, buffId) local buffData = csvdb["adv_map_buffCsv"][buffId] local cType, aim = self.buffData.effectValue1 if buffData.dispel ~= 0 then return end local dispel = false if self.buffData.effectValue1 == 0 then dispel = buffId == self.buffData.effectValue2 elseif self.buffData.effectValue1 == 1 then dispel = buffData.group == self.buffData.effectValue2 elseif self.buffData.effectValue1 == 2 then dispel = buffData.classify:sismember(self.buffData.effectValue2, " ") end return dispel end end, [Buff.CLEAR_BUFF] = function(_Buff) _Buff._init = function(self) for _, buff in ipairs(self.owner.buffs) do -- 挂上就清除一下子 if not buff.isDel and self:canEffect(buff.id) and not self.isDel then while not buff.isDel and not self.isDel do self:effect() buff:uncover() end end end end _Buff._canEffect = function(self, buffId) local buffData = csvdb["adv_map_buffCsv"][buffId] local cType, aim = self.buffData.effectValue1 if buffData.dispel ~= 0 then return end local dispel = false if self.buffData.effectValue1 == 0 then dispel = buffId == self.buffData.effectValue2 elseif self.buffData.effectValue1 == 1 then dispel = buffData.group == self.buffData.effectValue2 elseif self.buffData.effectValue1 == 2 then dispel = buffData.classify:sismember(self.buffData.effectValue2, " ") end return dispel end end, [Buff.OPEN_BLOCK] = function(_Buff) _Buff._afterRound = function(self) local roomNum = self:effect() self.owner.battle.adv:getCurMap():openBlockRand(roomNum, not self.owner.monsterId) end _Buff._effectValue = function(self) -- 数量 return self.buffData.effectValue1 * self.layer end end, [Buff.SP_CHANGE] = function(_Buff) _Buff._afterRound = function(self) local cType, value = self:effect() self.owner:changeSp(value, cType) end _Buff._effectValue = function(self) -- 值/% 数量 return self.buffData.effectValue1, self:doEffectChange(self.buffData.effectValue2) * self.layer end end, -- [Buff.EXP_ADD] = function(_Buff) -- _Buff._afterRound = function(self) -- local value = self:effect() -- self.owner.battle.player:addExp(value) -- end -- _Buff._effectValue = function(self) -- -- 经验值 -- return self.buffData.effectValue1 * self.layer -- end -- end, [Buff.DISABLE_BUFF] = function(_Buff) _Buff._effectValue = function(self) return self.buffData.effectValue1 end end, [Buff.DISABLE_AURA] = function(_Buff) _Buff._effectValue = function(self) return self.buffData.effectValue1 end end, [Buff.GET_AURA] = function(_Buff) _Buff._effectValue = function(self) return self.buffData.effectValue1 end end, [Buff.SP_MAX_CHANGE] = function(_Buff) _Buff._init = function(self) --初始化变化值 self.owner:reSetSpMax() end _Buff._overlay = function(self) self.owner:reSetSpMax() end _Buff._uncover = function(self) self.owner:reSetSpMax() end _Buff._endBuff = function(self) self.owner:reSetSpMax() end _Buff._effectValue = function(self) return self.buffData.effectValue1, self.buffData.effectValue2 * self.layer end end, [Buff.ITEM_GET_UP] = function(_Buff) _Buff._effectValue = function(self) -- 值/% 数量 id return self.buffData.effectValue1, self.buffData.effectValue2 * self.layer, self.buffData.effectValue3 end end, -- 影响到的buff类型 1=生命变化、2=生命上限、3=属性变化、6=伤害变化、7=受伤变化、15=回魔、16=生命变化 (胡博文) [Buff.Buff_EFFECT_CHANGE] = function(_Buff) _Buff._init = function(self) -- 先给自己的buff 搞一下子 for _, buff in ipairs(self.owner.buffs) do if not buff.isDel and buff.buffData.classify:sismember(self.buffData.effectValue1, " ") then buff:effectChange() end end end _Buff._effectValue = function(self) return self.buffData.effectValue1, self.buffData.effectValue2 * self.layer end _Buff._overlay = function(self) self:_init() end _Buff._uncover = function(self) self:_init() end end, [Buff.Buff_NO_PASSIVE_MONSTER] = function(_Buff) _Buff._effectValue = function(self) return self.buffData.effectValue1 end end, [Buff.SNEAK] = function(_Buff) _Buff._init = function(self) self.layer = self.buffData.effectValue1 end end, [Buff.GET_PASSIVE] = function( _Buff ) _Buff._init = function(self) self.owner:addPassive({id = self.buffData.effectValue1}) end _Buff._endBuff = function(self) self.owner:delPassiveById(self.buffData.effectValue1) end end } -- 同样的返回 effectValue1, effectValue2 * self.layer 类型的buff local function CommonFuncBackEffect12(_Buff) _Buff._effectValue = function(self) return self.buffData.effectValue1, self:doEffectChange(self.buffData.effectValue2) * self.layer end end BuffFactory[Buff.BACK_HURT] = CommonFuncBackEffect12 -- 值/% 数量 BuffFactory[Buff.HURT_CHANGE] = CommonFuncBackEffect12 -- 值/% 数量 BuffFactory[Buff.INJURED_CHANGE] = CommonFuncBackEffect12 -- 值/% 数量 BuffFactory[Buff.HURT_TRANSFER] = CommonFuncBackEffect12 -- 值/% 数量 BuffFactory[Buff.HURT_ABSORB] = CommonFuncBackEffect12 -- 值/% 数量 BuffFactory[Buff.CHANGE_DROP] = CommonFuncBackEffect12 -- id 数量 BuffFactory[Buff.EXP_UP] = CommonFuncBackEffect12 -- 值/% 数量 -- 历史遗留问题 BuffFactory[Buff.HP_CHANGE_NOW] = BuffFactory[Buff.HP_CHANGE] function Buff:ctor(owner, id) self.owner = owner self.id = id self.buffData = csvdb["adv_map_buffCsv"][self.id] self.isDel = false self.roundSpace = 0 --生效间隔 self.round = 0 --剩余的回合 self.count = -1 -- 可生效的次数 -1 无次数限制 self.layer = 1 -- 当前buff 层数 self.releaseId = nil -- 释放的怪物Id if BuffFactory[self.buffData.type] then BuffFactory[self.buffData.type](self) end end function Buff.create(owner, release, data) local buff = Buff.new(owner, data.id) buff:initNew(release, data) return buff end function Buff.load(owner, data) local buff = Buff.new(owner, data.id) buff:initByDB(data) return buff end function Buff:initNew(release, data) self.release = release or self.owner self.releaseId = self.release.monsterId or 0 self.round = self.buffData.round self.roundSpace = 0 --生效间隔 self.layer = 1 if self.buffData.effectTime > 0 then self.count = self.buffData.effectTime end if self.buffData.mapLock == 1 then self.mapId = self.owner.battle.adv:getCurMap().mapId end end function Buff:createAfter(layer) layer = layer or 1 local otype, maxLayer = self:getOverlay() if otype then self.layer = layer if maxLayer ~= 0 then self.layer = math.min(maxLayer, self.layer) end else self.layer = 1 end if self._init then self:_init() end self:pushBackEffect(1) buglog("Buff", "who: %s create buffId: %s", self.owner.monsterId, self.id) end function Buff:initByDB(data) if data.rele then if data.rele == 0 then self.release = self.owner.battle.player else self.release = self.owner.battle:getEnemyById(data.rele) end end self.releaseId = data.releId self.round = data.round self.roundSpace = data.roundSp if data.count then self.count = data.count end if data.mapId then self.mapId = data.mapId end self.layer = data.layer or 1 if self._initDB then self:_initDB(data) end end function Buff:afterRound() if self.owner.isDead or self:isHide() then return end -- keepTerm 检查 if not self:checkKeep() then self.isDel = true return end if self.roundSpace > 0 then self.roundSpace = self.roundSpace - 1 self:decRound() return end if self._afterRound then self:_afterRound() end if self.buffData.roundTime > 0 then self.roundSpace = self.buffData.roundTime end self:decRound() end -- 只使用owner 和 buffData 和 releaseId function Buff:checkKeep() if self.buffData.keepTerm == "" then return true end --[[ 1=怪物id; 2=建筑id; 3=事件id 4=队伍为特定属性时 5=拥有指定buff --]] local checkFunc = {} checkFunc[1] = function(_) local enemys = self.owner.battle.player:getTeam(2) for _, enemy in pairs(enemys) do if enemy.monsterId == self.releaseId then return true end end return false end checkFunc[2] = function(_, buildId) for roomId, room in pairs(self.owner.battle.adv:getCurMap().rooms) do for blockId, block in pairs(room.blocks) do if block.isOpen and block:getEventType() == AdvEventType.Build and block.event.id == buildId then return true end end end return false end checkFunc[3] = function(_, chooseId) for roomId, room in pairs(self.owner.battle.adv:getCurMap().rooms) do for blockId, block in pairs(room.blocks) do if block.isOpen and (block:getEventType() == AdvEventType.Choose or block:getEventType() == AdvEventType.LinkChoose) and block.event.id == chooseId then return true end end end return false end checkFunc[4] = function(_, teamAttr) local role = self.owner.battle.adv.owner return role:getHerosCamp(role:getProperty("advTeam").heros) == teamAttr end checkFunc[5] = function(_, buffId) local buff = self.owner:getBuffById(buffId) if buff then return true end return false end local keepTerm = self.buffData.keepTerm:toArray(true, "=") if not checkFunc[keepTerm[1]] then return true end return checkFunc[keepTerm[1]](table.unpack(keepTerm)) end function Buff:decRound() if self.buffData.round <= 0 then return end self.round = self.round - 1 if self.round <= 0 then self.isDel = true end end function Buff:afterLayer() -- 持续一层 if self.buffData.round == 0 or self.buffData.mapLock == 1 then self.isDel = true end end function Buff:canEffect(...) if not self._canEffect then return true end return self:_canEffect(...) end function Buff:pushBackEffect(etype) local shows = self.buffData.show:toTableArray(true) for _, one in ipairs(shows) do if one[1] == etype then self.owner.battle.adv:pushBackEvent(AdvBackEventType.BuffEffect, {etype = etype, id = self.id, blockId = self.owner.blockId, roomId = self.owner.roomId}) break end end end function Buff:effect() buglog("Buff", "who: %s effect buffId: %s", self.owner.monsterId, self.id) self:decCount() self:pushBackEffect(2) if self._effectValue then return self:_effectValue() end end -- 在当前阶段不可用 小透明 < 不会回合遍历 不会查找遍历 可以删除遍历 可以下层遍历 > function Buff:isHide() if self.isDel then return true end if self.buffData.mapLock == 1 and self.mapId and self.owner.battle.adv:getCurMap().mapId ~= self.mapId then return true end return false end --删除buff 时调用 function Buff:endBuff() if self._endBuff then self:_endBuff() end buglog("Buff", "who: %s endBuff buffId: %s", self.owner.monsterId, self.id) end function Buff:getType() return self.buffData.type end function Buff:decCount() if self.count == -1 then return end self.count = self.count - 1 if self.count <= 0 then self.isDel = true end end function Buff:getOverlay() if self.buffData.overlay == "" then return false end local otype, layer = table.unpack(self.buffData.overlay:toArray(true, "=")) if otype == 1 then -- 叠加 return true, layer or 0 -- 0 叠加无数层 end return false end -- 叠加 function Buff:overlay(releaser, data, layer) local otype, maxLayer = self:getOverlay() if self.isDel or not otype then -- 新获得的 (不可叠加相当于新获得的) self:endBuff() self.isDel = false self:initNew(releaser, data) self:createAfter(layer) else -- 重置回合 次数 self.roundSpace = 0 self.round = self.buffData.round if self.buffData.effectTime > 0 then self.count = self.buffData.effectTime else self.count = -1 end self.release = releaser or self.release -- 叠加层数 local oldLayer = self.layer self.layer = self.layer + layer if maxLayer ~= 0 then self.layer = math.min(maxLayer, self.layer) end if oldLayer ~= self.layer and self._overlay then self:_overlay() end self:pushBackEffect(1) buglog("Buff", "who: %s overlay buffId: %s", self.owner.monsterId, self.id) end end -- 扣减层数 function Buff:uncover(layer, isAura) layer = layer or 1 local oldLayer = self.layer self.layer = self.layer - layer if self.layer <= 0 then self.isDel = true end if isAura then if layer == -1 then self.layer = 0 self.isDel = true else self.layer = math.max(1, self.layer) self.isDel = false end end if self.isDel then return end if oldLayer ~= self.layer then if self._uncover then self:_uncover() end end end -- buff 效果增益减益 function Buff:effectChange() if self._effectChange then self:_effectChange() end end function Buff:doEffectChange(effect) if self.buffData.classify == "" then return effect end local change = self.owner:getBuffEffectChange(self.buffData.classify) return effect * (1 + change) end function Buff:getLayer() return self.layer end function Buff:getDB() local db = {} if self._getDB then db = self:_getDB() end db.id = self.id if self.release and not self.release.isDead then db.rele = self.release.id or 0 --释放者的id (0 为玩家) (不存在 则释放者不存在或者已经死亡) end if self.buffData.round > 0 then db.round = self.round end db.roundSp = self.roundSpace if self.count ~= -1 then db.count = self.count end if self.mapId then db.mapId = self.mapId end db.layer = self.layer if self.buffData.keepTerm:toArray(true, "=")[1] == 1 then db.releId = self.releaseId end return db end return Buff