+ Ouvrir une nouvelle discussion
Affichage des résultats 1 à 2 sur 2

Discussion: [Plugin] ItemCalc

  1. #1
    Junior Member Online status: Polymnie est déconnecté Reputation: Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte
    Date d'inscription
    mai 2011
    Messages
    34

    [Plugin] ItemCalc

    Third in my series of ugly, hard-to-configure, un-localized plugins is ItemCalc. ItemCalc presents a window into which you can input a piece of equipment's stats and receive information about its level, stat budget and predicted damage, armour or critical defence.

    The following image shows an item whose stats have been entered into the first column. The second column shows the ratio of the stat budget allocations. The third column shows the equivalent of that allocation had it been a primary stat instead. At the bottom, is the item's suspected level (which differs from its minimum level to equip), the predicted vendor price, and since it's a weapon, the predicted DPS and damage range.


    How to use
    1. Toggle the visibility of the window: /itemcalc
    2. If the budget seems wrong, assume the plugin is wrong. DO NOT /bug ITEM BUDGETS based on what this plugin calculates.

    Notes - Item Budgets
    1. Item budgets don't work for pre-Rise of Isengard items. Some pre-66 scaling items do.
    2. Class-slot and ranged-slot equipment (instruments, chisels, standards, etc) are not supported as their budgets are very different.
    3. Two-handed legendary passive stats are not supported, but you can learn a bit by tinkering with them.
    4. Weapon damage-type (beleriand, etc) contributes to the stat budget. If a weapon seems below-budget, check the damage-type.
    5. If the budget seems wrong, assume the plugin is wrong. DO NOT /bug ITEM BUDGETS based on what this plugin calculates.

    Notes - DPS and Armour
    1. Update 7 is alleged to have changed some DPS values, but the Lorebook (my primary source of data) does not yet reflect this. I do in-game cross-checking, but it's not feasible to track down every level of weapon.
    3. DPS and armour are not calculated for epics, as I have insufficient data.
    4. DPS and armour are sometimes a bit off. Shields, cloaks, and items above level 80 have larger armour error-margins.

    Notes - Vendor Price
    1. Spears seem to have two different vendor-price formulae and no way to predict which will be used.
    2. Equipment that you buy from a reputation vendor either uses a different formula, or a huge multiplier, to make its purchase and vendor values so high.

    Updates
    2012/05/20 Major rewrite, possibly introduced new bugs. Added vendor-price prediction. Adjusted mitigation. Adjusted block rating on shields. Adjusted some pre-66 scaling.
    2012/05/21 Added ranged weapons. Adjusted some pre-50 dps.

    Code:
    import "Turbine.UI.Lotro"
    -------------------------------------------------------------------------------
    local WindowLeft = Turbine.UI.Display:GetWidth() / 2
    local WindowTop = 0
    local debug = false
    -------------------------------------------------------------------------------
    local StatLabels = {}
    local TextBoxes = {}
    local UnitLabels = {}
    local EquivLabels = {}
    
    local StatOrder = {"Maximum Morale", "Maximum Power", "in-Combat Morale Regen",
    	"in-Combat Power Regen", "Might", "Agility", "Vitality", "Will",
    	"Fate", "Critical Rating", "Finesse Rating", "Physical Mastery Rating",
    	"Tactical Mastery Rating", "Resistance Rating", "Incoming Healing Rating",
    	"Block Rating", "Parry Rating", "Evade Rating", "Physical Mitigation",
    	"Tactical Mitigation"}
    
    local QualityNames = {"uncommon", "rare", "incomparable", "epic"}
    local CategoryNames = {"light armour", "medium armour", "heavy armour", "cloak",
    	"jewellery", "shield", "melee 1h", "melee 2h", "ranged"}
    local ArmourNames = {"head", "shoulders", "chest", "hands", "legs", "feet"}
    local JewelleryNames = {"bracelet", "earring", "necklace", "pocket", "ring"}
    local ShieldNames = {"light", "warden", "heavy"}
    local Melee1Names = {"axe", "club", "dagger", "hammer", "mace", "spear", "sword"}
    local Melee2Names = {"axe", "club", "halberd", "hammer", "rune-stone", "staff", "sword"}
    local RangedNames = {"bow", "crossbow", "javelin"}
    
    local QualityColours = {Turbine.UI.Color(1, 1, 0), --ffff00 (from lorebook.css)
    	Turbine.UI.Color(0.761, 0, 0.780), --c200c7
    	Turbine.UI.Color(0, 0.996, 1), --00feff
    	Turbine.UI.Color(0.949, 0.671, 0.047)} --f2ab0c
    -------------------------------------------------------------------------------
    function round(number, zeroes)
    	local zeroes = zeroes or 0
    	return math.floor(number * (10 ^ zeroes) + .5) / (10 ^ zeroes)
    end
    -------------------------------------------------------------------------------
    -- level-guessing and stat-allocation functions
    function TypicalRatingsByLevel(stat, level)
    	local typical
    	if stat == "Maximum Morale" then
    		if level > 49 then
    			typical = level * 3.5 - 125.5
    		else
    			typical = level * 0.9 + 0.9
    		end
    	elseif stat == "Maximum Power" then
    		if level > 49 then
    			typical = level * 3 - 104
    		else
    			typical = level * 0.9 + 0.9
    		end
    	elseif stat == "in-Combat Morale Regen" then
    		if level > 49 then
    			typical = level * 0.9 - 14.1
    		else
    			typical = level * 0.6 + 0.6
    		end
    	elseif stat == "in-Combat Power Regen" then
    		if level > 49 then
    			typical = level * 0.3 + 30.3
    		else
    			typical = level * 0.9 + 0.9
    		end
    	elseif stat == "Might"
    	or stat == "Agility"
    	or stat == "Vitality"
    	or stat == "Will"
    	or stat == "Fate" then
    		if level > 59 then
    			typical = level * 0.5 - 10.5
    		elseif level > 49 then
    			typical = level * 0.3 + 1.3
    		else
    			typical = level * 0.3 + 0.1
    		end
    	elseif stat == "Critical Rating" then
    		typical = level * 4
    	elseif stat == "Finesse Rating" then
    		if level > 51 then
    			typical = level * 12 + 12
    		elseif level < 50 then
    			typical = level * 12 + 48
    		else
    			typical = 636
    		end
    	elseif stat == "Physical Mastery Rating" then
    		typical = level * 4
    	elseif stat == "Tactical Mastery Rating" then
    		typical = level * 4
    	elseif stat == "Resistance Rating" then
    		typical = level * 6
    	elseif stat == "Incoming Healing Rating" then
    		typical = level * 8
    	elseif stat == "Block Rating" then
    		if CategoryButton:GetText() == "shield" then -- ugly and ominous
    			typical = level * 6
    		else
    			typical = level * 4
    		end
    	elseif stat == "Parry Rating" then
    		typical = level * 4
    	elseif stat == "Evade Rating" then
    		typical = level * 4
    	elseif stat == "Physical Mitigation" then
    		typical = level * 8.1
    	elseif stat == "Tactical Mitigation" then
    		typical = level * 8.1
    	end
    
    	if typical < 1 then  -- avoid later div-by-0 and other oddities
    		return 1
    	else
    		return typical
    	end
    end
    
    function GuessLevel(stat, rating)
    	local slope, ambiguous
    	local constant = 0
    	if stat == "Maximum Morale" then
    		slope = 3.5
    		constant = - 125.5
    	elseif stat == "Maximum Power" then
    		slope = 3
    		constant = - 104
    	elseif stat == "in-Combat Morale Regen" then
    		slope = 0.9
    		constant = - 14.1
    	elseif stat == "in-Combat Power Regen" then
    		slope = 0.3
    		constant = 30.3
    		ambiguous = true
    	elseif stat == "Might"
    	or stat == "Agility"
    	or stat == "Vitality"
    	or stat == "Will"
    	or stat == "Fate" then
    		slope = 0.5
    		constant = - 10.5
    		ambiguous = true
    	elseif stat == "Critical Rating" then
    		slope = 4
    	elseif stat == "Finesse Rating" then
    		slope = 12
    		constant = 12
    	elseif stat == "Physical Mastery Rating" then
    		slope = 4
    	elseif stat == "Tactical Mastery Rating" then
    		slope = 4
    	elseif stat == "Resistance Rating" then
    		slope = 6
    	elseif stat == "Incoming Healing Rating" then
    		slope = 8
    	elseif stat == "Block Rating" then
    		if CategoryButton:GetText() == "shield" then -- ugly and ominous
    			slope = 6
    		else
    			slope = 4
    		end
    	elseif stat == "Parry Rating" then
    		slope = 4
    	elseif stat == "Evade Rating" then
    		slope = 4
    	elseif stat == "Physical Mitigation" then
    		slope = 8.1
    	elseif stat == "Tactical Mitigation" then
    		slope = 8.1
    	end
    
    	local BestGuess, NewGuess, mult
    	for i = 1, 4 do
    		NewGuess = math.floor(((rating / i) - constant) / slope)
    
    		-- assume the mult that leads closest to 75 is correct
    		if not BestGuess or math.abs(75 - NewGuess) < math.abs(75 - BestGuess) then
    			BestGuess = NewGuess
    			mult = i
    		end
    	end
    
    	if ambiguous and (mult == 1 or mult == 3) then -- don't trust
    		if debug then
    			Turbine.Shell.WriteLine(string.format("[calc] ((%s %s / %d) - %s) / %s = %s?",
    				rating, stat, mult, constant, slope, BestGuess))
    		end
    		return BestGuess, false
    	else -- trust, but I could be wrong
    		if debug then
    			Turbine.Shell.WriteLine(string.format("[calc] ((%s %s / %d) - %s) / %s = %s",
    				rating, stat, mult, constant, slope, BestGuess))
    		end
    		return BestGuess, true
    	end
    end
    -------------------------------------------------------------------------------
    -- armour-guessing functions
    function GuessArmour(level)
    	local QualityText = QualityButton:GetText()
    	if QualityText == "epic" then -- insufficient data to implement
    		return "?"
    	end
    
    	local multiplier
    	local category = CategoryButton:GetText()
    	local ArmourText = ArmourButton:GetText()
    	local ShieldText = ShieldButton:GetText()
    
    	if ArmourText == "chest" then
    		multiplier = 8.1 * 1.2
    	elseif ArmourText == "feet" then
    		multiplier = 8.1 * 0.48
    	elseif ArmourText == "hands" then
    		multiplier = 8.1 * 0.6
    	elseif ArmourText == "head" then
    		multiplier = 8.1 * 0.36
    	elseif ArmourText == "legs" then
    		multiplier = 8.1
    	elseif ArmourText == "shoulders" then
    		multiplier = 8.1 * 0.36
    	end
    
    	if category == "medium armour" then
    		multiplier = multiplier * 17 / 12
    	elseif category == "heavy armour" then
    		multiplier = multiplier * 11 / 6
    	elseif category == "cloak" then
    		multiplier = 8.1 * 11 / 15
    	elseif category == "shield" then
    		if ShieldText == "light" then
    			multiplier = 8.1 * 31 / 24
    		elseif ShieldText == "warden" then
    			multiplier = 15.24
    		else
    			multiplier = 8.1 * 25 / 6
    		end
    	end
    
    	-- shields are frustrating
    	if category == "shield" and ShieldText == "light" then
    		if QualityText == "incomparable" then
    			return round(level * multiplier)
    		elseif QualityText == "rare" then
    			return round((level - 2) * multiplier)
    		else
    			return round(level * multiplier * 0.785)
    		end
    	elseif category == "shield" and ShieldText == "heavy" then
    		if QualityText == "incomparable" then
    			return math.ceil(level * multiplier)
    		elseif QualityText == "rare" then
    			return round(math.ceil(level * multiplier) * 0.8)
    		else
    			return round(math.ceil((level - 3) * multiplier) * 0.8)
    		end
    	else
    		if QualityText == "incomparable" then
    			return round(level * multiplier)
    		elseif QualityText == "rare" then
    			return round(round(level * multiplier) * 0.95)
    		else
    			return round(round((level - 3) * multiplier) * 0.95)
    		end
    	end
    end
    -------------------------------------------------------------------------------
    -- dps-guessing functions
    local hardcodedDPS = {} -- ugly, hopefully U7 will simplify this
    hardcodedDPS[51] = 38
    hardcodedDPS[52] = 39
    hardcodedDPS[53] = 40.1
    hardcodedDPS[54] = 42.1
    hardcodedDPS[55] = 44.2
    hardcodedDPS[56] = 46.5
    hardcodedDPS[57] = 48.3
    hardcodedDPS[58] = 50.1
    
    function GuessDamage(level)
    	local QualityText = QualityButton:GetText()
    	if QualityText == "epic" then -- insufficient data to implement
    		return "damage prediction: ?"
    	end
    
    	local result = hardcodedDPS[level]
    	if level > 64 then
    		result = level * 3.25 - 149.4
    	elseif level > 58 then
    		result = level * 1.4 - 30.6
    	elseif level < 51 then
    		result = level * 0.7 + 2.1
    	end
    
    	local category = CategoryButton:GetText()
    	if category == "melee 2h" or category == "ranged" then
    		if level > 50 then
    			result = result * 17 / 15
    		else
    			result = result * 1.14
    		end
    	end
    
    	if QualityText == "incomparable" then
    		result = result * 1.038
    	elseif QualityText == "uncommon" then
    		result = result * 0.9375 -- 15 / 16
    	end
    
    	local min, max
    	if category == "melee 1h" then
    		min = round(result * 1.425) -- 1.9 * 3 / 4
    		max = round(result * 2.375) -- 1.9 * 5 / 4
    	elseif category == "melee 2h" then
    		min = round(result * 1.875) -- 2.5 * 3 / 4
    		max = round(result * 3.125) -- 2.5 * 5 / 4
    	elseif category == "ranged" then
    		if RangedButton:GetText() == "javelin" then
    			min = round(result * 1.875) -- 2.5 * 3 / 4
    			max = round(result * 3.125) -- 2.5 * 5 / 4
    		else
    			min = round(result * 1.562) -- 2.2 * 0.71
    			max = round(result * 2.838) -- 2.2 * 1.29
    		end
    	end
    
    	return string.format("\ndamage prediction: %s DPS\n(%s - %s Damage)", round(result, 1), min, max)
    end
    -------------------------------------------------------------------------------
    function GuessVendor(level)
    	local copper
    	local category = CategoryButton:GetText()
    	local ArmourText = ArmourButton:GetText()
    	local JewelleryText = JewelleryButton:GetText()
    	local ShieldText = ShieldButton:GetText()
    	local Melee1Text = Melee1Button:GetText()
    	local Melee2Text = Melee2Button:GetText()
    	local RangedText = RangedButton:GetText()
    
    	if category == "light armour" then
    		if ArmourText == "chest" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 76
    		elseif ArmourText == "legs" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 60
    		elseif ArmourText == "head" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 50
    		elseif ArmourText == "hands" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 40
    		elseif ArmourText == "feet" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 40
    		elseif	ArmourText == "shoulders" then
    			copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 36
    		end
    	elseif category == "medium armour" then
    		if ArmourText == "chest" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 83
    		elseif ArmourText == "legs" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 67
    		elseif ArmourText == "head" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 55
    		elseif ArmourText == "hands" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 45
    		elseif ArmourText == "feet" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 45
    		elseif ArmourText == "shoulders" then
    			copper = math.min(level, 50) * 16.5 + math.max(level - 50, 0) * 16 + 39
    		end
    	elseif category == "heavy armour" then
    		if ArmourText == "chest" then
    			copper = math.min(level, 50) * 21.5 + math.max(level - 50, 0) * 18 + 107
    		elseif ArmourText == "legs" then
    			copper = math.min(level, 50) * 21.5 + math.max(level - 50, 0) * 18 + 85
    		elseif ArmourText == "head" then
    			copper = math.min(level, 50) * 20 + math.max(level - 50, 0) * 18 + 56
    		elseif ArmourText == "hands" then
    			copper = math.min(level, 50) * 20 + math.max(level - 50, 0) * 18 + 44
    		elseif ArmourText == "feet" then
    			copper = math.min(level, 50) * 20 + math.max(level - 50, 0) * 18 + 44
    		elseif ArmourText == "shoulders" then
    			copper = math.min(level, 50) * 20 + math.max(level - 50, 0) * 18 + 38
    		end
    	elseif category == "cloak" then
    		copper = math.min(level, 50) * 15 + math.max(level - 50, 0) * 16 + 0
    	elseif category == "jewellery" then
    		if JewelleryText == "bracelet" then
    			copper = math.min(level, 50) * 5 + math.max(level - 50, 0) * 6 + 50
    		elseif JewelleryText == "earring" then
    			copper = math.min(level, 50) * 5 + math.max(level - 50, 0) * 6 + 0
    		elseif JewelleryText == "necklace" then
    			copper = math.min(level, 50) * 5 + math.max(level - 50, 0) * 6 + 150
    		elseif JewelleryText == "ring" then
    			copper = math.min(level, 50) * 5 + math.max(level - 50, 0) * 6 + 50
    		elseif JewelleryText == "pocket" then
    			copper = math.min(level, 50) * 22 + math.max(level - 50, 0) * 24 + 82
    		end
    	elseif category == "shield" then
    		if ShieldText == "light" then
    			copper = math.min(level, 50) * 11 + math.max(level - 50, 0) * 12 + 110
    		elseif ShieldText == "warden" then
    			copper = math.min(level, 50) * 12 + math.max(level - 50, 0) * 12 + 110
    		elseif ShieldText == "heavy" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 560
    		end
    	elseif category == "melee 1h" then
    		if Melee1Text == "axe" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 150
    		elseif Melee1Text == "club" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 148
    		elseif Melee1Text == "dagger" then
    			copper = math.min(level, 50) * 8 + math.max(level - 50, 0) * 10 + 130
    		elseif Melee1Text == "hammer" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 148
    		elseif Melee1Text == "mace" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 148
    		elseif Melee1Text == "spear" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 50
    		elseif Melee1Text == "sword" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 150
    		end
    	elseif category == "melee 2h" then
    		if Melee2Text == "axe" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 560
    		elseif Melee2Text == "club" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 560
    		elseif Melee2Text == "halberd" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 200
    		elseif Melee2Text == "hammer" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 560
    		elseif Melee2Text == "rune-stone" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 100
    		elseif Melee2Text == "staff" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 100
    		elseif Melee2Text == "sword" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 560
    		end
    	elseif category == "ranged" then
    		if RangedText == "bow" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 120
    		elseif RangedText == "crossbow" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 500
    		elseif RangedText == "javelin" then
    			copper = math.min(level, 50) * 14 + math.max(level - 50, 0) * 14 + 120
    		end
    	end
    
    	local QualityText = QualityButton:GetText()
    	if QualityText == "uncommon" then
    		copper = copper * 0.6
    	elseif QualityText == "incomparable" then
    		copper = copper * 1.5
    	elseif QualityText == "epic" then
    		copper = copper * 2
    	end
    
    	local output = "vendor prediction:"
    	local silver = math.floor(copper / 100)
    	if silver > 0 then
    		copper = copper - (silver * 100)
    		output = string.format("%s %ss", output, silver)
    	end
    	if copper ~= 0 then
    		output = string.format("%s %dc", output, copper) -- forced to integer
    	end
    
    	return output
    end
    -------------------------------------------------------------------------------
    -- main function
    function Calculate()
    	-- determine valid inputs and best-guess of level
    	local ValidInputs = {}
    	local best = 0
    	local trustbest = false
    	for i = 1, #StatOrder do
    		local rating = tonumber(TextBoxes[i]:GetText())
    		if rating then
    			ValidInputs[i] = rating
    			TextBoxes[i]:SetText(rating) -- fix whitespace problems
    			local guess, trustguess = GuessLevel(StatOrder[i], rating)
    			if trustguess and (not trustbest or guess > best) then
    				best = guess
    				trustbest = true
    			elseif not trustbest and guess > best then
    				best = guess
    			end
    		else
    			TextBoxes[i]:SetText("") -- clear bad inputs
    		end
    	end
    	LevelLabel:SetText("suspected level: "..best)
    	if best < 66 then
    		LevelLabel:SetForeColor(Turbine.UI.Color(1, 0, 0))
    	else
    		LevelLabel:SetForeColor(Turbine.UI.Color(0, 1, 0))
    	end
    
    
    	-- calculate units, equivs, and totals
    	local override = tonumber(OverrideBox:GetText()) or best
    	local UnitTotal = 0
    	local EquivTotal = 0
    	local primary = TypicalRatingsByLevel("Might", override) -- all the primary stats are the same
    	for i = 1, #StatOrder do
    		if ValidInputs[i] then
    			local unit = ValidInputs[i] / TypicalRatingsByLevel(StatOrder[i], override)
    			local equiv = unit * primary
    			UnitTotal = UnitTotal + unit
    			EquivTotal = EquivTotal + equiv
    			UnitLabels[i]:SetText(unit)
    			EquivLabels[i]:SetText(equiv)
    		else
    			UnitLabels[i]:SetText(".")
    			EquivLabels[i]:SetText(".")
    		end
    	end
    	UnitTotalLabel:SetText(UnitTotal)
    	EquivTotalLabel:SetText(EquivTotal)
    
    	local QualitySize = 8
    	if QualityButton:GetText() == "uncommon" then
    		QualitySize = 5
    	elseif QualityButton:GetText() == "rare" then
    		QualitySize = 6
    	elseif QualityButton:GetText() == "incomparable" then
    		QualitySize = 7
    	end
    
    	local category = CategoryButton:GetText()
    	if category == "melee 2h" then
    		QualitySize = QualitySize * 2
    	end
    	UnitMaxLabel:SetText("of "..QualitySize)
    	EquivMaxLabel:SetText("of "..QualitySize * primary)
    
    	local extra = GuessVendor(override)
    	if category == "melee 1h" or category == "melee 2h" or category == "ranged" then
    		extra = extra..GuessDamage(override)
    	elseif category ~= "jewellery" then
    		extra = extra.."\narmour prediction: "..GuessArmour(override)
    		if category == "shield" then
    			if ShieldButton:GetText() == "heavy" then
    				extra = extra.."\ncritical defence: "..(override + 1) * 20
    			elseif ShieldButton:GetText() == "warden" then
    				extra = extra.."\ncritical defence: "..(override + 1) * 16
    			else
    				extra = extra.."\ncritical defence: "..(override + 1) * 8
    			end
    		end
    	end
    	ExtraLabel:SetText(extra)
    end
    
    function Reset()
    	for i = 1, #StatOrder do
    		TextBoxes[i]:SetText("")
    	end
    	OverrideBox:SetText("")
    	Calculate()
    end
    -------------------------------------------------------------------------------
    -- tedious window-layout and menu functions
    local WindowWidth = 380
    local WindowHeight = 580
    CalcWindow = Turbine.UI.Lotro.Window()
    CalcWindow:SetPosition(WindowLeft, WindowTop)
    CalcWindow:SetSize(WindowWidth, WindowHeight)
    CalcWindow:SetText("ItemCalc")
    CalcWindow:SetVisible(true)
    
    function MakeLabel(Left, Top, Width, Height)
    	local TempLabel = Turbine.UI.Label()
    	TempLabel:SetParent(CalcWindow)
    	TempLabel:SetPosition(Left, Top)
    	TempLabel:SetSize(Width, Height)
    	TempLabel:SetFont(Turbine.UI.Lotro.Font.Verdana16)
    	TempLabel:SetMouseVisible(false)
    	return TempLabel
    end
    
    function MakeTextbox(Left, Top, Width, Height)
    	local TempTextbox = Turbine.UI.Lotro.TextBox()
    	TempTextbox:SetParent(CalcWindow)
    	TempTextbox:SetPosition(Left, Top)
    	TempTextbox:SetSize(Width, Height)
    	TempTextbox:SetFont(Turbine.UI.Lotro.Font.Verdana16)
    	return TempTextbox
    end
    
    function MakeButton(Left, Top, Width, Height, Text)
    	local TempButton = Turbine.UI.Lotro.Button()
    	TempButton:SetParent(CalcWindow)
    	TempButton:SetPosition(Left, Top)
    	TempButton:SetSize(Width, Height)
    	TempButton:SetFont(Turbine.UI.Lotro.Font.Verdana16)
    	TempButton:SetText(Text)
    	return TempButton
    end
    
    for i = 1, #StatOrder do
    	StatLabels[i] = MakeLabel(20, 10 + i * 20, 170, 20)
    	StatLabels[i]:SetText(StatOrder[i])
    
    	TextBoxes[i] = MakeTextbox(190, 10 + i * 20, 50, 20)
    
    	UnitLabels[i] = MakeLabel(250, 10 + i * 20, 40, 19)
    	UnitLabels[i]:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    
    	EquivLabels[i] = MakeLabel(300, 10 + i * 20, 60, 19)
    	EquivLabels[i]:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    end
    
    LevelLabel = MakeLabel(20, 10 + (#StatOrder + 1) * 20, 140, 19)
    
    UnitTotalLabel = MakeLabel(250, 10 + (#StatOrder + 1) * 20, 40, 19)
    UnitTotalLabel:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    
    EquivTotalLabel = MakeLabel(300, 10 + (#StatOrder + 1) * 20, 60, 19)
    EquivTotalLabel:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    
    OverrideLabel = MakeLabel(20, 10 + (#StatOrder + 2) * 20, 100, 19)
    OverrideLabel:SetText("level override:")
    
    OverrideBox = MakeTextbox(120, 10 + (#StatOrder + 2) * 20, 50, 20)
    
    UnitMaxLabel = MakeLabel(250, 10 + (#StatOrder + 2) * 20, 40, 19)
    UnitMaxLabel:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    
    EquivMaxLabel = MakeLabel(300, 10 + (#StatOrder + 2) * 20, 60, 19)
    EquivMaxLabel:SetTextAlignment(Turbine.UI.ContentAlignment.TopRight)
    
    CalculateButton = MakeButton(20, 10 + (#StatOrder + 3) * 20, 70, 20, "calculate")
    CalculateButton.Click = function(sender, args)
    	Calculate()
    end
    
    DebugButton = MakeButton(90, 10 + (#StatOrder + 3) * 20, 50, 20, "debug")
    DebugButton.Click = function(sender, args)
    	if debug then
    		debug = false
    		Turbine.Shell.WriteLine("ItemCalc debugging is now off.")
    	else
    		debug = true
    		Turbine.Shell.WriteLine("ItemCalc debugging is now on.")
    	end
    end
    
    ResetButton = MakeButton(140, 10 + (#StatOrder + 3) * 20, 50, 20, "reset")
    ResetButton.Click = function(sender, args)
    	Reset()
    end
    
    QualityButton = MakeButton(20, 10 + (#StatOrder + 4) * 20, 100, 20, QualityNames[1])
    QualityButton:SetForeColor(QualityColours[1])
    QualityContext = Turbine.UI.ContextMenu()
    QualityContextItems = QualityContext:GetItems()
    for i = 1, #QualityNames do
    	local menuItem = Turbine.UI.MenuItem(QualityNames[i])
    	menuItem.Click = function(sender, args)
    		QualityButton:SetText(QualityNames[i])
    		QualityButton:SetForeColor(QualityColours[i])
    		Calculate()
    	end
    	QualityContextItems:Add(menuItem)
    end
    QualityButton.Click = function(sender, args)
    	QualityContext:ShowMenu()
    end
    
    CategoryButton = MakeButton(120, 10 + (#StatOrder + 4) * 20, 110, 20, CategoryNames[1])
    CategoryContext = Turbine.UI.ContextMenu()
    CategoryContextItems = CategoryContext:GetItems()
    for i = 1, #CategoryNames do
    	local menuItem = Turbine.UI.MenuItem(CategoryNames[i])
    	menuItem.Click = function(sender, args)
    		CategoryButton:SetText(CategoryNames[i])
    		ArmourButton:SetVisible(false)
    		JewelleryButton:SetVisible(false)
    		ShieldButton:SetVisible(false)
    		Melee1Button:SetVisible(false)
    		Melee2Button:SetVisible(false)
    		RangedButton:SetVisible(false)
    		if CategoryNames[i] == "light armour"
    		or CategoryNames[i] == "medium armour"
    		or CategoryNames[i] == "heavy armour" then
    			ArmourButton:SetVisible(true)
    		elseif CategoryNames[i] == "jewellery" then
    			JewelleryButton:SetVisible(true)
    		elseif CategoryNames[i] == "shield" then
    			ShieldButton:SetVisible(true)
    		elseif CategoryNames[i] == "melee 1h" then
    			Melee1Button:SetVisible(true)
    		elseif CategoryNames[i] == "melee 2h" then
    			Melee2Button:SetVisible(true)
    		elseif CategoryNames[i] == "ranged" then
    			RangedButton:SetVisible(true)
    		end
    		Calculate()
    	end
    	CategoryContextItems:Add(menuItem)
    end
    CategoryButton.Click = function(sender, args)
    	CategoryContext:ShowMenu()
    end
    
    ArmourButton = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, ArmourNames[1])
    ArmourContext = Turbine.UI.ContextMenu()
    ArmourContextItems = ArmourContext:GetItems()
    for i = 1, #ArmourNames do
    	local menuItem = Turbine.UI.MenuItem(ArmourNames[i])
    	menuItem.Click = function(sender, args)
    		ArmourButton:SetText(ArmourNames[i])
    		Calculate()
    	end
    	ArmourContextItems:Add(menuItem)
    end
    ArmourButton.Click = function(sender, args)
    	ArmourContext:ShowMenu()
    end
    
    JewelleryButton = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, JewelleryNames[1])
    JewelleryContext = Turbine.UI.ContextMenu()
    JewelleryContextItems = JewelleryContext:GetItems()
    for i = 1, #JewelleryNames do
    	local menuItem = Turbine.UI.MenuItem(JewelleryNames[i])
    	menuItem.Click = function(sender, args)
    		JewelleryButton:SetText(JewelleryNames[i])
    		Calculate()
    	end
    	JewelleryContextItems:Add(menuItem)
    end
    JewelleryButton.Click = function(sender, args)
    	JewelleryContext:ShowMenu()
    end
    JewelleryButton:SetVisible(false) -- since we start with armour
    
    ShieldButton = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, ShieldNames[1])
    ShieldContext = Turbine.UI.ContextMenu()
    ShieldContextItems = ShieldContext:GetItems()
    for i = 1, #ShieldNames do
    	local menuItem = Turbine.UI.MenuItem(ShieldNames[i])
    	menuItem.Click = function(sender, args)
    		ShieldButton:SetText(ShieldNames[i])
    		Calculate()
    	end
    	ShieldContextItems:Add(menuItem)
    end
    ShieldButton.Click = function(sender, args)
    	ShieldContext:ShowMenu()
    end
    ShieldButton:SetVisible(false) -- since we start with armour
    
    Melee1Button = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, Melee1Names[1])
    Melee1Context = Turbine.UI.ContextMenu()
    Melee1ContextItems = Melee1Context:GetItems()
    for i = 1, #Melee1Names do
    	local menuItem = Turbine.UI.MenuItem(Melee1Names[i])
    	menuItem.Click = function(sender, args)
    		Melee1Button:SetText(Melee1Names[i])
    		Calculate()
    	end
    	Melee1ContextItems:Add(menuItem)
    end
    Melee1Button.Click = function(sender, args)
    	Melee1Context:ShowMenu()
    end
    Melee1Button:SetVisible(false) -- since we start with armour
    
    Melee2Button = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, Melee2Names[1])
    Melee2Context = Turbine.UI.ContextMenu()
    Melee2ContextItems = Melee2Context:GetItems()
    for i = 1, #Melee2Names do
    	local menuItem = Turbine.UI.MenuItem(Melee2Names[i])
    	menuItem.Click = function(sender, args)
    		Melee2Button:SetText(Melee2Names[i])
    		Calculate()
    	end
    	Melee2ContextItems:Add(menuItem)
    end
    Melee2Button.Click = function(sender, args)
    	Melee2Context:ShowMenu()
    end
    Melee2Button:SetVisible(false) -- since we start with armour
    
    RangedButton = MakeButton(230, 10 + (#StatOrder + 4) * 20, 80, 20, RangedNames[1])
    RangedContext = Turbine.UI.ContextMenu()
    RangedContextItems = RangedContext:GetItems()
    for i = 1, #RangedNames do
    	local menuItem = Turbine.UI.MenuItem(RangedNames[i])
    	menuItem.Click = function(sender, args)
    		RangedButton:SetText(RangedNames[i])
    		Calculate()
    	end
    	RangedContextItems:Add(menuItem)
    end
    RangedButton.Click = function(sender, args)
    	RangedContext:ShowMenu()
    end
    RangedButton:SetVisible(false) -- since we start with armour
    
    ExtraLabel = MakeLabel(20, 10 + (#StatOrder + 5) * 20, 300, 48)
    -------------------------------------------------------------------------------
    -- command-line processing
    CommandLine = Turbine.ShellCommand()
    CommandLine.Execute = function(sender, cmd, args)
    	if CalcWindow:IsVisible() then
    		CalcWindow:SetVisible(false)
    	else
    		CalcWindow:SetVisible(true)
    	end
    end
    Turbine.Shell.AddCommand("ItemCalc", CommandLine)
    -------------------------------------------------------------------------------
    -- create a dummy window, and update until loaded, at which point set loaded=true and set the unload commands.
    local loaded = false
    tmpWindow = Turbine.UI.Window()
    tmpWindow.Update = function()
    	if Plugins["ItemCalc"] ~= nil and not loaded then
    		loaded = true
    		Plugins["ItemCalc"].Unload = function(self, sender, args)
    			Turbine.Shell.RemoveCommand(CommandLine)
    		end
    		tmpWindow:SetWantsUpdates(false)
    		Turbine.Shell.WriteLine("ItemCalc plugin loaded.".._VERSION)
    		Reset()
    	end
    end
    tmpWindow:SetWantsUpdates(true)
    Dernière modification par Polymnie ; 21/05/2012 à 07h53.

  2. #2
    Junior Member Online status: Polymnie est déconnecté Reputation: Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte Polymnie the Neophyte
    Date d'inscription
    mai 2011
    Messages
    34

    Re: [Plugin] ItemCalc

    Added vendor-price prediction, which can help cross-check item-level.

+ Ouvrir une nouvelle discussion

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages