---------------------------------------------------------------
-- 英雄逻辑

-- addHero 				根据英雄id添加英雄
-- addHeroByGrid 		根据英雄grid添加英雄（注意grid没有被其它地方引用）
-- delHeroByIndex 		根据英雄下表删除英雄
---------------------------------------------------------------

local HeroExcel = require("excel.hero")
local UpNeedExcel = require("excel.upNeed")
local TequanExcel = require("excel.qqTequan")
local SkillExcel = require("excel.skill")
local BufferExcel = require("excel.buffer")
local SkinExcel = require("excel.skin")
local EquipExcel = require("excel.equip")
local Log = require("common.Log")
local LogDefine = require("common.LogDefine")
local Lang = require("common.Lang")
local Util = require("common.Util")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local Broadcast = require("broadcast.Broadcast")
local BarTaskLogic = require("bar.BarTaskLogic")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local RoleAttr = require("role.RoleAttr")
local RoleDefine = require("role.RoleDefine")
local RoleHeadLogic = require("role.RoleHeadLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local HeroBook = require("hero.HeroBook")
local HeroGrid = require("hero.HeroGrid")
local HeroDefine = require("hero.HeroDefine")
local HeroEquip = require("hero.HeroEquip")
local CombatPosLogic = require("combat.CombatPosLogic")
local CombatDefine = require("combat.CombatDefine")
local SkinLogic = require("skin.SkinLogic")
local FenjieLogic = require("hecheng.FenjieLogic")
local MonthHecJuex = require("monthAct.MonthHecJuex")
local JjcLogic = require("jjc.JjcLogic")
local HechengLogic = require("hecheng.HechengLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local GuideLogic = require("guide.GuideLogic")
local RoleLogic = require("role.RoleLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local TuiSongLiBao = require("present.TuiSongLiBao")
local SuipianLogic = require("bag.SuipianLogic")
local MoshouLogic = require("moshou.MoshouLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local VipLogic = require("vip.VipLogic")
local FuwenLogic = require("fuwen.FuwenLogic")
local GlobalWorld = require("core.GlobalWorld")
local SysParameter = require("common.SysParameter")
local JibanLogic = require("combat.JibanLogic")
local EquipLogic = require("equip.EquipLogic")
local XingYaoGongMing = require("xingYaoMen.XingYaoGongMing")
local HeroGrowUp = require("absAct.HeroGrowUp")
local MengxinLogic = require("present.MengxinLogic")
local Config = require("Config")
local HeroLogLogic = require("absAct.HeroLogLogic")
local ExclusiveTaskLogic = require("absAct.ExclusiveTaskLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local BingshuLogic = require("fuwen.BingshuLogic")
local GiftLogic = require("topup.GiftLogic")
local HeroMiddleLogic = require("hero.HeroMiddleLogic")
local CommonDefine = require("common.CommonDefine")
local HeroExclusiveWeapon = require("hero.HeroExclusiveWeapon")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")
local HeroPubLogic = require("hero.HeroPubLogic")
local WinnerRelicLogic = require("winnerRelic.WinnerRelicLogic")
local GodsAreaNS = require("godsArea.GodsAreaNS")
local Abs365CardLogic = require("absAct.Abs365CardLogic")
local HeroSeed = require("hero.HeroSeed")
local DeleteHeroConfig = require("excel.delteHero")
local AnotherWorldBattleNS = require("anotherWorldBattle.AnotherWorldBattleNS")
local HeroTianYuan = require("hero.HeroTianYuan")
local HeroArtifacts = require("hero.HeroArtifacts")


HERO_MAX_STAR    =        15    -- 目前英雄最大星级

local HERO_RESET_FREECNT = 10 	-- 每日重置次数	
local HERO_RESET_MAXSTAR = 9 	-- 只能重置9星以下(包含9星)	
local CHONGSHENG_RETURN_STAR = 5 -- 重生返还x星本体碎片	

-- 用于弹窗礼包类型
local Upgrade_HERO_EVENT = 3

-- 百战成神: 英雄数据变更且该英雄在五族阵容中则同步跨服
local function syncBaiZhanChengShenHero(human, heroUuid)
	if not heroUuid or heroUuid == "" or heroUuid == "0" then return end
	local BaiZhanChengShenNS = require("baiZhanChengShen.BaiZhanChengShenNS")
	BaiZhanChengShenNS.onHeroDataUpdate(human, heroUuid)
end

----------------------------------- 结构体封装 --------------------------------------
-- 获取技能信息
function makeSkillNet(net, id)
	local skillConfig = SkillExcel.skill[id]
	if not skillConfig then return end
	net.id   = id
	net.icon = skillConfig.icon
	net.name = skillConfig.name
	net.type = skillConfig.type
	net.desc = skillConfig.desc
	net.need = skillConfig.need or 0
	net.lv   = skillConfig.skillLv or 0
    -- todo

    net.cd[0] = #skillConfig.cd 
    if net.cd[0] ~= 0 then
 		net.cd[1] = skillConfig.cd[1]
    	net.cd[2] = skillConfig.cd[2]
    end

    local len = #skillConfig.buffers
    for i = 1,len do
        local buffId = skillConfig.buffers[i][1]
        local buffConfig = BufferExcel.buffer[buffId]
        net.buff[i].id = buffId
        net.buff[i].name = buffConfig.name
        net.buff[i].desc = buffConfig.desc
    end
    net.buff[0] = len
    net.lvUpDesc = skillConfig.lvUpDesc
    -- todo
end

-- 封装UpStarCond协议结构体
function makeUpStarCond(net, cond)
	local ttype = cond[1]
	net.type = ttype
	if ttype == HechengLogic.COND_TYPE_HEROID then
		local heroID = cond[2]
		local heroConfig = HeroExcel.hero[heroID]
        local star = cond[4] or heroConfig.star
		net.id = heroID
		net.icon = heroConfig.head 
		net.star = star 
		net.camp = heroConfig.camp 
		net.name = heroConfig.name
        net.grade = heroConfig.grade 
		net.cnt = cond[3]
	elseif ttype == HechengLogic.COND_TYPE_CAMPSTAR then
		net.id = 0
		net.icon = 0
		net.name = ""
        net.grade = 0 
		net.camp = cond[2]
		net.star = cond[3]
		net.cnt = cond[4]
	end
end

-------------------------------- 英雄属性计算 ------------------------------------------
--等级加成
local function lvAdd(lv, upAttrs, attrs)
	for _, upAttr in ipairs(upAttrs) do
		local key = upAttr[1]
		local value = upAttr[2]
		attrs[key] = attrs[key] + value * (lv - 1)
	end
end

--星級加成
local function starAdd(star, atkStarRate, hpStarRate, attrs)
	attrs[RoleDefine.ATK] = attrs[RoleDefine.ATK] * (1 + atkStarRate/10000)
	attrs[RoleDefine.HP] = attrs[RoleDefine.HP] * (1 + hpStarRate/10000)
end

--阶数加成
local function qualityAdd(heroConfig, quality, attrs)
    local qualityConfig = HeroExcel.quality[heroConfig.quality]
    local qualityEnd = quality + 1
	for i = 1, qualityEnd do
		for key, rateConfig in pairs(qualityConfig) do
            local rate = rateConfig[i]
            if rate then
               if key == RoleDefine.DEF or key == RoleDefine.SPEED then
                   attrs[key] = attrs[key] + rate[1]
               else
                   attrs[key] = attrs[key] * rate[1]
               end
            end
		end
	end
end

-- 伙伴基础
function doCalcHero(grid, attrs)
	if not grid and attrs then return end
	local heroConfig = HeroExcel.hero[grid.id]
    local attrConfig = HeroDefine.getAttrConfig(grid.id, grid.star)
    if not attrConfig then
       assert(nil, "attrConfig is nil id "..grid.id.." star "..grid.star)
    end

	for _,v in ipairs(attrConfig.attrs) do
		RoleAttr.updateValue(v[1], v[2], attrs)
	end	

	lvAdd(grid.lv, attrConfig.up, attrs)
	starAdd(grid.star, attrConfig.atkStarRate, attrConfig.hpStarRate, attrs)
	qualityAdd(heroConfig, grid.quality, attrs)
end

-- 时装
function doCalcHeroSkin(skinID, attrs)
	--[[local skinConfig = SkinExcel.skin[skinID]
	for _, v in ipairs(skinConfig.attrs) do
		RoleAttr.updateValue(v[1], v[2], attrs)
	end]]
end

-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------

local function sortZhanli(a, b)
	return a[2] > b[2]
end


function TransformHeroEquipAttr(human)
	for index = 1, human.db.heroBag[0] do
        local heroGrid = human.db.heroBag[index]
        if heroGrid and heroGrid.lv >= 2 then

			for i = 1, ItemDefine.EQUIP_MAX_CNT do
				local equipGrid = heroGrid.equip and heroGrid.equip[i]
				if equipGrid then
					if equipGrid.attr then
						local _, attrInfo = next(equipGrid.attr)
						if type(attrInfo) == "table" then
							return
						end

						equipGrid.attr = EquipLogic.AttrHashToArray(equipGrid.attr)
					end

					if equipGrid.washAttr then
						equipGrid.washAttr = EquipLogic.AttrHashToArray(equipGrid.washAttr)
					end
				end
			end
		end
	end
end


local function playerNewUniqueTagCheck(human)
	local playerNewUniqueTag= human.db.newUniqueTag
	for _, v in pairs(DeleteHeroConfig.Sheet1) do
		if v.newUniqueTag == playerNewUniqueTag then
			return true
		end
	end

	return false
end

local function isDelHero(human, heroUuid)
	local playerNewUniqueTag= human.db.newUniqueTag
	for _, v in pairs(DeleteHeroConfig.Sheet1) do
		if v.newUniqueTag == playerNewUniqueTag and heroUuid == v.deleteHeros then
			return true
		end
	end
end


local function getDelHeroIdxArr(human)
	local delHeroIdxArr = {}

	for i=1,human.db.heroBag[0] do
		local heroGrid = human.db.heroBag[i]
		if heroGrid and isDelHero(human, heroGrid.uuid) then
			delHeroIdxArr[#delHeroIdxArr+1] = i
		end
	end

	if #delHeroIdxArr == 0 then
		return
	end

	return delHeroIdxArr
end



-- 临时处理异常获得的英雄
local function deleteErrHero(human)
	if human.db.delErrHeroTag then
		return
	end

	if not playerNewUniqueTagCheck(human) then
		human.db.delErrHeroTag = true
		return
	end

	local delHeroIdxArr = getDelHeroIdxArr(human)
	if delHeroIdxArr then
		local logType =  "errHandle"
		for _,heroIdx in ipairs(delHeroIdxArr) do
			delHeroByIndex(human, heroIdx, logType)
		end
	end

	human.db.delErrHeroTag = true
end

-- 处理老数据, 英雄身上装备检查
local function equipCheck(human)
	if human.db.equipCheck then
		return
	end

	local EquipLogicGrid = require("equip.EquipLogicGrid")
	for index = 1, human.db.heroBag[0] do
		local heroGrid = human.db.heroBag[index]
		if heroGrid and heroGrid.equip and next(heroGrid.equip) then
			for _, equipGrid in pairs(heroGrid.equip) do
				equipGrid.baseRandVal = EquipLogicGrid.GenEquipBaseRandomVal(equipGrid.id)
			end
		end
	end

	human.db.equipCheck = true
end





-- 下发英雄背包列表
function sendHeroBagList(human)
	equipCheck(human)

	local msgRet = Msg.gc.GC_HERO_BAG_LIST
	local cnt = 0
	human.maxZDL = {}
	human.maxZDL.maxHero = {}
	human.maxZDL.heroCnt = 0
	human.maxZDL.zhandouli = 0

	-- deleteErrHero(human)

	local list = {}
	for index = 1, human.db.heroBag[0] do
        local heroGrid = human.db.heroBag[index]
        if heroGrid then
			cnt = cnt + 1
			HeroGrid.makeHeroSimple(msgRet.list[cnt], heroGrid, index, human)

			if cnt >= HeroDefine.PAGE_HERO_COUNT then
				msgRet.list[0] = cnt
				Msg.send(msgRet, human.fd)
				cnt = 0
			end
			list[#list + 1] = {heroGrid.uuid or "", heroGrid.zhandouli or 0}
        end

	end
	if cnt > 0 then
		msgRet.list[0] = cnt
		Msg.send(msgRet, human.fd)
	end

	if #list > 0 then
		table.sort( list , sortZhanli )
		local maxCnt = human.db.lv >= 100 and 6 or 5
		for i = 1 , maxCnt do
			local heroDb = list[i]
			if heroDb then
				human.maxZDL.heroCnt = human.maxZDL.heroCnt + 1
				human.maxZDL.maxHero[heroDb[1]] = heroDb[2]
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + heroDb[2]
			end
		end
	end

	SkinLogic.OnLoginCheckEquipSkin(human)
	print(" human onLogin  maxZDL is : ",  human.maxZDL.zhandouli)
end

-- 修正 玩家最高战力
function checkChangeMaxZDL(human, heroGrid)
	if human.maxZDL and heroGrid.uuid then
		if human.maxZDL.maxHero[heroGrid.uuid] then
			human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
			human.maxZDL.zhandouli = 0
			for _, v in pairs(human.maxZDL.maxHero) do
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + v
			end
		else
			local maxCnt = human.db.lv >= 100 and 6 or 5
			if human.maxZDL.heroCnt < maxCnt then
				human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
				human.maxZDL.zhandouli = human.maxZDL.zhandouli + heroGrid.zhandouli
				human.maxZDL.heroCnt = human.maxZDL.heroCnt + 1
			else
				local minZDL = 0
				local minUuid 
				for thisUuid, v in pairs(human.maxZDL.maxHero) do
					minUuid = minZDL == 0 and thisUuid or minUuid
					minZDL = minZDL == 0 and v or minZDL
					if minZDL > v then
						minZDL = v
						minUuid = thisUuid
					end
				end

				if minZDL < heroGrid.zhandouli then
					human.maxZDL.maxHero[minUuid] = nil
					human.maxZDL.maxHero[heroGrid.uuid] = heroGrid.zhandouli
					human.maxZDL.zhandouli = human.maxZDL.zhandouli - minZDL + heroGrid.zhandouli
				end
			end
		end

        print(" checkChangeMaxZDL   ", human.maxZDL.zhandouli)
	end

	
end

-- 发送英雄详细信息：静态,只是1个英雄的
function sendHeroBagStatic(human, id, tuJian)
	local heroConfig = HeroExcel.hero[id]
	if not heroConfig then return end
	
	local msgRet = Msg.gc.GC_HERO_BAG_STATIC
	HeroGrid.makeHeroStatic(msgRet.heroStatic, id, tuJian)
	Msg.send(msgRet, human.fd)
end

-- 玩家身上动态数据
function sendHeroGridDynamic(human, heroGrid, index, isQuery)
	if not isQuery then sendHeroBagUpdate(human, index) end	
	local msgRet = Msg.gc.GC_HERO_BAG_DYNAMIC
	msgRet.index = index or 0
    msgRet.canLv = isHeroLvDot(human, heroGrid) == true and 1 or 0
    msgRet.canUp = isHeroUpDot(human, heroGrid) == true and 1 or 0
    msgRet.canEquip = HeroEquip.isEquipDot(human, heroGrid) == true and 1 or 0
    msgRet.canFuwen = FuwenLogic.isFuwenDot(human, heroGrid) == true and 1 or 0
    msgRet.canJueXing = isHeroJuexingDot(human, index, heroGrid) == true and 1 or 0
	msgRet.canWeapon = HeroExclusiveWeapon.isWeaponDot(human, heroGrid) == true and 1 or 0
	msgRet.canSeed = HeroSeed.isSeedDot(human, heroGrid) == true and 1 or 0
	msgRet.canTianYuan = HeroTianYuan.isTianYuanDot(human, heroGrid) == true and 1 or 0
	msgRet.canArtifacts = HeroArtifacts.isArtifactsDot(human, heroGrid) == true and 1 or 0

	local bingShuState = BingshuLogic.isBingShuDot(human, heroGrid)
	if bingShuState == -1 then
		msgRet.canBingShu = -1 
	else
		msgRet.canBingShu = bingShuState == true and 1 or 0
	end

	HeroGrid.makeHeroDynamic(msgRet.heroDynamic, heroGrid, index, human)
	Msg.send(msgRet, human.fd)
end

-- 配置数据
function sendHeroBagDynamicByID(human, heroID, star)
	local msgRet = Msg.gc.GC_HERO_BAG_DYNAMIC_BY_ID
	HeroGrid.makeHeroDynamicByID(msgRet.heroDynamic, heroID, star)
	Msg.send(msgRet, human.fd)
end

-- 发送英雄详细信息 
function sendHeroBagDynamic(human, id, index, isQuery)
	local heroGrid = getHeroGrid(human, id, index)
	if not heroGrid then return end

	sendHeroGridDynamic(human, heroGrid, index, isQuery)
end

-- 发送英雄添加/变化
function sendHeroBagUpdate(human, index)
	local heroGrid = human.db.heroBag[index]
	if type(heroGrid) ~= "table" then return end

	local msgRet = Msg.gc.GC_HERO_BAG_ADD				
	HeroGrid.makeHeroSimple(msgRet.data, heroGrid, index, human)

	Msg.send(msgRet, human.fd)
end

-- 发送英雄删除
function sendHeroBagDel(human, index)
	local msgRet = Msg.gc.GC_HERO_BAG_DELETE
	msgRet.index = index
	Msg.send(msgRet, human.fd)
end

-- 背包容量查询
function sendHeroBagCap(human)
	calcHeroBagCap(human)
	local nowBuyCnt = human.db.buyCapCnt or 0	
	local msgRet = Msg.gc.GC_HERO_CAP_QUERY
	msgRet.cap = human.db.heroBag[0]
	msgRet.buyZuanshi = (nowBuyCnt + 1) * 100	
	if nowBuyCnt >= HeroDefine.BUY_CAP_CNT then
		msgRet.buyZuanshi = -1  --达到上限
	end
	Msg.send(msgRet, human.fd)
end
-----------------------------------------------------------------------------------------

-- 锁定英雄
function lockHero(human, isLock, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end	
	if isLock == 1 then 
		heroGrid.isLock = true
	elseif isLock == 0 then 
		heroGrid.isLock = nil
	end
	
	local msgRet = Msg.gc.GC_HERO_BAG_LOCK
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.type = heroGrid.isLock and 1 or 0
	Msg.send(msgRet, human.fd)
end

-- 返回英雄背包空余格子数
function getEmptyCnt(human)
	local emptyCnt = 0
	for i = 1, human.db.heroBag[0] do
		if human.db.heroBag[i] == nil then
			emptyCnt = emptyCnt + 1	
		end
	end
	return emptyCnt
end

-- 获得英雄背包第一个空格子下标
function getEmptyIndex(human)
	for index = 1, human.db.heroBag[0]do
		local grid = human.db.heroBag[index]
		if grid == nil then			
			return index
		end
	end
end

-- 新增英雄
function addHero(human, id, star, cnt, logType, noSend)
	if cnt < 1 then return end
	local heroConfig = HeroExcel.hero[id]
	if not heroConfig then return end	

	-- 某些英雄自动分解
	local isFenjie, fenjieList = FenjieLogic.autoFenjie(human, id, cnt, logType)
	if isFenjie then
		return nil, fenjieList
	end
	
	-- 先判断英雄背包是否满
	if getEmptyCnt(human) < cnt then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
	end

	local heroIndex, uuid = nil
	for i = 1, cnt do		
		local heroGrid = HeroGrid.createHeroGrid(id,star)
		-- 判断英雄是否已经穿戴了皮肤，如果有应该同步
		local skinLogic = require"skin.SkinLogic"
		local skinOn = skinLogic.checkHeroSkinById(human,id)
		if skinOn then 
			heroGrid.skinOn = skinOn
		end
		heroIndex = addHeroByGrid(human, heroGrid, logType, noSend)
        uuid = heroGrid.uuid
	end

	return heroIndex, uuid
end

-- 英雄添加日志
function writeLogHeroAdd(human, logType, heroGrid)
	-- Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.account, human.db.name, human.db.lv, 
	-- 	LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, 1, heroGrid.uuid, heroGrid.star)

	Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, 
		LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, 1, heroGrid.uuid, heroGrid.star)
end

-- 英雄删除日志
function writeLogHeroDel(human, logType, heroGrid)
	-- Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.account, human.db.name, human.db.lv, 
	-- 	LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, -1, heroGrid.uuid, heroGrid.star)
	Log.write(Log.LOGID_OSS_HERO, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, 
		LogDefine.DEFINE[logType] + LogDefine.TYPE["hero"] , heroGrid.id, -1, heroGrid.uuid, heroGrid.star)
end

-- 新增英雄
function addHeroByGrid(human, heroGrid, logType, noSend)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["hero"] then
		assert()
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	-- 某些英雄自动分解
	local isFenjie, fenjieList = FenjieLogic.autoFenjie(human, heroGrid.id, 1, logType)
	if isFenjie then
		return nil, fenjieList
	end
	
	-- 先判断英雄背包是否满
	if getEmptyCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
    end

	local emptyIndex = getEmptyIndex(human)
	if not emptyIndex then return end 

    heroGrid.bagIndex = emptyIndex
	human.db.heroBag[emptyIndex] = heroGrid
	ObjHuman.doCalcHero(human, emptyIndex)
	if not noSend then
		sendHeroBagUpdate(human, emptyIndex)
	end	

	onGetNewHero(human, heroGrid, logType, emptyIndex)	

	writeLogHeroAdd(human, logType, heroGrid)
	checkChangeMaxZDL(human, heroGrid)

	if heroConfig.grade >= HeroDefine.HERO_SSR_GRADE then
		HeroPubLogic.UpdateHero(human, HeroPubLogic.HERO_OP_ADD, heroGrid.id, heroGrid.uuid)
	end


	return emptyIndex
end

local yunYingActParam = {}
function onGetNewHero(human, heroGrid, logType, heroIndex)
	local heroConfig = HeroExcel.hero[heroGrid.id]
    local grade = heroConfig.grade
	HeroBook.onAddHero(human, heroGrid.id, heroGrid.star)
	RoleHeadLogic.onAddHero(human, heroGrid.id)	
	-- 先知置换 和十星置换 不予计算活动
	if logType ~= "xianzhi_zhihuan" and logType ~= "tenStar_displace" then
		GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_HERO)
		TuiSongLiBao.tuiSongLiBaoOnTask(human, TuiSongLiBao.TUISONGLIBAOTASK_STARS_HERO, heroConfig.star, nil)
		HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE12, heroGrid.star)

        if grade == 4 then
            MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_15,1)
        end
	end	
	XingYaoGongMing.onAddHero(human,heroGrid,heroIndex)

    HeroLogLogic.finishTaskCB(human, HeroLogLogic.HERO_LOG_TYPE_7, 1, heroGrid.id)

    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = logType
    yunYingActParam[2] = heroGrid.id
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onGetNewHeroAct", yunYingActParam)
    
    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = heroGrid.id
    yunYingActParam[2] = heroGrid.star
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onHeroStarChange", yunYingActParam)   

	-- 获取新英雄
	TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_GETPOINTHERO, human.db._id, 1, heroGrid.star, heroGrid.id)
end

-- 根据下标删除英雄
function delHeroByIndex(human, index, logType, noSend)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["hero"] then
		assert()
	end

	if human.db.heroBag[index] == nil then
		return
	end
	
	--SkinLogic.onDelHero(human, index)
	local heroGrid = human.db.heroBag[index]	
    human.db.heroBag[index] = nil
	human.heroAttrs[index] = nil
	
	if not noSend then
		sendHeroBagDel(human, index)
	end
	
	-- 删除酒馆任务中的上战的英雄
	BarTaskLogic.heroIndexByDelForPos(human, index)	
	-- 删除 默认出站队列中的 英雄	
	CombatPosLogic.heroIndexByDelForPos(human, heroGrid.uuid)
	XingYaoGongMing.onDelHero(human,heroGrid,index)
	ObjHuman.doCalc(human)

	writeLogHeroDel(human, logType, heroGrid)

	local heroConfig = HeroExcel.hero[heroGrid.id]
	if heroConfig.grade >= HeroDefine.HERO_SSR_GRADE then
		HeroPubLogic.UpdateHero(human, HeroPubLogic.HERO_OP_DEL, heroGrid.id, heroGrid.uuid)
	end

	GodsAreaNS.UpdateHeroData(human, heroGrid.uuid, 0)
end




-- 英雄升级
function heroLvUp(human, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]	
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end		
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_LV) then
		return
	end
	
	-- 判断等级上限
	local star = heroGrid.star
	local nowLv = heroGrid.lv
	local maxLv = HeroGrid.getMaxLv(star, heroGrid.quality)

	if nowLv >= maxLv then
		return
	end

	-- local upLv, needJinbi, needSoulCnt = HeroGrid.getLevelUpCnt(human, nowLv, maxLv)

	-- 改为一次只能升一级
	-- local upLv, needJinbi, needSoulCnt = HeroGrid.getLevelUpCnt(human, nowLv, nowLv+1)

	-- 新修改：10级前一次最高升5级，10级后一次只能升1级
	local upLv, needJinbi, needSoulCnt = 0,0,0
	if nowLv < 10 then
		upLv, needJinbi, needSoulCnt = HeroGrid.getLevelUpCnt(human, nowLv, maxLv)
	else
		upLv, needJinbi, needSoulCnt = HeroGrid.getLevelUpCnt(human, nowLv, nowLv+1)
	end

	--print(" upLv, needJinbi, needSoulCnt", upLv, needJinbi, needSoulCnt)
	if upLv < 1 then return end
	
	-- 判断消耗材料
	if human.db.jinbi < needJinbi then
		return Broadcast.sendErr(human, Lang.COMMON_NO_JINBI)
	end
	if BagLogic.getItemCnt(human, ItemDefine.ITEM_GREEN_EXP_ID) < needSoulCnt then
		local strName = ItemDefine.getValue(ItemDefine.ITEM_GREEN_EXP_ID, "name")
		return Broadcast.sendErr(human, Util.format(Lang.COMMON_NO_ITEM, strName))
	end
	
	-- 扣道具
	ObjHuman.updateJinbi(human, -needJinbi, "hero_up")
	BagLogic.delItem(human, ItemDefine.ITEM_GREEN_EXP_ID, needSoulCnt, "hero_up")
	
	-- 改db
	heroGrid.lv = nowLv + upLv

	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	
	local msgRet = Msg.gc.GC_HERO_LEVEL_UP
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)

	GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_HEROUP)
	refreshDot(human, heroGrid.uuid)

    if nowLv < 50 and heroGrid.lv >= 50 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_6,1)
    elseif nowLv < 100 and heroGrid.lv >= 100 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_14,1)
    elseif nowLv < 200 and heroGrid.lv >= 200 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_20,1)
    elseif nowLv < 145 and heroGrid.lv >= 145 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_17,1)
    elseif nowLv < 185 and heroGrid.lv >= 185 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_18,1)
    end
	
	XingYaoGongMing.onHeroLvUp(human,heroGrid,heroIndex)
    --Log.write(Log.LOGID_OSS_HEROLVUP, human.db._id, human.db.account, human.db.name, heroGrid.uuid, nowLv, heroGrid.lv)
	Log.write(Log.LOGID_OSS_HEROLVUP, human.db._id, human.db.newUniqueTag, human.db.name, heroGrid.uuid, nowLv, heroGrid.lv)
	checkChangeMaxZDL(human, heroGrid)

	GodsAreaNS.UpdateHeroData(human, heroGrid.uuid, 1)
	AnotherWorldBattleNS.HeroDataUpdate(human, heroGrid.uuid)
	syncBaiZhanChengShenHero(human, heroGrid.uuid)
end

-- 英雄升阶查询
function heroUpgradeQuery(human, heroID, heroIndex)
	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end

	local cf = HeroExcel.hero[heroID]
	if not cf then return end

	local star = cf.star
	local nextQuality = heroGrid.quality + 1		
	local maxLv = HeroGrid.getMaxLv(heroGrid.star, nextQuality)
	local upcf = UpNeedExcel.upQuality[nextQuality]
	if not maxLv or not upcf then 
		return Broadcast.sendErr(human, Lang.HERO_UPGRADE_ERR_FULL)
	end

	local nextHeroGrid = HeroGrid.getHeroGridCalcCache(heroGrid)
	nextHeroGrid.quality = nextQuality
	local nextAttrs = RoleAttr.calcHeroGrid(nextHeroGrid, heroIndex, human)
	local zhandouli = RoleAttr.calcZhandouli(nextAttrs)	

	local msgRet = Msg.gc.GC_HERO_UPGRADE_QUERY
	msgRet.id = heroID
	msgRet.index = heroIndex
	local net = msgRet.data
	net.id = heroID
	net.maxLv = maxLv	
	net.zhandouli = zhandouli
	net.attr[0] = 4
	net.attr[1].key = RoleDefine.ATK
	net.attr[1].value = nextAttrs[RoleDefine.ATK]
	net.attr[2].key = RoleDefine.HP
	net.attr[2].value = nextAttrs[RoleDefine.HP] 
	net.attr[3].key = RoleDefine.SPEED
	net.attr[3].value = nextAttrs[RoleDefine.SPEED] 	
	net.attr[4].key = RoleDefine.DEF
	net.attr[4].value = nextAttrs[RoleDefine.DEF] 	
	net.needJinbi = upcf.money
	net.needItemCnt = upcf.jinjieshi
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd) 
end

