2019-10-26 09:20:32 +08:00
using SharpDX ;
2017-09-21 18:33:05 +08:00
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
{
2017-09-28 12:28:09 +08:00
public virtual MetaName Type = > MetaName . CBaseArchetypeDef ;
public CBaseArchetypeDef _BaseArchetypeDef ;
2018-12-03 16:54:04 +08:00
public CBaseArchetypeDef BaseArchetypeDef = > _BaseArchetypeDef ; // for browsing.
2017-09-28 12:28:09 +08:00
2017-09-21 18:33:05 +08:00
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 ; }
2017-09-28 12:28:09 +08:00
2017-09-21 18:33:05 +08:00
2018-12-03 16:54:04 +08:00
public string Name
2017-09-21 18:33:05 +08:00
{
2018-12-03 16:54:04 +08:00
get
2017-09-21 18:33:05 +08:00
{
2017-09-28 12:28:09 +08:00
return _BaseArchetypeDef . name . ToString ( ) ;
2017-09-21 18:33:05 +08:00
}
}
2018-12-03 16:54:04 +08:00
public string AssetName
2017-09-21 18:33:05 +08:00
{
2018-12-03 16:54:04 +08:00
get
2017-09-21 18:33:05 +08:00
{
2017-09-28 12:28:09 +08:00
return _BaseArchetypeDef . assetName . ToString ( ) ;
2017-09-21 18:33:05 +08:00
}
}
2017-09-28 12:28:09 +08:00
protected void InitVars ( ref CBaseArchetypeDef arch )
2017-09-21 18:33:05 +08:00
{
2018-12-03 16:54:04 +08:00
_BaseArchetypeDef = arch ;
2017-09-21 18:33:05 +08:00
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 ;
2017-09-28 00:24:21 +08:00
LodDist = arch . lodDist ;
}
public void Init ( YtypFile ytyp , ref CBaseArchetypeDef arch )
{
Ytyp = ytyp ;
InitVars ( ref arch ) ;
2017-09-21 18:33:05 +08:00
}
2017-09-28 12:28:09 +08:00
public virtual bool IsActive ( float hour )
2017-09-21 18:33:05 +08:00
{
2017-09-28 12:28:09 +08:00
return true ;
2017-09-21 18:33:05 +08:00
}
2017-09-28 12:28:09 +08:00
public override string ToString ( )
{
return _BaseArchetypeDef . ToString ( ) ;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class TimeArchetype : Archetype
{
public override MetaName Type = > MetaName . CTimeArchetypeDef ;
2018-12-03 16:54:04 +08:00
public CTimeArchetypeDef _TimeArchetypeDef ;
public CTimeArchetypeDef TimeArchetypeDef = > _TimeArchetypeDef ; // for browsing.
2017-09-28 12:28:09 +08:00
public uint TimeFlags { get ; set ; }
public bool [ ] ActiveHours { get ; set ; }
public string [ ] ActiveHoursText { get ; set ; }
2018-12-16 19:32:33 +08:00
public bool ExtraFlag { get { return ( ( TimeFlags > > 24 ) & 1 ) = = 1 ; } }
2017-09-28 12:28:09 +08:00
public void Init ( YtypFile ytyp , ref CTimeArchetypeDef arch )
2017-09-21 18:33:05 +08:00
{
Ytyp = ytyp ;
2017-09-28 00:24:21 +08:00
InitVars ( ref arch . _BaseArchetypeDef ) ;
2018-12-03 16:54:04 +08:00
_TimeArchetypeDef = arch ;
2017-09-28 12:28:09 +08:00
2018-12-03 16:54:04 +08:00
TimeFlags = arch . TimeArchetypeDef . timeFlags ;
2018-12-16 19:32:33 +08:00
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 ] ;
}
2017-09-28 12:28:09 +08:00
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" ) ) ;
}
2017-09-21 18:33:05 +08:00
}
2018-12-16 19:32:33 +08:00
public void SetTimeFlags ( uint flags )
2017-09-21 18:33:05 +08:00
{
2018-12-16 19:32:33 +08:00
TimeFlags = flags ;
_TimeArchetypeDef . _TimeArchetypeDef . timeFlags = flags ;
UpdateActiveHours ( ) ;
2017-09-21 18:33:05 +08:00
}
2018-12-16 19:32:33 +08:00
2017-09-21 18:33:05 +08:00
}
2017-09-28 12:28:09 +08:00
public class MloArchetype : Archetype
2017-09-21 18:33:05 +08:00
{
2017-09-28 12:28:09 +08:00
public override MetaName Type = > MetaName . CMloArchetypeDef ;
2018-07-27 04:16:54 +08:00
2018-12-03 16:54:04 +08:00
public CMloArchetypeDef MloArchetypeDef = > _MloArchetypeDef ; // for browsing.
public CMloArchetypeDef _MloArchetypeDef ;
public CMloArchetypeDefData _MloArchetypeDefData ;
2017-09-28 12:28:09 +08:00
2018-01-02 12:37:09 +08:00
public MCEntityDef [ ] entities { get ; set ; }
public MCMloRoomDef [ ] rooms { get ; set ; }
public MCMloPortalDef [ ] portals { get ; set ; }
public MCMloEntitySet [ ] entitySets { get ; set ; }
2017-09-21 18:33:05 +08:00
public CMloTimeCycleModifier [ ] timeCycleModifiers { get ; set ; }
2017-09-28 12:28:09 +08:00
2018-12-03 16:54:04 +08:00
2017-09-28 12:28:09 +08:00
public void Init ( YtypFile ytyp , ref CMloArchetypeDef arch )
{
Ytyp = ytyp ;
InitVars ( ref arch . _BaseArchetypeDef ) ;
2018-12-03 16:54:04 +08:00
_MloArchetypeDef = arch ;
_MloArchetypeDefData = arch . MloArchetypeDef ;
}
2019-12-28 20:24:36 +08:00
public bool AddEntity ( YmapEntityDef ent , int roomIndex , int portalIndex = - 1 , int entsetIndex = - 1 )
2018-12-03 16:54:04 +08:00
{
if ( ent = = null ) return false ;
2019-12-28 20:24:36 +08:00
if ( roomIndex > = ( rooms ? . Length ? ? 0 ) )
2018-12-03 16:54:04 +08:00
{
throw new ArgumentOutOfRangeException ( $"Room index {roomIndex} exceeds the amount of rooms in {Name}." ) ;
}
2019-12-28 20:24:36 +08:00
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}." ) ;
}
2018-12-03 16:54:04 +08:00
var mcEntityDef = new MCEntityDef ( ref ent . _CEntityDef , this ) ;
2019-12-28 20:24:36 +08:00
if ( ( roomIndex > = 0 ) | | ( portalIndex > = 0 ) )
{
2019-12-29 21:56:29 +08:00
var entList = entities ? . ToList ( ) ? ? new List < MCEntityDef > ( ) ;
ent . Index = entList . Count ;
2019-12-28 20:24:36 +08:00
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 )
2018-12-03 16:54:04 +08:00
{
2019-12-28 20:24:36 +08:00
var entset = entitySets [ entsetIndex ] ;
2019-12-29 21:56:29 +08:00
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 ] ;
}
2018-12-03 16:54:04 +08:00
}
2019-12-28 20:24:36 +08:00
else return false ;
2018-12-03 16:54:04 +08:00
2019-12-29 21:56:29 +08:00
UpdateAllEntityIndexes ( ) ;
2018-12-03 16:54:04 +08:00
2019-12-28 20:24:36 +08:00
return true ;
2018-12-03 16:54:04 +08:00
}
2019-12-29 21:56:29 +08:00
public bool RemoveEntity ( YmapEntityDef ent )
{
if ( ent = = null ) return false ;
2018-12-03 16:54:04 +08:00
2019-12-29 21:56:29 +08:00
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 ( ) ;
2019-12-28 20:24:36 +08:00
2019-12-29 21:56:29 +08:00
var locs = set . Locations . ToList ( ) ;
locs . RemoveAt ( idx ) ;
set . Locations = locs . ToArray ( ) ;
2019-12-28 20:24:36 +08:00
2019-12-29 21:56:29 +08:00
UpdateAllEntityIndexes ( ) ;
return true ;
}
return false ;
}
2018-12-03 16:54:04 +08:00
2019-12-29 21:56:29 +08:00
if ( ent . Index > = entities . Length ) return false ;
2018-12-03 16:54:04 +08:00
2019-12-29 21:56:29 +08:00
var delent = entities [ ent . Index ] ;
2018-12-03 16:54:04 +08:00
if ( delent ! = null )
{
2019-12-29 21:56:29 +08:00
var newentities = new MCEntityDef [ entities . Length - 1 ] ;
var didDel = false ;
2018-12-03 16:54:04 +08:00
int index = 0 ;
int delIndex = 0 ;
for ( int i = 0 ; i < entities . Length ; i + + )
{
if ( entities [ i ] = = delent )
{
delIndex = i ;
didDel = true ;
continue ;
}
2019-12-29 21:56:29 +08:00
var newent = entities [ i ] ;
newentities [ index ] = newent ;
2018-12-03 16:54:04 +08:00
index + + ;
}
2019-10-26 09:20:32 +08:00
2018-12-03 16:54:04 +08:00
entities = newentities ;
2019-10-26 09:20:32 +08:00
if ( didDel )
{
FixRoomIndexes ( delIndex ) ;
FixPortalIndexes ( delIndex ) ;
2019-12-29 21:56:29 +08:00
UpdateAllEntityIndexes ( ) ;
2019-10-26 09:20:32 +08:00
}
2018-12-03 16:54:04 +08:00
return didDel ;
}
return false ;
}
2019-12-28 13:01:09 +08:00
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 ( ) ;
2019-12-29 21:56:29 +08:00
for ( int i = 0 ; i < rooms . Length ; i + + )
{
rooms [ i ] . Index = i ;
}
2019-12-28 13:01:09 +08:00
}
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 ( ) ;
}
public void RemovePortal ( MCMloPortalDef portal )
{
if ( portal = = null ) return ;
var newportals = portals . ToList ( ) ;
newportals . Remove ( portal ) ;
portals = newportals . ToArray ( ) ;
2019-12-29 21:56:29 +08:00
for ( int i = 0 ; i < portals . Length ; i + + )
{
portals [ i ] . Index = i ;
}
2019-12-28 13:01:09 +08:00
}
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 ( ) ;
2019-12-29 21:56:29 +08:00
for ( int i = 0 ; i < entitySets . Length ; i + + )
{
entitySets [ i ] . Index = i ;
}
UpdateAllEntityIndexes ( ) ;
2019-12-28 13:01:09 +08:00
}
2019-10-26 09:20:32 +08:00
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 ( ) ;
}
}
2018-12-03 16:54:04 +08:00
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 ( ) ;
}
2017-09-28 12:28:09 +08:00
}
2018-01-02 12:37:09 +08:00
2019-12-29 21:56:29 +08:00
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 + + ;
}
}
}
}
2018-01-02 12:37:09 +08:00
public void LoadChildren ( Meta meta )
{
2018-12-03 16:54:04 +08:00
var centities = MetaTypes . ConvertDataArray < CEntityDef > ( meta , MetaName . CEntityDef , _MloArchetypeDefData . entities ) ;
2018-01-02 12:37:09 +08:00
if ( centities ! = null )
{
entities = new MCEntityDef [ centities . Length ] ;
for ( int i = 0 ; i < centities . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
entities [ i ] = new MCEntityDef ( meta , ref centities [ i ] ) { OwnerMlo = this , Index = i } ;
2018-01-02 12:37:09 +08:00
}
}
2018-12-03 16:54:04 +08:00
var crooms = MetaTypes . ConvertDataArray < CMloRoomDef > ( meta , MetaName . CMloRoomDef , _MloArchetypeDefData . rooms ) ;
2018-01-02 12:37:09 +08:00
if ( crooms ! = null )
{
rooms = new MCMloRoomDef [ crooms . Length ] ;
for ( int i = 0 ; i < crooms . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
rooms [ i ] = new MCMloRoomDef ( meta , crooms [ i ] ) { OwnerMlo = this , Index = i } ;
2018-01-02 12:37:09 +08:00
}
}
2018-12-03 16:54:04 +08:00
var cportals = MetaTypes . ConvertDataArray < CMloPortalDef > ( meta , MetaName . CMloPortalDef , _MloArchetypeDefData . portals ) ;
2018-01-02 12:37:09 +08:00
if ( cportals ! = null )
{
portals = new MCMloPortalDef [ cportals . Length ] ;
for ( int i = 0 ; i < cportals . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
portals [ i ] = new MCMloPortalDef ( meta , cportals [ i ] ) { OwnerMlo = this , Index = i } ;
2018-01-02 12:37:09 +08:00
}
}
2018-12-03 16:54:04 +08:00
var centitySets = MetaTypes . ConvertDataArray < CMloEntitySet > ( meta , MetaName . CMloEntitySet , _MloArchetypeDefData . entitySets ) ;
2018-01-02 12:37:09 +08:00
if ( centitySets ! = null )
{
entitySets = new MCMloEntitySet [ centitySets . Length ] ;
for ( int i = 0 ; i < centitySets . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
entitySets [ i ] = new MCMloEntitySet ( meta , centitySets [ i ] , this ) { OwnerMlo = this , Index = i } ;
2018-01-02 12:37:09 +08:00
}
2019-12-29 21:56:29 +08:00
UpdateAllEntityIndexes ( ) ;
2018-01-02 12:37:09 +08:00
}
2018-12-03 16:54:04 +08:00
timeCycleModifiers = MetaTypes . ConvertDataArray < CMloTimeCycleModifier > ( meta , MetaName . CMloTimeCycleModifier , _MloArchetypeDefData . timeCycleModifiers ) ;
2018-01-02 12:37:09 +08:00
}
2019-12-28 01:08:45 +08:00
public int GetEntityObjectIndex ( MCEntityDef ent )
2018-12-03 16:54:04 +08:00
{
2019-12-28 01:08:45 +08:00
if ( entities = = null ) return - 1 ;
2018-12-03 16:54:04 +08:00
for ( int i = 0 ; i < entities . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
var e = entities [ i ] ;
2018-12-03 16:54:04 +08:00
if ( e = = ent )
{
2019-12-28 01:08:45 +08:00
return i ;
2018-12-03 16:54:04 +08:00
}
}
2019-12-28 01:08:45 +08:00
return - 1 ;
}
public MCMloRoomDef GetEntityRoom ( MCEntityDef ent )
{
if ( rooms = = null ) return null ;
int objectIndex = GetEntityObjectIndex ( ent ) ;
if ( objectIndex < 0 ) return null ;
2017-09-21 18:33:05 +08:00
2018-12-03 16:54:04 +08:00
for ( int i = 0 ; i < rooms . Length ; i + + )
{
2019-12-28 01:08:45 +08:00
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 )
2018-12-03 16:54:04 +08:00
{
2019-12-28 01:08:45 +08:00
for ( int j = 0 ; j < set . Entities . Length ; j + + )
2018-12-03 16:54:04 +08:00
{
2019-12-28 01:08:45 +08:00
if ( set . Entities [ j ] = = ent )
{
return set ;
}
2018-12-03 16:54:04 +08:00
}
}
}
2017-09-28 12:28:09 +08:00
2019-12-28 01:08:45 +08:00
return null ;
2018-12-03 16:54:04 +08:00
}
2019-12-28 01:08:45 +08:00
2018-12-03 16:54:04 +08:00
}
2017-09-28 12:28:09 +08:00
2017-09-21 18:33:05 +08:00
[TypeConverter(typeof(ExpandableObjectConverter))]
2017-09-28 00:24:21 +08:00
public class MloInstanceData
2017-09-21 18:33:05 +08:00
{
2017-09-28 00:24:21 +08:00
public YmapEntityDef Owner { get ; set ; }
2019-12-28 20:24:36 +08:00
public MloArchetype MloArch { get ; set ; }
2017-09-28 00:24:21 +08:00
public CMloInstanceDef _Instance ;
public CMloInstanceDef Instance { get { return _Instance ; } set { _Instance = value ; } }
2018-01-02 06:44:45 +08:00
public uint [ ] defaultEntitySets { get ; set ; }
2017-09-28 00:24:21 +08:00
public YmapEntityDef [ ] Entities { get ; set ; }
2019-12-29 21:56:29 +08:00
public MloInstanceEntitySet [ ] EntitySets { get ; set ; }
2017-09-28 00:24:21 +08:00
2019-12-28 20:24:36 +08:00
public MloInstanceData ( YmapEntityDef owner , MloArchetype mloa )
2018-12-03 16:54:04 +08:00
{
2019-12-28 20:24:36 +08:00
Owner = owner ;
MloArch = mloa ;
2018-12-03 16:54:04 +08:00
}
2017-09-21 18:33:05 +08:00
2019-12-28 20:24:36 +08:00
public void CreateYmapEntities ( )
2017-09-21 18:33:05 +08:00
{
2019-12-28 20:24:36 +08:00
if ( Owner = = null ) return ;
if ( MloArch ? . entities = = null ) return ;
var ec = MloArch . entities . Length ;
2018-01-02 14:43:47 +08:00
var entlist = new List < YmapEntityDef > ( ) ;
2017-09-28 00:24:21 +08:00
for ( int i = 0 ; i < ec ; i + + )
2017-09-21 18:33:05 +08:00
{
2019-12-29 21:56:29 +08:00
var e = CreateYmapEntity ( Owner , MloArch . entities [ i ] , i ) ;
2018-01-02 14:43:47 +08:00
entlist . Add ( e ) ;
2017-09-28 00:24:21 +08:00
}
2018-01-02 12:37:09 +08:00
2018-01-02 14:43:47 +08:00
int lasti = ec ;
2019-12-28 20:24:36 +08:00
var entitySets = MloArch . entitySets ;
2018-01-02 12:37:09 +08:00
if ( entitySets ! = null )
{
2019-12-29 21:56:29 +08:00
EntitySets = new MloInstanceEntitySet [ entitySets . Length ] ;
2018-01-02 14:43:47 +08:00
for ( int i = 0 ; i < entitySets . Length ; i + + )
{
var entitySet = entitySets [ i ] ;
2019-12-29 21:56:29 +08:00
var instset = new MloInstanceEntitySet ( entitySet , this ) ;
2018-01-02 14:43:47 +08:00
if ( entitySet . Entities ! = null )
{
for ( int j = 0 ; j < entitySet . Entities . Length ; j + + )
{
2019-12-29 21:56:29 +08:00
var e = CreateYmapEntity ( Owner , entitySet . Entities [ j ] , lasti ) ;
instset . Entities . Add ( e ) ;
2018-12-03 16:54:04 +08:00
e . MloEntitySet = instset ;
2018-01-02 14:43:47 +08:00
lasti + + ;
}
}
2019-12-29 21:56:29 +08:00
EntitySets [ i ] = instset ;
2018-01-02 14:43:47 +08:00
}
}
2019-12-29 21:56:29 +08:00
if ( ( defaultEntitySets ! = null ) & & ( EntitySets ! = null ) )
2018-01-02 14:43:47 +08:00
{
2018-12-03 16:54:04 +08:00
for ( var i = 0 ; i < defaultEntitySets . Length ; i + + )
{
uint index = defaultEntitySets [ i ] ;
2019-12-29 21:56:29 +08:00
if ( index > = EntitySets . Length ) continue ;
var instset = EntitySets [ index ] ;
2018-12-03 16:54:04 +08:00
instset . Visible = true ;
}
2018-01-02 12:37:09 +08:00
}
2018-01-02 14:43:47 +08:00
Entities = entlist . ToArray ( ) ;
}
2018-12-03 16:54:04 +08:00
public void InitYmapEntityArchetypes ( GameFileCache gfc )
2018-01-02 14:43:47 +08:00
{
2018-12-03 16:54:04 +08:00
if ( Owner = = null ) return ;
var arch = Owner . Archetype ;
if ( Entities ! = null )
{
for ( int j = 0 ; j < Entities . Length ; j + + )
{
var ient = Entities [ j ] ;
2019-01-09 15:09:12 +08:00
var iarch = gfc . GetArchetype ( ient . _CEntityDef . archetypeName ) ;
2018-12-03 16:54:04 +08:00
ient . SetArchetype ( iarch ) ;
if ( iarch = = null )
{ } //can't find archetype - des stuff eg {des_prologue_door}
}
UpdateBBs ( arch ) ;
}
if ( EntitySets ! = null )
{
2019-12-29 21:56:29 +08:00
for ( int e = 0 ; e < EntitySets . Length ; e + + )
2018-12-03 16:54:04 +08:00
{
2019-12-29 21:56:29 +08:00
var entitySet = EntitySets [ e ] ;
var entities = entitySet . Entities ;
2018-12-03 16:54:04 +08:00
if ( entities = = null ) continue ;
for ( int i = 0 ; i < entities . Count ; i + + )
{
var ient = entities [ i ] ;
2019-01-09 15:09:12 +08:00
var iarch = gfc . GetArchetype ( ient . _CEntityDef . archetypeName ) ;
2018-12-03 16:54:04 +08:00
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 ) ;
2018-01-02 14:43:47 +08:00
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 ( ) ;
2019-11-27 17:24:02 +08:00
e . UpdateEntityHash ( ) ;
2018-01-02 14:43:47 +08:00
return e ;
2017-09-28 00:24:21 +08:00
}
2017-09-21 18:33:05 +08:00
2018-12-03 16:54:04 +08:00
public MCEntityDef TryGetArchetypeEntity ( YmapEntityDef ymapEntity )
{
if ( ymapEntity = = null ) return null ;
if ( Owner ? . Archetype = = null ) return null ;
if ( ! ( Owner . Archetype is MloArchetype mloa ) ) return null ;
2019-12-29 21:56:29 +08:00
var index = Array . FindIndex ( Entities , x = > x = = ymapEntity ) ;
if ( ( index > = 0 ) & & ( index < mloa . entities . Length ) )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
return mloa . entities [ index ] ;
2019-12-28 01:08:45 +08:00
}
2019-12-29 21:56:29 +08:00
if ( EntitySets ! = null )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
for ( int e = 0 ; e < EntitySets . Length ; e + + )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
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 ) )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
return setents [ idx ] ;
2019-12-28 01:08:45 +08:00
}
}
}
2019-12-29 21:56:29 +08:00
return null ;
2018-12-03 16:54:04 +08:00
}
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 ) ;
2019-12-28 01:08:45 +08:00
if ( ( index > = 0 ) & & ( index < Entities . Length ) )
{
return Entities [ index ] ;
}
2019-12-29 21:56:29 +08:00
if ( EntitySets ! = null )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
for ( int e = 0 ; e < EntitySets . Length ; e + + )
2019-12-28 01:08:45 +08:00
{
2019-12-29 21:56:29 +08:00
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 ] ;
}
2019-12-28 01:08:45 +08:00
}
}
return null ;
2018-12-03 16:54:04 +08:00
}
2017-09-21 18:33:05 +08:00
2018-01-02 06:44:45 +08:00
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...
}
2017-09-28 00:24:21 +08:00
public void UpdateEntities ( )
{
if ( Entities = = null ) return ;
if ( Owner = = null ) return ;
for ( int i = 0 ; i < Entities . Length ; i + + )
{
2019-12-29 21:56:29 +08:00
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 ) ;
}
}
}
2017-09-21 18:33:05 +08:00
}
2017-09-28 00:24:21 +08:00
2017-09-21 18:33:05 +08:00
}
2017-09-28 00:24:21 +08:00
2018-12-03 16:54:04 +08:00
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 ( ) ;
}
public void AddEntity ( YmapEntityDef e )
{
if ( e = = null ) return ;
2019-12-28 20:24:36 +08:00
if ( e . MloEntitySet ! = null )
{
e . MloEntitySet . AddEntity ( e ) ;
}
2019-12-29 21:56:29 +08:00
else
{
if ( Entities = = null ) Entities = new YmapEntityDef [ 0 ] ;
var entities = Entities . ToList ( ) ;
entities . Add ( e ) ;
Entities = entities . ToArray ( ) ;
}
UpdateAllEntityIndexes ( ) ;
2018-12-03 16:54:04 +08:00
}
2019-12-28 20:24:36 +08:00
public bool DeleteEntity ( YmapEntityDef ent )
{
2019-12-29 21:56:29 +08:00
var del = false ;
2019-12-28 20:24:36 +08:00
if ( ent . MloEntitySet ! = null )
{
2019-12-29 21:56:29 +08:00
del = ent . MloEntitySet . DeleteEntity ( ent ) ;
UpdateAllEntityIndexes ( ) ;
return del ;
2019-12-28 20:24:36 +08:00
}
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 ;
2019-12-29 21:56:29 +08:00
var newentities = new YmapEntityDef [ Entities . Length - 1 ] ;
2019-12-28 20:24:36 +08:00
for ( int i = 0 ; i < Entities . Length ; i + + )
{
2019-12-29 21:56:29 +08:00
if ( i = = ent . Index )
2019-12-28 20:24:36 +08:00
{
del = true ;
continue ;
}
newentities [ index ] = Entities [ i ] ;
newentities [ index ] . Index = index ;
index + + ;
}
if ( del )
{
2019-12-29 21:56:29 +08:00
Entities = newentities ;
UpdateAllEntityIndexes ( ) ;
return true ;
2019-12-28 20:24:36 +08:00
}
else throw new ArgumentException ( "The entity specified was not found in this MloInstance. It cannot be deleted." ) ;
}
2019-12-29 21:56:29 +08:00
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 ;
}
2018-12-16 19:32:33 +08:00
public void UpdateDefaultEntitySets ( )
{
var list = new List < uint > ( ) ;
2019-12-29 21:56:29 +08:00
if ( EntitySets ! = null )
2018-12-16 19:32:33 +08:00
{
2019-12-29 21:56:29 +08:00
for ( uint i = 0 ; i < EntitySets . Length ; i + + )
2018-12-16 19:32:33 +08:00
{
2019-12-29 21:56:29 +08:00
var entset = EntitySets [ i ] ;
if ( entset ! = null )
2018-12-16 19:32:33 +08:00
{
2019-12-29 21:56:29 +08:00
if ( entset . Visible )
2019-01-13 14:04:32 +08:00
{
list . Add ( i ) ;
}
2018-12-16 19:32:33 +08:00
}
}
}
defaultEntitySets = list . ToArray ( ) ;
}
2019-12-29 21:56:29 +08:00
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 + + ;
}
}
}
}
2018-12-03 16:54:04 +08:00
}
2017-09-28 00:24:21 +08:00
2018-12-03 16:54:04 +08:00
[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 ; }
}
2018-01-02 06:44:45 +08:00
2018-12-03 16:54:04 +08:00
public bool Visible { get ; set ; }
2019-12-28 01:08:45 +08:00
public bool VisibleOrForced
{
get
{
if ( Visible ) return true ;
if ( EntitySet = = null ) return false ;
return EntitySet . ForceVisible ;
}
}
2019-12-28 20:24:36 +08:00
public void AddEntity ( YmapEntityDef ent )
{
if ( Entities = = null ) Entities = new List < YmapEntityDef > ( ) ;
Entities . Add ( ent ) ;
}
2019-12-28 01:08:45 +08:00
public bool DeleteEntity ( YmapEntityDef ent )
{
2019-12-29 21:56:29 +08:00
if ( Entities = = null ) return false ;
return Entities . Remove ( ent ) ;
2019-12-28 01:08:45 +08:00
}
2017-09-21 18:33:05 +08:00
}
2017-09-28 00:24:21 +08:00
2017-09-21 18:33:05 +08:00
}