AdvBuff.lua 10.5 KB

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(每回合)

--角色一些属性的变化
local function commonAttr(_Buff, attrName)
	_Buff._init = function(self, data) --初始化变化值
		self.owner:reSetAttr(attrName)
	end
	_Buff._effectValue = function(self)
		return self.buffData.effectValue1, self.buffData.effectValue2
	end
	_Buff._endBuff = function(self, data)
		self.owner:reSetAttr(attrName)
	end
end

local BuffFactory = {
	[Buff.HP_CHANGE] = function(_Buff)
		_Buff._init = function(self, data) --初始化变化值
			self._changeV = 0
			if self.buffData.effectValue1 == 0 then --固定值
				self._changeV = 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"}
				self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 / 100
			end
			if self._changeV < 0 then
				if self.release then
					self._changeV = -self.release:getHurtValue(-self._changeV)
				end
			end
		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._changeV
		end
		_Buff._getDB = function(self)
			return {cv = self._changeV}
		end
	end,

	[Buff.HP_MAX_CHANGE] = function(_Buff)
		_Buff._init = function(self, data) --初始化变化值
			self._changeV = 0
			if self.buffData.effectValue1 == 0 then --固定值
				self._changeV = 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"}
				self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 / 100
			end
			local old = self.owner.hpMax
			self.owner.hpMax = math.max(1, self.owner.hpMax + self._changeV)
			self._changeV = self.owner.hpMax - old
			if self._changeV > 0 then
				self.owner:recover(self._changeV, self.release) -- 防止release不存在,地图点buff
			elseif self._changeV < 0 then
				self.owner:hurt(self.release and self.release:getHurtValue(-self._changeV) or -self._changeV, self.release, {hurtType = 2, buffId = self.id})
				self.owner.hp = math.min(self.owner.hpMax, self.owner.hp)
			end
		end
		_Buff._initDB = function(self, data)
			self._changeV = data.cv
		end
		_Buff._endBuff = function(self, data)
			if self._changeV then
				self.owner.hpMax = math.max(1, self.owner.hpMax - self._changeV)
				self.owner.hp = math.min(self.owner.hpMax, self.owner.hp)
			end
		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.BACK_HURT] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2, self.buffData.effectValue3
		end
	end,

	[Buff.HURT_CHANGE] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2
		end
	end,

	[Buff.INJURED_CHANGE] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2
		end
	end,

	[Buff.HURT_TRANSFER] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2
		end
	end,

	[Buff.HURT_ABSORB] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2
		end
	end,
	
	[Buff.CHANGE_DROP] = function(_Buff)
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1, self.buffData.effectValue2
		end
	end,

	[Buff.IMMNUE_BUFF] = function(_Buff)
		_Buff._init = function(self, data)
			self.count = self.buffData.effectValue3
		end
		_Buff._canEffect = function(self, buffId, buffGroup)
			local cType, aim = self.buffData.effectValue1, self.buffData.effectValue2
			if (cType == 0 and buffId == aim) or (cType == 1 and buffGroup == aim) then
				return true
			end
		end
	end,

	[Buff.CLEAR_BUFF] = function(_Buff)
		_Buff._init = function(self, data)
			self.count = self.buffData.effectValue3
			for _, buff in ipairs(self.buffs) do -- 挂上就清除一下子
				if not buff.isDel and self:canEffect(buff.id, buff:getGroup()) then
					buff.isDel = true
					self:effect()
				end
			end 
		end
		_Buff._canEffect = function(self, buffId, buffGroup)
			local cType, aim = self.buffData.effectValue1, self.buffData.effectValue2
			if (cType == 0 and buffId == aim) or (cType == 1 and buffGroup == aim) then
				return true
			end
		end
	end,

	[Buff.OPEN_BLOCK] = function(_Buff)
		_Buff._afterRound = function(self)
			local roomNum = self:effect()
			self.owner.battle.adv:openBlockRand(roomNum)
		end
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1
		end
	end,

	[Buff.SP_CHANGE] = function(_Buff)
		--cType 0 or nil  值  1 百分比
		_Buff._afterRound = function(self)
			local value, cType = self:effect()
			self.owner:changeSp(value, cType)
		end
		_Buff._effectValue = function(self)
			return self.buffData.effectValue2, self.buffData.effectValue1
		end
	end,

	[Buff.HP_CHANGE_NOW] = function(_Buff)
		_Buff._init = function(self, data) --初始化变化值
			self._changeV = 0
			if self.buffData.effectValue1 == 0 then --固定值
				self._changeV = 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"}
				self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 / 100
			end
			if self._changeV < 0 then
				self._changeV = self.release and -self.release:getHurtValue(-self._changeV) or self._changeV
			end
		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._changeV
		end
		_Buff._getDB = function(self)
			return {cv = self._changeV}
		end
	end,

	[Buff.EXP_ADD] = function(_Buff)
		--cType 0 or nil  值  1 百分比
		_Buff._afterRound = function(self)
			local value = self:effect()
			self.owner.battle.player:addExp(value)
		end
		_Buff._effectValue = function(self)
			return self.buffData.effectValue1
		end
	end,
}

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 无次数限制

	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.round = self.buffData.round
	if self.buffData.effectTime > 0 then
		self.count = self.buffData.effectTime
	end
	if self._init then
		self:_init(data)
	end
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.round = data.round
	self.roundSpace = data.roundSp -- 可以优化为0的时候不记录
	if data.count then
		self.count = data.count
	end

	if self._initDB then
		self:_initDB(data)
	end
end


function Buff:afterRound()
	if self.isDel or self.owner.isDead then 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

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:canEffect(...)
	if not self._canEffect then
		return true
	end
	return self:_canEffect(...)
end

function Buff:effect()
	self:decCount()
	if self._effectValue then
		return self:_effectValue()
	end
end
--删除buff 时调用
function Buff:endBuff()
	if self._endBuff then
		self:_endBuff()
	end
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:getGroup()
	return self.buffData.group
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
	return db
end

return Buff