HeroAction.lua 9.83 KB
local ipairs = ipairs
local table = table
local math = math
local next = next
local string = string
local redisproxy = redisproxy
local MsgPack = MsgPack
local getRandomName = getRandomName
local mcast_util = mcast_util
local string_format = string.format
local tonumber = tonumber
local require = require
local table_insert = table.insert
local tconcat = table.concat
local table_unpack = table.unpack

local _M = {}
function _M.levelUpRpc( agent, data )
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local hero = role.heros[msg.id]
	if not hero then return end

	if hero:getProperty("level") >= hero:getMaxLevel() then return end
	local curData = csvdb["unit_expCsv"][hero:getProperty("level")]
	local cost = {[ItemId.Exp] = curData.exp, [ItemId.Gold] = curData.gold}
	if not role:checkItemEnough(cost) then return end
	role:costItems(cost, {})
	hero:updateProperty({field = "level", delta = 1})
	
	SendPacket(actionCodes.Hero_levelUpRpc, '')
	return true
end

function _M.breakRpc( agent, data )
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local hero = role.heros[msg.id]
	if not hero then return end

	if hero:getProperty("level") < hero:getMaxLevel() then return end
	if hero:getProperty("breakL") >= #csvdb["unit_breakCsv"] then return end
	local curData = csvdb["unit_breakCsv"][hero:getProperty("breakL")]
	local cost = {[ItemId.BreakCost] = curData.cost, [ItemId.Gold] = curData.gold}
	if not role:checkItemEnough(cost) then return end
	role:costItems(cost, {})
	hero:updateProperty({field = "breakL", delta = 1})
	
	SendPacket(actionCodes.Hero_breakRpc, '')
	return true
end

function _M.wakeRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local hero = role.heros[msg.id]
	if not hero then return end
	if hero:getProperty("wakeL") >= #csvdb["unit_wakeCsv"] then return end
	local cost = {[hero:getProperty("type")] = csvdb["unit_wakeCsv"][hero:getProperty("wakeL")].cost}
	local isEnough, less = role:checkItemEnough(cost)
	if not isEnough then
		cost[ItemId.HeroFC[csvdb["unitCsv"][hero:getProperty("type")].rare]] = less[hero:getProperty("type")]
		if not role:checkItemEnough(cost) then return end
	end
	role:costItems(cost, {})
	hero:updateProperty({field = "wakeL", delta = 1})

	SendPacket(actionCodes.Hero_wakeRpc, '')
	return true
end

function _M.skillUpRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local index = msg.skillIdx -- 第几个技能 -- 1  2  3  
	local hero = role.heros[msg.id]
	if not hero then return end
	local curLevel = hero:getSkillLevel(index)
	if hero:getLSPoint() <= 0 or curLevel >= #hero:getSkillData(index) then return end
	hero:updateProperty({field = "skillL", value = hero:getProperty("skillL"):setv(index, curLevel + 1)})

	SendPacket(actionCodes.Hero_skillUpRpc, '')
	return true
end

function _M.talentRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local hero = role.heros[msg.id]
	if not hero then return end

	local index = msg.index -- 第几个天赋
	local need = {[1] = 1, [2] = 1, [3] = 1, [4] = 1}
	if not need[index] then return end

	local talent = hero:getProperty("talent")
	local curStage = talent:getv(0, 1)
	if curStage > csvdb["unit_breakCsv"][hero:getProperty("breakL")].talent then return end
	
	local curData = csvdb["unit_talentCsv"][curStage] 
	if not curData then return end

	local level = talent:getv(index, 0)
	if level >= #curData then return end

	local talentData = curData[level]
	if not talentData then return end
	local cost = talentData.cost:toNumMap()
	if not role:checkItemEnough(cost) then return end
	role:costItems(cost, {})
	talent = talent:incrv(index, 1)

	--是否进阶
	local max = true
	for i = 1, 4 do
		if talent:getv(i, 0) < #curData then
			max = false
			break
		end
	end
	if max then
		talent = talent:setv(0, curStage + 1)
		for i = 1, 4 do
			talent = talent:setv(i, 0)
		end
	end
	hero:updateProperty({field = "talent", value = talent})
	SendPacket(actionCodes.Hero_talentRpc, '')
	return true
end

-- 暂时没有这个功能
function _M.likeHeroRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local heroType = msg.type
	local result = {status = 0}
	local isLike = false
	local hadLike = role:getProperty("likeHero"):toArray(true, "=")
	for _, v in pairs(hadLike) do
		if v == heroType then
			isLike = true
			break
		end
	end
	if isLike then
		result.status = 1
	else
		redisproxy:hincrby("hero:like", "hero:"..heroType, 1)
		table.insert(hadLike, heroType)
		role:setProperty("likeHero", table.concat(hadLike, "="))
	end

	SendPacket(actionCodes.Hero_likeHeroRpc, MsgPack.pack(result))
	return true
end
local RankLikeNum = 5 --热度显示几个
local TimeLikeNum = 95 -- 时间显示几个
local function getCommentKey(heroType)
	return {
		commentListKey = string.format("list:%d:herocomments", heroType),
		commentRankKey = string.format("rank:%d:herocomments", heroType),
		commentKey = string.format("hero:%d:comments", heroType),
	}
end

