fix(combat): synchronize auto-target presentation

Make the retained toolbar consume retail's payload-free selection notice from canonical live state so a reentrant Auto Target replacement cannot be erased by the outer clear. Restrict automatic acquisition to the requested hostile non-player monster policy and record the intentional PK edge divergence.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-12 20:26:00 +02:00
parent 8be933fc94
commit 0f2d98c501
11 changed files with 225 additions and 7 deletions

View file

@ -0,0 +1,46 @@
using AcDream.Core.Combat;
using AcDream.Core.Items;
namespace AcDream.Core.Tests.Combat;
public sealed class CombatTargetPolicyTests
{
private const uint PlayerId = 0x50000001u;
private static ClientObject Creature(
uint id,
uint flags = 0,
uint petOwner = 0) => new()
{
ObjectId = id,
Type = ItemType.Creature,
PublicWeenieBitfield = flags,
PetOwnerId = petOwner,
};
[Fact]
public void AutomaticAcquisition_AcceptsOnlyAttackableNonPlayerMonster()
{
var player = Creature(PlayerId, SelectedObjectHealthPolicy.BfPlayer);
var monster = Creature(0x50000010u, SelectedObjectHealthPolicy.BfAttackable);
var friendlyNpc = Creature(0x50000011u);
var pet = Creature(0x50000012u, petOwner: PlayerId);
var hostilePlayer = Creature(
0x50000013u,
SelectedObjectHealthPolicy.BfPlayer
| SelectedObjectHealthPolicy.BfPlayerKiller);
player.PublicWeenieBitfield |= SelectedObjectHealthPolicy.BfPlayerKiller;
var attackableDoor = new ClientObject
{
ObjectId = 0x50000014u,
Type = ItemType.Misc,
PublicWeenieBitfield = SelectedObjectHealthPolicy.BfAttackable,
};
Assert.True(CombatTargetPolicy.IsHostileMonster(PlayerId, player, monster));
Assert.False(CombatTargetPolicy.IsHostileMonster(PlayerId, player, friendlyNpc));
Assert.False(CombatTargetPolicy.IsHostileMonster(PlayerId, player, pet));
Assert.False(CombatTargetPolicy.IsHostileMonster(PlayerId, player, hostilePlayer));
Assert.False(CombatTargetPolicy.IsHostileMonster(PlayerId, player, attackableDoor));
}
}