AdvPlayer.lua 10.7 KB
-- 角色
local Buff = require "adv.AdvBuff"
local Passive = require "adv.AdvPassive"

local BaseObject = class("BaseObject")
function BaseObject:ctor(battle)
	self.battle = battle
	self.hpMax = 0
	self.hp = 0
	self.atk = 0
	self.aType = 0 --攻击类型
	self.lock = nil
	self.passives = {} --固有技能
	self.buffs = {} --buff
	self.isDead = false
end
--初始化角色
function BaseObject:initData(data)
	self.hpMax = data.hpMax or data.hp
	self.hp = data.hp
	--可变化的值
	self.atk = data.atk
	self.miss = data.miss
	self.hit = data.hit
	--基础值记录
	self._atk = data._atk or self.atk
	self._miss = data._miss or self.miss
	self._hit = data._hit or self.hit
end
-- 角色初始化完以后才是 技能和被动技能  方便初始化 buff 的 释放对象
function BaseObject:initAfter(data)
	for _, passive in ipairs(data.passives or {}) do
		table.insert(self.passives, Passive.load(self, passive))
	end
	for _, buff in ipairs(data.buffs or {}) do
		table.insert(self.buffs, Buff.load(self, buff))
	end
end

function BaseObject:afterRound()
	for _, passive in ipairs(self.passives) do
		passive:afterRound(self)
	end
	for _, buff in ipairs(self.buffs) do
		buff:afterRound(self)
	end
end

function BaseObject:clearRound()
	for i = #self.passives, 1, -1 do
		if self.passives[i].isDel then
			self.passives[i]:endPassive()
			table.remove(self.passives, i)
		end
	end
	for i = #self.buffs, 1, -1 do
		if self.buffs[i].isDel then
			self.buffs[i]:endBuff()
			table.remove(self.buffs, i)
		end
	end
end
function BaseObject:clear()
	self.buffs = {}
	self.passives = {}
end

function BaseObject:addBuff(buffId, releaser)
	local buffData = csvdb["adv_buffCsv"][buffId]
	if not buffData then return end
	for _, buff in ipairs(self.buffs) do
		if not buff.isDel and (buff:getType() == CLEAR_BUFF or buff:getType() == IMMNUE_BUFF) then
			local cType, aim = buff:effectValue() -- 0=buffid 1=buff组
			if (cType == 0 and buffId == aim) or (cType == 1 and buffData.group == aim) then  -- buff 剔除
				buff:decCount() --减少次数
				return
			end
		end
	end
	table.insert(self.buffs, Buff.create(self, releaser, {id = buffId}))
end

function BaseObject:hadBuff(bType)
	for _, buff in ipairs(self.buffs) do
		if not buff.isDel and buff:getType() == bType then
			return true
		end
	end
end

-- 通用的buff 效果汇总  -- 0 固定 1百分比  两种分类
function BaseObject:getCommonBuffEffect(bType)
	local effect, count = {[0] = 0, [1] = 0}, 0
	for _, buff in ipairs(self.buffs) do
		if not buff.isDel and buff:getType() == bType then
			local cType, value = buff:effectValue()
			if cType then
				change[cType] = change[cType] + value
				count = count + 1
			end
		end
	end
	return effect, count --效果 和生效的buff 个数
end
--伤害反弹
function BaseObject:getBackHurtBuff(isAtk)
	local effect = {[0] = 0, [1] = 0}
	for _, buff in ipairs(self.buffs) do
		if not buff.isDel and buff:getType() == Buff.BACK_HURT then
			local cType, value, aType = buff:effectValue()  --  aType 0 全部  1 普通攻击
			if cType then
				if aType == 0 or isAtk then
					change[cType] = change[cType] + value
				end
			end
		end
	end
	return effect
end

--释放者伤害变化
function BaseObject:getHurtChange()
	local change = self:getCommonBuffEffect(Buff.HURT_CHANGE)
	return change
end
--受伤者受伤变化
function BaseObject:getInjuredChange()
	local change = self:getCommonBuffEffect(Buff.INJURED_CHANGE)
	return change
