Подбор волком и одержимым зомби: E поднимает природные мелочи мира (камешки rock01 и т.п., CanPickup + IsTerrainDecoration)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-13 17:23:58 +03:00
co-authored by Claude Opus 5.5
parent c29ab2bb51
commit a8ee6eb5cf
3 changed files with 59 additions and 1 deletions
+59 -1
View File
@@ -352,7 +352,7 @@ namespace NecromancerTome
} }
if (best == null) if (best == null)
{ {
return false; return TryPickupBlock(_world, _player, cam, from, _wolf);
} }
ItemStack rest = Take(best.itemStack); ItemStack rest = Take(best.itemStack);
if (rest == null) if (rest == null)
@@ -370,6 +370,64 @@ namespace NecromancerTome
return true; return true;
} }
/// <summary>E на подбираемую «природную мелочь» мира - камешек rock01 и т. п. (тест 13.10: «лутающие одержимые и
/// питомцы не могут подбирать предметы, например камни»): блок с CanPickup, что персонаж поднимает по E, - в
/// сумку (что выдаёт - Block.OnBlockPickedUp, как у игры), блок убрать. Только IsTerrainDecoration: CanPickup
/// есть и у построек игрока (каркасы, фонари, котелки) - их по E не утаскиваем. Чужой участок - как у игры
/// (CanPickupBlockAt). Ближайший к лучу камеры в PickupReach от того, кто подбирает.</summary>
static bool TryPickupBlock(World _world, EntityPlayerLocal _player, Transform _cam, Vector3 _from, EntityAlive _who)
{
Vector3i c = World.worldToBlockPos(_who.position);
int r = Mathf.CeilToInt(PickupReach);
Vector3i best = Vector3i.zero;
BlockValue bestBv = BlockValue.Air;
float bestDeg = PickupAimDeg;
for (int x = -r; x <= r; x++)
for (int y = -1; y <= 2; y++)
for (int z = -r; z <= r; z++)
{
Vector3i p = new Vector3i(c.x + x, c.y + y, c.z + z);
BlockValue bv = _world.GetBlock(p);
if (bv.isair || bv.ischild)
{
continue;
}
Block b = bv.Block;
if (b == null || !b.CanPickup || !b.IsTerrainDecoration)
{
continue;
}
Vector3 at = p.ToVector3() + new Vector3(0.5f, 0.3f, 0.5f);
if ((at - _who.position).sqrMagnitude > PickupReach * PickupReach)
{
continue;
}
float deg = Vector3.Angle(_cam.forward, at - _from);
if (deg < bestDeg)
{
bestDeg = deg;
best = p;
bestBv = bv;
}
}
if (bestBv.isair || !_world.CanPickupBlockAt(best, GameManager.Instance.GetPersistentLocalPlayer()))
{
return false;
}
ItemStack st = bestBv.Block.OnBlockPickedUp(_world, best, bestBv, _player.entityId);
ItemStack rest = Take(st);
if (rest == null)
{
return true;
}
if (rest.IsEmpty())
{
_world.SetBlockRPC(best, BlockValue.Air);
Debug.Log("[NecromancerTome] WolfBag: поднят блок " + bestBv.Block.GetBlockName() + " " + best);
}
return true;
}
/// <summary>«Взять всё» - по ячейкам, пока есть место.</summary> /// <summary>«Взять всё» - по ячейкам, пока есть место.</summary>
public static void TakeAll(TEFeatureStorage _te) public static void TakeAll(TEFeatureStorage _te)
{ {
Binary file not shown.
Binary file not shown.