AdvBattle.lua 6.12 KB
local Player, Enemy = table.unpack(require "adv.advPlayer")
local Buff = require "adv.AdvBuff"
local Passive = require "adv.AdvPassive"
local Battle = class("Battle")
function Battle:ctor(adv)
	self.adv = adv
	self.player = nil --玩家
	self.isNewPlayer = false
	self.enemy = nil
	self.enemys = {} --怪
	self.tempData = {} -- 临时回合数据
	self:initPlayer()
	self:initEnemys()
	self:initAfter()
	if self.isNewPlayer then
		self.player:triggerPassive(Passive.BORN_ONCE)
	end
end

function Battle:initAfter()
	self.player:initAfter(self.adv.advTeam.player)
	for _, enemy in pairs(self.enemys) do
		enemy:initAfter(self.adv.rooms[enemy.roomId].blocks[enemy.blockId].event.enemy)
	end
	if self.adv.advTeam.enemyId then
		local enemy = self:getEnemyById(self.adv.advTeam.enemyId)
		self.enemy = enemy
	end
end

function Battle:initPlayer()
	if not next(self.adv.advTeam.heros) then return end
	if not self.adv.advTeam.player then
		local hp = 0
		local player = {}
		player.passives = {}
		for slot, heroId in pairs(self.adv.advTeam.heros) do
			if self.adv.owner.heros[heroId] then
				hp = hp + self.adv.owner.heros[heroId]:getProperty("battleV")
				local advSkillId = csvdb["unitCsv"][self.adv.owner.heros[heroId]:getSkinId()]["adv"]
				if advSkillId > 1000 then
					table.insert(player.passives, {id = advSkillId, level = self.adv.owner.heros[heroId]:getSkillLevel(4)})
				end
			end
		end
		player.hp = hp
		player.atk = tonumber(string.format("%0.0f", player.hp * 0.1)) --todo 系数是临时的
		player.def = 0
		player.miss = 0
		player.hit = 100
		self.adv.advTeam.player = player
		self.isNewPlayer = true
	end
	self.player = Player.new(self, self.adv.advTeam.player)
end

function Battle:initEnemys()
	for _, room in pairs(self.adv.rooms) do
		for _, block in pairs(room.blocks) do
			self:addEnemy(room, block)	
		end
	end
end

function Battle:addEnemy(room, block)
	if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then
		if not block.event.enemy then
			local enemyCsv = csvdb["event_monsterCsv"][block.event.id]
			local enemy = {}
			enemy.hp = enemyCsv.hp + enemyCsv.levelhp * self.adv.advInfo.level
			enemy.atk = enemyCsv.atk + enemyCsv.levelatk * self.adv.advInfo.level
			enemy.hit = enemyCsv.hit + enemyCsv.levelhit * self.adv.advInfo.level
			enemy.miss = enemyCsv.miss + enemyCsv.levelmiss * self.adv.advInfo.level
			enemy.def = enemyCsv.def + enemyCsv.leveldef * self.adv.advInfo.level
			enemy.passives = {}
			for _, id in ipairs(enemyCsv.passive:toArray(true, "=")) do
				table.insert(enemy.passives, {id = id})
			end
			block.event.enemy = enemy
		end
		local player = Enemy.new(self, block.event.mId or 999, block.event.id, room.roomId, block.blockId, not block.isOpen, block.event.enemy)
		table.insert(self.enemys, player)
		return player
	end 
end

function Battle:getEnemy(roomId, blockId)
	for _, enemy in ipairs(self.enemys) do
		if enemy.roomId == roomId and enemy.blockId == blockId then
			return enemy
		end
	end
end

function Battle:getEnemyById(id)
	for _, enemy in ipairs(self.enemys) do
		if enemy.id == id then
			return enemy
		end
	end
end

function Battle:getRBByEnemyId(enemyId)
	local enemy = self:getEnemyById(enemyId)
	return enemy.roomId, enemy.blockId
end

function Battle:isBattleEnd()
	if not self.enemy then
		return true
	end
end

--战斗开始
function Battle:battleBegin(roomId, blockId)
	self.tempData = {} -- 清理上次战斗数据
	if self.enemy then
		self.player:reset(self.adv.advTeam.player)
		self.enemy:reset(self.adv.rooms[self.enemy.roomId].blocks[self.enemy.blockId].event.enemy)
	end
	local enemy = self:getEnemy(roomId, blockId)
	if enemy then
		self.enemy = enemy
		self.player:battleBegin()
		self.enemy:battleBegin()
		self:doBattleTurn()
	end
end

-- 检查回合数同步
function Battle:checkTurn(turn)
	if self.tempData[turn] then
		return true
	end
end

-- 战斗内一回合
function Battle:doBattleTurn()
	local enemy = self.enemy
	-- 玩家先出手
	self.adv:backAtk(nil, enemy.id)
	self:doPlayerTurn(self.player, enemy)
	--是否无法攻击
	if not enemy.isDead and not enemy:hadBuff(Buff.CANT_BACK_ATK) then
		self.adv:backAtk(enemy.id, nil)
		self:doPlayerTurn(enemy, self.player)
	end
	-- 判定死亡
	if enemy.isDead or self.player.isDead then
		local deadPlayer = enemy.isDead and enemy or self.player
		deadPlayer:battleEnd()
		self.enemy = nil
	else
		self.adv:backTurnEnd()
	end
	self:getTempDB()
end

--战斗内角色回合逻辑
function Battle:doPlayerTurn(atkPlayer, hurtPlayer)
	atkPlayer:beforeTurn()
	if #(atkPlayer.skillOrder) > 0 then
		atkPlayer:releaseSpecialSkill()
	else
		hurtPlayer:hurt(atkPlayer:getHurtValue(), atkPlayer, {hurtType = 1})
	end
	atkPlayer:afterTurn()
	atkPlayer:clearTurn()
end

--触发全员被动技能
function Battle:triggerPassive(condType, params)
	self.player:triggerPassive(condType, params)
	for _, enemy in ipairs(self.enemys) do
		enemy:triggerPassive(condType, params)
	end
end

--回合
function Battle:afterRound()
	self.player:afterRound()
	table.sort(self.enemys, function(e1, e2)
		return e1.id < e2.id
	end)
	for _, enemy in ipairs(self.enemys) do
		enemy:afterRound()
	end
	self.player:clearRound()
	for _, enemy in ipairs(self.enemys) do
		enemy:clearRound()
	end
	for i = #self.enemys, 1, -1 do
		if self.enemys[i].isDead then
			self.adv:enemyDead(self.enemys[i].roomId, self.enemys[i].blockId)
			self.enemys[i]:clear()
			table.remove(self.enemys, i)
		end
	end

	if self.adv.advInfo.power > 0 then
		self.adv:changePower(-1)
	else
		self.player:hurt(self.player.hpMax / 10, nil, {hurtType = 4})
	end
	if self.player.isDead then
		self.adv:over(false)
	end
end

-- 写入临时数据
function Battle:getTempDB()
	local turnDB = {}
	if self.enemy then
		turnDB.enemy = self.enemy:getDB()
	end
	turnDB.player = self.player:getDB()
	table.insert(self.tempData, turnDB)
end

--写入数据
function Battle:getDB()
	if not self.enemy then
		self.adv.advTeam.enemyId = nil
	else
		self.adv.advTeam.enemyId = self.enemy.id
		return
	end
	self.adv.advTeam.player = self.player:getDB()
	for _, enemy in ipairs(self.enemys) do
		local block = self.adv.rooms[enemy.roomId].blocks[enemy.blockId]
		block.event.enemy = enemy:getDB()
	end
end

return Battle