local function trimComment(heroType, commentId) -- 剪裁 CommentList
	local commentKey = getCommentKey(heroType)
	local redret = redisproxy:pipelining(function (red)
		red:lpush(commentKey.commentListKey, commentId)
		red:lrange(commentKey.commentListKey, TimeLikeNum,-1)
		red:ltrim(commentKey.commentListKey, 0, TimeLikeNum - 1)
		red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1)
	end)
	local hots = {}
	for _, hot in pairs(redret[4]) do
		hots[hot] = 1
	end
	redisproxy:pipelining(function (red)
		local needDel = {}
		for _, tempId in pairs(redret[2]) do
			if not hots[tempId] then
				table.insert(needDel, tempId)
			end
		end
		if #needDel > 0 then
			red:zrem(commentKey.commentRankKey, table_unpack(needDel))
			red:hdel(commentKey.commentKey, table_unpack(needDel))
		end
	end)
end


function _M.commentHeroRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local heroType = msg.type
	local content = msg.content

	local result = {status = 0}  -- status 0 成功  1 已经评论过了
	local curStutus = role.dailyData:getProperty("commentHero")
	if curStutus:getv(heroType, 0) ~= 0 then
		result.status = 1
	else
		local commentKey = getCommentKey(heroType)
		local SERV = string.format("NAMED%d", math.random(1, 5))
		local legal, mod = skynet.call(SERV, "lua", "check", content)
		if not legal then
			content = mod or ""
		end
		local commentId = tostring(redisproxy:hincrby("hero:comment:autoincr", "hero:" .. heroType, 1))
		local comment = {
			commentId = commentId, 
			content = content,
			roleId = role:getProperty("id"),
			name = role:getProperty("name"),
			-- time = skynet.timex()
		}
		redisproxy:hset(commentKey.commentKey, commentId, json.encode(comment))
		trimComment(heroType, commentId)

		comment.like = 0
		result.comment = comment
		role.dailyData:setProperty("commentHero", curStutus:setv(heroType, 1))
	end
	SendPacket(actionCodes.Hero_commentHeroRpc, MsgPack.pack(result))
	return true
end

function _M.getCommentsRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local heroType = msg.type
	local list = {}  -- 评论列表
	local commentKey = getCommentKey(heroType)
	local commentRoleKey = string.format("comment:%d:like", role:getProperty("id"))
	local redret = redisproxy:pipelining(function (red)
		red:lrange(commentKey.commentListKey, 0,TimeLikeNum - 1)
		red:zrevrange(commentKey.commentRankKey, 0, -1, "WITHSCORES") --热门
		red:hget("hero:like", "hero:"..heroType)
		red:lrange(commentRoleKey, 0, 999)
	end)

	local likeMap = {}
	local idList = {}
	local liked = {}
	for i = 1, #redret[2], 2 do
		likeMap[redret[2][i]] = redret[2][i + 1]
		if i < RankLikeNum * 2 then
			table.insert(idList, redret[2][i])
		end
	end
	for i = 1, #redret[1] do
		table.insert(idList, redret[1][i])
	end
	for i = 1, #redret[4] do
		liked[redret[4][i]] = 1
	end

	local commentData = redisproxy:pipelining(function (red)
		for _, commentId in ipairs(idList) do
			red:hget(commentKey.commentKey, commentId)
		end
	end)
	for _, commentS in ipairs(commentData or {}) do
		local comment = json.decode(commentS)
		comment.like = likeMap[tostring(comment.commentId)] or 0
		comment.liked = liked[heroType .. ":" .. comment.commentId] or 0
		table.insert(list, comment)
	end
	SendPacket(actionCodes.Hero_getCommentsRpc, MsgPack.pack({list = list, like = tonumber(redret[3] or 0)}))
	return true
end

function _M.likeCommentRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local actType = msg.actType  -- 1 顶 2 踩
	local heroType = msg.type
	local commentId = msg.commentId  --评论id
	local commentKey = getCommentKey(heroType)
	local add = 0
	if actType == 1 then
		add = 1
	elseif actType == 2 then
		add = -1
	else
		return 
	end

	local result = {status = 0} 
	local commentIndex = heroType .. ":" .. commentId 
	local commentRoleKey = string.format("comment:%d:like", role:getProperty("id"))
	local redret = redisproxy:pipelining(function (red)
		red:hexists(commentKey.commentKey, commentId) 
		red:lrem(commentRoleKey, 1, commentIndex)
		red:lpush(commentRoleKey, commentIndex)
		red:ltrim(commentRoleKey, 0, 999)
	end)
	if (tonumber(redret[2]) or 0) > 0 then
		result.status = 1
	else
		if redret[1] == 1 then-- 查不到也返回ture
			local redret2 = redisproxy:pipelining(function (red)
				red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门
				red:zincrby(commentKey.commentRankKey, add, commentId)
				red:zrevrange(commentKey.commentRankKey, 0, RankLikeNum - 1) --热门
			end)
			local out = {}
			for _, v in pairs(redret2[1]) do
				out[v] = 1
			end
			local new = {}
			for _, v in pairs(redret2[3]) do
				if out[v] then
					out[v] = nil
				else
					new[v] = 1
				end
			end
			for tempId, _ in pairs(out) do
				trimComment(heroType, tempId)
			end
			redisproxy:pipelining(function (red)
				for tempId, _ in pairs(new) do
					red:lrem(commentKey.commentListKey, 0, tempId)
				end
			end)
		end
	end

	SendPacket(actionCodes.Hero_likeCommentRpc, MsgPack.pack(result))
	return true
end

return _M