3995af736c
BossState (server-only) + BossAISystem: sole mover, seek -> telegraphed radial slam (AttackWindup) -> phase-2 speed + swarmer summon. Excluded from the EnemyAISystem Charger pass; knockback-immune at all 3 stamp sites; arena-anchored spawn; scaled Health/HitRadius/AttackRange. Grunt windup now commits in its last ~30% (whiffs out-of-range); Charger stagger roots; grunt speed 4.2->5.2; swarmer telegraph synced. SweptMove + zone-enemy spawn-stamp extracted to shared helpers. Zero new [GhostField]. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 lines
1.5 KiB
C#
30 lines
1.5 KiB
C#
using ProjectM.Simulation;
|
|
using Unity.Entities;
|
|
using Unity.Mathematics;
|
|
using Unity.Transforms;
|
|
|
|
namespace ProjectM.Server
|
|
{
|
|
/// <summary>
|
|
/// The ONE per-enemy spawn-stamp for expedition ROOM enemies, shared by RoomEnemyDirectorSystem (wave drip) and
|
|
/// BossAISystem (phase-two summon). Keeps the teardown/relevancy/clear-count contract in a single place so a boss
|
|
/// add can never silently drop a tag: <see cref="ZoneEnemyTag"/> (counted by the room-clear gate),
|
|
/// <see cref="RoomTag"/> (the RoomTeardown filter — Room byte MUST equal the current room), and
|
|
/// <see cref="RegionTag"/>{Expedition} (relevancy — an untagged add would leak to base players, a Base-tagged one
|
|
/// would hide from the expedition party). Scale preserved via <c>baked.WithPosition</c> (never FromPosition, which
|
|
/// resets the [GhostField] Scale). Returns the spawned entity so a caller can layer extra (e.g. boss HP/scale).
|
|
/// </summary>
|
|
public static class ZoneEnemySpawnUtil
|
|
{
|
|
public static Entity Spawn(EntityCommandBuffer ecb, Entity prefab, in LocalTransform baked, float3 pos, byte region, byte room)
|
|
{
|
|
var enemy = ecb.Instantiate(prefab);
|
|
ecb.SetComponent(enemy, baked.WithPosition(pos)); // preserve the baked [GhostField] Scale
|
|
ecb.AddComponent(enemy, new RegionTag { Region = region });
|
|
ecb.AddComponent<ZoneEnemyTag>(enemy);
|
|
ecb.AddComponent(enemy, new RoomTag { Room = room });
|
|
return enemy;
|
|
}
|
|
}
|
|
}
|