diff --git a/config.lua.dist b/config.lua.dist index cd0d063d566..d68cea72088 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -91,6 +91,16 @@ maxContainerDepth = 200 maxInboxItems = 0 maxExivaWhitelist = 100 +-- Player base critical +-- NOTE: 0.05 means 5% +playerBaseCriticalChance = 0.05 +-- NOTE: 0.1 means 10% +playerBaseCriticalDamage = 0.1 + +-- Weapon Proficiency +weaponProficiencyMaxLevels = 10 +weaponProficiencyMaxPerksPerLevel = 6 + -- Animus Mastery - SoulPit (Get more info in: https://github.com/opentibiabr/canary/pull/3230) -- NOTE: animusMasteryMaxMonsterXpMultiplier is the maximum experience the multiplier can be. -- NOTE: animusMasteryMonsterXpMultiplier is the monster experience multiplier that has the animus mastery unlocked. diff --git a/data-canary/scripts/actions/objects/imbuement_shrine.lua b/data-canary/scripts/actions/objects/imbuement_shrine.lua index 3d3d7ded8fe..3182d2903ad 100644 --- a/data-canary/scripts/actions/objects/imbuement_shrine.lua +++ b/data-canary/scripts/actions/objects/imbuement_shrine.lua @@ -5,11 +5,7 @@ function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotke return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You did not collect enough knowledge from the ancient Shapers. Visit the Shaper temple in Montag for help.") end - if not target or type(target) ~= "userdata" or not target:isItem() then - return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use the shrine on an valid item.") - end - - player:openImbuementWindow(target) + player:openImbuementWindow() return true end diff --git a/data-otservbr-global/monster/bosses/the_brainstealer.lua b/data-otservbr-global/monster/bosses/the_brainstealer.lua index 3e425f356f4..5efd0a36145 100644 --- a/data-otservbr-global/monster/bosses/the_brainstealer.lua +++ b/data-otservbr-global/monster/bosses/the_brainstealer.lua @@ -60,7 +60,7 @@ monster.loot = { { name = "crystal coin", mincount = 1, maxcount = 5, chance = 100000 }, { name = "violet gem", chance = 50000 }, { name = "mastermind potion", chance = 50000 }, - { name = "transcendence potion", chance = 50000 }, + { id = 49271, chance = 50000 }, -- transcendence potion { name = "moonstone", chance = 50000 }, { name = "ultimate spirit potion", chance = 50000 }, { name = "white gem", chance = 50000 }, diff --git a/data-otservbr-global/monster/bosses/the_monster.lua b/data-otservbr-global/monster/bosses/the_monster.lua index 8d2fae4728d..00d06820330 100644 --- a/data-otservbr-global/monster/bosses/the_monster.lua +++ b/data-otservbr-global/monster/bosses/the_monster.lua @@ -63,7 +63,7 @@ monster.loot = { { name = "ultimate mana potion", chance = 24300, maxcount = 5 }, { name = "ultimate spirit potion", chance = 25750, maxcount = 4 }, { name = "mastermind potion", chance = 23200, maxcount = 3 }, - { name = "transcendence potion", chance = 23200, maxcount = 3 }, + { id = 49271, chance = 23200, maxcount = 3 }, -- transcendence potion { name = "berserk potion", chance = 24800, maxcount = 3 }, { name = "bullseye potion", chance = 23500, maxcount = 3 }, { name = "yellow gem", chance = 26200, maxcount = 5 }, diff --git a/data-otservbr-global/monster/dawnport/dawnfly.lua b/data-otservbr-global/monster/dawnport/dawnfly.lua index 240be3c7934..eb193bfb355 100644 --- a/data-otservbr-global/monster/dawnport/dawnfly.lua +++ b/data-otservbr-global/monster/dawnport/dawnfly.lua @@ -64,6 +64,7 @@ monster.loot = { { id = 3379, chance = 4140 }, -- doublet { id = 17458, chance = 11940 }, -- damselfly wing { id = 17463, chance = 10130 }, -- damselfly eye + { id = 50166, chance = 3140 }, -- simple jo staff { id = 3031, chance = 100000, maxCount = 12 }, -- gold coin { id = 266, chance = 3630 }, -- health potion { id = 268, chance = 3800 }, -- mana potion diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua index ee57d52bee9..1614cdbb91d 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua @@ -82,7 +82,7 @@ monster.loot = { { name = "ultimate spirit potion", chance = 23530, maxCount = 6 }, { name = "bullseye potion", chance = 19610, maxCount = 10 }, { name = "mastermind potion", chance = 19610, maxCount = 10 }, - { name = "transcendence potion", chance = 19610, maxCount = 10 }, + { id = 49271, chance = 19610, maxCount = 10 }, -- transcendence potion { name = "death toll", chance = 13730, maxCount = 2 }, { name = "ivory comb", chance = 13730 }, { name = "angel figurine", chance = 11760 }, diff --git a/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua index 3e533bfe73d..35eb001bc48 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua @@ -83,7 +83,7 @@ monster.loot = { { name = "ultimate spirit potion", chance = 23530, maxCount = 6 }, { name = "bullseye potion", chance = 19610, maxCount = 10 }, { name = "mastermind potion", chance = 19610, maxCount = 10 }, - { name = "transcendence potion", chance = 19610, maxCount = 10 }, + { id = 49271, chance = 19610, maxCount = 10 }, -- transcendence potion { name = "death toll", chance = 13730, maxCount = 2 }, { name = "ivory comb", chance = 13730 }, { name = "angel figurine", chance = 11760 }, diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua index 3c4ef786844..e572b73b1ee 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua @@ -84,7 +84,7 @@ monster.loot = { { name = "ultimate spirit potion", minCount = 0, maxCount = 20, chance = 32000 }, { name = "bullseye potion", minCount = 0, maxCount = 10, chance = 12000 }, { name = "mastermind potion", minCount = 0, maxCount = 10, chance = 12000 }, - { name = "transcendence potion", minCount = 0, maxCount = 10, chance = 12000 }, + { id = 49271, minCount = 0, maxCount = 10, chance = 12000 }, -- transcendence potion { name = "silver token", minCount = 0, maxCount = 2, chance = 8000 }, { name = "blue gem", chance = 9000 }, { id = 23542, chance = 5200 }, -- collar of blue plasma diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua index 1c43518dfd0..0493594de34 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua @@ -87,7 +87,7 @@ monster.loot = { { name = "bullseye potion", minCount = 0, maxCount = 10, chance = 12000 }, { name = "mastermind potion", minCount = 0, maxCount = 10, chance = 12000 }, { name = "berserk potion", minCount = 0, maxCount = 10, chance = 12000 }, - { name = "transcendence potion", minCount = 0, maxCount = 10, chance = 12000 }, + { id = 49271, minCount = 0, maxCount = 10, chance = 12000 }, -- transcendence potion { name = "piece of draconian steel", minCount = 0, maxCount = 3, chance = 9000 }, { id = 3039, minCount = 0, maxCount = 2, chance = 12000 }, -- red gem { name = "silver token", minCount = 0, maxCount = 2, chance = 9500 }, diff --git a/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua index 827df3f786d..41490c66126 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua @@ -91,7 +91,7 @@ monster.loot = { { name = "berserk potion", chance = 20300, maxCount = 10 }, { name = "blue gem", chance = 18500, maxCount = 2 }, { name = "bullseye potion", chance = 18500, maxCount = 10 }, - { name = "transcendence potion", chance = 18500, maxCount = 10 }, + { id = 49271, chance = 18500, maxCount = 10 }, -- transcendence potion { name = "magma coat", chance = 16600 }, { name = "terra rod", chance = 1100 }, { name = "crystal coin", chance = 9200 }, diff --git a/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua b/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua index 942faab3f4f..e895195f520 100644 --- a/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua +++ b/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua @@ -67,7 +67,7 @@ monster.loot = { { name = "berserk potion", chance = 22449, maxCount = 5 }, { name = "mastermind potion", chance = 18367, maxCount = 5 }, { name = "naga basin", chance = 12245 }, - { name = "transcendence potion", chance = 18367, maxCount = 5 }, + { id = 49271, chance = 18367, maxCount = 5 }, -- transcendence potion { name = "piece of timira's sensors", chance = 10204 }, { name = "giant amethyst", chance = 6122 }, { name = "giant ruby", chance = 4082 }, diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua index bf5734d7346..92bc5b9d832 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua @@ -76,7 +76,7 @@ monster.loot = { { name = "bullseye potion", chance = 24490, maxCount = 5 }, { name = "berserk potion", chance = 22449, maxCount = 5 }, { name = "mastermind potion", chance = 18367, maxCount = 5 }, - { name = "transcendence potion", chance = 18367, maxCount = 5 }, + { id = 49271, chance = 18367, maxCount = 5 }, -- transcendence potion { name = "giant amethyst", chance = 6122 }, { name = "giant ruby", chance = 4082 }, { name = "giant emerald", chance = 4082 }, diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua index c23ae24688c..f493b8e4eda 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua @@ -86,7 +86,7 @@ monster.loot = { { name = "dragon figurine", chance = 10000, maxCount = 1 }, { name = "bullseye potion", chance = 15000, minCount = 10, maxCount = 25 }, { name = "mastermind potion", chance = 15000, minCount = 10, maxCount = 25 }, - { name = "transcendence potion", chance = 15000, minCount = 10, maxCount = 25 }, + { id = 49271, chance = 15000, minCount = 10, maxCount = 25 }, -- transcendence potion { name = "berserk potion", chance = 15000, minCount = 10, maxCount = 25 }, { name = "ultimate mana potion", chance = 18000, minCount = 50, maxCount = 100 }, { name = "supreme health potion", chance = 18000, minCount = 50, maxCount = 100 }, diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua index d3fb6ce897b..509b057c974 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua @@ -86,7 +86,7 @@ monster.loot = { { name = "dragon figurine", chance = 10000, maxCount = 1 }, { name = "bullseye potion", chance = 15000, minCount = 10, maxCount = 25 }, { name = "mastermind potion", chance = 15000, minCount = 10, maxCount = 25 }, - { name = "transcendence potion", chance = 15000, minCount = 10, maxCount = 25 }, + { id = 49271, chance = 15000, minCount = 10, maxCount = 25 }, -- transcendence potion { name = "berserk potion", chance = 15000, minCount = 10, maxCount = 25 }, { name = "ultimate mana potion", chance = 18000, minCount = 50, maxCount = 100 }, { name = "supreme health potion", chance = 18000, minCount = 50, maxCount = 100 }, diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua index 89d59d49428..2b6c41b48e6 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua @@ -98,7 +98,7 @@ monster.loot = { { name = "huge chunk of crude iron", chance = 42860 }, { name = "magic sulphur", chance = 3570 }, { name = "mastermind potion", chance = 42860, maxCount = 6 }, - { name = "transcendence potion", chance = 42860, maxCount = 6 }, + { id = 49271, chance = 42860, maxCount = 6 }, -- transcendence potion { name = "maxxenius head", chance = 7140 }, { name = "mysterious remains", chance = 85710 }, { name = "ornate locket", chance = 14290 }, diff --git a/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua index ae5b39b6176..022077ff18d 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua @@ -103,7 +103,7 @@ monster.loot = { { name = "magic sulphur", chance = 8490 }, { name = "mastermind potion", chance = 12900, maxCount = 18 }, { name = "mysterious remains", chance = 93400 }, - { name = "transcendence potion", chance = 12900, maxCount = 18 }, + { id = 49271, chance = 12900, maxCount = 18 }, -- transcendence potion { name = "piggy bank", chance = 100000 }, { name = "piggy bank", chance = 94340 }, { name = "platinum coin", chance = 100000, maxCount = 9 }, diff --git a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua index 91ae9642b48..d5884d3d82b 100644 --- a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua +++ b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua @@ -93,7 +93,7 @@ monster.loot = { { name = "royal star", chance = 31325, maxCount = 100 }, { name = "bullseye potion", chance = 22590, maxCount = 10 }, { name = "berserk potion", chance = 21988, maxCount = 10 }, - { name = "transcendence potion", chance = 21988, maxCount = 10 }, + { id = 49271, chance = 21988, maxCount = 10 }, -- transcendence potion { name = "blue gem", chance = 21687, maxCount = 2 }, { name = "mastermind potion", chance = 17771, maxCount = 10 }, { name = "green gem", chance = 17470, maxCount = 2 }, diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua index 26be31879ea..1fd53524b96 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua @@ -84,7 +84,7 @@ monster.loot = { { name = "yellow gem", chance = 90000 }, { name = "wand of voodoo", chance = 90000 }, { name = "mastermind potion", chance = 30000, maxCount = 2 }, - { name = "transcendence potion", chance = 30000, maxCount = 2 }, + { id = 49271, chance = 30000, maxCount = 2 }, -- transcendence potion { name = "onyx chip", chance = 30000, maxCount = 12 }, { name = "small diamond", chance = 30000, maxCount = 12 }, { name = "small emerald", chance = 30000, maxCount = 12 }, diff --git a/data-otservbr-global/monster/vermins/emerald_damselfly.lua b/data-otservbr-global/monster/vermins/emerald_damselfly.lua index f0f03317f62..c3d29489301 100644 --- a/data-otservbr-global/monster/vermins/emerald_damselfly.lua +++ b/data-otservbr-global/monster/vermins/emerald_damselfly.lua @@ -79,6 +79,7 @@ monster.loot = { { name = "arrow", chance = 7570, maxCount = 5 }, { name = "health potion", chance = 3580 }, { name = "mana potion", chance = 3550 }, + { id = 50166, chance = 3140 }, -- simple jo staff { id = 17458, chance = 11830 }, -- damselfly wing { id = 17463, chance = 9970 }, -- damselfly eye } diff --git a/data-otservbr-global/npc/albinius.lua b/data-otservbr-global/npc/albinius.lua index 57106ef9df0..c3279e1b622 100644 --- a/data-otservbr-global/npc/albinius.lua +++ b/data-otservbr-global/npc/albinius.lua @@ -273,6 +273,17 @@ keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "Precisely time." }) keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I find ways to unveil the secrets of the stars. Judging by this question, I doubt you follow my weekly publications concerning this research." }) +npcConfig.shop = { + { itemName = "blank imbuement scroll", clientId = 51442, buy = 25000 }, + { itemName = "etcher", clientId = 51443, buy = 30000 } +} + +npcType.onSellItem = function(npc, player, itemId, subtype, amount, ignore, name, totalCost) + player:sendTextMessage(MESSAGE_TRADE, string.format("Sold %ix %s for %i gold.", amount, name, totalCost)) +end + +npcType.onCheckItem = function(npc, player, clientId, subType) end + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/blue_valley/enpa-deia_pema.lua b/data-otservbr-global/npc/blue_valley/enpa-deia_pema.lua index 5a3e72b1cb6..e50e3de6af1 100644 --- a/data-otservbr-global/npc/blue_valley/enpa-deia_pema.lua +++ b/data-otservbr-global/npc/blue_valley/enpa-deia_pema.lua @@ -40,6 +40,7 @@ npcConfig.shop = { -- Sellable items { itemName = "legs of enlightenment", clientId = 50269, buy = 40000, sell = 400 }, { itemName = "nunchaku of enlightenment", clientId = 50273, buy = 50000, sell = 500 }, { itemName = "plain monk robe", clientId = 50257, buy = 450 }, + { itemName = "simple jo staff", clientId = 50166, buy = 10 }, { itemName = "robe of enlightenment", clientId = 50268, buy = 150000, sell = 150 }, { itemName = "sais of enlightenment", clientId = 50272, buy = 100000, sell = 100 }, } diff --git a/data-otservbr-global/scripts/actions/object/etcher.lua b/data-otservbr-global/scripts/actions/object/etcher.lua new file mode 100644 index 00000000000..c3ac356494a --- /dev/null +++ b/data-otservbr-global/scripts/actions/object/etcher.lua @@ -0,0 +1,26 @@ +local etcher = Action() + +function etcher.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not item or not item:isItem() then + return false + end + + if not target or not target:isItem() then + return false + end + + local clearImbuements = player:clearAllImbuements(target) + + if clearImbuements then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have cleared all imbuements from the item.") + item:remove(1) + player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) + else + player:sendCancelMessage("This item has no imbuements to clear.") + end + + return true +end + +etcher:id(51443) +etcher:register() diff --git a/data-otservbr-global/scripts/actions/object/greater_proficiency_catalyst.lua b/data-otservbr-global/scripts/actions/object/greater_proficiency_catalyst.lua new file mode 100644 index 00000000000..385061b2570 --- /dev/null +++ b/data-otservbr-global/scripts/actions/object/greater_proficiency_catalyst.lua @@ -0,0 +1 @@ +createProficiencyCatalyst(51589, 100000) diff --git a/data-otservbr-global/scripts/actions/object/imbuement_scrolls.lua b/data-otservbr-global/scripts/actions/object/imbuement_scrolls.lua new file mode 100644 index 00000000000..d7355947949 --- /dev/null +++ b/data-otservbr-global/scripts/actions/object/imbuement_scrolls.lua @@ -0,0 +1,32 @@ +local imbuement = Action() + +function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not item or not item:isItem() then + return true + end + + if not target or not target:isItem() then + return true + end + + if target:getType():getImbuementSlot() <= 0 then + player:sendCancelMessage("This item is not imbuable.") + return true + end + + player:applyImbuementScroll(target, item) + + return true +end + +-- Register Powerful Scrolls +for scrollId = 51444, 51467 do + imbuement:id(scrollId) +end + +-- Register Intricate Scrolls +for scrollId = 51724, 51747 do + imbuement:id(scrollId) +end + +imbuement:register() diff --git a/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua b/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua index 5cec0f7506d..fe6754a2f43 100644 --- a/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua +++ b/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua @@ -5,11 +5,7 @@ function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotke return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You did not collect enough knowledge from the ancient Shapers. Visit the Shaper temple in Thais for help.") end - if type(target) ~= "userdata" or not target:isItem() then - return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use the shrine on an valid item.") - end - - player:openImbuementWindow(target) + player:openImbuementWindow() return true end diff --git a/data-otservbr-global/scripts/actions/object/proficiency_catalyst.lua b/data-otservbr-global/scripts/actions/object/proficiency_catalyst.lua new file mode 100644 index 00000000000..520ac7dbfca --- /dev/null +++ b/data-otservbr-global/scripts/actions/object/proficiency_catalyst.lua @@ -0,0 +1 @@ +createProficiencyCatalyst(51588, 25000) diff --git a/data/XML/imbuements.xml b/data/XML/imbuements.xml index 539cd48c2c6..b0cec87c7af 100644 --- a/data/XML/imbuements.xml +++ b/data/XML/imbuements.xml @@ -35,6 +35,7 @@ + @@ -42,6 +43,7 @@ + @@ -53,6 +55,7 @@ + @@ -60,6 +63,7 @@ + @@ -71,6 +75,7 @@ + @@ -78,6 +83,7 @@ + @@ -89,6 +95,7 @@ + @@ -96,6 +103,7 @@ + @@ -107,6 +115,7 @@ + @@ -114,6 +123,7 @@ + @@ -126,6 +136,7 @@ + @@ -133,6 +144,7 @@ + @@ -145,6 +157,7 @@ + @@ -152,6 +165,7 @@ + @@ -164,6 +178,7 @@ + @@ -171,6 +186,7 @@ + @@ -183,6 +199,7 @@ + @@ -190,6 +207,7 @@ + @@ -201,6 +219,7 @@ + @@ -208,6 +227,7 @@ + @@ -219,6 +239,7 @@ + @@ -226,6 +247,7 @@ + @@ -237,6 +259,7 @@ + @@ -244,6 +267,7 @@ + @@ -255,6 +279,7 @@ + @@ -262,6 +287,7 @@ + @@ -273,6 +299,7 @@ + @@ -280,6 +307,7 @@ + @@ -292,6 +320,7 @@ + @@ -299,6 +328,7 @@ + @@ -311,6 +341,7 @@ + @@ -318,6 +349,7 @@ + @@ -329,6 +361,7 @@ + @@ -336,24 +369,27 @@ + - + - + + - + + @@ -365,6 +401,7 @@ + @@ -372,6 +409,7 @@ + @@ -383,6 +421,7 @@ + @@ -390,6 +429,7 @@ + @@ -401,6 +441,7 @@ + @@ -408,6 +449,7 @@ + @@ -417,15 +459,17 @@ - - + + + - - - + + + + @@ -433,17 +477,19 @@ - + + - + + diff --git a/data/XML/mounts.xml b/data/XML/mounts.xml index 68f2165c6f1..0b41c5d770e 100644 --- a/data/XML/mounts.xml +++ b/data/XML/mounts.xml @@ -235,4 +235,5 @@ + diff --git a/data/XML/outfits.xml b/data/XML/outfits.xml index b869746de34..87f51013eb3 100644 --- a/data/XML/outfits.xml +++ b/data/XML/outfits.xml @@ -125,6 +125,8 @@ + + @@ -251,4 +253,6 @@ + + diff --git a/data/items/appearances.dat b/data/items/appearances.dat index 86d860fc414..d2b56f3bf1c 100644 Binary files a/data/items/appearances.dat and b/data/items/appearances.dat differ diff --git a/data/items/items.xml b/data/items/items.xml index 7e973c4ddd5..ec95ad222c8 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -35991,6 +35991,13 @@ + + + + + + + @@ -57254,7 +57261,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -75573,7 +75579,7 @@ Granted by TibiaGoals.com"/> - + @@ -75605,7 +75611,7 @@ Granted by TibiaGoals.com"/> - + @@ -75637,7 +75643,7 @@ Granted by TibiaGoals.com"/> - + @@ -75669,7 +75675,7 @@ Granted by TibiaGoals.com"/> - + @@ -75701,7 +75707,7 @@ Granted by TibiaGoals.com"/> - + @@ -75733,7 +75739,7 @@ Granted by TibiaGoals.com"/> - + @@ -75763,7 +75769,7 @@ Granted by TibiaGoals.com"/> - + @@ -75792,7 +75798,7 @@ Granted by TibiaGoals.com"/> - + @@ -75821,7 +75827,7 @@ Granted by TibiaGoals.com"/> - + @@ -75850,7 +75856,7 @@ Granted by TibiaGoals.com"/> - + @@ -75879,7 +75885,7 @@ Granted by TibiaGoals.com"/> - + @@ -75908,7 +75914,7 @@ Granted by TibiaGoals.com"/> - + @@ -75963,7 +75969,7 @@ Granted by TibiaGoals.com"/> - + @@ -75995,7 +76001,7 @@ Granted by TibiaGoals.com"/> - + @@ -76027,7 +76033,7 @@ Granted by TibiaGoals.com"/> - + @@ -76059,7 +76065,7 @@ Granted by TibiaGoals.com"/> - + @@ -76113,11 +76119,11 @@ Granted by TibiaGoals.com"/> - - + + - + @@ -76154,11 +76160,11 @@ Granted by TibiaGoals.com"/> - - + + - + @@ -76224,11 +76230,11 @@ Granted by TibiaGoals.com"/> - - + + - + @@ -76265,11 +76271,11 @@ Granted by TibiaGoals.com"/> - - + + - + @@ -76583,7 +76589,7 @@ Granted by TibiaGoals.com"/> - + @@ -76748,7 +76754,7 @@ Granted by TibiaGoals.com"/> - + @@ -76806,7 +76812,7 @@ Granted by TibiaGoals.com"/> - + @@ -76822,11 +76828,11 @@ Granted by TibiaGoals.com"/> - - + + - + @@ -77241,7 +77247,7 @@ Granted by TibiaGoals.com"/> - + @@ -77272,7 +77278,7 @@ Granted by TibiaGoals.com"/> - + @@ -77333,7 +77339,7 @@ Granted by TibiaGoals.com"/> - + @@ -77524,7 +77530,7 @@ Granted by TibiaGoals.com"/> - + @@ -80402,10 +80408,14 @@ Granted by TibiaGoals.com"/> - + + + + + + - @@ -81949,7 +81959,7 @@ Granted by TibiaGoals.com"/> - + @@ -81997,7 +82007,7 @@ Granted by TibiaGoals.com"/> - + @@ -82043,7 +82053,7 @@ Granted by TibiaGoals.com"/> - + @@ -83073,7 +83083,7 @@ Granted by TibiaGoals.com"/> - + @@ -83105,7 +83115,7 @@ Granted by TibiaGoals.com"/> - + @@ -83278,7 +83288,7 @@ Granted by TibiaGoals.com"/> - + @@ -83286,6 +83296,7 @@ Granted by TibiaGoals.com"/> + @@ -83441,7 +83452,7 @@ Granted by TibiaGoals.com"/> - + @@ -83938,7 +83949,7 @@ Granted by TibiaGoals.com"/> - + @@ -84108,6 +84119,9 @@ Granted by TibiaGoals.com"/> + + + @@ -84189,7 +84203,7 @@ Granted by TibiaGoals.com"/> - + @@ -84236,7 +84250,7 @@ Granted by TibiaGoals.com"/> - + @@ -84266,7 +84280,7 @@ Granted by TibiaGoals.com"/> - + @@ -84289,7 +84303,7 @@ Granted by TibiaGoals.com"/> - + @@ -84302,8 +84316,8 @@ Granted by TibiaGoals.com"/> - - + + @@ -84471,7 +84485,7 @@ Granted by TibiaGoals.com"/> - + @@ -84518,6 +84532,246 @@ Granted by TibiaGoals.com"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -84659,9 +84913,292 @@ Granted by TibiaGoals.com"/> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/items/proficiencies.json b/data/items/proficiencies.json new file mode 100644 index 00000000000..34f54dd5827 --- /dev/null +++ b/data/items/proficiencies.json @@ -0,0 +1,26281 @@ +[ + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 1H Sword", + "ProficiencyId": 6, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 1H Axe", + "ProficiencyId": 8, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 1H Club", + "ProficiencyId": 9, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Sword", + "ProficiencyId": 10, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Axe", + "ProficiencyId": 11, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Club", + "ProficiencyId": 12, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + }, + { + "AugmentType": 14, + "SpellId": 124, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 124, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 124, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 124, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 124, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Bow", + "ProficiencyId": 13, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 294, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 294, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 294, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 294, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 294, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Fist", + "ProficiencyId": 14, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.1 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.1 + }, + { + "Type": 12, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 13, + "Type": 5, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 24, + "Type": 5, + "Value": 0.125 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.04 + }, + { + "AugmentType": 2, + "SpellId": 24, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 8, + "Type": 9, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 1H Wand", + "ProficiencyId": 15, + "Version": 9 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.1 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 120, + "Type": 5, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 118, + "Type": 5, + "Value": 0.125 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.04 + }, + { + "AugmentType": 2, + "SpellId": 118, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 64, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 84, + "Type": 5, + "Value": 0.06 + }, + { + "Type": 16, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 1H Rod", + "ProficiencyId": 16, + "Version": 12 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 1H Axe", + "ProficiencyId": 17, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 1H Club", + "ProficiencyId": 18, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 1H Sword", + "ProficiencyId": 19, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Sword", + "ProficiencyId": 20, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Club", + "ProficiencyId": 21, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 105, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 105, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 105, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 5.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Axe", + "ProficiencyId": 22, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + }, + { + "AugmentType": 14, + "SpellId": 124, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 124, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 124, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 124, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 124, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Bow", + "ProficiencyId": 23, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 294, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 294, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 294, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 294, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 294, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Fist", + "ProficiencyId": 24, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.1 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 120, + "Type": 5, + "Value": 0.08 + }, + { + "AugmentType": 16, + "SpellId": 118, + "Type": 5, + "Value": 0.25 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.08 + }, + { + "AugmentType": 2, + "SpellId": 118, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 64, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 84, + "Type": 5, + "Value": 0.06 + }, + { + "Type": 16, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 1H Rod", + "ProficiencyId": 25, + "Version": 12 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.1 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.1 + }, + { + "Type": 12, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 13, + "Type": 5, + "Value": 0.08 + }, + { + "AugmentType": 16, + "SpellId": 24, + "Type": 5, + "Value": 0.25 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.08 + }, + { + "AugmentType": 2, + "SpellId": 24, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 2 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 8, + "Type": 9, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 1H Wand", + "ProficiencyId": 26, + "Version": 9 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 1H Axe", + "ProficiencyId": 27, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 1H Club", + "ProficiencyId": 28, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 1H Sword", + "ProficiencyId": 29, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 261, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 261, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Sword", + "ProficiencyId": 30, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 261, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 261, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Club", + "ProficiencyId": 31, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 261, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 261, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 261, + "Type": 5, + "Value": 0.2 + }, + { + "Type": 11, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 261, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 261, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Axe", + "ProficiencyId": 32, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 14, + "SpellId": 288, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 15, + "SpellId": 288, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 288, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 288, + "Type": 5, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.075 + }, + { + "AugmentType": 17, + "SpellId": 288, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Fist", + "ProficiencyId": 33, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 20 + }, + { + "Range": 4, + "Type": 22, + "Value": 10 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.75 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 1 + }, + { + "SkillId": 7, + "Type": 3, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 1.25 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.08 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Bow", + "ProficiencyId": 34, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.075 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 263, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 16, + "Value": 0.02 + }, + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 263, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 10, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 2 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.05 + }, + { + "Type": 16, + "Value": 0.02 + }, + { + "Type": 14, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 1H Rod", + "ProficiencyId": 35, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "ElementId": 256, + "Type": 13, + "Value": 0.075 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 260, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.05 + }, + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "ElementId": 256, + "Type": 9, + "Value": 0.015 + }, + { + "AugmentType": 16, + "SpellId": 260, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 10, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "DamageType": 256, + "Type": 4, + "Value": 2 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "Type": 14, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 1H Wand", + "ProficiencyId": 36, + "Version": 10 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 1H Sword", + "ProficiencyId": 37, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 1H Axe", + "ProficiencyId": 38, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 1H Club", + "ProficiencyId": 39, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 2H Club", + "ProficiencyId": 40, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 2H Axe", + "ProficiencyId": 41, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -6.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 62, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 62, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Amber 2H Sword", + "ProficiencyId": 42, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 293, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 293, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 293, + "Type": 5, + "Value": -4.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 293, + "Type": 5, + "Value": 0.07 + }, + { + "AugmentType": 14, + "SpellId": 293, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 293, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 293, + "Type": 5, + "Value": -8.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 293, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.25 + } + ] + } + ], + "Name": "Amber 2H Fist", + "ProficiencyId": 43, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.125 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 258, + "Type": 5, + "Value": 0.06 + }, + { + "AugmentType": 14, + "SpellId": 258, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.125 + }, + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 258, + "Type": 5, + "Value": 0.06 + }, + { + "AugmentType": 14, + "SpellId": 258, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 258, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 6, + "SpellId": 258, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 258, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 2 + } + ] + } + ], + "Name": "Amber 2H Bow", + "ProficiencyId": 44, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 27, + "Value": 0.08 + }, + { + "Type": 14, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.01 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 43, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 43, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Amber 1H Rod", + "ProficiencyId": 45, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.04 + }, + { + "Type": 14, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.01 + }, + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.01 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 119, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 119, + "Type": 5, + "Value": 0.5 + } + ] + } + ], + "Name": "Amber 1H Wand", + "ProficiencyId": 46, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 1H Club", + "ProficiencyId": 47, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 1H Axe", + "ProficiencyId": 48, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 1H Sword", + "ProficiencyId": 49, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 2H Club", + "ProficiencyId": 50, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 2H Axe", + "ProficiencyId": 51, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 2H Sword", + "ProficiencyId": 52, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 289, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 289, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 289, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 2H Fist", + "ProficiencyId": 53, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 57, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.01 + }, + { + "AugmentType": 15, + "SpellId": 57, + "Type": 5, + "Value": 0.03 + } + ] + } + ], + "Name": "Inferniarch 2H Distance", + "ProficiencyId": 54, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 154, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 154, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 15, + "SpellId": 154, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Inferniarch 1H Wand", + "ProficiencyId": 55, + "Version": 10 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 157, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 157, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 15, + "SpellId": 157, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Inferniarch 1H Rod", + "ProficiencyId": 56, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Club", + "ProficiencyId": 57, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Axe", + "ProficiencyId": 58, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Sword", + "ProficiencyId": 59, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 1H Club", + "ProficiencyId": 60, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 1H Axe", + "ProficiencyId": 61, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 1H Sword", + "ProficiencyId": 62, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 289, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 289, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 11, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 289, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Fist", + "ProficiencyId": 63, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 57, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 57, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 14, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 10, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Bow", + "ProficiencyId": 64, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 154, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 154, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 154, + "Type": 5, + "Value": 0.2 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Rending Inferniarch 1H Wand", + "ProficiencyId": 65, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 157, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 157, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 157, + "Type": 5, + "Value": 0.2 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Rending Inferniarch 1H Rod", + "ProficiencyId": 66, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Club", + "ProficiencyId": 67, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Axe", + "ProficiencyId": 68, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Sword", + "ProficiencyId": 69, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 1H Club", + "ProficiencyId": 70, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 1H Axe", + "ProficiencyId": 71, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 1H Sword", + "ProficiencyId": 72, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 289, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 289, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 11, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 289, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Fist", + "ProficiencyId": 73, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 57, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 57, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 14, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 10, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Bow", + "ProficiencyId": 74, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 157, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 157, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 14, + "SpellId": 157, + "Type": 5, + "Value": 0.4 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Draining Inferniarch 1H Rod", + "ProficiencyId": 75, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 154, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 154, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 14, + "SpellId": 154, + "Type": 5, + "Value": 0.4 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Draining Inferniarch 1H Wand", + "ProficiencyId": 76, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Club", + "ProficiencyId": 77, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Axe", + "ProficiencyId": 78, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Sword", + "ProficiencyId": 79, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 1H Club", + "ProficiencyId": 80, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 1H Axe", + "ProficiencyId": 81, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 80, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 80, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 1H Sword", + "ProficiencyId": 82, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 289, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 289, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 11, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 289, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Fist", + "ProficiencyId": 83, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 154, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 154, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 154, + "Type": 5, + "Value": 0.4 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Siphoning Inferniarch 1H Wand", + "ProficiencyId": 84, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 157, + "Type": 5, + "Value": -8.0 + }, + { + "AugmentType": 17, + "SpellId": 157, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 157, + "Type": 5, + "Value": 0.4 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Siphoning Inferniarch 1H Rod", + "ProficiencyId": 85, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 57, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 57, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 14, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + }, + { + "Type": 10, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Bow", + "ProficiencyId": 86, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Eldritch 2H Club", + "ProficiencyId": 87, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 1.0 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Eldritch 2H Axe", + "ProficiencyId": 88, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Eldritch 2H Sword", + "ProficiencyId": 89, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.125 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Eldritch 2H Fist", + "ProficiencyId": 90, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Range": 2, + "Type": 22, + "Value": 12 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + }, + { + "Range": 4, + "Type": 22, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Range": 1, + "Type": 22, + "Value": 24 + }, + { + "ElementId": 128, + "Type": 9, + "Value": 0.015 + }, + { + "Range": 4, + "Type": 22, + "Value": 16 + } + ] + } + ], + "Name": "Eldritch 2H Distance", + "ProficiencyId": 91, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.035 + }, + { + "AugmentType": 3, + "SpellId": 84, + "Type": 5, + "Value": 0.04 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.07 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.015 + } + ] + } + ], + "Name": "Eldritch 1H Rod", + "ProficiencyId": 92, + "Version": 9 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "DamageType": 256, + "Type": 4, + "Value": 1 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.035 + }, + { + "AugmentType": 16, + "SpellId": 240, + "Type": 5, + "Value": 0.05 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.07 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.015 + } + ] + } + ], + "Name": "Eldritch 1H Wand", + "ProficiencyId": 93, + "Version": 9 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 1.5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.12 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.02 + } + ] + } + ], + "Name": "Gilded Eldritch 2H Club", + "ProficiencyId": 94, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 1.5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 1.0 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.12 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.02 + } + ] + } + ], + "Name": "Gilded Eldritch 2H Axe", + "ProficiencyId": 95, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 1.5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.12 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.02 + } + ] + } + ], + "Name": "Gilded Eldritch 2H Sword", + "ProficiencyId": 96, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.125 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 2 + } + ] + } + ], + "Name": "Gilded Eldritch 2H Fist", + "ProficiencyId": 97, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Range": 2, + "Type": 22, + "Value": 12 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + }, + { + "Range": 4, + "Type": 22, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 16, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Range": 1, + "Type": 22, + "Value": 24 + }, + { + "ElementId": 128, + "Type": 9, + "Value": 0.02 + }, + { + "Range": 4, + "Type": 22, + "Value": 16 + } + ] + } + ], + "Name": "Gilded Eldritch 2H Distance", + "ProficiencyId": 98, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "DamageType": 256, + "Type": 4, + "Value": 1 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 240, + "Type": 5, + "Value": 0.075 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.075 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.02 + } + ] + } + ], + "Name": "Gilded Eldritch 1H Wand", + "ProficiencyId": 99, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + }, + { + "AugmentType": 3, + "SpellId": 84, + "Type": 5, + "Value": 0.06 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 10, + "Value": 0.02 + } + ] + } + ], + "Name": "Gilded Eldritch 1H Rod", + "ProficiencyId": 100, + "Version": 9 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 1H Club", + "ProficiencyId": 101, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 1H Axe", + "ProficiencyId": 102, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 1H Sword", + "ProficiencyId": 103, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Club", + "ProficiencyId": 104, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Axe", + "ProficiencyId": 105, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Sword", + "ProficiencyId": 106, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Fist", + "ProficiencyId": 107, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Bow", + "ProficiencyId": 108, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 1H Club", + "ProficiencyId": 109, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 1H Axe", + "ProficiencyId": 110, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 1H Sword", + "ProficiencyId": 111, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 2H Club", + "ProficiencyId": 112, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 2H Axe", + "ProficiencyId": 113, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 2H Sword", + "ProficiencyId": 114, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 2H Fist", + "ProficiencyId": 115, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 1H Club", + "ProficiencyId": 117, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 1H Axe", + "ProficiencyId": 118, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 1H Sword", + "ProficiencyId": 119, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.16 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 2H Club", + "ProficiencyId": 120, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.16 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 2H Axe", + "ProficiencyId": 121, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.16 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 2H Sword", + "ProficiencyId": 122, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.16 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.15 + } + ] + } + ], + "Name": "Master Umbral 2H Fist", + "ProficiencyId": 123, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 21, + "Value": 40 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Master Umbral 2H Bow", + "ProficiencyId": 124, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 24, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 2.0 + } + ] + } + ], + "Name": "Throw - Small Stone", + "ProficiencyId": 125, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.04 + } + ] + } + ], + "Name": "Throw - Snowball", + "ProficiencyId": 126, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + } + ], + "Name": "Throw - Spear", + "ProficiencyId": 127, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 4 + } + ] + } + ], + "Name": "Throw - Throwing Star", + "ProficiencyId": 128, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 4 + } + ] + } + ], + "Name": "Throw - Throwing Knife", + "ProficiencyId": 129, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 7 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Umbral 2H Bow", + "ProficiencyId": 130, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Throw - Hunting Spear", + "ProficiencyId": 131, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.01 + } + ] + } + ], + "Name": "Throw - Viper Star", + "ProficiencyId": 132, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 4 + } + ] + } + ], + "Name": "Throw - Enchanted Spear", + "ProficiencyId": 133, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 16 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "SkillId": 9, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 1H Club", + "ProficiencyId": 134, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 16 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "SkillId": 10, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 1H Axe", + "ProficiencyId": 135, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 16 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "SkillId": 8, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 1H Sword", + "ProficiencyId": 136, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 287, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 287, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 287, + "Type": 5, + "Value": 0.01 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "SkillId": 11, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 2H Fist", + "ProficiencyId": 137, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "Range": 4, + "Type": 22, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 122, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 19, + "Value": 5 + }, + { + "AugmentType": 15, + "SpellId": 122, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 122, + "Type": 5, + "Value": 0.02 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 2H Distance", + "ProficiencyId": 138, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + }, + { + "AugmentType": 14, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 1H Club", + "ProficiencyId": 139, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + }, + { + "AugmentType": 14, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 1H Axe", + "ProficiencyId": 140, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + }, + { + "AugmentType": 14, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 1H Sword", + "ProficiencyId": 141, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.13 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.06 + }, + { + "AugmentType": 14, + "SpellId": 287, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 15, + "SpellId": 287, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 287, + "Type": 5, + "Value": 0.01 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 11, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 2H Fist", + "ProficiencyId": 142, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.05 + }, + { + "Range": 1, + "Type": 22, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 122, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 10 + }, + { + "AugmentType": 14, + "SpellId": 122, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 122, + "Type": 5, + "Value": 0.02 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 2H Distance", + "ProficiencyId": 143, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 15, + "Value": 0.025 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.06 + }, + { + "SkillId": 6, + "Type": 27, + "Value": 0.14 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 1H Club", + "ProficiencyId": 144, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 26, + "Value": 0.14 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.025 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.06 + }, + { + "SkillId": 6, + "Type": 27, + "Value": 0.14 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 2H Sword", + "ProficiencyId": 145, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.025 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 59, + "Type": 5, + "Value": -2.0 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.06 + }, + { + "SkillId": 6, + "Type": 27, + "Value": 0.14 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 2H Axe", + "ProficiencyId": 146, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 26, + "Value": 0.15 + }, + { + "SkillId": 6, + "Type": 27, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 287, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 287, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 287, + "Type": 5, + "Value": 0.01 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.05 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 2H Fist", + "ProficiencyId": 147, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.08 + }, + { + "Range": 6, + "Type": 22, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 122, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 12, + "Value": 0.025 + }, + { + "AugmentType": 15, + "SpellId": 122, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 122, + "Type": 5, + "Value": 0.02 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.05 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 2H Distance", + "ProficiencyId": 148, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + } + ] + } + ], + "Name": "Throw - Assassin Star", + "ProficiencyId": 149, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.04 + } + ] + } + ], + "Name": "Throw - Royal Spear", + "ProficiencyId": 150, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.05 + }, + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 153, + "Type": 5, + "Value": -4.0 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + }, + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 153, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 1H Rod", + "ProficiencyId": 151, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.05 + }, + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.01 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 23, + "Type": 5, + "Value": 0.01 + }, + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Cobra 1H Wand", + "ProficiencyId": 152, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.05 + }, + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + }, + { + "DamageType": 16, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 43, + "Type": 5, + "Value": 0.01 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 1H Rod", + "ProficiencyId": 153, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.05 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 6, + "SpellId": 150, + "Type": 5, + "Value": -4.0 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "AugmentType": 16, + "SpellId": 150, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Lion 1H Wand", + "ProficiencyId": 154, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 20 + }, + { + "AugmentType": 17, + "SpellId": 120, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 1.0 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.5 + }, + { + "DamageType": 16, + "Type": 4, + "Value": 1 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 1H Rod", + "ProficiencyId": 155, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + }, + { + "Type": 21, + "Value": 20 + }, + { + "AugmentType": 17, + "SpellId": 13, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 1.0 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.5 + }, + { + "DamageType": 32, + "Type": 4, + "Value": 1 + }, + { + "BestiaryId": 3, + "BestiaryName": "Bird", + "Type": 6, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.05 + } + ] + } + ], + "Name": "Falcon 1H Wand", + "ProficiencyId": 156, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.0025 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.0025 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.0025 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.0025 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.005 + } + ] + } + ], + "Name": "Throw - Glooth Spear", + "ProficiencyId": 157, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.005 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.04 + } + ] + } + ], + "Name": "Throw - Leaf Star", + "ProficiencyId": 158, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Throw - Royal Star", + "ProficiencyId": 159, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.5 + } + ] + } + ], + "Name": "Sword 1H Ice Rapier", + "ProficiencyId": 161, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 169, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 169, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 169, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 169, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Carving Caster", + "ProficiencyId": 162, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 270, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 270, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 270, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 270, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Carving Distance", + "ProficiencyId": 163, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Carving Club", + "ProficiencyId": 164, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Carving Axe", + "ProficiencyId": 165, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Carving Sword", + "ProficiencyId": 166, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 169, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 169, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 169, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 169, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Mayhem Caster", + "ProficiencyId": 177, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 270, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 270, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 270, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 270, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Mayhem Distance", + "ProficiencyId": 178, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 271, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Mayhem Club", + "ProficiencyId": 179, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 271, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Mayhem Axe", + "ProficiencyId": 180, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 271, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Mayhem Sword", + "ProficiencyId": 181, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 169, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 169, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 169, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 169, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Remedy Caster", + "ProficiencyId": 192, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 270, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 270, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 270, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 270, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Remedy Distance", + "ProficiencyId": 193, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Remedy Club", + "ProficiencyId": 194, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Remedy Axe", + "ProficiencyId": 195, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Replica Remedy Sword", + "ProficiencyId": 196, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 2H Club", + "ProficiencyId": 207, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 1H Club", + "ProficiencyId": 208, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 1H Axe", + "ProficiencyId": 209, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 1H Sword", + "ProficiencyId": 210, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 2H Axe", + "ProficiencyId": 211, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 2H Sword", + "ProficiencyId": 212, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Destruction 2H Fist", + "ProficiencyId": 213, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + } + ], + "Name": "Destruction 1H Rod", + "ProficiencyId": 214, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.035 + } + ] + } + ], + "Name": "Destruction 2H Distance", + "ProficiencyId": 215, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + }, + { + "Type": 14, + "Value": 0.025 + } + ] + } + ], + "Name": "Destruction 1H Wand", + "ProficiencyId": 216, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.02 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + }, + { + "ElementId": 8, + "Type": 9, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 1.0 + } + ] + } + ], + "Name": "Caster 1H Energized Limb", + "ProficiencyId": 217, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Sword 1H Templar Scytheblade", + "ProficiencyId": 218, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 1H Sword Class 1", + "ProficiencyId": 219, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.075 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.075 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 26, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.03 + } + ] + } + ], + "Name": "Caster 1H Deepling Fork", + "ProficiencyId": 220, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 23, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 14, + "SpellId": 121, + "Type": 5, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 23, + "Type": 5, + "Value": 0.025 + }, + { + "AugmentType": 14, + "SpellId": 121, + "Type": 5, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Caster 1H Deepling Ceremonial Dagger", + "ProficiencyId": 221, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 88, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 112, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.025 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.01 + }, + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 88, + "Type": 5, + "Value": 0.015 + }, + { + "AugmentType": 17, + "SpellId": 112, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Caster 1H Dream Blossom Staff", + "ProficiencyId": 222, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Axe Class 1", + "ProficiencyId": 223, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 1H Axe Class 1", + "ProficiencyId": 224, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Sword Class 1", + "ProficiencyId": 225, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Club Class 1", + "ProficiencyId": 226, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 1H Club Class 1", + "ProficiencyId": 227, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 2, + "Type": 22, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.04 + }, + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Distance", + "ProficiencyId": 228, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Fist Class 1", + "ProficiencyId": 229, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 18, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Caster", + "ProficiencyId": 230, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Silver Dagger", + "ProficiencyId": 231, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Serpent Sword", + "ProficiencyId": 232, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Poison Dagger", + "ProficiencyId": 233, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Machete", + "ProficiencyId": 234, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.015 + } + ] + } + ], + "Name": "Sword 1H Heavy Machete", + "ProficiencyId": 235, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Bone Sword", + "ProficiencyId": 236, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 4, + "BestiaryName": "Construct", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Axe 2H Golden Axe", + "ProficiencyId": 237, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 158, + "Type": 5, + "Value": -150.0 + }, + { + "Type": 2, + "Value": 1 + }, + { + "SkillId": 8, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 80, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 80, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 1H Magic Sword", + "ProficiencyId": 238, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 10 + } + ] + } + ], + "Name": "Sword 1H Crimson Sword", + "ProficiencyId": 239, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + } + ], + "Name": "Sword 1H Assassin Dagger", + "ProficiencyId": 240, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 14 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 141, + "Type": 5, + "Value": -10.0 + } + ] + } + ], + "Name": "Sword 1H Bloody Edge", + "ProficiencyId": 241, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.25 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.25 + }, + { + "SkillId": 11, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 8, + "BestiaryName": "Fey", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.5 + }, + { + "Type": 0, + "Value": 2 + } + ] + } + ], + "Name": "Sword 1H Mumpiz Slayer", + "ProficiencyId": 242, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 4, + "BestiaryName": "Construct", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Club 1H Crowbar", + "ProficiencyId": 243, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 19, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 61, + "Type": 5, + "Value": 0.25 + } + ] + } + ], + "Name": "Club 1H Gluttons Mace", + "ProficiencyId": 244, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.15 + } + ] + } + ], + "Name": "Club 1H Club Of The Fury", + "ProficiencyId": 245, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Club 1H Stale Bread Of Ancientness", + "ProficiencyId": 246, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 4, + "BestiaryName": "Construct", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Gongs Mallet", + "ProficiencyId": 247, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + }, + { + "SkillId": 11, + "Type": 26, + "Value": 0.08 + } + ] + } + ], + "Name": "Club 1H Banana Staff", + "ProficiencyId": 248, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 27, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 123, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Club 1H Life Preserver", + "ProficiencyId": 249, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.075 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Club 1H Giant Smithhammer", + "ProficiencyId": 250, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 15 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + } + ] + } + ], + "Name": "Naga 1H Axe", + "ProficiencyId": 251, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 15 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.75 + } + ] + } + ], + "Name": "Naga 1H Club", + "ProficiencyId": 252, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 156, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 156, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 156, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 156, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Naga 1H Rod", + "ProficiencyId": 253, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 15 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + } + ] + } + ], + "Name": "Naga 1H Sword", + "ProficiencyId": 254, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 155, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 155, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 155, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 14, + "SpellId": 155, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Naga 1H Wand", + "ProficiencyId": 255, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 3 + }, + { + "Type": 19, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Naga 2H Distance", + "ProficiencyId": 256, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 30 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.12 + } + ] + } + ], + "Name": "Naga 2H Fist", + "ProficiencyId": 257, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.5 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 266, + "Type": 5, + "Value": -3600.0 + }, + { + "AugmentType": 6, + "SpellId": 267, + "Type": 5, + "Value": -3600.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 265, + "Type": 5, + "Value": -3600.0 + }, + { + "AugmentType": 6, + "SpellId": 283, + "Type": 5, + "Value": -3600.0 + }, + { + "AugmentType": 6, + "SpellId": 264, + "Type": 5, + "Value": -3600.0 + } + ] + } + ], + "Name": "Club 1H lich staff", + "ProficiencyId": 258, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 0, + "Value": 2 + }, + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 14, + "BestiaryName": "Mammal", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.15 + } + ] + } + ], + "Name": "Sword 1H Pointed Rabbitslayer", + "ProficiencyId": 259, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 0, + "Value": 3 + }, + { + "Type": 15, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + } + ] + } + ], + "Name": "Sword 1H Poets Fencing Quill\t", + "ProficiencyId": 260, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.05 + }, + { + "DamageType": 64, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + }, + { + "Type": 20, + "Value": 22 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.025 + } + ] + } + ], + "Name": "Jungle 1H Rod", + "ProficiencyId": 261, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.3 + }, + { + "Type": 14, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + }, + { + "Type": 20, + "Value": 22 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.25 + } + ] + } + ], + "Name": "Jungle 1H Wand", + "ProficiencyId": 262, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 25 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 107, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 107, + "Type": 5, + "Value": 0.065 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 107, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Jungle 2H Club", + "ProficiencyId": 263, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 25 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 107, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 107, + "Type": 5, + "Value": 0.065 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 107, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Jungle 1H Axe", + "ProficiencyId": 264, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 7, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + } + ], + "Name": "Jungle 2H Distance", + "ProficiencyId": 265, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Wyvern Fang", + "ProficiencyId": 266, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.04 + }, + { + "Type": 18, + "Value": 10 + } + ] + } + ], + "Name": "Sword 1H Cowtana", + "ProficiencyId": 267, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.07 + }, + { + "Type": 21, + "Value": 21 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.07 + }, + { + "Type": 20, + "Value": 14 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.14 + }, + { + "Type": 0, + "Value": 2 + }, + { + "Type": 15, + "Value": 0.42 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Djinn Blade", + "ProficiencyId": 268, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.4 + }, + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 178, + "Type": 5, + "Value": 0.5 + } + ] + } + ], + "Name": "Wand 1H Scorcher", + "ProficiencyId": 269, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.4 + }, + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 173, + "Type": 5, + "Value": 0.5 + } + ] + } + ], + "Name": "Rod 1H Chiller", + "ProficiencyId": 270, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 5 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 1, + "Type": 5, + "Value": 0.2 + } + ] + } + ], + "Name": "Rod 1H Snakebite Rod", + "ProficiencyId": 271, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 177, + "Type": 5, + "Value": 0.2 + } + ] + } + ], + "Name": "Wand 1H Wand of Vortex", + "ProficiencyId": 272, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 5 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 112, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Rod 1H Moonlight Rod", + "ProficiencyId": 273, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 5 + }, + { + "Type": 18, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 89, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Wand 1H Wand of Dragonbreath", + "ProficiencyId": 274, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Pharao Sword", + "ProficiencyId": 275, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + } + ], + "Name": "Generic 1H Sword Class 2", + "ProficiencyId": 276, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 2 + } + ] + } + ], + "Name": "Generic 1H Caster Class 2", + "ProficiencyId": 277, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 3 + } + ] + } + ], + "Name": "Generic 2H Distance Class 2", + "ProficiencyId": 278, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + } + ], + "Name": "Generic 2H Fist Class 2", + "ProficiencyId": 279, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 2H Axe Class 2", + "ProficiencyId": 280, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + } + ], + "Name": "Generic 2H Club Class 2", + "ProficiencyId": 281, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + } + ], + "Name": "Generic 2H Sword Class 2", + "ProficiencyId": 282, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + }, + { + "Type": 21, + "Value": 5 + } + ] + } + ], + "Name": "Generic 1H Club Class 2", + "ProficiencyId": 283, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "SkillId": 10, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Axe 1H Vile Ornamented Axe", + "ProficiencyId": 284, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 2H Dragon Slayer", + "ProficiencyId": 285, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 4 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 87, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Wand 1H Wand of Decay", + "ProficiencyId": 286, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 4 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + } + ], + "Name": "Rod 1H Necrotic Rod", + "ProficiencyId": 287, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "Type": 7, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 7, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 2H Thaian Sword", + "ProficiencyId": 288, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 9, + "BestiaryName": "Giant", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Sword 2H Giant Sword", + "ProficiencyId": 289, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.1 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 10 + }, + { + "AugmentType": 16, + "SpellId": 89, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Wand 1H Wand of Draconia", + "ProficiencyId": 290, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 5 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 3 + }, + { + "AugmentType": 16, + "SpellId": 112, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + } + ] + } + ], + "Name": "Rod 1H Northwind Rod", + "ProficiencyId": 291, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 13, + "Value": 0.05 + }, + { + "Type": 14, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 22, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.01 + }, + { + "Type": 10, + "Value": 0.01 + } + ] + } + ], + "Name": "Wand 1H Wand of Cosmic Energy", + "ProficiencyId": 292, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.05 + }, + { + "Type": 14, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 113, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + }, + { + "Type": 10, + "Value": 0.01 + } + ] + } + ], + "Name": "Rod 1H Terra Rod", + "ProficiencyId": 293, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Earth Club", + "ProficiencyId": 294, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Earth Axe", + "ProficiencyId": 295, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 16, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Earth Sword", + "ProficiencyId": 296, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Energy Club", + "ProficiencyId": 297, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Energy Axe", + "ProficiencyId": 298, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Energy Sword", + "ProficiencyId": 299, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Ice Club", + "ProficiencyId": 300, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Ice Axe", + "ProficiencyId": 301, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 64, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Ice Sword", + "ProficiencyId": 302, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Fire Club", + "ProficiencyId": 303, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Fire Axe", + "ProficiencyId": 304, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Replica Fire Sword", + "ProficiencyId": 305, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Fire Sword", + "ProficiencyId": 306, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 12, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 2H Havoc Blade", + "ProficiencyId": 307, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 27, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 20 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 2H Avenger", + "ProficiencyId": 308, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.08 + }, + { + "Type": 17, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.12 + }, + { + "Type": 16, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 2H Calamity", + "ProficiencyId": 309, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 9, + "BestiaryName": "Giant", + "Type": 6, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.1 + } + ] + } + ], + "Name": "Sword 2H Magic Longsword", + "ProficiencyId": 310, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 5 + } + ] + } + ], + "Name": "Sword 2H Warlord Sword", + "ProficiencyId": 311, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 19, + "Type": 5, + "Value": 0.05 + }, + { + "Range": 3, + "Type": 22, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 19, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 13, + "Value": 0.05 + } + ] + } + ], + "Name": "Wand 1H Wand of Inferno", + "ProficiencyId": 312, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 112, + "Type": 5, + "Value": 0.025 + }, + { + "ElementId": 64, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 112, + "Type": 5, + "Value": 0.025 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 13, + "Value": 0.05 + } + ] + } + ], + "Name": "Rod 1H Hailstorm Rod", + "ProficiencyId": 313, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.125 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 122, + "Type": 5, + "Value": 0.06 + }, + { + "AugmentType": 14, + "SpellId": 122, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 12 + }, + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 122, + "Type": 5, + "Value": 0.06 + }, + { + "AugmentType": 14, + "SpellId": 122, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 258, + "Type": 5, + "Value": 0.025 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.125 + }, + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "AugmentType": 15, + "SpellId": 122, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 2 + } + ] + } + ], + "Name": "Amber 2H Crossbow", + "ProficiencyId": 315, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 1H Shiny Blade", + "ProficiencyId": 316, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + }, + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 1H The Epiphany", + "ProficiencyId": 317, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 1, + "Type": 22, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 148, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 148, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 9, + "BestiaryName": "Giant", + "Type": 6, + "Value": 0.04 + } + ] + } + ], + "Name": "Rod 1H Ogre Scepta", + "ProficiencyId": 318, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.01 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 13, + "Value": 0.04 + } + ] + } + ], + "Name": "Rod 1H Springsprout Rod", + "ProficiencyId": 319, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 10 + }, + { + "Type": 11, + "Value": 0.1 + }, + { + "Type": 18, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 10 + }, + { + "Type": 15, + "Value": 1.0 + }, + { + "Type": 18, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + } + ], + "Name": "Wand 1H Wand of Dimensions", + "ProficiencyId": 320, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.03 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "Type": 24, + "Value": 1 + } + ] + } + ], + "Name": "Wand 1H Wand of Starstorm", + "ProficiencyId": 321, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "ElementId": 16, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 16, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Rod 1H Muck Rod", + "ProficiencyId": 322, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "ElementId": 64, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 64, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Rod 1H Glacial Rod", + "ProficiencyId": 323, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "ElementId": 32, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 32, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Wand 1H Wand of Defiance", + "ProficiencyId": 324, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "ElementId": 8, + "Type": 9, + "Value": 0.02 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Wand 1H Wand of Everblazing", + "ProficiencyId": 325, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.03 + }, + { + "Type": 20, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.025 + }, + { + "Type": 21, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.03 + } + ] + } + ], + "Name": "Rod 1H Underworld Rod", + "ProficiencyId": 326, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.03 + }, + { + "Type": 18, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 10, + "BestiaryName": "Human", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.03 + } + ] + } + ], + "Name": "Wand 1H Wand of Voodoo", + "ProficiencyId": 327, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 2 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.08 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.08 + } + ] + } + ], + "Name": "Club 2H Brutetamer's Staff", + "ProficiencyId": 328, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + } + ], + "Name": "Club 2H Spiked Squelcher", + "ProficiencyId": 329, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.005 + } + ] + } + ], + "Name": "Club 2H Amber Staff", + "ProficiencyId": 330, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Range": 4, + "Type": 22, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "BestiaryId": 8, + "BestiaryName": "Fey", + "Type": 6, + "Value": 0.025 + } + ] + } + ], + "Name": "Distance 2H Musician's Bow", + "ProficiencyId": 331, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "SkillId": 11, + "Type": 25, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "SkillId": 11, + "Type": 25, + "Value": 0.07 + } + ] + } + ], + "Name": "Club 2H Deepling Staff", + "ProficiencyId": 332, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "Type": 21, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.02 + } + ] + } + ], + "Name": "Distance 2H Elvish Bow", + "ProficiencyId": 333, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + } + ], + "Name": "Axe 2H Deepling Trident", + "ProficiencyId": 334, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 270, + "Type": 5, + "Value": -4.0 + }, + { + "Type": 15, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 270, + "Type": 5, + "Value": 1.0 + }, + { + "AugmentType": 2, + "SpellId": 270, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + } + ], + "Name": "Distance 2H Icicle Bow", + "ProficiencyId": 335, + "Version": 7 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Distance 2H Silkweaver Bow", + "ProficiencyId": 336, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.03 + } + ] + } + ], + "Name": "Axe 1H Deepling Axe", + "ProficiencyId": 337, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 7, + "Type": 22, + "Value": 15 + } + ] + } + ], + "Name": "Distance 2H Warsinger Bow", + "ProficiencyId": 338, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 106, + "Type": 5, + "Value": 0.15 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.1 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Club 1H Silver Mace", + "ProficiencyId": 339, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + }, + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.01 + } + ] + } + ], + "Name": "Distance 2H Composite Hornbow", + "ProficiencyId": 340, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + } + ] + } + ], + "Name": "Club 1H Ornate Mace", + "ProficiencyId": 341, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Club 1H Northern Star", + "ProficiencyId": 342, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 5 + }, + { + "Type": 21, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + } + ], + "Name": "Axe 1H Golden Sickle", + "ProficiencyId": 343, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 19, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.15 + }, + { + "Type": 18, + "Value": 3 + } + ] + } + ], + "Name": "Axe 1H Daramian Axe", + "ProficiencyId": 344, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 16 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 271, + "Type": 5, + "Value": 0.3 + }, + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 271, + "Type": 5, + "Value": 0.5 + }, + { + "AugmentType": 15, + "SpellId": 271, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 271, + "Type": 5, + "Value": 0.15 + } + ] + } + ], + "Name": "Axe 2H Scythe Of The Reaper", + "ProficiencyId": 345, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.4 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.05 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.05 + } + ] + } + ], + "Name": "Axe 2H Farmer's Avenger", + "ProficiencyId": 346, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.05 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 271, + "Type": 5, + "Value": 0.25 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 271, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 11, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 271, + "Type": 5, + "Value": 1.0 + }, + { + "Type": 15, + "Value": 1.0 + } + ] + } + ], + "Name": "Axe 1H Ice Hatchet", + "ProficiencyId": 347, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 19, + "Value": 3 + } + ] + } + ], + "Name": "Distance 2H Hive Bow", + "ProficiencyId": 348, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.06 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 27, + "Value": 0.08 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Axe 2H Phantasmal Axe", + "ProficiencyId": 349, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 59, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 1, + "Value": 5 + }, + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.4 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 59, + "Type": 5, + "Value": 0.15 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.12 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 59, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Axe 2H Ravager's Axe", + "ProficiencyId": 350, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 26, + "Value": 0.07 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.5 + } + ] + } + ], + "Name": "Wand 1H Shimmer Wand", + "ProficiencyId": 351, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 27, + "Value": 0.07 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.5 + } + ] + } + ], + "Name": "Rod 1H Shimmer Rod", + "ProficiencyId": 352, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 107, + "Type": 5, + "Value": 0.2 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.75 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 107, + "Type": 5, + "Value": 0.5 + }, + { + "AugmentType": 16, + "SpellId": 107, + "Type": 5, + "Value": 0.3 + }, + { + "AugmentType": 15, + "SpellId": 107, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 107, + "Type": 5, + "Value": 0.05 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.75 + } + ] + } + ], + "Name": "Axe 2H Twin Axe", + "ProficiencyId": 353, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + } + ], + "Name": "Axe 2H Executioner", + "ProficiencyId": 354, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "Type": 15, + "Value": 0.15 + } + ] + } + ], + "Name": "Axe 2H Ruthless Axe", + "ProficiencyId": 355, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 26, + "Value": 0.07 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.25 + } + ] + } + ], + "Name": "Distance 2H Shimmer Bow", + "ProficiencyId": 356, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 26, + "Value": 0.07 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 13, + "Type": 25, + "Value": 0.25 + } + ] + } + ], + "Name": "Sword 1H Shimmer Sword", + "ProficiencyId": 357, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.15 + }, + { + "Type": 20, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.03 + }, + { + "ElementId": 256, + "Type": 13, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "DamageType": 256, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Wand 1H Wand of Darkness", + "ProficiencyId": 358, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.07 + } + ] + } + ], + "Name": "Axe 2H Demonwing Axe", + "ProficiencyId": 359, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.5 + } + ] + } + ], + "Name": "Axe 2H Great Axe", + "ProficiencyId": 360, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Range": 1, + "Type": 22, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.1 + } + ] + } + ], + "Name": "Distance 2H Mycological Bow", + "ProficiencyId": 361, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.02 + }, + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + } + ], + "Name": "Distance 2H Modified Crossbow", + "ProficiencyId": 362, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.075 + } + ] + }, + { + "Perks": [ + { + "Type": 24, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 7, + "Type": 22, + "Value": 10 + }, + { + "Type": 21, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 8, + "BestiaryName": "Fey", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Distance 2H Rift Bow", + "ProficiencyId": 363, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 1, + "Type": 22, + "Value": 6 + }, + { + "Type": 21, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 2, + "Type": 22, + "Value": 7 + }, + { + "Type": 21, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 8 + }, + { + "Type": 21, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 9 + }, + { + "Type": 21, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 10 + }, + { + "Type": 21, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Range": 6, + "Type": 22, + "Value": 11 + }, + { + "Type": 21, + "Value": 3 + } + ] + } + ], + "Name": "Distance 2H Living Vine Bow", + "ProficiencyId": 364, + "Version": 5 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 10 + }, + { + "ElementId": 128, + "Type": 9, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + }, + { + "ElementId": 128, + "Type": 13, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Distance 2H Bow of Cataclysm", + "ProficiencyId": 365, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Bright Sword", + "ProficiencyId": 366, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Gnome Sword", + "ProficiencyId": 367, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 20 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "Type": 7, + "Value": 0.025 + } + ] + } + ], + "Name": "Sword 1H Winterblade", + "ProficiencyId": 368, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 20 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "Type": 7, + "Value": 0.025 + } + ] + } + ], + "Name": "Sword 1H Summerblade", + "ProficiencyId": 369, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 15 + } + ] + } + ], + "Name": "Sword 1H Impaler Of The Igniter", + "ProficiencyId": 370, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Sword 1H Ink Sword", + "ProficiencyId": 371, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "Range": 6, + "Type": 22, + "Value": 10 + }, + { + "Type": 18, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + } + ] + } + ], + "Name": "Distance 2H Arbalest", + "ProficiencyId": 372, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 2, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 27, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.15 + } + ] + } + ], + "Name": "Distance 2H Ornate Crossbow", + "ProficiencyId": 373, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Sword 1H Mystic Blade", + "ProficiencyId": 374, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Axe 1H Heroic Axe", + "ProficiencyId": 375, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + } + ] + } + ], + "Name": "Club 1H Cranial Basher", + "ProficiencyId": 376, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 8, + "Type": 26, + "Value": 0.06 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.4 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 61, + "Type": 5, + "Value": 0.05 + } + ] + } + ], + "Name": "Sword 1H Justice Seeker", + "ProficiencyId": 377, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.04 + } + ] + } + ], + "Name": "Distance 2H Chain Bolter", + "ProficiencyId": 378, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.2 + } + ] + } + ], + "Name": "Axe 1H Royal Axe", + "ProficiencyId": 379, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.2 + } + ] + } + ], + "Name": "Club 1H Blessed Sceptre", + "ProficiencyId": 380, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Type": 19, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.015 + }, + { + "Type": 0, + "Value": 1 + }, + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 1, + "BestiaryName": "Amphibic", + "Type": 6, + "Value": 0.04 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + } + ], + "Name": "Distance 2H Triple Bolt Crossbow", + "ProficiencyId": 381, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.03 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.05 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 9, + "BestiaryName": "Giant", + "Type": 6, + "Value": 0.04 + } + ] + } + ], + "Name": "Distance 2H The Ironworker", + "ProficiencyId": 382, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.015 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 17, + "SpellId": 61, + "Type": 5, + "Value": 0.025 + } + ] + } + ], + "Name": "Club 2H Orcish Maul", + "ProficiencyId": 383, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.015 + }, + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 17, + "SpellId": 61, + "Type": 5, + "Value": 0.025 + } + ] + } + ], + "Name": "Axe 2H Headchopper", + "ProficiencyId": 384, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.02 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.015 + }, + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + }, + { + "AugmentType": 17, + "SpellId": 61, + "Type": 5, + "Value": 0.025 + } + ] + } + ], + "Name": "Sword 2H Blacksteel Sword", + "ProficiencyId": 385, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 57, + "Type": 5, + "Value": 0.15 + }, + { + "Type": 11, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 4, + "BestiaryName": "Construct", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + } + ] + } + ], + "Name": "Distance 2H Crystal Crossbow", + "ProficiencyId": 386, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "BestiaryId": 10, + "BestiaryName": "Human", + "Type": 6, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 10 + } + ] + } + ], + "Name": "Sword 1H Blade of Corruption", + "ProficiencyId": 387, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 1, + "Type": 22, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 5 + }, + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 3 + }, + { + "Type": 7, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + } + ], + "Name": "Distance 2H The Devileye", + "ProficiencyId": 388, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.04 + }, + { + "AugmentType": 15, + "SpellId": 105, + "Type": 5, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Sword 1H Emerald Sword", + "ProficiencyId": 389, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 2 + }, + { + "Type": 23, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.015 + }, + { + "Range": 6, + "Type": 22, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + } + ], + "Name": "Distance 2H Thorn Spitter", + "ProficiencyId": 391, + "Version": 6 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 25, + "Value": 0.075 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Range": 5, + "Type": 22, + "Value": 12 + }, + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 8, + "BestiaryName": "Fey", + "Type": 6, + "Value": 0.02 + }, + { + "Type": 23, + "Value": 0.01 + } + ] + } + ], + "Name": "Distance 2H Rift Crossbow", + "ProficiencyId": 392, + "Version": 4 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 0.01 + }, + { + "Range": 6, + "Type": 22, + "Value": 12 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.04 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + } + ], + "Name": "Distance 2H Royal Crossbow", + "ProficiencyId": 393, + "Version": 8 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + }, + { + "Type": 20, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Fist 2H Sai Of Enlightenment", + "ProficiencyId": 397, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + }, + { + "Type": 20, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Fist 2H Nunchaku Of Enlightenment", + "ProficiencyId": 398, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + }, + { + "Type": 20, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 292, + "Type": 5, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + } + ] + } + ], + "Name": "Fist 2H Fists Of Enlightenment", + "ProficiencyId": 399, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.03 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Fist 2H Drachaku", + "ProficiencyId": 400, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 290, + "Type": 5, + "Value": 0.25 + }, + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 290, + "Type": 5, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 2, + "SpellId": 290, + "Type": 5, + "Value": 0.14 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + } + ], + "Name": "Fist 2H Depth Claws", + "ProficiencyId": 401, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.1 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 19, + "BestiaryName": "Vermin", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.035 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + } + ], + "Name": "Jungle 2H Fist", + "ProficiencyId": 402, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 26, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 25 + }, + { + "Type": 24, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 258, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 16, + "SpellId": 258, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "Range": 4, + "Type": 22, + "Value": 25 + }, + { + "Type": 20, + "Value": 30 + }, + { + "ElementId": 128, + "Type": 13, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 23, + "Value": 1.0 + } + ] + }, + { + "Perks": [ + { + "ElementId": 128, + "Type": 9, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.1 + }, + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.1 + } + ] + } + ], + "Name": "Distance 2H Elethriel's Elemental Bow", + "ProficiencyId": 403, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.25 + }, + { + "AugmentType": 14, + "SpellId": 106, + "Type": 5, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 106, + "Type": 5, + "Value": 0.25 + }, + { + "AugmentType": 15, + "SpellId": 106, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 106, + "Type": 5, + "Value": 0.075 + } + ] + } + ], + "Name": "Sword 1H Ravenwing", + "ProficiencyId": 404, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.2 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 268, + "Type": 5, + "Value": -4.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 125, + "Type": 5, + "Value": 0.1 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "SkillId": 1, + "Type": 27, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 3 + } + ] + } + ], + "Name": "Distance 2H Yol's Bow", + "ProficiencyId": 405, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.015 + }, + { + "Type": 21, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + } + ] + } + ], + "Name": "Axe 1H Crystalline Axe", + "ProficiencyId": 406, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 6, + "SpellId": 158, + "Type": 5, + "Value": -150.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 3, + "SpellId": 158, + "Type": 5, + "Value": 0.25 + }, + { + "SkillId": 10, + "Type": 27, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.2 + }, + { + "SkillId": 10, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Axe 1H Plague Bite", + "ProficiencyId": 407, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + }, + { + "Type": 21, + "Value": 20 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Club 1H Obsidian Truncheon", + "ProficiencyId": 408, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 8, + "BestiaryName": "Fey", + "Type": 6, + "Value": 0.025 + }, + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 7, + "Value": 0.025 + } + ] + } + ], + "Name": "Club 1H Maimer", + "ProficiencyId": 409, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 20, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + }, + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 3, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.025 + } + ] + } + ], + "Name": "Club 1H Mortal Mace", + "ProficiencyId": 410, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 4 + }, + { + "Type": 7, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 8 + }, + { + "Type": 7, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 16 + }, + { + "Type": 7, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 32 + }, + { + "Type": 7, + "Value": 0.04 + } + ] + } + ], + "Name": "Glooth 2H Club", + "ProficiencyId": 411, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 4 + }, + { + "Type": 7, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 8 + }, + { + "Type": 7, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 16 + }, + { + "Type": 7, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 32 + }, + { + "Type": 7, + "Value": 0.04 + } + ] + } + ], + "Name": "Glooth 2H Axe", + "ProficiencyId": 412, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 4 + }, + { + "Type": 7, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 8 + }, + { + "Type": 7, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 16 + }, + { + "Type": 7, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 32 + }, + { + "Type": 7, + "Value": 0.04 + } + ] + } + ], + "Name": "Glooth 2H Sword", + "ProficiencyId": 413, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 5, + "BestiaryName": "Demon", + "Type": 6, + "Value": 0.015 + }, + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + } + ], + "Name": "Axe 1H Stonecutter Axe", + "ProficiencyId": 414, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 59, + "Type": 5, + "Value": 0.25 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 59, + "Type": 5, + "Value": 0.6 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.03 + }, + { + "AugmentType": 2, + "SpellId": 59, + "Type": 5, + "Value": 0.045 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 59, + "Type": 5, + "Value": 0.125 + }, + { + "SkillId": 10, + "Type": 26, + "Value": 0.04 + } + ] + } + ], + "Name": "Axe 1H Reaper's Axe", + "ProficiencyId": 415, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 20, + "BestiaryName": "Extra Dimensional", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Axe 1H Mythril Axe", + "ProficiencyId": 416, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 1, + "Value": 5 + }, + { + "SkillId": 6, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.03 + } + ] + } + ], + "Name": "Axe 1H Impaler", + "ProficiencyId": 417, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 7, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.0666 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 62, + "Type": 5, + "Value": 0.12 + }, + { + "AugmentType": 14, + "SpellId": 62, + "Type": 5, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 62, + "Type": 5, + "Value": 0.0666 + } + ] + } + ], + "Name": "Axe 1H Hellforged Axe", + "ProficiencyId": 418, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 3, + "Value": 1 + }, + { + "DamageType": 8, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 25, + "Value": 0.25 + }, + { + "SkillId": 1, + "Type": 25, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "SkillId": 10, + "Type": 26, + "Value": 0.15 + }, + { + "ElementId": 8, + "Type": 13, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + }, + { + "ElementId": 8, + "Type": 9, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Axe 1H Solar Axe", + "ProficiencyId": 419, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 18, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 17, + "BestiaryName": "Slime", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Glooth Whip", + "ProficiencyId": 420, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 20, + "BestiaryName": "Extra Dimensional", + "Type": 6, + "Value": 0.04 + } + ] + } + ], + "Name": "Sword 1H Broken Macuahuitl", + "ProficiencyId": 421, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 2, + "BestiaryName": "Aquatic", + "Type": 6, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 8 + } + ] + } + ], + "Name": "Club 1H Deepling Squelcher", + "ProficiencyId": 422, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 6, + "Type": 3, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 6, + "Type": 27, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "DamageType": 1048576, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + } + ], + "Name": "Club 2H Enchanted Staff", + "ProficiencyId": 423, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 27, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.3 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.5 + } + ] + } + ], + "Name": "Club 1H Light Mace", + "ProficiencyId": 424, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 6, + "Type": 25, + "Value": 0.07 + } + ] + }, + { + "Perks": [ + { + "Type": 2, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 3, + "SpellId": 123, + "Type": 5, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 61, + "Type": 5, + "Value": 0.1 + }, + { + "DamageType": 1048576, + "Type": 4, + "Value": 1 + } + ] + } + ], + "Name": "Club 1H Queen's Sceptre", + "ProficiencyId": 425, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 7, + "BestiaryName": "Elemental", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Sulphurous Demonbone", + "ProficiencyId": 426, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Unliving Demonbone", + "ProficiencyId": 427, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 13, + "BestiaryName": "Magical", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Energized Demonbone", + "ProficiencyId": 428, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Rotten Demonbone", + "ProficiencyId": 429, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "SkillId": 9, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 10, + "BestiaryName": "Human", + "Type": 6, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 1H Demonbone", + "ProficiencyId": 430, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 6, + "Type": 27, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 21, + "Value": 25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.02 + }, + { + "BestiaryId": 6, + "BestiaryName": "Dragon", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + } + ], + "Name": "Club 1H Snake God's Sceptre", + "ProficiencyId": 431, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 9, + "BestiaryName": "Giant", + "Type": 6, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "Type": 15, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 107, + "Type": 5, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 107, + "Type": 5, + "Value": 0.16 + }, + { + "Type": 11, + "Value": 0.05 + }, + { + "AugmentType": 17, + "SpellId": 107, + "Type": 5, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + } + ], + "Name": "Club 1H Thunder Hammer", + "ProficiencyId": 432, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 3 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.25 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + }, + { + "Type": 8, + "Value": 0.05 + }, + { + "Type": 17, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "DamageType": 256, + "Type": 4, + "Value": 2 + } + ] + } + ], + "Name": "Club 1H Dark Trinity Mace", + "ProficiencyId": 433, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 11, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.5 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 3 + } + ] + } + ], + "Name": "Club 1H Ferumbras Staff", + "ProficiencyId": 434, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 19, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.2 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 61, + "Type": 5, + "Value": 0.4 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 61, + "Type": 5, + "Value": 0.075 + } + ] + } + ], + "Name": "Club 2H One Hit Wonder", + "ProficiencyId": 435, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.15 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 2H Arcane Staff", + "ProficiencyId": 436, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.15 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 16 + } + ] + }, + { + "Perks": [ + { + "Type": 18, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 2, + "SpellId": 62, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.05 + } + ] + } + ], + "Name": "Club 2H Hammer Of Prophecy", + "ProficiencyId": 437, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.0075 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + }, + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.0175 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 12, + "BestiaryName": "Lycanthrope", + "Type": 6, + "Value": 0.025 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + } + ], + "Name": "Club 2H Resizer", + "ProficiencyId": 438, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 9, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.2 + }, + { + "Type": 21, + "Value": 30 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Club 2H Skullcrusher", + "ProficiencyId": 439, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 11, + "Type": 25, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.025 + }, + { + "Type": 20, + "Value": 15 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 18, + "BestiaryName": "Undead", + "Type": 6, + "Value": 0.025 + } + ] + } + ], + "Name": "Club 2H The Stomper", + "ProficiencyId": 440, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "DamageType": 32, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.015 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.015 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 15 + }, + { + "Type": 10, + "Value": 0.005 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 119, + "Type": 5, + "Value": 0.025 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 10, + "BestiaryName": "Human", + "Type": 6, + "Value": 0.02 + } + ] + } + ], + "Name": "Wand 1H Ferumbras' Staff (Failed)", + "ProficiencyId": 441, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 1, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 14, + "Value": 0.03 + }, + { + "SkillId": 1, + "Type": 26, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 20, + "Value": 30 + }, + { + "Type": 10, + "Value": 0.01 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 119, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 10, + "BestiaryName": "Human", + "Type": 6, + "Value": 0.04 + } + ] + } + ], + "Name": "Wand 1H Ferumbras' Staff (Enchanted)", + "ProficiencyId": 442, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.35 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.4 + }, + { + "Type": 21, + "Value": 15 + } + ] + } + ], + "Name": "Sword 1H Ripper's Sabre", + "ProficiencyId": 443, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 2, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.02 + }, + { + "Type": 20, + "Value": 7 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 26, + "Value": 0.02 + } + ] + } + ], + "Name": "Sword 1H Ritual Bone Knife", + "ProficiencyId": 444, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 20, + "BestiaryName": "Extra Dimensional", + "Type": 6, + "Value": 0.01 + } + ] + } + ], + "Name": "Axe 2H Broken Iks Spear", + "ProficiencyId": 445, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 15, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "Type": 15, + "Value": 0.06 + } + ] + } + ], + "Name": "Club 1H Mallet Handle", + "ProficiencyId": 446, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + }, + { + "AugmentType": 14, + "SpellId": 124, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 124, + "Type": 5, + "Value": 0.02 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 124, + "Type": 5, + "Value": 0.2 + }, + { + "AugmentType": 2, + "SpellId": 124, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 124, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.02 + } + ] + } + ], + "Name": "Sanguine 2H Crossbow", + "ProficiencyId": 447, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 19, + "Value": 10 + }, + { + "Range": 4, + "Type": 22, + "Value": 10 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 21, + "BestiaryName": "Inkborn", + "Type": 6, + "Value": 0.03 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 0.75 + }, + { + "Type": 12, + "Value": 0.06 + } + ] + }, + { + "Perks": [ + { + "DamageType": 128, + "Type": 4, + "Value": 1 + }, + { + "SkillId": 7, + "Type": 3, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 1.25 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.08 + }, + { + "Type": 18, + "Value": 7 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.01 + } + ] + } + ], + "Name": "Soul 2H Crossbow", + "ProficiencyId": 448, + "Version": 3 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 1, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "SkillId": 8, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 10 + }, + { + "Type": 7, + "Value": 0.03 + }, + { + "Type": 20, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "Type": 21, + "Value": 20 + }, + { + "BestiaryId": 16, + "BestiaryName": "Reptile", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 20, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "Type": 11, + "Value": 0.03 + } + ] + } + ], + "Name": "Sword 2H Tagralt Blade", + "ProficiencyId": 449, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + }, + { + "AugmentType": 14, + "SpellId": 124, + "Type": 5, + "Value": 0.05 + }, + { + "Type": 12, + "Value": 0.04 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 124, + "Type": 5, + "Value": 0.04 + }, + { + "Type": 12, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 16, + "SpellId": 124, + "Type": 5, + "Value": 0.4 + }, + { + "AugmentType": 2, + "SpellId": 124, + "Type": 5, + "Value": 0.08 + }, + { + "Type": 7, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + }, + { + "AugmentType": 17, + "SpellId": 124, + "Type": 5, + "Value": 0.03 + }, + { + "Type": 0, + "Value": 2 + } + ] + }, + { + "Perks": [ + { + "Type": 12, + "Value": 0.1 + }, + { + "SkillId": 1, + "Type": 27, + "Value": 2.0 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.03 + } + ] + } + ], + "Name": "Grand Sanguine 2H Crossbow", + "ProficiencyId": 450, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 10 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.12 + }, + { + "Type": 19, + "Value": 8 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.03 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "Type": 18, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 26, + "Value": 0.1 + } + ] + } + ], + "Name": "Master Umbral 2H Crossbow", + "ProficiencyId": 451, + "Version": 2 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 7 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.08 + }, + { + "Type": 19, + "Value": 6 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.02 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "Type": 20, + "Value": 3 + } + ] + } + ], + "Name": "Umbral 2H Crossbow", + "ProficiencyId": 452, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Range": 3, + "Type": 22, + "Value": 5 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.05 + }, + { + "Type": 19, + "Value": 4 + } + ] + }, + { + "Perks": [ + { + "BestiaryId": 11, + "BestiaryName": "Humanoid", + "Type": 6, + "Value": 0.03 + }, + { + "Type": 11, + "Value": 0.015 + } + ] + } + ], + "Name": "Crude Umbral 2H Crossbow", + "ProficiencyId": 453, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 12, + "Value": 0.48 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 8, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 57, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 15, + "SpellId": 57, + "Type": 5, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Rending Inferniarch 2H Crossbow", + "ProficiencyId": 454, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 16, + "Value": 0.05 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 14, + "SpellId": 57, + "Type": 5, + "Value": 0.1 + }, + { + "AugmentType": 16, + "SpellId": 57, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Siphoning Inferniarch 2H Crossbow", + "ProficiencyId": 455, + "Version": 1 + }, + { + "Levels": [ + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 25, + "Value": 0.1 + }, + { + "Type": 15, + "Value": 0.1 + } + ] + }, + { + "Perks": [ + { + "Type": 17, + "Value": 0.145 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 15, + "SpellId": 57, + "Type": 5, + "Value": 0.05 + }, + { + "AugmentType": 16, + "SpellId": 57, + "Type": 5, + "Value": 0.08 + } + ] + }, + { + "Perks": [ + { + "SkillId": 7, + "Type": 3, + "Value": 1 + }, + { + "BestiaryId": 15, + "BestiaryName": "Plant", + "Type": 6, + "Value": 0.03 + }, + { + "DamageType": 128, + "Type": 4, + "Value": 1 + } + ] + }, + { + "Perks": [ + { + "Type": 7, + "Value": 0.03 + }, + { + "SkillId": 7, + "Type": 26, + "Value": 0.05 + }, + { + "AugmentType": 6, + "SpellId": 238, + "Type": 5, + "Value": -2.0 + } + ] + }, + { + "Perks": [ + { + "AugmentType": 17, + "SpellId": 57, + "Type": 5, + "Value": 0.015 + } + ] + } + ], + "Name": "Draining Inferniarch 2H Crossbow", + "ProficiencyId": 456, + "Version": 1 + } +] \ No newline at end of file diff --git a/data/modules/scripts/gamestore/catalog/consumables_exercise_weapons.lua b/data/modules/scripts/gamestore/catalog/consumables_exercise_weapons.lua index d4590b3baa1..3c882347213 100644 --- a/data/modules/scripts/gamestore/catalog/consumables_exercise_weapons.lua +++ b/data/modules/scripts/gamestore/catalog/consumables_exercise_weapons.lua @@ -68,6 +68,15 @@ return { description = "Use it to train your shielding skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your shielding skill\n{info} usable 1800 times a piece", type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, }, + { + icons = { "Durable_Exercise_Wraps.png" }, + name = "Durable Exercise Wraps", + price = 90, + itemtype = 50294, + charges = 1800, + description = "Use it to train your fist skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your fist skill\n{info} usable 1800 times a piece", + type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, + }, { icons = { "Exercise_Axe.png" }, name = "Exercise Axe", @@ -131,6 +140,15 @@ return { description = "Use it to train your shielding skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your shielding skill\n{info} usable 500 times a piece", type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, }, + { + icons = { "Exercise_Wraps.png" }, + name = "Exercise Wraps", + price = 25, + itemtype = 50294, + charges = 500, + description = "Use it to train your fist skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your fist skill\n{info} usable 500 times a piece", + type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, + }, { icons = { "Lasting_Exercise_Axe.png" }, name = "Lasting Exercise Axe", @@ -194,5 +212,14 @@ return { description = "Use it to train your shielding skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your shielding skill\n{info} usable 14400 times a piece", type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, }, + { + icons = { "Lasting_Exercise_Wraps.png" }, + name = "Lasting Exercise Wraps", + price = 720, + itemtype = 50295, + charges = 14400, + description = "Use it to train your fist skill on an exercise dummy!\n\n{character}\n{storeinbox}\n{info} use it on an exercise dummy to train your fist skill\n{info} usable 14400 times a piece", + type = GameStore.OfferTypes.OFFER_TYPE_CHARGES, + }, }, } diff --git a/data/scripts/globalevents/save_interval.lua b/data/scripts/globalevents/save_interval.lua index 6e24bc53edc..765f40afa97 100644 --- a/data/scripts/globalevents/save_interval.lua +++ b/data/scripts/globalevents/save_interval.lua @@ -1,4 +1,8 @@ +local saveTimeStr = configManager.getString(configKeys.GLOBAL_SERVER_SAVE_TIME) or "00:00" +local isSaveScheduled = false + local function serverSave(interval) + isSaveScheduled = false if configManager.getBoolean(configKeys.TOGGLE_SAVE_INTERVAL_CLEAN_MAP) then cleanMap() end @@ -10,19 +14,69 @@ local function serverSave(interval) Webhook.sendMessage("Server save", message, WEBHOOK_COLOR_WARNING) end +local function getTimeLeftMs(timeStr) + if type(timeStr) ~= "string" then + return nil + end + + local hStr, mStr = timeStr:match("^(%d+):(%d+)$") + if not hStr or not mStr then + return nil + end + + local h, m = tonumber(hStr), tonumber(mStr) + if not h or not m or h < 0 or h > 23 or m < 0 or m > 59 then + return nil + end + + local nowTs = os.time() + local nowDate = os.date("*t", nowTs) + local saveTs = os.time({ + year = nowDate.year, + month = nowDate.month, + day = nowDate.day, + hour = h, + min = m, + sec = 0, + }) + + if saveTs <= nowTs then + saveTs = saveTs + 24 * 60 * 60 + end + + return (saveTs - nowTs) * 1000 +end + local save = GlobalEvent("save") function save.onTime(interval) - local remainingTime = 60 * 1000 - if configManager.getBoolean(configKeys.TOGGLE_SAVE_INTERVAL) then - local message = "The server will save all accounts within " .. (remainingTime / 1000) .. " seconds. \z - You might lag or freeze for 5 seconds, please find a safe place." - Game.broadcastMessage(message, MESSAGE_GAME_HIGHLIGHT) - logger.info(string.format(message, SAVE_INTERVAL_CONFIG_TIME, SAVE_INTERVAL_TYPE)) - addEvent(serverSave, remainingTime, interval) + if not configManager.getBoolean(configKeys.TOGGLE_SAVE_INTERVAL) then + return true + end + + if isSaveScheduled then return true end - return not configManager.getBoolean(configKeys.TOGGLE_SAVE_INTERVAL) + + local WARNING = 60 * 1000 + local timeLeft = getTimeLeftMs(saveTimeStr) + + if not timeLeft or timeLeft > WARNING then + return true + end + + if timeLeft <= 1000 then + serverSave(interval) + else + local secs = math.floor(timeLeft / 1000) + local msg = string.format("The server will save all accounts within %d seconds. " .. "You might lag or freeze for 5 seconds, please find a safe place.", secs) + Game.broadcastMessage(msg, MESSAGE_GAME_HIGHLIGHT) + logger.info(msg) + isSaveScheduled = true + addEvent(serverSave, timeLeft - 1000, interval) + end + + return true end if SAVE_INTERVAL_TIME ~= 0 then diff --git a/data/scripts/lib/proficiency_helper.lua b/data/scripts/lib/proficiency_helper.lua new file mode 100644 index 00000000000..83f254feda6 --- /dev/null +++ b/data/scripts/lib/proficiency_helper.lua @@ -0,0 +1,32 @@ +function createProficiencyCatalyst(itemId, experience) + local catalyst = Action() + + function catalyst.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not item or not item:isItem() then + return false + end + + if not target or not target:isItem() then + return false + end + + local weaponId = target:getId() + local itemType = ItemType(weaponId) + if not itemType:isWeapon() then + player:sendCancelMessage("You can only use this on weapons.") + return true + end + + local success = player:addWeaponExperience(experience, weaponId) + if success then + item:remove(1) + player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) + else + player:sendCancelMessage("Failed to apply proficiency experience.") + end + return true + end + + catalyst:id(itemId) + catalyst:register() +end diff --git a/data/scripts/lib/register_achievements.lua b/data/scripts/lib/register_achievements.lua index eabe47a7191..6e6df0e7a37 100644 --- a/data/scripts/lib/register_achievements.lua +++ b/data/scripts/lib/register_achievements.lua @@ -559,6 +559,14 @@ ACHIEVEMENTS = { [560] = { name = "Umbral Redeemer", grade = 2, points = 6, description = "You managed to create, improve and transform your katar into a master state and have proven yourself worthy in a nightmarish world." }, [561] = { name = "Hell Rider", grade = 1, points = 2, description = "Pray it never finds its way back to its original stable with you still riding." }, [562] = { name = "Alpha Rider", grade = 1, points = 2, description = "You never can tell, who's boss here." }, + -- [563] = Unknown/non-existent + [564] = { name = "The First of Many", grade = 1, points = 3, description = "The first step to greatness has been done." }, + [565] = { name = "A Well-Honed Arsenal", grade = 2, points = 5, description = "Your expertise in weaponry reaches new heights." }, + [566] = { name = "Arsenal of War", grade = 3, points = 7, description = "Feared by your enemies, admired by many - your reputation in weapon mastery precedes you." }, + -- [567] = Unknown/non-existent + [568] = { name = "Bat Person", grade = 1, points = 3, description = "No matter your command, this beast is all ears!" }, + [569] = { name = "Illuminator", grade = 1, points = 3, description = "Joran and Yvette have brought the colours back to the world, and you have freed it from the monsters of this story. The world of books is now yours." }, + [570] = { name = "Power of Words", grade = 2, points = 5, description = "The pen is mightier than the sword. In a way, yes, you have had this experience. You have seen with your own eyes what the power of words can do, the written word, to be precise." }, } --[[ diff --git a/data/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua index cc4c2988c2e..6bb42593a2e 100644 --- a/data/scripts/lib/register_monster_type.lua +++ b/data/scripts/lib/register_monster_type.lua @@ -380,10 +380,10 @@ local function configureLootAttributes(lootObject, lootProperties) lootObject:setUnique(lootProperties.unique or false) end -local function addChildrenLoot(parent, childrenLoot) +local function addChildrenLoot(parent, childrenLoot, monsterName) SortLootByChance(childrenLoot) for _, child in pairs(childrenLoot) do - local childLoot = Loot() + local childLoot = Loot(monsterName or "") if child.name then if not childLoot:setIdFromName(child.name) then return true @@ -404,8 +404,9 @@ function MonsterType:createLoot(lootTable) SortLootByChance(lootTable) local lootError = false + local monsterName = self:name() or "" for _, loot in pairs(lootTable) do - local parent = Loot() + local parent = Loot(monsterName) if loot.name then if not parent:setIdFromName(loot.name) then lootError = true @@ -419,7 +420,7 @@ function MonsterType:createLoot(lootTable) configureLootAttributes(parent, loot) - if loot.child and addChildrenLoot(parent, loot.child) then + if loot.child and addChildrenLoot(parent, loot.child, monsterName) then lootError = true end @@ -427,7 +428,7 @@ function MonsterType:createLoot(lootTable) end if lootError then - logger.warn("[MonsterType:createLoot] - Monster: {} loot could not be loaded correctly", self:getName()) + logger.warn("[MonsterType:createLoot] - Monster: {} loot could not be loaded correctly", monsterName) end end diff --git a/data/scripts/talkactions/god/weapon_proficiency.lua b/data/scripts/talkactions/god/weapon_proficiency.lua new file mode 100644 index 00000000000..ca44c544232 --- /dev/null +++ b/data/scripts/talkactions/god/weapon_proficiency.lua @@ -0,0 +1,25 @@ +local weaponProficiency = TalkAction("/proficiency") +function weaponProficiency.onSay(player, words, param) + -- Create log + logCommand(player, words, param) + + if param == "" then + player:sendCancelMessage("Command param required.") + return true + end + + local experience = tonumber(param) + if not experience then + player:sendCancelMessage("Usage: /proficiency ") + return true + end + + player:addWeaponExperience(experience, 0) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("Added %d weapon experience to your equipped weapon.", experience)) + + return true +end + +weaponProficiency:separator(" ") +weaponProficiency:groupType("god") +weaponProficiency:register() diff --git a/src/canary_server.cpp b/src/canary_server.cpp index 7792a5b6f4b..0cbb7d82677 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -33,6 +33,7 @@ #include "server/network/protocol/protocolstatus.hpp" #include "server/network/webhook/webhook.hpp" #include "creatures/players/vocations/vocation.hpp" +#include "creatures/players/components/weapon_proficiency.hpp" CanaryServer::CanaryServer( Logger &logger, @@ -376,6 +377,7 @@ void CanaryServer::loadModules() { logger.info("Loading modules and scripts..."); auto coreFolder = g_configManager().getString(CORE_DIRECTORY); + modulesLoadHelper(WeaponProficiency::loadFromJson(), "proficiencies.json"); // Load appearances.dat first modulesLoadHelper((g_game().loadAppearanceProtobuf(coreFolder + "/items/appearances.dat") == ERROR_NONE), "appearances.dat"); @@ -417,10 +419,10 @@ void CanaryServer::loadModules() { g_game().logCyclopediaStats(); } -void CanaryServer::modulesLoadHelper(bool loaded, std::string moduleName) { - logger.debug("Loading {}", moduleName); +void CanaryServer::modulesLoadHelper(bool loaded, std::string_view identifier) { + logger.debug("Loading {}", identifier); if (!loaded) { - throw FailedToInitializeCanary(fmt::format("Cannot load: {}", moduleName)); + throw FailedToInitializeCanary(fmt::format("Cannot load: {}", identifier)); } } diff --git a/src/canary_server.hpp b/src/canary_server.hpp index 0e2d3147638..d4461a3dcd0 100644 --- a/src/canary_server.hpp +++ b/src/canary_server.hpp @@ -69,5 +69,5 @@ class CanaryServer { void setWorldType(); void loadMaps() const; void setupHousesRent(); - void modulesLoadHelper(bool loaded, std::string moduleName); + void modulesLoadHelper(bool loaded, std::string_view identifier); }; diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index 2956414f17f..f6225fee73d 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -196,6 +196,8 @@ enum ConfigKey_t : uint16_t { PARTY_LIST_MAX_DISTANCE, PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR, PARTY_SHARE_LOOT_BOOSTS, + PLAYER_BASE_CRITICAL_CHANCE, + PLAYER_BASE_CRITICAL_DAMAGE, PREMIUM_DEPOT_LIMIT, PREY_BONUS_REROLL_PRICE, PREY_BONUS_TIME, @@ -337,5 +339,7 @@ enum ConfigKey_t : uint16_t { XP_DISPLAY_MODE, AMPLIFICATION_CHANCE_FORMULA_A, AMPLIFICATION_CHANCE_FORMULA_B, - AMPLIFICATION_CHANCE_FORMULA_C + AMPLIFICATION_CHANCE_FORMULA_C, + WEAPON_PROFICIENCY_MAX_LEVELS, + WEAPON_PROFICIENCY_MAX_PERKS_PER_LEVEL }; diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index d311dd6b983..3295f9c4c24 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -204,6 +204,9 @@ bool ConfigManager::load() { loadFloatConfig(L, AMPLIFICATION_CHANCE_FORMULA_B, "amplificationChanceFormulaB", 1.7); loadFloatConfig(L, AMPLIFICATION_CHANCE_FORMULA_C, "amplificationChanceFormulaC", 0.4); + loadFloatConfig(L, PLAYER_BASE_CRITICAL_CHANCE, "playerBaseCriticalChance", 0.05); + loadFloatConfig(L, PLAYER_BASE_CRITICAL_DAMAGE, "playerBaseCriticalDamage", 0.1); + loadFloatConfig(L, ANIMUS_MASTERY_MAX_MONSTER_XP_MULTIPLIER, "animusMasteryMaxMonsterXpMultiplier", 4.0); loadFloatConfig(L, ANIMUS_MASTERY_MONSTER_XP_MULTIPLIER, "animusMasteryMonsterXpMultiplier", 2.0); loadFloatConfig(L, ANIMUS_MASTERY_MONSTERS_XP_MULTIPLIER, "animusMasteryMonstersXpMultiplier", 0.1); @@ -354,6 +357,8 @@ bool ConfigManager::load() { loadIntConfig(L, AUGMENT_POWERFUL_IMPACT_PERCENT, "augmentPowerfulImpactPercent", 10); loadIntConfig(L, AUGMENT_STRONG_IMPACT_PERCENT, "augmentStrongImpactPercent", 7); loadIntConfig(L, ANIMUS_MASTERY_MONSTERS_TO_INCREASE_XP_MULTIPLIER, "animusMasteryMonstersToIncreaseXpMultiplier", 10); + loadIntConfig(L, WEAPON_PROFICIENCY_MAX_LEVELS, "weaponProficiencyMaxLevels", 10); + loadIntConfig(L, WEAPON_PROFICIENCY_MAX_PERKS_PER_LEVEL, "weaponProficiencyMaxPerksPerLevel", 6); loadStringConfig(L, CORE_DIRECTORY, "coreDirectory", "data"); loadStringConfig(L, DATA_DIRECTORY, "dataPackDirectory", "data-otservbr-global"); diff --git a/src/core.hpp b/src/core.hpp index 397c15196ab..87d74ce560e 100644 --- a/src/core.hpp +++ b/src/core.hpp @@ -15,7 +15,7 @@ static constexpr auto AUTHENTICATOR_PERIOD = 30U; // SERVER_MAJOR_VERSION is the actual full version of the server, including minor and patch numbers. // This is intended for internal use to identify the exact state of the server (release) software. static constexpr auto SERVER_RELEASE_VERSION = "3.4.2"; -static constexpr auto CLIENT_VERSION = 1500; +static constexpr auto CLIENT_VERSION = 1511; #define CLIENT_VERSION_UPPER (CLIENT_VERSION / 100) #define CLIENT_VERSION_LOWER (CLIENT_VERSION % 100) diff --git a/src/creatures/CMakeLists.txt b/src/creatures/CMakeLists.txt index 1f3b18247ea..1d88eee76a0 100644 --- a/src/creatures/CMakeLists.txt +++ b/src/creatures/CMakeLists.txt @@ -34,5 +34,6 @@ target_sources( players/components/wheel/player_wheel.cpp players/components/player_vip.cpp players/components/wheel/wheel_gems.cpp + players/components/weapon_proficiency.cpp players/vocations/vocation.cpp ) diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index 2f7a23f6a1b..592c0da7801 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -121,6 +121,7 @@ CombatDamage Combat::getCombatDamage(const std::shared_ptr &creature, } if (casterPlayer && wheelSpell && wheelSpell->isInstant()) { wheelSpell->getCombatDataAugment(casterPlayer, damage); + casterPlayer->weaponProficiency().applySpellAugment(damage, wheelSpell->getSpellId()); } } @@ -741,7 +742,7 @@ void Combat::CombatHealthFunc(const std::shared_ptr &caster, const std damage.secondary.value *= attackerPlayer->getBuff(BUFF_AUTOATTACKDEALT) / 100.; } - if (attackerPlayer && attackerPlayer->getPlayerVocationEnum() == VOCATION_MONK_CIP && damage.origin == ORIGIN_FIST) { + if (attackerPlayer->getPlayerVocationEnum() == VOCATION_MONK_CIP && damage.origin == ORIGIN_FIST) { auto bonusMantra = attackerPlayer->getMantra(); auto bonusAscetic = attackerPlayer->wheel().getStage(WheelStage_t::ASCETIC); damage.primary.value -= bonusMantra * bonusAscetic; @@ -754,6 +755,10 @@ void Combat::CombatHealthFunc(const std::shared_ptr &caster, const std } } + attackerPlayer->weaponProficiency().applySkillAutoAttackPercentage(damage); + attackerPlayer->weaponProficiency().applySkillSpellPercentage(damage); + attackerPlayer->weaponProficiency().applySkillSpellPercentage(damage, true); + damage.damageMultiplier += attackerPlayer->wheel().getMajorStatConditional("Divine Empowerment", WheelMajor_t::DAMAGE); g_logger().trace("Wheel Divine Empowerment damage multiplier {}", damage.damageMultiplier); } @@ -762,6 +767,11 @@ void Combat::CombatHealthFunc(const std::shared_ptr &caster, const std return; } + if (attackerPlayer) { + attackerPlayer->weaponProficiency().applyOn(WeaponProficiencyHealth_t::LIFE, WeaponProficiencyGain_t::HIT); + attackerPlayer->weaponProficiency().applyOn(WeaponProficiencyHealth_t::MANA, WeaponProficiencyGain_t::HIT); + } + // Player attacking monster if (attackerPlayer && targetMonster) { const auto &slot = attackerPlayer->getPreyWithMonster(targetMonster->getRaceId()); @@ -770,6 +780,10 @@ void Combat::CombatHealthFunc(const std::shared_ptr &caster, const std damage.secondary.value += static_cast(std::ceil((damage.secondary.value * slot->bonusPercentage) / 100)); } + attackerPlayer->weaponProficiency().applyBestiaryDamage(damage, targetMonster); + attackerPlayer->weaponProficiency().applyBossDamage(damage, targetMonster); + attackerPlayer->weaponProficiency().applyPowerfulFoeDamage(damage, targetMonster); + // Monster type onPlayerAttack event targetMonster->onAttackedByPlayer(attackerPlayer); } @@ -1009,7 +1023,7 @@ uint16_t Combat::monkEffectByElementalBond(CombatType_t combatType, uint16_t eff return effect; // fallback: WHITE } case CONST_ME_WHITE_ENERGY_SPARK: - return effect; // Não possui variantes + return effect; // Don't have variants default: return effect; } @@ -2482,15 +2496,17 @@ void Combat::applyExtensions(const std::shared_ptr &caster, const std: const auto &player = caster->getPlayer(); const auto &monster = caster->getMonster(); - uint16_t baseChance = 0; - int32_t baseBonus = 50; if (player) { - baseChance = player->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE); - baseBonus = player->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE); + uint16_t baseChance = player->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) + player->getBaseCritical().chance * 10000; + int32_t baseBonus = player->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + player->getBaseCritical().damage * 10000; uint16_t lowBlowRaceid = player->parseRacebyCharm(CHARM_LOW); uint16_t savageBlowRaceid = player->parseRacebyCharm(CHARM_SAVAGE); + player->weaponProficiency().applyAutoAttackCritical(damage); + player->weaponProficiency().applyRunesCritical(damage, params.aggressive); + player->weaponProficiency().applyElementCritical(damage); + baseBonus += damage.criticalDamage; baseChance += static_cast(damage.criticalChance); @@ -2590,8 +2606,8 @@ void Combat::applyExtensions(const std::shared_ptr &caster, const std: } } } else if (monster) { - baseChance = monster->getCriticalChance() * 100; - baseBonus = monster->getCriticalDamage() * 100; + uint16_t baseChance = monster->getCriticalChance() * 100; + int32_t baseBonus = monster->getCriticalDamage() * 100; baseBonus += damage.criticalDamage; double multiplier = 1.0 + static_cast(baseBonus) / 10000; baseChance += static_cast(damage.criticalChance); diff --git a/src/creatures/combat/spells.cpp b/src/creatures/combat/spells.cpp index b3f80295222..1f8e568e7f4 100644 --- a/src/creatures/combat/spells.cpp +++ b/src/creatures/combat/spells.cpp @@ -753,7 +753,7 @@ void Spell::getCombatDataAugment(const std::shared_ptr &player, CombatDa continue; } if ( - augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact || augment->type == Augment_t::Base + augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact || augment->type == Augment_t::BaseDamage || augment->type == Augment_t::BaseHealing ) { const float augmentPercent = augment->value / 100.0; damage.primary.value += static_cast(damage.primary.value * augmentPercent); diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp index 6197cfbac59..7d64f7ee86b 100644 --- a/src/creatures/creatures_definitions.hpp +++ b/src/creatures/creatures_definitions.hpp @@ -318,6 +318,7 @@ enum CombatOrigin : uint8_t { ORIGIN_RANGED, ORIGIN_HARMONY, // ONLY HARMONY HEAL WILL HAVE ITS ORIGIN FROM HARMONY ORIGIN_FIST, + ORIGIN_WEAPON_PROFICIENCY, }; enum CallBackParam_t { @@ -527,22 +528,23 @@ enum BestiaryType_t : uint8_t { BESTY_RACE_DEMON = 5, BESTY_RACE_DRAGON = 6, BESTY_RACE_ELEMENTAL = 7, - BESTY_RACE_EXTRA_DIMENSIONAL = 8, - BESTY_RACE_FEY = 9, - BESTY_RACE_GIANT = 10, - BESTY_RACE_HUMAN = 11, - BESTY_RACE_HUMANOID = 12, - BESTY_RACE_LYCANTHROPE = 13, - BESTY_RACE_MAGICAL = 14, - BESTY_RACE_MAMMAL = 15, - BESTY_RACE_PLANT = 16, - BESTY_RACE_REPTILE = 17, - BESTY_RACE_SLIME = 18, - BESTY_RACE_UNDEAD = 19, - BESTY_RACE_VERMIN = 20, + BESTY_RACE_FEY = 8, + BESTY_RACE_GIANT = 9, + BESTY_RACE_HUMAN = 10, + BESTY_RACE_HUMANOID = 11, + BESTY_RACE_LYCANTHROPE = 12, + BESTY_RACE_MAGICAL = 13, + BESTY_RACE_MAMMAL = 14, + BESTY_RACE_PLANT = 15, + BESTY_RACE_REPTILE = 16, + BESTY_RACE_SLIME = 17, + BESTY_RACE_UNDEAD = 18, + BESTY_RACE_VERMIN = 19, + BESTY_RACE_EXTRA_DIMENSIONAL = 20, + BESTY_RACE_INKBORN = 21, BESTY_RACE_FIRST = BESTY_RACE_AMPHIBIC, - BESTY_RACE_LAST = BESTY_RACE_VERMIN, + BESTY_RACE_LAST = BESTY_RACE_INKBORN, }; enum MonstersEvent_t : uint8_t { diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index f95fe8b5315..b611262b929 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -2357,6 +2357,9 @@ void Monster::death(const std::shared_ptr &lastHitCreature) { return; } + targetPlayer->weaponProficiency().applyOn(WeaponProficiencyHealth_t::LIFE, WeaponProficiencyGain_t::KILL); + targetPlayer->weaponProficiency().applyOn(WeaponProficiencyHealth_t::MANA, WeaponProficiencyGain_t::KILL); + auto [activeCharm, _] = g_iobestiary().getCharmFromTarget(targetPlayer, m_monsterType); if (activeCharm == CHARM_CARNAGE) { const auto &charm = g_iobestiary().getBestiaryCharm(activeCharm); @@ -2365,6 +2368,16 @@ void Monster::death(const std::shared_ptr &lastHitCreature) { g_iobestiary().parseCharmCombat(charm, targetPlayer, getMonster()); } } + + const auto weaponExperienceFromBoss = targetPlayer->weaponProficiency().getBosstiaryExperience(m_monsterType->info.bosstiaryRace); + if (weaponExperienceFromBoss > 0) { + targetPlayer->weaponProficiency().addExperience(weaponExperienceFromBoss); + } + + const auto weaponExperienceFromBestiary = targetPlayer->weaponProficiency().getBestiaryExperience(m_monsterType->info.bestiaryStars); + if (weaponExperienceFromBestiary > 0) { + targetPlayer->weaponProficiency().addExperience(weaponExperienceFromBestiary); + } } std::shared_ptr Monster::getCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature) { diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index 4a5172e3544..0ed638a4755 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -20,12 +20,15 @@ class ConditionDamage; class Loot { public: Loot() = default; + explicit Loot(std::string monsterName) : + monsterName(std::move(monsterName)) { } // non-copyable Loot(const Loot &) = delete; Loot &operator=(const Loot &) = delete; LootBlock lootBlock; + std::string monsterName; }; class BaseSpell; diff --git a/src/creatures/players/components/weapon_proficiency.cpp b/src/creatures/players/components/weapon_proficiency.cpp new file mode 100644 index 00000000000..fe13bb5bf42 --- /dev/null +++ b/src/creatures/players/components/weapon_proficiency.cpp @@ -0,0 +1,1267 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +// Player.hpp already includes the weapon +#include "creatures/players/player.hpp" +#include "creatures/monsters/monster.hpp" +#include "items/weapons/weapons.hpp" +#include "creatures/monsters/monsters.hpp" +#include "canary_server.hpp" + +#include "config/configmanager.hpp" +#include "io/fileloader.hpp" +#include "io/io_bosstiary.hpp" +#include "utils/tools.hpp" +#include "utils/hash.hpp" +#include "kv/value_wrapper.hpp" + +#include "kv/kv.hpp" + +namespace AugmentType { + constexpr uint8_t DAMAGE = 2; + constexpr uint8_t HEAL = 3; + constexpr uint8_t COOLDOWN = 6; + constexpr uint8_t LIFE_LEECH = 14; + constexpr uint8_t MANA_LEECH = 15; + constexpr uint8_t CRITICAL_DAMAGE = 16; + constexpr uint8_t CRITICAL_CHANCE = 17; +} + +std::unordered_map WeaponProficiency::proficiencies; + +std::vector WeaponProficiency::crossbowExperience = { + 600, + 8000, + 30000, + 150000, + 650000, + 2500000, + 10000000, + 20000000, + 30000000 +}; + +std::vector WeaponProficiency::knightExperience = { + 1250, + 20000, + 80000, + 300000, + 1500000, + 6000000, + 20000000, + 40000000, + 60000000 +}; + +std::vector WeaponProficiency::standardExperience = { + 1750, + 25000, + 100000, + 400000, + 2000000, + 8000000, + 30000000, + 60000000, + 90000000 +}; + +WeaponProficiency::WeaponProficiency(Player &player) : + m_player(player) { } + +bool WeaponProficiency::isValidWeaponId(uint16_t weaponId) const { + return weaponId > 0 && weaponId < Item::items.size(); +} + +static void registerPerks(const nlohmann::json &perksJson, ProficiencyLevel &proficiencyLevel) { + using enum WeaponProficiencyBonus_t; + + uint8_t perkIndex = 0; + const uint8_t maxPerks = g_configManager().getNumber(WEAPON_PROFICIENCY_MAX_PERKS_PER_LEVEL); + for (const auto &perkJson : perksJson) { + if (perkIndex >= maxPerks) { + g_logger().error("{} - Proficiency level exceeded the maximum perks, skipping perk index above {}", __FUNCTION__, perkIndex + 1); + break; + } + + ProficiencyPerk proficiencyPerk; + proficiencyPerk.type = perkJson["Type"].get(); + proficiencyPerk.value = perkJson["Value"].get(); + + uint64_t shiftedValue = 0; + if (proficiencyPerk.type == SPECIALIZED_MAGIC_LEVEL) { + shiftedValue = perkJson["DamageType"].get(); + } else if (proficiencyPerk.type == ELEMENTAL_HIT_CHANCE || proficiencyPerk.type == ELEMENTAL_CRITICAL_EXTRA_DAMAGE) { + shiftedValue = perkJson["ElementId"].get(); + } + + if (shiftedValue > 0) { + const auto unshiftedValue = undoShift(shiftedValue); + proficiencyPerk.element = getCombatFromCipbiaElement(static_cast(unshiftedValue)); + } + + if (perkJson.contains("Range")) { + proficiencyPerk.range = perkJson["Range"].get(); + } + if (perkJson.contains("AugmentType")) { + proficiencyPerk.augmentType = perkJson["AugmentType"].get(); + } + if (perkJson.contains("SpellId")) { + proficiencyPerk.spellId = perkJson["SpellId"].get(); + } + if (perkJson.contains("SkillId")) { + const auto skill = perkJson["SkillId"].get(); + + const auto skillOpt = magic_enum::enum_cast(skill); + if (skillOpt.has_value()) { + proficiencyPerk.skillId = getSkillsFromCipbiaSkill(skillOpt.value()); + } else { + g_logger().error("{} - Invalid skill id {}, skipping skill register", __FUNCTION__, skill); + } + } + if (perkJson.contains("BestiaryId")) { + proficiencyPerk.bestiaryId = perkJson["BestiaryId"].get(); + } + if (perkJson.contains("BestiaryName")) { + proficiencyPerk.bestiaryName = perkJson["BestiaryName"].get(); + } + + proficiencyPerk.index = perkIndex; + + proficiencyLevel.perks.push_back(std::move(proficiencyPerk)); + perkIndex++; + } +} + +static void registerLevels(const nlohmann::json &levelsJson, Proficiency &proficiency) { + uint8_t levelIndex = 0; + const uint8_t maxLevels = g_configManager().getNumber(WEAPON_PROFICIENCY_MAX_LEVELS); + for (const auto &levelJson : levelsJson) { + if (levelIndex >= maxLevels) { + g_logger().error("{} - Proficiency '{}' exceeded the maximum level, skipping levels above {}", __FUNCTION__, proficiency.id, levelIndex + 1); + break; + } + + ProficiencyLevel proficiencyLevel; + registerPerks(levelJson["Perks"], proficiencyLevel); + + for (auto &perk : proficiencyLevel.perks) { + perk.level = levelIndex; + } + + proficiency.level.push_back(std::move(proficiencyLevel)); + levelIndex++; + } + + proficiency.maxLevel = levelIndex; +} + +[[nodiscard]] std::unordered_map &WeaponProficiency::getProficiencies() { + return proficiencies; +} + +bool WeaponProficiency::loadFromJson(bool reload /* = false */) { + g_logger().info("{}oading weapon proficiencies...", reload ? "Rel" : "L"); + + if (reload) { + proficiencies.clear(); + } + + auto coreFolder = g_configManager().getString(CORE_DIRECTORY); + auto folder = fmt::format("{}/items/proficiencies.json", coreFolder); + std::ifstream file(folder); + if (!file.is_open()) { + throw FailedToInitializeCanary(fmt::format("{} - Unable to open file '{}'", __FUNCTION__, folder)); + } + + nlohmann::json proficienciesJson; + try { + file >> proficienciesJson; + } catch (const nlohmann::json::parse_error &e) { + throw FailedToInitializeCanary(fmt::format("{} - JSON parsing error in file '{}': {}", __FUNCTION__, folder, e.what())); + } + + try { + for (const auto &proficiencyJson : proficienciesJson) { + Proficiency proficiency; + proficiency.id = proficiencyJson["ProficiencyId"].get(); + + registerLevels(proficiencyJson["Levels"], proficiency); + + proficiencies[proficiency.id] = std::move(proficiency); + } + } catch (const nlohmann::json::exception &e) { + throw FailedToInitializeCanary(fmt::format("{} - JSON exception in file '{}': {}", __FUNCTION__, folder, e.what())); + } + + g_logger().info("Weapon proficiencies loaded!"); + + return true; +} + +void WeaponProficiency::load() { + proficiency.clear(); + + auto wp_kv = m_player.kv()->scoped("weapon-proficiency"); + for (const auto &key : wp_kv->keys()) { + int parsedId = 0; + try { + parsedId = std::stoi(key); + } catch (const std::invalid_argument &e) { + g_logger().error("{} - Invalid key '{}' in weapon-proficiency KV: {}", __FUNCTION__, key, e.what()); + continue; + } catch (const std::out_of_range &e) { + g_logger().error("{} - Out of range key '{}' in weapon-proficiency KV: {}", __FUNCTION__, key, e.what()); + continue; + } + + // Validate that the stored weapon ID has a valid proficiencyId + const auto weaponId = static_cast(parsedId); + if (!isValidWeaponId(weaponId) || Item::items[weaponId].proficiencyId == 0) { + g_logger().warn("{} - Skipping invalid weapon proficiency data for weapon ID '{}' (player: {})", __FUNCTION__, parsedId, m_player.getName()); + continue; + } + + if (auto val = wp_kv->get(key); val.has_value()) { + proficiency[weaponId] = deserialize(val.value()); + } + } +} + +void WeaponProficiency::save(uint16_t weaponId) const { + if (auto it = proficiency.find(weaponId); it != proficiency.end()) { + m_player.kv()->scoped("weapon-proficiency")->set(std::to_string(weaponId), serialize(it->second)); + } +} + +bool WeaponProficiency::saveAll() const { + auto wp_kv = m_player.kv()->scoped("weapon-proficiency"); + for (const auto &[weaponId, weaponData] : proficiency) { + wp_kv->set(std::to_string(weaponId), serialize(weaponData)); + } + + return true; +} + +WeaponProficiencyData WeaponProficiency::deserialize(const ValueWrapper &val) { + auto map = val.get(); + if (map.empty()) { + return {}; + } + + WeaponProficiencyData weaponData; + if (auto expIt = map.find("experience"); expIt != map.end()) { + weaponData.experience = static_cast(expIt->second->get()); + } + if (auto masteredIt = map.find("mastered"); masteredIt != map.end()) { + weaponData.mastered = masteredIt->second->get(); + } + if (auto perksIt = map.find("perks"); perksIt != map.end()) { + weaponData.perks = deserializePerks(perksIt->second->getVariant()); + } + + return weaponData; +} + +std::vector WeaponProficiency::deserializePerks(const ValueWrapper &val) { + auto array = val.get(); + if (array.empty()) { + return {}; + } + + std::vector perks; + + for (const auto &item : array) { + (void)perks.emplace_back(deserializePerk(item)); + } + + return perks; +} + +ProficiencyPerk WeaponProficiency::deserializePerk(const ValueWrapper &val) { + auto map = val.get(); + if (map.empty()) { + return {}; + } + + ProficiencyPerk perk; + + auto getInt = [&](const std::string &key) -> int64_t { + if (auto it = map.find(key); it != map.end()) { + return it->second->get(); + } + return 0; + }; + + perk.index = static_cast(getInt("index")); + perk.type = static_cast(getInt("type")); + if (auto it = map.find("value"); it != map.end()) { + perk.value = it->second->get(); + } + perk.level = static_cast(getInt("level")); + perk.augmentType = static_cast(getInt("augmentType")); + perk.bestiaryId = static_cast(getInt("bestiaryId")); + if (auto it = map.find("bestiaryName"); it != map.end()) { + perk.bestiaryName = it->second->get(); + } + perk.element = static_cast(getInt("element")); + perk.range = static_cast(getInt("range")); + perk.skillId = static_cast(getInt("skillId")); + perk.spellId = static_cast(getInt("spellId")); + + return perk; +} + +ValueWrapper WeaponProficiency::serialize(const WeaponProficiencyData &weaponData) const { + return { + std::pair { "experience", ValueWrapper(static_cast(weaponData.experience)) }, + std::pair { "mastered", ValueWrapper(weaponData.mastered) }, + std::pair { "perks", serializePerks(weaponData.perks) }, + }; +} + +ValueWrapper WeaponProficiency::serializePerk(const ProficiencyPerk &perk) const { + return { + { "index", static_cast(perk.index) }, + { "type", static_cast(perk.type) }, + { "value", perk.value }, + { "level", static_cast(perk.level) }, + { "augmentType", static_cast(perk.augmentType) }, + { "bestiaryId", static_cast(perk.bestiaryId) }, + { "bestiaryName", static_cast(perk.bestiaryName) }, + { "element", static_cast(perk.element) }, + { "range", static_cast(perk.range) }, + { "skillId", static_cast(perk.skillId) }, + { "spellId", static_cast(perk.spellId) }, + }; +} + +std::vector WeaponProficiency::serializePerks(const std::vector &perks) const { + std::vector arrayWrapper; + for (const auto &perk : perks) { + (void)arrayWrapper.emplace_back(serializePerk(perk)); + } + + return arrayWrapper; +} + +void WeaponProficiency::applyPerks(uint16_t weaponId) { + using enum WeaponProficiencyBonus_t; + + const auto &perks = getSelectedPerks(weaponId); + for (const auto &selectedPerk : perks) { + switch (selectedPerk.type) { + case SPELL_AUGMENT: { + WeaponProficiencySpells::Bonus augmentBonus; + switch (selectedPerk.augmentType) { + case AugmentType::DAMAGE: + augmentBonus.increase.damage = selectedPerk.value; + break; + case AugmentType::HEAL: + augmentBonus.increase.heal = selectedPerk.value; + break; + case AugmentType::COOLDOWN: + augmentBonus.decrease.cooldown = std::abs(selectedPerk.value); + break; + case AugmentType::LIFE_LEECH: + augmentBonus.leech.life = selectedPerk.value; + break; + case AugmentType::MANA_LEECH: + augmentBonus.leech.mana = selectedPerk.value; + break; + case AugmentType::CRITICAL_DAMAGE: + augmentBonus.increase.criticalDamage = selectedPerk.value; + break; + case AugmentType::CRITICAL_CHANCE: + augmentBonus.increase.criticalChance = selectedPerk.value; + break; + default: + g_logger().error("[{}] - Unknown augment type {}", __FUNCTION__, selectedPerk.augmentType); + continue; + } + addSpellBonus(selectedPerk.spellId, augmentBonus); + break; + } + case SPECIALIZED_MAGIC_LEVEL: + addSpecializedMagic(selectedPerk.element, selectedPerk.value); + break; + case AUTO_ATTACK_CRITICAL_EXTRA_DAMAGE: + case AUTO_ATTACK_CRITICAL_HIT_CHANCE: + case ELEMENTAL_HIT_CHANCE: + case ELEMENTAL_CRITICAL_EXTRA_DAMAGE: + case RUNE_CRITICAL_HIT_CHANCE: + case RUNE_CRITICAL_EXTRA_DAMAGE: + case CRITICAL_HIT_CHANCE: + case CRITICAL_EXTRA_DAMAGE: + applyCriticalBonus(selectedPerk); + break; + case WEAPON_PROFICIENCY_BESTIARY: + addBestiaryDamage(selectedPerk.bestiaryId, selectedPerk.value); + break; + case POWERFUL_FOE_BONUS: + addPowerfulFoeDamage(selectedPerk.value); + break; + case SKILL_BONUS: + addSkillBonus(selectedPerk.skillId, selectedPerk.value); + break; + case LIFE_LEECH: + case MANA_LEECH: + addSkillBonus(selectedPerk.type == LIFE_LEECH ? SKILL_LIFE_LEECH_AMOUNT : SKILL_MANA_LEECH_AMOUNT, selectedPerk.value * 10000); + break; + case PERFECT_SHOT_DAMAGE: + setPerfectShotBonus(selectedPerk.range, selectedPerk.value); + break; + case SKILL_PERCENTAGE_AUTO_ATTACK: + case SKILL_PERCENTAGE_SPELL_DAMAGE: + case SKILL_PERCENTAGE_SPELL_HEALING: + applySkillPercentageBonus(selectedPerk); + break; + default: + addStat(selectedPerk.type, selectedPerk.value); + break; + } + } + + m_player.sendSkills(); +} + +void WeaponProficiency::applyCriticalBonus(const ProficiencyPerk &perk) { + using enum WeaponProficiencyBonus_t; + WeaponProficiencyCriticalBonus criticalBonus; + criticalBonus.chance = (perk.type == AUTO_ATTACK_CRITICAL_HIT_CHANCE || perk.type == ELEMENTAL_HIT_CHANCE || perk.type == RUNE_CRITICAL_HIT_CHANCE || perk.type == CRITICAL_HIT_CHANCE) ? perk.value : 0; + criticalBonus.damage = (perk.type == AUTO_ATTACK_CRITICAL_EXTRA_DAMAGE || perk.type == ELEMENTAL_CRITICAL_EXTRA_DAMAGE || perk.type == RUNE_CRITICAL_EXTRA_DAMAGE || perk.type == CRITICAL_EXTRA_DAMAGE) ? perk.value : 0; + + switch (perk.type) { + case AUTO_ATTACK_CRITICAL_EXTRA_DAMAGE: + case AUTO_ATTACK_CRITICAL_HIT_CHANCE: + addAutoAttackCritical(criticalBonus); + break; + case ELEMENTAL_HIT_CHANCE: + case ELEMENTAL_CRITICAL_EXTRA_DAMAGE: + addElementCritical(perk.element, criticalBonus); + break; + case RUNE_CRITICAL_HIT_CHANCE: + case RUNE_CRITICAL_EXTRA_DAMAGE: + addRunesCritical(criticalBonus); + break; + case CRITICAL_HIT_CHANCE: + case CRITICAL_EXTRA_DAMAGE: + addGeneralCritical(criticalBonus); + break; + default: + break; + } +} + +void WeaponProficiency::applySkillPercentageBonus(const ProficiencyPerk &perk) { + using enum WeaponProficiencyBonus_t; + using enum SkillPercentage_t; + SkillPercentage_t type; + switch (perk.type) { + case SKILL_PERCENTAGE_AUTO_ATTACK: + type = AutoAttack; + break; + case SKILL_PERCENTAGE_SPELL_DAMAGE: + type = SpellDamage; + break; + case SKILL_PERCENTAGE_SPELL_HEALING: + type = SpellHealing; + break; + default: + return; + } + addSkillPercentage(perk.skillId, type, perk.value); +} + +std::vector WeaponProficiency::getSelectedPerks(uint16_t weaponId) const { + if (auto it = proficiency.find(weaponId); it != proficiency.end()) { + return it->second.perks; + } + + return {}; +} + +void WeaponProficiency::clearSelectedPerks(uint16_t weaponId) { + if (weaponId == 0) { + return; + } + + if (auto it = proficiency.find(weaponId); it != proficiency.end()) { + it->second.perks.clear(); + } +} + +void WeaponProficiency::setSelectedPerk(uint8_t level, uint8_t perkIndex, uint16_t weaponId /* = 0 */) { + using enum WeaponProficiencyBonus_t; + + if (weaponId == 0) { + weaponId = m_player.getWeaponId(true); + } + + if (weaponId == 0) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return; + } + + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Weapon ID out of range: {}", __FUNCTION__, weaponId); + return; + } + + auto proficiencyId = Item::items[weaponId].proficiencyId; + if (!proficiencies.contains(proficiencyId)) { + g_logger().error("{} - Proficiency not found for weapon ID: {}", __FUNCTION__, weaponId); + return; + } + + const auto &info = proficiencies.at(proficiencyId); + if (level >= info.level.size()) { + g_logger().error("{} - Proficiency level exceeds maximum size for weapon ID: {}", __FUNCTION__, weaponId); + return; + } + const auto &selectedLevel = info.level.at(level); + + if (perkIndex >= selectedLevel.perks.size()) { + g_logger().error("{} - Proficiency level {} exceeds maximum perks size for weapon ID: {}", __FUNCTION__, level, weaponId); + return; + } + const auto &selectedPerk = selectedLevel.perks.at(perkIndex); + + if (auto it = proficiency.find(weaponId); it != proficiency.end()) { + it->second.perks.push_back(selectedPerk); + } +} + +std::unordered_map, double, PairHash, PairEqual> WeaponProficiency::getActiveAugments(uint16_t weaponId) { + std::unordered_map, double, PairHash, PairEqual> augments; + + weaponId = weaponId == 0 ? m_player.getWeaponId(true) : weaponId; + + if (weaponId == 0) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return augments; + } + + const auto &perks = getSelectedPerks(weaponId); + + for (const auto &perk : perks) { + if (perk.spellId && perk.augmentType) { + const auto key = std::make_pair(perk.spellId, perk.augmentType); + augments[key] += perk.value; + } + } + + return augments; +} + +const std::vector &WeaponProficiency::getExperienceArray(uint16_t weaponId) const { + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return standardExperience; + } + + const auto &itemType = Item::items[weaponId]; + if (itemType.ammoType == AMMO_BOLT) { + return crossbowExperience; + } + + const auto weaponType = itemType.weaponType; + if (weaponType == WEAPON_SWORD || weaponType == WEAPON_CLUB || weaponType == WEAPON_AXE) { + return knightExperience; + } + + return standardExperience; +} + +uint32_t WeaponProficiency::nextLevelExperience(uint16_t weaponId) { + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return 0; + } + + const auto &experienceArray = getExperienceArray(weaponId); + + auto prof_it = proficiencies.find(Item::items[weaponId].proficiencyId); + if (prof_it == proficiencies.end()) { + g_logger().error("{} - Proficiency not found for weapon ID: {}", __FUNCTION__, weaponId); + return 0; + } + + const auto &proficiencyInfo = prof_it->second; + if (!proficiency.contains(weaponId)) { + return experienceArray[0]; + } + + const auto &playerProficiency = proficiency.at(weaponId); + if (proficiencyInfo.maxLevel == 0) { + return 0; + } + const auto maxExpLevels = static_cast(std::min(experienceArray.size(), proficiencyInfo.maxLevel - 1)); + for (uint8_t i = 0; i < maxExpLevels; ++i) { + if (playerProficiency.experience >= experienceArray[i]) { + continue; + } + + return experienceArray[i] - playerProficiency.experience; + } + + return 0; +} + +uint32_t WeaponProficiency::getMaxExperience(uint16_t weaponId) const { + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return 0; + } + + const auto &experienceArray = getExperienceArray(weaponId); + auto prof_it = proficiencies.find(Item::items[weaponId].proficiencyId); + if (prof_it == proficiencies.end()) { + g_logger().error("{} - Proficiency not found for weapon ID: {}", __FUNCTION__, weaponId); + return 0; + } + + const auto &proficiencyInfo = prof_it->second; + if (experienceArray.empty()) { + return 0; + } + + if (!proficiency.contains(weaponId)) { + return experienceArray.back(); + } + + if (proficiencyInfo.maxLevel == 0) { + return 0; + } + size_t masteryIndex = std::min(experienceArray.size(), static_cast(proficiencyInfo.maxLevel - 1)); + if (masteryIndex > 0) { + return experienceArray[masteryIndex - 1]; + } + return 0; +} + +void WeaponProficiency::addExperience(uint32_t experience, uint16_t weaponId /* = 0 */) { + weaponId = weaponId > 0 ? weaponId : m_player.getWeaponId(true); + + if (weaponId == 0) { + return; + } + + // Validate that the item has a valid proficiency + if (!isValidWeaponId(weaponId) || Item::items[weaponId].proficiencyId == 0) { + g_logger().debug("{} - Weapon ID '{}' has no proficiency assigned", __FUNCTION__, weaponId); + return; + } + + if (nextLevelExperience(weaponId) <= 0) { + return; + } + + uint32_t maxExperience = getMaxExperience(weaponId); + + if (!proficiency.contains(weaponId)) { + (void)proficiency.try_emplace(weaponId, std::min(experience, maxExperience)); + m_player.sendWeaponProficiency(weaponId); + + return; + } + + uint32_t newExperience = proficiency[weaponId].experience + experience; + + if (newExperience >= maxExperience) { + proficiency[weaponId].mastered = true; + proficiency[weaponId].experience = maxExperience; + m_player.sendWeaponProficiency(weaponId); + + return; + } + + proficiency[weaponId].experience = newExperience; + + m_player.sendWeaponProficiency(weaponId); +} + +uint32_t WeaponProficiency::getBosstiaryExperience(BosstiaryRarity_t rarity) const { + using enum BosstiaryRarity_t; + switch (rarity) { + case RARITY_BANE: + return 500; + case RARITY_ARCHFOE: + return 5000; + case RARITY_NEMESIS: + return 15000; + default: + return 0; + } +} + +uint32_t WeaponProficiency::getBestiaryExperience(uint8_t monsterStar) const { + if (monsterStar > 5) { // Assuming 5 is max star + monsterStar = 5; + } + double poly = -1.133 * std::pow(monsterStar, 5) + 14.083 * std::pow(monsterStar, 4) + -59.666 * std::pow(monsterStar, 3) + 102.916 * std::pow(monsterStar, 2) + -27.2 * monsterStar + 1.0; + return static_cast(std::max(0.0, poly)); +} + +uint32_t WeaponProficiency::getExperience(uint16_t weaponId /* = 0 */) const { + if (!proficiency.contains(weaponId)) { + return 0; + } + + return proficiency.at(weaponId).experience; +} + +bool WeaponProficiency::isUpgradeAvailable(uint16_t weaponId /* = 0 */) const { + weaponId = weaponId > 0 ? weaponId : m_player.getWeaponId(true); + + if (weaponId == 0) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return false; + } + + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Weapon ID out of range: {}", __FUNCTION__, weaponId); + return false; + } + + const auto &experienceArray = getExperienceArray(weaponId); + + auto proficiencyId = Item::items[weaponId].proficiencyId; + + if (!proficiency.contains(weaponId)) { + return false; + } + + if (!proficiencies.contains(proficiencyId)) { + return false; + } + + const auto &proficiencyInfo = proficiencies.at(proficiencyId); + + const auto &playerProficiency = proficiency.at(weaponId); + + size_t limit = std::min(experienceArray.size(), static_cast(proficiencyInfo.maxLevel)); + for (size_t i = 0; i < limit; ++i) { + if (playerProficiency.experience < experienceArray[i]) { + break; + } + + if (playerProficiency.perks.size() < i + 1) { + return true; + } + } + + return false; +} + +void WeaponProficiency::addStat(WeaponProficiencyBonus_t type, double_t value) { + auto enumValue = static_cast(type); + if (enumValue >= magic_enum::enum_count()) { + g_logger().error("[{}]. Type {} is out of range, value {}. Error message: {}", __FUNCTION__, enumValue, value, "Enum value is out of range"); + return; + } + m_stats[enumValue] += value; +} + +double_t WeaponProficiency::getStat(WeaponProficiencyBonus_t type) const { + auto enumValue = static_cast(type); + try { + return m_stats.at(enumValue); + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Instant type {}. Error message: {}", __FUNCTION__, enumValue, e.what()); + } + return 0; +} + +void WeaponProficiency::resetStats() { + m_stats.fill(0); +} + +void WeaponProficiency::addSkillPercentage(skills_t skill, SkillPercentage_t type, double_t value) { + using enum SkillPercentage_t; + auto &skillPercentage = m_skillPercentages[skill]; + skillPercentage.skill = skill; + + switch (type) { + case AutoAttack: + skillPercentage.autoAttack += value; + break; + case SpellDamage: + skillPercentage.spellDamage += value; + break; + case SpellHealing: + skillPercentage.spellHealing += value; + break; + default: + break; + } +} + +const SkillPercentage &WeaponProficiency::getSkillPercentage(skills_t skill) const { + static const SkillPercentage defaultSkillPercentage; + if (auto it = m_skillPercentages.find(skill); it != m_skillPercentages.end()) { + return it->second; + } + return defaultSkillPercentage; +} + +void WeaponProficiency::addSpecializedMagic(CombatType_t type, uint16_t value) { + auto enumValue = static_cast(type); + try { + m_specializedMagic.at(enumValue) += value; + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Type {} is out of range, value {}. Error message: {}", __FUNCTION__, enumValue, value, e.what()); + } +} + +uint16_t WeaponProficiency::getSpecializedMagic(CombatType_t type) const { + auto enumValue = static_cast(type); + try { + return m_specializedMagic.at(enumValue); + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Instant type {}. Error message: {}", __FUNCTION__, enumValue, e.what()); + } + return 0; +} + +void WeaponProficiency::resetSpecializedMagic() { + m_specializedMagic.fill(0); +} + +uint32_t WeaponProficiency::getSkillBonus(skills_t type) const { + auto enumValue = static_cast(type); + try { + return m_skills.at(enumValue); + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Skill type {}. Error message: {}", __FUNCTION__, enumValue, e.what()); + } + return 0; +} + +void WeaponProficiency::addSkillBonus(skills_t type, uint32_t value) { + auto enumValue = static_cast(type); + try { + m_skills.at(enumValue) += value; + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Type {} is out of range, value {}. Error message: {}", __FUNCTION__, enumValue, value, e.what()); + } +} + +void WeaponProficiency::resetSkillBonuses() { + m_skills.fill(0); +} + +double_t WeaponProficiency::getPowerfulFoeDamage() const { + return m_powerfulFoeDamage; +} + +void WeaponProficiency::addPowerfulFoeDamage(double_t percent) { + m_powerfulFoeDamage += percent; +} + +void WeaponProficiency::resetPowerfulFoeDamage() { + m_powerfulFoeDamage = 0; +} + +const WeaponProficiencyCriticalBonus &WeaponProficiency::getAutoAttackCritical() const { + return m_autoAttackCritical; +} + +void WeaponProficiency::addAutoAttackCritical(const WeaponProficiencyCriticalBonus &bonus) { + m_autoAttackCritical.chance += bonus.chance; + m_autoAttackCritical.damage += bonus.damage; +} + +const WeaponProficiencyCriticalBonus &WeaponProficiency::getRunesCritical() const { + return m_runesCritical; +} + +void WeaponProficiency::addRunesCritical(const WeaponProficiencyCriticalBonus &bonus) { + m_runesCritical.chance += bonus.chance; + m_runesCritical.damage += bonus.damage; +} + +const WeaponProficiencyCriticalBonus &WeaponProficiency::getGeneralCritical() const { + return m_generalCritical; +} + +void WeaponProficiency::addGeneralCritical(const WeaponProficiencyCriticalBonus &bonus) { + m_generalCritical.chance += bonus.chance; + m_generalCritical.damage += bonus.damage; +} + +WeaponProficiencyCriticalBonus WeaponProficiency::getElementCritical(CombatType_t type) const { + if (type == COMBAT_NONE) { + return {}; + } + const auto enumValue = static_cast(type); + if (enumValue < m_elementCritical.size()) { + return m_elementCritical[enumValue]; + } + g_logger().error("[{}]. Element type {} is out of range.", __FUNCTION__, enumValue); + return {}; +} + +void WeaponProficiency::addElementCritical(CombatType_t type, const WeaponProficiencyCriticalBonus &bonus) { + if (type == COMBAT_NONE) { + return; + } + + const auto enumValue = static_cast(type); + if (enumValue >= m_elementCritical.size()) { + g_logger().error("[{}]. Type {} is out of range.", __FUNCTION__, enumValue); + return; + } + + m_elementCritical[enumValue].chance += bonus.chance; + m_elementCritical[enumValue].damage += bonus.damage; +} + +uint32_t WeaponProficiency::getSpellBonus(uint16_t spellId, WeaponProficiencySpellBoost_t boost) const { + using enum WeaponProficiencySpellBoost_t; + + auto it = m_spellsBonuses.find(spellId); + if (it == m_spellsBonuses.end()) { + return 0; + } + + const auto &[leech, increase, decrease] = it->second; + switch (boost) { + case COOLDOWN: + return decrease.cooldown; + case MANA: + return decrease.manaCost; + case SECONDARY_GROUP_COOLDOWN: + return decrease.secondaryGroupCooldown; + case CRITICAL_CHANCE: + return increase.criticalChance; + case CRITICAL_DAMAGE: + return increase.criticalDamage; + case DAMAGE: + return increase.damage; + case DAMAGE_REDUCTION: + return increase.damageReduction; + case HEAL: + return increase.heal; + case LIFE_LEECH: + return leech.life; + case MANA_LEECH: + return leech.mana; + default: + return 0; + } +} + +void WeaponProficiency::addSpellBonus(uint16_t spellId, const WeaponProficiencySpells::Bonus &bonus) { + if (auto it = m_spellsBonuses.find(spellId); it != m_spellsBonuses.end()) { + it->second.decrease.cooldown += bonus.decrease.cooldown; + it->second.decrease.manaCost += bonus.decrease.manaCost; + it->second.decrease.secondaryGroupCooldown += bonus.decrease.secondaryGroupCooldown; + it->second.increase.additionalTarget += bonus.increase.additionalTarget; + it->second.increase.area = it->second.increase.area || bonus.increase.area; + it->second.increase.criticalChance += bonus.increase.criticalChance; + it->second.increase.criticalDamage += bonus.increase.criticalDamage; + it->second.increase.damage += bonus.increase.damage; + it->second.increase.damageReduction += bonus.increase.damageReduction; + it->second.increase.duration += bonus.increase.duration; + it->second.increase.heal += bonus.increase.heal; + it->second.leech.life += bonus.leech.life; + it->second.leech.mana += bonus.leech.mana; + return; + } + m_spellsBonuses[spellId] = bonus; +} + +void WeaponProficiency::setPerfectShotBonus(uint8_t range, double_t damage) { + m_perfectShot.range = range; + m_perfectShot.damage += damage; +} + +const WeaponProficiencyPerfectShotBonus &WeaponProficiency::getPerfectShotBonus() const { + return m_perfectShot; +} + +void WeaponProficiency::resetPerfectShotBonus() { + m_perfectShot = {}; +} + +double_t WeaponProficiency::getBestiaryDamage(uint8_t race) const { + if (auto it = m_bestiaryDamage.find(race); it != m_bestiaryDamage.end()) { + return it->second; + } + + return 0; +} + +void WeaponProficiency::addBestiaryDamage(uint8_t race, double_t bonus) { + if (auto it = m_bestiaryDamage.find(race); it != m_bestiaryDamage.end()) { + it->second += bonus; + return; + } + m_bestiaryDamage[race] = bonus; +} + +void WeaponProficiency::resetBestiaryDamage() { + m_bestiaryDamage.clear(); +} + +uint16_t WeaponProficiency::getSkillValueFromWeapon() const { + const auto &weapon = m_player.getWeapon(true); + if (!weapon) { + return 0; + } + + const auto weaponId = weapon->getID(); + if (!isValidWeaponId(weaponId)) { + g_logger().error("{} - Invalid weapon ID: {}", __FUNCTION__, weaponId); + return 0; + } + + switch (Item::items[weaponId].type) { + case ITEM_TYPE_SWORD: + return m_player.getSkillLevel(SKILL_SWORD); + case ITEM_TYPE_AXE: + return m_player.getSkillLevel(SKILL_AXE); + case ITEM_TYPE_CLUB: + return m_player.getSkillLevel(SKILL_CLUB); + case ITEM_TYPE_WAND: + return m_player.getMagicLevel(); + case ITEM_TYPE_DISTANCE: + return m_player.getSkillLevel(SKILL_DISTANCE); + default: + return 0; + } +} + +void WeaponProficiency::applyAutoAttackCritical(CombatDamage &damage) const { + if (damage.origin == ORIGIN_FIST || damage.origin == ORIGIN_MELEE || damage.origin == ORIGIN_RANGED) { + const auto &autoAttackCritical = getAutoAttackCritical(); + damage.criticalChance += autoAttackCritical.chance * 10000; + damage.criticalDamage += autoAttackCritical.damage * 10000; + } +} + +void WeaponProficiency::applyRunesCritical(CombatDamage &damage, bool aggressive) const { + if (!damage.runeSpellName.empty() && aggressive) { + const auto &runesCritical = getRunesCritical(); + damage.criticalChance += runesCritical.chance * 10000; + damage.criticalDamage += runesCritical.damage * 10000; + } +} + +void WeaponProficiency::applyElementCritical(CombatDamage &damage) const { + if (damage.primary.type == COMBAT_NONE || damage.primary.type >= COMBAT_COUNT) { + return; + } + + const auto elementCritical = getElementCritical(damage.primary.type); + if (elementCritical.chance > 0 || elementCritical.damage > 0) { + damage.criticalChance += elementCritical.chance * 10000; + damage.criticalDamage += elementCritical.damage * 10000; + } +} + +void WeaponProficiency::applyBestiaryDamage(CombatDamage &damage, const std::shared_ptr &monster) const { + if (!monster) { + return; + } + const auto &monsterType = monster->getMonsterType(); + if (!monsterType) { + return; + } + + const auto race = magic_enum::enum_integer(monsterType->info.bestiaryRace); + if (race > 0) { + const auto bestiaryDamage = getBestiaryDamage(race); + damage.primary.value *= 1 + bestiaryDamage; + damage.secondary.value *= 1 + bestiaryDamage; + } +} + +void WeaponProficiency::applyBossDamage(CombatDamage &damage, const std::shared_ptr &monster) const { + using enum WeaponProficiencyBonus_t; + if (!monster) { + return; + } + + const auto mt = monster->getMonsterType(); + if (mt && mt->isBoss()) { + const auto bonusDamage = getStat(POWERFUL_FOE_BONUS); + damage.primary.value *= 1 + bonusDamage; + damage.secondary.value *= 1 + bonusDamage; + } +} + +void WeaponProficiency::applyPowerfulFoeDamage(CombatDamage &damage, const std::shared_ptr &monster) const { + using enum WeaponProficiencyBonus_t; + if (!monster) { + return; + } + + const auto forgeStack = monster->getForgeStack(); + const auto mt = monster->getMonsterType(); + if (forgeStack > 0 || (mt && mt->isBoss())) { + const auto bonusDamage = getPowerfulFoeDamage(); + damage.primary.value *= 1 + bonusDamage; + damage.secondary.value *= 1 + bonusDamage; + } +} + +void WeaponProficiency::applySkillAutoAttackPercentage(CombatDamage &damage) const { + using enum WeaponProficiencyBonus_t; + + if (damage.origin != ORIGIN_FIST && damage.origin != ORIGIN_MELEE && damage.origin != ORIGIN_RANGED) { + return; + } + + const auto &weapon = m_player.getWeapon(true); + if (!weapon) { + return; + } + + for (const auto &[skill, skillPercentage] : m_skillPercentages) { + if (skillPercentage.autoAttack <= 0) { + continue; + } + + const auto bonusDamage = m_player.getSkillLevel(skill) * skillPercentage.autoAttack; + + if (damage.primary.type != COMBAT_NONE) { + damage.primary.value -= std::ceil(bonusDamage); + } + if (damage.secondary.type != COMBAT_NONE) { + damage.secondary.value -= std::ceil(bonusDamage); + } + } +} + +void WeaponProficiency::applySkillSpellPercentage(CombatDamage &damage, bool healing) const { + using enum WeaponProficiencyBonus_t; + + if (damage.instantSpellName.empty()) { + return; + } + + if (healing && damage.primary.type != COMBAT_HEALING) { + return; + } + + const auto &weapon = m_player.getWeapon(true); + if (!weapon) { + return; + } + + for (const auto &[skill, skillPercentage] : m_skillPercentages) { + const auto skillPercentageValue = healing ? skillPercentage.spellHealing : skillPercentage.spellDamage; + if (skillPercentageValue <= 0) { + continue; + } + + const auto bonusDamage = std::ceil(m_player.getSkillLevel(skill) * skillPercentageValue); + + if (damage.primary.type != COMBAT_NONE) { + damage.primary.value += (damage.primary.value < 0 ? -bonusDamage : bonusDamage); + } + if (damage.secondary.type != COMBAT_NONE) { + damage.secondary.value += (damage.secondary.value < 0 ? -bonusDamage : bonusDamage); + } + } +} + +void WeaponProficiency::applyOn(WeaponProficiencyHealth_t healthType, WeaponProficiencyGain_t gainType) const { + using enum WeaponProficiencyBonus_t; + + WeaponProficiencyBonus_t statsType; + if (healthType == WeaponProficiencyHealth_t::LIFE) { + statsType = gainType == WeaponProficiencyGain_t::KILL ? LIFE_GAIN_ON_KILL : LIFE_GAIN_ON_HIT; + } else { + statsType = gainType == WeaponProficiencyGain_t::KILL ? MANA_GAIN_ON_KILL : MANA_GAIN_ON_HIT; + } + + CombatParams params; + params.combatType = COMBAT_HEALING; + params.soundImpactEffect = SoundEffect_t::SPELL_LIGHT_HEALING; + + CombatDamage damage; + + damage.origin = ORIGIN_WEAPON_PROFICIENCY; + + damage.primary.type = params.combatType; + damage.primary.value = getStat(statsType); + + const auto &playerCreature = m_player.getCreature(); + if (healthType == WeaponProficiencyHealth_t::LIFE) { + Combat::doCombatHealth(nullptr, playerCreature, damage, params); + } else { + Combat::doCombatMana(nullptr, playerCreature, damage, params); + } +} + +void WeaponProficiency::applySpellAugment(CombatDamage &damage, uint16_t spellId) const { + if (auto it = m_spellsBonuses.find(spellId); it != m_spellsBonuses.end()) { + damage.damageMultiplier += it->second.increase.damage * 10000; + damage.healingMultiplier += it->second.increase.heal * 10000; + damage.criticalChance += it->second.increase.criticalChance * 10000; + damage.criticalDamage += it->second.increase.criticalDamage * 10000; + damage.lifeLeech += it->second.leech.life * 10000; + damage.manaLeech += it->second.leech.mana * 10000; + } +} + +std::vector> WeaponProficiency::getActiveBestiariesDamage() const { + using enum WeaponProficiencyBonus_t; + std::vector> bestiariesDamage; + + const auto weaponId = m_player.getWeaponId(true); + + const auto &perks = getSelectedPerks(weaponId); + for (const auto &perk : perks) { + if (perk.type == WEAPON_PROFICIENCY_BESTIARY && !perk.bestiaryName.empty()) { + (void)bestiariesDamage.emplace_back(perk.bestiaryName, perk.value); + } + } + + return bestiariesDamage; +} + +std::optional> WeaponProficiency::getActiveElementalCriticalType(WeaponProficiencyBonus_t criticalType) const { + using enum WeaponProficiencyBonus_t; + + if (criticalType != ELEMENTAL_HIT_CHANCE && criticalType != ELEMENTAL_CRITICAL_EXTRA_DAMAGE) { + return std::nullopt; + } + + const auto weaponId = m_player.getWeaponId(true); + + const auto &perks = getSelectedPerks(weaponId); + auto it = std::ranges::find_if(perks, [&](const auto &perk) { + return perk.type == criticalType && perk.element != COMBAT_NONE; + }); + + if (it != perks.end()) { + return std::make_pair(getCipbiaElement(it->element), it->value); + } + + return std::nullopt; +} + +void WeaponProficiency::clearAllStats() { + resetStats(); + resetSpecializedMagic(); + resetSkillBonuses(); + resetPowerfulFoeDamage(); + resetBestiaryDamage(); + + m_skillPercentages.clear(); + m_autoAttackCritical.clear(); + m_runesCritical.clear(); + m_generalCritical.clear(); + m_elementCritical.fill({}); + m_spellsBonuses.clear(); + resetPerfectShotBonus(); +} diff --git a/src/creatures/players/components/weapon_proficiency.hpp b/src/creatures/players/components/weapon_proficiency.hpp new file mode 100644 index 00000000000..07e1ae3af03 --- /dev/null +++ b/src/creatures/players/components/weapon_proficiency.hpp @@ -0,0 +1,160 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#include "enums/weapon_proficiency.hpp" +#include "creatures/creatures_definitions.hpp" +#include "utils/hash.hpp" + +enum class BosstiaryRarity_t : uint8_t; + +class Monster; +class Player; +class ValueWrapper; + +struct WeaponProficiencyData; +struct Proficiency; + +class WeaponProficiency { +public: + explicit WeaponProficiency(Player &player); + + [[nodiscard]] static bool loadFromJson(bool reload = false); + + [[nodiscard]] static std::unordered_map &getProficiencies(); + + void load(); + void save(uint16_t weaponId) const; + bool saveAll() const; + + static WeaponProficiencyData deserialize(const ValueWrapper &val); + static ProficiencyPerk deserializePerk(const ValueWrapper &val); + static std::vector deserializePerks(const ValueWrapper &val); + ValueWrapper serialize(const WeaponProficiencyData &weaponData) const; + ValueWrapper serializePerk(const ProficiencyPerk &perk) const; + std::vector serializePerks(const std::vector &perks) const; + + void applyPerks(uint16_t weaponId); + std::vector getSelectedPerks(uint16_t itemId) const; + void clearSelectedPerks(uint16_t weaponId); + void setSelectedPerk(uint8_t level, uint8_t perkIndex, uint16_t weaponId = 0); + std::unordered_map, double, PairHash, PairEqual> getActiveAugments(uint16_t weaponId = 0); + const std::vector &getExperienceArray(uint16_t weaponId) const; + uint32_t nextLevelExperience(uint16_t weaponId); + uint32_t getMaxExperience(uint16_t weaponId) const; + void addExperience(uint32_t experience, uint16_t weaponId = 0); + [[nodiscard]] uint32_t getBosstiaryExperience(BosstiaryRarity_t rarity) const; + [[nodiscard]] uint32_t getBestiaryExperience(uint8_t monsterStar) const; + [[nodiscard]] uint32_t getExperience(uint16_t weaponId = 0) const; + [[nodiscard]] bool isUpgradeAvailable(uint16_t weaponId = 0) const; + + void addStat(WeaponProficiencyBonus_t stat, double_t value); + [[nodiscard]] double_t getStat(WeaponProficiencyBonus_t stat) const; + void resetStats(); + + void addSkillPercentage(skills_t skill, SkillPercentage_t type, double_t value); + + [[nodiscard]] uint16_t getSpecializedMagic(CombatType_t type) const; + void addSpecializedMagic(CombatType_t type, uint16_t value); + void resetSpecializedMagic(); + + [[nodiscard]] uint32_t getSkillBonus(skills_t type) const; + void addSkillBonus(skills_t type, uint32_t value); + void resetSkillBonuses(); + + [[nodiscard]] double_t getPowerfulFoeDamage() const; + void addPowerfulFoeDamage(double_t percent); + void resetPowerfulFoeDamage(); + + [[nodiscard]] const WeaponProficiencyCriticalBonus &getAutoAttackCritical() const; + void addAutoAttackCritical(const WeaponProficiencyCriticalBonus &bonus); + + [[nodiscard]] const WeaponProficiencyCriticalBonus &getRunesCritical() const; + void addRunesCritical(const WeaponProficiencyCriticalBonus &bonus); + + [[nodiscard]] const WeaponProficiencyCriticalBonus &getGeneralCritical() const; + void addGeneralCritical(const WeaponProficiencyCriticalBonus &bonus); + + [[nodiscard]] WeaponProficiencyCriticalBonus getElementCritical(CombatType_t type) const; + void addElementCritical(CombatType_t type, const WeaponProficiencyCriticalBonus &bonus); + + [[nodiscard]] uint32_t getSpellBonus(uint16_t spellId, WeaponProficiencySpellBoost_t boost) const; + void addSpellBonus(uint16_t spellId, const WeaponProficiencySpells::Bonus &bonus); + + void setPerfectShotBonus(uint8_t range, double_t damage); + [[nodiscard]] const WeaponProficiencyPerfectShotBonus &getPerfectShotBonus() const; + void resetPerfectShotBonus(); + + [[nodiscard]] double_t getBestiaryDamage(uint8_t raceId) const; + void addBestiaryDamage(uint8_t raceId, double_t bonus); + void resetBestiaryDamage(); + + [[nodiscard]] uint16_t getSkillValueFromWeapon() const; + + void applyAutoAttackCritical(CombatDamage &damage) const; + void applyRunesCritical(CombatDamage &damage, bool aggressive) const; + void applyElementCritical(CombatDamage &damage) const; + + void applyBestiaryDamage(CombatDamage &damage, const std::shared_ptr &monster) const; + void applyBossDamage(CombatDamage &damage, const std::shared_ptr &monster) const; + void applyPowerfulFoeDamage(CombatDamage &damage, const std::shared_ptr &monster) const; + + void applySkillAutoAttackPercentage(CombatDamage &damage) const; + void applySkillSpellPercentage(CombatDamage &damage, bool healing = false) const; + + void applyOn(WeaponProficiencyHealth_t healthType, WeaponProficiencyGain_t gainType) const; + + void applySpellAugment(CombatDamage &damage, uint16_t spellId) const; + + [[nodiscard]] const SkillPercentage &getSkillPercentage(skills_t skill) const; + + [[nodiscard]] std::vector> getActiveBestiariesDamage() const; + [[nodiscard]] std::optional> getActiveElementalCriticalType(WeaponProficiencyBonus_t criticalType) const; + + void clearAllStats(); + +private: + void applyCriticalBonus(const ProficiencyPerk &perk); + void applySkillPercentageBonus(const ProficiencyPerk &perk); + + [[nodiscard]] bool isValidWeaponId(uint16_t weaponId) const; + + Player &m_player; + + std::unordered_map proficiency; + + static std::unordered_map proficiencies; + + static std::vector crossbowExperience; + static std::vector standardExperience; + static std::vector knightExperience; + + std::array() + 1> m_stats = { 0 }; + + std::unordered_map m_skillPercentages; + + std::array m_specializedMagic = { 0 }; + + std::array m_skills = { 0 }; + + double_t m_powerfulFoeDamage = 0; + + WeaponProficiencyCriticalBonus m_autoAttackCritical; + WeaponProficiencyCriticalBonus m_runesCritical; + WeaponProficiencyCriticalBonus m_generalCritical; + + std::array m_elementCritical = { 0 }; + + std::unordered_map m_spellsBonuses; + + WeaponProficiencyPerfectShotBonus m_perfectShot; + + std::unordered_map m_bestiaryDamage; +}; diff --git a/src/creatures/players/components/wheel/player_wheel.cpp b/src/creatures/players/components/wheel/player_wheel.cpp index 8777285c857..f63b5ea9356 100644 --- a/src/creatures/players/components/wheel/player_wheel.cpp +++ b/src/creatures/players/components/wheel/player_wheel.cpp @@ -326,8 +326,8 @@ namespace { g_logger().debug("spell target stage {}, grade {}", stage, size); if (spellTable.name == spellName && stage < static_cast(size)) { const auto &spellData = spellTable.grade[stage]; - if (spellData.increase.aditionalTarget) { - return spellData.increase.aditionalTarget; + if (spellData.increase.additionalTarget) { + return spellData.increase.additionalTarget; } } } @@ -1313,7 +1313,7 @@ void PlayerWheel::addSpellBonus(const std::string &spellName, const WheelSpells: m_spellsBonuses[spellName].decrease.cooldown += bonus.decrease.cooldown; m_spellsBonuses[spellName].decrease.manaCost += bonus.decrease.manaCost; m_spellsBonuses[spellName].decrease.secondaryGroupCooldown += bonus.decrease.secondaryGroupCooldown; - m_spellsBonuses[spellName].increase.aditionalTarget += bonus.increase.aditionalTarget; + m_spellsBonuses[spellName].increase.additionalTarget += bonus.increase.additionalTarget; m_spellsBonuses[spellName].increase.area = bonus.increase.area; m_spellsBonuses[spellName].increase.criticalChance += bonus.increase.criticalChance; m_spellsBonuses[spellName].increase.criticalDamage += bonus.increase.criticalDamage; @@ -2560,6 +2560,44 @@ void PlayerWheel::loadDedicationAndConvictionPerks() { } } +std::unordered_map, double, PairHash, PairEqual> PlayerWheel::getActiveAugments() const { + std::unordered_map, double, PairHash, PairEqual> wheelAugments; + + const auto &ioBonusData = g_game().getIOWheel()->getWheelBonusData(); + + auto registerAugment = [&](const uint16_t currentSpellId, const std::string &spellName, uint8_t grade) { + const auto vocationBaseId = m_player.getVocation()->getBaseId(); + if (vocationBaseId == Vocation_t::VOCATION_SORCERER) { + getAugmentsByVocation(currentSpellId, spellName, grade, ioBonusData.spells.sorcerer, wheelAugments); + } else if (vocationBaseId == Vocation_t::VOCATION_DRUID) { + getAugmentsByVocation(currentSpellId, spellName, grade, ioBonusData.spells.druid, wheelAugments); + } else if (vocationBaseId == Vocation_t::VOCATION_PALADIN) { + getAugmentsByVocation(currentSpellId, spellName, grade, ioBonusData.spells.paladin, wheelAugments); + } else if (vocationBaseId == Vocation_t::VOCATION_KNIGHT) { + getAugmentsByVocation(currentSpellId, spellName, grade, ioBonusData.spells.knight, wheelAugments); + } else if (vocationBaseId == Vocation_t::VOCATION_MONK) { + getAugmentsByVocation(currentSpellId, spellName, grade, ioBonusData.spells.monk, wheelAugments); + } + }; + + std::unordered_map spellGrades; + for (const auto &spellName : m_playerBonusData.spells) { + const auto &spell = g_spells().getSpellByName(spellName); + if (!spell) { + continue; + } + + auto spellId = spell->getSpellId(); + spellGrades[spellId]++; + + uint8_t grade = spellGrades[spellId]; + + registerAugment(spellId, spellName, grade); + } + + return wheelAugments; +} + void PlayerWheel::addSpellToVector(const std::string &spellName) { m_playerBonusData.spells.emplace_back(spellName); } diff --git a/src/creatures/players/components/wheel/player_wheel.hpp b/src/creatures/players/components/wheel/player_wheel.hpp index 7aa5d39ad48..3cde96a19d8 100644 --- a/src/creatures/players/components/wheel/player_wheel.hpp +++ b/src/creatures/players/components/wheel/player_wheel.hpp @@ -12,6 +12,8 @@ #include "creatures/creatures_definitions.hpp" #include "creatures/players/components/wheel/wheel_definitions.hpp" #include "creatures/players/components/wheel/wheel_spells.hpp" +#include "utils/hash.hpp" +#include "items/items_definitions.hpp" class Creature; class IOWheel; @@ -177,6 +179,50 @@ class PlayerWheel { void loadDedicationAndConvictionPerks(); + template + void getAugmentsByVocation( + const uint16_t spellId, + const std::string &spellName, + uint8_t grade, + const VocationArray &vocSpells, + std::unordered_map, double, PairHash, PairEqual> &map + ) const { + // helper: add or accumulate value into map + auto addValue = [&](Augment_t augmentType, double value) { + if (value == 0.0) { + return; + } + const auto key = std::make_pair(spellId, magic_enum::enum_integer(augmentType)); + map[key] += value; + }; + + for (const auto &spellBonus : vocSpells) { + if (spellBonus.name != spellName) { + continue; + } + + if (grade >= spellBonus.grade.size()) { + continue; + } + const auto &bonus = spellBonus.grade[grade]; + addValue(Augment_t::ManaCost, -bonus.decrease.manaCost); + addValue(Augment_t::BaseDamage, bonus.increase.damage / 100.0); + addValue(Augment_t::BaseHealing, bonus.increase.heal / 100.0); + addValue(Augment_t::DurationIncreased, bonus.increase.duration); + addValue(Augment_t::AdditionalTargets, bonus.increase.additionalTarget); + addValue(Augment_t::Cooldown, -(bonus.decrease.cooldown / 1000.0)); + addValue(Augment_t::SecondaryGroupCooldown, -(bonus.decrease.secondaryGroupCooldown / 1000.0)); + addValue(Augment_t::AffectedAreaEnlarged, bonus.increase.area); + addValue(Augment_t::IncreasedDamageReduction, bonus.increase.damageReduction / 100.0); + addValue(Augment_t::LifeLeech, bonus.leech.life / 100.0); + addValue(Augment_t::ManaLeech, bonus.leech.mana / 100.0); + addValue(Augment_t::CriticalExtraDamage, bonus.increase.criticalDamage / 100.0); + addValue(Augment_t::CriticalHitChance, bonus.increase.criticalChance / 100.0); + } + } + + std::unordered_map, double, PairHash, PairEqual> getActiveAugments() const; + /** * @brief Adds a spell to the spells vector. * @details This function adds a spell to the player's spells vector, only if the spell doesn't already exist in the vector. diff --git a/src/creatures/players/components/wheel/wheel_definitions.hpp b/src/creatures/players/components/wheel/wheel_definitions.hpp index f044ca855d2..ee45401e191 100644 --- a/src/creatures/players/components/wheel/wheel_definitions.hpp +++ b/src/creatures/players/components/wheel/wheel_definitions.hpp @@ -131,6 +131,7 @@ enum class WheelStat_t : uint8_t { MANA_LEECH_CHANCE = 13, DODGE = 14, CRITICAL_DAMAGE = 15, + CRITICAL_CHANCE = 16, TOTAL_COUNT // Always last }; diff --git a/src/creatures/players/components/wheel/wheel_spells.hpp b/src/creatures/players/components/wheel/wheel_spells.hpp index 9e7a300d05f..43e7f0009ac 100644 --- a/src/creatures/players/components/wheel/wheel_spells.hpp +++ b/src/creatures/players/components/wheel/wheel_spells.hpp @@ -14,7 +14,7 @@ namespace WheelSpells { bool area = false; int damage = 0; int heal = 0; - int aditionalTarget = 0; + int additionalTarget = 0; int damageReduction = 0; int duration = 0; int criticalDamage = 0; diff --git a/src/creatures/players/imbuements/imbuements.cpp b/src/creatures/players/imbuements/imbuements.cpp index 15094b8751a..8a04ea20834 100644 --- a/src/creatures/players/imbuements/imbuements.cpp +++ b/src/creatures/players/imbuements/imbuements.cpp @@ -36,6 +36,14 @@ Imbuement* Imbuements::getImbuement(uint16_t id) { return &it->second; } +Imbuement* Imbuements::getImbuementByScrollID(uint16_t scrollId) { + if (auto it = scrollIdMap.find(scrollId); it != scrollIdMap.end()) { + return it->second; + } + + return nullptr; +} + bool Imbuements::loadFromXml(bool /* reloading */) { pugi::xml_document doc; auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/imbuements.xml"; @@ -55,7 +63,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { g_logger().warn("Missing id for base entry"); continue; } - basesImbuement.emplace_back( + [[maybe_unused]] const auto &unusedBase = basesImbuement.emplace_back( pugi::cast(id.value()), baseNode.attribute("name").as_string(), pugi::cast(baseNode.attribute("price").value()), @@ -72,7 +80,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { g_logger().warn("Missing id for category entry"); continue; } - categoriesImbuement.emplace_back( + [[maybe_unused]] const auto &unusedCategory = categoriesImbuement.emplace_back( pugi::cast(id.value()), baseNode.attribute("name").as_string(), baseNode.attribute("agressive").as_bool(true) @@ -157,7 +165,13 @@ bool Imbuements::loadFromXml(bool /* reloading */) { } std::string type = attr.as_string(); - if (strcasecmp(type.c_str(), "item") == 0) { + if (strcasecmp(type.c_str(), "scroll") == 0) { + if ((attr = childNode.attribute("value"))) { + imbuement.scrollId = pugi::cast(attr.value()); + } else { + g_logger().warn("Missing scroll ID for imbuement name '{}'", imbuement.name); + } + } else if (strcasecmp(type.c_str(), "item") == 0) { if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing item ID for imbuement name '{}'", imbuement.name); continue; @@ -178,7 +192,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - imbuement.items.emplace_back(sourceId, count); + [[maybe_unused]] const auto &unusedItem = imbuement.items.emplace_back(sourceId, count); } else if (strcasecmp(type.c_str(), "description") == 0) { std::string description = imbuement.name; @@ -314,6 +328,14 @@ bool Imbuements::loadFromXml(bool /* reloading */) { } } } + + if (imbuement.scrollId != 0) { + auto [it, scrollInserted] = scrollIdMap.emplace(imbuement.scrollId, &imbuement); + if (!scrollInserted) { + g_logger().warn("Duplicate scroll ID {} for imbuement '{}', already mapped to '{}'", imbuement.scrollId, imbuement.name, it->second->getName()); + it->second = &imbuement; + } + } } } @@ -322,6 +344,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { bool Imbuements::reload() { imbuementMap.clear(); + scrollIdMap.clear(); basesImbuement.clear(); categoriesImbuement.clear(); @@ -347,12 +370,13 @@ CategoryImbuement* Imbuements::getCategoryByID(uint16_t id) { return categoryImbuements != categoriesImbuement.end() ? &*categoryImbuements : nullptr; } -std::vector Imbuements::getImbuements(const std::shared_ptr &player, const std::shared_ptr &item) { +std::vector Imbuements::getImbuements(const std::shared_ptr &player, const std::shared_ptr &item /* = nullptr */, bool scroll /* = false */) { std::vector imbuements; for (auto &[key, value] : imbuementMap) { Imbuement* imbuement = &value; - if (!imbuement) { + + if (scroll && imbuement->getScrollItemID() == 0) { continue; } @@ -366,16 +390,16 @@ std::vector Imbuements::getImbuements(const std::shared_ptr // Send only the imbuements registered on item (in items.xml) to the imbuement window const CategoryImbuement* categoryImbuement = getCategoryByID(imbuement->getCategory()); - if (!item->hasImbuementType(static_cast(categoryImbuement->id), imbuement->getBaseID())) { + if (item && !item->hasImbuementType(static_cast(categoryImbuement->id), imbuement->getBaseID())) { continue; } // If the item is already imbued with an imbuement, remove the imbuement from the next free slot - if (item->hasImbuementCategoryId(categoryImbuement->id)) { + if (item && item->hasImbuementCategoryId(categoryImbuement->id)) { continue; } - imbuements.emplace_back(imbuement); + [[maybe_unused]] auto &unusedImbuement = imbuements.emplace_back(imbuement); } return imbuements; @@ -587,3 +611,7 @@ void ImbuementDecay::checkImbuementDecay() { g_logger().trace("No more items to decay. Stopped imbuement decay scheduler."); } } + +uint16_t Imbuement::getScrollItemID() const { + return scrollId; +} diff --git a/src/creatures/players/imbuements/imbuements.hpp b/src/creatures/players/imbuements/imbuements.hpp index 6d44bcd42ab..d999ae49971 100644 --- a/src/creatures/players/imbuements/imbuements.hpp +++ b/src/creatures/players/imbuements/imbuements.hpp @@ -54,11 +54,12 @@ class Imbuements { static Imbuements &getInstance(); - Imbuement* getImbuement(uint16_t id); + [[nodiscard]] Imbuement* getImbuement(uint16_t id); + [[nodiscard]] Imbuement* getImbuementByScrollID(uint16_t scrollId); - BaseImbuement* getBaseByID(uint16_t id); - CategoryImbuement* getCategoryByID(uint16_t id); - std::vector getImbuements(const std::shared_ptr &player, const std::shared_ptr &item); + [[nodiscard]] BaseImbuement* getBaseByID(uint16_t id); + [[nodiscard]] CategoryImbuement* getCategoryByID(uint16_t id); + [[nodiscard]] std::vector getImbuements(const std::shared_ptr &player, const std::shared_ptr &item = nullptr, bool scroll = false); protected: friend class Imbuement; @@ -66,6 +67,7 @@ class Imbuements { private: std::map imbuementMap; + std::unordered_map scrollIdMap; std::vector basesImbuement; std::vector categoriesImbuement; @@ -80,24 +82,26 @@ class Imbuement { Imbuement(uint16_t initId, uint16_t initBaseId) : id(initId), baseid(initBaseId) { } - uint16_t getID() const; + [[nodiscard]] uint16_t getID() const; - uint16_t getBaseID() const; + [[nodiscard]] uint16_t getBaseID() const; - uint32_t getStorage() const; + [[nodiscard]] uint32_t getStorage() const; - bool isPremium() const; - std::string getName() const; - std::string getDescription() const; + [[nodiscard]] bool isPremium() const; + [[nodiscard]] std::string getName() const; + [[nodiscard]] std::string getDescription() const; - std::string getSubGroup() const; + [[nodiscard]] std::string getSubGroup() const; - uint16_t getCategory() const; + [[nodiscard]] uint16_t getCategory() const; - const std::vector> &getItems() const; + [[nodiscard]] const std::vector> &getItems() const; - uint16_t getIconID() const; + [[nodiscard]] uint16_t getIconID() const; + [[nodiscard]] uint16_t getScrollItemID() const; + uint16_t scrollId = 0; uint16_t icon = 1; int32_t stats[maxSkillOrStatId + 1] = {}; int32_t skills[SKILL_LAST + 1] = {}; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 989c568b7e3..ce619166189 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -28,6 +28,7 @@ #include "enums/account_errors.hpp" #include "enums/account_group_type.hpp" #include "enums/account_type.hpp" +#include "enums/imbuement.hpp" #include "enums/object_category.hpp" #include "enums/player_blessings.hpp" #include "enums/player_icons.hpp" @@ -82,7 +83,8 @@ Player::Player() : m_animusMastery(*this), m_playerAttachedEffects(*this), m_storage(*this), - m_forgeHistoryPlayer(*this) { + m_forgeHistoryPlayer(*this), + m_weaponProficiency(*this) { } Player::Player(std::shared_ptr p) : @@ -99,7 +101,10 @@ Player::Player(std::shared_ptr p) : m_animusMastery(*this), m_playerAttachedEffects(*this), m_storage(*this), - m_forgeHistoryPlayer(*this) { + m_forgeHistoryPlayer(*this), + m_weaponProficiency(*this) { + baseCritical.chance = g_configManager().getFloat(PLAYER_BASE_CRITICAL_CHANCE); + baseCritical.damage = g_configManager().getFloat(PLAYER_BASE_CRITICAL_DAMAGE); m_wheelPlayer.init(); m_animusMastery.init(); } @@ -332,6 +337,15 @@ void Player::removeConditionSuppressions(const std::vector &toR } } +uint16_t Player::getWeaponId(bool ignoreAmmo /* = false */) const { + const auto &weapon = getWeapon(ignoreAmmo); + if (!weapon) { + return 0; + } + + return weapon->getID(); +} + std::shared_ptr Player::getWeapon(Slots_t slot, bool ignoreAmmo) const { const auto &item = inventory[slot]; if (!item) { @@ -726,6 +740,9 @@ int32_t Player::getDefense(bool sendToClient /* = false*/) const { defenseSkill = getSkillLevel(SKILL_SHIELD); } + defenseValue += weaponProficiency().getStat(WeaponProficiencyBonus_t::DEFENSE_BONUS); + defenseValue += weaponProficiency().getStat(WeaponProficiencyBonus_t::WEAPON_SHIELD_MODIFIER); + if (defenseSkill == 0) { switch (fightMode) { case FIGHTMODE_ATTACK: @@ -758,6 +775,9 @@ uint16_t Player::getDefenseEquipment() const { } } + defenseValue += weaponProficiency().getStat(WeaponProficiencyBonus_t::DEFENSE_BONUS); + defenseValue += weaponProficiency().getStat(WeaponProficiencyBonus_t::WEAPON_SHIELD_MODIFIER); + return defenseValue; } @@ -2446,8 +2466,152 @@ void Player::sendHouseAuctionMessage(uint32_t houseId, HouseAuctionType type, ui } // Imbuements +void Player::applyScrollImbuement(const std::shared_ptr &item, const std::shared_ptr &scrollItem) { + if (!item || !scrollItem) { + return; + } + + const auto freeImbuementSlot = item->getFreeImbuementSlot(); + if (freeImbuementSlot < 0) { + return; + } + + const Imbuement* imbuement = g_imbuements().getImbuementByScrollID(scrollItem->getID()); + if (!imbuement) { + return; + } + + const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID()); + if (!baseImbuement) { + return; + } + + const auto &thisPlayer = getPlayer(); + if (!item->canAddImbuement(static_cast(freeImbuementSlot), thisPlayer, imbuement)) { + return; + } + + if (g_game().internalRemoveItem(scrollItem, 1) != RETURNVALUE_NOERROR) { + g_logger().error("[Player::applyScrollImbuement] - Failed to remove scroll item {} from player {}", scrollItem->getID(), getName()); + return; + } + + item->setImbuement(freeImbuementSlot, imbuement->getID(), baseImbuement->duration); + g_imbuementDecay().startImbuementDecay(item); -void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr &item, uint8_t slot, bool protectionCharm) { + if (item->getParent() == getPlayer()) { + addItemImbuementStats(imbuement); + } +} + +void Player::createScrollImbuement(const Imbuement* imbuement) { + if (!imbuement) { + return; + } + + const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID()); + if (!baseImbuement) { + return; + } + + const auto &items = imbuement->getItems(); + for (auto &[itemId, amount] : items) { + const auto playerItemAmount = getItemTypeCount(itemId) + getStashItemCount(itemId); + if (playerItemAmount < amount) { + sendImbuementResult("You don't have all necessary items."); + return; + } + } + + auto emptyScrollsCount = getItemTypeCount(ITEM_EMPTY_IMBUEMENT_SCROLL) + getStashItemCount(ITEM_EMPTY_IMBUEMENT_SCROLL); + if (emptyScrollsCount == 0) { + sendImbuementResult("You don't have all necessary items."); + return; + } + + uint32_t price = baseImbuement->price; + if (!g_game().removeMoney(static_self_cast(), price, 0, true)) { + const std::string message = fmt::format("You don't have {} gold coins.", price); + + g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, player do not have money", this->getName()); + sendImbuementResult(message); + return; + } + + g_metrics().addCounter("balance_decrease", price, { { "player", getName() }, { "context", "apply_imbuement" } }); + + for (const auto &[key, value] : items) { + const uint32_t inventoryItemCount = getItemTypeCount(key); + if (inventoryItemCount >= value) { + removeItemOfType(key, value, -1, true); + continue; + } + + uint32_t mathItemCount = value; + if (inventoryItemCount > 0 && removeItemOfType(key, inventoryItemCount, -1, false)) { + mathItemCount = mathItemCount - inventoryItemCount; + } + + const ItemType &itemType = Item::items[key]; + + const auto withdrawItemMessage = fmt::format("Using {}x {} from your stash.", mathItemCount, itemType.name); + withdrawItem(itemType.id, mathItemCount); + sendTextMessage(MESSAGE_STATUS, withdrawItemMessage); + } + + if (!removeItemCountById(ITEM_EMPTY_IMBUEMENT_SCROLL, 1, true)) { + g_logger().error("Failed to remove empty imbuement scroll from player with name {}", getName()); + return; + } + + const auto imbuementScrollId = imbuement->getScrollItemID(); + const auto &imbuementScroll = Item::CreateItem(imbuementScrollId, 1); + ReturnValue ret = g_game().internalAddItem(static_self_cast(), imbuementScroll, INDEX_WHEREEVER, 0); + if (ret != RETURNVALUE_NOERROR) { + g_logger().error("Failed to add imbuement scroll id '{}' to player with name {}", imbuementScrollId, getName()); + sendImbuementResult("Failed to add imbuement scroll. Please contact administration."); + return; + } + + openImbuementWindow(ImbuementAction::Scroll, nullptr); +} + +bool Player::clearAllImbuements(const std::shared_ptr &item) { + if (!item) { + return false; + } + + auto itemSlots = item->getImbuementSlot(); + if (itemSlots == 0) { + sendTextMessage(MESSAGE_FAILURE, "Sorry, not possible."); + return false; + } + + std::vector> imbuementsToRemove; + + for (uint8_t slot = 0; slot < itemSlots; slot++) { + ImbuementInfo imbuementInfo; + if (item->getImbuementInfo(slot, &imbuementInfo) && imbuementInfo.imbuement) { + (void)imbuementsToRemove.emplace_back(slot, imbuementInfo); + } + } + + if (imbuementsToRemove.empty()) { + sendTextMessage(MESSAGE_FAILURE, "Sorry, not possible."); + return false; + } + + for (const auto &[slot, imbuementInfo] : imbuementsToRemove) { + if (item->getParent() == getPlayer()) { + removeItemImbuementStats(imbuementInfo.imbuement); + } + item->clearImbuement(slot, imbuementInfo.imbuement->getID()); + } + + return true; +} + +void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr &item, uint8_t slot) { if (!imbuement || !item) { return; } @@ -2461,7 +2625,7 @@ void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr< ImbuementInfo imbuementInfo; if (item->getImbuementInfo(slot, &imbuementInfo)) { g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, item already contains imbuement", this->getName()); - this->sendImbuementResult("An error ocurred, please reopen imbuement window."); + sendImbuementResult("An error occurred, please reopen imbuement window."); return; } @@ -2474,7 +2638,7 @@ void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr< if (item->getImbuementInfo(i, &existingImbuement) && existingImbuement.imbuement) { if (existingImbuement.imbuement->getName() == imbuement->getName()) { g_logger().error("[Player::onApplyImbuement] - Player {} attempted to apply the same imbuement in multiple slots", this->getName()); - this->sendImbuementResult("You cannot apply the same imbuement in multiple slots."); + sendImbuementResult("You cannot apply the same imbuement in multiple slots."); return; } } @@ -2501,7 +2665,6 @@ void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr< } uint32_t price = baseImbuement->price; - price += protectionCharm ? baseImbuement->protectionPrice : 0; if (!g_game().removeMoney(thisPlayer, price, 0, true)) { const std::string message = fmt::format("You don't have {} gold coins.", price); @@ -2530,17 +2693,10 @@ void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr< const ItemType &itemType = Item::items[key]; withdrawItemMessage << "Using " << mathItemCount << "x " << itemType.name << " from your stash. "; - withdrawItem(itemType.id, mathItemCount); + (void)withdrawItem(itemType.id, mathItemCount); sendTextMessage(MESSAGE_STATUS, withdrawItemMessage.str()); } - if (!protectionCharm && uniform_random(1, 100) > baseImbuement->percent) { - openImbuementWindow(item); - sendImbuementResult("Oh no!\n\nThe imbuement has failed. You have lost the astral sources and gold you needed for the imbuement.\n\nNext time use a protection charm to better your chances."); - openImbuementWindow(item); - return; - } - if (canAddImbuement) { // Update imbuement stats item if the item is equipped if (item->getParent() == thisPlayer) { @@ -2555,7 +2711,7 @@ void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr< g_imbuementDecay().startImbuementDecay(item); } - openImbuementWindow(item); + openImbuementWindow(ImbuementAction::PickItem, item); } void Player::onClearImbuement(const std::shared_ptr &item, uint8_t slot) { @@ -2566,7 +2722,7 @@ void Player::onClearImbuement(const std::shared_ptr &item, uint8_t slot) { ImbuementInfo imbuementInfo; if (!item->getImbuementInfo(slot, &imbuementInfo)) { g_logger().error("[Player::onClearImbuement] - An error occurred while player with name {} try to apply imbuement, item not contains imbuement", this->getName()); - this->sendImbuementResult("An error ocurred, please reopen imbuement window."); + sendImbuementResult("An error occurred, please reopen imbuement window."); return; } @@ -2579,8 +2735,8 @@ void Player::onClearImbuement(const std::shared_ptr &item, uint8_t slot) { const std::string message = fmt::format("You don't have {} gold coins.", baseImbuement->removeCost); g_logger().error("[Player::onClearImbuement] - An error occurred while player with name {} try to apply imbuement, player do not have money", this->getName()); - this->sendImbuementResult(message); - this->openImbuementWindow(item); + sendImbuementResult(message); + openImbuementWindow(ImbuementAction::PickItem, item); return; } g_metrics().addCounter("balance_decrease", baseImbuement->removeCost, { { "player", getName() }, { "context", "clear_imbuement" } }); @@ -2590,28 +2746,17 @@ void Player::onClearImbuement(const std::shared_ptr &item, uint8_t slot) { } item->clearImbuement(slot, imbuementInfo.imbuement->getID()); - this->openImbuementWindow(item); + openImbuementWindow(ImbuementAction::PickItem, item); } -void Player::openImbuementWindow(const std::shared_ptr &item) { - if (!client || !item) { - return; - } - - if (item->getImbuementSlot() <= 0) { - this->sendTextMessage(MESSAGE_EVENT_ADVANCE, "This item is not imbuable."); - return; - } - - const auto &itemParent = item->getTopParent(); - if (itemParent && itemParent != getPlayer()) { - this->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have to pick up the item to imbue it."); +void Player::openImbuementWindow(ImbuementAction action, const std::shared_ptr &item) { + if (!client) { return; } updateImbuementTrackerStats(); - client->openImbuementWindow(item); + client->openImbuementWindow(action, item); } // inventory @@ -5567,6 +5712,34 @@ std::vector> Player::getEquippedAugmentItems() const { return equippedAugmentItems; } +std::unordered_map, double, PairHash, PairEqual> Player::getEquippedAugments() const { + std::unordered_map, double, PairHash, PairEqual> equippedAugments; + + const auto &equippedAugmentItems = getEquippedAugmentItems(); + for (const auto &item : equippedAugmentItems) { + for (const auto &augment : item->getAugments()) { + if (augment->type == Augment_t::None) { + continue; + } + + const auto &spell = g_spells().getInstantSpellByName(augment->spellName); + const auto spellId = spell ? spell->getSpellId() : 0; + + if (spellId == 0) { + continue; + } + + const auto key = std::make_pair(spellId, static_cast(augment->type)); + + double divisor = augment->type == Augment_t::Cooldown ? -1000.0 : 100.0; + + equippedAugments[key] += augment->value / divisor; + } + } + + return equippedAugments; +} + std::vector> Player::getEquippedItems() const { static const std::vector valid_slots { CONST_SLOT_HEAD, @@ -7055,8 +7228,15 @@ uint16_t Player::getSkillLevel(skills_t skill) const { skillLevel += m_wheelPlayer.getMajorStatConditional("Combat Mastery", WheelMajor_t::CRITICAL_DMG_2); skillLevel += m_wheelPlayer.getMajorStatConditional("Ballistic Mastery", WheelMajor_t::CRITICAL_DMG); skillLevel += m_wheelPlayer.checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_DAMAGE); + skillLevel += m_weaponProficiency.getGeneralCritical().damage * 10000; + } else if (skill == SKILL_CRITICAL_HIT_CHANCE) { + skillLevel += m_weaponProficiency.getGeneralCritical().chance * 10000; } + // Weapon proficiency + const auto weaponProficiencySkill = m_weaponProficiency.getSkillBonus(skill); + skillLevel += weaponProficiencySkill; + const int32_t avatarCritChance = m_wheelPlayer.checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_CHANCE); if (skill == SKILL_CRITICAL_HIT_CHANCE && avatarCritChance > 0) { skillLevel = avatarCritChance; // 100% @@ -7112,17 +7292,19 @@ int32_t Player::getPerfectShotDamage(uint8_t range, bool useCharges) const { result = it->second; } + const auto &perfectShotBonus = weaponProficiency().getPerfectShotBonus(); + if (perfectShotBonus.range == range) { + result += perfectShotBonus.damage; + } + for (const auto &item : getEquippedItems()) { const ItemType &itemType = Item::items[item->getID()]; - if (!itemType.abilities) { - continue; - } - - if (!itemType.abilities->perfectShotRange) { + if (!itemType.abilities || itemType.abilities->perfectShotRange == 0 || itemType.abilities->perfectShotDamage == 0) { continue; } + uint8_t perfectShotRange = itemType.abilities->perfectShotRange; - if (itemType.abilities->perfectShotRange == range) { + if (perfectShotRange == range) { result += itemType.abilities->perfectShotDamage; const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { @@ -7146,7 +7328,9 @@ void Player::setPerfectShotDamage(uint8_t range, int32_t damage) { } int32_t Player::getSpecializedMagicLevel(CombatType_t combat, bool useCharges) const { - int32_t result = specializedMagicLevel[combatTypeToIndex(combat)] + m_wheelPlayer.getSpecializedMagic(combat); + int32_t result = specializedMagicLevel[combatTypeToIndex(combat)]; + result += m_wheelPlayer.getSpecializedMagic(combat); + result += m_weaponProficiency.getSpecializedMagic(combat); for (const auto &item : getEquippedItems()) { const ItemType &itemType = Item::items[item->getID()]; if (!itemType.abilities) { @@ -8266,6 +8450,7 @@ void Player::postRemoveNotification(const std::shared_ptr &thing, const s } } } + bool requireListUpdate = true; if (link == LINK_OWNER || link == LINK_TOPPARENT) { @@ -11895,6 +12080,15 @@ const PlayerStorage &Player::storage() const { return m_storage; } +// Weapon Proficiency interface +WeaponProficiency &Player::weaponProficiency() { + return m_weaponProficiency; +} + +const WeaponProficiency &Player::weaponProficiency() const { + return m_weaponProficiency; +} + void Player::sendLootMessage(const std::string &message) const { const auto &party = getParty(); if (!party) { @@ -12208,7 +12402,7 @@ AcceptTransferErrorMessage Player::canAcceptTransferHouse(uint32_t houseId) { bool Player::isFirstOnStack() const { const auto &playerTile = getTile(); if (!playerTile) { - return false; + return true; } const auto &bottomCreature = playerTile->getBottomCreature(); @@ -12217,6 +12411,11 @@ bool Player::isFirstOnStack() const { return false; } + if (hasCondition(CONDITION_SPELLCOOLDOWN)) { + g_logger().warn("[isFirstOnStack] cooldown error for player: {}", getName()); + return false; + } + return this == bottomPlayer.get(); } @@ -12254,6 +12453,41 @@ void Player::resetOldCharms() { g_logger().info("Player: {}, recalculated charm points based on unlocked bestiary: {}", getName(), totalRefund); } +std::array Player::getSkillsEquipment() const { + std::array skillsEquipment = {}; + for (uint16_t skill = SKILL_FIRST; skill <= SKILL_LAST; skill++) { + SkillsEquipment skillEquipment = {}; + + for (uint32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_AMMO; ++slot) { + const auto slotType = static_cast(slot); + const auto &item = getInventoryItem(slotType); + if (!item) { + continue; + } + + const ItemType &itemType = Item::items[item->getID()]; + if (itemType.abilities) { + skillEquipment.equipment += itemType.abilities->skills[skill] / 10000.0; + } + + for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { + ImbuementInfo imbuementInfo; + if (item->getImbuementInfo(slotid, &imbuementInfo) && imbuementInfo.imbuement) { + skillEquipment.imbuement += imbuementInfo.imbuement->skills[skill] / 10000.0; + } + } + } + + skillsEquipment[skill] = skillEquipment; + } + + return skillsEquipment; +} + +const BaseCritical &Player::getBaseCritical() const { + return baseCritical; +} + Virtue_t Player::getVirtue() const { return virtue; } @@ -12451,3 +12685,16 @@ Player::ExivaRestrictions &Player::getExivaRestrictions() { const Player::ExivaRestrictions &Player::getExivaRestrictions() const { return exivaRestrictions; } + +void Player::sendWeaponProficiency(uint16_t weaponId /* = 0 */) { + if (weaponId == 0) { + const auto &weapon = getWeapon(true); + if (weapon) { + weaponId = weapon->getID(); + } + } + + if (client) { + client->sendWeaponProficiency(weaponId); + } +} diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index bd878b07f3b..fc61b9fc370 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -30,6 +30,8 @@ #include "creatures/players/components/player_vip.hpp" #include "creatures/players/components/wheel/wheel_gems.hpp" #include "creatures/players/components/player_attached_effects.hpp" +#include "creatures/players/components/weapon_proficiency.hpp" +#include "utils/hash.hpp" class House; class NetworkMessage; @@ -81,6 +83,7 @@ enum class HouseAuctionType : uint8_t; enum class BidErrorMessage : uint8_t; enum class TransferErrorMessage : uint8_t; enum class AcceptTransferErrorMessage : uint8_t; +enum class ImbuementAction : uint8_t; enum ObjectCategory_t : uint8_t; enum PreySlot_t : uint8_t; enum SpeakClasses : uint8_t; @@ -95,6 +98,16 @@ using UsersMap = std::map>; using InvitedMap = std::map>; using HouseMap = std::map>; +struct SkillsEquipment { + double_t equipment = 0; + double_t imbuement = 0; +}; + +struct BaseCritical { + double_t chance = 0.05; + double_t damage = 0.1; +}; + struct CharmInfo { uint16_t raceId = 0; uint8_t tier = 0; @@ -171,6 +184,11 @@ class Player final : public Creature, public Cylinder, public Bankable { ExivaRestrictions &getExivaRestrictions(); const ExivaRestrictions &getExivaRestrictions() const; + void sendWeaponProficiency(uint16_t weaponId = 0); + + std::array getSkillsEquipment() const; + const BaseCritical &getBaseCritical() const; + /** * @brief Gets the current virtue of the player. * @return The virtue as Virtue_t. @@ -783,6 +801,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void updateLastAggressiveAction(); + uint16_t getWeaponId(bool ignoreAmmo = false) const; std::shared_ptr getWeapon(Slots_t slot, bool ignoreAmmo) const; std::shared_ptr getWeapon(bool ignoreAmmo = false) const; WeaponType_t getWeaponType() const; @@ -1059,9 +1078,12 @@ class Player final : public Creature, public Cylinder, public Bankable { void sendResourceBalance(Resource_t resourceType, uint64_t value) const; void sendHouseAuctionMessage(uint32_t houseId, HouseAuctionType type, uint8_t index, bool bidSuccess = false) const; // Imbuements - void onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr &item, uint8_t slot, bool protectionCharm); + void applyScrollImbuement(const std::shared_ptr &item, const std::shared_ptr &scrollItem); + void createScrollImbuement(const Imbuement* imbuement); + void onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr &item, uint8_t slot); void onClearImbuement(const std::shared_ptr &item, uint8_t slot); - void openImbuementWindow(const std::shared_ptr &item); + bool clearAllImbuements(const std::shared_ptr &item); + void openImbuementWindow(ImbuementAction action, const std::shared_ptr &item); void sendImbuementResult(const std::string &message) const; void closeImbuementWindow() const; void sendPodiumWindow(const std::shared_ptr &podium, const Position &position, uint16_t itemId, uint8_t stackpos) const; @@ -1418,6 +1440,8 @@ class Player final : public Creature, public Cylinder, public Bankable { // Gets the equipped items with augment std::vector> getEquippedAugmentItems() const; + std::unordered_map, double, PairHash, PairEqual> getEquippedAugments() const; + /** * @brief Get the equipped items of the player-> * @details This function returns a vector containing the items currently equipped by the player @@ -1461,9 +1485,14 @@ class Player final : public Creature, public Cylinder, public Bankable { PlayerAttachedEffects &attachedEffects(); const PlayerAttachedEffects &attachedEffects() const; + // Player storage interface PlayerStorage &storage(); const PlayerStorage &storage() const; + // Player weapon proficiency interface + WeaponProficiency &weaponProficiency(); + const WeaponProficiency &weaponProficiency() const; + void sendLootMessage(const std::string &message) const; std::shared_ptr getLootPouch(); @@ -1626,6 +1655,8 @@ class Player final : public Creature, public Cylinder, public Bankable { time_t lastLoginSaved = 0; time_t lastLogout = 0; + BaseCritical baseCritical; + uint64_t experience = 0; uint64_t manaSpent = 0; uint64_t lastAttack = 0; @@ -1869,6 +1900,7 @@ class Player final : public Creature, public Cylinder, public Bankable { PlayerAttachedEffects m_playerAttachedEffects; PlayerStorage m_storage; PlayerForgeHistory m_forgeHistoryPlayer; + WeaponProficiency m_weaponProficiency; std::mutex quickLootMutex; diff --git a/src/enums/imbuement.hpp b/src/enums/imbuement.hpp new file mode 100644 index 00000000000..fe89fee80f2 --- /dev/null +++ b/src/enums/imbuement.hpp @@ -0,0 +1,20 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#ifndef USE_PRECOMPILED_HEADERS + #include +#endif + +enum class ImbuementAction : uint8_t { + Open, + PickItem, + Scroll +}; diff --git a/src/enums/weapon_proficiency.hpp b/src/enums/weapon_proficiency.hpp new file mode 100644 index 00000000000..0f7911a30b0 --- /dev/null +++ b/src/enums/weapon_proficiency.hpp @@ -0,0 +1,190 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019–present OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#ifndef USE_PRECOMPILED_HEADERS + #include +#endif + +#include "creatures/creatures_definitions.hpp" + +enum class WeaponProficiencyBonus_t : uint8_t { + ATTACK_DAMAGE = 0, // bonus to the attack damage of the weapon, which is added to the base damage - OK + DEFENSE_BONUS = 1, // bonus to the defense of the weapon, which is added to the armor value - OK + WEAPON_SHIELD_MODIFIER = 2, // bonus to the shield modifier of the weapon - OK + SKILL_BONUS = 3, // bonus to the skill level of the weapon (distance, sword, axe, club, fist, magic, shield, fishing) - OK + SPECIALIZED_MAGIC_LEVEL = 4, // bonus magic level for specialized spells - OK + SPELL_AUGMENT = 5, // bonus damage against specific creatures based on spell augment - OK + WEAPON_PROFICIENCY_BESTIARY = 6, // renamed from BESTIARY to avoid shadowing CyclopediaTitle_t::BESTIARY + POWERFUL_FOE_BONUS = 7, // bonus damage against bosses, influenced and fiendish creatures - OK + CRITICAL_HIT_CHANCE = 8, // chance to deal critical damage with the weapon - OK + ELEMENTAL_HIT_CHANCE = 9, // chance to deal elemental damage with the weapon - OK + RUNE_CRITICAL_HIT_CHANCE = 10, // chance to deal critical damage with runes - OK + AUTO_ATTACK_CRITICAL_HIT_CHANCE = 11, // chance to deal critical damage with auto attacks - OK + CRITICAL_EXTRA_DAMAGE = 12, // extra damage dealt when a critical hit occurs - OK + ELEMENTAL_CRITICAL_EXTRA_DAMAGE = 13, // extra elemental damage dealt when a critical hit occurs - OK + RUNE_CRITICAL_EXTRA_DAMAGE = 14, // extra damage dealt when a critical hit occurs with runes - OK + AUTO_ATTACK_CRITICAL_EXTRA_DAMAGE = 15, // extra damage dealt when a critical hit occurs with auto attacks - OK + MANA_LEECH = 16, // chance to leech mana from the target when hitting with the weapon - OK + LIFE_LEECH = 17, // chance to leech life from the target when hitting with the weapon - OK + MANA_GAIN_ON_HIT = 18, // chance to gain mana when hitting a creature with the weapon - OK + LIFE_GAIN_ON_HIT = 19, // chance to gain life when hitting a creature with the weapon - OK + MANA_GAIN_ON_KILL = 20, // chance to gain mana when killing a creature with the weapon - OK + LIFE_GAIN_ON_KILL = 21, // chance to gain life when killing a creature with the weapon - OK + PERFECT_SHOT_DAMAGE = 22, // bonus damage when hitting a target with a perfect shot - OK + RANGED_HIT_CHANCE = 23, // chance to hit a target with ranged attacks - OK + ATTACK_RANGE = 24, // the range of the weapon, how far it can hit a target (increases the current range of the weapon) - OK + SKILL_PERCENTAGE_AUTO_ATTACK = 25, // a percentage of your current skill level as extra damage on auto attacks - OK + SKILL_PERCENTAGE_SPELL_DAMAGE = 26, // a percentage of your current skill level as extra damage for spells - OK + SKILL_PERCENTAGE_SPELL_HEALING = 27, // a percentage of your current skill level as extra healing for spells - OK +}; + +enum class SkillPercentage_t : uint8_t { + AutoAttack, + SpellDamage, + SpellHealing, +}; + +enum class WeaponProficiencySpellBoost_t : uint8_t { + MANA = 0, + COOLDOWN = 1, + GROUP_COOLDOWN = 2, + SECONDARY_GROUP_COOLDOWN = 3, + MANA_LEECH = 4, + MANA_LEECH_CHANCE = 5, + LIFE_LEECH = 6, + LIFE_LEECH_CHANCE = 7, + DAMAGE = 8, + DAMAGE_REDUCTION = 9, + HEAL = 10, + CRITICAL_DAMAGE = 11, + CRITICAL_CHANCE = 12, + + TOTAL_COUNT = 13 +}; + +enum class WeaponProficiencyHealth_t : uint8_t { + LIFE = 0, + MANA = 1, +}; + +enum class WeaponProficiencyGain_t : uint8_t { + HIT = 0, + KILL = 1, +}; + +enum class WeaponProficiencyExperience_t : uint8_t { + Easy = 1, + Medium = 2, + Hard = 3, +}; + +struct ProficiencyPerk { + ProficiencyPerk() = default; + + uint8_t level = 0; + uint8_t index = 0; + + double_t value = 0.0; + + uint16_t spellId = 0; + uint8_t range = 0; + uint16_t bestiaryId = 0; + std::string bestiaryName = ""; + uint8_t augmentType = 0; + skills_t skillId = SKILL_NONE; + CombatType_t element = COMBAT_NONE; + WeaponProficiencyBonus_t type = WeaponProficiencyBonus_t::ATTACK_DAMAGE; +}; + +struct ProficiencyLevel { + std::vector perks = {}; +}; + +struct Proficiency { + Proficiency() = default; + explicit Proficiency(uint16_t id) : + id(id) { } + + uint16_t id = 0; + std::vector level = {}; + uint8_t maxLevel = 0; +}; + +struct WeaponProficiencyData { + uint32_t experience = 0; + std::vector perks = {}; + bool mastered = false; +}; + +struct WeaponProficiencyBonusStat { + CombatType_t element = COMBAT_NONE; + uint32_t value = 0; +}; + +struct WeaponProficiencyPerfectShotBonus { + uint8_t range = 0; + uint8_t damage = 0; +}; + +struct SkillPercentage { + skills_t skill = SKILL_NONE; + + double_t spellHealing = 0; + double_t autoAttack = 0; + double_t spellDamage = 0; + + void clear() { + skill = SKILL_NONE; + spellHealing = 0; + autoAttack = 0; + spellDamage = 0; + } +}; + +struct WeaponProficiencyCriticalBonus { + double_t chance = 0; + double_t damage = 0; + + void clear() { + chance = 0; + damage = 0; + } +}; + +namespace WeaponProficiencySpells { + struct Increase { + bool area = false; + double_t damage = 0; + double_t heal = 0; + int32_t additionalTarget = 0; + double_t damageReduction = 0; + int32_t duration = 0; + double_t criticalDamage = 0; + double_t criticalChance = 0; + }; + + struct Decrease { + int32_t cooldown = 0; + int32_t manaCost = 0; + int32_t secondaryGroupCooldown = 0; + }; + + struct Leech { + double_t mana = 0; + double_t life = 0; + }; + + struct Bonus { + Leech leech; + Increase increase; + Decrease decrease; + }; +} diff --git a/src/game/game.cpp b/src/game/game.cpp index 4f4416fdb35..6735622aa98 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -3522,7 +3522,7 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = [this, playerId, itemId, hasTier, tier] { playerEquipItem(playerId, itemId, hasTier, tier); }, - __FUNCTION__ + fmt::format("{} - Player::setNextActionTask ", __FUNCTION__) ); player->setNextActionTask(task); } @@ -6142,7 +6142,7 @@ void Game::playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::str player->vip().edit(guid, description, icon, notify, vipGroupsId); } -void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t slot, bool protectionCharm) { +void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t slot) { const auto &player = getPlayerByID(playerId); if (!player) { return; @@ -6155,12 +6155,13 @@ void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t player->updateUIExhausted(); - if (!player->hasImbuingItem()) { + Imbuement* imbuement = g_imbuements().getImbuement(imbuementid); + if (!imbuement) { return; } - Imbuement* imbuement = g_imbuements().getImbuement(imbuementid); - if (!imbuement) { + if (!player->hasImbuingItem()) { + player->createScrollImbuement(imbuement); return; } @@ -6175,7 +6176,7 @@ void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t return; } - player->onApplyImbuement(imbuement, item, slot, protectionCharm); + player->onApplyImbuement(imbuement, item, slot); } void Game::playerClearImbuement(uint32_t playerid, uint8_t slot) { @@ -7486,7 +7487,7 @@ bool Game::combatChangeHealth(const std::shared_ptr &attacker, const s int32_t damageY = attackerPlayer->getPerfectShotDamage(distanceY, true); const auto &item = attackerPlayer->getWeapon(); if (item && item->getWeaponType() == WEAPON_DISTANCE) { - std::shared_ptr quiver = attackerPlayer->getInventoryItem(CONST_SLOT_RIGHT); + const auto &quiver = attackerPlayer->getInventoryItem(CONST_SLOT_RIGHT); if (quiver && quiver->getWeaponType()) { if (quiver->getPerfectShotRange() == distanceX) { damageX -= quiver->getPerfectShotDamage(); @@ -7984,14 +7985,9 @@ void Game::applyManaLeech( const std::shared_ptr &attackerPlayer, const std::shared_ptr &targetMonster, const std::shared_ptr &target, const CombatDamage &damage, const int32_t &realDamage ) const { // Wheel of destiny bonus - mana leech chance and amount - auto wheelLeechChance = attackerPlayer->wheel().checkDrainBodyLeech(target, SKILL_MANA_LEECH_CHANCE); auto wheelLeechAmount = attackerPlayer->wheel().checkDrainBodyLeech(target, SKILL_MANA_LEECH_AMOUNT); - - uint16_t manaChance = attackerPlayer->getSkillLevel(SKILL_MANA_LEECH_CHANCE) + wheelLeechChance + damage.manaLeechChance; uint16_t manaSkill = attackerPlayer->getSkillLevel(SKILL_MANA_LEECH_AMOUNT) + wheelLeechAmount + damage.manaLeech; - if (normal_random(0, 100) >= manaChance) { - return; - } + // Void charm rune if (targetMonster && attackerPlayer->parseRacebyCharm(CHARM_VOID) == targetMonster->getRaceId()) { if (const auto &charm = g_iobestiary().getBestiaryCharm(CHARM_VOID)) { @@ -7999,6 +7995,10 @@ void Game::applyManaLeech( } } + if (manaSkill == 0) { + return; + } + CombatParams tmpParams; CombatDamage tmpDamage; @@ -8015,19 +8015,19 @@ void Game::applyLifeLeech( const std::shared_ptr &attackerPlayer, const std::shared_ptr &targetMonster, const std::shared_ptr &target, const CombatDamage &damage, const int32_t &realDamage ) const { // Wheel of destiny bonus - life leech chance and amount - auto wheelLeechChance = attackerPlayer->wheel().checkDrainBodyLeech(target, SKILL_LIFE_LEECH_CHANCE); auto wheelLeechAmount = attackerPlayer->wheel().checkDrainBodyLeech(target, SKILL_LIFE_LEECH_AMOUNT); - uint16_t lifeChance = attackerPlayer->getSkillLevel(SKILL_LIFE_LEECH_CHANCE) + wheelLeechChance + damage.lifeLeechChance; uint16_t lifeSkill = attackerPlayer->getSkillLevel(SKILL_LIFE_LEECH_AMOUNT) + wheelLeechAmount + damage.lifeLeech; - if (normal_random(0, 100) >= lifeChance) { - return; - } + if (targetMonster && attackerPlayer->parseRacebyCharm(CHARM_VAMP) == targetMonster->getRaceId()) { if (const auto &charm = g_iobestiary().getBestiaryCharm(CHARM_VAMP)) { lifeSkill += charm->chance[attackerPlayer->getCharmTier(CHARM_VAMP)] * 100; } } + if (lifeSkill == 0) { + return; + } + CombatParams tmpParams; CombatDamage tmpDamage; diff --git a/src/game/game.hpp b/src/game/game.hpp index 61b7fc25ed6..081f3a505d1 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -380,7 +380,7 @@ class Game { void playerRequestAddVip(uint32_t playerId, const std::string &name); void playerRequestRemoveVip(uint32_t playerId, uint32_t guid); void playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::string &description, uint32_t icon, bool notify, std::vector vipGroupsId); - void playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t slot, bool protectionCharm); + void playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t slot); void playerClearImbuement(uint32_t playerid, uint8_t slot); void playerCloseImbuementWindow(uint32_t playerid); void playerTurn(uint32_t playerId, Direction dir); diff --git a/src/game/scheduling/events_scheduler.cpp b/src/game/scheduling/events_scheduler.cpp index 453a2832682..0ccabfd5f2d 100644 --- a/src/game/scheduling/events_scheduler.cpp +++ b/src/game/scheduling/events_scheduler.cpp @@ -12,8 +12,6 @@ #include "config/configmanager.hpp" #include "lua/scripts/scripts.hpp" -#include - namespace { bool parseDateTime(const std::string &dateStr, const std::string &timeStr, std::time_t &result) { int month = 0; diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index d8940ac5fea..4f5023c39a7 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -1012,6 +1012,8 @@ void IOLoginDataLoad::loadPlayerInitializeSystem(const std::shared_ptr & player->title().checkAndUpdateNewTitles(); player->cyclopedia().loadSummaryData(); + player->weaponProficiency().load(); + player->initializePrey(); player->initializeTaskHunting(); // Load and apply the player's Virtue from the saved spell data, if available diff --git a/src/io/io_wheel.cpp b/src/io/io_wheel.cpp index 956d5d60825..a9c4910dbd9 100644 --- a/src/io/io_wheel.cpp +++ b/src/io/io_wheel.cpp @@ -264,7 +264,7 @@ void IOWheel::initializeKnightSpells() { m_wheelBonusData.spells.knight[2].name = "Chivalrous Challenge"; m_wheelBonusData.spells.knight[2].grade[1].decrease.manaCost = 20; - m_wheelBonusData.spells.knight[2].grade[2].increase.aditionalTarget = 1; + m_wheelBonusData.spells.knight[2].grade[2].increase.additionalTarget = 1; m_wheelBonusData.spells.knight[3].name = "Intense Wound Cleansing"; m_wheelBonusData.spells.knight[3].grade[1].increase.heal = 125; @@ -285,7 +285,7 @@ void IOWheel::initializePaladinSpells() { m_wheelBonusData.spells.paladin[1].grade[2].increase.damage = 380; m_wheelBonusData.spells.paladin[2].name = "Divine Dazzle"; - m_wheelBonusData.spells.paladin[2].grade[1].increase.aditionalTarget = 1; + m_wheelBonusData.spells.paladin[2].grade[1].increase.additionalTarget = 1; m_wheelBonusData.spells.paladin[2].grade[2].increase.duration = 4; m_wheelBonusData.spells.paladin[2].grade[2].decrease.cooldown = 4; @@ -334,8 +334,8 @@ void IOWheel::initializeMonkSpells() { // Chained Penance: Grade 1 adds 1 extra target; Grade 2 adds 2 extra targets m_wheelBonusData.spells.monk[2].name = "Chained Penance"; - m_wheelBonusData.spells.monk[2].grade[1].increase.aditionalTarget = 1; - m_wheelBonusData.spells.monk[2].grade[2].increase.aditionalTarget = 2; + m_wheelBonusData.spells.monk[2].grade[1].increase.additionalTarget = 1; + m_wheelBonusData.spells.monk[2].grade[2].increase.additionalTarget = 2; // Flurry of Blows: Grade 1 grants life leech; Grade 2 increases damage m_wheelBonusData.spells.monk[3].name = "Flurry of Blows"; diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 906d0084bfd..5c9578c0eec 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -288,6 +288,10 @@ void IOLoginData::saveOnlyDataForOnlinePlayer(const std::shared_ptr &pla player->wheel().saveKVModGrades(); player->wheel().saveKVScrolls(); + if (!player->weaponProficiency().saveAll()) { + throw DatabaseException("[IOLoginData::saveOnlyDataForOnlinePlayer] - Failed to save player weapon proficiency: " + player->getName()); + } + if (!IOLoginDataSave::savePlayerStorage(player)) { throw DatabaseException("[IOLoginDataSave::savePlayerStorage] - Failed to save player storage: " + player->getName()); } diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp index 5f04307a4e4..55f54e88236 100644 --- a/src/items/functions/item/item_parse.cpp +++ b/src/items/functions/item/item_parse.cpp @@ -842,7 +842,7 @@ void ItemParse::parseImbuement(const std::string &stringValue, pugi::xml_node at continue; } } else { - g_logger().warn("[ParseImbuement::initParseImbuement] - Unknown type: {}", valueAttribute.as_string()); + g_logger().warn("[ParseImbuement::initParseImbuement] - Unknown imbuement type: {}", subKeyAttribute.as_string()); } } } diff --git a/src/items/item.cpp b/src/items/item.cpp index a246e112a03..62e8117dc7d 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -468,6 +468,21 @@ bool Item::hasImbuementAttribute(const std::string &attributeSlot) const { return getCustomAttribute(attributeSlot) != nullptr; } +int8_t Item::getFreeImbuementSlot() const { + if (getImbuementSlot() == 0) { + return -1; + } + + for (uint8_t slotId = 0; slotId < getImbuementSlot(); slotId++) { + ImbuementInfo imbuementInfo; + if (!getImbuementInfo(slotId, &imbuementInfo)) { + return slotId; + } + } + + return -1; +} + bool Item::getImbuementInfo(uint8_t slot, ImbuementInfo* imbuementInfo) const { std::string attributeSlot = std::to_string(ITEM_IMBUEMENT_SLOT + slot); if (!hasImbuementAttribute(attributeSlot)) { @@ -487,23 +502,41 @@ void Item::setImbuement(uint8_t slot, uint16_t imbuementId, uint32_t duration) { } bool Item::canAddImbuement(uint8_t slot, const std::shared_ptr &player, const Imbuement* imbuement) { + if (!player) { + g_logger().error("[Item::canAddImbuement] - Null player while validating imbuement for item id {}", getID()); + return false; + } + + if (!imbuement) { + g_logger().error("[Item::canAddImbuement] - Null imbuement while validating item id {}", getID()); + player->sendImbuementResult("Invalid imbuement selection."); + return false; + } + auto itemSlots = getImbuementSlot(); if (itemSlots == 0 || slot >= itemSlots) { - g_logger().error("[Player::onApplyImbuement] - Player {} attempted to apply imbuement in an invalid slot ({})", player->getName(), slot); + g_logger().error("[Item::canAddImbuement] - Player {} attempted to apply imbuement in an invalid slot ({})", player->getName(), slot); player->sendImbuementResult("Invalid slot selection."); return false; } - // Get category imbuement for acess category id + // Get category imbuement for access category id const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory()); + if (!categoryImbuement) { + g_logger().error("[Item::canAddImbuement] - Invalid imbuement category '{}' for item id {}", imbuement->getCategory(), getID()); + player->sendImbuementResult("This object cannot be imbued with that scroll."); + return false; + } + if (!hasImbuementType(static_cast(categoryImbuement->id), imbuement->getBaseID())) { + player->sendImbuementResult("This object cannot be imbued with that scroll."); return false; } // Checks if the item already has the imbuement category id if (hasImbuementCategoryId(categoryImbuement->id)) { g_logger().error("[Item::setImbuement] - An error occurred while player with name {} try to apply imbuement, item already contains imbuement of the same type: {}", player->getName(), imbuement->getName()); - player->sendImbuementResult("An error ocurred, please reopen imbuement window."); + player->sendImbuementResult("This item already has this imbuement type."); return false; } diff --git a/src/items/item.hpp b/src/items/item.hpp index 15b03e6317a..a882313ba80 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -726,6 +726,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { } bool hasImbuementCategoryId(uint16_t categoryId) const; bool hasImbuementAttribute(const std::string &attributeSlot) const; + int8_t getFreeImbuementSlot() const; bool hasImbuements() const { for (uint8_t slotid = 0; slotid < getImbuementSlot(); slotid++) { ImbuementInfo imbuementInfo; diff --git a/src/items/items.cpp b/src/items/items.cpp index ad75c0829d7..7312a3f1a8a 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -17,6 +17,7 @@ #include "utils/pugicast.hpp" #include "creatures/combat/spells.hpp" #include "utils/tools.hpp" +#include "creatures/players/components/weapon_proficiency.hpp" #include @@ -102,15 +103,13 @@ std::string ItemType::getFormattedAugmentDescription(const std::shared_ptrvalue > 0 ? '-' : '+'; + using enum Augment_t; if (Items::isAugmentWithoutValueDescription(augmentInfo->type)) { return fmt::format("{} -> {}", augmentSpellNameCapitalized, augmentName); - } else if (augmentInfo->type == Augment_t::Cooldown) { + } else if (augmentInfo->type == Cooldown) { return fmt::format("{} -> {}{}s {}", augmentSpellNameCapitalized, signal, augmentInfo->value / 1000, augmentName); - } else if (augmentInfo->type == Augment_t::Base) { - const auto &spell = g_spells().getSpellByName(augmentInfo->spellName); - if (spell) { - return fmt::format("{} -> {:+}% {} {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName, spell->getGroup() == SPELLGROUP_HEALING ? "healing" : "damage"); - } + } else if (augmentInfo->type == BaseDamage || augmentInfo->type == BaseHealing) { + return fmt::format("{} -> {:+}% {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName); } return fmt::format("{} -> {:+}% {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName); @@ -140,6 +139,17 @@ bool Items::reload() { return true; } +ItemTypes_t protoItemCategoryToCpp(uint32_t protoCategory) { + // Protobuf enums for categories (values 1-31) + // We map them to our internal ItemTypes_t + if (protoCategory >= 1 && protoCategory <= 27) { + return static_cast(protoCategory); + } + // Add specific mappings if protobuf categories diverge or extend beyond 27 + // Currently, values above 27 in proto don't have exact matches in ItemTypes_t (1-27) + return ITEM_TYPE_OTHER; +} + void Items::loadFromProtobuf() { using namespace Canary::protobuf::appearances; @@ -206,7 +216,7 @@ void Items::loadFromProtobuf() { } if (object.flags().has_market()) { - iType.type = static_cast(object.flags().market().category()); + iType.type = protoItemCategoryToCpp(object.flags().market().category()); } iType.name = object.name(); @@ -249,6 +259,16 @@ void Items::loadFromProtobuf() { iType.expireStop = object.flags().expirestop(); iType.isWrapKit = object.flags().wrapkit(); iType.isDualWielding = object.flags().dual_wielding(); + if (object.flags().has_proficiency() && object.flags().proficiency().has_proficiency_id()) { + auto &proficiencies = WeaponProficiency::getProficiencies(); + const auto proficiencyId = static_cast(object.flags().proficiency().proficiency_id()); + auto profIt = proficiencies.find(proficiencyId); + if (profIt == proficiencies.end()) { + g_logger().warn("[Items::loadFromProtobuf] - Unknown Proficiency ID '{}'", proficiencyId); + } else { + iType.proficiencyId = proficiencyId; + } + } if (!iType.name.empty()) { nameToItems.insert({ asLowerCaseString(iType.name), iType.id }); diff --git a/src/items/items.hpp b/src/items/items.hpp index 0e68c22f520..5181a889444 100644 --- a/src/items/items.hpp +++ b/src/items/items.hpp @@ -104,24 +104,24 @@ class ItemType { ItemType(ItemType &&other) noexcept = default; ItemType &operator=(ItemType &&other) = default; - bool triggerExhaustion() const; + [[nodiscard]] bool triggerExhaustion() const; - bool isGroundTile() const { + [[nodiscard]] bool isGroundTile() const { return group == ITEM_GROUP_GROUND; } - bool isContainer() const { + [[nodiscard]] bool isContainer() const { return group == ITEM_GROUP_CONTAINER; } - bool isSplash() const { + [[nodiscard]] bool isSplash() const { return group == ITEM_GROUP_SPLASH; } - bool isFluidContainer() const { + [[nodiscard]] bool isFluidContainer() const { return group == ITEM_GROUP_FLUID; } - bool isShield() const { + [[nodiscard]] bool isShield() const { return type == ITEM_TYPE_SHIELD && !isSpellBook(); } - bool isSpellBook() const { + [[nodiscard]] bool isSpellBook() const { return spellbook; } @@ -220,15 +220,15 @@ class ItemType { return *abilities; } - int32_t getSpeed() const { + [[nodiscard]] int32_t getSpeed() const { return abilities ? abilities->speed : 0; } - int32_t getSkill(skills_t skill) const { + [[nodiscard]] int32_t getSkill(skills_t skill) const { return abilities ? abilities->skills[skill] : 0; } - int32_t getStat(stats_t stat) const { + [[nodiscard]] int32_t getStat(stats_t stat) const { return abilities ? abilities->stats[stat] : 0; } @@ -248,8 +248,8 @@ class ItemType { return str; } - std::string parseAugmentDescription(bool inspect = false) const; - std::string getFormattedAugmentDescription(const std::shared_ptr &augmentInfo) const; + [[nodiscard]] std::string parseAugmentDescription(bool inspect = false) const; + [[nodiscard]] std::string getFormattedAugmentDescription(const std::shared_ptr &augmentInfo) const; void addAugment(std::string spellName, Augment_t augmentType, int32_t value); @@ -330,6 +330,8 @@ class ItemType { uint8_t imbuementSlot = 0; uint8_t stackSize = 100; + uint16_t proficiencyId = 0; + int8_t hitChance = 0; std::vector> augments; @@ -398,8 +400,8 @@ class Items { const ItemType &operator[](size_t id) const { return getItemType(id); } - const ItemType &getItemType(size_t id) const; - ItemType &getItemType(size_t id); + [[nodiscard]] const ItemType &getItemType(size_t id) const; + [[nodiscard]] ItemType &getItemType(size_t id); /** * @brief Check if the itemid "hasId" is stored on "items", if not, return false @@ -408,11 +410,11 @@ class Items { * @return true if the item exist * @return false if the item not exist */ - bool hasItemType(size_t hasId) const; + [[nodiscard]] bool hasItemType(size_t hasId) const; - uint16_t getItemIdByName(const std::string &name); + [[nodiscard]] uint16_t getItemIdByName(const std::string &name); - ItemTypes_t getLootType(const std::string &strValue) const; + [[nodiscard]] ItemTypes_t getLootType(const std::string &strValue) const; bool loadFromXml(); void parseItemNode(const pugi::xml_node &itemNode, uint16_t id); diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp index 878fd00fe39..6bf25ee8365 100644 --- a/src/items/items_definitions.hpp +++ b/src/items/items_definitions.hpp @@ -275,15 +275,27 @@ enum ImbuementTypes_t : int64_t { }; enum class Augment_t : uint8_t { - None, - Base, - PowerfulImpact, - StrongImpact, - IncreasedDamage, - Cooldown, - CriticalExtraDamage, - LifeLeech, - ManaLeech + None = 0, + ManaCost = 1, // Not implemented to use in items.xml + BaseDamage = 2, + BaseHealing = 3, + DurationIncreased = 4, // Not implemented to use in items.xml + AdditionalTargets = 5, // Not implemented to use in items.xml + Cooldown = 6, + SecondaryGroupCooldown = 7, // Not implemented to use in items.xml + AffectedAreaEnlarged = 8, // Not implemented to use in items.xml + IncreasedDamageReduction = 9, // Not implemented to use in items.xml + + EnhancedEffect = 12, // Not implemented to use in items.xml + IncreasedSkill = 13, // Not implemented to use in items.xml + LifeLeech = 14, + ManaLeech = 15, + CriticalExtraDamage = 16, + CriticalHitChance = 17, + + PowerfulImpact = 100, + StrongImpact = 101, + IncreasedDamage = 102, }; enum class ContainerCategory_t : uint8_t { diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp index 49f3bbc566f..4094a124e42 100644 --- a/src/items/weapons/weapons.cpp +++ b/src/items/weapons/weapons.cpp @@ -132,7 +132,9 @@ void Weapon::configureWeapon(const ItemType &it) { id = it.id; } -int32_t Weapon::playerWeaponCheck(const std::shared_ptr &player, const std::shared_ptr &target, uint8_t shootRange) const { +int32_t Weapon::playerWeaponCheck(const std::shared_ptr &player, const std::shared_ptr &target, int32_t shootRange) const { + shootRange += player->weaponProficiency().getStat(WeaponProficiencyBonus_t::ATTACK_RANGE); + const Position &playerPos = player->getPosition(); const Position &targetPos = target->getPosition(); if (playerPos.z != targetPos.z) { @@ -641,10 +643,11 @@ int16_t WeaponMelee::getElementDamageValue() const { } int32_t WeaponMelee::getWeaponDamage(const std::shared_ptr &player, const std::shared_ptr &, const std::shared_ptr &item, bool maxDamage /*= false*/) const { + const auto proficiencyAttack = player->weaponProficiency().getStat(WeaponProficiencyBonus_t::ATTACK_DAMAGE); const int32_t attackSkill = player->getWeaponSkill(item); const int32_t physicalAttack = std::max(0, item->getAttack()); const int32_t elementalAttack = getElementDamageValue(); - const int32_t combinedAttack = physicalAttack + elementalAttack; + const int32_t combinedAttack = physicalAttack + elementalAttack + proficiencyAttack; const float attackFactor = player->getAttackFactor(); const uint32_t level = player->getLevel(); @@ -825,6 +828,7 @@ bool WeaponDistance::useWeapon(const std::shared_ptr &player, const std: const auto &bow = player->getWeapon(true); if (bow && bow->getHitChance() != 0) { chance += bow->getHitChance(); + chance += player->weaponProficiency().getStat(WeaponProficiencyBonus_t::RANGED_HIT_CHANCE); } } @@ -894,6 +898,7 @@ int16_t WeaponDistance::getElementDamageValue() const { int32_t WeaponDistance::getWeaponDamage(const std::shared_ptr &player, const std::shared_ptr &target, const std::shared_ptr &item, bool maxDamage /*= false*/) const { int32_t attackValue = item->getAttack(); + attackValue += player->weaponProficiency().getStat(WeaponProficiencyBonus_t::ATTACK_DAMAGE); bool hasElement = false; if (player && item && item->getWeaponType() == WEAPON_AMMO) { diff --git a/src/items/weapons/weapons.hpp b/src/items/weapons/weapons.hpp index 0d0d27cd43f..093c58aef02 100644 --- a/src/items/weapons/weapons.hpp +++ b/src/items/weapons/weapons.hpp @@ -64,7 +64,7 @@ class Weapon { return false; } - int32_t playerWeaponCheck(const std::shared_ptr &player, const std::shared_ptr &target, uint8_t shootRange) const; + int32_t playerWeaponCheck(const std::shared_ptr &player, const std::shared_ptr &target, int32_t shootRange) const; static bool useFist(const std::shared_ptr &player, const std::shared_ptr &target); virtual bool useWeapon(const std::shared_ptr &player, const std::shared_ptr &item, const std::shared_ptr &target) const; diff --git a/src/lua/creature/movement.cpp b/src/lua/creature/movement.cpp index 1a9390759f5..c42dea7a6f0 100644 --- a/src/lua/creature/movement.cpp +++ b/src/lua/creature/movement.cpp @@ -623,6 +623,12 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr &moveEvent, const player->setMainBackpackUnassigned(item->getContainer()); } + if (slot == CONST_SLOT_LEFT) { + player->weaponProficiency().clearAllStats(); + player->weaponProficiency().applyPerks(item->getID()); + player->sendWeaponProficiency(item->getID()); + } + player->sendStats(); player->sendSkills(); player->updatePartyMantra(); @@ -712,6 +718,11 @@ uint32_t MoveEvent::DeEquipItem(const std::shared_ptr &, const std::s g_game().transformItem(item, it.transformDeEquipTo); } + if (slot == CONST_SLOT_LEFT) { + player->weaponProficiency().clearAllStats(); + player->sendWeaponProficiency(item->getID()); + } + player->sendStats(); player->sendSkills(); player->updatePartyMantra(); diff --git a/src/lua/functions/creatures/monster/loot_functions.cpp b/src/lua/functions/creatures/monster/loot_functions.cpp index 46afa6e2d01..35795ee27e6 100644 --- a/src/lua/functions/creatures/monster/loot_functions.cpp +++ b/src/lua/functions/creatures/monster/loot_functions.cpp @@ -38,52 +38,83 @@ void LootFunctions::init(lua_State* L) { } int LootFunctions::luaCreateLoot(lua_State* L) { - // Loot() will create a new loot item - auto loot = std::make_shared(); + // Loot(monsterName) will create a new loot item + const int argc = lua_gettop(L); + + std::shared_ptr loot = std::make_shared(); + + if (argc >= 2) { + if (!Lua::isString(L, 2)) { + luaL_error(L, "Loot([monsterName]) expects argument #1 to be a string"); + return 0; + } + + std::string monsterName = Lua::getString(L, 2); + loot = std::make_shared(monsterName); + } + Lua::pushUserdata(L, loot); Lua::setMetatable(L, -1, "Loot"); return 1; } -int LootFunctions::luaLootSetId(lua_State* L) { - // loot:setId(id) +template +static int luaLootSetter(lua_State* L) { const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); if (loot) { - if (Lua::isNumber(L, 2)) { - loot->lootBlock.id = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - g_logger().warn("[LootFunctions::luaLootSetId] - " - "Unknown loot item loot, int value expected"); - lua_pushnil(L); - } + loot->lootBlock.*member = Lua::getNumber(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } +template +static int luaLootStringSetter(lua_State* L) { + const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); + if (loot) { + loot->lootBlock.*member = Lua::getString(L, 2); + Lua::pushBoolean(L, true); + } else { + lua_pushnil(L); + } + return 1; +} + +int LootFunctions::luaLootSetId(lua_State* L) { + return luaLootSetter(L); +} + int LootFunctions::luaLootSetIdFromName(lua_State* L) { // loot:setIdFromName(name) const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); if (loot && Lua::isString(L, 2)) { auto name = Lua::getString(L, 2); + const auto &monsterName = loot->monsterName; + const auto monsterContext = monsterName.empty() ? "" : " (monster: " + monsterName + ")"; const auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name)); if (ids.first == Item::items.nameToItems.cend()) { g_logger().warn("[LootFunctions::luaLootSetIdFromName] - " - "Unknown loot item {}", - name); + "Unknown loot item '{}'{}", + name, monsterContext); lua_pushnil(L); return 1; } if (std::next(ids.first) != ids.second) { + // Build a list of all conflicting IDs for a useful debug message + std::string conflictingIds; + for (auto it = ids.first; it != ids.second; ++it) { + if (!conflictingIds.empty()) { + conflictingIds += ", "; + } + conflictingIds += std::to_string(it->second); + } g_logger().warn("[LootFunctions::luaLootSetIdFromName] - " - "Non-unique loot item {}", - name); - lua_pushnil(L); - return 1; + "Duplicate item name '{}' found with IDs: [{}]. Using first ID: {}{}", + name, conflictingIds, ids.first->second, monsterContext); } loot->lootBlock.id = ids.first->second; @@ -96,172 +127,60 @@ int LootFunctions::luaLootSetIdFromName(lua_State* L) { return 1; } -int LootFunctions::luaLootSetSubType(lua_State* L) { - // loot:setSubType(type) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.subType = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; +int LootFunctions::luaLootSetMinCount(lua_State* L) { + return luaLootSetter(L); } -int LootFunctions::luaLootSetChance(lua_State* L) { - // loot:setChance(chance) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.chance = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; +int LootFunctions::luaLootSetMaxCount(lua_State* L) { + return luaLootSetter(L); } -int LootFunctions::luaLootSetMinCount(lua_State* L) { - // loot:setMinCount(min) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.countmin = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; +int LootFunctions::luaLootSetSubType(lua_State* L) { + return luaLootSetter(L); } -int LootFunctions::luaLootSetMaxCount(lua_State* L) { - // loot:setMaxCount(max) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.countmax = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; +int LootFunctions::luaLootSetChance(lua_State* L) { + return luaLootSetter(L); } int LootFunctions::luaLootSetActionId(lua_State* L) { - // loot:setActionId(actionid) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.actionId = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetText(lua_State* L) { - // loot:setText(text) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.text = Lua::getString(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootStringSetter<&LootBlock::text>(L); } int LootFunctions::luaLootSetNameItem(lua_State* L) { - // loot:setNameItem(name) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.name = Lua::getString(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootStringSetter<&LootBlock::name>(L); } int LootFunctions::luaLootSetArticle(lua_State* L) { - // loot:setArticle(article) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.article = Lua::getString(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootStringSetter<&LootBlock::article>(L); } int LootFunctions::luaLootSetAttack(lua_State* L) { - // loot:setAttack(attack) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.attack = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetDefense(lua_State* L) { - // loot:setDefense(defense) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.defense = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetExtraDefense(lua_State* L) { - // loot:setExtraDefense(defense) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.extraDefense = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetArmor(lua_State* L) { - // loot:setArmor(armor) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.armor = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetShootRange(lua_State* L) { - // loot:setShootRange(range) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.shootRange = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetHitChance(lua_State* L) { - // loot:setHitChance(chance) - const auto &loot = Lua::getUserdataShared(L, 1, "Loot"); - if (loot) { - loot->lootBlock.hitChance = Lua::getNumber(L, 2); - Lua::pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; + return luaLootSetter(L); } int LootFunctions::luaLootSetUnique(lua_State* L) { diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 8681cf6069b..cdc3292e67f 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -34,6 +34,7 @@ #include "enums/account_coins.hpp" #include "enums/account_errors.hpp" #include "enums/player_icons.hpp" +#include "enums/imbuement.hpp" #include "lua/functions/lua_functions_loader.hpp" void PlayerFunctions::init(lua_State* L) { @@ -259,8 +260,10 @@ void PlayerFunctions::init(lua_State* L) { Lua::registerMethod(L, "Player", "forgetSpell", PlayerFunctions::luaPlayerForgetSpell); Lua::registerMethod(L, "Player", "hasLearnedSpell", PlayerFunctions::luaPlayerHasLearnedSpell); + Lua::registerMethod(L, "Player", "applyImbuementScroll", PlayerFunctions::luaPlayerApplyImbuementScroll); Lua::registerMethod(L, "Player", "openImbuementWindow", PlayerFunctions::luaPlayerOpenImbuementWindow); Lua::registerMethod(L, "Player", "closeImbuementWindow", PlayerFunctions::luaPlayerCloseImbuementWindow); + Lua::registerMethod(L, "Player", "clearAllImbuements", PlayerFunctions::luaPlayerClearAllImbuements); Lua::registerMethod(L, "Player", "sendTutorial", PlayerFunctions::luaPlayerSendTutorial); Lua::registerMethod(L, "Player", "addMapMark", PlayerFunctions::luaPlayerAddMapMark); @@ -417,6 +420,9 @@ void PlayerFunctions::init(lua_State* L) { Lua::registerMethod(L, "Player", "getHarmonyDamage", PlayerFunctions::luaPlayerGetHarmonyDamage); Lua::registerMethod(L, "Player", "calculateFlatDamageHealing", PlayerFunctions::luaCalculateFlatDamageHealing); + Lua::registerMethod(L, "Player", "setSpeed", PlayerFunctions::luaPlayerSetSpeed); + Lua::registerMethod(L, "Player", "addWeaponExperience", PlayerFunctions::luaPlayerAddWeaponExperience); + // OTCR Features Lua::registerMethod(L, "Player", "getMapShader", PlayerFunctions::luaPlayerGetMapShader); Lua::registerMethod(L, "Player", "setMapShader", PlayerFunctions::luaPlayerSetMapShader); @@ -3296,8 +3302,8 @@ int PlayerFunctions::luaPlayerSendTutorial(lua_State* L) { return 1; } -int PlayerFunctions::luaPlayerOpenImbuementWindow(lua_State* L) { - // player:openImbuementWindow(item) +int PlayerFunctions::luaPlayerApplyImbuementScroll(lua_State* L) { + // player:applyImbuementScroll(item, scrollItem) const auto &player = Lua::getUserdataShared(L, 1, "Player"); if (!player) { Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); @@ -3306,13 +3312,32 @@ int PlayerFunctions::luaPlayerOpenImbuementWindow(lua_State* L) { } const auto &item = Lua::getUserdataShared(L, 2, "Item"); - if (!item) { + const auto &scrollItem = Lua::getUserdataShared(L, 3, "Item"); + if (!item || !scrollItem) { Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); Lua::pushBoolean(L, false); return 1; } - player->openImbuementWindow(item); + player->applyScrollImbuement(item, scrollItem); + + return 1; +} + +int PlayerFunctions::luaPlayerOpenImbuementWindow(lua_State* L) { + // player:openImbuementWindow([action[, item]]) + const auto &player = Lua::getUserdataShared(L, 1, "Player"); + if (!player) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 1; + } + + const ImbuementAction action = Lua::getNumber(L, 2, ImbuementAction::Open); + const auto &item = Lua::getUserdataShared(L, 3, "Item"); + + player->openImbuementWindow(action, item); + Lua::pushBoolean(L, true); return 1; } @@ -3329,6 +3354,27 @@ int PlayerFunctions::luaPlayerCloseImbuementWindow(lua_State* L) { return 1; } +int PlayerFunctions::luaPlayerClearAllImbuements(lua_State* L) { + // player:clearAllImbuements(item) + const auto &player = Lua::getUserdataShared(L, 1, "Player"); + if (!player) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 1; + } + + const auto &item = Lua::getUserdataShared(L, 2, "Item"); + if (!item) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 1; + } + + const bool result = player->clearAllImbuements(item); + Lua::pushBoolean(L, result); + return 1; +} + int PlayerFunctions::luaPlayerAddMapMark(lua_State* L) { // player:addMapMark(position, type, description) const auto &player = Lua::getUserdataShared(L, 1, "Player"); @@ -5182,3 +5228,48 @@ int PlayerFunctions::luaPlayerGetVirtue(lua_State* L) { lua_pushnumber(L, static_cast(player->getVirtue())); return 1; } + +int PlayerFunctions::luaPlayerSetSpeed(lua_State* L) { + // player:setSpeed(speed) + const auto &player = Lua::getUserdataShared(L, 1, "Player"); + if (!player) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 1; + } + + const int32_t speed = Lua::getNumber(L, 2); + g_game().setCreatureSpeed(player, speed); + Lua::pushBoolean(L, true); + return 1; +} + +int PlayerFunctions::luaPlayerAddWeaponExperience(lua_State* L) { + // player:addWeaponExperience(experience, itemId) + const auto &player = Lua::getUserdataShared(L, 1, "Player"); + if (!player) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 1; + } + + const auto experience = Lua::getNumber(L, 2); + const auto itemId = Lua::getNumber(L, 3, 0); + + if (experience == 0) { + Lua::pushBoolean(L, true); + return 1; + } + + // Validate that the item has a valid proficiency + if (itemId > 0 && (itemId >= Item::items.size() || Item::items[itemId].proficiencyId == 0)) { + g_logger().warn("[{}] - Item ID '{}' has no proficiency assigned", __FUNCTION__, itemId); + Lua::pushBoolean(L, false); + return 1; + } + + player->weaponProficiency().addExperience(experience, itemId); + + Lua::pushBoolean(L, true); + return 1; +} diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index 2cb6de48b45..a259f318601 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -245,8 +245,10 @@ class PlayerFunctions { static int luaPlayerForgetSpell(lua_State* L); static int luaPlayerHasLearnedSpell(lua_State* L); + static int luaPlayerApplyImbuementScroll(lua_State* L); static int luaPlayerOpenImbuementWindow(lua_State* L); static int luaPlayerCloseImbuementWindow(lua_State* L); + static int luaPlayerClearAllImbuements(lua_State* L); static int luaPlayerSendTutorial(lua_State* L); static int luaPlayerAddMapMark(lua_State* L); @@ -408,5 +410,8 @@ class PlayerFunctions { static int luaPlayerGetHarmonyDamage(lua_State* L); static int luaCalculateFlatDamageHealing(lua_State* L); + static int luaPlayerSetSpeed(lua_State* L); + static int luaPlayerAddWeaponExperience(lua_State* L); + friend class CreatureFunctions; }; diff --git a/src/pch.hpp b/src/pch.hpp index d202a21f6d3..1b07e6b55f3 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -22,7 +22,7 @@ #include "utils/vectorsort.hpp" // -------------------- -// STL Includes +// Standard STL Includes // -------------------- #include @@ -49,6 +49,8 @@ #include #include #include +#include +#include // -------------------- // System Includes @@ -146,6 +148,8 @@ format_as(E e) { #include +#include + // ------------------------- // GIT Metadata Includes // ------------------------- @@ -154,13 +158,6 @@ format_as(E e) { #include "gitmetadata.h" #endif -// --------------------- -// Standard STL Includes -// --------------------- - -#include -#include - /** * Static custom libraries that can be pre-compiled like DI and messaging */ diff --git a/src/protobuf/appearances.proto b/src/protobuf/appearances.proto index d15742abe12..12fcac2dc98 100644 --- a/src/protobuf/appearances.proto +++ b/src/protobuf/appearances.proto @@ -42,8 +42,12 @@ enum ITEM_CATEGORY { ITEM_CATEGORY_TIBIA_COINS = 23; ITEM_CATEGORY_CREATURE_PRODUCTS = 24; ITEM_CATEGORY_QUIVER = 25; - ITEM_CATEGORY_SOULCORES = 26; + ITEM_CATEGORY_TWOHANDWEAPON = 26; ITEM_CATEGORY_FIST_WEAPONS = 27; + ITEM_CATEGORY_BACKPACK = 28; + ITEM_CATEGORY_ONEHANDWEAPON = 29; + ITEM_CATEGORY_ARROW = 30; + ITEM_CATEGORY_SOULCORES = 31; } enum PLAYER_PROFESSION { @@ -183,6 +187,7 @@ message AppearanceFlags { optional bool wrapkit = 57; optional AppearanceFlagSkillWheelGem skillwheel_gem = 58; optional bool dual_wielding = 59; + optional AppearanceFlagProficiency proficiency = 61; } message AppearanceFlagUpgradeClassification { @@ -261,8 +266,12 @@ message AppearanceFlagCyclopedia { } message AppearanceFlagSkillWheelGem { - optional uint32 gem_quality_id = 1; - optional uint32 vocation_id = 2; + optional uint32 gem_quality_id = 1; + optional uint32 vocation_id = 2; +} + +message AppearanceFlagProficiency { + optional uint32 proficiency_id = 1; } message SpecialMeaningAppearanceIds { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 98284f0e00f..a2747c51d98 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -55,6 +55,7 @@ #include "enums/player_blessings.hpp" #include "enums/player_cyclopedia.hpp" #include "enums/container_type.hpp" +#include "enums/imbuement.hpp" /* * NOTE: This namespace is used so that we can add functions without having to declare them in the ".hpp/.hpp" file @@ -301,13 +302,8 @@ namespace { * @param[in] msg The network message to which the calculated skill values will be added. * @param[in] skill The specific skill to calculate (e.g., Life Leech, Mana Leech, Critical Hit Damage, etc.). */ - void addCyclopediaSkills(std::shared_ptr &player, NetworkMessage &msg, skills_t skill) { + void addCyclopediaSkills(std::shared_ptr &player, NetworkMessage &msg, skills_t skill, const SkillsEquipment &skillEquipment) { const auto skillTotal = player->getSkillLevel(skill); - const auto &playerItem = player->getInventoryItem(CONST_SLOT_LEFT); - double skillEquipment = 0.0; - if (playerItem) { - skillEquipment = playerItem->getSkill(skill); - } double skillWheel = 0.0; const auto &playerWheel = player->wheel(); @@ -322,13 +318,34 @@ namespace { skillWheel += playerWheel.checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_DAMAGE); } - double skillImbuement = skillTotal - skillEquipment - skillWheel; + double skillEquipmentValue = skillEquipment.equipment + (player->weaponProficiency().getSkillBonus(skill) / 10000.); + double skillEvent = 0.0; msg.addDouble(skillTotal / 10000.); - msg.addDouble(skillEquipment / 10000.); - msg.addDouble(skillImbuement / 10000.); + msg.addDouble(skillEquipmentValue); + msg.addDouble(skillEquipment.imbuement); msg.addDouble(skillWheel / 10000.); - msg.addDouble(0.00); + msg.addDouble(skillEvent); + } + + void addCyclopediaCriticalSkill(std::shared_ptr &player, NetworkMessage &msg, skills_t skill, const SkillsEquipment &skillEquipment) { + const auto &playerBaseCritical = player->getBaseCritical(); + + double concoctionCritical = 0.0; + double baseCritical = skill == SKILL_CRITICAL_HIT_CHANCE ? playerBaseCritical.chance : playerBaseCritical.damage; + double wheelCritical = player->wheel().getStat(skill == SKILL_CRITICAL_HIT_CHANCE ? WheelStat_t::CRITICAL_CHANCE : WheelStat_t::CRITICAL_DAMAGE) / 10000.0; + + const auto &proficiencyCritical = player->weaponProficiency().getGeneralCritical(); + double proficiencyCriticalValue = skill == SKILL_CRITICAL_HIT_CHANCE ? proficiencyCritical.chance : proficiencyCritical.damage; + double skillEquipmentValue = skillEquipment.equipment + proficiencyCriticalValue; + const auto totalCritical = baseCritical + skillEquipmentValue + wheelCritical + skillEquipment.imbuement + concoctionCritical; + + msg.addDouble(totalCritical); + msg.addDouble(baseCritical); + msg.addDouble(skillEquipmentValue); + msg.addDouble(skillEquipment.imbuement); + msg.addDouble(wheelCritical); + msg.addDouble(concoctionCritical); } } // namespace @@ -1349,6 +1366,12 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvby case 0xB1: parseHighscores(msg); break; + case 0xB2: + parseImbuementAction(msg); + break; + case 0xB3: + parseWeaponProficiency(msg); + break; case 0xBA: parseTaskHuntingAction(msg); break; @@ -1851,9 +1874,8 @@ void ProtocolGame::parseToggleMount(NetworkMessage &msg) { void ProtocolGame::parseApplyImbuement(NetworkMessage &msg) { uint8_t slot = msg.getByte(); - auto imbuementId = msg.get(); - bool protectionCharm = msg.getByte(true) != 0x00; - g_game().playerApplyImbuement(player->getID(), imbuementId, slot, protectionCharm); + auto imbuementId = msg.get(); + g_game().playerApplyImbuement(player->getID(), imbuementId, slot); } void ProtocolGame::parseClearImbuement(NetworkMessage &msg) { @@ -2209,6 +2231,10 @@ void ProtocolGame::parseInspectionObject(NetworkMessage &msg) { auto itemId = msg.get(); uint16_t itemCount = msg.getByte(); g_game().playerInspectItem(player, itemId, static_cast(itemCount), (inspectionType == INSPECT_CYCLOPEDIA)); + } else if (inspectionType == INSPECT_PROFICIENCY) { + const auto itemId = msg.get(); + msg.getByte(); // Unknown byte + sendWeaponProficiencyWindow(itemId); } } @@ -2301,6 +2327,87 @@ void ProtocolGame::parseHighscores(NetworkMessage &msg) { g_game().playerHighscores(player, type, category, vocation, worldName, page, entriesPerPage); } +void ProtocolGame::parseImbuementAction(NetworkMessage &msg) { + if (oldProtocol) { + return; + } + + auto action = static_cast(msg.getByte()); // 0x01 - pick item, 0x02 - scroll imbuement + + std::shared_ptr item = nullptr; + + if (action == ImbuementAction::PickItem) { + msg.skipBytes(2); // Unknown bytes + auto slotId = msg.getByte(); + msg.skipBytes(1); // Unknown byte + msg.skipBytes(1); // Unknown byte + auto itemId = msg.get(); + auto slotIndex = msg.getByte(); + + const bool isContainerItem = slotId >= 0x40; + if (isContainerItem) { + // Padding to not conflict with inventory slot + // the client sends with this padding + slotId -= 0x40; + const auto &container = player->getContainerByID(slotId); + item = container ? container->getItemByIndex(slotIndex) : nullptr; + } else { + item = player->getInventoryItem(static_cast(slotId)); + } + + if (!item || item->getID() != itemId) { + return; + } + + if (item->getImbuementSlot() <= 0) { + if (isContainerItem) { + player->sendImbuementResult("This item is not imbuable."); + } + return; + } + } + + openImbuementWindow(action, item); +} + +void ProtocolGame::parseWeaponProficiency(NetworkMessage &msg) { + if (oldProtocol) { + return; + } + + auto action = msg.getByte(); + auto weaponId = msg.get(); + + if (action == 0x03) { + const auto equippedWeaponId = player->getWeaponId(true); + if (equippedWeaponId != 0 && weaponId == equippedWeaponId) { + player->weaponProficiency().clearAllStats(); + } + player->weaponProficiency().clearSelectedPerks(weaponId); + + auto slots = msg.getByte(); + for (uint8_t slot = 0; slot < slots; slot++) { + auto level = msg.getByte(); + auto perkIndex = msg.getByte(); + + player->weaponProficiency().setSelectedPerk(level, perkIndex, weaponId); + } + + if (equippedWeaponId != 0 && weaponId == equippedWeaponId) { + player->weaponProficiency().applyPerks(weaponId); + } + } else if (action == 0x02) { + const auto equippedWeaponId = player->getWeaponId(true); + if (equippedWeaponId != 0 && weaponId == equippedWeaponId) { + player->weaponProficiency().clearAllStats(); + } + player->weaponProficiency().clearSelectedPerks(weaponId); + } + + sendWeaponProficiencyWindow(weaponId); + sendWeaponProficiency(weaponId); +} + void ProtocolGame::parseTaskHuntingAction(NetworkMessage &msg) { if (oldProtocol) { return; @@ -4242,32 +4349,33 @@ void ProtocolGame::sendCyclopediaCharacterOffenceStats() { msg.addByte(CYCLOPEDIA_CHARACTERINFO_OFFENCESTATS); msg.addByte(0x00); // 0x00 Here means 'no error' - msg.addDouble(player->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) / 10000.); // Crit Chance Total - msg.addDouble(0.00); - msg.addDouble(0.00); - msg.addDouble(0.00); - msg.addDouble(0.00); + const auto &skilsEquipment = player->getSkillsEquipment(); - addCyclopediaSkills(player, msg, SKILL_CRITICAL_HIT_DAMAGE); - addCyclopediaSkills(player, msg, SKILL_LIFE_LEECH_AMOUNT); - addCyclopediaSkills(player, msg, SKILL_MANA_LEECH_AMOUNT); + addCyclopediaCriticalSkill(player, msg, SKILL_CRITICAL_HIT_CHANCE, skilsEquipment[SKILL_CRITICAL_HIT_CHANCE]); + addCyclopediaCriticalSkill(player, msg, SKILL_CRITICAL_HIT_DAMAGE, skilsEquipment[SKILL_CRITICAL_HIT_DAMAGE]); - msg.addDouble(getForgeSkillStat(CONST_SLOT_LEFT)); // Onslaught Total - msg.addDouble(getForgeSkillStat(CONST_SLOT_LEFT, false)); - msg.addDouble(getForgeSkillStat(CONST_SLOT_LEFT) - getForgeSkillStat(CONST_SLOT_LEFT, false)); - msg.addDouble(0.00); + addCyclopediaSkills(player, msg, SKILL_LIFE_LEECH_AMOUNT, skilsEquipment[SKILL_LIFE_LEECH_AMOUNT]); + addCyclopediaSkills(player, msg, SKILL_MANA_LEECH_AMOUNT, skilsEquipment[SKILL_MANA_LEECH_AMOUNT]); + + const double onslaughtTotal = getForgeSkillStat(CONST_SLOT_LEFT); + const double onslaughtEquipment = getForgeSkillStat(CONST_SLOT_LEFT, false); + msg.addDouble(onslaughtTotal); // Onslaught Total + msg.addDouble(onslaughtEquipment); + msg.addDouble(onslaughtTotal - onslaughtEquipment); + msg.addDouble(0.0); // NOTHING msg.addDouble(player->getCleavePercent() / 100.); // Perfect shot range (12.70) - for (uint8_t range = 1; range <= 5; range++) { + for (uint8_t range = 1; range <= 7; range++) { msg.add(static_cast(player->getPerfectShotDamage(range))); } const auto flatBonus = player->calculateFlatDamageHealing(); + uint16_t flatDamageHealingUnknown = 0; msg.add(flatBonus); // Flat Damage and Healing Total msg.add(flatBonus); - msg.add(0x00); + msg.add(flatDamageHealingUnknown); const auto &weapon = player->getWeapon(); if (weapon) { @@ -4285,6 +4393,7 @@ void ProtocolGame::sendCyclopediaCharacterOffenceStats() { msg.addByte(0x00); } else if (it.weaponType == WEAPON_DISTANCE || it.weaponType == WEAPON_AMMO || it.weaponType == WEAPON_MISSILE) { int32_t physicalAttack = std::max(0, weapon->getAttack()); + physicalAttack += player->weaponProficiency().getStat(WeaponProficiencyBonus_t::ATTACK_DAMAGE); int32_t elementalAttack = 0; if (it.abilities && it.abilities->elementType != COMBAT_NONE) { elementalAttack = std::max(0, it.abilities->elementDamage); @@ -4383,6 +4492,97 @@ void ProtocolGame::sendCyclopediaCharacterOffenceStats() { msg.addByte(0x00); } + msg.addDouble(player->weaponProficiency().getPowerfulFoeDamage()); // Influenced/Bosses damage + + const auto &runesCritical = player->weaponProficiency().getRunesCritical(); + const auto &autoAttackCritical = player->weaponProficiency().getAutoAttackCritical(); + + const auto &bestiariesDamage = player->weaponProficiency().getActiveBestiariesDamage(); + msg.add(bestiariesDamage.size()); // Bestiary Damage size + for (const auto &[name, amount] : bestiariesDamage) { + msg.addString(name); // Bestiary category name + msg.addDouble(amount); // Amount + } + + const auto &elementalCriticalChanceOpt = player->weaponProficiency().getActiveElementalCriticalType(WeaponProficiencyBonus_t::ELEMENTAL_HIT_CHANCE); + msg.addByte(elementalCriticalChanceOpt.has_value()); // Has Element Critical Chance + if (elementalCriticalChanceOpt.has_value()) { + msg.addByte(elementalCriticalChanceOpt.value().first); // Element Critical Chance Element ID + msg.addDouble(elementalCriticalChanceOpt.value().second); // Applied Element Critical Chance Value + } + + msg.addDouble(runesCritical.chance); // Offensive Runes Critical Chance + msg.addDouble(autoAttackCritical.chance); // Auto Attack Critical Chance + + const auto &elementalCriticalDamageOpt = player->weaponProficiency().getActiveElementalCriticalType(WeaponProficiencyBonus_t::ELEMENTAL_CRITICAL_EXTRA_DAMAGE); + msg.addByte(elementalCriticalDamageOpt.has_value()); // Has Element Critical Damage + if (elementalCriticalDamageOpt.has_value()) { + msg.addByte(elementalCriticalDamageOpt.value().first); // Element Critical Damage Element ID + msg.addDouble(elementalCriticalDamageOpt.value().second); // Applied Element Critical Damage Value + } + + msg.addDouble(runesCritical.damage); // Offensive Runes Critical Damage + msg.addDouble(autoAttackCritical.damage); // Auto Attack Critical Damage + + msg.add(player->weaponProficiency().getStat(WeaponProficiencyBonus_t::LIFE_GAIN_ON_HIT)); // Life Gain on Hit + msg.add(player->weaponProficiency().getStat(WeaponProficiencyBonus_t::MANA_GAIN_ON_HIT)); // Mana Gain on Hit + msg.add(player->weaponProficiency().getStat(WeaponProficiencyBonus_t::LIFE_GAIN_ON_KILL)); // Life Gain on Kill + msg.add(player->weaponProficiency().getStat(WeaponProficiencyBonus_t::MANA_GAIN_ON_KILL)); // Mana Gain on Kill + + skills_t skill = SKILL_NONE; + if (weapon) { + switch (Item::items[weapon->getID()].type) { + case ITEM_TYPE_SWORD: + skill = SKILL_SWORD; + break; + case ITEM_TYPE_AXE: + skill = SKILL_AXE; + break; + case ITEM_TYPE_CLUB: + skill = SKILL_CLUB; + break; + case ITEM_TYPE_WAND: + skill = SKILL_MAGLEVEL; + break; + case ITEM_TYPE_DISTANCE: + skill = SKILL_DISTANCE; + break; + default: + break; + } + } + + const auto &skillPercentage = player->weaponProficiency().getSkillPercentage(skill); + + double playerSkill = 0.0; + if (skillPercentage.skill != SKILL_NONE) { + playerSkill = skillPercentage.skill == SKILL_MAGLEVEL ? player->getMagicLevel() : player->getSkillLevel(skillPercentage.skill); + } + + bool hasAutoAttackSkill = skillPercentage.skill != SKILL_NONE && skillPercentage.autoAttack; + msg.addByte(hasAutoAttackSkill); // Has Auto Attack Skill + if (hasAutoAttackSkill) { + msg.addByte(static_cast(getCipbiaSkill(skillPercentage.skill))); // Auto Attack Skill ID + msg.addDouble(skillPercentage.autoAttack); // Percent Auto Attack Skill + msg.addDouble(std::round(playerSkill * skillPercentage.autoAttack)); // Applied Auto Attack Value + } + + bool hasSpellDamage = skillPercentage.skill != SKILL_NONE && skillPercentage.spellDamage; + msg.addByte(hasSpellDamage); // Has Spell Damage + if (hasSpellDamage) { + msg.addByte(static_cast(getCipbiaSkill(skillPercentage.skill))); // Spell Damage Skill ID + msg.addDouble(skillPercentage.spellDamage); // Percent Spell Damage + msg.addDouble(std::round(playerSkill * skillPercentage.spellDamage)); // Applied Spell Damage Value + } + + bool hasSpellHealing = skillPercentage.skill != SKILL_NONE && skillPercentage.spellHealing; + msg.addByte(hasSpellHealing); // Has Spell Healing + if (hasSpellHealing) { + msg.addByte(static_cast(getCipbiaSkill(skillPercentage.skill))); // Spell Healing Skill ID + msg.addDouble(skillPercentage.spellHealing); // Percent Spell Healing Skill + msg.addDouble(std::round(playerSkill * skillPercentage.spellHealing)); // Applied Spell Healing Value + } + writeToOutputBuffer(msg); } @@ -4505,7 +4705,39 @@ void ProtocolGame::sendCyclopediaCharacterMiscStats() { msg.add(duration); } - msg.addByte(0x00); + // Active foods are not yet implemented (future feature) + uint8_t activeFoods = 0; + msg.addByte(activeFoods); + for (uint8_t i = 0; i < activeFoods; ++i) { + msg.add(0x00); // Item ID + msg.addByte(0x00); + msg.addByte(0x00); + msg.add(0x00); // Time Left + } + + const auto &weaponProficiencyAugments = player->weaponProficiency().getActiveAugments(); + msg.addByte(weaponProficiencyAugments.size()); + for (const auto &[key, value] : weaponProficiencyAugments) { + msg.add(key.first); // Spell ID + msg.addByte(key.second); // Augment Type + msg.addDouble(value); // Spell Augment Value + } + + const auto &wheelAugments = player->wheel().getActiveAugments(); + msg.addByte(wheelAugments.size()); + for (const auto &[key, value] : wheelAugments) { + msg.add(key.first); // Spell ID + msg.addByte(key.second); // Augment Type + msg.addDouble(value); // Spell Augment Value + } + + const auto &equippedAugments = player->getEquippedAugments(); + msg.addByte(equippedAugments.size()); + for (const auto &[key, value] : equippedAugments) { + msg.add(key.first); // Spell ID + msg.addByte(key.second); // Augment Type + msg.addDouble(value); // Spell Augment Value + } writeToOutputBuffer(msg); } @@ -7020,11 +7252,13 @@ void ProtocolGame::sendUpdateTileItem(const Position &pos, uint32_t stackpos, co writeToOutputBuffer(msg); } -void ProtocolGame::sendRemoveTileThing(const Position &pos, uint32_t stackpos) { +void ProtocolGame::sendRemoveTileThing(const Position &pos, uint32_t stackpos, std::source_location location) { if (!canSee(pos)) { return; } + g_logger().trace("Removing tile thing at position {}, stackpos {} from protocol game, location: {}, called from: {} {}", pos.toString(), stackpos, location.function_name(), location.file_name(), location.line()); + NetworkMessage msg; RemoveTileThing(msg, pos, stackpos); writeToOutputBuffer(msg); @@ -7192,6 +7426,7 @@ void ProtocolGame::sendAddCreature(const std::shared_ptr &creature, co sendInventoryItem(static_cast(i), player->getInventoryItem(static_cast(i))); } + player->sendWeaponProficiency(); sendStats(); sendSkills(); sendBlessStatus(); @@ -8318,6 +8553,7 @@ void ProtocolGame::AddPlayerSkills(NetworkMessage &msg) { msg.addByte(0x00); } else if (it.weaponType == WEAPON_DISTANCE || it.weaponType == WEAPON_AMMO || it.weaponType == WEAPON_MISSILE) { int32_t physicalAttack = std::max(0, weapon->getAttack()); + physicalAttack += player->weaponProficiency().getStat(WeaponProficiencyBonus_t::ATTACK_DAMAGE); int32_t elementalAttack = 0; if (it.abilities && it.abilities->elementType != COMBAT_NONE) { elementalAttack = std::max(0, it.abilities->elementDamage); @@ -8444,91 +8680,118 @@ void ProtocolGame::AddOutfit(NetworkMessage &msg, const Outfit_t &outfit, bool a } } -void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) const { - Imbuement* imbuement = g_imbuements().getImbuement(imbuementId); +void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementID, bool isScrollAction /* = false */) const { + Imbuement* imbuement = g_imbuements().getImbuement(imbuementID); const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID()); - const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory()); - msg.add(imbuementId); - msg.addString(baseImbuement->name + " " + imbuement->getName()); + msg.add(imbuement->getID()); + msg.addString(fmt::format("{} {}", baseImbuement->name, imbuement->getName())); msg.addString(imbuement->getDescription()); - msg.addString(categoryImbuement->name + imbuement->getSubGroup()); + + msg.addByte(imbuement->getBaseID() - 1); msg.add(imbuement->getIconID()); msg.add(baseImbuement->duration); - msg.addByte(imbuement->isPremium() ? 0x01 : 0x00); - - const auto items = imbuement->getItems(); + auto items = imbuement->getItems(); + if (isScrollAction) { + (void)items.emplace_back(std::make_pair(ITEM_EMPTY_IMBUEMENT_SCROLL, 1)); + } msg.addByte(items.size()); - for (const auto &itm : items) { - const ItemType &it = Item::items[itm.first]; - msg.add(itm.first); + for (const auto &[id, amount] : items) { + const ItemType &it = Item::items[id]; + msg.add(id); msg.addString(it.name); - msg.add(itm.second); + msg.add(amount); } msg.add(baseImbuement->price); - msg.addByte(baseImbuement->percent); - msg.add(baseImbuement->protectionPrice); } -void ProtocolGame::openImbuementWindow(const std::shared_ptr &item) { - if (!item || item->isRemoved()) { - return; +void ProtocolGame::addAvailableImbuementsInfo(NetworkMessage &msg, const std::shared_ptr &item, phmap::flat_hash_map &neededItems, bool isScrollAction /* = false */) const { + std::vector imbuements = g_imbuements().getImbuements(player, item, isScrollAction); + msg.add(imbuements.size()); + for (const Imbuement* imbuement : imbuements) { + addImbuementInfo(msg, imbuement->getID(), isScrollAction); + + const auto &imbuementItems = imbuement->getItems(); + for (const auto &[id, _] : imbuementItems) { + if (!neededItems.count(id)) { + const uint32_t invCount = player->getItemTypeCount(id); + const uint32_t stashCount = player->getStashItemCount(id); + const uint32_t total = invCount + stashCount; + neededItems[id] = static_cast(std::min(total, std::numeric_limits::max())); + } + } + } + + if (isScrollAction) { + if (!neededItems.count(ITEM_EMPTY_IMBUEMENT_SCROLL)) { + const uint32_t invCount = player->getItemTypeCount(ITEM_EMPTY_IMBUEMENT_SCROLL); + const uint32_t stashCount = player->getStashItemCount(ITEM_EMPTY_IMBUEMENT_SCROLL); + const uint32_t total = invCount + stashCount; + neededItems[ITEM_EMPTY_IMBUEMENT_SCROLL] = static_cast(std::min(total, std::numeric_limits::max())); + } } +} - player->setImbuingItem(item); +void ProtocolGame::openImbuementWindow(ImbuementAction action, const std::shared_ptr &item) { + if (!item && action == ImbuementAction::PickItem) { + return; + } NetworkMessage msg; msg.addByte(0xEB); - msg.add(item->getID()); - if (!oldProtocol && item->getClassification() > 0) { - msg.addByte(0); - } - msg.addByte(item->getImbuementSlot()); - // Send imbuement time - for (auto slotid = 0; slotid < item->getImbuementSlot(); slotid++) { - ImbuementInfo imbuementInfo; - if (!item->getImbuementInfo(slotid, &imbuementInfo)) { - msg.addByte(0x00); - continue; - } + phmap::flat_hash_map neededItems; - msg.addByte(0x01); - addImbuementInfo(msg, imbuementInfo.imbuement->getID()); - msg.add(imbuementInfo.duration); - msg.add(g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID())->removeCost); - } + msg.addByte(static_cast(action)); + const auto emptyImbuementScrolls = player->getItemTypeCount(ITEM_EMPTY_IMBUEMENT_SCROLL) + player->getStashItemCount(ITEM_EMPTY_IMBUEMENT_SCROLL); + msg.addByte(emptyImbuementScrolls > 0 ? 0x01 : 0x00); + if (action == ImbuementAction::Open) { + msg.add(0); + } else if (action == ImbuementAction::PickItem) { + player->setImbuingItem(item); + msg.add(item->getID()); + if (item->getClassification() > 0) { + msg.addByte(item->getTier()); + } - std::vector imbuements = g_imbuements().getImbuements(player, item); - phmap::flat_hash_map needItems; + msg.addByte(item->getImbuementSlot()); - msg.add(imbuements.size()); - for (const Imbuement* imbuement : imbuements) { - addImbuementInfo(msg, imbuement->getID()); - - const auto items = imbuement->getItems(); - for (const auto &itm : items) { - if (!needItems.count(itm.first)) { - needItems[itm.first] = player->getItemTypeCount(itm.first); - uint32_t stashCount = player->getStashItemCount(Item::items[itm.first].id); - if (stashCount > 0) { - needItems[itm.first] += stashCount; - } + // Imbuements applied + for (uint8_t slotID = 0; slotID < static_cast(item->getImbuementSlot()); slotID++) { + ImbuementInfo imbuementInfo; + if (!item->getImbuementInfo(slotID, &imbuementInfo)) { + msg.addByte(0x00); + continue; } + + msg.addByte(0x01); + addImbuementInfo(msg, imbuementInfo.imbuement->getID()); + msg.add(imbuementInfo.duration); + msg.add(g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID())->removeCost); } + + addAvailableImbuementsInfo(msg, item, neededItems); + + } else if (action == ImbuementAction::Scroll) { + const auto freeSlots = player->getFreeBackpackSlots(); + msg.addByte(freeSlots > 0 ? 0x01 : 0x00); + msg.addByte(0); // Unknown Byte + + addAvailableImbuementsInfo(msg, nullptr, neededItems, true); } - msg.add(needItems.size()); - for (const auto &itm : needItems) { - msg.add(itm.first); - msg.add(itm.second); + msg.add(neededItems.size()); + for (const auto &[id, amount] : neededItems) { + msg.add(id); + msg.add(amount); } - sendResourcesBalance(player->getMoney(), player->getBankBalance(), player->getPreyCards(), player->getTaskHuntingPoints()); + sendResourceBalance(RESOURCE_BANK, player->getBankBalance()); + sendResourceBalance(RESOURCE_INVENTORY_MONEY, player->getMoney()); writeToOutputBuffer(msg); } @@ -10398,3 +10661,43 @@ void ProtocolGame::sendExivaRestrictions( writeToOutputBuffer(msg); } + +void ProtocolGame::sendWeaponProficiency(uint16_t weaponId) { + if (!player || oldProtocol) { + return; + } + + NetworkMessage msg; + + msg.addByte(0x5C); + + msg.add(weaponId); + msg.add(weaponId > 0 ? player->weaponProficiency().getExperience(weaponId) : 0); + msg.addByte(weaponId > 0 && player->weaponProficiency().isUpgradeAvailable(weaponId) ? 0x01 : 0x00); + + writeToOutputBuffer(msg); +} + +void ProtocolGame::sendWeaponProficiencyWindow(uint16_t weaponId) { + if (!player || oldProtocol) { + return; + } + + NetworkMessage msg; + msg.addByte(0xC4); + + msg.add(weaponId); + msg.add(player->weaponProficiency().getExperience(weaponId)); + + const auto &selectedPerks = player->weaponProficiency().getSelectedPerks(weaponId); + + const uint8_t perkCount = static_cast(std::min(selectedPerks.size(), std::numeric_limits::max())); + msg.addByte(perkCount); + for (size_t i = 0; i < perkCount; ++i) { + const auto &perk = selectedPerks[i]; + msg.addByte(perk.level); + msg.addByte(perk.index); + } + + writeToOutputBuffer(msg); +} diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 730ee06eece..7eb064123d2 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -35,6 +35,7 @@ enum SoundEffect_t : uint16_t; enum class SourceEffect_t : uint8_t; enum class HouseAuctionType : uint8_t; enum class MonkData_t : uint8_t; +enum class ImbuementAction : uint8_t; class NetworkMessage; class Player; @@ -174,6 +175,8 @@ class ProtocolGame final : public Protocol { void parseCyclopediaCharacterInfo(NetworkMessage &msg); void parseHighscores(NetworkMessage &msg); + void parseImbuementAction(NetworkMessage &msg); + void parseWeaponProficiency(NetworkMessage &msg); void parseTaskHuntingAction(NetworkMessage &msg); void sendHighscoresNoData(); void sendHighscores(const std::vector &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer); @@ -265,7 +268,8 @@ class ProtocolGame final : public Protocol { void parseCloseChannel(NetworkMessage &msg); // Imbuement info - void addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) const; + void addImbuementInfo(NetworkMessage &msg, uint16_t imbuementID, bool isScrollAction = false) const; + void addAvailableImbuementsInfo(NetworkMessage &msg, const std::shared_ptr &item, phmap::flat_hash_map &neededItems, bool isScrollAction = false) const; // Send functions void sendChannelMessage(const std::string &author, const std::string &text, SpeakClasses type, uint16_t channel); @@ -282,7 +286,7 @@ class ProtocolGame final : public Protocol { void sendIconBakragore(const IconBakragore icon); void sendFYIBox(const std::string &message); - void openImbuementWindow(const std::shared_ptr &item); + void openImbuementWindow(ImbuementAction action, const std::shared_ptr &item = nullptr); void sendImbuementResult(const std::string &message); void closeImbuementWindow(); @@ -434,7 +438,7 @@ class ProtocolGame final : public Protocol { void sendAddTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr &item); void sendUpdateTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr &item); - void sendRemoveTileThing(const Position &pos, uint32_t stackpos); + void sendRemoveTileThing(const Position &pos, uint32_t stackpos, std::source_location loc = std::source_location::current()); void sendUpdateTileCreature(const Position &pos, uint32_t stackpos, const std::shared_ptr &creature); void sendUpdateTile(const std::shared_ptr &tile, const Position &pos); @@ -611,4 +615,7 @@ class ProtocolGame final : public Protocol { const std::vector &addedGuildNames = {}, const std::vector &removedGuildNames = {} ); + + void sendWeaponProficiency(uint16_t weaponId); + void sendWeaponProficiencyWindow(uint16_t weaponId); }; diff --git a/src/server/server_definitions.hpp b/src/server/server_definitions.hpp index c8e44336d27..14fcc8c0f5b 100644 --- a/src/server/server_definitions.hpp +++ b/src/server/server_definitions.hpp @@ -83,7 +83,8 @@ enum InspectObjectTypes : uint8_t { INSPECT_NORMALOBJECT = 0, INSPECT_NPCTRADE = 1, INSPECT_PLAYERTRADE = 2, - INSPECT_CYCLOPEDIA = 3 + INSPECT_CYCLOPEDIA = 3, + INSPECT_PROFICIENCY = 4, }; enum CyclopediaCharacterInfo_OutfitType_t : uint8_t { diff --git a/src/utils/hash.hpp b/src/utils/hash.hpp index 7acee5551e7..f3699f8198c 100644 --- a/src/utils/hash.hpp +++ b/src/utils/hash.hpp @@ -1,5 +1,18 @@ #pragma once +struct PairHash { + std::size_t operator()(const std::pair &p) const noexcept { + // Simple hash combine: shift the 16-bit and add 8-bit + return (static_cast(p.first) << 8) ^ p.second; + } +}; + +struct PairEqual { + bool operator()(const std::pair &a, const std::pair &b) const noexcept { + return a.first == b.first && a.second == b.second; + } +}; + namespace stdext { template using hash = phmap::Hash; diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp index 383613988fb..b5b495ee2be 100644 --- a/src/utils/tools.cpp +++ b/src/utils/tools.cpp @@ -68,6 +68,18 @@ void printXMLError(const std::string &where, const std::string &fileName, const g_logger().error("^"); } +uint8_t undoShift(uint64_t value) { + if (value == 0) { + return 0; + } + + auto trailingZeros = std::countr_zero(value); + if (trailingZeros < 2) { + return 0; + } + return trailingZeros - 2; +} + static uint32_t circularShift(int bits, uint32_t value) { return (value << bits) | (value >> (32 - bits)); } @@ -1983,6 +1995,89 @@ unsigned int getNumberOfCores() { return cores; } +skills_t getSkillsFromCipbiaSkill(CipbiaSkills_t cipbiaSkills) { + using enum CipbiaSkills_t; + + switch (cipbiaSkills) { + case MagicLevel: + return SKILL_MAGLEVEL; + case Shield: + return SKILL_SHIELD; + case Distance: + return SKILL_DISTANCE; + case Sword: + return SKILL_SWORD; + case Club: + return SKILL_CLUB; + case Axe: + return SKILL_AXE; + case Fist: + return SKILL_FIST; + case Fishing: + return SKILL_FISHING; + default: + return SKILL_NONE; + } +} + +CipbiaSkills_t getCipbiaSkill(skills_t skill) { + using enum CipbiaSkills_t; + + switch (skill) { + case SKILL_MAGLEVEL: + return MagicLevel; + case SKILL_SHIELD: + return Shield; + case SKILL_DISTANCE: + return Distance; + case SKILL_SWORD: + return Sword; + case SKILL_CLUB: + return Club; + case SKILL_AXE: + return Axe; + case SKILL_FIST: + return Fist; + case SKILL_FISHING: + return Fishing; + default: + return None; + } +} + +CombatType_t getCombatFromCipbiaElement(Cipbia_Elementals_t cipbiaElement) { + switch (cipbiaElement) { + case CIPBIA_ELEMENTAL_PHYSICAL: + return COMBAT_PHYSICALDAMAGE; + case CIPBIA_ELEMENTAL_ENERGY: + return COMBAT_ENERGYDAMAGE; + case CIPBIA_ELEMENTAL_EARTH: + return COMBAT_EARTHDAMAGE; + case CIPBIA_ELEMENTAL_FIRE: + return COMBAT_FIREDAMAGE; + case CIPBIA_ELEMENTAL_LIFEDRAIN: + return COMBAT_LIFEDRAIN; + case CIPBIA_ELEMENTAL_HEALING: + return COMBAT_HEALING; + case CIPBIA_ELEMENTAL_DROWN: + return COMBAT_DROWNDAMAGE; + case CIPBIA_ELEMENTAL_ICE: + return COMBAT_ICEDAMAGE; + case CIPBIA_ELEMENTAL_HOLY: + return COMBAT_HOLYDAMAGE; + case CIPBIA_ELEMENTAL_DEATH: + return COMBAT_DEATHDAMAGE; + case CIPBIA_ELEMENTAL_MANADRAIN: + return COMBAT_MANADRAIN; + case CIPBIA_ELEMENTAL_AGONY: + return COMBAT_AGONYDAMAGE; + case CIPBIA_ELEMENTAL_HEALING_2: + return COMBAT_HEALING; + default: + return COMBAT_NONE; + } +} + Cipbia_Elementals_t getCipbiaElement(CombatType_t combatType) { switch (combatType) { case COMBAT_PHYSICALDAMAGE: diff --git a/src/utils/tools.hpp b/src/utils/tools.hpp index bb7192133ca..594ffdb59ad 100644 --- a/src/utils/tools.hpp +++ b/src/utils/tools.hpp @@ -15,6 +15,7 @@ namespace pugi { struct Position; +enum skills_t : int8_t; enum CombatType_t : uint8_t; enum Direction : uint8_t; enum MagicEffectClasses : uint16_t; @@ -33,6 +34,7 @@ enum class ItemAttribute_t : uint64_t; enum ReturnValue : uint16_t; enum SpellGroup_t : uint8_t; enum Cipbia_Elementals_t : uint8_t; +enum class CipbiaSkills_t : uint8_t; enum PlayerPronoun_t : uint8_t; enum PlayerSex_t : uint8_t; @@ -42,11 +44,13 @@ enum PlayerSex_t : uint8_t; void printXMLError(const std::string &where, const std::string &fileName, const pugi::xml_parse_result &result); -std::string transformToSHA1(const std::string &input); +[[nodiscard]] uint8_t undoShift(uint64_t value); -uint16_t getStashSize(const std::map &itemList); +[[nodiscard]] std::string transformToSHA1(const std::string &input); -std::string generateToken(const std::string &secret, uint32_t ticks); +[[nodiscard]] uint16_t getStashSize(const std::map &itemList); + +[[nodiscard]] std::string generateToken(const std::string &secret, uint32_t ticks); void replaceString(std::string &str, const std::string &sought, const std::string &replacement); void trim_right(std::string &source, char t); @@ -54,14 +58,14 @@ void trim_left(std::string &source, char t); std::string keepFirstWordOnly(std::string &str); void toLowerCaseString(std::string &source); -std::string asLowerCaseString(std::string source); -std::string asUpperCaseString(std::string source); +[[nodiscard]] std::string asLowerCaseString(std::string source); +[[nodiscard]] std::string asUpperCaseString(std::string source); -std::string toCamelCase(const std::string &str); -std::string toPascalCase(const std::string &str); -std::string toSnakeCase(const std::string &str); -std::string toKebabCase(const std::string &str); -std::string toStartCaseWithSpace(const std::string &str); +[[nodiscard]] std::string toCamelCase(const std::string &str); +[[nodiscard]] std::string toPascalCase(const std::string &str); +[[nodiscard]] std::string toSnakeCase(const std::string &str); +[[nodiscard]] std::string toKebabCase(const std::string &str); +[[nodiscard]] std::string toStartCaseWithSpace(const std::string &str); using StringVector = std::vector; using IntegerVector = std::vector; @@ -96,11 +100,11 @@ std::string formatDateTime(int64_t ms); * @param name The enum name to format. * @return A string with the formatted enum name. */ -std::string formatEnumName(std::string_view name); -std::time_t getTimeNow(); -int64_t getTimeMsNow(); -int64_t getTimeUsNow(); -std::string convertIPToString(uint32_t ip); +[[nodiscard]] std::string formatEnumName(std::string_view name); +[[nodiscard]] std::time_t getTimeNow(); +[[nodiscard]] int64_t getTimeMsNow(); +[[nodiscard]] int64_t getTimeUsNow(); +[[nodiscard]] std::string convertIPToString(uint32_t ip); void trimString(std::string &str); @@ -151,7 +155,7 @@ CombatType_t indexToCombatType(size_t v); ItemAttribute_t stringToItemAttribute(const std::string &str); -const char* getReturnMessage(ReturnValue value); +[[nodiscard]] const char* getReturnMessage(ReturnValue value); void sleep_for(uint64_t ms); void capitalizeWords(std::string &source); @@ -164,7 +168,7 @@ bool isCaskItem(uint16_t itemId); std::string getObjectCategoryName(ObjectCategory_t category); bool isValidObjectCategory(ObjectCategory_t category); -int64_t OTSYS_TIME(bool useTime = false); +[[nodiscard]] int64_t OTSYS_TIME(bool useTime = false); void UPDATE_OTSYS_TIME(); SpellGroup_t stringToSpellGroup(const std::string &value); @@ -176,7 +180,10 @@ std::vector split(const std::string &str, char delimiter = ','); std::string getFormattedTimeRemaining(uint32_t time); unsigned int getNumberOfCores(); +CipbiaSkills_t getCipbiaSkill(skills_t skill); +skills_t getSkillsFromCipbiaSkill(CipbiaSkills_t cipbiaSkills); +CombatType_t getCombatFromCipbiaElement(Cipbia_Elementals_t combatType); Cipbia_Elementals_t getCipbiaElement(CombatType_t combatType); std::string formatNumber(uint64_t number); @@ -191,7 +198,7 @@ std::string formatWithArticle(const std::string &value, bool withSpace = true); std::string toKey(const std::string &str); -static inline double quadraticPoly(double a, double b, double c, double x) { +inline double quadraticPoly(double a, double b, double c, double x) { return a * x * x + b * x + c; } diff --git a/src/utils/utils_definitions.hpp b/src/utils/utils_definitions.hpp index b5e643c9d08..62a9a5fc18f 100644 --- a/src/utils/utils_definitions.hpp +++ b/src/utils/utils_definitions.hpp @@ -25,6 +25,18 @@ enum SpawnType_t : uint8_t { RESPAWN_IN_NIGHT_CAVE = 4, }; +enum class CipbiaSkills_t : uint8_t { + None = 0, + MagicLevel = 1, + Shield = 6, + Distance = 7, + Sword = 8, + Club = 9, + Axe = 10, + Fist = 11, + Fishing = 13, +}; + enum Cipbia_Elementals_t : uint8_t { CIPBIA_ELEMENTAL_PHYSICAL = 0, CIPBIA_ELEMENTAL_FIRE = 1, @@ -39,6 +51,8 @@ enum Cipbia_Elementals_t : uint8_t { CIPBIA_ELEMENTAL_MANADRAIN = 10, CIPBIA_ELEMENTAL_AGONY = 11, CIPBIA_ELEMENTAL_UNDEFINED = 12, + + CIPBIA_ELEMENTAL_HEALING_2 = 18, }; enum MagicEffectClasses : uint16_t { @@ -242,7 +256,17 @@ enum MagicEffectClasses : uint16_t { CONST_ME_OUTBURST_WHITE = 289, CONST_ME_OUTBURST_GREEN = 290, - CONST_ME_OUTBURST_PINK = 291, + CONST_ME_OUTBURST_YELLOW = 291, + + CONST_ME_INK_EXPLOSION = 292, + CONST_ME_PAPER_PLANE = 293, + CONST_ME_WOODEN_STAKES = 294, + CONST_ME_FIRE_SPARKLES = 295, + CONST_ME_OPENING_MAGIC_BOOK = 296, + + CONST_ME_GRAY_ELECTRIC_SPARK = 301, + CONST_ME_GREEN_ELECTRIC_SPARK = 302, + CONST_ME_PURPLE_ELECTRIC_SPARK = 303, CONST_ME_LAST }; @@ -679,6 +703,8 @@ enum ItemID_t : uint16_t { ITEM_SANCTUARY = 49890, + ITEM_EMPTY_IMBUEMENT_SCROLL = 51442, + ITEM_NONE = 0 }; diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index bc8e08e47bb..ca1a2348fa4 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -55,6 +55,7 @@ + @@ -277,6 +278,7 @@ +