Module:Mazunki/Dungeons

From Melvor Idle
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Documentation for this module may be created at Module:Mazunki/Dungeons/doc

local pm = require("Module:CombatAreas/AreaTables")
local p = {}

local AreaData = mw.loadData('Module:CombatAreas/data')
local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Monsters = require('Module:Monsters')
local CombatAreas = require('Module:CombatAreas')
local Pets = require('Module:Pets')

function p.getDungeonTable(frame)
	local result = '{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|-class="headerRow-0"'
	result = result..'\r\n!Icon!!Dungeon!!Monsters!!Boss Level!!Total HP!!Min DR (melee)!!Min DR (ranged)!!Min DR (magic)!!Reward(s)!!Boss Pet'

	for i, dungIdx in ipairs(AreaData.displayOrder.dungeons) do
		local dung = CombatAreas.getAreaByID('dungeon', dungIdx)
		result = result..'\r\n|-'
		result = result..'\r\n|data-sort-value="'..dung.name..'"|'..Icons.Icon({dung.name, type='dungeon', size='50', notext=true})
		result = result..'||'..Icons.Icon({dung.name, type='dungeon', noicon=true})
		result = result..'||'..Shared.tableCount(dung.monsters)

		local boss = Monsters.getMonsterByID(dung.monsters[Shared.tableCount(dung.monsters)])
		result = result..'||'..Monsters._getMonsterCombatLevel(boss)
		result = result..'||'..p._getDungeonTotalHP(dung, true) -- accountForEnemyDR = true
		
		local minDR = p._getDungeonMinDR(dung, 1000, 0.4)
		result = result..'||'..minDR["Melee"].."%"
		result = result..'||'..minDR["Ranged"].."%"
		result = result..'||'..minDR["Magic"].."%"

		result = result..'||'..pm._getDungeonRewards(dung, false)
		if dung.petID ~= nil then
			local pet = Pets.getPetByID(dung.petID)
			result = result..'||data-sort-value="'..pet.name..'"|'..Icons.Icon({pet.name, type='pet'})
		else
			result = result..'|| '
		end
	end

	result = result..'\r\n|}'
	return result
end

function p._getMaxHitPerMonsterStyle(dung)
	local maxHitsPerMonsterStyle = { Melee = 0, Ranged = 0, Magic = 0 }
	for i, monsterID in Shared.skpairs(dung.monsters) do
		local monster = Monsters.getMonsterByID(monsterID)
		if monster == nil and monsterID == -1 then
			for _, id in Shared.skpairs(AreaData.itm.monsters) do
				local monster = Monsters.getMonsterByID(id)
				local styleName = Constants.getCombatStyleName(monster.attackType)
				local maxHit = Monsters._getMonsterMaxHit(monster, true) -- doStuns = true
		
				if styleName == "Random" then
					for randomStyle, value in Shared.skpairs(maxHitsPerMonsterStyle) do
						if maxHit > value then
							maxHitsPerMonsterStyle[randomStyle] = maxHit
						end
					end
				else
					if maxHit > maxHitsPerMonsterStyle[styleName] then
						maxHitsPerMonsterStyle[styleName] = maxHit
					end
				end
			end
		else
			local styleName = Constants.getCombatStyleName(monster.attackType)
			local maxHit = Monsters._getMonsterMaxHit(monster, true) -- doStuns = true
			if styleName == "Random" then
				for randomStyle, value in Shared.skpairs(maxHitsPerMonsterStyle) do
					if maxHit > value then
						maxHitsPerMonsterStyle[randomStyle] = maxHit
					end
				end
			else
				if maxHit > maxHitsPerMonsterStyle[styleName] then
					maxHitsPerMonsterStyle[styleName] = maxHit
				end
			end
		end
	end
	return maxHitsPerMonsterStyle
end

function p._getDRRequiredPerPlayerStyle(dung, playerStyle, autoEatTreshold, enemyMaxHitsPerStyle, mode)
	local _mode = mode or "Hardcore" -- default to hardcore if mode is nil
	maxStyleDR = 0
	for enemyStyle, styleHit in Shared.skpairs(enemyMaxHitsPerStyle) do
		if styleHit > 0 and styleHit > autoEatTreshold then
			local styleDR = math.ceil((1 - (autoEatTreshold / styleHit)) * 100)
			styleDR = math.ceil(styleDR / Constants.getTriangleDRModifier(playerStyle, enemyStyle, _mode))
			maxStyleDR = math.max(maxStyleDR, styleDR)
		end
	end
	return maxStyleDR
end

