diff --git a/Config/Localization.csv b/Config/Localization.csv index 53c32cd..4dbb593 100644 --- a/Config/Localization.csv +++ b/Config/Localization.csv @@ -84,6 +84,7 @@ resourceBloodSphereDesc,items,Item,,,,"Necromancer's blood thickened and sealed resourceBloodStone,items,Item,,,,Blood Stone,,Blutstein,Piedra de sangre,Pierre de sang,Pietra di sangue,血の石,피의 돌,Krwawy kamień,Pedra de sangue,Кровавый камень,Kan Taşı,血石,血石 resourceBloodStoneDesc,items,Item,,,,Necromancer's blood hardened into stone. An inexhaustible charge for the Spatial Bracelet: pulling blocks costs it nothing at all. It also fuels the Bone Steed and the Geo-Ossuary forever.,,Zu Stein erstarrtes Nekromantenblut. Eine unerschöpfliche Ladung für das Raumarmband: das Einziehen von Blöcken kostet sie überhaupt nichts. Treibt außerdem das Knochenross und das Geo-Ossarium für immer an.,Sangre del nigromante endurecida hasta volverse piedra. Una carga inagotable para el Brazalete espacial: absorber bloques no le cuesta nada. También alimenta para siempre al Corcel de hueso y al Geo-osario.,Du sang de nécromancien durci en pierre. Une charge inépuisable pour le Bracelet spatial : aspirer des blocs ne lui coûte rien. Alimente aussi pour toujours le Destrier d'os et le Géo-ossuaire.,Sangue del negromante indurito in pietra. Una carica inesauribile per il Bracciale spaziale: assorbire blocchi non le costa nulla. Alimenta anche per sempre il Destriero d'ossa e il Geo-ossario.,ネクロマンサーの血が固まり石となったもの。「空間の腕輪」の尽きることのない充填であり、ブロックの吸収では何も消耗しない。 骨の駿馬とジオ納骨堂の燃料にもなり、尽きることはない。,"강령술사의 피가 굳어 돌이 된 것. '공간의 팔찌'의 마르지 않는 충전체로, 블록을 흡수해도 전혀 소모되지 않습니다. 뼈 군마와 지오 납골당의 연료로도 영원히 쓰인다.",Krew nekromanty zastygła w kamień. Niewyczerpany ładunek do Bransolety przestrzennej: wciąganie bloków nic go nie kosztuje. Zasila też na zawsze Kościanego rumaka i Geo-ossuarium.,Sangue do necromante endurecido em pedra. Uma carga inesgotável para o Bracelete espacial: absorver blocos não lhe custa nada. Também abastece para sempre o Corcel de osso e o Geo-ossário.,"Кровь некроманта, затвердевшая камнем. Неиссякаемый заряд для Пространственного браслета: поглощение блоков не тратит его вовсе. Также вечно питает Костяного скакуна и Гео-оссуарий.",Taşa dönüşmüş nekromant kanı. Uzam Bileziği için tükenmez bir yük: blok çekmek onu hiç eksiltmez. Kemik Atı'nı ve Jeo-Kemiklik'i de sonsuza dek besler.,亡灵法师之血凝固成石。空间手环永不枯竭的充能:吸收方块不会消耗它分毫。 还能永久为骨骸坐骑和地脉骨堂供能。,亡靈法師之血凝固成石。空間手環永不枯竭的充能:吸收方塊不會消耗它分毫。 還能永久為骨骸坐騎和地脈骨堂供能。 resourceNecromancerBloodNeedsKnife,items,Item,,,,You need a knife to perform this ritual,,Für dieses Ritual brauchst du ein Messer,Necesitas un cuchillo para realizar este ritual,Il te faut un couteau pour accomplir ce rituel,Ti serve un coltello per compiere questo rituale,この儀式にはナイフが必要です,이 의식을 치르려면 칼이 필요합니다,Do tego rytuału potrzebujesz noża,Você precisa de uma faca para realizar este ritual,Для этого ритуала нужен нож,Bu ritüeli gerçekleştirmek için bir bıçağa ihtiyacın var,进行此仪式需要一把刀,進行此儀式需要一把刀 +resourceNecromancerBloodStationForbidden,items,Item,,,,"This ritual can only be performed by hand, not at a workstation",,"Dieses Ritual kann nur von Hand vollzogen werden, nicht an einer Station","Este ritual solo puede realizarse a mano, no en una estación de trabajo","Ce rituel ne s'accomplit qu'à la main, pas sur un poste de travail","Questo rituale si compie solo a mano, non a una stazione di lavoro",この儀式は作業台ではなく自分の手でのみ行える,이 의식은 작업대가 아닌 손으로만 수행할 수 있습니다,"Ten rytuał można wykonać wyłącznie własnymi rękami, nie przy stacji roboczej","Este ritual só pode ser realizado com as próprias mãos, não numa estação de trabalho","Этот ритуал можно провести только своими руками, не на станции","Bu ritüel yalnızca kendi ellerinle yapılabilir, bir çalışma masasında değil",这个仪式只能亲手进行,不能在工作台上完成,這個儀式只能親手進行,不能在工作臺上完成 bookSummonZombieGriffin,items,Item,,,,Grimoire of the Grave Vulture,,Grimoire des Grabgeiers,Grimorio del buitre sepulcral,Grimoire du vautour des tombes,Grimorio dell'avvoltoio sepolcrale,墓場のハゲワシの魔導書,무덤 독수리의 마도서,Grimuar grobowego sępa,Grimório do abutre sepulcral,Гримуар могильного стервятника,Mezar Akbabası Grimuarı,墓地秃鹫魔典,墓地禿鷲魔典 bookSummonZombieGriffinDesc,items,Item,,,,"A necromantic tome that raises a grave vulture bound to your will. It fights alongside you against other zombies until it dies. Your servant guards you on its own: any hostile that comes within 20 meters of you gets attacked. Only one servant can be out at a time - summoning another sends the current one back. Press E to recall it back into the book. Power attack possesses it: you take control of the servant while your body stays behind, defenceless.",,"Ein nekromantisches Buch, das einen Grabgeier erweckt, der deinem Willen unterworfen ist. Er kämpft an deiner Seite gegen andere Zombies, bis er stirbt. Dein Diener bewacht dich von selbst: Jeder Feind, der dir näher als 20 Meter kommt, wird angegriffen. Es kann immer nur ein Diener draußen sein - beschwörst du einen anderen, kehrt der bisherige zurück. Mit E rufst du ihn ins Buch zurück. Mit dem Powerangriff fährst du in deinen Diener und steuerst ihn; dein Körper bleibt schutzlos zurück.","Un tomo nigromántico que alza un Buitre Sepulcral sometido a tu voluntad. Lucha a tu lado contra otros zombis hasta morir. Tu sirviente te protege por su cuenta: ataca a todo enemigo que se acerque a menos de 20 metros de ti. Solo puede haber un sirviente fuera a la vez: invocar otro hace volver al actual. Pulsa E para devolverlo al libro. El ataque potente te permite poseer a tu sirviente y controlarlo; tu cuerpo se queda atrás, indefenso.","Un ouvrage nécromantique qui relève un Vautour des Tombes soumis à ta volonté. Il combat à tes côtés contre les autres zombies jusqu'à sa mort. Ton serviteur te protège de lui-même : tout ennemi qui s'approche à moins de 20 mètres de toi est attaqué. Un seul serviteur peut être dehors à la fois : en invoquer un autre renvoie l'actuel. E le rappelle dans le livre. L'attaque puissante te fait posséder ton serviteur : tu le diriges, tandis que ton corps reste sur place, sans défense.","Un tomo negromantico che rialza un Avvoltoio Sepolcrale soggetto alla tua volontà. Combatte al tuo fianco contro gli altri zombie finché non muore. Il tuo servitore ti protegge da solo: ogni nemico che si avvicina a meno di 20 metri da te viene attaccato. Può essere fuori un solo servitore alla volta: evocarne un altro richiama quello attuale. E lo richiama nel libro. L'attacco potente ti fa possedere il servitore: lo controlli tu, mentre il tuo corpo resta indietro, indifeso.",あなたの意志に縛られた墓場のハゲワシを起こす降霊術の書。死ぬまで、あなたの側で他のゾンビと戦う。僕は自らあなたを守り、20メートル以内に近づいた敵に襲いかかる。同時に出しておける僕は一体だけで、別の僕を呼ぶと今の僕は戻る。Eで書物へ呼び戻せる。強攻撃で僕に憑依し、自ら操れる。そのあいだ体は無防備のまま残る。,당신의 의지에 묶인 무덤 독수리을(를) 일으키는 강령술 서적. 죽을 때까지 당신 곁에서 다른 좀비와 싸운다. 종복은 스스로 당신을 지키며 20미터 안으로 다가온 적을 공격한다. 종복은 한 번에 하나만 불러낼 수 있고 다른 종복을 소환하면 지금의 종복은 돌아간다. E로 책 속에 불러들인다. 강공격으로 종복에게 빙의해 직접 조종한다. 그동안 몸은 무방비로 남는다.,"Nekromancki tom, który wskrzesza Grobowego Sępa związanego twoją wolą. Walczy u twojego boku z innymi zombie, aż zginie. Twój sługa sam cię strzeże: atakuje każdego wroga, który zbliży się do ciebie na mniej niż 20 metrów. Naraz może być przywołany tylko jeden sługa - przywołanie innego odsyła obecnego. E odwołuje go z powrotem do księgi. Atak specjalny pozwala opętać sługę i sterować nim; twoje ciało zostaje bez obrony.","Um tomo necromântico que ergue um Abutre Sepulcral preso à sua vontade. Luta ao seu lado contra outros zumbis até morrer. Seu servo protege você por conta própria: ataca todo inimigo que chegar a menos de 20 metros de você. Só pode haver um servo fora por vez - invocar outro manda o atual de volta. E o chama de volta para o livro. O ataque forte faz você possuir o servo e controlá-lo; seu corpo fica para trás, indefeso.","Некромантский фолиант, поднимающий могильного стервятника, подчинённого вашей воле. Он сражается на вашей стороне против других зомби, пока не погибнет. Слуга сам охраняет вас: нападает на любого врага, подошедшего к вам ближе 20 метров. Одновременно можно держать только одного слугу - призыв другого отзывает нынешнего. E отзывает его обратно в книгу. Силовая атака - вселиться в слугу и управлять им; ваше тело остаётся на месте беззащитным.","İradene bağlı bir Mezar Akbabası dirilten bir nekromansi kitabı. Ölene kadar yanında diğer zombilere karşı savaşır. Hizmetkârın seni kendiliğinden korur: sana 20 metreden fazla yaklaşan her düşmana saldırır. Aynı anda yalnızca bir hizmetkâr dışarıda olabilir - bir başkasını çağırmak mevcut olanı geri gönderir. E onu kitaba geri çağırır. Güçlü saldırı hizmetkârını ele geçirmeni sağlar: onu sen yönetirsin, bedenin ise savunmasız geride kalır.",一本亡灵法术典籍,唤起一只受你意志束缚的墓地秃鹫。它会在你身边与其他僵尸战斗,直到死亡。仆从会主动护卫你:任何靠近你20米以内的敌人都会遭到攻击。同时只能有一个仆从在外——召唤另一个会让当前的仆从返回。按E可将其召回书中。使用强力攻击可附身仆从、亲自操控它,而你的身体会毫无防备地留在原地。,一本亡靈法術典籍,喚起一隻受你意志束縛的墓地禿鷲。牠會在你身邊與其他殭屍戰鬥,直到死亡。僕從會主動護衛你:任何靠近你20公尺以內的敵人都會遭到攻擊。同時只能有一個僕從在外——召喚另一個會讓目前的僕從返回。按E可將其召回書中。使用強力攻擊可附身僕從、親自操控牠,而你的身體會毫無防備地留在原地。 necroZombieGriffinAlreadyActive,items,Item,,,,You already have a Grave Vulture - press E to recall it,,Du hast bereits einen Grabgeier - mit E rufst du ihn zurück,Ya tienes un buitre sepulcral: pulsa E para devolverlo,Tu as déjà un vautour des tombes - appuie sur E pour le rappeler,Hai già un avvoltoio sepolcrale: premi E per richiamarlo,すでに墓場のハゲワシがいます - Eで呼び戻してください,이미 무덤 독수리가 있습니다 - E로 불러들이세요,Masz już grobowego sępa - odwołaj go klawiszem E,Você já tem um abutre sepulcral - aperte E para chamá-lo de volta,У вас уже есть могильный стервятник - отзовите его клавишей E,Zaten bir Mezar Akbabası var - geri çağırmak için E'ye bas,你已经有一只墓地秃鹫了——按E将其召回,你已經有一隻墓地禿鷲了——按E將其召回 diff --git a/HarmonySrc/NecromancerBloodPatch.cs b/HarmonySrc/NecromancerBloodPatch.cs index 44d0dc9..a25ecde 100644 --- a/HarmonySrc/NecromancerBloodPatch.cs +++ b/HarmonySrc/NecromancerBloodPatch.cs @@ -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"); + } + } + } } diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index 7614448..d187778 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb index 694a44a..edc0d3a 100644 Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