Пространственный браслет: в руке пусто, блочный хват
Свёрток-«коробочка на бечёвке» (parcelGenericPrefab + HoldType=31, унаследованные от Петли вора) для браслета выглядел нелепо. Теперь в руке не видно ничего, только кулак, повёрнутый вниз. Связка списана с ванильного vehicleMinibikePlaceable (items.xml:13385), где те же две строки стоят подряд: HoldType="7" + HoldingItemHidden="true". Найдено декомпиляцией Assembly-CSharp 3.2.0 через Mono.Cecil, который лежит прямо в игре (Mods/0_TFP_Harmony/Mono.Cecil.dll): - HoldType=7 - это и есть блочный хват: его ставит ItemClassBlock..ctor, а в blocks.xml свойство HoldType не встречается ни разу, то есть каждый блок в игре держится именно этим значением. Костет - это 70, запасной вариант не понадобился. - HoldingItemHidden - штатное свойство ItemClass (PropHoldingItemHidden в .cctor, ParseBool в Init), а Inventory.setHoldingItemTransform в конце делает SetActive(!HoldingItemHidden). Гаснет только модель в руке - иконка инвентаря и предмет на земле не трогаются. - Пустой меш поставить нельзя: ItemClass.CloneModel подставляет заглушку leather.fbx, если ассет не загрузился. Поэтому Meshfile оставлен затычкой, а DropMeshfile - ванильный мешок, как у минибайка. - Действия предмета не задеты: ItemActionEat читает HoldType только ради AnimationDelay[HoldType].RayCast, который равен 0f и у 31, и у 7; ExecuteAction, за которую держится SpatialVaultPatch, его не читает. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEXvXg1FSAQJHrvYbeAKqq
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab1b3eadaf
commit
a645c53ff3
+80
-11
@@ -214,7 +214,31 @@
|
|||||||
<triggered_effect trigger="onProjectileImpact" action="AddBuff" target="positionAOE" range="2" buff="buffNecroDeviatorCharm">
|
<triggered_effect trigger="onProjectileImpact" action="AddBuff" target="positionAOE" range="2" buff="buffNecroDeviatorCharm">
|
||||||
<requirement name="EntityTagCompare" target="other" tags="zombie"/>
|
<requirement name="EntityTagCompare" target="other" tags="zombie"/>
|
||||||
</triggered_effect>
|
</triggered_effect>
|
||||||
|
<!-- Generic stone-on-flesh thud, deliberately left UNCONDITIONAL: it fires on every
|
||||||
|
impact (ground, wall, zombie) so a miss still sounds like something landed. -->
|
||||||
<triggered_effect trigger="onProjectileImpact" action="PlaySound" sound="stonehitorganic"/>
|
<triggered_effect trigger="onProjectileImpact" action="PlaySound" sound="stonehitorganic"/>
|
||||||
|
<!-- The charm's OWN cue - fires only on a hit that actually charms, gated by the exact
|
||||||
|
same "other is a zombie" requirement the AddBuff above uses, so it can never fire on
|
||||||
|
a miss. Requirements on a PlaySound effect are the vanilla stun baton pattern
|
||||||
|
(Data/Config/items.xml:4005 - IsAlive/EntityTagCompare on target="other"), not
|
||||||
|
invented here; onProjectileImpact populating "other" with the hit entity is proven
|
||||||
|
by the AddBuff right above, which already works in game.
|
||||||
|
|
||||||
|
target="other" is meant to play the clip FROM the zombie, i.e. positional at the
|
||||||
|
point of impact instead of at the thrower's head (the attribute itself is vanilla -
|
||||||
|
items.xml:5514 uses target="self"). If it turns out silent in game, drop just the
|
||||||
|
attribute: the effect then plays on self and the gating still holds.
|
||||||
|
|
||||||
|
THE MOD'S OWN SOUND, the first one in the whole mod that is not a borrowed vanilla
|
||||||
|
id: "necroSpiritStoneHit" is defined in this mod's Config/sounds.xml and its clip
|
||||||
|
lives in Resources/necrosounds, built from the Unity project (see that file's header
|
||||||
|
for why a plain wav next to the XML cannot work). If the sound is missing in game,
|
||||||
|
the failure is SILENT - look for "AudioManager LoadAudio failed to load audio clip"
|
||||||
|
in the game log, and note that the generic stonehitorganic above will still play, so
|
||||||
|
"I heard something" is not proof this one fired. -->
|
||||||
|
<triggered_effect trigger="onProjectileImpact" action="PlaySound" target="other" sound="necroSpiritStoneHit">
|
||||||
|
<requirement name="EntityTagCompare" target="other" tags="zombie"/>
|
||||||
|
</triggered_effect>
|
||||||
</effect_group>
|
</effect_group>
|
||||||
</item>
|
</item>
|
||||||
</append>
|
</append>
|
||||||
@@ -1401,19 +1425,64 @@
|
|||||||
(bundle, computer, forge, explosion, campfire, gunsmithing, book). -->
|
(bundle, computer, forge, explosion, campfire, gunsmithing, book). -->
|
||||||
<property name="DescriptionKey" value="braceletSpatialVaultDesc"/>
|
<property name="DescriptionKey" value="braceletSpatialVaultDesc"/>
|
||||||
<property name="CustomIcon" value="ProstranstvennoeHranilische"/>
|
<property name="CustomIcon" value="ProstranstvennoeHranilische"/>
|
||||||
<!-- Same "seed"-style grip as braceletThiefLoop originally had (see that item's own
|
<!-- МЕШ И ХВАТ, 2026-09-13. Просьба в два захода: сперва "пусть будет камень, а
|
||||||
comment for the full history) - foodCropYuccaFruit's own HoldType="31" +
|
хват давай сделаем как когда пытаешься ставить какой-нибудь блок", затем
|
||||||
parcelGenericPrefab.prefab. Unlike Thief's Loop, this item never touches
|
уточнение - "браслет это браслет... в идеале меш камня вообще убрать". Было:
|
||||||
Class="Zoom" (both its actions are Class="Eat"), so it never hit the
|
свёрток-«семечко» parcelGenericPrefab.prefab (коробочка, перевязанная бечёвкой -
|
||||||
"Attachments" transform error that forced Thief's Loop onto a real weapon mesh -
|
для браслета нелепо) + HoldType="31", и то и другое унаследовано от Петли вора.
|
||||||
no reason to change this one's mesh too. TintColor changed to green 2026-08-30
|
|
||||||
per direct request. -->
|
ИТОГ: в руке НЕТ НИЧЕГО, только кулак. Пустой префаб собирать не пришлось - в
|
||||||
|
движке есть готовое свойство, и вся связка целиком списана с ванильного
|
||||||
|
vehicleMinibikePlaceable (items.xml:13385), у которого стоят ровно те же две
|
||||||
|
строки подряд: HoldType="7" + HoldingItemHidden="true".
|
||||||
|
|
||||||
|
HoldType="7" - это и есть блочный хват ("кулак вниз, как будто держишь руль"),
|
||||||
|
не угаданный номер. Декомпилировано Mono.Cecil'ом из Assembly-CSharp 3.2.0
|
||||||
|
(сам Mono.Cecil.dll лежит в Mods/0_TFP_Harmony, отдельный декомпилятор не нужен):
|
||||||
|
|
||||||
|
ItemClassBlock..ctor -> HoldType = new DataItem<int>(7)
|
||||||
|
AnimationDelayData.AnimationDelay[7] =
|
||||||
|
new AnimationDelays(0, 0f, 0f, .31f, .31f, true) <- последний флаг TwoHanded
|
||||||
|
|
||||||
|
В blocks.xml свойства HoldType нет ни разу (0 вхождений), то есть КАЖДЫЙ блок в
|
||||||
|
игре держится именно семёркой из этого конструктора. Костет
|
||||||
|
(meleeWpnKnucklesT0LeatherKnuckles) - это HoldType="70", запасной вариант не
|
||||||
|
понадобился.
|
||||||
|
|
||||||
|
HoldingItemHidden="true" - штатное свойство ItemClass, а не трюк:
|
||||||
|
ItemClass..cctor заводит PropHoldingItemHidden = "HoldingItemHidden",
|
||||||
|
ItemClass.Init читает его через StringParsers.ParseBool, а
|
||||||
|
Inventory.setHoldingItemTransform в самом конце делает
|
||||||
|
holdingItemTransform.gameObject.SetActive(!HoldingItemHidden). Гасится ТОЛЬКО
|
||||||
|
модель в руке: иконка в инвентаре (своя рисованная ProstranstvennoeHranilische)
|
||||||
|
и мешок на земле не трогаются, действия предмета живут в ItemActionEat и от
|
||||||
|
этого GameObject не зависят.
|
||||||
|
|
||||||
|
Пустой меш поставить было НЕЛЬЗЯ, и это проверено, а не предположено:
|
||||||
|
ItemClass.CloneModel, если имя меша пустое и ассет не загрузился, подставляет
|
||||||
|
заглушку "@:Other/Items/Crafting/leather.fbx" - в руке оказался бы кусок кожи.
|
||||||
|
Единственный ванильный предмет вообще без Meshfile - meleeHandMaster (голые
|
||||||
|
руки), и он выкручивается через Canhold="false", что нам не подходит: браслет
|
||||||
|
надо держать, чтобы им пользоваться.
|
||||||
|
|
||||||
|
Meshfile оставлен камнем как безобидная затычка (в руке он скрыт, а для
|
||||||
|
MeshPurpose World/Local/Preview что-то иметь надо), DropMeshfile - ванильный
|
||||||
|
мешок sack_droppedPrefab, ровно тем же приёмом и по той же причине, что у
|
||||||
|
vehicleMinibikePlaceable: выброшенный предмет должно быть видно на земле, а
|
||||||
|
своей модели у него нет. HandMeshfile убран за ненадобностью.
|
||||||
|
|
||||||
|
Про HoldType и действия: единственное место, где ItemActionEat вообще читает
|
||||||
|
HoldType, - AnimationDelay[HoldType].RayCast (в PercentDone и IsActionRunning),
|
||||||
|
и он равен 0f и у старого 31, и у нового 7 (InitStatic заполняет все 100 слотов
|
||||||
|
нулями, ItemClassBlock переписывает слот 7, оставляя RayCast нулём).
|
||||||
|
ExecuteAction, за которую держится SpatialVaultPatch.cs, HoldType не читает
|
||||||
|
вовсе - проверено сканом IL по всей сборке. -->
|
||||||
<property name="Material" value="Morganic"/>
|
<property name="Material" value="Morganic"/>
|
||||||
<property name="Meshfile" value="@:Other/Items/Food/parcelGenericPrefab.prefab"/>
|
<property name="Meshfile" value="@:Other/Items/Crafting/rock_smallPrefab.prefab"/>
|
||||||
<property name="HandMeshfile" value="@:Other/Items/Food/parcelGenericPrefab.prefab"/>
|
<property name="DropMeshfile" value="@:Other/Items/Misc/sack_droppedPrefab.prefab"/>
|
||||||
<property name="DropMeshfile" value="@:Other/Items/Food/parcelGenericPrefab.prefab"/>
|
|
||||||
<property name="TintColor" value="30, 200, 60"/>
|
<property name="TintColor" value="30, 200, 60"/>
|
||||||
<property name="HoldType" value="31"/>
|
<property name="HoldType" value="7"/>
|
||||||
|
<property name="HoldingItemHidden" value="true"/>
|
||||||
<property name="Weight" value="0"/>
|
<property name="Weight" value="0"/>
|
||||||
<property name="Stacknumber" value="1"/>
|
<property name="Stacknumber" value="1"/>
|
||||||
<property name="EconomicValue" value="0"/>
|
<property name="EconomicValue" value="0"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user