public void AddObject(ThnObject obj) { sceneObjects[obj.Name] = obj; if (obj.Object != null) { World?.AddObject(obj.Object); } }
private bool firstFrame = false; //Stops a desync in scene starting void RoomDoSceneScript(ThnScript sc, ScriptState state) { hotspots = new List <RTCHotspot>(); firstFrame = true; currentState = state; if (sc == null) { currentState = ScriptState.None; } waitingForFinish = sc; scene.BeginScene(Scripts(sceneScripts, new[] { sc })); string[] ships = Array.Empty <string>(); if (session.Ships != null) { ships = session.Ships.Select(x => Game.GameData.GetShip(x.ShipCRC).Nickname).ToArray(); } for (int i = 0; (i < ships.Length && i < currentRoom.ForSaleShipPlacements.Count); i++) { ThnObject marker = scene.GetObject(currentRoom.ForSaleShipPlacements[i]); if (marker == null) { FLLog.Error("Base", "Couldn't display " + ships[i] + " on " + currentRoom.ForSaleShipPlacements[i]); continue; } var toSellShip = Game.GameData.GetShip(ships[i]); //Set up object var obj = new GameObject(toSellShip.ModelFile.LoadFile(Game.ResourceManager), Game.ResourceManager) { Parent = marker.Object }; obj.PhysicsComponent = null; marker.Object.Children.Add(obj); if (obj.HardpointExists("HpMount")) { Matrix4x4.Invert(obj.GetHardpoint("HpMount").Transform, out var tr); obj.SetLocalTransform(tr); } } if (sc == null) { SetRoomCameraAndShip(); letterboxAmount = -1; ui.Visible = true; } else { ui.Visible = false; letterboxAmount = 1; } if (cState == CutsceneState.Decision) { letterboxAmount = -1; } }
public ThnSound(string soundname, SoundManager man, ThnAudioProps props, ThnObject obj) { Object = obj; this.man = man; SoundName = soundname; man.LoadSound(soundname); Props = props; if (Props != null) { Attenuation = props.Attenuation; } }
public Cutscene(ThnScriptContext context, GameDataManager gameData, Viewport viewport, Game game) { this.game = game; this.gameData = gameData; scriptContext = context; camera = new ThnCamera(viewport); Renderer = new SystemRenderer(camera, gameData, game.GetService <GameResourceManager>(), game); World = new GameWorld(Renderer, false); //thn = script; var evs = new List <ThnEvent>(); foreach (var thn in context.Scripts) { totalDuration = Math.Max(totalDuration, thn.Duration); foreach (var ev in thn.Events) { ev.TimeOffset = 0; evs.Add(ev); } AddEntities(thn); } //work around SET_CAMERA not being called in disco (match vanilla behaviour) var firstCamera = Objects.Values.Where(x => x.Camera != null).FirstOrDefault(); if (firstCamera != null) { camera.Transform = firstCamera.Camera; } evs.Sort((x, y) => x.Time.CompareTo(y.Time)); foreach (var item in evs) { events.Enqueue(item); } //Add starspheres in the right order var sorted = ((IEnumerable <Tuple <IDrawable, ThnObject> >)layers).Reverse().OrderBy(x => x.Item2.Entity.SortGroup).ToArray(); Renderer.StarSphereModels = new RigidModel[sorted.Length]; Renderer.StarSphereWorlds = new Matrix4x4[sorted.Length]; Renderer.StarSphereLightings = new Lighting[sorted.Length]; starSphereObjects = new ThnObject[sorted.Length]; for (int i = 0; i < sorted.Length; i++) { Renderer.StarSphereModels[i] = (sorted[i].Item1 as IRigidModelFile).CreateRigidModel(true); Renderer.StarSphereWorlds[i] = sorted[i].Item2.Rotate * Matrix4x4.CreateTranslation(sorted[i].Item2.Translate); Renderer.StarSphereLightings[i] = Lighting.Empty; starSphereObjects[i] = sorted[i].Item2; } //Add objects to the renderer World.RegisterAll(); }
void ProcessNextCutscene() { var ct = toPlay.Dequeue(); int position = 0; int i = 0; foreach (var npc in ct.Chars) { var obj = new GameObject() { Nickname = npc.Actor }; var costumeName = Game.GameData.GetCostumeForNPC(npc.Npc); Game.GameData.GetCostume(costumeName, out var body, out var head, out var lh, out var rh); var skel = new DfmSkeletonManager(body, head, lh, rh); obj.RenderComponent = new CharacterRenderer(skel); var anmComponent = new AnimationComponent(obj, Game.GameData.GetCharacterAnimations()); obj.AnimationComponent = anmComponent; obj.Components.Add(anmComponent); string spot = npc.Spot; if (string.IsNullOrEmpty(spot)) { spot = ct.Reserves[0].Spot[position++]; } var pos = scene.GetObject(spot).Translate; obj.SetLocalTransform(Matrix4x4.CreateTranslation(pos)); var thnObj = new ThnObject(); thnObj.Name = npc.Actor; thnObj.Rotate = Matrix4x4.Identity; thnObj.Translate = pos; thnObj.Object = obj; scene.AddObject(thnObj); scene.FidgetScript(new ThnScript(session.Game.GameData.ResolveDataPath(npc.Fidget))); if (i == 0) { hotspots.Add(new RTCHotspot() { ini = ct, obj = thnObj, npc = npc.Npc }); } i++; } }
void SetRoomCameraAndShip() { if (currentRoom.Camera != null) { scene.SetCamera(currentRoom.Camera); } ThnObject shipMarker = scene.GetObject(currentRoom.PlayerShipPlacement); if (shipMarker != null) { if (playerShip.HardpointExists("HpMount")) { Matrix4x4.Invert(playerShip.GetHardpoint("HpMount").Transform, out var tr); playerShip.SetLocalTransform(tr); } else { playerShip.SetLocalTransform(Matrix4x4.Identity); } shipMarker.Object.Children.Add(playerShip); } }
public Cutscene(IEnumerable <ThnScript> scripts, FreelancerGame game) { camera = new ThnCamera(game.Viewport); Renderer = new SystemRenderer(camera, game.GameData, game.ResourceManager); World = new GameWorld(Renderer); //thn = script; var evs = new List <ThnEvent>(); bool hasScene = false; List <Tuple <IDrawable, Matrix4, int> > layers = new List <Tuple <IDrawable, Matrix4, int> >(); foreach (var thn in scripts) { foreach (var ev in thn.Events) { evs.Add(ev); } foreach (var kv in thn.Entities) { if ((kv.Value.ObjectFlags & ThnObjectFlags.Reference) == ThnObjectFlags.Reference) { continue; } var obj = new ThnObject(); obj.Name = kv.Key; obj.Translate = kv.Value.Position ?? Vector3.Zero; obj.Rotate = kv.Value.RotationMatrix ?? Matrix4.Identity; if (kv.Value.Type == EntityTypes.Compound) { //Fetch model IDrawable drawable; switch (kv.Value.MeshCategory.ToLowerInvariant()) { case "solar": drawable = game.GameData.GetSolar(kv.Value.Template); break; case "spaceship": var sh = game.GameData.GetShip(kv.Value.Template); drawable = sh.Drawable; break; case "prop": drawable = game.GameData.GetProp(kv.Value.Template); break; case "room": drawable = game.GameData.GetRoom(kv.Value.Template); break; case "equipment cart": drawable = game.GameData.GetCart(kv.Value.Template); break; case "equipment": var eq = game.GameData.GetEquipment(kv.Value.Template); drawable = eq.GetDrawable(); break; case "asteroid": drawable = game.GameData.GetAsteroid(kv.Value.Template); break; default: throw new NotImplementedException("Mesh Category " + kv.Value.MeshCategory); } if (kv.Value.UserFlag != 0) { //This is a starsphere var transform = (kv.Value.RotationMatrix ?? Matrix4.Identity) * Matrix4.CreateTranslation(kv.Value.Position ?? Vector3.Zero); layers.Add(new Tuple <IDrawable, Matrix4, int>(drawable, transform, kv.Value.SortGroup)); } else { obj.Object = new GameObject(drawable, game.ResourceManager, false); obj.Object.PhysicsComponent = null; //Jitter seems to interfere with directly setting orientation var r = (ModelRenderer)obj.Object.RenderComponent; r.LightGroup = kv.Value.LightGroup; r.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic; r.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient; //HIDDEN just seems to be an editor flag? //r.Hidden = (kv.Value.ObjectFlags & ThnObjectFlags.Hidden) == ThnObjectFlags.Hidden; r.NoFog = kv.Value.NoFog; } } else if (kv.Value.Type == EntityTypes.PSys) { var fx = game.GameData.GetEffect(kv.Value.Template); obj.Object = new GameObject(); obj.Object.RenderComponent = new ParticleEffectRenderer(fx) { Active = false }; } else if (kv.Value.Type == EntityTypes.Scene) { if (hasScene) { //throw new Exception("Thn can only have one scene"); //TODO: This needs to be handled better continue; } var amb = kv.Value.Ambient.Value; if (amb.X == 0 && amb.Y == 0 && amb.Z == 0) { continue; } hasScene = true; Renderer.SystemLighting.Ambient = new Color4(amb.X / 255f, amb.Y / 255f, amb.Z / 255f, 1); } else if (kv.Value.Type == EntityTypes.Light) { var lt = new DynamicLight(); lt.LightGroup = kv.Value.LightGroup; lt.Active = kv.Value.LightProps.On; lt.Light = kv.Value.LightProps.Render; obj.Light = lt; if (kv.Value.RotationMatrix.HasValue) { var m = kv.Value.RotationMatrix.Value; lt.Light.Direction = (new Vector4(lt.Light.Direction.Normalized(), 0) * m).Xyz.Normalized(); } Renderer.SystemLighting.Lights.Add(lt); } else if (kv.Value.Type == EntityTypes.Camera) { obj.Camera = new ThnCameraTransform(); obj.Camera.Position = kv.Value.Position.Value; obj.Camera.Orientation = kv.Value.RotationMatrix ?? Matrix4.Identity; obj.Camera.FovH = kv.Value.FovH ?? obj.Camera.FovH; obj.Camera.AspectRatio = kv.Value.HVAspect ?? obj.Camera.AspectRatio; } else if (kv.Value.Type == EntityTypes.Marker) { obj.Object = new GameObject(); obj.Object.Name = "Marker"; obj.Object.Nickname = ""; } if (obj.Object != null) { Vector3 transform = kv.Value.Position ?? Vector3.Zero; obj.Object.Transform = (kv.Value.RotationMatrix ?? Matrix4.Identity) * Matrix4.CreateTranslation(transform); World.Objects.Add(obj.Object); } obj.Entity = kv.Value; Objects.Add(kv.Key, obj); } } evs.Sort((x, y) => x.Time.CompareTo(y.Time)); foreach (var item in evs) { events.Enqueue(item); } //Add starspheres in the right order layers.Sort((x, y) => x.Item3.CompareTo(y.Item3)); Renderer.StarSphereModels = new IDrawable[layers.Count]; Renderer.StarSphereWorlds = new Matrix4[layers.Count]; for (int i = 0; i < layers.Count; i++) { Renderer.StarSphereModels[i] = layers[i].Item1; Renderer.StarSphereWorlds[i] = layers[i].Item2; } //Add objects to the renderer World.RegisterAll(); }
void AddEntities(ThnScript thn) { foreach (var kv in thn.Entities) { if (Objects.ContainsKey(kv.Key)) { continue; } if ((kv.Value.ObjectFlags & ThnObjectFlags.Reference) == ThnObjectFlags.Reference) { continue; } var obj = new ThnObject(); obj.Name = kv.Key; obj.Translate = kv.Value.Position ?? Vector3.Zero; obj.Rotate = kv.Value.RotationMatrix ?? Matrix4.Identity; //PlayerShip object if (spawnObjects && scriptContext.PlayerShip != null && kv.Value.Type == EntityTypes.Compound && kv.Value.Template.Equals("playership", StringComparison.InvariantCultureIgnoreCase)) { obj.Object = scriptContext.PlayerShip; obj.Object.RenderComponent.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic; obj.Object.RenderComponent.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient; obj.Object.RenderComponent.NoFog = kv.Value.NoFog; ((ModelRenderer)obj.Object.RenderComponent).LightGroup = kv.Value.LightGroup; obj.Entity = kv.Value; Vector3 transform = kv.Value.Position ?? Vector3.Zero; obj.Object.Transform = (kv.Value.RotationMatrix ?? Matrix4.Identity) * Matrix4.CreateTranslation(transform); obj.HpMount = scriptContext.PlayerShip.GetHardpoint("HpMount"); World.Objects.Add(obj.Object); Objects.Add(kv.Key, obj); continue; } var template = kv.Value.Template; string replacement; if (scriptContext != null && scriptContext.Substitutions.TryGetValue(kv.Value.Template, out replacement)) { template = replacement; } if (spawnObjects && kv.Value.Type == EntityTypes.Compound) { bool getHpMount = false; //Fetch model IDrawable drawable; switch (kv.Value.MeshCategory.ToLowerInvariant()) { case "solar": drawable = gameData.GetSolar(template); break; case "ship": case "spaceship": getHpMount = true; var sh = gameData.GetShip(template); sh.LoadResources(); drawable = sh.Drawable; break; case "prop": drawable = gameData.GetProp(template); break; case "room": drawable = gameData.GetRoom(template); break; case "equipment cart": drawable = gameData.GetCart(template); break; case "equipment": var eq = gameData.GetEquipment(template); eq.LoadResources(); drawable = eq.GetDrawable(); break; case "asteroid": drawable = gameData.GetAsteroid(kv.Value.Template); break; default: throw new NotImplementedException("Mesh Category " + kv.Value.MeshCategory); } if (kv.Value.UserFlag != 0) { //This is a starsphere var transform = (kv.Value.RotationMatrix ?? Matrix4.Identity) * Matrix4.CreateTranslation(kv.Value.Position ?? Vector3.Zero); layers.Add(new Tuple <IDrawable, Matrix4, int>(drawable, transform, kv.Value.SortGroup)); } else { obj.Object = new GameObject(drawable, game.GetService <ResourceManager>(), true, false); obj.Object.Name = kv.Value.Name; obj.Object.PhysicsComponent = null; //Jitter seems to interfere with directly setting orientation if (getHpMount) { obj.HpMount = obj.Object.GetHardpoint("HpMount"); } var r = (ModelRenderer)obj.Object.RenderComponent; r.LightGroup = kv.Value.LightGroup; r.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic; r.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient; //HIDDEN just seems to be an editor flag? //r.Hidden = (kv.Value.ObjectFlags & ThnObjectFlags.Hidden) == ThnObjectFlags.Hidden; r.NoFog = kv.Value.NoFog; } } else if (kv.Value.Type == EntityTypes.PSys) { var fx = gameData.GetEffect(kv.Value.Template); obj.Object = new GameObject(); obj.Object.RenderComponent = new ParticleEffectRenderer(fx) { Active = false }; } else if (kv.Value.Type == EntityTypes.Scene) { if (hasScene) { //throw new Exception("Thn can only have one scene"); //TODO: This needs to be handled better continue; } var amb = kv.Value.Ambient.Value; if (amb.X == 0 && amb.Y == 0 && amb.Z == 0) { continue; } hasScene = true; Renderer.SystemLighting.Ambient = new Color4(amb.X / 255f, amb.Y / 255f, amb.Z / 255f, 1); } else if (kv.Value.Type == EntityTypes.Light) { var lt = new DynamicLight(); lt.LightGroup = kv.Value.LightGroup; lt.Active = kv.Value.LightProps.On; lt.Light = kv.Value.LightProps.Render; obj.Light = lt; obj.LightDir = lt.Light.Direction; if (kv.Value.RotationMatrix.HasValue) { var m = kv.Value.RotationMatrix.Value; lt.Light.Direction = (new Vector4(lt.Light.Direction.Normalized(), 0) * m).Xyz.Normalized(); } if (Renderer != null) { Renderer.SystemLighting.Lights.Add(lt); } } else if (kv.Value.Type == EntityTypes.Camera) { obj.Camera = new ThnCameraTransform(); obj.Camera.Position = kv.Value.Position.Value; obj.Camera.Orientation = kv.Value.RotationMatrix ?? Matrix4.Identity; obj.Camera.FovH = kv.Value.FovH ?? obj.Camera.FovH; obj.Camera.AspectRatio = kv.Value.HVAspect ?? obj.Camera.AspectRatio; } else if (kv.Value.Type == EntityTypes.Marker) { obj.Object = new GameObject(); obj.Object.Name = "Marker"; obj.Object.Nickname = ""; } else if (kv.Value.Type == EntityTypes.Sound) { obj.Sound = new ThnSound(kv.Value.Template, game.GetService <SoundManager>(), kv.Value.AudioProps, obj); obj.Sound.Spatial = (kv.Value.ObjectFlags & ThnObjectFlags.Spatial) == ThnObjectFlags.Spatial; } if (obj.Object != null) { Vector3 transform = kv.Value.Position ?? Vector3.Zero; obj.Object.Transform = (kv.Value.RotationMatrix ?? Matrix4.Identity) * Matrix4.CreateTranslation(transform); World.Objects.Add(obj.Object); } obj.Entity = kv.Value; Objects[kv.Key] = obj; } }
public ThnSoundInstance(ThnSound snd, Media.SoundInstance ms) { Object = snd.Object; Spatial = snd.Spatial; Instance = ms; }
void SceneSetup(ThnScript[] scripts, bool resetObjects = true) { hasScene = false; currentTime = 0; if (resetObjects) { sceneObjects = new Dictionary<string, ThnObject>(StringComparer.OrdinalIgnoreCase); layers = new List<Tuple<IDrawable, ThnObject>>(); } if (spawnObjects && resetObjects) { if (Renderer != null) { Renderer.Dispose(); World.Dispose(); } Renderer = new SystemRenderer(camera, gameData, game.GetService<GameResourceManager>(), game); World = new GameWorld(Renderer, false); } if (scriptContext.SetScript != null && resetObjects) { var inst = new ThnScriptInstance(this, scriptContext.SetScript); inst.ConstructEntities(sceneObjects, spawnObjects); } if (instances != null && resetObjects) { foreach (var inst in instances) inst.Cleanup(); } if(resetObjects) instances = new List<ThnScriptInstance>(); foreach (var script in scripts) { var ts = new ThnScriptInstance(this, script); ts.ConstructEntities(sceneObjects, spawnObjects && resetObjects); instances.Add(ts); } if (resetObjects) { var firstCamera = sceneObjects.Values.FirstOrDefault(x => x.Camera != null); if (firstCamera == null) firstCamera = sceneObjects.Values.FirstOrDefault(x => x.Camera != null); if (firstCamera != null) { camera.Transform = firstCamera.Camera; } } if (spawnObjects && resetObjects) { //Add starspheres in the right order var sorted = ((IEnumerable<Tuple<IDrawable, ThnObject>>) layers).Reverse() .OrderBy(x => x.Item2.Entity.SortGroup).ToArray(); Renderer.StarSphereModels = new RigidModel[sorted.Length]; Renderer.StarSphereWorlds = new Matrix4x4[sorted.Length]; Renderer.StarSphereLightings = new Lighting[sorted.Length]; starSphereObjects = new ThnObject[sorted.Length]; for (int i = 0; i < sorted.Length; i++) { Renderer.StarSphereModels[i] = (sorted[i].Item1 as IRigidModelFile).CreateRigidModel(true); Renderer.StarSphereWorlds[i] = sorted[i].Item2.Rotate * Matrix4x4.CreateTranslation(sorted[i].Item2.Translate); Renderer.StarSphereLightings[i] = Lighting.Empty; starSphereObjects[i] = sorted[i].Item2; } //Add objects to the renderer World.RegisterAll(); } lagCounter = 0; //Init _Update(0); running = true; }
public void AddStarsphere(IDrawable drawable, ThnObject obj) { layers.Add(new Tuple<IDrawable, ThnObject>(drawable, obj)); }
public void ConstructEntities(Dictionary <string, ThnObject> objects, bool spawnObjects) { this.Objects = objects; foreach (var kv in thn.Entities) { if (Objects.ContainsKey(kv.Key)) { continue; } if ((kv.Value.ObjectFlags & ThnObjectFlags.Reference) == ThnObjectFlags.Reference) { continue; } var obj = new ThnObject(); obj.Name = kv.Key; obj.Translate = kv.Value.Position ?? Vector3.Zero; obj.Rotate = kv.Value.RotationMatrix ?? Matrix4x4.Identity; //PlayerShip object if (spawnObjects && Cutscene.PlayerShip != null && kv.Value.Type == EntityTypes.Compound && kv.Value.Template.Equals("playership", StringComparison.InvariantCultureIgnoreCase)) { obj.Object = Cutscene.PlayerShip; obj.Object.RenderComponent.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic; obj.Object.RenderComponent.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient; obj.Object.RenderComponent.NoFog = kv.Value.NoFog; ((ModelRenderer)obj.Object.RenderComponent).LightGroup = kv.Value.LightGroup; obj.Entity = kv.Value; Vector3 transform = kv.Value.Position ?? Vector3.Zero; obj.Object.SetLocalTransform((kv.Value.RotationMatrix ?? Matrix4x4.Identity) * Matrix4x4.CreateTranslation(transform)); obj.HpMount = Cutscene.PlayerShip.GetHardpoint("HpMount"); Cutscene.World.AddObject(obj.Object); Objects.Add(kv.Key, obj); continue; } var template = kv.Value.Template; string replacement; if (Cutscene.Substitutions != null && Cutscene.Substitutions.TryGetValue(kv.Value.Template, out replacement)) { template = replacement; } var resman = Cutscene.Game.GetService <ResourceManager>(); var gameData = Cutscene.GameData; if (spawnObjects && kv.Value.Type == EntityTypes.Compound) { bool getHpMount = false; //Fetch model IDrawable drawable = null; float[] lodranges = null; if (!string.IsNullOrEmpty(template)) { switch (kv.Value.MeshCategory.ToLowerInvariant()) { case "solar": (drawable, lodranges) = gameData.GetSolar(template); break; case "ship": case "spaceship": getHpMount = true; var sh = gameData.GetShip(template); drawable = sh.ModelFile.LoadFile(resman); break; case "prop": drawable = gameData.GetProp(template); break; case "room": drawable = gameData.GetRoom(template); break; case "equipment cart": drawable = gameData.GetCart(template); break; case "equipment": var eq = gameData.GetEquipment(template); drawable = eq?.ModelFile.LoadFile(resman); break; case "asteroid": drawable = gameData.GetAsteroid(kv.Value.Template); break; default: throw new NotImplementedException("Mesh Category " + kv.Value.MeshCategory); } } else { FLLog.Warning("Thn", $"object '{kv.Value.Name}' has empty template, category " + $"'{kv.Value.MeshCategory}'"); } drawable?.Initialize(resman); if (kv.Value.UserFlag != 0) { //This is a starsphere Cutscene.AddStarsphere(drawable, obj); } else { obj.Object = new GameObject(drawable, Cutscene.Game.GetService <ResourceManager>(), true, false); obj.Object.Name = kv.Value.Name; obj.Object.PhysicsComponent = null; //Jitter seems to interfere with directly setting orientation if (getHpMount) { obj.HpMount = obj.Object.GetHardpoint("HpMount"); } var r = (ModelRenderer)obj.Object.RenderComponent; if (r != null) { r.LightGroup = kv.Value.LightGroup; r.LitDynamic = (kv.Value.ObjectFlags & ThnObjectFlags.LitDynamic) == ThnObjectFlags.LitDynamic; r.LitAmbient = (kv.Value.ObjectFlags & ThnObjectFlags.LitAmbient) == ThnObjectFlags.LitAmbient; //HIDDEN just seems to be an editor flag? //r.Hidden = (kv.Value.ObjectFlags & ThnObjectFlags.Hidden) == ThnObjectFlags.Hidden; r.NoFog = kv.Value.NoFog; r.LODRanges = lodranges; } } } else if (kv.Value.Type == EntityTypes.PSys) { var fx = gameData.GetEffect(kv.Value.Template); if (fx != null) { obj.Object = new GameObject(); obj.Object.RenderComponent = new ParticleEffectRenderer(fx.GetEffect(resman)) { Active = false }; } } else if (kv.Value.Type == EntityTypes.Scene) { if (kv.Value.DisplayText != null) { Cutscene.SetDisplayText(kv.Value.DisplayText); } var amb = kv.Value.Ambient.Value; if (amb.X == 0 && amb.Y == 0 && amb.Z == 0) { continue; } Cutscene.SetAmbient(amb); } else if (kv.Value.Type == EntityTypes.Light) { var lt = new DynamicLight(); lt.LightGroup = kv.Value.LightGroup; lt.Active = kv.Value.LightProps.On; lt.Light = kv.Value.LightProps.Render; obj.Light = lt; obj.LightDir = lt.Light.Direction; if (kv.Value.RotationMatrix.HasValue) { var m = kv.Value.RotationMatrix.Value; lt.Light.Direction = Vector3.TransformNormal(lt.Light.Direction, m); } if (Cutscene.Renderer != null) { Cutscene.Renderer.SystemLighting.Lights.Add(lt); } } else if (kv.Value.Type == EntityTypes.Camera) { obj.Camera = new ThnCameraTransform(); obj.Camera.Position = kv.Value.Position.Value; obj.Camera.Orientation = kv.Value.RotationMatrix ?? Matrix4x4.Identity; obj.Camera.FovH = kv.Value.FovH ?? obj.Camera.FovH; obj.Camera.AspectRatio = kv.Value.HVAspect ?? obj.Camera.AspectRatio; if (kv.Value.NearPlane != null) { obj.Camera.Znear = kv.Value.NearPlane.Value; } if (kv.Value.FarPlane != null) { obj.Camera.Zfar = kv.Value.FarPlane.Value; } } else if (kv.Value.Type == EntityTypes.Marker) { obj.Object = new GameObject(); obj.Object.Name = "Marker"; obj.Object.Nickname = ""; if (kv.Value.MainObject && Cutscene.MainObject != null) { obj.Object.Parent = Cutscene.MainObject; obj.Object.Components.Add(new DirtyTransformComponent(obj.Object)); obj.PosFromObject = true; } } else if (kv.Value.Type == EntityTypes.Deformable) { //TODO: Hacky with fidget/placement scripts if (string.IsNullOrEmpty(kv.Value.Actor) || !objects.ContainsKey(kv.Value.Actor)) { obj.Object = new GameObject(); gameData.GetCostume(template, out DfmFile body, out DfmFile head, out DfmFile leftHand, out DfmFile rightHand); var skel = new DfmSkeletonManager(body, head, leftHand, rightHand); obj.Object.RenderComponent = new CharacterRenderer(skel); var anmComponent = new AnimationComponent(obj.Object, gameData.GetCharacterAnimations()); obj.Object.AnimationComponent = anmComponent; obj.Object.Components.Add(anmComponent); } else { obj.Actor = kv.Value.Actor; if (Objects.TryGetValue(obj.Actor, out var act)) { act.Translate = obj.Translate; act.Rotate = obj.Rotate; act.Update(); } } } else if (kv.Value.Type == EntityTypes.Sound) { obj.Sound = new ThnSound(kv.Value.Template, Cutscene.Game.GetService <SoundManager>(), kv.Value.AudioProps, obj); obj.Sound.Spatial = (kv.Value.ObjectFlags & ThnObjectFlags.SoundSpatial) == ThnObjectFlags.SoundSpatial; } if (obj.Object != null) { if (!obj.PosFromObject) { Vector3 transform = kv.Value.Position ?? Vector3.Zero; obj.Object.SetLocalTransform((kv.Value.RotationMatrix ?? Matrix4x4.Identity) * Matrix4x4.CreateTranslation(transform)); } Cutscene.World.AddObject(obj.Object); } obj.Entity = kv.Value; Objects[kv.Key] = obj; } }