diff --git a/spec/System/TestGeneratedUniques_spec.lua b/spec/System/TestGeneratedUniques_spec.lua new file mode 100644 index 00000000000..a68f5935bbc --- /dev/null +++ b/spec/System/TestGeneratedUniques_spec.lua @@ -0,0 +1,33 @@ +describe("Generated uniques", function() + local function findGeneratedItem(name) + for _, itemText in ipairs(data.uniques.generated) do + if itemText:sub(1, #name + 1) == name .. "\n" then + return itemText + end + end + end + + it("includes weapon-legal Catarina veiled mods on Cane of Kulemak", function() + local cane = findGeneratedItem("Cane of Kulemak") + assert.is_not_nil(cane) + assert.is_not_nil(cane:find("+2 to Level of Socketed Support Gems", 1, true)) + assert.is_not_nil(cane:find("+(5-8)% to Quality of Socketed Support Gems", 1, true)) + assert.is_not_nil(cane:find("chance to Explode", 1, true)) + end) + + it("excludes weapon-illegal Catarina veiled mods from Cane of Kulemak", function() + local cane = findGeneratedItem("Cane of Kulemak") + assert.is_not_nil(cane) + assert.is_nil(cane:find("maximum number of Spectres", 1, true)) + assert.is_nil(cane:find("Minions are Aggressive", 1, true)) + end) + + it("does not add Catarina signature mods to Paradoxica or Replica Paradoxica", function() + for _, name in ipairs({ "Paradoxica", "Replica Paradoxica" }) do + local item = findGeneratedItem(name) + assert.is_not_nil(item) + assert.is_nil(item:find("to Quality of Socketed Support Gems", 1, true)) + assert.is_nil(item:find("chance to Explode", 1, true)) + end + end) +end) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index dfdc865eb20..f7382e66613 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -424,6 +424,7 @@ c["+12% to Fire Damage over Time Multiplier with Attack Skills"]={{[1]={flags=0, c["+12% to Fire and Cold Resistances"]={{[1]={flags=0,keywordFlags=0,name="FireResist",type="BASE",value=12},[2]={flags=0,keywordFlags=0,name="ColdResist",type="BASE",value=12}},nil} c["+12% to Fire and Lightning Resistances"]={{[1]={flags=0,keywordFlags=0,name="FireResist",type="BASE",value=12},[2]={flags=0,keywordFlags=0,name="LightningResist",type="BASE",value=12}},nil} c["+12% to Melee Critical Strike Multiplier"]={{[1]={flags=256,keywordFlags=0,name="CritMultiplier",type="BASE",value=12}},nil} +c["+12% to Quality of Socketed Support Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="quality",keyword="support",value=12}}},nil} c["+12% to all Elemental Resistances"]={{[1]={flags=0,keywordFlags=0,name="ElementalResist",type="BASE",value=12}},nil} c["+12% to all Elemental Resistances for each Empty White Socket on any Equipped Item"]={{[1]={[1]={type="Multiplier",var="EmptyWhiteSocketsInAnySlot"},flags=0,keywordFlags=0,name="ElementalResist",type="BASE",value=12}},nil} c["+120 Energy Shield gained on Killing a Shocked Enemy"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="Shocked"},flags=0,keywordFlags=0,name="EnergyShieldOnKill",type="BASE",value=120}},nil} @@ -917,6 +918,7 @@ c["+3 to Level of Socketed Fire Gems"]={{[1]={[1]={slotName="{SlotName}",type="S c["+3 to Level of Socketed Golem Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyword="golem",value=3}}},nil} c["+3 to Level of Socketed Lightning Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyword="lightning",value=3}}},nil} c["+3 to Level of Socketed Minion Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyword="minion",value=3}}},nil} +c["+3 to Level of Socketed Support Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyword="support",value=3}}},nil} c["+3 to Level of Socketed Warcry Gems"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyword="warcry",value=3}}},nil} c["+3 to Level of all Absolution Gems"]={{[1]={flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyOfScaledMod="value",keyword="absolution",value=3}}},nil} c["+3 to Level of all Alchemist's Mark Gems"]={{[1]={flags=0,keywordFlags=0,name="GemProperty",type="LIST",value={key="level",keyOfScaledMod="value",keyword="alchemist's mark",value=3}}},nil} @@ -3262,6 +3264,7 @@ c["145 to 200 Added Cold Damage with Bow Attacks"]={{[1]={flags=131076,keywordFl c["145% increased Evasion and Energy Shield"]={{[1]={flags=0,keywordFlags=0,name="EvasionAndEnergyShield",type="INC",value=145}},nil} c["145% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=145}},nil} c["146% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=146}},nil} +c["148% increased Spell Damage"]={{[1]={flags=2,keywordFlags=0,name="Damage",type="INC",value=148}},nil} c["15 to 289 Added Lightning Damage with Wand Attacks"]={{[1]={flags=8388612,keywordFlags=0,name="LightningMin",type="BASE",value=15},[2]={flags=8388612,keywordFlags=0,name="LightningMax",type="BASE",value=289}},nil} c["15% Chance to Block Attack Damage"]={{[1]={flags=0,keywordFlags=0,name="BlockChance",type="BASE",value=15}},nil} c["15% Chance to Block Spell Damage"]={{[1]={flags=0,keywordFlags=0,name="SpellBlockChance",type="BASE",value=15}},nil} @@ -6563,6 +6566,7 @@ c["85% increased Spell Damage"]={{[1]={flags=2,keywordFlags=0,name="Damage",type c["85% less Ward during Effect"]={{[1]={[1]={type="Condition",var="UsingFlask"},flags=0,keywordFlags=0,name="Ward",type="MORE",value=-85}},nil} c["88% increased Damage with Poison if you have at least 300 Dexterity"]={{[1]={[1]={stat="Dex",threshold=300,type="StatThreshold"},flags=0,keywordFlags=2097152,name="Damage",type="INC",value=88}},nil} c["88% increased Physical Damage"]={{[1]={flags=0,keywordFlags=0,name="PhysicalDamage",type="INC",value=88}},nil} +c["89% increased Spell Damage"]={{[1]={flags=2,keywordFlags=0,name="Damage",type="INC",value=89}},nil} c["9 to 15 Added Physical Damage with Bow Attacks"]={{[1]={flags=131076,keywordFlags=0,name="PhysicalMin",type="BASE",value=9},[2]={flags=131076,keywordFlags=0,name="PhysicalMax",type="BASE",value=15}},nil} c["9% Chance to Block Attack Damage"]={{[1]={flags=0,keywordFlags=0,name="BlockChance",type="BASE",value=9}},nil} c["9% Chance to Block Spell Damage"]={{[1]={flags=0,keywordFlags=0,name="SpellBlockChance",type="BASE",value=9}},nil} @@ -8623,6 +8627,8 @@ c["Enemies you Kill during Effect have a 25% chance to Explode, dealing a tenth c["Enemies you Kill during Effect have a 30% chance to Explode, dealing a tenth of their maximum Life as Damage of a Random Element"]={{[1]={[1]={type="Condition",var="UsingFlask"},flags=0,keywordFlags=0,name="ExplodeMod",type="LIST",value={amount=10,chance=0.3,keyOfScaledMod="chance",type="RandomElement"}},[2]={flags=0,keywordFlags=0,name="CanExplode",type="FLAG",value=true}},nil} c["Enemies you Kill have a 10% chance to Explode, dealing a quarter of their maximum Life as Chaos Damage"]={{[1]={flags=0,keywordFlags=0,name="ExplodeMod",type="LIST",value={amount=25,chance=0.1,keyOfScaledMod="chance",type="Chaos"}},[2]={flags=0,keywordFlags=0,name="CanExplode",type="FLAG",value=true}},nil} c["Enemies you Kill have a 20% chance to Explode, dealing a quarter of their maximum Life as Chaos Damage"]={{[1]={flags=0,keywordFlags=0,name="ExplodeMod",type="LIST",value={amount=25,chance=0.2,keyOfScaledMod="chance",type="Chaos"}},[2]={flags=0,keywordFlags=0,name="CanExplode",type="FLAG",value=true}},nil} +c["Enemies you Kill have a 25% chance to Explode, dealing a quarter of their maximum Life as Chaos Damage"]={{[1]={flags=0,keywordFlags=0,name="ExplodeMod",type="LIST",value={amount=25,chance=0.25,keyOfScaledMod="chance",type="Chaos"}},[2]={flags=0,keywordFlags=0,name="CanExplode",type="FLAG",value=true}},nil} +c["Enemies you Kill have a 35% chance to Explode, dealing a quarter of their maximum Life as Chaos Damage"]={{[1]={flags=0,keywordFlags=0,name="ExplodeMod",type="LIST",value={amount=25,chance=0.35,keyOfScaledMod="chance",type="Chaos"}},[2]={flags=0,keywordFlags=0,name="CanExplode",type="FLAG",value=true}},nil} c["Enemies you Kill that are affected by Elemental Ailments"]={nil,"Enemies you Kill that are affected by Elemental Ailments "} c["Enemies you Kill that are affected by Elemental Ailments grant 100% increased Flask Charges"]={nil,"Enemies you Kill that are affected by Elemental Ailments grant 100% increased Flask Charges "} c["Enemies you Kill that are affected by Elemental Ailments grant 40% increased Flask Charges"]={nil,"Enemies you Kill that are affected by Elemental Ailments grant 40% increased Flask Charges "} @@ -11561,7 +11567,9 @@ c["Socketed Curse Gems have 30% increased Reservation Efficiency"]={{[1]={[1]={k c["Socketed Curse Gems have 50% increased Reservation Efficiency"]={{[1]={[1]={keyword="curse",slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSkillMod",type="LIST",value={mod={flags=0,keywordFlags=0,name="ReservationEfficiency",type="INC",value=50}}}},nil} c["Socketed Curse Gems have 80% increased Reservation Efficiency"]={{[1]={[1]={keyword="curse",slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSkillMod",type="LIST",value={mod={flags=0,keywordFlags=0,name="ReservationEfficiency",type="INC",value=80}}}},nil} c["Socketed Gems Cost and Reserve Life instead of Mana"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportBloodMagicUniquePrismGuardian"}}},nil} +c["Socketed Gems are Supported by Level 1 Arcane Surge"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportArcaneSurge"}}},nil} c["Socketed Gems are Supported by Level 1 Arrow Nova"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportArrowNova"}}},nil} +c["Socketed Gems are Supported by Level 1 Cast While Channelling"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportCastWhileChannelling"}},[2]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportCastWhileChannellingTriggered"}}},nil} c["Socketed Gems are Supported by Level 1 Elemental Penetration"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportElementalPenetration"}}},nil} c["Socketed Gems are Supported by Level 1 Generosity"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportGenerosity"}}},nil} c["Socketed Gems are Supported by Level 1 Greater Spell Echo"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportGreaterSpellEcho"}}},nil} @@ -12039,6 +12047,7 @@ c["Socketed Gems are Supported by Level 5 Cold to Fire"]={{[1]={[1]={slotName="{ c["Socketed Gems are Supported by Level 5 Concentrated Effect"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=5,skillId="SupportConcentratedEffect"}}},nil} c["Socketed Gems are Supported by Level 5 Elemental Proliferation"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=5,skillId="SupportElementalProliferation"}}},nil} c["Socketed Gems are Supported by Level 8 Trap"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=8,skillId="SupportTrap"}}},nil} +c["Socketed Gems are supported by Level 1 Cast On Critical Strike"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportCastOnCriticalStrike"}},[2]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportCastOnCritTriggered"}}},nil} c["Socketed Gems are supported by Level 1 Chance to Bleed"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportChanceToBleed"}}},nil} c["Socketed Gems are supported by Level 1 Multistrike"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=1,skillId="SupportMultistrike"}}},nil} c["Socketed Gems are supported by Level 10 Blind"]={{[1]={[1]={slotName="{SlotName}",type="SocketedIn"},flags=0,keywordFlags=0,name="ExtraSupport",type="LIST",value={level=10,skillId="SupportBlind"}}},nil} diff --git a/src/Data/Uniques/Special/Generated.lua b/src/Data/Uniques/Special/Generated.lua index 72fb68e188e..007222a3abc 100644 --- a/src/Data/Uniques/Special/Generated.lua +++ b/src/Data/Uniques/Special/Generated.lua @@ -18,17 +18,22 @@ local parseVeiledModName = function(string) gsub("(%d)", " %1 ")) end -local veiledModIsActive = function(mod, baseType, specificType1, specificType2) +local veiledModIsActive = function(mod, baseType, specificType1, specificType2, poolKey) local baseIndex = isValueInTable(mod.weightKey, baseType) local typeIndex1 = isValueInTable(mod.weightKey, specificType1) local typeIndex2 = isValueInTable(mod.weightKey, specificType2) + -- Master signature mods (e.g. Catarina's) carry their weight on a pool key such as "catarina_veiled_prefix" + -- and only list the slots they are excluded from, so the pool key only applies when no slot key matched + local poolIndex = poolKey and isValueInTable(mod.weightKey, poolKey) return (typeIndex1 and mod.weightVal[typeIndex1] > 0) or (typeIndex2 and mod.weightVal[typeIndex2] > 0) or (not typeIndex1 and not typeIndex2 and baseIndex and mod.weightVal[baseIndex] > 0) + or (not typeIndex1 and not typeIndex2 and not baseIndex and poolIndex and mod.weightVal[poolIndex] > 0) end local getVeiledMods = function (veiledPool, baseType, specificType1, specificType2) local veiledMods = { } + local poolKey = veiledPool == "catarina" and "catarina_veiled_prefix" or nil for veiledModIndex, veiledMod in pairs(data.veiledMods) do - if veiledModIsActive(veiledMod, baseType, specificType1, specificType2) then + if veiledModIsActive(veiledMod, baseType, specificType1, specificType2, poolKey) then local veiledName = parseVeiledModName(veiledModIndex) veiledName = "("..veiledMod.type..") "..veiledName @@ -112,9 +117,9 @@ local caneOfKulemak = { "Has Alt Variant Two: true", "Has Alt Variant Three: true", "Selected Variant: 1", - "Selected Alt Variant: 2", - "Selected Alt Variant Two: 20", - "Selected Alt Variant Three: 21", + "Selected Alt Variant: 3", + "Selected Alt Variant Two: 25", + "Selected Alt Variant Three: 26", } for _, mod in pairs(caneOfKulemakMods) do