RolePlugin.lua 8.6 KB


local RolePlugin = {}

function RolePlugin.bind(Role)

	function Role:log()

	end

	function Role:loadAll()
		self:loadDaily()
		self:loadHeros()
	end

	function Role:reloadWhenLogin()
	end

	function Role:onCrossDay(now, notify)
		local roleId = self:getProperty("id")
		local ltime = self:getProperty("ltime")

		if isCrossDay(ltime, now) then
			local response = {}

			self.dailyData:refreshDailyData(notify)

			if notify then
				self:notifyUpdateProperties(response)
			end
			return true
		end
	end
	function Role:onOfflineEvent()
		
	end

	local function checkItemCount(self, itemId, count)
		local itemData = csvdb["itemCsv"][itemId]
		-- 种类 类型数量限制
		local page = globalCsv.store_type[itemData.type]
		local limit = self:getProperty("bagLimit")[page]
		if limit and self:getItemCount(itemId) == 0 then
			local curCount = 0
			local items = self:getProperty("items"):toNumMap()
			for _itemId, _count in pairs(items) do
				local _itemData = csvdb["itemCsv"][itemId]
				if globalCsv.store_type[_itemData.type] == page then
					curCount = curCount + 1
					if curCount >= limit then 
						count = 0
						break
					end
				end
			end
		end
		-- 其他
		
		return count
	end

	local function _award(self, itemId, count, params)
		local itemData = csvdb["itemCsv"][itemId]
		local curType = itemData.type
		local change = {} -- 奖励被转化为了其他奖励 id = count

		local itemIdAward = {
			[ItemId.PlayerExp] = function()
				self:addPlayExp(count)
			end,
		}

		local itemTypeAward = {
			[ItemType.Hero] = function()
				params.type = itemId - ItemStartId.Hero
				for i = 1, count do
					self:addHero(params)
				end
			end,
		}
		-- 对数量筛查
		local count = checkItemCount(self, itemId, count)
		if count ~= 0 then
			if itemIdAward[itemId] then
				itemIdAward[itemId]()
			elseif itemTypeAward[curType] then
				itemTypeAward[curType]()
			else
				params.itemId = itemId
				params.count = count
				self:addItem(params)
			end
		end

		return count, change --  count 刷新实际发放的奖励个数 change 物品实际奖励与当前id 不符 就发生转换 而不实际发奖
	end


	-- 发奖功能入口  award string id=count or {[id] = count}
	function Role:award(gift, params)
		local tgift = {}
		if type(gift) == "string" then
			for _, one in pairs(gift:toTableArray(true)) do
				tgift[one[1]] = (tgift[one[1]] or 0) + one[2]
			end
		else
			tgift = gift
		end
		local reward, allChange = {}, {}

		for itemId, count in pairs(tgift) do
			local count, change = _award(self, itemId, count, clone(params or {}))
			if next(change) then
				local cr, cc = self:award(change, params) -- 内部转换忽略
				for _id, _ct in pairs(cr) do
					reward[_id] = (reward[_id] or 0) + _ct
				end
				table.insert(allChange, {form = {[itemId] = count}, to = cr})
			else
				if count > 0 then
					reward[itemId] = (reward[itemId] or 0) + count
				end
			end
		end

		return reward, allChange --实际获得的奖励 和 最高级奖励转化过程
	end

	function Role:addPlayExp(addExp)
		local level = self:getProperty("level")
		if not csvdb["player_expCsv"][level + 1] then
			return
		end
		
		local exp = self:getProperty("exp")
		local newExp = exp + addExp
		while newExp >= csvdb["player_expCsv"][level].exp do
			if csvdb["player_expCsv"][level + 1] then -- 有下一级
				newExp = newExp - csvdb["player_expCsv"][level].exp
				level = level + 1
			else
				newExp = csvdb["player_expCsv"][level].exp - 1 -- 没有下一级了 经验溢出太多 扣除
			end
		end
		self:updateProperties({level = level, exp = newExp})
	end

	function Role:addItem(params)
		params = params or {}
		if params.itemId ==  ItemId.Diamond then
			self:gainDiamond(params)
			return
		end
		local items = self:getProperty("items")
		local origin = items:getv(params.itemId, 0)
		local nums = origin+params.count
		if nums <= 0 then
			items = items:delk(params.itemId)
			nums = 0
		else
			items = items:incrv(params.itemId, params.count)
		end
		self:setProperty("items", items)
		if not params.notNotify then
			SendPacket(actionCodes.Role_updateItems, MsgPack.pack({[params.itemId] = nums}))
		end
	end

	function Role:checkItemEnough(itemCountT)
		local less = {}
		for itemId, count in pairs(itemCountT) do
			local last = self:getItemCount(itemId) - count
			if last < 0 then
				less[itemId] = -last
			end
		end
		return (not next(less)), less -- 是否足够,,缺什么缺多少
	end

	function Role:costItems(itemCountT, params)
		if itemCountT[ItemId.Diamond] then  --优先扣除钻石
			local pms = clone(params or {})
			pms.count = itemCountT[ItemId.Diamond]
			if not self:costDiamond(pms) then
				return
			end
			itemCountT[ItemId.Diamond] = nil
		end
		for itemId, count in pairs(itemCountT) do
			local pms = clone(params or {})
			pms.itemId = itemId
			pms.count = - count
			self:addItem(pms)
		end
		return true
	end

	function Role:getItemCount(itemId)
		if itemId == ItemId.Diamond then 
			return self:getAllDiamond()
		end
		return self:getProperty("items"):getv(itemId, 0)
	end

	function Role:getAllDiamond()
		return self:getProperty("diamond") + self:getProperty("reDiamond")
	end

	function Role:gainDiamond(params)
		if not params or type(params) ~= "table" then return false end
		local count = tonum(params.count)
		if isnan(count) then
			return false
		end
		local origind = self:getProperty("diamond")
		local originr = self:getProperty("reDiamond")
		local origin = origind + originr
		if params.isRecharge then
			self:incrProperty("reDiamond", count)
		else
			self:incrProperty("diamond", count)
		end
		self:notifyUpdateProperty("diamond", self:getAllDiamond())
		return true
	end

	function Role:costDiamond(params)
		if not params or type(params) ~= "table" then return false end
		local count = tonum(params.count)
		if isnan(count) then
			return false
		end
		if count <= 0 then
			return false
		end
		local origind = self:getProperty("diamond")
		local originr = self:getProperty("reDiamond")
		local origin = origind + originr

		if origin < 0 then
			return false
		end
		if origin < count then
			return false
		end
		local last = count
		local costFirst = {"diamond", "reDiamond"}
		if params.isRecharge then
			costFirst = {"reDiamond", "diamond"}
		end
		last  = math.max(last - self:getProperty(costFirst[1]), 0)
		if last < count then
			self:incrProperty(costFirst[1], last - count)
		end
		if last > 0 then
			self:incrProperty(costFirst[2], -last)
		end

		self:notifyUpdateProperty("diamond", self:getAllDiamond())
		return true
	end

	function Role:addHero(params)
		local roleId = self:getProperty("id")
		local heroId = tonum(redisproxy:hincrby(string.format(R_INCR, roleId), "hero", 1))

		local heroType = params.type
		local unitData = csvdb["unitCsv"][heroType]

		redisproxy:sadd(string.format(R_HEROS, roleId), heroId)

		local heroInfo = {
			key = string.format(R_HERO, roleId, heroId),
			id 	= heroId,
			type= heroType,
		}
		
		local newHero = require("models.Hero").new(heroInfo)
		newHero:create()
		newHero.owner = self
		newHero:saveBattleValue()
		self.heros[heroId] = newHero

		if not params.notNotify then
			local heroResponse = {}
			table.insert(heroResponse, newHero:data())
			local bin = MsgPack.pack(heroResponse)
			SendPacket(actionCodes.Hero_loadInfos, bin)
		end
	end

	function Role:delHero(params)
		local roleId = self:getProperty('id')
		local hero = self.heros[heroId]
		if not hero then return end

		self.heros[heroId] = nil
		redisproxy:pipelining(function (red)
			red:del(string.format(R_HERO, roleId, heroId))
			red:srem(string.format(R_HEROS, roleId), heroId)
		end)
		SendPacket(actionCodes.Hero_loadInfos, MsgPack.pack({{id = heroId, bDel = true}}))
	end

	function Role:loadHeros()
		local roleId = self:getProperty("id")
		local heroIds = redisproxy:smembers(string.format(R_HEROS, roleId))
		local redret = redisproxy:pipelining(function (red)
			for _, heroId in ipairs(heroIds) do
				red:hgetall(string.format(R_HERO, roleId, heroId))
			end
		end)
		for index, heroId in ipairs(heroIds) do
			local hero = require("models.Hero").new({key = string.format(R_HERO, roleId, heroId)})
			if hero:load(table.array2Table(redret[index])) then
				hero.owner = self
				self.heros[tonumber(heroId)] = hero
			end
		end
	end

	function Role:loadDaily()
		local roleId = self:getProperty("id")
		local dataKey = string.format(R_DAILY, roleId)
		self.dailyData = require("models.Daily").new({key = dataKey})
		self.dailyData.owner = self
		if not redisproxy:exists(dataKey) then
			self.dailyData:create()
		else
			self.dailyData:load()
		end
	end

	function Role:getAdvData()
		if not self.advData then 
			self.advData = require("adv.Adv").new(self)
			self.advData:initByInfo()
		end
		return self.advData
	end
end

return RolePlugin