Release 1.2.41

- Show save prompt before updating
- Add options for Enemy is Blinded, Dealt Non-Crit Recently, Ignited/Frozen an Enemy Recently
- Reworked node stat difference to avoid issue with certain radius jewels
This commit is contained in:
Openarl
2017-02-13 00:09:27 +10:00
parent b1c9eb5cb6
commit fc2586c7e1
15 changed files with 331 additions and 181 deletions

View File

@@ -31,7 +31,7 @@ function buildMode:Init(dbFileName, buildName)
self.anchorTopBarLeft = common.New("Control", nil, 4, 4, 0, 20)
self.controls.back = common.New("ButtonControl", {"LEFT",self.anchorTopBarLeft,"RIGHT"}, 0, 0, 60, 20, "<< Back", function()
if self.unsaved then
self:OpenSavePopup(false)
self:OpenSavePopup("LIST")
else
main:SetMode("LIST", self.dbFileName and self.buildName)
end
@@ -352,11 +352,11 @@ function buildMode:Init(dbFileName, buildName)
self.abortSave = false
end
function buildMode:CanExit()
function buildMode:CanExit(mode)
if not self.unsaved then
return true
end
self:OpenSavePopup(true)
self:OpenSavePopup(mode)
return false
end
@@ -408,7 +408,7 @@ function buildMode:OnFrame(inputEvents)
inputEvents[id] = nil
elseif event.key == "w" then
if self.unsaved then
self:OpenSavePopup(false)
self:OpenSavePopup("LIST")
else
main:SetMode("LIST", self.dbFileName and self.buildName)
end
@@ -526,20 +526,27 @@ function buildMode:OnFrame(inputEvents)
self:DrawControls(main.viewPort)
end
function buildMode:OpenSavePopup(exit)
main:OpenPopup(280, 100, "Save Changes", {
common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..(exit and "before exiting?" or "now?")),
function buildMode:OpenSavePopup(mode)
local modeDesc = {
["LIST"] = "now?",
["EXIT"] = "before exiting?",
["UPDATE"] = "before updating?",
}
main:OpenPopup(290, 100, "Save Changes", {
common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]),
common.New("ButtonControl", nil, -90, 70, 80, 20, "Save", function()
main:ClosePopup()
self.actionOnSave = exit and "EXIT" or "LIST"
self.actionOnSave = mode
self:SaveDBFile()
end),
common.New("ButtonControl", nil, 0, 70, 80, 20, "Don't Save", function()
main:ClosePopup()
if exit then
Exit()
else
if mode == "LIST" then
main:SetMode("LIST", self.dbFileName and self.buildName)
elseif mode == "EXIT" then
Exit()
elseif mode == "UPDATE" then
launch:ApplyUpdate(launch.updateAvailable)
end
end),
common.New("ButtonControl", nil, 90, 70, 80, 20, "Cancel", function()
@@ -702,9 +709,11 @@ function buildMode:SaveDBFile()
file:write(xmlText)
file:close()
if self.actionOnSave == "LIST" then
main:SetMode("LIST", self.buildName)
main:SetMode("LIST", self.dbFileName and self.buildName)
elseif self.actionOnSave == "EXIT" then
Exit()
elseif self.actionOnSave == "UPDATE" then
launch:ApplyUpdate(launch.updateAvailable)
end
self.actionOnSave = nil
end

View File

@@ -633,6 +633,7 @@ local function initEnv(build, mode)
modDB:NewMod("BlockChance", "BASE", 15, "Base", { type = "Condition", var = "DualWielding" })
modDB:NewMod("LifeRegenPercent", "BASE", 4, "Base", { type = "Condition", var = "OnConsecratedGround" })
modDB:NewMod("Misc", "LIST", { type = "EnemyModifier", mod = modLib.createMod("DamageTaken", "INC", 50, "Shock") }, "Base", { type = "Condition", var = "EnemyShocked" })
modDB:NewMod("Misc", "LIST", { type = "EnemyModifier", mod = modLib.createMod("HitChance", "MORE", -50, "Blind") }, "Base", { type = "Condition", var = "EnemyBlinded" })
-- Add bandit mods
if build.banditNormal == "Alira" then
@@ -678,32 +679,52 @@ local function initEnv(build, mode)
end
-- This function:
-- 1. Merges modifiers for all items, optionally replacing one item
-- 1. Merges modifiers for all items
-- 2. Builds a list of jewels with radius functions
-- 3. Merges modifiers for all allocated passive nodes
-- 4. Builds a list of active skills and their supports
-- 5. Builds modifier lists for all active skills
local function mergeMainMods(env, repSlotName, repItem)
local function mergeMainMods(env, override)
local build = env.build
override = override or { }
-- Build list of passive nodes
local nodes
if override.addNodes or override.removeNodes then
nodes = { }
if override.addNodes then
for node in pairs(override.addNodes) do
nodes[node.id] = node
end
end
for _, node in pairs(build.spec.allocNodes) do
if not override.removeNodes or not override.removeNodes[node] then
nodes[node.id] = node
end
end
else
nodes = build.spec.allocNodes
end
-- Build and merge item modifiers, and create list of radius jewels
env.radiusJewelList = wipeTable(env.radiusJewelList)
env.itemList = { }
env.flasks = { }
env.modDB.conditions["UsingAllCorruptedItems"] = true
for slotName, slot in pairs(build.itemsTab.slots) do
local item
if slotName == repSlotName then
item = repItem
if slotName == override.repSlotName then
item = override.repItem
else
item = build.itemsTab.list[slot.selItemId]
end
if slot.nodeId then
-- Slot is a jewel socket, check if socket is allocated
if not build.spec.allocNodes[slot.nodeId] then
if not nodes[slot.nodeId] then
item = nil
elseif item and item.jewelRadiusIndex then
-- Jewel has a radius, add it to the list
local funcList = item.jewelFunc or { function(nodeMods, out, data)
local funcList = item.jewelFuncList or { function(nodeMods, out, data)
-- Default function just tallies all stats in radius
if nodeMods then
for _, stat in pairs({"Str","Dex","Int"}) do
@@ -727,12 +748,10 @@ local function mergeMainMods(env, repSlotName, repItem)
end
end
if item and item.type == "Flask" then
if env.configInput["enableFlask"..slot.slotNum] then
-- FIXME dunno lol
env.modDB.conditions["UsingFlask"] = true
else
item = nil
if slot.active then
env.flasks[item] = true
end
item = nil
end
env.itemList[slotName] = item
if item then
@@ -760,6 +779,14 @@ local function mergeMainMods(env, repSlotName, repItem)
end
end
end
if override.toggleFlask then
if env.flasks[override.toggleFlask] then
env.flasks[override.toggleFlask] = nil
else
env.flasks[override.toggleFlask] = true
end
end
if env.mode == "MAIN" then
-- Process extra skills granted by items
@@ -844,7 +871,7 @@ local function mergeMainMods(env, repSlotName, repItem)
end
-- Build and merge modifiers for allocated passives
env.modDB:AddList(buildNodeModList(env, build.spec.allocNodes, true))
env.modDB:AddList(buildNodeModList(env, nodes, true))
-- Determine main skill group
if env.mode == "CALCS" then
@@ -1015,6 +1042,15 @@ local function performCalcs(env)
end
end
-- Merge flask modifiers
if env.mode_combat then
local effectInc = modDB:Sum("INC", nil, "FlaskEffect")
for item in pairs(env.flasks) do
modDB.conditions["UsingFlask"] = true
modDB:ScaleAddList(item.modList, 1 + (effectInc + item.flaskData.effectInc) / 100)
end
end
-- Set conditions
local condList = modDB.conditions
if env.weaponData1.type == "Staff" then
@@ -1538,7 +1574,7 @@ local function performCalcs(env)
output.EvadeChance = 0
else
local enemyAccuracy = round(calcVal(enemyDB, "Accuracy"))
output.EvadeChance = 100 - calcHitChance(output.Evasion, enemyAccuracy)
output.EvadeChance = 100 - calcHitChance(output.Evasion, enemyAccuracy) * calcMod(enemyDB, nil, "HitChance")
if breakdown then
breakdown.EvadeChance = {
s_format("Enemy level: %d ^8(%s the Configuration tab)", env.enemyLevel, env.configInput.enemyLevel and "overridden from" or "can be overridden in"),
@@ -2894,11 +2930,12 @@ end
local calcs = { }
-- Get calculator for tree node modifiers
-- Get fast calculator for adding tree node modifiers
function calcs.getNodeCalculator(build)
return getCalculator(build, true, function(env, nodeList, remove)
-- Build and merge/unmerge modifiers for these nodes
local nodeModList = buildNodeModList(env, nodeList)
return getCalculator(build, true, function(env, nodeList)
-- Build and merge modifiers for these nodes
env.modDB:AddList(buildNodeModList(env, nodeList))
--[[local nodeModList = buildNodeModList(env, nodeList)
if remove then
for _, mod in ipairs(nodeModList) do
if mod.type == "LIST" or mod.type == "FLAG" then
@@ -2916,15 +2953,14 @@ function calcs.getNodeCalculator(build)
end
else
env.modDB:AddList(nodeModList)
end
end]]
end)
end
-- Get calculator for item modifiers
function calcs.getItemCalculator(build)
return getCalculator(build, false, function(env, repSlotName, repItem)
-- Merge main mods, replacing the item in the given slot with the given item
mergeMainMods(env, repSlotName, repItem)
-- Get calculator for other changes (adding/removing nodes, items, gems, etc)
function calcs.getMiscCalculator(build)
return getCalculator(build, false, function(env, override)
mergeMainMods(env, override)
end)
end

View File

@@ -450,45 +450,41 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum)
local durationInc = sumLocal(modList, "Duration", "INC", 0)
if item.base.flask.life or item.base.flask.mana then
-- Recovery flask
flaskData.instantPerc = sumLocal(modList, "FlaskInstantRecovery", "BASE", 0)
local recoveryMod = 1 + sumLocal(modList, "FlaskRecovery", "INC", 0) / 100
local rateMod = 1 + sumLocal(modList, "FlaskRecoveryRate", "INC", 0) / 100
local instant = sumLocal(modList, "FlaskInstantRecovery", "BASE", 0)
local durBase = item.base.flask.duration * (1 + durationInc / 100)
flaskData.duration = item.base.flask.duration * (1 + durationInc / 100) / rateMod
if item.base.flask.life then
local base = item.base.flask.life * (1 + item.quality / 100) * recoveryMod
local inst = base * instant / 100
local grad = base * (1 - instant / 100) * (1 + durationInc / 100)
flaskData.lifeTotal = inst + grad
flaskData.lifeDuration = durBase / rateMod
flaskData.lifeBase = item.base.flask.life * (1 + item.quality / 100) * recoveryMod
flaskData.lifeInstant = flaskData.lifeBase * flaskData.instantPerc / 100
flaskData.lifeGradual = flaskData.lifeBase * (1 - flaskData.instantPerc / 100) * (1 + durationInc / 100)
flaskData.lifeTotal = flaskData.lifeInstant + flaskData.lifeGradual
end
if item.base.flask.mana then
local base = item.base.flask.mana * (1 + item.quality / 100) * recoveryMod
local inst = base * instant / 100
local grad = base * (1 - instant / 100) * (1 + durationInc / 100)
flaskData.manaTotal = inst + grad
flaskData.manaDuration = durBase / rateMod
flaskData.manaBase = item.base.flask.mana * (1 + item.quality / 100) * recoveryMod
flaskData.manaInstant = flaskData.manaBase * flaskData.instantPerc / 100
flaskData.manaGradual = flaskData.manaBase * (1 - flaskData.instantPerc / 100) * (1 + durationInc / 100)
flaskData.manaTotal = flaskData.manaInstant + flaskData.manaGradual
end
else
-- Utility flask
flaskData.duration = round(item.base.flask.duration * (1 + (durationInc + item.quality) / 100), 1)
flaskData.duration = item.base.flask.duration * (1 + (durationInc + item.quality) / 100)
end
local extra = sumLocal(modList, "FlaskCharges", "BASE", 0)
local usedInc = sumLocal(modList, "FlaskChargesUsed", "INC", 0)
local gainedInc = sumLocal(modList, "FlaskChargeRecovery", "INC", 0)
flaskData.chargesMax = item.base.flask.chargesMax + extra
flaskData.chargesUsed = m_floor(item.base.flask.chargesUsed * (1 + usedInc / 100))
flaskData.gainMod = 1 + gainedInc / 100
flaskData.chargesMax = item.base.flask.chargesMax + sumLocal(modList, "FlaskCharges", "BASE", 0)
flaskData.chargesUsed = m_floor(item.base.flask.chargesUsed * (1 + sumLocal(modList, "FlaskChargesUsed", "INC", 0) / 100))
flaskData.gainMod = 1 + sumLocal(modList, "FlaskChargeRecovery", "INC", 0) / 100
flaskData.effectInc = sumLocal(modList, "FlaskEffect", "INC", 0)
for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do
if value.type == "FlaskData" then
flaskData[value.key] = value.value
end
end
elseif item.type == "Jewel" then
item.jewelFunc = nil
item.jewelFuncList = nil
for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do
if value.type == "JewelFunc" then
item.jewelFunc = item.jewelFunc or { }
t_insert(item.jewelFunc, value.func)
item.jewelFuncList = item.jewelFuncList or { }
t_insert(item.jewelFuncList, value.func)
end
end
end

View File

@@ -126,7 +126,10 @@ function main:Init()
self:OpenPopup(800, 250, "Update Available", {
common.New("TextListControl", nil, 0, 20, 780, 190, nil, changeList),
common.New("ButtonControl", nil, -45, 220, 80, 20, "Update", function()
launch:ApplyUpdate(launch.updateAvailable)
local ret = self:CallMode("CanExit", "UPDATE")
if ret == nil or ret == true then
launch:ApplyUpdate(launch.updateAvailable)
end
main:ClosePopup()
end),
common.New("ButtonControl", nil, 45, 220, 80, 20, "Cancel", function()
@@ -204,7 +207,7 @@ function main:Init()
end
function main:CanExit()
local ret = self:CallMode("CanExit")
local ret = self:CallMode("CanExit", "EXIT")
if ret ~= nil then
return ret
else

View File

@@ -111,6 +111,7 @@ local modNameList = {
-- Stun modifiers
["stun recovery"] = "StunRecovery",
["stun and block recovery"] = "StunRecovery",
["block and stun recovery"] = "StunRecovery",
["stun threshold"] = "StunThreshold",
["block recovery"] = "BlockRecovery",
["enemy stun threshold"] = "EnemyStunThreshold",
@@ -236,6 +237,8 @@ local modNameList = {
["effect"] = "FlaskEffect",
["effect of flasks"] = "FlaskEffect",
["amount recovered"] = "FlaskRecovery",
["life recovered"] = "FlaskRecovery",
["mana recovered"] = "FlaskRecovery",
["life recovery from flasks"] = "FlaskLifeRecovery",
["mana recovery from flasks"] = "FlaskManaRecovery",
["flask effect duration"] = "FlaskDuration",
@@ -397,10 +400,13 @@ local modTagList = {
["if you've crit recently"] = { tag = { type = "Condition", var = "CritRecently" } },
["if you've dealt a critical strike recently"] = { tag = { type = "Condition", var = "CritRecently" } },
["if you haven't crit recently"] = { tag = { type = "Condition", var = "CritRecently", neg = true } },
["if you've dealt a non%-critical strike recently"] = { tag = { type = "Condition", var = "NonCritRecently" } },
["if you've killed recently"] = { tag = { type = "Condition", var = "KilledRecently" } },
["if you haven't killed recently"] = { tag = { type = "Condition", var = "KilledRecently", neg = true } },
["if you or your totems have killed recently"] = { tag = { type = "Condition", varList = {"KilledRecently","TotemsKilledRecently"} } },
["if you've killed a maimed enemy recently"] = { tagList = { { type = "Condition", var = "KilledRecently" }, { type = "Condition", var = "EnemyMaimed" } } },
["if you've frozen an enemy recently"] = { tag = { type = "Condition", var = "FrozenEnemyRecently" } },
["if you've ignited an enemy recently"] = { tag = { type = "Condition", var = "IgnitedEnemyRecently" } },
["if you've been hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } },
["if you were hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } },
["if you were damaged by a hit recently"] = { tag = { type = "Condition", var = "BeenHitRecently" } },
@@ -428,6 +434,7 @@ local modTagList = {
["against bleeding enemies"] = { tag = { type = "Condition", var = "EnemyBleeding" }, flags = ModFlag.Hit },
["against poisoned enemies"] = { tag = { type = "Condition", var = "EnemyPoisoned" }, flags = ModFlag.Hit },
["against hindered enemies"] = { tag = { type = "Condition", var = "EnemyHindered" }, flags = ModFlag.Hit },
["against blinded enemies"] = { tag = { type = "Condition", var = "EnemyBlinded" }, flags = ModFlag.Hit },
["against burning enemies"] = { tag = { type = "Condition", var = "EnemyBurning" }, flags = ModFlag.Hit },
["against ignited enemies"] = { tag = { type = "Condition", var = "EnemyIgnited" }, flags = ModFlag.Hit },
["against shocked enemies"] = { tag = { type = "Condition", var = "EnemyShocked" }, flags = ModFlag.Hit },
@@ -541,6 +548,9 @@ local specialModList = {
["your critical strike chance is lucky"] = { flag("CritChanceLucky") },
["phasing"] = { mod("Misc", "LIST", { type = "Condition", var = "Phasing" }) },
["onslaught"] = { mod("Misc", "LIST", { type = "Condition", var = "Onslaught" }) },
["creates a smoke cloud on use"] = { },
["creates chilled ground on use"] = { },
["creates consecrated ground on use"] = { },
-- Special item local modifiers
["no physical damage"] = { mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMin" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMax" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalDPS" }) },
["all attacks with this weapon are critical strikes"] = { mod("Misc", "LIST", { type = "WeaponData", key = "critChance", value = 100 }) },
@@ -622,6 +632,7 @@ local specialModList = {
["non%-critical strikes deal (%d+)%% damage"] = function(num) return { mod("Damage", "MORE", -100+num, nil, ModFlag.Hit, { type = "Condition", var = "CriticalStrike", neg = true }) } end,
["ignited enemies burn (%d+)%% faster"] = function(num) return { mod("IgniteBurnRate", "INC", num) } end,
["enemies ignited by an attack burn (%d+)%% faster"] = function(num) return { mod("IgniteBurnRate", "INC", num, nil, ModFlag.Attack) } end,
["gain unholy might during flask effect"] = { mod("Misc", "LIST", { type = "Condition", var = "UnholyMight" }, { type = "Condition", var = "UsingFlask" }) },
}
local keystoneList = {
-- List of keystones that can be found on uniques