-- 英雄升阶
function heroUpgradeDo(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil or heroGrid.id ~= heroID then
		return
	end

    if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_LV) then
	   return
	end
	
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local star = heroGrid.star
	local maxQuality = HeroGrid.getMaxQuality(star)
	local nextQuality = heroGrid.quality + 1
				
	-- 判断阶数上限
	if heroGrid.quality >= maxQuality then
		return
	end
	local upcf = UpNeedExcel.upQuality[nextQuality]
	if not upcf then return end
	
	-- 判断消耗材料
	local needJinbi = upcf.money
	local needItemCnt = upcf.jinjieshi
	if human.db.jinbi < needJinbi then
		return Broadcast.sendErr(human, Lang.COMMON_NO_JINBI)
	end
	local nowItemCnt = BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID)
	if nowItemCnt < needItemCnt then
		local strName = ItemDefine.getValue(ItemDefine.ITEM_HERO_UPGRADE_ID, "name")
		return Broadcast.sendErr(human, Util.format(Lang.COMMON_NO_ITEM, strName))
	end
	
	-- 扣材料
	ObjHuman.updateJinbi(human, -needJinbi, "hero_upgrade")
	BagLogic.delItem(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt, "hero_upgrade")
	
	-- 改db
	heroGrid.quality = nextQuality	
	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	
    GuideLogic.setDoSpecialGuide(human, GuideLogic.SKIPTYPE_JUMP_UPGRADE)
    ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_25,1)
	local msgRet = Msg.gc.GC_HERO_UPGRADE_DO
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)
	refreshDot(human, heroGrid.uuid)
	
	XingYaoGongMing.onHeroUpgrade(human,heroGrid,heroIndex)
	checkChangeMaxZDL(human, heroGrid)
	syncBaiZhanChengShenHero(human, heroGrid.uuid)
end

-- 重算背包熔炼
function calcHeroBagCap(human)
	local buyCnt = math.min(human.db.buyCapCnt or 0, HeroDefine.BUY_CAP_CNT)
	local heroBagCnt = HeroDefine.HERO_BAG_CNT 

	heroBagCnt = heroBagCnt + (VipLogic.getPowerArgs(human, VipLogic.VIP_POWER12) or 0)
	heroBagCnt = heroBagCnt + HeroDefine.HERO_BAG_BUY_ADD_CNT * buyCnt -- 购买获得背包格子

    if human.db.blue ~= nil and human.db.blue.isAdd ~= nil then -- 特权
        local cnt = TequanExcel.tequan[2].privilege
        heroBagCnt = heroBagCnt + cnt
    end

    if human.db.yellow ~= nil and human.db.yellow.isAdd ~= nil then -- 特权
        local cnt = TequanExcel.tequan[1].privilege
        heroBagCnt = heroBagCnt + cnt
    end

    -- 封印之章特权
    local cjPrivilege = ChengjiuLogic.checkPrivilege(human,ChengjiuDefine.PRIVILEGE_TYPE_1)
    if cjPrivilege then
        heroBagCnt = heroBagCnt + cjPrivilege
    end

    -- 特殊服务器处理
    -- vip需求砍掉之后，导致有的玩家英雄数量超过背包数量
    -- 经策划确认，140001-140021 服务器所有玩家增加背包数量300
    if Config.SVR_INDEX >= 140001 and Config.SVR_INDEX <= 140021 then
        heroBagCnt = heroBagCnt + 300
    end

    human.db.heroBag[0] = heroBagCnt
end

-- 购买英雄背包容量
function buyHeroCap(human)
	-- 上限判断
	local nowBuyCnt = human.db.buyCapCnt or 0
	if nowBuyCnt >= HeroDefine.BUY_CAP_CNT then 
		return Broadcast.sendErr(human, Lang.HERO_BAG_BUY_CAP_NO_CNT)
	end

	-- 判断消耗
	local needZuanshi = (nowBuyCnt + 1) * 100	
	if not ObjHuman.checkRMB(human, needZuanshi) then
		return
	end
	
	-- 扣消耗
	ObjHuman.decZuanshi(human, -needZuanshi, "buy_hero_cap")
	
	-- 改db	
	human.db.buyCapCnt = nowBuyCnt + 1
	sendHeroBagCap(human)
	Broadcast.sendErr(human, Lang.ITEM_BUY_SUCCESS)
end

-- 最大觉醒
function sendHeroJueXingMax(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local msgRet = Msg.gc.GC_HERO_JUEXING_QUERY_MAX
	msgRet.id = heroID
	msgRet.index = heroIndex
	Msg.send(msgRet, human.fd)
end

local JUEXING_SKILL_DIFF_LIST = {}
function getSkillDiffList(cf1, cf2)
	local diffCnt = 0
	for i = 1, #cf2.skillList do
		local skillID1 = cf1.skillList[i]
		local skillID2 = cf2.skillList[i]
		if skillID1 ~= skillID2 then
			diffCnt = diffCnt + 1
			local tb = JUEXING_SKILL_DIFF_LIST[diffCnt] or {}
			JUEXING_SKILL_DIFF_LIST[diffCnt] = tb
			tb[1] = skillID1
			tb[2] = skillID2			
		end
	end
	for i = 1, #cf2.beSkillList do
		local skillID1 = cf1.beSkillList[i]
		local skillID2 = cf2.beSkillList[i]
		if skillID1 ~= skillID2 then
			diffCnt = diffCnt + 1
			local tb = JUEXING_SKILL_DIFF_LIST[diffCnt] or {}
			JUEXING_SKILL_DIFF_LIST[diffCnt] = tb
			tb[1] = skillID1
			tb[2] = skillID2
		end
	end
	return diffCnt, JUEXING_SKILL_DIFF_LIST
end

-- 英雄升星 8~20 的额外条件表, 升到 key 星, 背包中还额外需要有 value[2] 个星级为 value[1] 的英雄
local upStarExtraCond = {
	[8] = {6, 5},
	[9] = {7, 5},
	[10] = {8, 5},
	[11] = {9, 5},
	[12] = {10, 5},
	[13] = {11, 5},
	[14] = {12, 5},
	[15] = {13, 5},

	[16] = {11, 10},
	[17] = {11, 15},
	[18] = {12, 10},
	[19] = {12, 15},
	[20] = {13, 10},
}

-- 升级额外条件检测
local function upStarExtraCondCheck(human, nextStar)
	local extraCond = upStarExtraCond[nextStar]
	if not extraCond then
		return true
	end

	local starCond = extraCond[1]
	local numCond = extraCond[2]
	local numCorrect = CalcStarHeroCnt(human, starCond)

	if numCorrect < numCond then
		return Broadcast.sendErr(human, Util.format(Lang.HERO_UPSTAR_EXTRA_COND, starCond, numCond))
	end

	return true
end



-- 英雄觉醒(升星)预览
local JUEXING_SPEED_UP = {[4]=10}
local JUEXING_ATK_UP = {[5]=40,[6]=40,[7]=40,[8]=40,[9]=40,[10]=20,[11]=20,[12]=20}
local JUEXING_HP_UP = {[5]=50,[6]=50,[7]=50,[8]=50,[9]=50,[10]=30,[11]=30,[12]=30}
function heroJueXingQuery(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

    -- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end
    
    local attrConfig = HeroDefine.getAttrConfig(heroID, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroID, heroGrid.star)
	if not nextAttrConfig then 
       return sendHeroJueXingMax(human, heroID, heroIndex)
    end

	-- 额外条件判断
	-- if not upStarExtraCondCheck(human, nextAttrConfig.star) then
	-- 	return
	-- end


	local msgRet = Msg.gc.GC_HERO_JUEXING_QUERY
	local dataNet = msgRet.data
	local maxQuality = HeroGrid.getMaxQuality(attrConfig.star)
	local nextMaxQuality = HeroGrid.getMaxQuality(nextAttrConfig.star)
	-- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end
	dataNet.id = heroID
	dataNet.index = heroIndex
	dataNet.star = heroGrid.star
	dataNet.nextStar = nextAttrConfig.star
	dataNet.maxLv = HeroGrid.getMaxLv(heroGrid.star, maxQuality)	
	dataNet.nextMaxLv = HeroGrid.getMaxLv(nextAttrConfig.star, nextMaxQuality)

	-- 展示变化的技能
	local diffCnt, diffList = getSkillDiffList(attrConfig, nextAttrConfig)
    diffCnt = diffCnt > #dataNet.skillUp and #dataNet.skillUp or diffCnt
	dataNet.isAllSkillUp = (diffCnt > 1) and 1 or 0
    dataNet.skillUp[0] = diffCnt
    for i=1, diffCnt do
	   makeSkillNet(dataNet.skillUp[i], diffList[i][2])
    end
	dataNet.speedUp = JUEXING_SPEED_UP[heroConfig.star] or 0
	dataNet.atkUpRate = JUEXING_ATK_UP[heroConfig.star] or 0
	dataNet.hpUpRate = JUEXING_HP_UP[heroConfig.star] or 0

	dataNet.needItems[0] = #attrConfig.needItems
	for i = 1, dataNet.needItems[0] do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		Grid.makeItem(dataNet.needItems[i], itemID, itemCnt)
	end
	dataNet.needHeros[0] = 0
	for i = 1, #attrConfig.cond do
		dataNet.needHeros[0] = dataNet.needHeros[0] + 1
		local condNet = dataNet.needHeros[dataNet.needHeros[0]]
		makeUpStarCond(condNet, attrConfig.cond[i])
	end	
	dataNet.needItemCnt = attrConfig.jinjieshi
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

function fontJueXingHeroNet(net, heroGrid, index, human)
	local attrs = ObjHuman.getHeroAttrs(human, index)  
	HeroGrid.makeHeroDynamic(net.dynamicData, heroGrid, index, human)
	HeroGrid.makeHeroSimple(net.simpleData, heroGrid, index, human)
	net.zhandouli = attrs[RoleDefine.ZHANDOULI] or 0
	net.atk = attrs[RoleDefine.ATK] or 0
	net.hp = attrs[RoleDefine.HP] or 0
	net.def = attrs[RoleDefine.DEF] or 0
	net.speed = attrs[RoleDefine.SPEED] or 0
end

-- 检查世界等级或者玩家等级是否满足条件
-- 检查达到角色等级或者世界等级
function isFixUpStarLv(human, targetStar)
	local config = HeroExcel.star[targetStar]
	if not config then 
		return false
	end
	if config.upStarNeedLv >= 0 and human.db.lv >= config.upStarNeedLv then
		return true, config.upStarNeedLv, config.upStarNeedWorldLv
	end 
	if config.upStarNeedWorldLv >= 0 and GlobalWorld.getWorldLv() >= config.upStarNeedWorldLv then
		return true, config.upStarNeedLv, config.upStarNeedWorldLv
	end 
	return false, config.upStarNeedLv, config.upStarNeedWorldLv	
end

-- 英雄觉醒(升星)
local yunYingActParam = {}
function heroJueXingDo(human, heroID, heroIndex, inputIDList, inputIndexList)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

    local attrConfig = HeroDefine.getAttrConfig(heroID, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroID, heroGrid.star)
	if not nextAttrConfig then return end

	-- 判断是否达到开放等级
	local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then
		if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
		elseif upStarNeedLv then
			return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
		end
		return
	end

	-- 额外条件判断
	if not upStarExtraCondCheck(human, nextAttrConfig.star) then
		return
	end

	-- 判断消耗材料
	local needItemCnt = attrConfig.jinjieshi
	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt) then
		return 
	end

	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		if not BagLogic.checkItemCnt(human, itemID, itemCnt) then
			return
		end
	end
	
	-- 英雄材料
	if not HechengLogic.checkCond(human, inputIDList, inputIndexList, attrConfig.cond) then
		return Broadcast.sendErr(human, Lang.HERO_JUEXING_CAILIAO_ERR)
	end
	-- 比较特别的情况。。
	for i = 1, inputIndexList[0] do
		if inputIndexList[i] == heroIndex then
			return -- 本体同时作为材料，骗分解材料
		end
	end

	-- 扣消耗
	BagLogic.delItem(human, ItemDefine.ITEM_HERO_UPGRADE_ID, needItemCnt, "hero_juexing")
	local fenjieList = FenjieLogic.fenjie(human, FenjieLogic.FENJIE_DO_JUEXING, inputIDList, inputIndexList)	
	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		BagLogic.delItem(human, itemID, itemCnt, "hero_juexing")
	end

	local msgRet = Msg.gc.GC_HERO_JUEXING_DO
	msgRet.id = heroID 
	msgRet.index = heroIndex
    msgRet.upStarNeedLv = upStarNeedLv
    msgRet.upStarNeedWorldLv = upStarNeedWorldLv
	fontJueXingHeroNet(msgRet.oldData, heroGrid, heroIndex, human)

    -- 继承英雄等级 阶数 装备 水晶 
    writeLogHeroDel(human, "hero_juexing", heroGrid)
	heroGrid.star = nextAttrConfig.star
	onGetNewHero(human, heroGrid, "hero_juexing", heroIndex)	
	ObjHuman.doCalcHero(human, heroIndex)

	sendHeroBagDynamic(human, heroGrid.id, heroIndex)
	writeLogHeroAdd(human, "hero_juexing", heroGrid)

	fontJueXingHeroNet(msgRet.newData, heroGrid, heroIndex, human)
	local diffCnt, diffList = getSkillDiffList(attrConfig, nextAttrConfig)
    diffCnt = diffCnt > #msgRet.skillUp and #msgRet.skillUp or diffCnt
	msgRet.isAllSkillUp = (diffCnt > 1) and 1 or 0
    msgRet.skillUp[0] = diffCnt
    for i=1, diffCnt do
	   makeSkillNet(msgRet.skillUp[i], diffList[i][2])
    end
	
	BagLogic.BagLogic_GetAllSendInfo(human, msgRet.itemList, fenjieList, CommonDefine.COMMON_SEND_PRIZE_TYPE_KEYVAL)
	-- if fenjieList then
	-- 	for itemID, itemCnt in pairs(fenjieList) do
	-- 		if msgRet.itemList[0] >= #msgRet.itemList then
	-- 			break
	-- 		end
	-- 		msgRet.itemList[0] = msgRet.itemList[0] + 1
	-- 		Grid.makeItem(msgRet.itemList[msgRet.itemList[0]], itemID, itemCnt)
	-- 	end
	-- end

	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
    ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE12, nextAttrConfig.star,heroGrid.id)

	local newstar = nextAttrConfig.star or 0
	local newcamp =	heroConfig.camp or 0
	LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID24,1,newcamp,newstar)
    if newstar == 5 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_11,1)
    end

    if newstar >= 5 then
        MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_13,1)
    end

    if newstar == 6 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_16,1)
        JibanLogic.onCallback(human,2,newstar)
	end

    if newstar == 10 then
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_23,1)
	end

	checkChangeMaxZDL(human, heroGrid)

    HeroLogLogic.finishTaskCB(human, HeroLogLogic.HERO_LOG_TYPE_8, 1, heroID, newstar)
	-- 弹窗礼包相关触发
	if human.db.heroLevelUpgrade < heroGrid.star then 
		human.db.heroLevelUpgrade = heroGrid.star
		-- GiftLogic.trigger(human,Upgrade_HERO_EVENT,{star = heroGrid.star})

		-- GiftLogic.trigger(human, GiftLogic.GIFT_HERO_UPGRADE_STAR_DAILY, {currentVal = heroGrid.star}, GiftLogic.GIFT_SEC_TYPE1)
	end

	GiftLogic.trigger(human,Upgrade_HERO_EVENT,{star = heroGrid.star})
	GiftLogic.trigger(human, GiftLogic.GIFT_HERO_UPGRADE_STAR_DAILY, {currentVal = heroGrid.star}, GiftLogic.GIFT_SEC_TYPE1)

    for i in ipairs(yunYingActParam) do
        yunYingActParam[i] = nil
    end
    yunYingActParam[1] = heroID
    yunYingActParam[2] = newstar
    yunYingActParam[3] = 1
    YunYingLogic.onCallBack(human, "onHeroStarChange", yunYingActParam)

	TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_GETHERO, human.db._id, 1, newstar)

	TriggerLogic.PublishEvent(TriggerDefine.HERO_YINGHUN_JINHUA, human.db._id, 1)

	TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_GETPOINTHERO, human.db._id, 1, newstar, heroID)

	if heroConfig.grade >= HeroDefine.HERO_SSR_GRADE then
		HeroPubLogic.UpdateHero(human, HeroPubLogic.HERO_OP_UPSTAR, heroID, heroGrid.uuid)
	end

	GodsAreaNS.UpdateHeroData(human, heroGrid.uuid, 1)

	AnotherWorldBattleNS.HeroDataUpdate(human, heroGrid.uuid)
	syncBaiZhanChengShenHero(human, heroGrid.uuid)
end

--返还宝石
function returnGem(gemData)
    if not gemData then
        return
    end

	local calCnt = function(level)
		local cnt = 0
		for i=level, 1, -1 do
			cnt = cnt + math.ceil(i/3)
		end
		return cnt
	end

    local num = 0
    for _, v in pairs(gemData) do
        num = num + calCnt(v.lv)
    end
    return  num
end


-- 英雄重生预览 
function heroChongShengQuery(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_LOCK)
	end

	local chongShengConfig = UpNeedExcel.chongSheng[heroGrid.star]
	if not chongShengConfig then -- 只能重生7-9星
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    -- 没有对应5星的存在
    local attrConfig = HeroDefine.getAttrConfig(heroID, CHONGSHENG_RETURN_STAR)
	if not attrConfig then 
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local suipianID = SuipianLogic.getSuipianIDbyHeroID(heroID)
	if not suipianID then -- 没有对应的本体碎片
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_SUIPIANID)
	end

	local otherSuipianID = chongShengConfig.suipianIDs[heroConfig.camp]
	if not otherSuipianID then -- 阵容不对
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local msgRet = Msg.gc.GC_HERO_CHONGSHENG_QUERY
	msgRet.id = heroID
	msgRet.index = heroIndex
	msgRet.needItemCnt = chongShengConfig.needItemCnt
	Grid.makeItem(msgRet.bentiSuipian, suipianID, chongShengConfig.bentiCnt)
	Grid.makeItem(msgRet.otherSuipian, otherSuipianID, chongShengConfig.suipianCnt)
	
	--Msg.trace(msgRet)

	--宝石返回
	
	local gemCnt = returnGem(heroGrid.gem)
	-- if gemCnt and gemCnt > 0 then
	-- 	Grid.makeItem(msgRet.gemVec, gemId, gemCnt)
	-- end

	local gemId = HeroDefine.HEROJOBTOGEM[heroConfig.job] or 0


	gemCnt = gemCnt or 0
	Grid.makeItem(msgRet.gemVec, gemId, gemCnt)


	Msg.send(msgRet, human.fd)
end


function getHeroMaxStarCtn(human)
	local heroBag = human.db.heroBag
	local maxStar = 0
	local starHeroCnt = 0
	for _,grid in ipairs(heroBag) do 
		if grid.star > maxStar then 
			maxStar = grid.star 
			starHeroCnt = 1 
		elseif  grid.star == maxStar then 
			starHeroCnt = starHeroCnt + 1
		end
	end
	return maxStar,starHeroCnt
end

-- 英雄重生
function heroChongShengDo(human, heroID, heroIndex)
	local heroConfig = HeroExcel.hero[heroID]
	if not heroConfig then return end

	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_LOCK)
	end

	local chongShengConfig = UpNeedExcel.chongSheng[heroGrid.star]
	if not chongShengConfig then -- 只能重生7-9星
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    local attrConfig = HeroDefine.getAttrConfig(heroID, CHONGSHENG_RETURN_STAR)
	if not attrConfig then 
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

	local suipianID = SuipianLogic.getSuipianIDbyHeroID(heroID)
	if not suipianID then -- 没有对应的本体碎片
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_SUIPIANID)
	end

	local otherSuipianID = chongShengConfig.suipianIDs[heroConfig.camp]
	if not otherSuipianID then -- 阵营不对
		return Broadcast.sendErr(human, Lang.HERO_CHONGSHENG_ERR_ID)
	end

    local nowItemCnt = BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_CHONGSHENG_ID)
	local needItemCnt = chongShengConfig.needItemCnt

    if nowItemCnt < needItemCnt then
        local strName = ItemDefine.getValue(ItemDefine.ITEM_HERO_CHONGSHENG_ID, "name")
		local strRet = Util.format(Lang.COMMON_NO_ITEM, strName)
		return Broadcast.sendErr(human, strRet)
    end

    -- 删除材料
    BagLogic.delItem(human, ItemDefine.ITEM_HERO_CHONGSHENG_ID, needItemCnt, "hero_chongsheng")

	-- 重置到初始返还的材料
	local upList = getResetReturnItems(heroGrid)

	local heroUuid = heroGrid.uuid
	local BaiZhanChengShenNS = require("baiZhanChengShen.BaiZhanChengShenNS")
	local bzcsRaces = BaiZhanChengShenNS.collectBzcsRacesWithHero(human, heroUuid)

	-- 先删除英雄
	delHeroByIndex(human, heroIndex, "hero_chongsheng")

    -- 返还装备
	for i = 1, ItemDefine.EQUIP_MAX_CNT do
		if i ~= ItemDefine.EQUIP_SUBTYPE_SHUIJIN and 
			heroGrid.equip and heroGrid.equip[i] then
			local equipGrid = heroGrid.equip[i]
            if equipGrid then
				equipGrid.putUuid = nil
			    EquipLogic.addByEquipGrid(human, equipGrid, "hero_chongsheng")
            end
		end
	end

	-- 返还符文
	for i = 1, 2 do
		local fuwenGrid = heroGrid.fuwen and heroGrid.fuwen[i]
		if fuwenGrid and fuwenGrid.id then
			FuwenLogic.addByGrid(human, fuwenGrid, "hero_chongsheng")
		end
	end


	--宝石返还
	local gemCnt = returnGem(heroGrid.gem)
	if gemCnt and gemCnt > 0 then
		local gemId = HeroDefine.HEROJOBTOGEM[heroConfig.job] or 0 
		BagLogic.addItem(human, gemId, gemCnt, "hero_chongsheng")
	end


	-- 再给东西
	BagLogic.addItem(human, suipianID, chongShengConfig.bentiCnt, "hero_chongsheng")
	BagLogic.addItem(human, otherSuipianID, chongShengConfig.suipianCnt, "hero_chongsheng")
	for itemID, itemCnt in pairs(upList) do
		BagLogic.addItem(human, itemID, itemCnt, "hero_chongsheng")
	end
	
	-- 通知客户端
	local msgRet = Msg.gc.GC_HERO_CHONGSHENG_DO
	msgRet.list[0] = 2
	Grid.makeItem(msgRet.list[1], suipianID, chongShengConfig.bentiCnt)
	Grid.makeItem(msgRet.list[2], otherSuipianID, chongShengConfig.suipianCnt)

	--宝石
	if gemCnt and gemCnt > 0 then
		local gemId = HeroDefine.HEROJOBTOGEM[heroConfig.job] or 0 
		msgRet.list[0] = msgRet.list[0] + 1
		Grid.makeItem(msgRet.list[3], gemId, gemCnt)
	end


	for itemID, itemCnt in pairs(upList) do
		msgRet.list[0] = msgRet.list[0] + 1
		Grid.makeItem(msgRet.list[msgRet.list[0]], itemID, itemCnt)
	end
	msgRet.list[0] = EquipLogic.makeEquipItem(human, msgRet.list, msgRet.list[0])
	Msg.send(msgRet, human.fd)

	checkChangeMaxZDL(human, heroGrid)
	if bzcsRaces and #bzcsRaces > 0 then
		BaiZhanChengShenNS.onHeroDataUpdate(human, nil, bzcsRaces)
	end
