Класс для респаума мобов
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