Forbid crafting necromancer's blood at workstations (#88)
Station crafts bypass XUiC_RecipeStack entirely - the queue lives in TileEntityWorkstation and HandleRecipeQueue completes it server-side - so neither the knife gate nor the 90% max-HP cost ever fired there. Veto the recipe in XUiC_WorkstationWindowGroup.CraftingRequirementsValid (greys the entry, disables the Craft action, blocks AddItemToQueue) and supply the tooltip via CraftingRequirementsInvalidMessage. Personal inventory crafting uses the base class and is unaffected. New localization key resourceNecromancerBloodStationForbidden (13 languages). Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@ namespace NecromancerTome
|
||||
/// (Extends meleeWpnBladeT0BoneKnife, never overrides DisplayType) is covered by the same
|
||||
/// check automatically.
|
||||
///
|
||||
/// PATCH POINTS - both on XUiC_RecipeStack, decompiled directly (not guessed):
|
||||
/// PATCH POINTS - the first two on XUiC_RecipeStack, decompiled directly (not guessed):
|
||||
/// - SetRecipe(...) Prefix: the earliest confirmed point a "craft this recipe" click reaches
|
||||
/// (XUiC_CraftingQueue.AddRecipeToCraftAtIndex calls straight into this). Blocking here
|
||||
/// (return false) stops the craft from ever starting - recipe/recipeCount never get set,
|
||||
@@ -47,6 +47,10 @@ namespace NecromancerTome
|
||||
/// - outputStack() Prefix+Postfix (via __state): outputStack() is where the output item is
|
||||
/// actually granted, once per queued unit - HP is only deducted when __result is true,
|
||||
/// i.e. the item genuinely was produced this call, not on a failed/blocked attempt.
|
||||
/// - XUiC_WorkstationWindowGroup.CraftingRequirementsValid / InvalidMessage, Postfix
|
||||
/// (2026-11-02): station crafting bypasses both points above entirely, so the blood
|
||||
/// recipe is now vetoed at every workstation window. Details at the patch classes
|
||||
/// near the bottom of this file.
|
||||
///
|
||||
/// CAVEAT - not glossed over: decompiling XUiC_RecipeStack/XUiC_CraftingQueue/XUiM_Recipes did
|
||||
/// NOT turn up the exact line that removes ingredients from the player's inventory (it happens
|
||||
@@ -235,4 +239,54 @@ namespace NecromancerTome
|
||||
Debug.Log("[NecromancerTome] NecromancerBloodPatch: crafted blood, deducted " + amount + " HP from owner=" + __state.entityId);
|
||||
}
|
||||
}
|
||||
|
||||
// 2026-11-02, the user found station crafting bypassing everything above: "Кровь
|
||||
// некроманта можно изготовить на верстаке, но тогда у некроманта не отнимается
|
||||
// здоровье... запретить изготавливать кровь некроманта на верстаке. Только в
|
||||
// собственном инвентаре."
|
||||
//
|
||||
// Root cause (3.4 decompile): a workstation never uses XUiC_RecipeStack. The queue
|
||||
// lives in TileEntityWorkstation.RecipeQueueItem[] and HandleRecipeQueue completes
|
||||
// crafts server-side into the station's own output slot - so both the knife gate
|
||||
// (SetRecipe) and the HP cost (outputStack) are silently skipped there. XML cannot
|
||||
// exclude this one recipe either: XUiM_Recipes.FilterRecipesByWorkstation shows
|
||||
// no-craft_area recipes at every station whose block lists "player" in
|
||||
// Workstation/CraftingAreaRecipes, and the recipe must stay craft_area-free to
|
||||
// remain craftable in the personal window at all.
|
||||
//
|
||||
// The veto therefore hangs on the one gate every station window shares:
|
||||
// XUiC_WorkstationWindowGroup (workbench, campfire, forge, chemistry station, cement
|
||||
// mixer - every station xui group subclasses it). ItemActionEntryCraft disables the
|
||||
// Craft entry AND refuses AddItemToQueue through CraftingRequirementsValid,
|
||||
// XUiC_RecipeList greys the recipe name through the same call, and
|
||||
// CraftingRequirementsInvalidMessage supplies the tooltip - exactly the vanilla path
|
||||
// for a missing tool. The personal inventory window uses the BASE
|
||||
// XUiC_CraftingWindowGroup, which these patches do not touch, so "только в
|
||||
// собственном инвентаре" holds.
|
||||
[HarmonyPatch(typeof(XUiC_WorkstationWindowGroup), "CraftingRequirementsValid")]
|
||||
public static class Patch_XUiC_WorkstationWindowGroup_Valid_NecromancerBlood
|
||||
{
|
||||
// Postfix, not Prefix: vanilla's tool/input/output/fuel checks still run for
|
||||
// every other recipe; we only veto ours afterwards. No console toggle: this
|
||||
// closes a bypass of two core item rules, which have none either.
|
||||
public static void Postfix(Recipe _recipe, ref bool __result)
|
||||
{
|
||||
if (_recipe != null && _recipe.GetName() == NecromancerBloodPatch.BloodItemName)
|
||||
{
|
||||
__result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(XUiC_WorkstationWindowGroup), "CraftingRequirementsInvalidMessage")]
|
||||
public static class Patch_XUiC_WorkstationWindowGroup_InvalidMessage_NecromancerBlood
|
||||
{
|
||||
public static void Postfix(Recipe _recipe, ref string __result)
|
||||
{
|
||||
if (_recipe != null && _recipe.GetName() == NecromancerBloodPatch.BloodItemName)
|
||||
{
|
||||
__result = Localization.Get("resourceNecromancerBloodStationForbidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user