RoleAdv.lua 7.8 KB

local RoleAdv = {}

function RoleAdv.bind(Role)


	local function getIdByCr(c, r)
		local crId = math.abs(r) + math.abs(c) * 100
		if c < 0 then
			crId = crId + 10000
		end
		if r < 0 then
			crId = crId + 20000
		end
		return crId
	end
	local function getCrById(crId)
		local c = math.floor(crId % 10000 / 100)
		local r = crId % 100
		local last = math.floor(crId / 10000)
		if last == 3 then
			c, r = -c, -r
		elseif last == 1 then
			c = -c
		elseif last == 2 then
			r = -r
		end
		return c, r
	end

	--检查 是否满足层数限制条件
	local function checkIsIn(checkValue, checkType, checkRange)
		if not checkValue then return end
		if checkType == 1 then
			local limits = checkRange:toNumMap()
			for min, max in pairs(limits) do
				if checkValue >= min and checkValue <= max then
					return true
				end
			end
		else
			local limit = checkRange:toArray(true, "=")
			for _, _l in ipairs(limit) do
				if _l == checkValue then
					return true
				end
			end
		end
	end

	--关卡事件库
	local function getEventLib(chapterId, level)
		local chapter = math.floor(chapterId / 100) % 100

		local libsToType = {
			["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS},
			["event_chooseCsv"] = AdvEventType.Choose,
			["event_dropCsv"] = AdvEventType.Drop,
			["event_buildingCsv"] = AdvEventType.Build,
			["event_traderCsv"] = AdvEventType.Trader,

		}
		local eventLib = {}
		for lib, eventType in pairs(libsToType) do
			if type(eventType) == "table" then
				for _, temp in ipairs(eventType) do
					eventLib[temp] = {}
				end
			else
				eventLib[eventType] = {}
			end
			for id, data in pairs(csvdb[lib]) do
				if data.levelchapter == chapter then
					if checkIsIn(level, data.leveltype, data.levellimit) then
						if type(eventType) == "table" then
							eventLib[eventType[data.type]][id] = data
						else
							eventLib[eventType][id] = data
						end
					end
				end
			end
		end
		return eventLib
	end

	-- 生成地图   是否可以生成地图上层判断
	function Role:randomAdvMap(chapterId, level)
		local chapterData = csvdb["adv_chapterCsv"][chapterId]
		if not chapterData then return end
		if level > chapterData.limitlevel then return end
		--随出地图
		local raw_pool = chapterData.mapid:toArray(true, "=")
		local advInfo = self:getProperty("advInfo")
		local lastMapId = advInfo.mapId  --非同一层不连续随出同一张类似的地图
		local lastChapterId = advInfo.chapter
		local pool = {}
		for _, mapId in ipairs(raw_pool) do
			local temp = csvdb["mapCsv"][mapId]
			if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图
				if checkIsIn(level, temp.leveltype, temp.levellimit) then
					table.insert(pool, mapId)
				end
			end
		end
		if not next(pool) then return end
		local mapId = pool[math.randomInt(1, #pool)]
		--随出事件
		local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"]
		if not mapData then return end

		table.clear(advInfo)
		advInfo.chapter = chapterId
		advInfo.level = level
		advInfo.mapId = mapId
		advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}, isPath = nil},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁  isPath 是否是路径

		--事件随机
		local eventLib = getEventLib(chapterId, level)
		local monsterEvents = {}  --处理钥匙掉落
		local haveBoss = false
		local function randomEvent(roomId, blockId, eventType)
			if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖
			local event = {etype = eventType}
			local randomFunc = {
				[AdvEventType.In] = function()
					advInfo.rooms[roomId]["open"][blockId] = 1
				end,
				[AdvEventType.Out] = function()
				end,
				[AdvEventType.BOSS] = function()
					if not next(eventLib[eventType]) or haveBoss then return false end
					haveBoss = true
					event.id = math.randWeight(eventLib[eventType], "showup")
				end,
				[AdvEventType.Choose] = function()
					if not next(eventLib[eventType]) then return false end
					event.id = math.randWeight(eventLib[eventType], "showup")
				end,
				[AdvEventType.Drop] = function()
					if not next(eventLib[eventType]) then return false end
					event.item = eventLib[eventType][math.randWeight(eventLib[eventType], "showup")]["range"]:randWeight(true)
				end,
				[AdvEventType.Monster] = function()
					if not next(eventLib[eventType]) then return false end
					event.id = math.randWeight(eventLib[eventType], "showup")
					table.insert(monsterEvents, event)
				end,
				[AdvEventType.Trader] = function()
					if not next(eventLib[eventType]) then return false end
					event.id = math.randWeight(eventLib[eventType], "showup")
				end,
				[AdvEventType.Build] = function()
					if not next(eventLib[eventType]) then return false end
					event.id = math.randWeight(eventLib[eventType], "showup")
				end,
			}

			if randomFunc[eventType] then
				if randomFunc[eventType]() ~= false then
					advInfo.rooms[roomId]["event"][blockId] = event
				end
			end
		end

		stagePool = {["global"] = {}}
		for roomId, roomName in pairs(mapData["rooms"]) do
			stagePool[roomId] = {}
			advInfo.rooms[roomId] = {event = {}, open = {}}  -- 事件, open
			local roomData
			if roomName == "path" then
				advInfo.rooms[roomId].isPath = true
				roomData = mapData["path"]
			else
				roomName = roomName:gsub("/", "_")
				roomData = csvdb["room_" .. roomName .. "Csv"]
			end
			for blockId, stageType in pairs(roomData["blocks"]) do
				if AdvSpecialStage[stageType] then
					eventType = AdvEventType[AdvSpecialStage[stageType]]
					randomEvent(roomId, blockId, eventType)
				else
					stagePool["global"][stageType] = stagePool["global"][stageType] or {}
					stagePool[roomId][stageType] = stagePool[roomId][stageType] or {}
					table.insert(stagePool["global"][stageType], {room = roomId, block = blockId})
					stagePool[roomId][stageType][blockId] = 1
				end
			end
		end
		-- 全地图事件 优先级高
		for stageType, events in pairs(mapData["events"]) do
			for _, event in ipairs(events) do
				local lastCount = #stagePool["global"][stageType]
				if lastCount <= 0 then break end
				if math.randomFloat(0, 1) <= (event["rate"] or 1) then
					local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"]))
					for i = 1, count do
						local idx = math.randomInt(1, lastCount)
						local cur = stagePool["global"][stageType][idx]
						randomEvent(cur["room"], cur["block"], event["event"])
						table.remove(stagePool["global"][stageType], idx)
						lastCount = lastCount - 1
						stagePool[cur["room"]][stageType][cur["block"]] = nil
					end
				end
			end
		end
		-- 随机单个房间的事件	
		for roomId, roomName in pairs(mapData["rooms"]) do
			local roomData
			if roomName == "path" then
				roomData = mapData["path"]
			else
				roomName = roomName:gsub("/", "_")
				roomData = csvdb["room_" .. roomName .. "Csv"]
			end
			for stageType, events in pairs(roomData["events"]) do
				local bpool = {}
				if stagePool[roomId][stageType] then
					for block, _ in pairs(stagePool[roomId][stageType]) do
						table.insert(bpool, block)
					end
				end
				for _, event in ipairs(events) do
					if #bpool <= 0 then break end
					if math.randomFloat(0, 1) <= (event["rate"] or 1) then
						local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"]))
						for i = 1, count do
							local idx = math.randomInt(1, #bpool)
							randomEvent(roomId, bpool[idx], event["event"])
							table.remove(bpool, idx)
						end
					end
				end
			end
		end
		if not haveBoss then
			if not next(monsterEvents) then
				print("这个地图没有钥匙!!! mapId : " .. mapId)
			else
				local event = monsterEvents[math.randomInt(1, #monsterEvents)]
				event.item = {1, 1}  --掉落钥匙
			end
		end
		self:updateProperty({field = "advInfo", value = advInfo})
	end

end

return RoleAdv