end

-- 回退
local HUITUI_HERO_LIST = {}
local HUITUI_ITEM_LIST = {}
function getHuituiReturns(heroGrid)
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	local config = UpNeedExcel.huiTui[heroGrid.star]
	if not config then return end
	local targetID = heroGrid.id
	if not targetID then return end	
    -- 13星无法升级，但可以回退
    if heroGrid.star < 13 then
        local upStarConfig = HeroDefine.getNextAttrConfig(heroGrid.id, heroGrid.star)
	    -- 不能升星的话也不能回退
	    if not upStarConfig then
	    	return
	    end
    end
	Util.cleanTable(HUITUI_HERO_LIST)
	Util.cleanTable(HUITUI_ITEM_LIST)
	local maxLv = HeroGrid.getMaxLv(config.targetStar, heroGrid.quality)
	local lv = heroGrid.lv
	if heroGrid.oldLV then
		lv = heroGrid.oldLV
	end
	
	local targetLv = math.min(lv, maxLv)
	-- 升级 不将阶
	for i = targetLv + 1, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			HUITUI_ITEM_LIST[ItemDefine.ITEM_GREEN_EXP_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			HUITUI_ITEM_LIST[ItemDefine.ITEM_JINBI_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

    -- 圣星文书
    HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_BOOK] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_BOOK] or 0) + config.upBook
	-- 进阶石
	HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_ID] = (HUITUI_ITEM_LIST[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + config.jinjieshi
	-- 5星本体碎片数量 
	local fiveBentiID = heroGrid.id
	local fiveBentiSuipianID = SuipianLogic.getSuipianIDbyHeroID(fiveBentiID)

	HUITUI_ITEM_LIST[fiveBentiSuipianID] = (HUITUI_ITEM_LIST[fiveBentiSuipianID] or 0) + config.fiveBentiCnt
	-- 5星同系碎片数量
	local materialConfig = UpNeedExcel.huiTuiMaterial[heroConfig.camp]
	HUITUI_ITEM_LIST[materialConfig.fiveHeroSuipian] = (HUITUI_ITEM_LIST[materialConfig.fiveHeroSuipian] or 0) + config.fiveSuipianCnt
	
	-- 9星傀儡数量
    local nineHeroCnt = (HUITUI_HERO_LIST[9] and HUITUI_HERO_LIST[9][2] or 0) + config.nineHeroCnt
	HUITUI_HERO_LIST[9] = {materialConfig.nineHero, nineHeroCnt}
	-- 10星傀儡数量
    local tenHeroCnt = (HUITUI_HERO_LIST[10] and HUITUI_HERO_LIST[10][2] or 0) + config.tenHeroCnt
	HUITUI_HERO_LIST[10] = {materialConfig.tenHero, tenHeroCnt}
	return config.targetStar, targetLv, config, HUITUI_ITEM_LIST, HUITUI_HERO_LIST
end

-- 回退查询
function sendHuituiQuery(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	local star, targetLv, config, items, heros = getHuituiReturns(heroGrid)
	if not star then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_STAR)
	end

	local msgRet = Msg.gc.GC_HERO_HUITUI_QUERY
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	HeroGrid.makeHeroSimple(msgRet.oldSimple, heroGrid, heroIndex, human)
	local others = HeroGrid.createOthers(targetLv, nil,nil, star)
	HeroGrid.makeHeroSimpleByID(msgRet.newSimple, heroID, heroIndex, others, nil, true)
	HeroGrid.makeHeroSimpleByGeneral(msgRet.newSimple, heroID)
	Grid.makeItem(msgRet.needItem, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt)
	msgRet.returnItems[0] = 0
	for itemID, itemCnt in pairs(items) do
		if msgRet.returnItems[0] >= #msgRet.returnItems then
			break
		end
		if itemCnt > 0 then
			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemID, itemCnt)
		end
	end

	--专属武器材料
	local weaponReturnItem = HeroExclusiveWeapon.CalcLevelCostItem(human, heroID, heroIndex)
	if weaponReturnItem then
		for itemID, itemCnt in pairs(weaponReturnItem) do
			if msgRet.returnItems[0] >= #msgRet.returnItems then
				break
			end
			if itemCnt > 0 then
				msgRet.returnItems[0] = msgRet.returnItems[0] + 1
				Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemID, itemCnt)
			end
		end
	end

	-- 英雄种子返还材料
	local seedReturnItem = HeroSeed.CalcReturnItem(human, heroGrid)
	if seedReturnItem then
		for _, itemInfo in ipairs(seedReturnItem) do
			if msgRet.returnItems[0] >= #msgRet.returnItems then
				break
			end
			
			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemInfo[1], itemInfo[2])
		end
	end

	local tianYuanReturnItem = HeroTianYuan.CalcReturnItem(human, heroGrid)
	if tianYuanReturnItem then
		for itemId, itemCnt in pairs(tianYuanReturnItem) do
			if msgRet.returnItems[0] >= #msgRet.returnItems then
				break
			end

			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemId, itemCnt)
		end
	end


	local artifactsReturnItems = HeroArtifacts.CalcReturnItem(human, heroGrid)
	if artifactsReturnItems then
		for itemId, itemCnt in pairs(artifactsReturnItems) do
			if msgRet.returnItems[0] >= #msgRet.returnItems then
				break
			end

			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemId, itemCnt)
		end
	end

	msgRet.returnHeros[0] = 0
	for star, v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		for i = 1, rHeroCnt do
			if msgRet.returnHeros[0] >= #msgRet.returnHeros then
				break
			end
            local others = HeroGrid.createOthers(1, nil,nil, star)
			msgRet.returnHeros[0] = msgRet.returnHeros[0] + 1
			local heroNet = msgRet.returnHeros[msgRet.returnHeros[0]]
			HeroGrid.makeHeroSimpleByID(heroNet, rHeroID, nil, others, human)
			HeroGrid.makeHeroSimpleByGeneral(heroNet, rHeroID)
            heroNet.star = star
		end
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)	
end

-- 回退操作
function huituiHero(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end
	local star, targetLv, config, items, heros = getHuituiReturns(heroGrid)
	if not star then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_STAR)
	end
	if heroGrid.isLock then
		return Broadcast.sendErr(human, Lang.HERO_HUITUI_ERR_LOCK)
	end
	local needHeroBagCnt = 0
	for star, v in pairs(heros) do
        local rHeroCnt = v[2]
		needHeroBagCnt = needHeroBagCnt + rHeroCnt
	end
	-- 检查英雄背包空间
	if getEmptyCnt(human) < needHeroBagCnt then
		return Broadcast.sendErr(human, Lang.HERO_BAG_FULL)
	end

	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt) then
		return
	end

	if heroGrid.relic then
		WinnerRelicLogic.WinnerRelic_CancelWinner(human, heroGrid, heroIndex)
		heroGrid.relic = {}
	end

	BagLogic.delItem(human, ItemDefine.ITEM_HERO_HUITUI_ID, config.needItemCnt, "hero_huitui")


	--专属武器材料
	local weaponReturnItem = HeroExclusiveWeapon.CalcLevelCostItem(human, heroID, heroIndex)
	if weaponReturnItem then
		for itemID, itemCnt in pairs(weaponReturnItem) do
			items[itemID] = items[itemID] or 0
			items[itemID] = items[itemID] + itemCnt
		end
	
		--重置专属武器等级
		HeroExclusiveWeapon.SetHeroWeaponLv(human, heroID, heroIndex, 0)
	end

	-- 英雄种子返还材料
	local seedReturnItem = HeroSeed.CalcReturnItem(human, heroGrid)
	if seedReturnItem then
		for _, itemInfo in ipairs(seedReturnItem) do
			local itemId = itemInfo[1]
			local itemCnt = itemInfo[2]
			items[itemId] = (items[itemId] or 0) + itemCnt
		end

		-- 重置英雄所有种子等级
		HeroSeed.ResetSeedLv(human, heroGrid)
	end

	-- 英雄天元返还材料
	local tianYuanReturnItem = HeroTianYuan.CalcReturnItem(human, heroGrid)
	if tianYuanReturnItem then
		for itemId, itemCnt in pairs(tianYuanReturnItem) do
			items[itemId] = (items[itemId] or 0) + itemCnt
		end

		-- 重置英雄天元数据
		HeroTianYuan.ResetTianYuanData(human, heroGrid)
	end

	-- 英雄神威灵装返还材料
	local artifactsReturnItems = HeroArtifacts.CalcReturnItem(human, heroGrid)
	if artifactsReturnItems then
		for itemId, itemCnt in pairs(artifactsReturnItems) do
			items[itemId] = (items[itemId] or 0) + itemCnt
		end

		-- 重置英雄神威灵装数据
		HeroArtifacts.ResetArtifactsData(human, heroGrid)
	end

	heroGrid.star = star
	heroGrid.lv = targetLv
	XingYaoGongMing.onDelHero(human,heroGrid,heroIndex)
	ObjHuman.doCalcHero(human, heroIndex)
	sendHeroBagDynamic(human, heroID, heroIndex)
	writeLogHeroAdd(human, "hero_huitui", heroGrid)

	for itemID, itemCnt in pairs(items) do
		if itemCnt > 0 then
			BagLogic.addItem(human, itemID, itemCnt, "hero_huitui")
		end
	end

	for star,v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		if rHeroCnt > 0 then
			addHero(human, rHeroID,star, rHeroCnt, "hero_huitui")
		end
	end
	
	local msgRet = Msg.gc.GC_HERO_HUITUI
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	HeroGrid.makeHeroSimple(msgRet.newSimple, heroGrid, heroIndex, human)
	msgRet.returnItems[0] = 0
	for itemID, itemCnt in pairs(items) do
		if msgRet.returnItems[0] >= #msgRet.returnItems then
			break
		end
		if itemCnt > 0 then
			msgRet.returnItems[0] = msgRet.returnItems[0] + 1
			Grid.makeItem(msgRet.returnItems[msgRet.returnItems[0]], itemID, itemCnt)
		end
	end
	msgRet.returnHeros[0] = 0
	for star,v in pairs(heros) do
        local rHeroID = v[1]
        local rHeroCnt = v[2]
		for i = 1, rHeroCnt do
			if msgRet.returnHeros[0] >= #msgRet.returnHeros then
				break
			end
			msgRet.returnHeros[0] = msgRet.returnHeros[0] + 1
			local heroNet = msgRet.returnHeros[msgRet.returnHeros[0]]
			HeroGrid.makeHeroSimpleByID(heroNet, rHeroID, nil, nil, human)
            heroNet.star = star
		end
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)	

	checkChangeMaxZDL(human, heroGrid)

	-- 更新酒馆数据
	local heroConfig = HeroExcel.hero[heroID]
	if heroConfig.grade >= HeroDefine.HERO_SSR_GRADE then
		HeroPubLogic.UpdateHero(human, HeroPubLogic.HERO_OP_RETURN, heroGrid.id, heroGrid.uuid)
	end

	GodsAreaNS.UpdateHeroData(human, heroGrid.uuid, 1)

	AnotherWorldBattleNS.HeroDataUpdate(human, heroGrid.uuid)
	syncBaiZhanChengShenHero(human, heroGrid.uuid)
end