function p._getDungeonMinDR(dung, maxHP, autoEatTresholdPercentage)
	--This is the highest DR to list as possible. Value might be slightly off right now, currently just setting up value for testing
	local MaxViableDR = 81
	--This is the highest DR row shown. This should be higher than MaxViableDR
	local MaxVisibleDR = 85
	
	local autoEatTreshold = math.floor(maxHP * autoEatTresholdPercentage)
	local enemyMaxHitsPerStyle = p._getMaxHitPerMonsterStyle(dung)
	-- mw.logObject(enemyMaxHitsPerStyle)
	-- mw.log("ae: "..autoEatTreshold)
	
	local reductionRequiredPerPlayerStyle = { Melee = 0, Ranged = 0, Magic = 0 }
	
	for playerStyle, dr in pairs(reductionRequiredPerPlayerStyle) do
		reductionRequiredPerPlayerStyle[playerStyle] = p._getDRRequiredPerPlayerStyle(dung, playerStyle, autoEatTreshold, enemyMaxHitsPerStyle)
	end
	
	return reductionRequiredPerPlayerStyle
end

function p._testing()
	local dung = CombatAreas.getArea("Into the Mist")
	local maxHp = 1120
	local ae = 0.4
	
	--return p._getDungeonTotalHP(dung, true)
	return p._getDungeonMinDR(dung, maxHp, ae)
end

function p._getDungeonDrTable(dung, gamemode, maxHP)
	local AutoEatVals = { T1 = 0.2, T2 = 0.3, T3 = 0.4, T3W = 0.45 } -- W = wasteful ring

	--Finally, build the table using those starting points
	local StyleHeader = "Melee!!Ranged!!Magic"
	StyleHeader = StyleHeader..'!!'..StyleHeader..'!!'..StyleHeader..'!!'..StyleHeader

	local result = '{| class="wikitable stickyHeader"'
	result = result..'\r\n|-class="headerRow-0"'
	result = result..'\r\n!Pre-Triangle DR!!colspan=3|AE T3 + Wasteful!!colspan=3|Auto Eat Tier 3!!colspan=3|Auto Eat Tier 2!!colspan=3|Auto Eat Tier 1'
	result = result..'\r\n|-class="headerRow-0"'
	result = result..'\r\n!DR %!!'..StyleHeader

	for tier, aevalue in Shared.skpairs(AutoEatValues) do
		--mw.log(aevalue)
	end

	result = result..'\r\n|}'

	return result
end

function p._getStrongestAfflicted()
	local maxHitsPerMonsterStyle = { Melee = 0, Ranged = 0, Magic = 0 }
	
	for _, id in Shared.skpairs(AreaData.itm.monsters) do
		local monster = Monsters.getMonsterByID(id)
		local styleName = Constants.getCombatStyleName(monster.attackType)
		
		local maxHit = Monsters._getMonsterMaxHit(monster, true) -- doStuns = true
		if styleName == "Random" then
			for randomStyle, value in Shared.skpairs(maxHitsPerMonsterStyle) do
				if maxHit > value then
					maxHitsPerMonsterStyle[randomStyle] = maxHit
				end
			end
		else
			if maxHit > maxHitsPerMonsterStyle[styleName] then
				maxHitsPerMonsterStyle[styleName] = maxHit
			end
		end
	end
	return maxHitsPerMonsterStyle
end

function p._getAfflictedAverageHP()
	local totalHp = 0
	local afflicted = AreaData.itm.monsters
	for _, id in Shared.skpairs(afflicted) do
		local monster = Monsters.getMonsterByID(id)
		totalHp = totalHp + Monsters._getMonsterHP(monster)
	end
	return math.ceil(totalHp / Shared.tableCount(afflicted))
end

function p._getDungeonTotalHP(dung, accountForEnemyDR)
	local calculateDr = accountForEnemyDR or false
	local totalHp = 0
	for i, monsterID in Shared.skpairs(dung.monsters) do
		local dr = 0
		local monsterHp = 0
		
		local monster = Monsters.getMonsterByID(monsterID)
		if monster == nil and monsterID == -1 then
			monsterHp = p._getAfflictedAverageHP()
			dr = 0.2 -- afflicted always have +20% dr
		else 
			monsterHp = Monsters._getMonsterHP(monster)
			dr = 0
		end
		
		if calculateDR then
			for i, eq in Shared.skpairs(monster.equipmentStats) do
				if eq.key == "damageReduction" then
					dr = dr + eq.value/100
				end
			end
		else
			dr = 0
		end
		
		local monsterPostReductionHP = math.floor(monsterHp / (1-dr))
		totalHp = totalHp + monsterPostReductionHP
	end
	return totalHp
end

return p