end
--重新计算属性
function BaseObject:reSetAttr(field)
	self[field] = self["_" .. field] --重置一下
	local fieldToBuff = {atk = Buff.IMMNUE_ATK, hit = Buff.HIT_CHANGE, miss = Buff.MISS_CHANGE}
	local effect = self:getCommonBuffEffect(fieldToBuff[field])
	self[field] = (self[field] + effect[0]) * (1 + effect[1])
end

--计算打出伤害加成后的值 
function BaseObject:getHurtValue(value)
	value = value or self.atk
	local hurtChange = self:getHurtChange()
	return math.max(0, (value + hurtChange[0]) * (1 + hurtChange[1]))
end
--计算自己伤害减免后的值
function BaseObject:getInjuredValue(value)
	local injuredChange = self:getInjuredChange()
	return math.max(0, (value + injuredChange[0]) * (1 + injuredChange[1]))
end

--最终伤害 = [ 敌方攻击 * (1+伤害增加百分比-伤害减少百分比)*(1+受伤增加百分比-受伤减少百分比)+(伤害增加固定值-伤害增加固定值+受伤增加固定值-受伤增加固定值)]*(1+侍宠百分比)-侍宠固定值
-- params   -- hurtType  1 普攻伤害  2 buff伤害  3 反弹伤害
--进入这个方法之前计算好释放者加成的伤害
function BaseObject:hurt(value, releaser, params)
	params = params or {}
	if params.hurtType and params.hurtType == 1 then
		if self:hadBuff(Buff.IMMNUE_ATK) then return end --无视普通攻击
		
		local hit = releaser.hit - self.miss  --命中率
		if hit < math.randomInt(1, 100) then --miss
			return
		end
	end

	value = self:getInjuredValue(value) --减伤计算
	if value == 0 then return end

	-- 舍身和恃宠
	local team = self:getTeam(1)
	local transfer = {}
	local absorb = {}
	for _, one in ipairs(team) do
		local change1, count1 = one:getCommonBuffEffect(Buff.INJURED_CHANGE)
		local change2, count2 = one:getCommonBuffEffect(Buff.HURT_ABSORB)
		if count1 > 0 then
			table.insert(transfer, {one, change1, count1})
		end
		if count2 > 0 then
			table.insert(absorb, {one, change2, count2})
		end
	end
	if #absorb == 1 then --舍身优先级高  --舍身生效
		if absorb[1][1] ~= self then --舍身的人不是自己才有效
			local absorbV = (value - absorb[1][2][0]) * absorb[1][2][1] + absorb[1][2][0]  --固定值先生效
			value = value - absorbV
			absorb[1][1]:hurt(absorbV, releaser, params)
		end
	else
		if #transfer == 1 and transfer[1][1] == self and #team > 1 then --侍宠 生效  
			local transferValue = (value - transfer[1][2][0])* transfer[1][2][1] + transfer[1][2][0] --固定值先生效
			value = value - transferValue
			local oneValue = transferValue / (#team - 1)
			for _, one in ipairs(team) do
				if one ~= self then
					one:hurt(oneValue, releaser, params)
				end
			end
		end
	end

	value = math.max(0, value)
	if value == 0 then return end
	-- 反弹伤害
	if params.hurtType ~= 3 and releaser and not releaser.isDead then
		local backEffect = self:getBackHurtBuff(params.hurtType == 1)
		local backValue = math.max(0, value * backEffect[1] + backEffect[0])
		releaser:hurt(backValue, releaser, {hurtType = 3})
	end

	--受伤了~
	self.hp = math.max(0, self.hp - value)
	if self.hp == 0 then
		self.isDead = true
	end
end
--恢复
function BaseObject:recover(value, releaser, params)
	params = params or {}
	value = math.max(0, value)
	self.hp = math.min(self.hpMax, self.hp + value)
end

function BaseObject:releaseSkill(skillId, skillLevel, target)
	skillLevel = skillLevel or 1
	local skillData = csvdb["adv_skillCsv"][skillId][skillLevel or 1]
	local targetChoose = skillData.target:toArray(true, "=")
	local targetNum = skillData.targetNum:toArray(true, "=")
	--确定目标
	local targets = {}
	if targetChoose[1] == 0 then --选定一个
		assert(target, "error " .. self.class.__cname .. "  releaseSkill id: " .. skillId .." targetChoose==0 but no target")
		table.insert(targets, target)
	elseif targetChoose[1] == 1 then --全部
		if not targetChoose[2] or targetChoose[2] == 0 then
			targets = self:getTeam(0)
		else --指定 monsterId
			local team = self:getTeam(0)
			for _, one in pairs(team) do
				if one.monsterId and one.monsterId == targetChoose[2] then
					table.insert(targets, one)
				end
			end
		end
	elseif targetChoose[1] == 2 then -- 我方
		if targetChoose[2] == 1 then
			table.insert(targets, self)
		elseif targetChoose[2] == 2 then
			targets = self:getTeam(1, true)
		elseif targetChoose[2] == 3 then
			targets = self:getTeam(1)
		end 
	elseif targetChoose[1] == 3 then -- 敌方
		targets = self:getTeam(2)
	end

	if targetChoose[1] ~= 0 then  -- 不是指定一个的进行 排序 和 数量筛选
		local tempT = targets
		local targets = {}
		local function randNum(isSort) 
			if #tempT <= targetNum[2] then
				targets = tempT
				return
			end 
			if isSort then
				for i = 1, targetNum[2] do
					table.insert(targets, tempT[i])
				end
			else
				for i = 1, targetNum[2] do
					local idx = math.randomInt(1, #tempT)
					table.insert(targets, tempT[idx])
					table.remove(tempT, idx)
				end
			end
		end
		if targetNum[1] == 0 then --任意排序
			randNum(false)
		elseif targetNum[1] == 1 then --血量从低到高
			table.sort(tempT, function(o1, o2)
				return o1.hp < o2.hp
			end)
			randNum(true)
		elseif targetNum[1] == 2 then --血量从高到低
			table.sort(tempT, function(o1, o2)
				return o1.hp > o2.hp
			end)
			randNum(true)
		else
			targets = tempT  --all
		end
	end
	-- 增加buff
	for _, buffId in ipairs(skillData.selfbuff:toArray(true, "=")) do
		self:addBuff(buffId, self)
	end

	for _, buffId in ipairs(skillData.targetbuff:toArray(true, "=")) do
		for _, target_ in ipairs(targets) do
			target_:addBuff(buffId, self)
		end
	end
end

--0 全部  1 我方  2 敌方
function BaseObject:getTeam(nType, noSelf)
	nType = nType or 0
	local team = {}
	local function addPlayer()
		if not noSelf or self.battle.player ~= self then
			if not self.battle.player.isDead then
				table.insert(team, self.battle.player)
			end
		end
	end
	local function addEnemy()
		for _, enemy in pairs(self.battle.enemys) do
			if not noSelf or enemy ~= self then 
				if not enemy.isDead and not enemy.lock then -- 已经翻开的
					table.insert(team, enemy)
				end
			end
		end
	end
	if nType == 0 then
		addPlayer()
		addEnemy()
	elseif nType == 1 then
		if self.class == Player then --玩家
			addPlayer()
		else
			addEnemy()
		end
	elseif nType == 2 then
		if self.class == Player then --玩家
			addEnemy()
		else
			addPlayer()
		end
	end
	return team
end

function BaseObject:getDB()
	local db = {}
	db.hpMax = self.hpMax
	db.hp = self.hp
	local baseAttr = {"atk", "miss", "hit"}
	for _, field in pairs(baseAttr) do
		db[field] = self[field]
		db["_"..field] = self["_" .. field]
	end
	db.passives = {}
	for _, passive in ipairs(self.passives) do
		table.insert(db.passives, passive:getDB())
	end
	db.buff = {}
	for _, buff in ipairs(self.buffs) do
		table.insert(db.buffs, buff:getDB())
	end
	return db
end

function BaseObject:triggerPassive(condType, params)
	
end

local Enemy = class("Enemy", BaseObject)
function Enemy:ctor(battle, monsterId, id, roomId, blockId, lock, enemy)
	Enemy.super.ctor(self, battle)
	self.id = id
	self.monsterId = monsterId
	self.roomId = roomId
	self.blockId = blockId
	self.lock = lock
	self:initData(enemy)
end
function Enemy:unlock(id)
	self.id = id
	self.lock = nil
end

local Player = class("Player", BaseObject)
function Player:ctor(battle, data)
	Player.super.ctor(self, battle)
	self:initData(data)
end

return Player, Enemy