Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions EpicLoot/API/Reload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private static void ReloadExternalTreasures()
AdventureDataManager.Config.TreasureMap.BiomeInfo.Add(treasure);
}

AdventureDataManager.Config.TreasureMap.UpdateBiomeList();
OnReload?.Invoke("Reloaded external treasures");
}

Expand Down
3 changes: 3 additions & 0 deletions EpicLoot/API/Treasure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public static string AddTreasureMap(string json)

ExternalTreasureMaps.Add(map);
AdventureDataManager.Config.TreasureMap.BiomeInfo.Add(map);
// The spawn-point cache only searches biomes in this list; without the refresh an
// API-added biome never got a radius range or a cached point.
AdventureDataManager.Config.TreasureMap.UpdateBiomeList();
return RuntimeRegistry.Register(map);
}
catch
Expand Down
72 changes: 47 additions & 25 deletions EpicLoot/EpicLoot.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BepInEx;
using Common;
using EpicLoot.Adventure;
using EpicLoot.Biomes;
using EpicLoot.Config;
using EpicLoot.Crafting;
using EpicLoot.CraftingV2;
Expand Down Expand Up @@ -37,7 +38,7 @@ namespace EpicLoot;
public sealed class EpicLoot : BaseUnityPlugin {
public const string PluginId = "randyknapp.mods.epicloot";
public const string DisplayName = "Epic Loot";
public const string Version = "0.13.4";
public const string Version = "0.13.5";

private static string ConfigFileName = PluginId + ".cfg";
private static string ConfigFileFullPath = BepInEx.Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName;
Expand Down Expand Up @@ -101,6 +102,12 @@ void Awake() {

cfg = new ELConfig(Config);

// A biomedata.json reload re-resolves the adventure config's biome names and rebuilds the item
// gating order. Subscribed after the first load, which already ran the three configs in
// dependency order (biomedata, adventuredata, iteminfo), so no immediate call is needed.
BiomeDataManager.OnBiomeDataInitialized += AdventureDataManager.OnBiomeDataChanged;
BiomeDataManager.OnBiomeDataInitialized += GatedItemTypeHelper.OnBiomeDataChanged;

// Set the referenced common logger to the EL specific reference so that common things get logged
PrefabCreator.Logger = Logger;
InitializeAbilities();
Expand Down Expand Up @@ -697,7 +704,6 @@ private static void LoadShardSlotChisels() {
}

private static void LoadUnidentifiedItems() {
// TODO: Add support for biomes added by other mods as needed.
GameObject genericPrefab = EpicAssets.AssetBundle.LoadAsset<GameObject>("_Unidentified");
CustomItem genericUnidentified = new CustomItem(genericPrefab, false);
ItemManager.Instance.AddItem(genericUnidentified);
Expand All @@ -710,30 +716,16 @@ private static void LoadUnidentifiedItems() {
continue;
}

foreach (ItemRarity rarity in Enum.GetValues(typeof(ItemRarity))) {
var prefab = Object.Instantiate(genericPrefab);
string prefabName = $"{biome}_{rarity}_Unidentified";
prefab.name = prefabName;
ItemDrop pid = prefab.GetComponent<ItemDrop>();
var magicItemComponent = pid.m_itemData.Data().GetOrCreate<MagicItemComponent>();
pid.m_itemData.m_dropPrefab = prefab;
magicItemComponent.SetMagicItem(new MagicItem {
Rarity = rarity,
IsUnidentified = true,
});
magicItemComponent.Save();
pid.Save();

ItemConfig unidentifiedIC = new ItemConfig() {
Name = $"$mod_epicloot_{rarity} $mod_epicloot_unidentified_{biome}",
Description = "$mod_epicloot_unidentified_introduce",
};

CustomItem custom = new CustomItem(prefab, false, unidentifiedIC);
ItemManager.Instance.AddItem(custom);
CreateUnidentifiedItems(genericPrefab, biome, $"$mod_epicloot_unidentified_{biome}", unidentifiedPrefabNames);
}

unidentifiedPrefabNames.Add(prefabName);
}
// Biomes other mods add, declared in biomedata.json. Only the local file counts here: LoadAssets
// runs once in Awake after the configs, and prefabs cannot be registered when a server pushes
// its biome data later, so biomedata.json has to ship with the modpack.
foreach (BiomeDefinition definition in BiomeDataManager.CustomBiomes) {
string displayName = $"$mod_epicloot_unidentified_prefix " +
$"{BiomeDataManager.GetLocalizationToken(definition.Biome)} $mod_epicloot_unidentified_suffix";
CreateUnidentifiedItems(genericPrefab, definition.Name, displayName, unidentifiedPrefabNames);
}

// Enable items once things are working so that ZNet issues don't happen.
Expand All @@ -755,6 +747,36 @@ void EnableUnidentifiedItems() {
ItemManager.OnItemsRegistered += EnableUnidentifiedItems;
}

// One {biomeName}_{rarity}_Unidentified prefab per rarity. The biome name is the prefix the identify
// flow parses back out (EnchantHelper.GetBiomeFromUnidentifiedItem), so it must not contain '_'.
private static void CreateUnidentifiedItems(GameObject genericPrefab, string biomeName, string biomeDisplayName,
List<string> unidentifiedPrefabNames) {
foreach (ItemRarity rarity in Enum.GetValues(typeof(ItemRarity))) {
var prefab = Object.Instantiate(genericPrefab);
string prefabName = $"{biomeName}_{rarity}_Unidentified";
prefab.name = prefabName;
ItemDrop pid = prefab.GetComponent<ItemDrop>();
var magicItemComponent = pid.m_itemData.Data().GetOrCreate<MagicItemComponent>();
pid.m_itemData.m_dropPrefab = prefab;
magicItemComponent.SetMagicItem(new MagicItem {
Rarity = rarity,
IsUnidentified = true,
});
magicItemComponent.Save();
pid.Save();

ItemConfig unidentifiedIC = new ItemConfig() {
Name = $"$mod_epicloot_{rarity} {biomeDisplayName}",
Description = "$mod_epicloot_unidentified_introduce",
};

CustomItem custom = new CustomItem(prefab, false, unidentifiedIC);
ItemManager.Instance.AddItem(custom);

unidentifiedPrefabNames.Add(prefabName);
}
}

private static void RegisterStatusEffects() {
RegisterBulwark();
RegisterUndying();
Expand Down
31 changes: 31 additions & 0 deletions EpicLoot/Package/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
**0.13.5**

Changes:
* Custom biome support. Biomes added by other mods (Expand World Data and the like) can be declared in the new `biomedata.json`, which now owns biome progression order, and boss keys
* Every `Biome` field in `adventuredata.json` and every biome key in `enchantcosts.json` takes a biome name (vanilla or from `biomedata.json`) or the numeric biome value
* An unknown biome name is now reported and that entry skipped, instead of the whole config file being thrown away
* Bounties, treasure maps, unidentified items and item gating all read biome order and boss keys from `biomedata.json`
* `Bounties.Bosses` in `adventuredata.json` is deprecated
* A biome with no boss keys is never gated
* Unidentified items are created at startup for every custom biome in the local `biomedata.json` (ship the file with the modpack; a server push alone cannot add prefabs)
* Under `BossKillUnlocksNextBiomeItems`, identifying an item no longer advances past the biome on the item's name
* The identify panel says `(Progress-gated)` when gating will identify a selected item at a lower tier than its biome
* New console commands: `biomes` lists the biome order with keys and status, `knowbiome <biome>` marks a biome discovered so custom-biome bounties can be tested
* `Tempering.CostsByRarity` in `adventuredata.json` now supports removing rarities from tempering entirely
* A rarity left out of the block is no longer temperable at all, and its items are kept out of the temper panel
* A rarity with an empty cost list is still temperable, for free
* Shardstone upgrades moved out of the Convert Materials tab's generic Upgrade list into their own Upgrade Shardstones mode
* That mode only lists an upgrade whose source stone you actually have, instead of every color you hold
* Sacrificing a shardstone now yields 2 dust, 2 reagents and 2 essence of its rarity
* Treasure chests and Bounties now resolve their spawn points much quicker
* Both systems now inherently support custom biomes, world size changes and biome distribution changes

Bugfixes:
* Adds detection and support for custom item containers (such as backpacks, quivers)
* Hotkeys to open sockets on inventory containing items like this automatically changes
* Partially broken creatures used for bounties no longer crash the bounty system
* Treasure maps added through the API now search for positions like normal
* Compendium group headings are no longer unreadable the first time the compendium is opened in a session
* Fixes shards being disenchtantable


**0.13.4**

Changes:
Expand Down
3 changes: 2 additions & 1 deletion EpicLoot/Package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ Shardstones grant a variety of small buffs to allow much greater control over yo
* Press Interact (E) on a socketed item in your inventory to open its shard slots, then drag in a shardstone or an Etched Runestone.
* Enchanted items can now drop with shard slots, and the rarer the item the more slots it is likely to have.
* Shardstones drop all over the world, each biome and boss has their own drops. Maybe you can find a unique shardstone also?
* Shardstones can be upgraded to a higher rarity, or converted into ordinary enchanting materials if you don't want them, at the enchanting table's Convert Materials tab.
* Shardstones can be upgraded to a higher rarity in the enchanting table's Convert Materials tab, under its own Upgrade Shardstones mode
* A shardstone you don't want can be sacrificed for dust, reagents and essence of its own rarity

Shard drops come from the loot tables, so if you have customized your loottables.json you will need to accept the config update prompt (or refresh BepInEx/config/EpicLoot/baseconfig/loottables.json) before any shardstones will drop.

Expand Down
2 changes: 1 addition & 1 deletion EpicLoot/Package/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "EpicLoot",
"version_number": "0.13.4",
"version_number": "0.13.5",
"website_url": "https://discord.gg/ZNhYeavv3C",
"description": "Adds loot drops, magic items, and enchanting to Valheim.",
"dependencies": [
Expand Down
11 changes: 11 additions & 0 deletions EpicLoot/config-patches/EL.examples.enchantcosts.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@
{ "Item": "EssenceMythic", "Amount": 1 },
{ "Item": "ReagentMythic", "Amount": 1 }
]
},
{
"IsMagic" : true,
"Rarity" : "Mythic",
"ItemTypes" : [ "Material" ],
"AmmoTypeSuffixes" : [ "Yagluth|Mythic|ShardStone" ],
"Products" : [
{ "Item": "DustMythic", "Amount": 4 },
{ "Item": "EssenceMythic", "Amount": 4 },
{ "Item": "ReagentMythic", "Amount": 4 }
]
}
]
}
Expand Down
15 changes: 8 additions & 7 deletions EpicLoot/config-patches/EL.examples.shardstoneconversions.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,21 @@
"Value": { "Item": "YagluthDrop", "Amount": 2 }
},
{
"Path": "$.MaterialConversions[?(@.Name == 'ShardStoneConvert_Red_Mythic_to_Essence')].Amount",
"Path": "$.MaterialConversions[?(@.Name == 'ShardStoneUpgrade_Red_Epic_to_Legendary')].Amount",
"Action": "Overwrite",
"Value": 4
"Value": 2
},
{
"Path": "$.MaterialConversions",
"Action": "Append",
"Value": {
"Name": "ShardStoneConvert_Fader_Mythic_to_Shard",
"Product": "ShardMythic",
"Amount": 3,
"Type": "Convert",
"Name": "ShardStoneUpgrade_Fader_Mythic_to_Mythic",
"Product": "Fader_Mythic_ShardStone",
"Amount": 1,
"Type": "ShardUpgrade",
"Resources": [
{ "Item": "Fader_Mythic_ShardStone", "Amount": 1 }
{ "Item": "Fader_Mythic_ShardStone", "Amount": 2 },
{ "Item": "ShardMythic", "Amount": 8 }
]
}
}
Expand Down
10 changes: 0 additions & 10 deletions EpicLoot/config/adventuredata.json
Original file line number Diff line number Diff line change
Expand Up @@ -380,16 +380,6 @@
{ "Biome": "AshLands", "TargetID": "Charred_Melee", "RewardGold": 5, "RewardIron": 9, "RewardCoins": 650, "Adds":
[ { "ID": "Charred_Archer", "Count": 2 }, { "ID": "Charred_Twitcher", "Count": 2 } ] }
],
"Bosses": [
{"Biome": "Meadows", "BossPrefab": "Eikthyr", "BossDefeatedKey": "defeated_eikthyr" },
{"Biome": "BlackForest", "BossPrefab": "gd_king", "BossDefeatedKey": "defeated_gdking" },
{"Biome": "Ocean", "BossPrefab": "gd_king", "BossDefeatedKey": "defeated_gdking" },
{"Biome": "Swamp", "BossPrefab": "Bonemass", "BossDefeatedKey": "defeated_bonemass" },
{"Biome": "Mountain", "BossPrefab": "Dragon", "BossDefeatedKey": "defeated_dragon" },
{"Biome": "Plains", "BossPrefab": "GoblinKing", "BossDefeatedKey": "defeated_goblinking" },
{"Biome": "Mistlands", "BossPrefab": "SeekerQueen", "BossDefeatedKey": "defeated_queen" },
{"Biome": "AshLands", "BossPrefab": "Fader", "BossDefeatedKey": "defeated_fader" }
],
"Names": {
"ChanceForSpecialName": 0.01,
"SpecialNames": [
Expand Down
13 changes: 13 additions & 0 deletions EpicLoot/config/biomedata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"Biomes": [
{ "Name": "Meadows", "ID": 1, "Order": 10, "BossDefeatedKeys": [ "defeated_eikthyr" ], "Color": "#75d966" },
{ "Name": "BlackForest", "ID": 8, "Order": 20, "BossDefeatedKeys": [ "defeated_gdking" ], "Color": "#72a178" },
{ "Name": "Ocean", "ID": 256, "Order": 30, "BossDefeatedKeys": [ "defeated_gdking" ], "Color": "#4a90d9" },
{ "Name": "Swamp", "ID": 2, "Order": 40, "BossDefeatedKeys": [ "defeated_bonemass" ], "Color": "#a88a6f" },
{ "Name": "Mountain", "ID": 4, "Order": 50, "BossDefeatedKeys": [ "defeated_dragon" ], "Color": "#a3bcd6" },
{ "Name": "Plains", "ID": 16, "Order": 60, "BossDefeatedKeys": [ "defeated_goblinking" ], "Color": "#d6cea3" },
{ "Name": "Mistlands", "ID": 512, "Order": 70, "BossDefeatedKeys": [ "defeated_queen" ], "Color": "#8b7cb3" },
{ "Name": "AshLands", "ID": 32, "Order": 80, "BossDefeatedKeys": [ "defeated_fader" ], "Color": "#d94a4a" },
{ "Name": "DeepNorth", "ID": 64, "Order": 90, "BossDefeatedKeys": [], "Color": "#a3d6d6" }
]
}
55 changes: 55 additions & 0 deletions EpicLoot/config/enchantcosts.json
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,61 @@
"Amount": 1
}
]
},
{
"IsMagic": true,
"ItemTypes": [ "Material" ],
"AmmoTypeSuffixes": [ "ShardStone" ],
"Rarity": "Magic",
"Products": [
{ "Item": "DustMagic", "Amount": 2 },
{ "Item": "ReagentMagic", "Amount": 2 },
{ "Item": "EssenceMagic", "Amount": 2 }
]
},
{
"IsMagic": true,
"ItemTypes": [ "Material" ],
"AmmoTypeSuffixes": [ "ShardStone" ],
"Rarity": "Rare",
"Products": [
{ "Item": "DustRare", "Amount": 2 },
{ "Item": "ReagentRare", "Amount": 2 },
{ "Item": "EssenceRare", "Amount": 2 }
]
},
{
"IsMagic": true,
"ItemTypes": [ "Material" ],
"AmmoTypeSuffixes": [ "ShardStone" ],
"Rarity": "Epic",
"Products": [
{ "Item": "DustEpic", "Amount": 2 },
{ "Item": "ReagentEpic", "Amount": 2 },
{ "Item": "EssenceEpic", "Amount": 2 }
]
},
{
"IsMagic": true,
"ItemTypes": [ "Material" ],
"AmmoTypeSuffixes": [ "ShardStone" ],
"Rarity": "Legendary",
"Products": [
{ "Item": "DustLegendary", "Amount": 2 },
{ "Item": "ReagentLegendary", "Amount": 2 },
{ "Item": "EssenceLegendary", "Amount": 2 }
]
},
{
"IsMagic": true,
"ItemTypes": [ "Material" ],
"AmmoTypeSuffixes": [ "ShardStone" ],
"Rarity": "Mythic",
"Products": [
{ "Item": "DustMythic", "Amount": 2 },
{ "Item": "ReagentMythic", "Amount": 2 },
{ "Item": "EssenceMythic", "Amount": 2 }
]
}
],
"EnchantCosts": [
Expand Down
Loading
Loading