Long gone are the days where we go to the deadfire wiki page to see what the debugnames are for the uniques we want in our builds. Now they are all craftable ingame. Hurray!
Big thanks for Noqn for providing Apotheosis, the modding tool for Pillars of Eternity II Deadfire
Installation is easy just place the mod folder in your override folder. If it doesn't exist create one.
PillarsOfEternityII_Data/override/MODFOLDERHERE
For the curious people of people who have unique items from other mods and want also those uniques to be craftable.
Use following UserScripts in Apotheosis program and save it.
Get Apotheosis here https://gitlab.com/noqn/apotheosis/-/tree/main
Follow instructions.
Then create a new script in Apotheosis
Paste below script and run it.
Restart POEII
Enjoy!
int count = 0;
string[] debugnames = { "" } ;
string[] debugnamesID = { "" } ;
// Creates a new recipe category called uniques
if (TryCreateGameData<RecipeCategory>("Lalolalo9_Unique_Crafting", out var Lalolalo9_Unique_CraftingCat))
{
if (Lalolalo9_Unique_CraftingCat.TryGetComponent(out RecipeCategoryComponent rcc))
{
var stringindex = rcc.DisplayName.AppendStringTableEntry("Uniques");
rcc.DisplayName = stringindex;
}
}
else
{
// If the catergory already exist assing Lalolalo9_Unique_CraftingCat var to it.
if(TryGetGameData<RecipeCategory>("Lalolalo9_Unique_Crafting", out Lalolalo9_Unique_CraftingCat))
{
}
}
// Starts adding all unique to a new list because creating new gamedataobjects while looping through it throws errors
foreach (var equipitemGDO in GameData.OfType<EquippableGameData>())
{
// If the item does not have an itemcomponent return
if (!TryGetGameData(equipitemGDO.DebugName, out _, out ItemComponent itemC))
{
return;
}
// Check the name of the item, if its empty chnaces are it does not exist in game
// Tip adding a + "" converts most objects in the game to string especially useful if working with enumerators like FilterTypes in Itemcomponent
var itemdisplayname = itemC.DisplayName.GetStringTableText() + "";
// We only want unique items and not quest related and items with names that are not empty
if (itemC.IsUnique == true && (itemC.FilterType + "") != "Quest" && (itemC.DisplayName.GetStringTableText() + "") != "")
{
// Recipe order in crafitn GUI are not alfabethic or anything, I found out that they are sorted according to when each items was made.
// This step makes the debugnames uniform and when we will sort it the items will be grouped nicely in crafting window
if (equipitemGDO.TryGetComponent(out EquippableComponent EquipCDOPreSorted))
{
// counting how many items are eligible
count = count + 1;
// preparation to assing correct debugnames so the lsit is nicely sorted
string filtertype = itemC.FilterType + "a";
string DebugNameToAdd = "Default";
string EquipTypeSubstituted = (EquipCDOPreSorted.EquipmentType + "").Replace("SmallShield","ShieldS").Replace("MediumShield","ShieldM").Replace("LargeShield","ShieldL");
if(EquipCDOPreSorted.EquipmentType != 0)
{
DebugNameToAdd = filtertype.FirstOrDefault() + "" + EquipTypeSubstituted + "_" + equipitemGDO.DebugName;
}
else
{
DebugNameToAdd = filtertype.FirstOrDefault() + "" + EquipCDOPreSorted.EquipmentSlot + "_" + equipitemGDO.DebugName;
}
// Adding items to the array
debugnames = debugnames.Concat(new string[] { DebugNameToAdd }).ToArray();
debugnamesID = debugnamesID.Concat(new string[] { equipitemGDO.DebugName }).ToArray();
}
}
}
// Sorts the list of debugnames based on the new debugnames
Array.Sort(debugnames, debugnamesID);
// Now we are making the RecipeData items
for (int i = 1; i < count ; i++)
{
// We check if the item can be created, if it exist which I doubt this will run
if (TryCreateGameData<RecipeData>("LalRecipe"+debugnames[i], out var createdRecipe))
{
// We want the recipe component so we can modify it
if (createdRecipe.TryGetComponent(out RecipeComponent recipeComponent))
{
// We want the item which we are adding a recipe to
// Actually all these step may be put together and using try create gamedata as the latest would be best to prevent any unneccesary objects created
if (TryGetGameData<ItemGameData>(debugnamesID[i], out var itemde))
{
// Adding the item to the output list of our recipe component
RecipeProduct itemtoAdd = RecipeProduct.Default with { ItemID = itemde.ID};
recipeComponent.Output = recipeComponent.Output.Add(itemtoAdd);
// Here we need the name again of our string so we can assign it as the recipe name in our overview
if (itemde.TryGetComponent(out EquippableComponent EquipCDO))
{
if (itemde.TryGetComponent(out ItemComponent itemCDO))
{
string NameToAdd = "Default";
// Some replacement to make in game a little bit more readable
string EquipTypeSubstitutedGUI = (EquipCDO.EquipmentType + "").Replace("SmallShield","ShieldS").Replace("MediumShield","ShieldM").Replace("LargeShield","ShieldL");
string EquipSlotSubstitutedGUI = (EquipCDO.EquipmentSlot + "").Replace("GrimoireOrTrinket","GrimTrin").Replace("RingAnyHand","Ring");
if(EquipCDO.EquipmentType != 0)
{
NameToAdd = EquipTypeSubstitutedGUI + " " + itemCDO.DisplayName.GetStringTableText();
}
else
{
NameToAdd = EquipSlotSubstitutedGUI + " " + itemCDO.DisplayName.GetStringTableText();
}
// Assigning the name to the recipe component
var stringindex = recipeComponent.DisplayName.AppendStringTableEntry(NameToAdd);
recipeComponent.DisplayName = stringindex;
}
}
}
// Setting the category and cost
recipeComponent.Category = Lalolalo9_Unique_CraftingCat.ID;
recipeComponent.Cost = 100;
}
}
}