function getHeroListById(human,heroId)
	local heroDBBag = human.db.heroBag
	local list = {}
	for idx,grid in pairs(heroDBBag) do
		if type(grid) == "table" and grid.id == heroId then
			list[#list+1] = idx
		end
	end
	return list
end

function getHeroGrid(human, heroID, heroIndex)
    if not heroID then return end
    if not heroIndex then return end
	local heroGrid = human.db.heroBag[heroIndex]
	if type(heroGrid) ~= "table" or heroGrid.id ~= heroID then
		return
	end
	return heroGrid
end

-- 根据uuid 获取heroGrid
function getHeroGridByUuid(human, uuid)
    if not uuid or uuid == "" or uuid == "0" then return end

    for index = 1, human.db.heroBag[0] do
       local heroGrid = human.db.heroBag[index]
       if heroGrid and type(heroGrid) == "table" then
          if heroGrid.uuid == uuid then
             return heroGrid, index
          end
       end
    end

    return nil
end

-- 获取下标英雄id 
function getHeroIdByIndex(human, heroIndex)
    if heroIndex <= 0 then
       return
    end

	local heroGrid = human.db.heroBag[heroIndex]
	if heroGrid == nil then
		return
	end
	return heroGrid.id
end

function makeHeroShare(msg, heroGrid, bagIndex, human)
	if type(heroGrid) ~= "table" then return end
	local heroConfig = HeroExcel.hero[heroGrid.id]
    if not heroConfig then return end

    msg.uuid = human.db._id
    msg.heroIndex = bagIndex
	HeroGrid.makeHeroSimple(msg.heroSimple, heroGrid, bagIndex, human)
	HeroGrid.makeHeroStatic(msg.heroStatic, heroGrid.id)
	HeroGrid.makeHeroDynamic(msg.heroDynamic, heroGrid, bagIndex, human)
	
	-- 装备信息
    msg.equips[0] = 0
	for i = 1, ItemDefine.EQUIP_MAX_CNT do
		local equipGrid = heroGrid.equip and heroGrid.equip[i]
		if equipGrid then
			msg.equips[0] = msg.equips[0] + 1
			local equipNet = msg.equips[msg.equips[0]] 
			Grid.makeItem(equipNet, equipGrid.id, 1, heroGrid.shuijingAttrID, equipGrid)
		end
	end
	-- 符文
    msg.fuWens[0] = 0
    for i = 1, 2 do
    	local fuwenData = heroGrid.fuwen and heroGrid.fuwen[i]
		if fuwenData and fuwenData.id then
			msg.fuWens[0] = msg.fuWens[0] + 1
			local fuwenNet = msg.fuWens[msg.fuWens[0]]
            fuwenNet.pos = i
			Grid.makeItem(fuwenNet.fuwen, fuwenData.id, 1, nil, fuwenData, i,0)
		end
	end
	return true
end

function makeHeroShareMonster(msg, monsterID, mosnterLv)
	local others = HeroGrid.createOthers(mosnterLv)
	msg.uuid = ""
	msg.heroIndex = 0
    HeroGrid.makeHeroSimpleByMonsterID(msg.heroSimple, monsterID, others)		
	HeroGrid.makeHeroStatic(msg.heroStatic, monsterID)
	HeroGrid.makeHeroDynamicByID(msg.heroDynamic, monsterID)	
	msg.equips[0] = 0
	msg.fuWens[0] = 0
end

function getHeroShareGrid(uuid, heroIndex)
    local fakeHuman = ObjHuman.onlineUuid[uuid]
	if not fakeHuman then
		local db = RoleDBLogic.getDb(uuid, RoleLogic.getCombatField())
		if not db then
			return 
		end
		fakeHuman = {db = db}
	end
	local bagIndex = heroIndex

	local heroGrid = bagIndex and fakeHuman.db.heroBag[bagIndex]
	return heroGrid, bagIndex, fakeHuman
end

function shareData(human, uuid, heroIndex, nChatType, nServerIndex)
	print("[shareData] 获取跨服数据开始 uuid = "..uuid.." heroIndex = "..heroIndex.." nChatType = "..nChatType.." nServerIndex = "..nServerIndex)
	if -1 >= nChatType or -1 >= nServerIndex then
		local msgRet = Msg.gc.GC_HERO_SHARE_DATA
		local heroGrid, bagIndex, fakeHuman = getHeroShareGrid(uuid, heroIndex) 
		if heroGrid then
			if not makeHeroShare(msgRet.data, heroGrid, bagIndex, fakeHuman) then
				return
			end
		else
			local monsterID, mosnterLv = JjcLogic.getHeroShareMonster(uuid, heroIndex)
			if not monsterID then return end
			makeHeroShareMonster(msgRet.data, monsterID, mosnterLv)
		end
		Msg.send(msgRet, human.fd)
	else
		print("[shareData] 获取跨服数据开始 uuid = "..uuid.." heroIndex = "..heroIndex.." nChatType = "..nChatType.." nServerIndex = "..nServerIndex)
		HeroMiddleLogic.HeroMiddleLogic_QueryHeroData_LW(human, uuid, heroIndex, nChatType, nServerIndex)
	end
end


-- 获取英雄背包中 最大等级的英雄
function getHeroBagMaxLev(human)
	local maxLv = 1
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and heroGrid.lv > maxLv then
			maxLv = heroGrid.lv
		end
	end
	return maxLv
end

-- 获取英雄背包中 最大星级的英雄
function getHeroBagMaxFuNeng(human)
	local maxStar = 0
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and heroGrid.id then 
			local heroConfig = HeroExcel.hero[heroGrid.id]
			if heroConfig and heroConfig.star > 10 then
				local star = heroConfig.star - 10 
				if star > maxStar then
					maxStar = star
				end
				if maxStar >= HERO_MAX_STAR - 10 then
					return maxStar
				end
			end
		end
		
	end
	return maxStar
end

-- 战力最高的6个英雄战力和
local function sortCombat(a, b)
	return a.zhandouli > b.zhandouli
end

local HeroSortTable = {}
function getHerosZDL(human)
	Util.cleanTable(HeroSortTable)
	local len = 0
	for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 then
            len = len + 1
            HeroSortTable[len] = heroGrid		
		end
	end
	if len > 1 then
		table.sort(HeroSortTable, sortCombat)
	end
	local zhandouli = 0
	for i = 1, 6 do
		local grid = HeroSortTable[i]
        zhandouli = zhandouli + (grid and grid.zhandouli or 0)
	end
    return zhandouli
end

-- 
function getHeroMaxZDL(human, camp)
	local zhandouli = 0
	local maxGrid = nil
	for index,heroGrid in pairs(human.db.heroBag) do
        if index ~= 0 then
		    local heroConfig = heroGrid and HeroExcel.hero[heroGrid.id]
		    if heroConfig and ((camp or 0) == 0 or heroConfig.camp == camp) 
		    	and heroGrid.zhandouli > zhandouli then
		    	zhandouli = heroGrid.zhandouli
		    	maxGrid = heroGrid 
		    end
        end
	end
	return zhandouli, maxGrid
end

-- 武将系统红点
function isDot(human)
    if human.db.lv < 9 then
       return false
    end

	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	if not combatHero then return end

	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		local uuid = combatHero[i]
        local heroGrid = getHeroGridByUuid(human, uuid)
        if heroGrid then
		   if isHeroDot(human, heroGrid) then
		   	return true
		   end
           
        --    if HeroBook.isDot(human) == 1 then
        --        return true
        --    end
        end
	end
end

-- 某个伙伴是否有红点
function isHeroDot(human, heroGrid)
	if not heroGrid then return end

    if human.db.lv < 9 then
       return false
    end

	-- 装备
	if HeroEquip.isEquipDot(human, heroGrid) then
		return true
	end

    if FuwenLogic.isFuwenDot(human, heroGrid) then
		return true
	end

	-- 升级/进阶
	if isHeroLevelDot(human, heroGrid) and 
		not XingYaoGongMing.isGongMing(human,heroIndex)  then
		return true
	end

    --
    if isHeroJuexingDot(human, heroGrid.bagIndex, heroGrid) then
       return true
    end

	if BingshuLogic.isBingShuDot(human, heroGrid) then
		return true
	end

	-- 专属武器
	if HeroExclusiveWeapon.isWeaponDot(human, heroGrid) then
		return true
	end

	-- 英雄种子
	if HeroSeed.isSeedDot(human, heroGrid) then
		return true
	end

	-- 英雄天元
	if HeroTianYuan.isTianYuanDot(human, heroGrid) then
		return true
	end

	-- 英雄神威灵装
	if HeroArtifacts.isArtifactsDot(human, heroGrid) then
		return true
	end
	
end

-- 升级判定
function isHeroLvDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

    local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	local lv = heroGrid and heroGrid.lv or 1
	local star = heroConfig and heroConfig.star or 0
	local quality = heroGrid and heroGrid.quality or 0
	local maxLv = HeroGrid.getMaxLv(heroGrid.star, quality)

	if lv < maxLv then -- 升级
		local conf = UpNeedExcel.upLv[lv + 1]
		if not conf then return end
		if human.db.jinbi < conf.money then return end
		if BagLogic.getItemCnt(human, ItemDefine.ITEM_GREEN_EXP_ID) < conf.soul then
			return 
		end
		return true
	end
end


-- 进阶判断
function isHeroUpDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

    local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

	local lv = heroGrid and heroGrid.lv or 1
	local star = heroGrid and heroGrid.star or 0
	local quality = heroGrid and heroGrid.quality or 0
	
	-- 进阶
	local maxQuality = HeroGrid.getMaxQuality(star)
	if quality >= maxQuality then
		--print("[isHeroUpDot] 当前quality 大于 总的星级 quality = "..quality.." maxQuality = "..maxQuality)
		return
	end

	local maxLv = HeroGrid.getMaxLv(heroGrid.star, maxQuality)	
	if lv >= maxLv then
		--print("[isHeroUpDot] 当前等级 大于 最大等级 lv = "..lv.." maxLv = "..maxLv)
		return
	end

	local nNowMaxLv = HeroGrid.getNowQualityMaxLv(star, quality)
	if lv < nNowMaxLv then
		--print("[isHeroUpDot] 当前等级 还未到达可升的最大等级 lv = "..lv.." nNowMaxLv = "..nNowMaxLv)
		return 
	end

	--print("[isHeroUpDot] id = "..heroGrid.id.." lv = "..lv.." star = "
		--..star.." quality = "..quality.." maxQuality = "..maxQuality.." maxLv = "..maxLv)

	local conf = UpNeedExcel.upQuality[quality + 1]
	if not conf then
		--print("[isHeroUpDot] 不存在下一星级配置 nextquality = "..quality + 1)
		return 
	end

	if human.db.jinbi < conf.money then
		--print("[isHeroUpDot] 玩家金币不足 jinbi = "..human.db.jinbi.." nNeedMoney = "..conf.money)
		return
	end

	if BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID) < conf.jinjieshi then
		--print("[isHeroUpDot] 玩家进阶道具不足 jinjieshi = "..BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID)
		--		.." nNeedjinjieshi = "..conf.jinjieshi)
		return 
	end 

	return true
end

-- 升级/进阶判断
function isHeroLevelDot(human, heroGrid)
    if human.db.lv < 9 then
       return false
    end

	if isHeroLvDot(human, heroGrid) then -- 升级
		return true
	end

	if isHeroUpDot(human, heroGrid) then -- 进阶判断
		return true
	end

end



-- 升星/觉醒红点
function isHeroJuexingDot(human, heroIndex, heroGrid)
    if human.db.lv < 9 then
       return
    end

	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end

    local attrConfig = HeroDefine.getAttrConfig(heroGrid.id, heroGrid.star)
    if not attrConfig then return end

	local nextAttrConfig = HeroDefine.getNextAttrConfig(heroGrid.id, heroGrid.star)
	if not nextAttrConfig then 
       return sendHeroJueXingMax(human, heroGrid.id, heroIndex)
    end

	-- 角色等级/世界等级是否可以
	local isFix = isFixUpStarLv(human, heroGrid.star+1)
	if not isFix then return end
	-- 判断消耗材料
    local needItemCnt = attrConfig.jinjieshi
	if BagLogic.getItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID) < needItemCnt then
		return 
	end
	-- 额外材料
	for i = 1, #attrConfig.needItems do
		local itemID = attrConfig.needItems[i][1]
		local itemCnt = attrConfig.needItems[i][2]
		if BagLogic.getItemCnt(human, itemID) < itemCnt then
			return
		end
	end

	local without = {}
	without[heroIndex] = true
	for _, cond in ipairs(attrConfig.cond) do
		local ctype = cond[1] 
		local needCnt = cond[3] 
		if not needCnt then return end
		if ctype == HechengLogic.COND_TYPE_CAMPSTAR then
			needCnt = cond[4]
		end
		for i = 1, needCnt do
			local index = selectJuexingGrid(human, ctype, cond, without) 
			if not index then return end
			without[index] = true
		end
	end
	return true
end

-- 查找升星材料
function selectJuexingGrid(human, ctype, cond, without)
    for index,heroGrid in pairs(human.db.heroBag) do
		if index ~= 0 and not without[index] and 
			isFixJuexingCond(heroGrid, ctype, cond) then
			return index
		end
	end
end

-- 是否满足材料需求
function isFixJuexingCond(grid, ctype, cond)
	local heroConfig = HeroExcel.hero[grid.id]
	if not heroConfig then return end
	if ctype == HechengLogic.COND_TYPE_HEROID then
        local needConfig = HeroExcel.hero[cond[2]]
        if not needConfig then return end

        local needStar = cond[4] or needConfig.star
		if grid.id == cond[2] and needStar == grid.star then
		   return true
		end
	elseif ctype == HechengLogic.COND_TYPE_CAMPSTAR then
		if cond[2] ~= 0 and cond[2] ~= heroConfig.camp then
			return 
		end
		if cond[3] ~= grid.star then
			return
		end
		return true
	end
end

function sendBagDots(human)
	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	local msgRet = Msg.gc.GC_HERO_BAG_DOTS
	msgRet.list[0] = 0
	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		local uuid = combatHero and combatHero[i]
        local heroGrid = getHeroGridByUuid(human, uuid)
		if heroGrid then
			msgRet.list[0] = msgRet.list[0] + 1
			local net = msgRet.list[msgRet.list[0]] 
			net.bagIndex = heroGrid.bagIndex
			net.isDot = isHeroDot(human, heroGrid) and 1 or 0
		end
	end
	--Msg.trace(msgRet)
	local redDotTag = HeroBook.isDot(human)
    msgRet.bookDot = redDotTag or 0
	Msg.send(msgRet, human.fd)
	refreshDot(human)
end

