diff --git a/HarmonySrc/WolfBag.cs b/HarmonySrc/WolfBag.cs index f63085e..fb59687 100644 --- a/HarmonySrc/WolfBag.cs +++ b/HarmonySrc/WolfBag.cs @@ -352,7 +352,7 @@ namespace NecromancerTome } if (best == null) { - return false; + return TryPickupBlock(_world, _player, cam, from, _wolf); } ItemStack rest = Take(best.itemStack); if (rest == null) @@ -370,6 +370,64 @@ namespace NecromancerTome return true; } + /// E на подбираемую «природную мелочь» мира - камешек rock01 и т. п. (тест 13.10: «лутающие одержимые и + /// питомцы не могут подбирать предметы, например камни»): блок с CanPickup, что персонаж поднимает по E, - в + /// сумку (что выдаёт - Block.OnBlockPickedUp, как у игры), блок убрать. Только IsTerrainDecoration: CanPickup + /// есть и у построек игрока (каркасы, фонари, котелки) - их по E не утаскиваем. Чужой участок - как у игры + /// (CanPickupBlockAt). Ближайший к лучу камеры в PickupReach от того, кто подбирает. + 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; + } + /// «Взять всё» - по ячейкам, пока есть место. public static void TakeAll(TEFeatureStorage _te) { diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index 6b33be1..469330b 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb index 110c750..100bcc7 100644 Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