Класс для респаума мобов
SelectiveSpawnPoint.cs
Код:
using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.ComponentModel; using System.Drawing.Design; using System.IO; using Engine; using Engine.EntitySystem; using Engine.MapSystem; using Engine.MathEx; using Engine.PhysicsSystem; using Engine.SoundSystem; using Engine.Renderer; using Engine.Utils; using Engine.FileSystem; using ProjectEntities; namespace ProjectEntities { /// <summary> /// Defines the <see cref="SpawnPoint"/> entity type. /// </summary> public class SelectiveSpawnPointType : MapObjectType { } public class SelectiveSpawnPoint : MapObject { [FieldSerialize] bool triggerFromCode; public class SelectiveSpawnPointItem { [FieldSerialize] private AIType aiType; [FieldSerialize] private UnitType unitType; public AIType AIType { get { return aiType; } set { aiType = value; } } public UnitType UnitType { get { return unitType; } set { unitType = value; } } } [Description("Список UnitTypes, которые будут порождены")] [FieldSerialize] private List<SelectiveSpawnPointItem> spawnerItems = new List<SelectiveSpawnPointItem>(); public List<SelectiveSpawnPointItem> SpawnerItems { get { return spawnerItems; } } [FieldSerialize] private FactionType faction; public FactionType Faction { get { return faction; } set { faction = value; } } [FieldSerialize] float spawnTime; [FieldSerialize] float spawnRadius; [FieldSerialize] int popNumber; [FieldSerialize] float closeToEvent; //counter for remaining time float spawnCounter; //the amount of entities left to spawn int popAmount; bool TFC; SelectiveSpawnPointType _type = null; public new SelectiveSpawnPointType Type { get { return _type; } } [Description("Время в секундах между порождениями")] [DefaultValue(20.0f)] public float SpawnTime { get { return spawnTime; } set { spawnTime = value; } } [Description("Радиус появления, который должен быть свободен от других юнитов")] [DefaultValue(10.0f)] public float SpawnRadius { get { return spawnRadius; } set { spawnRadius = value; } } [Description("Количество объектов, которые будут созданы")] public int PopNumber { get { return popNumber; } set { popNumber = value; } } [Description("Когда игрок входит в этот радиус, объекты будут появляться")] [DefaultValueAttribute(10.0f)] public float CloseToEvent { get { return closeToEvent; } set { closeToEvent = value; } } [Description("Должен быть вызван из кода")] [DefaultValueAttribute(false)] public bool TriggerFromCode { get { return triggerFromCode; } set { triggerFromCode = value; } } protected override void OnPostCreate(bool loaded) { base.OnPostCreate(loaded); spawnCounter = 0.0f; SubscribeToTickEvent(); TFC = TriggerFromCode; } protected override void OnTick() { base.OnTick(); spawnCounter += TickDelta; if (spawnCounter >= SpawnTime) //time to do it { triggerFromCode = TriggerFromCode; if (triggerFromCode == true) return; spawnCounter = 0.0f; if (!isSpawnPositionFree()) return; if (!isCloseToPoint()) return; popAmount++; if (popAmount <= PopNumber) { int next = World.Instance.Random.Next(0, spawnerItems.Count); Unit newUnit = (Unit)Entities.Instance.Create(spawnerItems[next].UnitType, Parent); if (spawnerItems[next].AIType != null) newUnit.InitialAI = spawnerItems[next].AIType; if (faction != null) newUnit.InitialFaction = faction; newUnit.Position = Position; newUnit.Rotation = Rotation; newUnit.PostCreate(); } // Reset so can be retriggered from code. if (popAmount == PopNumber && TFC==true) { TriggerFromCode = true; popAmount = 0; } } } Vec3 FindFreePositionForUnit(Unit unit, Vec3 center) { Vec3 volumeSize = unit.MapBounds.GetSize() + new Vec3(2, 2, 0); for (float zOffset = 0; ; zOffset += .3f) { for (float radius = 3; radius < 8; radius += .6f) { for (float angle = 0; angle < MathFunctions.PI * 2; angle += MathFunctions.PI / 32) { Vec3 pos = center + new Vec3(MathFunctions.Cos(angle), MathFunctions.Sin(angle), 0) * radius + new Vec3(0, 0, zOffset); Bounds volume = new Bounds(pos); volume.Expand(volumeSize * .5f); Body[] bodies = PhysicsWorld.Instance.VolumeCast( volume, (int)ContactGroup.CastOnlyContact); if (bodies.Length == 0) return pos; } } } } bool isCloseToPoint() { bool returnValue = false; if (CloseToEvent <= 0) { returnValue = true; } else { Map.Instance.GetObjects(new Sphere(Position, CloseToEvent), MapObjectSceneGraphGroups.UnitGroupMask, delegate(MapObject mapObject) { PlayerCharacter pchar = mapObject as PlayerCharacter; if (pchar != null) { returnValue = true; } }); } return returnValue; } bool isSpawnPositionFree() { bool returnValue = true; Map.Instance.GetObjects(new Sphere(Position, SpawnRadius), MapObjectSceneGraphGroups.UnitGroupMask, delegate(MapObject mapObject) { Unit unit = mapObject as Unit; //if there is atleast one then we won't spawn if (unit != null) { returnValue = false; } }); foreach (Entity obj in Entities.Instance.EntitiesCollection) { Unit un = obj as Unit; if (un != null) { if ((un.Position - Position).Length() < SpawnRadius) { returnValue = false; } } } return returnValue; } } }
Автор кода: bernie