----------------------------------
-- 角色相关逻辑
----------------------------------
local Config = require("Config")
local Util = require("common.Util")
local Log = require("common.Log")
local Lang = require("common.Lang")
local LogDefine = require("common.LogDefine")
local CommonDefine = require("common.CommonDefine")
local RoleExcel = require("excel.role")
local Msg = require("core.Msg")
local Obj = require("core.Obj")
local Timer = require("core.Timer")
local RoleAttr = require("role.RoleAttr")
local RoleDBLogic = require("role.RoleDBLogic")
local RoleDefine = require("role.RoleDefine")
local Broadcast = require("broadcast.Broadcast")
local BagLogic = require("bag.BagLogic")
local HeroLogic = require("hero.HeroLogic")
local VipLogic = require("vip.VipLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local BarTaskLogic = require("bar.BarTaskLogic")
local CombatPosLogic = require("combat.CombatPosLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local OnlineRewardLogic = require("onlineReward.OnlineRewardLogic")
local SettingLogic = require("setting.SettingLogic")
local ChatHandler = require("chat.Handler")
local FriendLogic = require("friend.FriendLogic")
local UnionDBLogic = require("union.UnionDBLogic")
local BuyLogic = require("topup.BuyLogic")
local GiftLogic = require("topup.GiftLogic")
local ReportManager = require("platform.ReportManager")
local BattleLogic = require("battle.BattleLogic")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local RoleLogic = require("role.RoleLogic")
local FuwenLogic = require("fuwen.FuwenLogic")
local EquipLogic = require("equip.EquipLogic")
local TequanLogic = require("qqTequan.TequanLogic")
local ShopLogic = require("shop.ShopLogic")
local MailLogic = require("mail.MailLogic")
local LianyuLogic = require("lianyu.LianyuLogic")
local MiddleLogic = require("middle.MiddleLogic")
local MiddleOption = require("middle.MiddleOption")
local GuideLogic = require("guide.GuideLogic")
local ItemDefine = require("bag.ItemDefine")
local DrillLogic = require("drill.DrillLogic")
local BRoleLogic = require("billboard.BRoleLogic")
local BillboardDefine = require("billboard.BillboardDefine")
local FcmLogic = require("fcm.FcmLogic")
local CombatLogic = require("combat.CombatLogic")
local SceneHandler = require("scene.Handler")
local TuiSongLiBao = require("present.TuiSongLiBao")
local CopyLogic = require("copy.CopyLogic")
local HuanJingTowerLogic = require("huanjingTower.HuanjingTowerLogic")
local UnionLivenessLogic = require("union.UnionLivenessLogic")
local UnionDonateLogic = require("union.UnionDonateLogic")
local RoleStrongLogic = require("role.RoleStrongLogic")
local DailyTaskLogic = require("dailyTask.DailyTaskLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local FirstChargeLogic = require("present.FirstChargeLogic")
local JjcLadderLogic = require("jjcLadder.JjcLadderLogic")
local RelationGiftLogic = require("present.RelationGiftLogic")
local WelfareGiftLogic = require("present.WelfareGiftLogic")
local GlobalWorld = require("core.GlobalWorld")
local ChatRecord = require("chat.ChatRecord")
local WarReportLogic = require("warReport.WarReportLogic")
local ZhuanpanLogic = require("zhuanpan.ZhuanpanLogic")
local UnionRedBagLogic = require("union.UnionRedBagLogic")
local JjcGodWarLogic = require("jjcGodWar.JjcGodWarLogic")
local JibanLogic = require("combat.JibanLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local KingWorldLogic = require("present.KingWorldLogic")
local CommonDB = require("common.CommonDB")
local ZhanbuLogic = require("zhanbu.ZhanbuLogic")
local TopupLogic = require("topup.TopupLogic")
local HeroLogLogic = require("absAct.HeroLogLogic")
local FanliLogic = require("platform.FanliLogic")
local HeroGrowUp = require("absAct.HeroGrowUp")
local MailManager = require("mail.MailManager")
local MailExcel = require("excel.mail")
local PfLogic = require("platform.PfLogic")
local MoshouLogic = require("moshou.MoshouLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local LostTempleLogic = require("lostTemple.lostTempleLogic")
local DrawCardV2Excel = require("excel.drawCard").drawCardV2
local WarOrder = require("shop.WarOrder")
local OpenServerActPowerUp = require("present.OpenServerActPowerUp")
local VoucherShopLogic = require("voucher.VoucherShopLogic")
local RacialTrialLogic = require("racialTrial.RacialTrialLogic")
local MaiDianDefine = require("MaiDian.MaiDianDefine")
local MainDianLogic = require("MaiDian.MaiDianLogic")
local OnlineAwardLogic = require("present.OnlineAwardLogic")
local RoleHeadLogic = require("role.RoleHeadLogic")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")
local MainTask = require("dailyTask.MainTask")
local ClutterDataLogic = require("clutter.ClutterDataLogic")
local QQBigShot = require("platform.QQBigShot")
local RebateLogic = require("platform.RebateLogic")
local HeroPubLogic = require("hero.HeroPubLogic")
local JjcNewLadderLogic = require("jjcnewladder.jjcNewLadderLogic")
local WinnerRelicLogic = require("winnerRelic.WinnerRelicLogic")
local commonOperate = require("core.commonOperate")
local AnotherWorldBattleNS = require("anotherWorldBattle.AnotherWorldBattleNS")
local RoleStorageBox = require("roleSystem.RoleStorageBox")
local BreakThroughTheme = require("battle.BreakThroughTheme")
local BattleGift = require("battle.BattleGift")
local BigRPlayerShow = require("broadcast.BigRPlayerShow")
local BaiZhanChengShenNS = require("baiZhanChengShen.BaiZhanChengShenNS")


local Json = require("common.Json")

local UnionLogic
local GodsAreaNS
local DataCache
local VoucherInvest


fds				= fds or {}				-- fd->obj_id,包括创角中+游戏中
onlineAccount 	= onlineAccount or {} 	-- account->human,包括创角中+游戏中(弃用, 没删掉是防止有些有些暂时没修改的地方访问时报错)
onlineNewUniqueTag = onlineNewUniqueTag or {} -- NewUniqueTag->human, 合服后可能存在多个角色account相同情况，所以用NewUniqueTag 
onlineHuman		= onlineHuman or {} 	-- name->human,仅包括游戏中
onlineUuid		= onlineUuid or {} 		-- uuid->human,仅包括游戏中

function create(fd, account, db, uTag)
	local human = {}
	Obj.create(human, Obj.TYPE_HUMAN)
	
	fds[fd] = human.id
	
	human.fd = fd
	-- human.db = db or RoleDBLogic.loadRole(account)

	human.db = db or RoleDBLogic.loadRole(uTag)

	if human.db ~= nil then
		initHuman(human)
	else
		human.account = account
		-- human.serverTag = serverTag
		human.newUniqueTag = uTag
	end	
	return human
end

function initHuman(human)
	local now = os.time()
	human.preLoginTime = human.db.lastLoginTime 				-- 上一次登录时间
	human.db.lastLoginTime = now								-- 记录最近一次登录时间
	human.saveDBTime = Timer.now								-- 人物数据库保存时间
	human.firstEnter = true										-- 首次进入场景

	-- 角色信息初始化
	--onlineAccount[human.db.account] = human
	onlineNewUniqueTag[human.db.newUniqueTag] = human

	onlineHuman[human.db.name] = human
	onlineUuid[human.db._id] = human
end

function destroy(human)
	--local account = human.account or human.db.account
	local newUniqueTag = human.newUniqueTag or human.db.newUniqueTag
	if human.fd then fds[human.fd] = nil end
	if human.db then	-- 已创角
		--onlineAccount[account] = nil
		onlineNewUniqueTag[newUniqueTag] = nil
		onlineHuman[human.db.name] = nil
		onlineUuid[human.db._id] = nil
	end
	Obj.destroy(human)
end

function doDisconnect(human, code)
	print("doDisconnect newUniqueTag:", human.newUniqueTag or human.db.newUniqueTag, " code:", code)

	if human.db then
		local now = os.time()
		if human.db.changeNameCnt ~= nil then
			--Log.write(Log.LOGID_OSS_LOGOUT, human.db._id, human.db.account, human.db.name, human.db.lv, human.db.ip, code, now - human.db.lastLoginTime)
			Log.write(Log.LOGID_OSS_LOGOUT, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, human.db.ip, code, now - human.db.lastLoginTime)
		end
		if human.fd then 	
			onLogout(human)
		end
	end

	if code ~= CommonDefine.DISCONNECT_NORMAL and code ~= CommonDefine.DISCONNECT_NORMAL_AFTER then
		if _G.is_middle ~= true then
			local mm = Msg.gc.GC_DISCONNECT
			mm.code = code
			mm.msg = CommonDefine.DISCONNECT_MSG[code] or ""
			Msg.send(mm, human.fd)
		end
	end

	if human.db then
		if code ~= CommonDefine.DISCONNECT_NORMAL then 		-- 正常断线先不销毁
			if code ~= CommonDefine.DISCONNECT_DUPLICATE then
				CombatLogic.forceFinish(human) 
			end
			ReportManager.quit(human,code)
			destroy(human)
			if code == CommonDefine.DISCONNECT_DUPLICATE then
			else
				if _G.is_middle == true then
					-- 数据销毁 要把db数据发回给正常服
					MiddleLogic.sendWL_DB_BACK(human)
				else
					local ret, err = pcall(save, human)
					if not ret then
						--Log.write(Log.LOGID_ERR_PCALL, "destroy account=" .. human.db.account, err)
						Log.write(Log.LOGID_ERR_PCALL, "destroy newUniqueTag=" .. human.db.newUniqueTag, err)
					end
				end
			end
			return
		end
	else
		destroy(human) 		-- 未创角，立刻销毁对象
		return
	end

	if not human.fd then
		assert()
	end
	fds[human.fd] = nil
	human.fd = nil
	human.f5 = Timer.now
end

-- 下线回调
function onLogout(human)
	local nowTime = os.time()
	human.db.lastLogoutTime = os.time() 		-- 记录最近登出时间
	local time = math.max(nowTime - human.db.lastLoginTime, 0)
	human.db.onlineTime = (human.db.onlineTime or 0) + time		-- 记录在线时长
	local time2 = nowTime - math.max(human.db.lastLoginTime, Util.getDayStartTime(nowTime))
	human.db.onlineTimeDay = (human.db.onlineTimeDay or 0) + math.max(time2, 0)		-- 记录本日在线时长

	LianyuLogic.onLogout(human)
    OnlineRewardLogic.onLogout(human, time)

    YunYingLogic.onCallBack(human, "onLogout")
	TriggerLogic.onLogout(human)

	-- local tMsgData = Msg.gc.GC_ONLINETIME_REPORT
    -- tMsgData.time = nowTime - human.db.onlineTimeDayReport
	-- tMsgData.nType = 0
    -- Msg.send(tMsgData, human.fd)
end


function saveCharDB()
	local now = Timer.now
	local minn
	local ans
	for _, human in pairs(onlineUuid) do
		if human.fd then
			local t = human.saveDBTime
			if 300000 <= now - t and (not minn or t < minn) then
				minn = t
				ans = human
			end
		end
	end
	if not ans then
		return
	end
	ans.saveDBTime = now
	local ret, err = pcall(save, ans)
	if not ret then
		Log.write(Log.LOGID_ERR_PCALL, "saveCharDB rolename="..ans.db.name, err)
	end
end

function humanOfflineCheck()
	if _G.is_middle == true then
		local now = os.time()
		-- for account, human in pairs(onlineAccount) do
		-- 	if human.fd == nil then
		-- 		if human.f5 == nil or Timer.now - human.f5 > 30000 then 
		-- 			doDisconnect(human, CommonDefine.DISCONNECT_NORMAL_AFTER)
		-- 		end
		-- 	end
		-- end

		for _, human in pairs(onlineNewUniqueTag) do
			if human.fd == nil then
				if human.f5 == nil or Timer.now - human.f5 > 30000 then 
					doDisconnect(human, CommonDefine.DISCONNECT_NORMAL_AFTER)
				end
			end
		end
		
		for account, humanTempInfo in pairs(MiddleLogic.TRY_LOGIN_HUMAN) do
			if now - humanTempInfo.tsForMiddle > 30 then
				MiddleLogic.TRY_LOGIN_HUMAN[account] = nil
			end
		end
	else
		for uuid, human in pairs(onlineUuid) do
            -- 暂时不检测 不主动结束战斗 方便客户端调试 dxzeng debug
			if CombatLogic.COMBAT_CACHE[uuid] and not Config.IS_DEBUG then -- reyes test
				CombatLogic.checkFinish(human)
			else
				if human.fd == nil then
					if human.f5 == nil or Timer.now - human.f5 > 32000 then
						doDisconnect(human, CommonDefine.DISCONNECT_NORMAL_AFTER)
					end
				end
			
			end
		end
	end
end

function save(human)
	RoleDBLogic.saveRole(human.db)
end

-- 获得在线人数(包含停留在创角页)
function getOnlineCnt()
	local onlineCnt = 0
	-- for _ in pairs(onlineAccount) do
	-- 	onlineCnt = onlineCnt + 1
	-- end
	for _ in pairs(onlineNewUniqueTag) do
		onlineCnt = onlineCnt + 1
	end

	return onlineCnt
end

function onZhandouliUpdate(human)
    -- 更新排行榜
	LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID22,human.db.zhandouli,nil,nil,true)

    YunYingLogic.onCallBack(human, "onZhandouli", human.db.zhandouli)

    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_203)

	OpenServerActPowerUp.ActPowerUp_PowerChange(human, human.db.zhandouli)

	if human.db.unionUuid then
		UnionLogic = UnionLogic or require("union.UnionLogic")
		UnionLogic.UpdateMemberPower(human)

		AnotherWorldBattleNS.PlayerPowerChange(human)
	end

end

local old_attr = {}
function doCalc(human)
	for k in pairs(old_attr) do
		old_attr[k] = nil
	end
	if human.attr then
		for k, v in pairs(human.attr) do
			old_attr[k] = v
		end
	end

	RoleAttr.doCalc(human)
    onZhandouliUpdate(human)

	local mm = Msg.gc.GC_ROLE_ATTR
	local len = 0
	local left = mm.attrs
	for k,v in pairs(human.attr) do
		if v ~= old_attr[k] then
			len = len + 1
			left[len].key = k
			left[len].value = v
		end
	end
	
	if 0 < len then
		left[0] = len
		Msg.send(mm, human.fd)
		--Msg.trace(mm)
	end
end

function sendAttr(human,key)
	if human.db.middleFlag and _G.is_middle ~= true then
		-- 这个时候的属性改变由跨服服计算
		return
	end
	
	if not human.attr[key] then return end
	local msgRet = Msg.gc.GC_ROLE_ATTR
	msgRet.attrs[0] = 1
	local attr = msgRet.attrs[1]
	attr.key = key
	attr.value = human.attr[key]
	Msg.send(msgRet, human.fd)
	--Msg.trace(msgRet)

	if key == RoleDefine.ZHANDOULI then
		TriggerLogic.PublishEvent(TriggerDefine.ZHANDOULI, human.db._id, human.attr[key])

		VoucherInvest = VoucherInvest or require("voucher.VoucherInvest")
		VoucherInvest.PowerUpdate(human)
	end
end

function doCalcHero(human, bagIndex)
	RoleAttr.doCalcHero(human, bagIndex)
	doCalc(human)
end

function getHeroAttrs(human, bagIndex)
	if not human.heroAttrs or not human.heroAttrs[bagIndex] then
		RoleAttr.doCalcHero(human, bagIndex)
	end
	return human.heroAttrs[bagIndex]
end

function checkLevelUp(human)
	local maxLevel = #RoleExcel.exp
	if human.db.lv > maxLevel then
		return 0
	end

	local levelUp = 0
	while human.db.exp > 0 do
        local needExp = 0
        if human.db.lv < maxLevel then
		    needExp = RoleExcel.exp[human.db.lv + 1].exp
		end
        if needExp <= human.db.exp then
		    if human.db.lv >= maxLevel then
			    if human.db.exp > needExp then
			        human.db.exp = needExp
			    end
			    break	
		    else
			    human.db.exp = human.db.exp - needExp
			    human.db.lv = human.db.lv + 1
			    levelUp = 1
                JibanLogic.onCallback(human,4,human.db.lv)
		    end
		else
		    break
		end
	end
	return levelUp
end


function onLvUpCB(human, oldLv, newLv)
	doCalc(human)
		
	--升级判断钻石基金是否返钻
	--FundLogic.onLvUp(human, oldLv, newLv)
	GuideLogic.onLvUpCB(human, oldLv, newLv)
    RoleSystemLogic.onLvUp(human)
	YunYingLogic.onLevelUp(human, oldLv, newLv)
	TuiSongLiBao.tuiSongLiBaoOnTask(human,TuiSongLiBao.TUISONGLIBAOTASK_LV, newLv, oldLv)
	CombatPosLogic.onLvUp(human, oldLv, newLv)
	ChengjiuLogic.onLvUp(human)
	BreakThroughTheme.onLvUp(human)

	-- 更新等级排名数据
    if BRoleLogic.updateData(BillboardDefine.TYPE_LV, human.db) then	
		-- 计算世界等级
		GlobalWorld.doCalcWorldLv()
	end

    -- 开服邮件
    local subDay = CommonDB.getServerOpenDay()
    human.db.sendPfEmail = human.db.sendPfEmail or {}
    for k, config in ipairs(MailExcel.openMail) do
        if subDay and 
            subDay >= config.openDay[1] and 
            subDay <= config.openDay[2] and
            PfLogic.isServerIndex(config.svrIndex) then 
              
            if newLv >= config.lv and 
                human.db.sendPfEmail[k] == nil then  

                human.db.sendPfEmail[k] = 1
            
		     	local title = MailExcel.mail[config.mailID].title
		     	local content = MailExcel.mail[config.mailID].content
		     	local senderName = MailExcel.mail[config.mailID].senderName
                if #config.items > 0 then
		     	    MailManager.add(MailManager.SYSTEM, human.db._id, title, content, config.items, senderName)
                else
                    MailManager.add(MailManager.SYSTEM, human.db._id, title, content, nil, senderName)
                end
            end
        end
    end

	MainDianLogic.MaiDian_Begin(human, MaiDianDefine.MAIDIAN_TYPE_LV, {nValue = newLv})
	TriggerLogic.PublishEvent(TriggerDefine.HUMAN_LV_UP, human.db._id, 1, newLv)
	

	GodsAreaNS = GodsAreaNS or require("godsArea.GodsAreaNS")
	GodsAreaNS.UpdateShowData(human, 2)

	DataCache = DataCache or require("core.DataCache")
	DataCache.Update_PlayerLv(human.db._id, human.db.lv)

	commonOperate.LvChange(human, oldLv, newLv)

	GiftLogic.trigger(human, GiftLogic.GIFT_UPGRADE_LV_EVENT, {currentVal = newLv}, GiftLogic.GIFT_SEC_TYPE1)

	--升级日志
	--Log.write(Log.LOGID_OSS_LEVELUP, human.db._id, human.db.account, human.db.name, oldLv, newLv)
	Log.write(Log.LOGID_OSS_LEVELUP, human.db._id, human.db.newUniqueTag, human.db.name, oldLv, newLv)
end

function addExp(human, addExp)
	if human.db.lv > #RoleExcel.exp then return end
    if not addExp then return end
    addExp = math.floor(addExp)
    if addExp == 0 then return end

    local total = human.db.exp + addExp
    total = math.max(0, total)
    total = math.floor(total)

    if total == human.db.exp then
        return
    end 
  
    local oldLv = human.db.lv
    human.db.exp = total
    local levelUp = checkLevelUp(human)
    if levelUp == 1 then
		onLvUpCB(human, oldLv, human.db.lv)
    else
		human.attr[RoleDefine.EXP] = human.db.exp
		sendAttr(human,RoleDefine.EXP)
	end
end


function canAddJinbi(human, d)
	if human.db.jinbi + d > ItemDefine.BAG_ITEM_MAX_JINBI then
		return Broadcast.sendErr(human, Lang.COMMON_ADD_JINBI_LIMIT) 
	else
		return true
	end
end

function updateJinbi(human, d, logType,item_id, num)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["jinbi"] then
		assert()
	end
	d = math.floor(d)
	if d == 0 then
		return
	end

	local val = human.db.jinbi + d
	if val < 0 then
		assert()
	end
	
	if val > ItemDefine.BAG_ITEM_MAX_JINBI then
		val = ItemDefine.BAG_ITEM_MAX_JINBI
		Broadcast.sendErr(human, Lang.COMMON_ADD_JINBI_LIMIT) 
	end
	
	--金币使用日志
	if item_id == nil then item_id = 0 end
	if num == nil then num = 0 end
	--Log.write(Log.LOGID_OSS_JINBI, human.db._id, human.db.account, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["jinbi"], item_id or 0, num or 0, val)

	Log.write(Log.LOGID_OSS_JINBI, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["jinbi"], item_id or 0, num or 0, val)
	human.db.jinbi = val
	if human.fd then
		human.attr[RoleDefine.JINBI] = human.db.jinbi
		sendAttr(human,RoleDefine.JINBI)
	end
	
	MiddleOption.updateYinliang(human, d, logType)
    if d < 0 then
	    HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE4, -d)
		TriggerLogic.PublishEvent(TriggerDefine.JINBI_DEL, human.db._id, -d)
    end
	return true	
end

function addZuanshi(human, d, logType, item_id, num)
	d = math.floor(d)
	if d < 0 then assert(nil) end
	if d == 0 then return end
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["zuanshi"]  then
		assert()
	end
	local val = human.db.zuanshi + d

	--钻石使用日志
	--Log.write(Log.LOGID_OSS_GOLD, human.db._id, human.db.account, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["zuanshi"] , item_id or 0, num or 0, val)
	Log.write(Log.LOGID_OSS_GOLD, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["zuanshi"] , item_id or 0, num or 0, val)
	human.db.zuanshi = val
	if human.fd then
		human.attr[RoleDefine.ZUANSHI] = human.db.zuanshi
		sendAttr(human, RoleDefine.ZUANSHI)
	end
	
	MiddleOption.updateYuanbao(human, d, logType)
	
	return true
end

function decZuanshi(human, d, logType, item_id, num, noSend)
	d = math.floor(d)
	if d > 0 then assert(nil) end	
	if d == 0 then return end
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["zuanshi"] then
		assert()
	end		

	local val = human.db.zuanshi + d

	if val < 0 then
		assert()
	end
	human.db.zuanshi = val
	--Log.write(Log.LOGID_OSS_GOLD, human.db._id, human.db.account, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["zuanshi"] , item_id or 0, num or 0, val)
	Log.write(Log.LOGID_OSS_GOLD, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["zuanshi"] , item_id or 0, num or 0, val)
	if human.fd then
		human.attr[RoleDefine.ZUANSHI] = human.db.zuanshi
		sendAttr(human, RoleDefine.ZUANSHI)
	end
	
    
    HeroLogLogic.finishTaskCB(human,HeroLogLogic.HERO_LOG_TYPE_6,-d)

	MiddleOption.updateYuanbao(human, d, logType)
	HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE5, -d)
    YunYingLogic.onCallBack(human, "onDecZuanshi",-d)
	TriggerLogic.PublishEvent(TriggerDefine.GUYU_DEL, human.db._id, -d)
	return true
end

-- 钻石不足时候的处理
function checkRMB(human, need)
	local sum = human.db.zuanshi
    if sum < need then
		if _G.is_middle == true then
			Broadcast.sendErr(human, Lang.COMMON_NO_ZUANSHI)
		else
			if not SceneHandler.canCharge(human) then
				Broadcast.sendErr(human, Lang.COMMON_NO_ZUANSHI)
			else
				local msgRet = Msg.gc.GC_BAG_NORMB
				Msg.send(msgRet,human.fd)
			end
		end		
        return false
    else
        return true
    end
end

function updateFriendHeart(human, d, logType,item_id, num)
	if not LogDefine.DEFINE[logType] or not LogDefine.TYPE["friendheart"] then
		assert()
	end
	d = math.floor(d)
	if d == 0 then
		return
	end

	local val = human.db.friendHeart + d
	if val < 0 then
		assert()
	end
	
	--好友爱心使用日志
	if item_id == nil then item_id = 0 end
	if num == nil then num = 0 end
	--Log.write(Log.LOGID_OSS_FRIENDHEART, human.db._id, human.db.account, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["friendheart"], item_id or 0, num or 0, val)
	Log.write(Log.LOGID_OSS_FRIENDHEART, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, d, LogDefine.DEFINE[logType] + LogDefine.TYPE["friendheart"], item_id or 0, num or 0, val)
	
	human.db.friendHeart = val
	if human.fd then
		human.attr[RoleDefine.FRIENDHEART] = human.db.friendHeart
		sendAttr(human,RoleDefine.FRIENDHEART)
	end
	return true	
end

function sendHumanInfo(human,isNew)
    -- 处理称号被销毁的
    if human.db.chenghao then
       if not human.db.chenghaoList[human.db.chenghao] then
          human.db.chenghao = nil
       end
    end 

    local subDay = CommonDB.getServerOpenDay()

	local mm = Msg.gc.GC_ZZ_HUMAN_INFO
    RoleLogic.getRoleBase(human, mm.roleBase)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    mm.unionName = union and union.name or ""
    mm.unionIdentity = union and union.id or ""
    mm.bannerID = union and union.bannerID or 0
    mm.unionFrame  = union and union.headFrame or 0
    mm.identity = human.db.identity
    mm.vipLv = VipLogic.getVipLv(human)
	-- mm.animation = human.db.animation or 0
    mm.animation = RoleHeadLogic.GetCorrectBodyId(human)
    mm.background = human.db.background or 0
	mm.debug = Config.IS_USE_GM_CMD and 1 or 0
    mm.worldLv = GlobalWorld.getWorldLv()
    mm.openDay = subDay or 0
	mm.guideState= GuideLogic.checkAllFinish(human)
	mm.isFrist = isNew and 1 or 0
	for  i = 1,#mm.warOrder do 
		mm.warOrder[0] = i
		WarOrder.getWarOrderInfo(human,i,mm.warOrder[i] )
	end

    local drawCardRateList = {}

	-- if nil ~= DrawCardV2Excel then
	-- 	local drawCardV2Confs = DrawCardV2Excel
	-- 	local num = drawCardV2Confs and (#drawCardV2Confs) or 0
	
	-- 	for i = 0 , num do 
	-- 		local drawCardV2Conf = drawCardV2Confs[i]
	-- 		drawCardRateList[i] = drawCardRateList[i] or {}
	-- 		for  weightIndex = 1 , #drawCardV2Conf.weight do 
	-- 			drawCardRateList[i][weightIndex] = drawCardRateList[i][weightIndex] or {}
	-- 			drawCardRateList[i][weightIndex] = drawCardV2Conf.weight[weightIndex][2]
	-- 		end
	-- 	end
	-- end

    mm.drawCardRateList = Json.Encode(drawCardRateList)
	mm.nSpeed[0] = 3
	mm.nSpeed[1] = 0
	mm.nSpeed[2] = 0
	mm.nSpeed[3] = 0
	if human.db.nSpeed then
		mm.nSpeed[1] = human.db.nSpeed[1] and human.db.nSpeed[1] or 0
		mm.nSpeed[2] = human.db.nSpeed[2] and human.db.nSpeed[2] or 0
		mm.nSpeed[3] = human.db.nSpeed[3] and human.db.nSpeed[3] or 0
	end

	Msg.send(mm, human.fd)
end

function enterCity(human)
	Msg.send(Msg.gc.GC_ENTER_CITY, human.fd)
end


-- 上线回调
function onLogin(human, isNew)
	human.db.ip = human.ip
	human.db.phpChanelID = human.phpChanelID

	if human.db.changeNameCnt ~= nil then
		--Log.write(Log.LOGID_OSS_LOGIN, human.db._id, human.db.account, human.db.name, human.db.lv, human.db.ip)
		Log.write(Log.LOGID_OSS_LOGIN, human.db._id, human.db.newUniqueTag, human.db.name, human.db.lv, human.db.ip)
	end
	
	updateDaily(human)
   	if not FcmLogic.checkFcm(human) then
   		return -- 防沉迷 踢下线
   	end

	TequanLogic.jihuopt(human)
    TequanLogic.setHumanTequan(human,human.pf_info)
    doCalc(human)
	sendHumanInfo(human,isNew)

		
	BagLogic.sendBagList(human)
	FuwenLogic.sendFuwenBagList(human)

	if Config.IS_USE_GM_CMD then
		HeroLogic.TransformHeroEquipAttr(human)
		EquipLogic.TransformEuipAttrData(human)
	end

    EquipLogic.sendEquipBagList(human)
	HeroLogic.sendHeroBagCap(human)
	HeroLogic.sendHeroBagList(human)
    CombatPosLogic.onLogin(human)
	VipLogic.onLogin(human)
	FriendLogic.onLogin(human)
	DailyTaskLogic.onLogin(human)
	--周任务和荣耀历程
	OnlineRewardLogic.onLogin(human)
	SettingLogic.query(human)
	ChatHandler.onLogin(human)
	BattleLogic.onLogin(human)	
	ChatPaoMaLogic.onLogin(human)
	MailLogic.cleanNilContent(human)
	YunYingLogic.onLogin(human)
	RoleStrongLogic.onLogin(human)
    RelationGiftLogic.onLogin(human)
    ChatRecord.sendAllNotRead(human)
	JjcGodWarLogic.onLogin(human)
    HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE1, 1)
	if not isNew then
		ReportManager.login(human)
	end
    LostTempleLogic.onLogin(human)
	HuanJingTowerLogic.onLogin(human)
    SettingLogic.onLogin(human)
	GuideLogic.onLogin(human)
	CombatLogic.onLogin(human) -- reyes test
	LianyuLogic.onLogin(human)
	MoshouLogic.onLogin(human)
    TopupLogic.checkKf(human)
	VoucherShopLogic.onLogin(human)
	RacialTrialLogic.onLogin(human)
	ZhanbuLogic.onLogin(human)
	RoleHeadLogic.onLogin(human)
	-- 最后执行离线发货
	BuyLogic.onLogin(human)
	GiftLogic.onLogin(human)
	MainTask.onLogin(human)
	ClutterDataLogic.onLogin(human)
	HeroPubLogic.onLogin(human)
	QQBigShot.onLogin(human)
	JjcNewLadderLogic.onLogin(human)
	WinnerRelicLogic.onLogin(human)
	commonOperate.onLogin(human)
	AnotherWorldBattleNS.onLogin(human)
	RoleStorageBox.onLogin(human)
	BreakThroughTheme.onLogin(human)
	BattleGift.onLogin(human)

    HeroLogLogic.finishTaskCB(human,HeroLogLogic.HERO_LOG_TYPE_1,1)
	-- 红点 检测   需要放在通用的onLogin 后面  保持数据的正确性 再检测红点
	local pcallRet, pcallErr = pcall(RoleSystemLogic.onLogin, human) 
	if not pcallRet then
		Log.write(Log.LOGID_ERR_PCALL, "RoleSystemLogic.onLogin err=" .. human.db.newUniqueTag, pcallErr)
	end

    enterCity(human)
    
    local day = Util.diffDay(human.db.createTime)
	if day == 2 or day == 7 then
		local msgRet = Msg.gc.GC_NOTICE_DADIAN
		msgRet.type = 2
		msgRet.param = day
		msgRet.param2 = 0
		Msg.send(msgRet,human.fd)
	end

	BigRPlayerShow.onLogin(human)
	
	-- 注意 这个函数写在doLogin的最后
	MiddleLogic.onLogin(human)

	--返利
	-- RebateLogic.NS_RebateQuery(human.phpChanelID, human.serverTag, human.db.account)
end

-- 这里有个潜规则，凡是使用每天都需更新的数据时，都必须先调用这个方法。by cc
function updateDaily(human, isGm)
	if not isGm then
		if human.db.update_daily_time and Util.isSameDay(human.db.update_daily_time) then
			return true
		end
	end

	-- 跨月
	if human.db.update_daily_time and Util.isSameMonth(human.db.update_daily_time) ~= true then
		human.db.topupAccountMonth = nil
	end
	
	YunYingLogic.updateDaily(human)
    BattleLogic.updateDaily(human)
	BarTaskLogic.refreshDailyTask(human)
    FriendLogic.refreshDailyTask(human)
	TequanLogic.cleanDaily(human)
	CopyLogic.updateDaily(human)
	HuanJingTowerLogic.updateDaily(human)
	VipLogic.updateDaily(human)
    WelfareGiftLogic.updateDaily(human)
    WarReportLogic.updateDaily(human)
    ZhanbuLogic.updateDaily(human)
    ZhuanpanLogic.updateDaily(human)
    LostTempleLogic.updateDaily(human)

	-- 美团2楼标记：每天重置一次
	human.db.mtFrom2floor = 0
	human.db.mtFrom2floorDay = nil

	human.db.update_daily_time = os.time()
	human.db.dailyTask = nil
	human.db.dailyShareTask = nil
	human.db.jjcDailyFight = nil
	human.db.jjcWorship = nil
    human.db.personMail = nil
    human.db.topupAcountDaily = nil
	human.db.dailyLeiChong = nil
	human.db.onlineTimeDay = nil
	human.db.onlineTimeDayReport = os.time()
	human.db.heroResetCnt = nil
	human.db.dailyLibao = nil
	human.db.ectypeLike = nil
	human.db.ectypHurt = nil
	human.db.ectypeCnt = nil
	human.db.ectypLikeUuid = nil
	human.db.adRewardCnt = nil
	human.db.adHatchRewardCnt = nil
	human.db.isTip = nil
	
	ShopLogic.updateDaily(human)
	LianyuLogic.updateDaily(human)
	DrillLogic.updateDaily(human)
    UnionLivenessLogic.updateDaily(human)
    UnionDonateLogic.updateDaily(human)
    FirstChargeLogic.updateDaily(human)
    JjcLadderLogic.updateDaily(human)
    BaiZhanChengShenNS.updateDaily(human)
    UnionRedBagLogic.updateDaily(human)
	JjcGodWarLogic.updateDaily(human)
	RacialTrialLogic.updateDaily(human)
	OnlineAwardLogic.NewUpdateDaily(human)
	ClutterDataLogic.updateDaily(human)
	BreakThroughTheme.updateDaily(human)
	BattleGift.updateDaily(human)


	QQBigShot.updateDaily(human)

	TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_DAILY_LOGIN, human.db._id, 1)
	
	-- 红点 发送  理论放最后
	RoleSystemLogic.onLogin(human)
end

--- GM角色立即存库
function GM_SaveDB(human)
	if not human then
		return
	end
	local now = Timer.now
	human.saveDBTime = now
	local ret, err = pcall(save, human)
end


-- 角色心跳
function refresh()	
	for _, human in pairs(onlineHuman) do
        --活动开启邮件提示
        RoleSystemLogic.checkMailTips(human)
	end
end