function refreshDot(human, uuid)
	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
	if not combatHero then return end

	local isFind = nil
	for i = 1, CombatDefine.COMBAT_HERO_CNT do
		if uuid == nil or combatHero[i] == uuid then
			isFind = true
			break
		end
	end
	if not isFind then return end
	RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_301)
end

-- 今日英雄重置剩余次数
function getResetLeftCnt(human)
	local heroResetCnt = human.db.heroResetCnt or 0
	return math.max(HERO_RESET_FREECNT - heroResetCnt, 0)
end

-- 重置返还材料
local RESET_RETURN_ITEMS = {}
function getResetReturnItems(heroGrid)
	Util.cleanTable(RESET_RETURN_ITEMS)

	-- 升级
	local lv = heroGrid.lv
	if heroGrid.oldLV then
		lv = heroGrid.oldLV
	end
	
	for i = 2, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	-- 升阶
	local quality = heroGrid.quality
	if heroGrid.oldQuality then
		quality = heroGrid.oldQuality
	end
	
	-- 升阶
	for i = 1, quality do
		local upcf = UpNeedExcel.upQuality[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + upcf.jinjieshi
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

    -- 升星材料
    for i = 1,heroGrid.star-1 do
        local attrConfig = HeroDefine.getAttrConfig(heroGrid.id, i)
        if attrConfig then
			if  attrConfig.jinjieshi > 0 then 
				RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + attrConfig.jinjieshi 

			end
            for j = 1,#attrConfig.needItems do
                RESET_RETURN_ITEMS[attrConfig.needItems[j][1]] = (RESET_RETURN_ITEMS[attrConfig.needItems[j][1]] or 0) + attrConfig.needItems[j][2]
            end
        end
    end
	-- 护符/水晶材料
	local maxCnt = 100 -- 防止死循环
	local equipID = heroGrid.equip and heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN]
	while equipID do
		maxCnt = maxCnt - 1
		if maxCnt < 0 then 
			assert() 
		end
		local eupcf = EquipExcel.shuijingUpNeed[equipID]
		if not eupcf then break end
		local preEquipID = eupcf.prevID
		equipID = preEquipID
		if preEquipID > 0 then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + eupcf.money
			RESET_RETURN_ITEMS[ItemDefine.ITEM_SHUIJING_UPLEVEL_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_SHUIJING_UPLEVEL_ID] or 0) + eupcf.jinghua
		end
	end

	return RESET_RETURN_ITEMS
end

function getRealResetReturnItems(heroGrid)
	Util.cleanTable(RESET_RETURN_ITEMS)

	-- 升级
	local lv = heroGrid.lv
	if heroGrid.oldLV then 
		lv = heroGrid.oldLV
	end
	
	for i = 2, lv do
		local upcf = UpNeedExcel.upLv[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_GREEN_EXP_ID] or 0) + upcf.soul
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	-- 升阶
	local quality = heroGrid.quality
	if heroGrid.oldQuality then
		quality = heroGrid.oldQuality
	end
	
	-- 升阶
	for i = 1, quality do
		local upcf = UpNeedExcel.upQuality[i]
		if upcf then
			RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_HERO_UPGRADE_ID] or 0) + upcf.jinjieshi
			RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] = (RESET_RETURN_ITEMS[ItemDefine.ITEM_JINBI_ID] or 0) + upcf.money
		end
	end

	return RESET_RETURN_ITEMS
end

-- 重置花费
function getResetNeedZuanshi(lv)
	if lv > 100 then
		return 50
	end
	return 0
end

-- 重置查询
function resetHeroQuery(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_RESET) then
		return
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	if heroConfig.star > HERO_RESET_MAXSTAR then
		return Broadcast.sendErr(human, Util.format(Lang.HERO_RESET_ERR_STAR, HERO_RESET_MAXSTAR + 1))
	end

	ObjHuman.updateDaily(human)
	--[[if getResetLeftCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_CNT)
	end--]]

	local list = getRealResetReturnItems(heroGrid)
	local msgRet = Msg.gc.GC_HERO_RESET_QUERY
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.needZuanshi = getResetNeedZuanshi(heroGrid.lv)
	msgRet.maxFreeCnt = HERO_RESET_FREECNT
	msgRet.leftFreeCnt = getResetLeftCnt(human)
	msgRet.items[0] = 0
	for itemID, itemCnt in pairs(list) do
		if msgRet.items[0] >= #msgRet.items then
			break
		end
		msgRet.items[0] = msgRet.items[0] + 1
		Grid.makeItem(msgRet.items[msgRet.items[0]], itemID, itemCnt)
	end
	if msgRet.items[0] < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_NONE)
	end
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 英雄重置
function resetHero(human, heroID, heroIndex)
	local heroGrid = getHeroGrid(human, heroID, heroIndex)
	if not heroGrid then return end

	if XingYaoGongMing.isGongMing(human,heroIndex,XingYaoGongMing.XYHERO_RESET) then
		return
	end
	
	local heroConfig = HeroExcel.hero[heroGrid.id]
	if not heroConfig then return end
	if heroConfig.star > HERO_RESET_MAXSTAR then
		return Broadcast.sendErr(human, Util.format(Lang.HERO_RESET_ERR_STAR, HERO_RESET_MAXSTAR + 1))
	end

	local list = getRealResetReturnItems(heroGrid)
	if not next(list) then 
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_NONE)
	end

	if getResetLeftCnt(human) < 1 then
		return Broadcast.sendErr(human, Lang.HERO_RESET_ERR_CNT)
	end

	local needZuanshi = getResetNeedZuanshi(heroGrid.lv)
	if not ObjHuman.checkRMB(human, needZuanshi) then
		return
	end
	ObjHuman.decZuanshi(human, -needZuanshi, "hero_reset")
	human.db.heroResetCnt = (human.db.heroResetCnt or 0) + 1

	heroGrid.lv = 1
	heroGrid.quality = 0
	if heroGrid.equip and heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN] then
		heroGrid.equip[ItemDefine.EQUIP_SUBTYPE_SHUIJIN] = nil 
		heroGrid.shuijingAttrID = nil
	end

	for itemID, itemCnt in pairs(list) do
		BagLogic.addItem(human, itemID, itemCnt, "hero_reset")
	end
	HeroEquip.putOffQuick(human, heroID, heroIndex, true)
	FuwenLogic.putOffQuick(human, heroID, heroIndex, true)
	XingYaoGongMing.onDelHero(human,heroGrid,heroIndex)
    heroGrid.fuwen = nil

	if heroGrid.relic then
		WinnerRelicLogic.WinnerRelic_CancelWinner(human, heroGrid, heroIndex)
		heroGrid.relic = {}
	end

    ObjHuman.doCalcHero(human,heroIndex)
    sendHeroBagDynamic(human, heroID, heroIndex)
	refreshDot(human, heroGrid.uuid)

	local msgRet = Msg.gc.GC_HERO_RESET
	msgRet.heroID = heroID
	msgRet.heroIndex = heroIndex
	msgRet.items[0] = 0 
	for itemID, itemCnt in pairs(list) do
		if msgRet.items[0] >= #msgRet.items then
			break
		end

		if not ItemDefine.isEquip(itemID) then
		   msgRet.items[0] = msgRet.items[0] + 1
		   Grid.makeItem(msgRet.items[msgRet.items[0]], itemID, itemCnt)
		end
	end
	msgRet.items[0] = EquipLogic.makeEquipItem(human, msgRet.items, msgRet.items[0])
	Msg.send(msgRet, human.fd)	

	checkChangeMaxZDL(human, heroGrid)
	syncBaiZhanChengShenHero(human, heroGrid.uuid)
end

-- 对所有英雄操作一次装备皮肤
function AllHeroEquipSkin(human)
    if not human then
        return
    end

	local nHeroLen = human.db.heroBag[0]
	if 0 >= nHeroLen then
		return
	end

	local tEquipSkin = {}
	for i = 1, nHeroLen, 1 do
		local heroGrid = human.db.heroBag[i]
		if heroGrid then
			local nID = heroGrid.id
			-- 不存在去查表
			if not tEquipSkin[nID] then
				local bHaveSkin = false
				local skinOn = SkinLogic.checkHeroSkinById(human, nID)

				if skinOn then
					heroGrid.skinOn = skinOn
					bHaveSkin = true
				else
					skinOn = -1
				end

				tEquipSkin[nID] = {bHaveSkin = bHaveSkin, skinOn = skinOn}
			else
				if true == tEquipSkin[nID].bHaveSkin then
					heroGrid.skinOn = tEquipSkin[nID].skinOn
				end
			end
		end
	end
end

-- 统计英雄背包中, 每类SSR, UR英雄的最高星级
function GetHeroMaxStarList(human)
	local noCalcHeroList = {}
	local maxStarList = {}

	for index = 1, human.db.heroBag[0] do
        local heroGrid = human.db.heroBag[index]
        if heroGrid and not noCalcHeroList[heroGrid.id] then
			local heroId = heroGrid.id
			local heroCfg = HeroExcel.hero[heroId]

			if heroCfg.grade < HeroDefine.HERO_SSR_GRADE then
				noCalcHeroList[heroId] = 1
			else
				if not maxStarList[heroId] then
					maxStarList[heroId] = {
						uuid = heroGrid.uuid,
						star = heroGrid.star
					}
				else
					if heroGrid.star > maxStarList[heroId].star then
						maxStarList[heroId].uuid = heroGrid.uuid
						maxStarList[heroId].star = heroGrid.star
					end
				end
			end
		end
	end

	return maxStarList
end

-- 统计背包中符合星级条件的英雄数量
function CalcStarHeroCnt(human, starCond, excludeList)
	local correctNum = 0
	for index = 1, human.db.heroBag[0] do
        local heroGrid = human.db.heroBag[index]
        if heroGrid and heroGrid.star >= starCond and (not excludeList or not excludeList[heroGrid.uuid]) then
			correctNum = correctNum + 1
		end
	end

	return correctNum
end



-- 获取背包中同Id最高星级的英雄
function GetMaxStarHero(human, heroId)
	local heroCfg = HeroExcel.hero[heroId]
	if heroCfg.grade < HeroDefine.HERO_SSR_GRADE then
		return
	end

	local posList = getHeroListById(human, heroId)
	if #posList == 0 then
		return
	end

	local herouuid
	local maxStar = 0
	for _, pos in ipairs(posList) do
		local heroGrid = human.db.heroBag[pos]
		if maxStar == 0 then
			maxStar = heroGrid.star
			herouuid = heroGrid.uuid
		end

		if heroGrid.star > maxStar then
			maxStar = heroGrid.star
			herouuid = heroGrid.uuid
		end
	end

	return maxStar, herouuid
end

function heroJueXingOneClickQuery(human)
	local tMsgData = Msg.gc.GC_HERO_JUEXIN_ONECLICK_QUERY
	tMsgData.bOneClick = 1
	local bOpen = Abs365CardLogic.IsBuyCard(human)
	if 0 == bOpen then
		print("[heroJueXingOneClickQuery] 未购买365卡直接返回")
		tMsgData.bOneClick = 0
		Msg.send(tMsgData, human.fd)
		return
	end

	Msg.send(tMsgData, human.fd)
	print("[heroJueXingOneClickQuery] 回复协议结束")
end

local function HeroLogic_CheckOneClickHero(human, tHero, tHeroInfo)
	local tCheckHero = {}
	local nHeroLen = tHero[0]
	-- 先检测英雄
	if nHeroLen % 2 ~= 0 then
		print("[heroJueXingOneClickDo] 英雄长度不正确 nHeroLen = "..nHeroLen)
		return false
	end

	-- 消耗材料检查
	local nJinJieShiNum, tExtraItem = 0, {}
	for i = 1, nHeroLen, 2 do
		local nHeroID, nHeroIndex = tHero[i], tHero[i+1]
		if not tCheckHero[nHeroID] then
			tCheckHero[nHeroID] = 1
		else
			print("[heroJueXingOneClickDo] 存在重复的英雄ID nHeroID = "..nHeroID)
			return false
		end

		-- 英雄是否存在
		local heroGrid = getHeroGrid(human, nHeroID, nHeroIndex)
		if not heroGrid then 
			return false
		end

		local attrConfig = HeroDefine.getAttrConfig(nHeroID, heroGrid.star)
		if not attrConfig then 
			return false
		end

		local nextAttrConfig = HeroDefine.getNextAttrConfig(nHeroID, heroGrid.star)
		if not nextAttrConfig then 
			return false
		end

		-- 判断是否达到开放等级
		local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
		if not isFix then
			if upStarNeedLv and upStarNeedWorldLv and upStarNeedWorldLv > 0 then
				return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV, upStarNeedLv, upStarNeedWorldLv))
			elseif upStarNeedLv then
				return Broadcast.sendErr(human, Util.format(Lang.HERO_JUEXING_ERR_HEROLV2, upStarNeedLv))
			end
			return false
		end

		-- 累加材料
		nJinJieShiNum = nJinJieShiNum + attrConfig.jinjieshi
		for j = 1, #attrConfig.needItems do
			local itemID = attrConfig.needItems[j][1]
			local itemCnt = attrConfig.needItems[j][2]
			if not tExtraItem[itemID] then
				tExtraItem[itemID] = 0
			end

			tExtraItem[itemID] = tExtraItem[itemID] + itemCnt
		end

		local tData = {
			nHeroID = nHeroID,
			nHeroIndex = nHeroIndex,
			tInputIDList = {},
			tInputIndexList = {}
		}

		table.insert(tHeroInfo, tData)
	end

	return true, nJinJieShiNum, tExtraItem
