mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-08-19 16:39:20 +08:00
1066 lines
35 KiB
C#
1066 lines
35 KiB
C#
using SharpDX;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CodeWalker.GameFiles
|
|
{
|
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
|
public class Archetype
|
|
{
|
|
public virtual MetaName Type => MetaName.CBaseArchetypeDef;
|
|
|
|
public CBaseArchetypeDef _BaseArchetypeDef;
|
|
public CBaseArchetypeDef BaseArchetypeDef => _BaseArchetypeDef; // for browsing.
|
|
|
|
public MetaHash Hash { get; set; }
|
|
public YtypFile Ytyp { get; set; }
|
|
public MetaHash DrawableDict { get; set; }
|
|
public MetaHash TextureDict { get; set; }
|
|
public MetaHash ClipDict { get; set; }
|
|
public Vector3 BBMin { get; set; }
|
|
public Vector3 BBMax { get; set; }
|
|
public Vector3 BSCenter { get; set; }
|
|
public float BSRadius { get; set; }
|
|
public float LodDist { get; set; }
|
|
public MetaWrapper[] Extensions { get; set; }
|
|
|
|
|
|
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return _BaseArchetypeDef.name.ToString();
|
|
}
|
|
}
|
|
public string AssetName
|
|
{
|
|
get
|
|
{
|
|
return _BaseArchetypeDef.assetName.ToString();
|
|
}
|
|
}
|
|
|
|
|
|
protected void InitVars(ref CBaseArchetypeDef arch)
|
|
{
|
|
_BaseArchetypeDef = arch;
|
|
Hash = arch.assetName;
|
|
if (Hash.Hash == 0) Hash = arch.name;
|
|
DrawableDict = arch.drawableDictionary;
|
|
TextureDict = arch.textureDictionary;
|
|
ClipDict = arch.clipDictionary;
|
|
BBMin = arch.bbMin;
|
|
BBMax = arch.bbMax;
|
|
BSCenter = arch.bsCentre;
|
|
BSRadius = arch.bsRadius;
|
|
LodDist = arch.lodDist;
|
|
}
|
|
|
|
public void Init(YtypFile ytyp, ref CBaseArchetypeDef arch)
|
|
{
|
|
Ytyp = ytyp;
|
|
InitVars(ref arch);
|
|
}
|
|
|
|
public virtual bool IsActive(float hour)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return _BaseArchetypeDef.ToString();
|
|
}
|
|
}
|
|
|
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
|
public class TimeArchetype : Archetype
|
|
{
|
|
public override MetaName Type => MetaName.CTimeArchetypeDef;
|
|
public CTimeArchetypeDef _TimeArchetypeDef;
|
|
public CTimeArchetypeDef TimeArchetypeDef => _TimeArchetypeDef; // for browsing.
|
|
|
|
public uint TimeFlags { get; set; }
|
|
public bool[] ActiveHours { get; set; }
|
|
public string[] ActiveHoursText { get; set; }
|
|
public bool ExtraFlag { get { return ((TimeFlags >> 24) & 1) == 1; } }
|
|
|
|
|
|
public void Init(YtypFile ytyp, ref CTimeArchetypeDef arch)
|
|
{
|
|
Ytyp = ytyp;
|
|
InitVars(ref arch._BaseArchetypeDef);
|
|
_TimeArchetypeDef = arch;
|
|
|
|
TimeFlags = arch.TimeArchetypeDef.timeFlags;
|
|
|
|
UpdateActiveHours();
|
|
}
|
|
|
|
public override bool IsActive(float hour)
|
|
{
|
|
if (ActiveHours == null) return true;
|
|
int h = ((int)hour) % 24;
|
|
if ((h < 0) || (h > 23)) return true;
|
|
return ActiveHours[h];
|
|
}
|
|
|
|
|
|
public void UpdateActiveHours()
|
|
{
|
|
if (ActiveHours == null)
|
|
{
|
|
ActiveHours = new bool[24];
|
|
ActiveHoursText = new string[24];
|
|
}
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
bool v = ((TimeFlags >> i) & 1) == 1;
|
|
ActiveHours[i] = v;
|
|
|
|
int nxth = (i < 23) ? (i + 1) : 0;
|
|
string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
|
|
ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off"));
|
|
}
|
|
}
|
|
|
|
public void SetTimeFlags(uint flags)
|
|
{
|
|
TimeFlags = flags;
|
|
_TimeArchetypeDef._TimeArchetypeDef.timeFlags = flags;
|
|
|
|
UpdateActiveHours();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class MloArchetype : Archetype
|
|
{
|
|
public override MetaName Type => MetaName.CMloArchetypeDef;
|
|
|
|
|
|
public CMloArchetypeDef MloArchetypeDef => _MloArchetypeDef; // for browsing.
|
|
public CMloArchetypeDef _MloArchetypeDef;
|
|
public CMloArchetypeDefData _MloArchetypeDefData;
|
|
|
|
public MCEntityDef[] entities { get; set; }
|
|
public MCMloRoomDef[] rooms { get; set; }
|
|
public MCMloPortalDef[] portals { get; set; }
|
|
public MCMloEntitySet[] entitySets { get; set; }
|
|
public CMloTimeCycleModifier[] timeCycleModifiers { get; set; }
|
|
|
|
|
|
public void Init(YtypFile ytyp, ref CMloArchetypeDef arch)
|
|
{
|
|
Ytyp = ytyp;
|
|
InitVars(ref arch._BaseArchetypeDef);
|
|
_MloArchetypeDef = arch;
|
|
_MloArchetypeDefData = arch.MloArchetypeDef;
|
|
}
|
|
|
|
public bool AddEntity(YmapEntityDef ent, int roomIndex, int portalIndex = -1, int entsetIndex = -1)
|
|
{
|
|
if (ent == null) return false;
|
|
|
|
if (roomIndex >= (rooms?.Length ?? 0))
|
|
{
|
|
throw new ArgumentOutOfRangeException($"Room index {roomIndex} exceeds the amount of rooms in {Name}.");
|
|
}
|
|
if (portalIndex >= (portals?.Length ?? 0))
|
|
{
|
|
throw new ArgumentOutOfRangeException($"Portal index {portalIndex} exceeds the amount of portals in {Name}.");
|
|
}
|
|
if (entsetIndex >= (entitySets?.Length ?? 0))
|
|
{
|
|
throw new ArgumentOutOfRangeException($"EntitySet index {entsetIndex} exceeds the amount of entitySets in {Name}.");
|
|
}
|
|
|
|
var mcEntityDef = new MCEntityDef(ref ent._CEntityDef, this);
|
|
|
|
|
|
if ((roomIndex >= 0) || (portalIndex >= 0))
|
|
{
|
|
var entList = entities?.ToList() ?? new List<MCEntityDef>();
|
|
ent.Index = entList.Count;
|
|
entList.Add(mcEntityDef);
|
|
entities = entList.ToArray();
|
|
|
|
if (roomIndex >= 0)
|
|
{
|
|
var attachedObjs = rooms[roomIndex].AttachedObjects?.ToList() ?? new List<uint>();
|
|
attachedObjs.Add((uint)ent.Index);
|
|
rooms[roomIndex].AttachedObjects = attachedObjs.ToArray();
|
|
}
|
|
if (portalIndex >= 0)
|
|
{
|
|
var attachedObjs = portals[portalIndex].AttachedObjects?.ToList() ?? new List<uint>();
|
|
attachedObjs.Add((uint)ent.Index);
|
|
portals[portalIndex].AttachedObjects = attachedObjs.ToArray();
|
|
}
|
|
}
|
|
else if (entsetIndex >= 0)
|
|
{
|
|
var entset = entitySets[entsetIndex];
|
|
|
|
var entList = entset.Entities?.ToList() ?? new List<MCEntityDef>();
|
|
entList.Add(mcEntityDef);
|
|
entset.Entities = entList.ToArray();
|
|
|
|
var locs = entset.Locations?.ToList() ?? new List<uint>();
|
|
locs.Add(0);//choose a better default location?
|
|
entset.Locations = locs.ToArray();
|
|
|
|
|
|
var mloInstance = ent.MloParent?.MloInstance;
|
|
if ((mloInstance?.EntitySets != null) && (entsetIndex < mloInstance.EntitySets.Length))
|
|
{
|
|
ent.MloEntitySet = mloInstance.EntitySets[entsetIndex];
|
|
}
|
|
}
|
|
else return false;
|
|
|
|
UpdateAllEntityIndexes();
|
|
|
|
return true;
|
|
}
|
|
public bool RemoveEntity(YmapEntityDef ent)
|
|
{
|
|
if (ent == null) return false;
|
|
|
|
if ((ent.MloEntitySet?.Entities != null) && (ent.MloEntitySet?.EntitySet != null))
|
|
{
|
|
var instents = ent.MloEntitySet.Entities;
|
|
var set = ent.MloEntitySet.EntitySet;
|
|
var idx = instents.IndexOf(ent);
|
|
if (idx >= 0)
|
|
{
|
|
var ents = set.Entities.ToList();
|
|
ents.RemoveAt(idx);
|
|
set.Entities = ents.ToArray();
|
|
|
|
var locs = set.Locations.ToList();
|
|
locs.RemoveAt(idx);
|
|
set.Locations = locs.ToArray();
|
|
|
|
UpdateAllEntityIndexes();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (ent.Index >= entities.Length) return false;
|
|
|
|
var delent = entities[ent.Index];
|
|
if (delent != null)
|
|
{
|
|
var newentities = new MCEntityDef[entities.Length - 1];
|
|
var didDel = false;
|
|
int index = 0;
|
|
int delIndex = 0;
|
|
for (int i = 0; i < entities.Length; i++)
|
|
{
|
|
if (entities[i] == delent)
|
|
{
|
|
delIndex = i;
|
|
didDel = true;
|
|
continue;
|
|
}
|
|
|
|
var newent = entities[i];
|
|
newentities[index] = newent;
|
|
index++;
|
|
}
|
|
|
|
entities = newentities;
|
|
|
|
if (didDel)
|
|
{
|
|
FixRoomIndexes(delIndex);
|
|
FixPortalIndexes(delIndex);
|
|
UpdateAllEntityIndexes();
|
|
}
|
|
return didDel;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void AddRoom(MCMloRoomDef room)
|
|
{
|
|
if (room == null) return;
|
|
|
|
room.OwnerMlo = this;
|
|
room.Index = rooms?.Length ?? 0;
|
|
|
|
var newrooms = rooms?.ToList() ?? new List<MCMloRoomDef>();
|
|
newrooms.Add(room);
|
|
rooms = newrooms.ToArray();
|
|
}
|
|
public void RemoveRoom(MCMloRoomDef room)
|
|
{
|
|
if (room == null) return;
|
|
|
|
var newrooms = rooms.ToList();
|
|
newrooms.Remove(room);
|
|
rooms = newrooms.ToArray();
|
|
|
|
for (int i = 0; i < rooms.Length; i++)
|
|
{
|
|
rooms[i].Index = i;
|
|
}
|
|
|
|
UpdatePortalCounts();//portal room indices probably would need to be updated anyway
|
|
}
|
|
|
|
public void AddPortal(MCMloPortalDef portal)
|
|
{
|
|
if (portal == null) return;
|
|
|
|
portal.OwnerMlo = this;
|
|
portal.Index = portals?.Length ?? 0;
|
|
|
|
var newportals = portals?.ToList() ?? new List<MCMloPortalDef>();
|
|
newportals.Add(portal);
|
|
portals = newportals.ToArray();
|
|
|
|
UpdatePortalCounts();
|
|
}
|
|
public void RemovePortal(MCMloPortalDef portal)
|
|
{
|
|
if (portal == null) return;
|
|
|
|
var newportals = portals.ToList();
|
|
newportals.Remove(portal);
|
|
portals = newportals.ToArray();
|
|
|
|
for (int i = 0; i < portals.Length; i++)
|
|
{
|
|
portals[i].Index = i;
|
|
}
|
|
|
|
UpdatePortalCounts();
|
|
}
|
|
|
|
public void AddEntitySet(MCMloEntitySet set)
|
|
{
|
|
if (set == null) return;
|
|
|
|
set.OwnerMlo = this;
|
|
set.Index = entitySets?.Length ?? 0;
|
|
|
|
var newsets = entitySets?.ToList() ?? new List<MCMloEntitySet>();
|
|
newsets.Add(set);
|
|
entitySets = newsets.ToArray();
|
|
}
|
|
public void RemoveEntitySet(MCMloEntitySet set)
|
|
{
|
|
if (set == null) return;
|
|
|
|
var newsets = entitySets.ToList();
|
|
newsets.Remove(set);
|
|
entitySets = newsets.ToArray();
|
|
|
|
for (int i = 0; i < entitySets.Length; i++)
|
|
{
|
|
entitySets[i].Index = i;
|
|
}
|
|
|
|
UpdateAllEntityIndexes();
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FixPortalIndexes(int deletedIndex)
|
|
{
|
|
foreach (var portal in portals)
|
|
{
|
|
List<uint> newAttachedObjects = new List<uint>();
|
|
if (portal.AttachedObjects == null)
|
|
continue;
|
|
|
|
foreach(var objIndex in portal.AttachedObjects)
|
|
{
|
|
if (objIndex == deletedIndex) continue;
|
|
if (objIndex > deletedIndex)
|
|
newAttachedObjects.Add(objIndex - 1); // move the index back so it matches the index in the entitiy array.
|
|
else newAttachedObjects.Add(objIndex); // else just add the index to the attached objects.
|
|
}
|
|
portal.AttachedObjects = newAttachedObjects.ToArray();
|
|
}
|
|
}
|
|
private void FixRoomIndexes(int deletedIndex)
|
|
{
|
|
foreach (var room in rooms)
|
|
{
|
|
List<uint> newAttachedObjects = new List<uint>();
|
|
if (room.AttachedObjects == null)
|
|
continue;
|
|
foreach (var objIndex in room.AttachedObjects)
|
|
{
|
|
if (objIndex == deletedIndex) continue;
|
|
if (objIndex > deletedIndex)
|
|
newAttachedObjects.Add(objIndex - 1); // move the index back so it matches the index in the entitiy array.
|
|
else newAttachedObjects.Add(objIndex); // else just add the index to the attached objects.
|
|
}
|
|
room.AttachedObjects = newAttachedObjects.ToArray();
|
|
}
|
|
}
|
|
|
|
private void UpdateAllEntityIndexes()
|
|
{
|
|
var index = 0;
|
|
if (entities != null)
|
|
{
|
|
for (int i = 0; i < entities.Length; i++)
|
|
{
|
|
entities[i].Index = index++;
|
|
}
|
|
}
|
|
if (entitySets != null)
|
|
{
|
|
for (int e = 0; e < entitySets.Length; e++)
|
|
{
|
|
var set = entitySets[e];
|
|
if (set?.Entities == null) continue;
|
|
for (int i = 0; i < set.Entities.Length; i++)
|
|
{
|
|
set.Entities[i].Index = index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdatePortalCounts()
|
|
{
|
|
if ((rooms == null) || (portals == null)) return;
|
|
|
|
foreach (var room in rooms)
|
|
{
|
|
uint count = 0;
|
|
foreach (var portal in portals)
|
|
{
|
|
if ((portal._Data.roomFrom == room.Index) || (portal._Data.roomTo == room.Index))
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
room._Data.portalCount = count;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public void LoadChildren(Meta meta)
|
|
{
|
|
var centities = MetaTypes.ConvertDataArray<CEntityDef>(meta, MetaName.CEntityDef, _MloArchetypeDefData.entities);
|
|
if (centities != null)
|
|
{
|
|
entities = new MCEntityDef[centities.Length];
|
|
for (int i = 0; i < centities.Length; i++)
|
|
{
|
|
entities[i] = new MCEntityDef(meta, ref centities[i]) { OwnerMlo = this, Index = i };
|
|
}
|
|
}
|
|
|
|
var crooms = MetaTypes.ConvertDataArray<CMloRoomDef>(meta, MetaName.CMloRoomDef, _MloArchetypeDefData.rooms);
|
|
if (crooms != null)
|
|
{
|
|
rooms = new MCMloRoomDef[crooms.Length];
|
|
for (int i = 0; i < crooms.Length; i++)
|
|
{
|
|
rooms[i] = new MCMloRoomDef(meta, crooms[i]) { OwnerMlo = this, Index = i };
|
|
}
|
|
}
|
|
|
|
var cportals = MetaTypes.ConvertDataArray<CMloPortalDef>(meta, MetaName.CMloPortalDef, _MloArchetypeDefData.portals);
|
|
if (cportals != null)
|
|
{
|
|
portals = new MCMloPortalDef[cportals.Length];
|
|
for (int i = 0; i < cportals.Length; i++)
|
|
{
|
|
portals[i] = new MCMloPortalDef(meta, cportals[i]) { OwnerMlo = this, Index = i };
|
|
}
|
|
}
|
|
|
|
var centitySets = MetaTypes.ConvertDataArray<CMloEntitySet>(meta, MetaName.CMloEntitySet, _MloArchetypeDefData.entitySets);
|
|
if (centitySets != null)
|
|
{
|
|
entitySets = new MCMloEntitySet[centitySets.Length];
|
|
for (int i = 0; i < centitySets.Length; i++)
|
|
{
|
|
entitySets[i] = new MCMloEntitySet(meta, centitySets[i], this) { OwnerMlo = this, Index = i };
|
|
}
|
|
UpdateAllEntityIndexes();
|
|
}
|
|
|
|
|
|
timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDefData.timeCycleModifiers);
|
|
|
|
}
|
|
|
|
public int GetEntityObjectIndex(MCEntityDef ent)
|
|
{
|
|
if (entities == null) return -1;
|
|
for (int i = 0; i < entities.Length; i++)
|
|
{
|
|
var e = entities[i];
|
|
if (e == ent)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
public MCMloRoomDef GetEntityRoom(MCEntityDef ent)
|
|
{
|
|
if (rooms == null) return null;
|
|
|
|
int objectIndex = GetEntityObjectIndex(ent);
|
|
if (objectIndex < 0) return null;
|
|
|
|
for (int i = 0; i < rooms.Length; i++)
|
|
{
|
|
var r = rooms[i];
|
|
if (r.AttachedObjects != null)
|
|
{
|
|
for (int j = 0; j < r.AttachedObjects.Length; j++)
|
|
{
|
|
var ind = r.AttachedObjects[j];
|
|
if (ind == objectIndex)
|
|
{
|
|
return r;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
public MCMloPortalDef GetEntityPortal(MCEntityDef ent)
|
|
{
|
|
if (portals == null) return null;
|
|
|
|
int objectIndex = GetEntityObjectIndex(ent);
|
|
if (objectIndex < 0) return null;
|
|
|
|
for (int i = 0; i < portals.Length; i++)
|
|
{
|
|
var p = portals[i];
|
|
if (p.AttachedObjects != null)
|
|
{
|
|
for (int j = 0; j < p.AttachedObjects.Length; j++)
|
|
{
|
|
var ind = p.AttachedObjects[j];
|
|
if (ind == objectIndex)
|
|
{
|
|
return p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
public MCMloEntitySet GetEntitySet(MCEntityDef ent)
|
|
{
|
|
if (entitySets == null) return null;
|
|
|
|
for (int i = 0; i < entitySets.Length; i++)
|
|
{
|
|
var set = entitySets[i];
|
|
if (set.Entities != null)
|
|
{
|
|
for (int j = 0; j < set.Entities.Length; j++)
|
|
{
|
|
if (set.Entities[j] == ent)
|
|
{
|
|
return set;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
|
public class MloInstanceData
|
|
{
|
|
public YmapEntityDef Owner { get; set; }
|
|
public MloArchetype MloArch { get; set; }
|
|
public CMloInstanceDef _Instance;
|
|
public CMloInstanceDef Instance { get { return _Instance; } set { _Instance = value; } }
|
|
public uint[] defaultEntitySets { get; set; }
|
|
|
|
public YmapEntityDef[] Entities { get; set; }
|
|
public MloInstanceEntitySet[] EntitySets { get; set; }
|
|
|
|
public MloInstanceData(YmapEntityDef owner, MloArchetype mloa)
|
|
{
|
|
Owner = owner;
|
|
MloArch = mloa;
|
|
}
|
|
|
|
public void CreateYmapEntities()
|
|
{
|
|
if (Owner == null) return;
|
|
if (MloArch?.entities == null) return;
|
|
var ec = MloArch.entities.Length;
|
|
|
|
var entlist = new List<YmapEntityDef>();
|
|
for (int i = 0; i < ec; i++)
|
|
{
|
|
var e = CreateYmapEntity(Owner, MloArch.entities[i], i);
|
|
entlist.Add(e);
|
|
}
|
|
|
|
int lasti = ec;
|
|
|
|
var entitySets = MloArch.entitySets;
|
|
if (entitySets != null)
|
|
{
|
|
EntitySets = new MloInstanceEntitySet[entitySets.Length];
|
|
for (int i = 0; i < entitySets.Length; i++)
|
|
{
|
|
var entitySet = entitySets[i];
|
|
var instset = new MloInstanceEntitySet(entitySet, this);
|
|
if (entitySet.Entities != null)
|
|
{
|
|
for (int j = 0; j < entitySet.Entities.Length; j++)
|
|
{
|
|
var e = CreateYmapEntity(Owner, entitySet.Entities[j], lasti);
|
|
instset.Entities.Add(e);
|
|
e.MloEntitySet = instset;
|
|
lasti++;
|
|
}
|
|
}
|
|
EntitySets[i] = instset;
|
|
}
|
|
}
|
|
|
|
if ((defaultEntitySets != null) && (EntitySets != null))
|
|
{
|
|
for (var i = 0; i < defaultEntitySets.Length; i++)
|
|
{
|
|
uint index = defaultEntitySets[i];
|
|
if (index >= EntitySets.Length) continue;
|
|
var instset = EntitySets[index];
|
|
instset.Visible = true;
|
|
}
|
|
}
|
|
|
|
Entities = entlist.ToArray();
|
|
}
|
|
|
|
public void InitYmapEntityArchetypes(GameFileCache gfc)
|
|
{
|
|
if (Owner == null) return;
|
|
var arch = Owner.Archetype;
|
|
|
|
if (Entities != null)
|
|
{
|
|
for (int j = 0; j < Entities.Length; j++)
|
|
{
|
|
var ient = Entities[j];
|
|
var iarch = gfc.GetArchetype(ient._CEntityDef.archetypeName);
|
|
ient.SetArchetype(iarch);
|
|
|
|
if (iarch == null)
|
|
{ } //can't find archetype - des stuff eg {des_prologue_door}
|
|
}
|
|
|
|
UpdateBBs(arch);
|
|
}
|
|
|
|
if (EntitySets != null)
|
|
{
|
|
for (int e = 0; e < EntitySets.Length; e++)
|
|
{
|
|
var entitySet = EntitySets[e];
|
|
var entities = entitySet.Entities;
|
|
if (entities == null) continue;
|
|
|
|
for (int i = 0; i < entities.Count; i++)
|
|
{
|
|
var ient = entities[i];
|
|
var iarch = gfc.GetArchetype(ient._CEntityDef.archetypeName);
|
|
ient.SetArchetype(iarch);
|
|
|
|
if (iarch == null)
|
|
{ } //can't find archetype - des stuff eg {des_prologue_door}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdateBBs(Archetype arch)
|
|
{
|
|
//update archetype room AABB's.. bad to have this here? where else to put it?
|
|
var mloa = arch as MloArchetype;
|
|
if (mloa != null)
|
|
{
|
|
Vector3 mlobbmin = Vector3.Zero;
|
|
Vector3 mlobbmax = Vector3.Zero;
|
|
Vector3[] c = new Vector3[8];
|
|
var rooms = mloa.rooms;
|
|
if (rooms != null)
|
|
{
|
|
for (int j = 0; j < rooms.Length; j++)
|
|
{
|
|
var room = rooms[j];
|
|
if ((room.AttachedObjects == null) || (room.AttachedObjects.Length == 0)) continue;
|
|
Vector3 min = new Vector3(float.MaxValue);
|
|
Vector3 max = new Vector3(float.MinValue);
|
|
for (int k = 0; k < room.AttachedObjects.Length; k++)
|
|
{
|
|
var objid = room.AttachedObjects[k];
|
|
if (objid < Entities.Length)
|
|
{
|
|
var rooment = Entities[objid];
|
|
if ((rooment != null) && (rooment.Archetype != null))
|
|
{
|
|
var earch = rooment.Archetype;
|
|
var pos = rooment._CEntityDef.position;
|
|
var ori = rooment.Orientation;
|
|
Vector3 abmin = earch.BBMin * rooment.Scale; //entity box
|
|
Vector3 abmax = earch.BBMax * rooment.Scale;
|
|
c[0] = abmin;
|
|
c[1] = new Vector3(abmin.X, abmin.Y, abmax.Z);
|
|
c[2] = new Vector3(abmin.X, abmax.Y, abmin.Z);
|
|
c[3] = new Vector3(abmin.X, abmax.Y, abmax.Z);
|
|
c[4] = new Vector3(abmax.X, abmin.Y, abmin.Z);
|
|
c[5] = new Vector3(abmax.X, abmin.Y, abmax.Z);
|
|
c[6] = new Vector3(abmax.X, abmax.Y, abmin.Z);
|
|
c[7] = abmax;
|
|
for (int n = 0; n < 8; n++)
|
|
{
|
|
Vector3 corn = ori.Multiply(c[n]) + pos;
|
|
min = Vector3.Min(min, corn);
|
|
max = Vector3.Max(max, corn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
room.BBMin_CW = min;
|
|
room.BBMax_CW = max;
|
|
mlobbmin = Vector3.Min(mlobbmin, min);
|
|
mlobbmax = Vector3.Max(mlobbmax, max);
|
|
}
|
|
}
|
|
mloa.BBMin = mlobbmin;
|
|
mloa.BBMax = mlobbmax;
|
|
}
|
|
}
|
|
|
|
public YmapEntityDef CreateYmapEntity(YmapEntityDef owner, MCEntityDef ment, int index)
|
|
{
|
|
YmapEntityDef e = new YmapEntityDef(null, index, ref ment._Data);
|
|
e.Extensions = ment.Extensions;
|
|
e.MloRefPosition = e.Position;
|
|
e.MloRefOrientation = e.Orientation;
|
|
e.MloParent = owner;
|
|
e.Position = owner.Position + owner.Orientation.Multiply(e.MloRefPosition);
|
|
e.Orientation = Quaternion.Multiply(owner.Orientation, e.MloRefOrientation);
|
|
e.UpdateWidgetPosition();
|
|
e.UpdateWidgetOrientation();
|
|
e.UpdateEntityHash();
|
|
return e;
|
|
}
|
|
|
|
public MCEntityDef TryGetArchetypeEntity(YmapEntityDef ymapEntity)
|
|
{
|
|
if (ymapEntity == null) return null;
|
|
if (Owner?.Archetype == null) return null;
|
|
if (!(Owner.Archetype is MloArchetype mloa)) return null;
|
|
|
|
var index = Array.FindIndex(Entities, x => x == ymapEntity);
|
|
if ((index >= 0) && (index < mloa.entities.Length))
|
|
{
|
|
return mloa.entities[index];
|
|
}
|
|
|
|
if (EntitySets != null)
|
|
{
|
|
for (int e = 0; e < EntitySets.Length; e++)
|
|
{
|
|
var entset = EntitySets[e];
|
|
var ents = entset.Entities;
|
|
var set = entset.EntitySet;
|
|
var setents = set?.Entities;
|
|
if ((ents == null) || (setents == null)) continue;
|
|
var idx = ents.IndexOf(ymapEntity);
|
|
if ((idx >= 0) && (idx < setents.Length))
|
|
{
|
|
return setents[idx];
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public YmapEntityDef TryGetYmapEntity(MCEntityDef mcEntity)
|
|
{
|
|
if (mcEntity == null) return null;
|
|
if (Owner?.Archetype == null) return null;
|
|
if (!(Owner.Archetype is MloArchetype mloa)) return null;
|
|
|
|
var index = Array.FindIndex(mloa.entities, x => x == mcEntity);
|
|
if ((index >= 0) && (index < Entities.Length))
|
|
{
|
|
return Entities[index];
|
|
}
|
|
|
|
if (EntitySets != null)
|
|
{
|
|
for (int e = 0; e < EntitySets.Length; e++)
|
|
{
|
|
var entset = EntitySets[e];
|
|
var ents = entset.Entities;
|
|
var set = entset.EntitySet;
|
|
var setents = set?.Entities;
|
|
if ((ents == null) || (setents == null)) continue;
|
|
var idx = Array.FindIndex(setents, x => x == mcEntity);
|
|
if ((idx >= 0) && (idx < ents.Count))
|
|
{
|
|
return ents[idx];
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void SetPosition(Vector3 pos)
|
|
{
|
|
var cent = _Instance.CEntityDef;
|
|
cent.position = pos;
|
|
_Instance.CEntityDef = cent; //TODO: maybe find a better way of doing this...
|
|
}
|
|
|
|
public void SetOrientation(Quaternion ori)
|
|
{
|
|
var cent = _Instance.CEntityDef;
|
|
cent.rotation = new Vector4(ori.X, ori.Y, ori.Z, ori.W); //mlo instances have oppposite orientations to normal entities...
|
|
_Instance.CEntityDef = cent; //TODO: maybe find a better way of doing this...
|
|
}
|
|
|
|
public void UpdateEntities()
|
|
{
|
|
if (Entities == null) return;
|
|
if (Owner == null) return;
|
|
|
|
for (int i = 0; i < Entities.Length; i++)
|
|
{
|
|
var ent = Entities[i];
|
|
UpdateEntity(ent);
|
|
}
|
|
|
|
if (EntitySets != null)
|
|
{
|
|
for (int e = 0; e < EntitySets.Length; e++)
|
|
{
|
|
var entset = EntitySets[e];
|
|
if (entset?.Entities != null)
|
|
{
|
|
for (int i = 0; i < entset.Entities.Count; i++)
|
|
{
|
|
var ent = entset.Entities[i];
|
|
UpdateEntity(ent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void UpdateEntity(YmapEntityDef e)
|
|
{
|
|
e.Position = Owner.Position + Owner.Orientation.Multiply(e.MloRefPosition);
|
|
e.Orientation = Quaternion.Multiply(Owner.Orientation, e.MloRefOrientation);
|
|
e.UpdateWidgetPosition();
|
|
e.UpdateWidgetOrientation();
|
|
e.UpdateEntityHash();
|
|
}
|
|
|
|
public void AddEntity(YmapEntityDef e)
|
|
{
|
|
if (e == null) return;
|
|
|
|
if (e.MloEntitySet != null)
|
|
{
|
|
e.MloEntitySet.AddEntity(e);
|
|
}
|
|
else
|
|
{
|
|
if (Entities == null) Entities = new YmapEntityDef[0];
|
|
var entities = Entities.ToList();
|
|
entities.Add(e);
|
|
Entities = entities.ToArray();
|
|
}
|
|
UpdateAllEntityIndexes();
|
|
}
|
|
|
|
public bool DeleteEntity(YmapEntityDef ent)
|
|
{
|
|
var del = false;
|
|
if (ent.MloEntitySet != null)
|
|
{
|
|
del = ent.MloEntitySet.DeleteEntity(ent);
|
|
UpdateAllEntityIndexes();
|
|
return del;
|
|
}
|
|
|
|
if (Entities == null)
|
|
{
|
|
throw new NullReferenceException("The Entities list returned null in our MloInstanceData. This could be an issue with initialization. The MloInstance probably doesn't exist.");
|
|
}
|
|
if (ent.Index >= Entities.Length)
|
|
{
|
|
throw new ArgumentOutOfRangeException("The index of the entity was greater than the amount of entities that exist in this MloInstance. Likely an issue with initializion.");
|
|
}
|
|
|
|
int index = 0;
|
|
var newentities = new YmapEntityDef[Entities.Length - 1];
|
|
|
|
for (int i = 0; i < Entities.Length; i++)
|
|
{
|
|
if (i == ent.Index)
|
|
{
|
|
del = true;
|
|
continue;
|
|
}
|
|
newentities[index] = Entities[i];
|
|
newentities[index].Index = index;
|
|
index++;
|
|
}
|
|
if (del)
|
|
{
|
|
Entities = newentities;
|
|
UpdateAllEntityIndexes();
|
|
return true;
|
|
}
|
|
else throw new ArgumentException("The entity specified was not found in this MloInstance. It cannot be deleted.");
|
|
}
|
|
|
|
public void AddEntitySet(MCMloEntitySet set)
|
|
{
|
|
var instset = new MloInstanceEntitySet(set, this);
|
|
var esets = EntitySets?.ToList() ?? new List<MloInstanceEntitySet>();
|
|
esets.Add(instset);
|
|
EntitySets = esets.ToArray();
|
|
}
|
|
|
|
public bool DeleteEntitySet(MCMloEntitySet set)
|
|
{
|
|
if (EntitySets == null) return false;
|
|
var esets = EntitySets.ToList();
|
|
var rem = esets.RemoveAll(s => s.EntitySet == set);
|
|
EntitySets = esets.ToArray();
|
|
UpdateAllEntityIndexes();
|
|
return rem == 1;
|
|
}
|
|
|
|
public void UpdateDefaultEntitySets()
|
|
{
|
|
var list = new List<uint>();
|
|
|
|
if (EntitySets != null)
|
|
{
|
|
for (uint i = 0; i < EntitySets.Length; i++)
|
|
{
|
|
var entset = EntitySets[i];
|
|
if (entset != null)
|
|
{
|
|
if (entset.Visible)
|
|
{
|
|
list.Add(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
defaultEntitySets = list.ToArray();
|
|
}
|
|
|
|
private void UpdateAllEntityIndexes()
|
|
{
|
|
var index = 0;
|
|
if (Entities != null)
|
|
{
|
|
for (int i = 0; i < Entities.Length; i++)
|
|
{
|
|
Entities[i].Index = index++;
|
|
}
|
|
}
|
|
if (EntitySets != null)
|
|
{
|
|
for (int e = 0; e < EntitySets.Length; e++)
|
|
{
|
|
var set = EntitySets[e];
|
|
if (set?.Entities == null) continue;
|
|
for (int i = 0; i < set.Entities.Count; i++)
|
|
{
|
|
set.Entities[i].Index = index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
|
public class MloInstanceEntitySet
|
|
{
|
|
public MloInstanceEntitySet(MCMloEntitySet entSet, MloInstanceData instance)
|
|
{
|
|
EntitySet = entSet;
|
|
Entities = new List<YmapEntityDef>();
|
|
Instance = instance;
|
|
}
|
|
|
|
public MCMloEntitySet EntitySet { get; set; }
|
|
public List<YmapEntityDef> Entities { get; set; }
|
|
public MloInstanceData Instance { get; set; }
|
|
|
|
public uint[] Locations
|
|
{
|
|
get { return EntitySet?.Locations; }
|
|
set { if (EntitySet != null) EntitySet.Locations = value; }
|
|
}
|
|
|
|
public bool Visible { get; set; }
|
|
public bool VisibleOrForced
|
|
{
|
|
get
|
|
{
|
|
if (Visible) return true;
|
|
if (EntitySet == null) return false;
|
|
return EntitySet.ForceVisible;
|
|
}
|
|
}
|
|
|
|
public void AddEntity(YmapEntityDef ent)
|
|
{
|
|
if (Entities == null) Entities = new List<YmapEntityDef>();
|
|
Entities.Add(ent);
|
|
}
|
|
public bool DeleteEntity(YmapEntityDef ent)
|
|
{
|
|
if (Entities == null) return false;
|
|
return Entities.Remove(ent);
|
|
}
|
|
}
|
|
|
|
|
|
}
|