end

function heroJueXingOneClickDo(human, tHeroData)
	local nAllLen = tHeroData[0]
	if 0 >= nAllLen then
		return
	end
	print("[heroJueXingOneClickDo] 开始进入协议")

	local tHero, tInputIDList, tInputIndexList = {}, {}, {}
	local nBeginLen, nForNum, nGuiShuIndex = 1, 0, 1

	tHero[0] = 0
	tInputIDList[0] = 0
	tInputIndexList[0] = 0

	local tCheckIndex = {}

	while nBeginLen < nAllLen do
		if nForNum >= 200 then
			print("[heroJueXingOneClickDo] 解析数据失败")
			return
		end
		nForNum = nForNum + 1

		local nHeroID, nHeroIndex = tHeroData[nBeginLen], tHeroData[nBeginLen + 1]
		if not tCheckIndex[nHeroIndex] then
			tCheckIndex[nHeroIndex] = true
		else
			print("[heroJueXingOneClickDo] 存在重复的英雄Index nHeroIndex = "..nHeroIndex)
			return
		end
		
		tHero[0] = tHero[0] + 2
		table.insert(tHero, nHeroID)
		table.insert(tHero, nHeroIndex)

		nBeginLen = nBeginLen + 2
		local nIDLen = tHeroData[nBeginLen]
		if not nIDLen or nBeginLen + nIDLen > nAllLen then
			break
		end

		-- 处理消耗的HeroID
		table.insert(tInputIDList, nGuiShuIndex)
		table.insert(tInputIDList, nIDLen)
		tInputIDList[0] = tInputIDList[0] + 2

		for i = nBeginLen + 1, nBeginLen + nIDLen, 1 do
			tInputIDList[0] = tInputIDList[0] + 1
			table.insert(tInputIDList, tHeroData[i])
		end

		-- 处理消耗的HeroIndex
		nBeginLen = nBeginLen + nIDLen + 1
		if nBeginLen > nAllLen then
			break
		end

		local nHeroIndexLen = tHeroData[nBeginLen]
		if not nHeroIndexLen then
			print("[heroJueXingOneClickDo] 不存在对应的nHeroIndexLen nBeginLen = "..nBeginLen)
			return
		end

		table.insert(tInputIndexList, nGuiShuIndex)
		table.insert(tInputIndexList, nHeroIndexLen)
		tInputIndexList[0] = tInputIndexList[0] + 2

		for i = nBeginLen + 1, nBeginLen + nHeroIndexLen, 1 do
			local nIndex = tHeroData[i]
			if not tCheckIndex[nIndex] then
				tCheckIndex[nIndex] = true
			else
				print("[heroJueXingOneClickDo] 存在重复的英雄Index nHeroIndex = "..nIndex)
				return
			end

			tInputIndexList[0] = tInputIndexList[0] + 1
			table.insert(tInputIndexList, nIndex)
		end

		nBeginLen = nBeginLen + nHeroIndexLen + 1
		nGuiShuIndex = nGuiShuIndex + 1
	end
	
	print("[heroJueXingOneClickDo] 解析上传数据完成")
	
	local tHeroInfo = {}
	local nHeroLen, nInputIDLen, nInputIndexLen = tHero[0], tInputIDList[0], tInputIndexList[0]
	if 0 >= nHeroLen or 0 >= nInputIDLen or 0 >= nInputIndexLen then
		print("[heroJueXingOneClickDo] 上传的数据长度不正确")
		return
	end

	-- 先检测英雄
	local bRet, nJinJieShiNum, tExtraItem = HeroLogic_CheckOneClickHero(human, tHero, tHeroInfo)
	if false == bRet or not nJinJieShiNum or not tExtraItem then
		print("[heroJueXingOneClickDo] 英雄检查不通过")
		return
	end

	print("[heroJueXingOneClickDo] 检测英雄 完成")

	-- 检查消耗材料是否足够
	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_HERO_UPGRADE_ID, nJinJieShiNum) then
		print("[heroJueXingOneClickDo] 英雄消耗材料不足 nJinJieShiNum = "..nJinJieShiNum)
		return 
	end

	print("[heroJueXingOneClickDo] 检查消耗材料是否足够 完成")

	-- 检查消耗额外材料
	for itemID, itemCnt in pairs(tExtraItem) do
		if not BagLogic.checkItemCnt(human, itemID, itemCnt) then
			print("[heroJueXingOneClickDo] 英雄消耗额外材料不足 itemID = "..itemID.." itemCnt = "..itemCnt)
			return
		end
	end

	print("[heroJueXingOneClickDo] 检查消耗额外材料 完成")

	-- 统计消耗的英雄ID
	local i, nLen = 1, 0
	while i < nInputIDLen do
		if nLen >= 100 then
			print("[heroJueXingOneClickDo] 循环次数不正确，死循环返回")
			return
		end
		nLen = nLen + 1

		local nIndex = tInputIDList[i]
		i = i + 1
		local nHeroIDLen = tInputIDList[i]

		if not tHeroInfo[nIndex] then
			print("[heroJueXingOneClickDo] 英雄ID 下标 与上传的英雄信息数量不同 nIndex = "..nIndex)
			return
		end

		local tHeroInputIDList = tHeroInfo[nIndex].tInputIDList
		for j = i + 1, i + nHeroIDLen, 1 do
			local nID = tInputIDList[j]
			table.insert(tHeroInputIDList, nID)
		end
		tHeroInputIDList[0] = nHeroIDLen
		
		i = i + nHeroIDLen + 1
	end

	print("[heroJueXingOneClickDo] 统计消耗的英雄ID 完成")

	-- 统计消耗的英雄Index
	i = 1
	nLen = 0
	while i < nInputIndexLen do
		if nLen >= 100 then
			print("[heroJueXingOneClickDo] 循环次数不正确，死循环返回")
			return
		end
		nLen = nLen + 1

		local nIndex = tInputIndexList[i]
		i = i + 1
		local nHeroIndexLen = tInputIndexList[i]
		if not tHeroInfo[nIndex] then
			print("[heroJueXingOneClickDo] 英雄下标 与上传的英雄信息数量不同 nIndex = "..nIndex)
			return
		end

		local tHeroInputIndexList = tHeroInfo[nIndex].tInputIndexList
		for j = i + 1, i + nHeroIndexLen, 1 do
			local nID = tInputIndexList[j]
			table.insert(tHeroInputIndexList, nID)
		end
		tHeroInputIndexList[0] = nHeroIndexLen
		
		i = i + nHeroIndexLen + 1
	end

	print("[heroJueXingOneClickDo] 统计消耗的英雄Index 完成")

	-- table.print_lua_table(tHeroInfo)

	-- 检查升级数据是否有问题
	for _, v in ipairs(tHeroInfo) do
		local nHeroID, nHeroIndex = v.nHeroID, v.nHeroIndex
		local heroGrid = getHeroGrid(human, nHeroID, nHeroIndex)
		if not heroGrid then 
			print("[heroJueXingOneClickDo] 获取不到对应的英雄 heroGrid nHeroID = "..nHeroID.." nHeroIndex = "..nHeroIndex)
			return 
		end

    	local attrConfig = HeroDefine.getAttrConfig(nHeroID, heroGrid.star)
		if not attrConfig then 
			print("[heroJueXingOneClickDo] 获取不到对应的英雄attr属性 heroGrid nHeroID = "..nHeroID.." nHeroIndex = "..nHeroIndex)
			return
		end

		if not HechengLogic.checkCond(human, v.tInputIDList, v.tInputIndexList, attrConfig.cond) then
			return Broadcast.sendErr(human, Lang.HERO_JUEXING_CAILIAO_ERR)
		end
	end

	print("[heroJueXingOneClickDo] 进入扣材料阶段")
	-- 扣消耗
	BagLogic.delItem(human, ItemDefine.ITEM_HERO_UPGRADE_ID, nJinJieShiNum, "hero_juexing")
	-- 额外材料
	for itemID, itemCnt in pairs(tExtraItem) do
		BagLogic.delItem(human, itemID, itemCnt, "hero_juexing")
	end

	print("[heroJueXingOneClickDo] 开始正式合成英雄")

	local tMsgData = Msg.gc.GC_HERO_JUEXING_ONECLICK_DO
	tMsgData.tHeroList[0] = #tHeroInfo
	for j, v in ipairs(tHeroInfo) do
		-- 下面的数据已经在上面检查过了
		local heroGrid = getHeroGrid(human, v.nHeroID, v.nHeroIndex)
		local isFix, upStarNeedLv, upStarNeedWorldLv = isFixUpStarLv(human, heroGrid.star+1)
		local nextAttrConfig = HeroDefine.getNextAttrConfig(v.nHeroID, heroGrid.star)
		local attrConfig = HeroDefine.getAttrConfig(v.nHeroID, heroGrid.star)

		local fenjieList = FenjieLogic.fenjie(human, FenjieLogic.FENJIE_DO_JUEXING, v.tInputIDList, v.tInputIndexList)
		local tData = tMsgData.tHeroList[j]

		tData.id = v.nHeroID
		tData.index = v.nHeroIndex
		fontJueXingHeroNet(tData.oldData, heroGrid, v.nHeroIndex, human)

		-- 继承英雄等级 阶数 装备 水晶 
		writeLogHeroDel(human, "hero_juexing", heroGrid)
		heroGrid.star = nextAttrConfig.star
		onGetNewHero(human, heroGrid, "hero_juexing", v.nHeroIndex)	
		ObjHuman.doCalcHero(human, v.nHeroIndex)

		sendHeroBagDynamic(human, heroGrid.id, v.nHeroIndex)
		writeLogHeroAdd(human, "hero_juexing", heroGrid)

		fontJueXingHeroNet(tData.newData, heroGrid, v.nHeroIndex, human)
		local diffCnt, diffList = getSkillDiffList(attrConfig, nextAttrConfig)
		diffCnt = diffCnt > #tData.skillUp and #tData.skillUp or diffCnt
		tData.isAllSkillUp = (diffCnt > 1) and 1 or 0
		tData.skillUp[0] = diffCnt
		for k = 1, diffCnt do
			makeSkillNet(tData.skillUp[k], diffList[k][2])
		end

		BagLogic.BagLogic_GetAllSendInfo(human, tData.itemList, fenjieList, CommonDefine.COMMON_SEND_PRIZE_TYPE_KEYVAL)

		ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE12, nextAttrConfig.star,heroGrid.id)

		local heroConfig = HeroExcel.hero[v.nHeroID]
		local newstar = nextAttrConfig.star or 0
		local newcamp =	heroConfig.camp or 0
		LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID24,1,newcamp,newstar)
		if newstar == 5 then
			ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_11,1)
		end

		if newstar >= 5 then
			MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_13,1)
		end

		if newstar == 6 then
			ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_16,1)
			JibanLogic.onCallback(human,2,newstar)
		end

		if newstar == 10 then
			ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_23,1)
		end

		checkChangeMaxZDL(human, heroGrid)

		HeroLogLogic.finishTaskCB(human, HeroLogLogic.HERO_LOG_TYPE_8, 1, v.nHeroID, newstar)
		-- 弹窗礼包相关触发
		if human.db.heroLevelUpgrade < heroGrid.star then 
			human.db.heroLevelUpgrade = heroGrid.star
			-- GiftLogic.trigger(human,Upgrade_HERO_EVENT,{star = heroGrid.star})

			-- GiftLogic.trigger(human, GiftLogic.GIFT_HERO_UPGRADE_STAR_DAILY, {currentVal = heroGrid.star}, GiftLogic.GIFT_SEC_TYPE1)
		end

		GiftLogic.trigger(human,Upgrade_HERO_EVENT,{star = heroGrid.star})
		GiftLogic.trigger(human, GiftLogic.GIFT_HERO_UPGRADE_STAR_DAILY, {currentVal = heroGrid.star}, GiftLogic.GIFT_SEC_TYPE1)

		for j in ipairs(yunYingActParam) do
			yunYingActParam[j] = nil
		end
		yunYingActParam[1] = v.nHeroID
		yunYingActParam[2] = newstar
		yunYingActParam[3] = 1
		YunYingLogic.onCallBack(human, "onHeroStarChange", yunYingActParam)

		TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_GETHERO, human.db._id, 1, newstar)

		TriggerLogic.PublishEvent(TriggerDefine.HERO_YINGHUN_JINHUA, human.db._id, 1)

		TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_GETPOINTHERO, human.db._id, 1, newstar,  v.nHeroID)

		if heroConfig.grade >= HeroDefine.HERO_SSR_GRADE then
			HeroPubLogic.UpdateHero(human, HeroPubLogic.HERO_OP_UPSTAR, v.nHeroID, heroGrid.uuid)
		end

		GodsAreaNS.UpdateHeroData(human, heroGrid.uuid, 1)
	end

	print("[heroJueXingOneClickDo] 正式合成英雄结束")

	Msg.send(tMsgData, human.fd)

	print("[heroJueXingOneClickDo] 发送协议完成")

	-- HechengLogic.hechengQuery(human, 0)
end