public override Entity Create(Main main) { Entity result = new Entity(main, "PointLight"); result.Add("Transform", new Transform()); PointLight pointLight = new PointLight(); pointLight.Attenuation.Value = 10.0f; pointLight.Color.Value = Vector3.One; result.Add("PointLight", pointLight); return result; }
public override void Awake() { base.Awake(); this.blockFactory = Factory.Get <EffectBlockFactory>(); this.EnabledWhenPaused = false; if (main.EditorEnabled) { this.BlockQueue.Clear(); } this.particles = ParticleSystem.Get(main, "WhiteShatter"); for (int i = 0; i < maxSparkLights; i++) { PointLight light = new PointLight(); light.Serialize = false; light.Color.Value = new Vector3(1.0f); light.Enabled.Value = false; this.Entity.Add(light); this.sparkLights.Add(light); } if (!this.main.EditorEnabled) { this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsFilled, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferredFromMap) { foreach (Voxel.Coord c in coords) { Voxel.t id = c.Data.ID; if (id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.HardPowered || id == Voxel.t.Infected || id == Voxel.t.HardInfected || (transferredFromMap == null && (id == Voxel.t.Blue || id == Voxel.t.Neutral || id == Voxel.t.Hard))) { Voxel.Coord newCoord = c; newCoord.Data = Voxel.States.Empty; int generation; EffectBlock.Entry generationsKey = new EffectBlock.Entry { Voxel = map, Coordinate = newCoord }; if (this.generations.TryGetValue(generationsKey, out generation)) { this.generations.Remove(generationsKey); } if (!this.isInQueue(map.Entity, newCoord, false)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = newCoord, Time = propagateDelay, Generation = generation, }); } } } })); this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsEmptied, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferringToNewMap) { foreach (Voxel.Coord coord in coords) { Voxel.t id = coord.Data.ID; if (id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.HardPowered || id == Voxel.t.PermanentPowered) { this.removedPoweredCoords.Add(coord); } if (transferringToNewMap != null) { continue; } if (id == Voxel.t.Critical) // Critical. Explodes when destroyed. { Explosion.Explode(main, map, coord); } else if (id == Voxel.t.Powered || id == Voxel.t.Blue || id == Voxel.t.Neutral || id == Voxel.t.Infected || id == Voxel.t.Floater) { int generation; Voxel.Coord c = coord; c.Data = Voxel.States.Empty; EffectBlock.Entry generationKey = new EffectBlock.Entry { Voxel = map, Coordinate = c }; if (this.generations.TryGetValue(generationKey, out generation)) { this.generations.Remove(generationKey); } if (id == Voxel.t.Floater) { Entity blockEntity = this.blockFactory.CreateAndBind(main); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); effectBlock.Delay = 4.0f; effectBlock.Offset.Value = map.GetRelativePosition(coord); effectBlock.StartPosition = map.GetAbsolutePosition(coord) + new Vector3(2.5f, 5.0f, 2.5f); effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(1.0f, 1.0f, 0); effectBlock.TotalLifetime = 0.5f; effectBlock.Setup(map.Entity, coord, coord.Data.ID); main.Add(blockEntity); } if (generation == 0) { if (!this.isInQueue(map.Entity, coord, true)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = coord, Time = propagateDelay, Removing = true, }); } } else if (generation < maxGenerations) { Direction down = map.GetRelativeDirection(Direction.NegativeY); for (int i = 0; i < 6; i++) { Direction dir = DirectionExtensions.Directions[i]; Voxel.Coord adjacent = coord.Move(dir); if (!coords.Contains(adjacent)) { Voxel.t adjacentID = map[adjacent].ID; bool adjacentIsFloater = adjacentID == Voxel.t.Floater; if (dir != down || adjacentIsFloater) { if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Neutral || adjacentID == Voxel.t.Infected || adjacentIsFloater) { if (!this.isInQueue(map.Entity, adjacent, true)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = adjacent, Time = propagateDelay, Removing = true, Generation = generation + 1, }); } } } } } } } else if (id == Voxel.t.White || id == Voxel.t.Glass) // Shatter effects. { ParticleSystem shatter = ParticleSystem.Get(main, "WhiteShatter"); Vector3 pos = map.GetAbsolutePosition(coord); for (int i = 0; i < 50; i++) { Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f); shatter.AddParticle(pos + offset, offset); } float time = this.main.TotalTime; if (time - this.lastShatterSound > 0.3f) { this.lastShatterSound = time; Sound.PostEvent(AK.EVENTS.PLAY_WHITE_SHATTER, pos); } } } if (this.removedPoweredCoords.Count > 0) { IEnumerable <IEnumerable <Voxel.Box> > poweredIslands = map.GetAdjacentIslands(this.removedPoweredCoords, x => x.ID == Voxel.t.Powered || x.ID == Voxel.t.HardPowered, x => x == Voxel.States.PermanentPowered || x == Voxel.States.PoweredSwitch); List <Voxel.Coord> poweredCoords = poweredIslands.SelectMany(x => x).SelectMany(x => x.GetCoords()).ToList(); if (poweredCoords.Count > 0) { lock (map.MutationLock) { map.Empty(poweredCoords, true, true, map, false); for (int i = 0; i < poweredCoords.Count; i++) { Voxel.Coord coord = poweredCoords[i]; if (coord.Data.ID == Voxel.t.HardPowered) { map.Fill(coord, Voxel.States.Hard, true, map); } else { map.Fill(coord, Voxel.States.Blue, true, map); } } } this.toRegenerate.Add(map); } this.removedPoweredCoords.Clear(); } })); } }
public void Update(float dt) { float sparkLightFade = sparkLightBrightness * dt / sparkLightFadeTime; for (int i = 0; i < activeSparkLights; i++) { PointLight light = this.sparkLights[i]; float a = light.Color.Value.X - sparkLightFade; if (a < 0.0f) { light.Enabled.Value = false; PointLight swap = this.sparkLights[activeSparkLights - 1]; this.sparkLights[i] = swap; this.sparkLights[activeSparkLights - 1] = light; activeSparkLights--; oldestSparkLight = activeSparkLights; } else { light.Color.Value = new Vector3(a); } } for (int i = 0; i < this.BlockQueue.Length; i++) { ScheduledBlock entry = this.BlockQueue[i]; entry.Time -= dt; if (entry.Time < 0.0f) { this.BlockQueue.RemoveAt(i); i--; Entity mapEntity = entry.Voxel.Target; if (mapEntity != null && mapEntity.Active) { Voxel map = mapEntity.Get <Voxel>(); Voxel.Coord c = entry.Coordinate; Voxel.t id = map[c].ID; bool regenerate = false; if (entry.Removing) { if (entry.Generation == 0 && id == 0) { Direction down = map.GetRelativeDirection(Direction.NegativeY); for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; bool adjacentIsFloater = adjacentID == Voxel.t.Floater; if (dir != down || adjacentIsFloater) { if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Neutral || adjacentID == Voxel.t.Infected || adjacentIsFloater) { if (!this.isInQueue(map.Entity, adjacent, true)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = adjacent, Time = propagateDelay, Removing = true, Generation = 1, }); } } } } } else if (entry.Generation > 0 && (id == Voxel.t.Blue || id == Voxel.t.Infected || id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch || id == Voxel.t.Neutral || id == Voxel.t.Floater)) { this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = c }] = entry.Generation; map.Empty(c); this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Burn); regenerate = true; } } else if (id == Voxel.t.Blue) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.PoweredSwitch) { map.Empty(c, false, true, map); map.Fill(c, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Blue); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Neutral) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Neutral); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.HardInfected) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Hard); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Hard) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.HardInfected) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Hard); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (id == Voxel.t.Powered && adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Blue) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Switch) { map.Empty(adjacent, true, true, map); map.Fill(adjacent, Voxel.States.PoweredSwitch); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Hard) { map.Empty(adjacent, true, true, map); map.Fill(adjacent, Voxel.States.HardPowered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Critical) { map.Empty(adjacent); regenerate = true; } } } else if (id == Voxel.t.Infected || id == Voxel.t.HardInfected) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Infected); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous); regenerate = true; } else if (adjacentID == Voxel.t.Hard && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.HardInfected); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous); regenerate = true; } else if (adjacentID == Voxel.t.Critical) { map.Empty(adjacent); regenerate = true; } } } if (regenerate) { this.toRegenerate.Add(map); } } } } for (int i = 0; i < this.toRegenerate.Count; i++) { this.toRegenerate[i].Regenerate(); } this.toRegenerate.Clear(); }
public static void Attach(Main main, Entity entity, Player player, AnimatedModel model, FPSInput input, Phone phone, Property <bool> enableWalking, Property <bool> phoneActive, Property <bool> noteActive) { UIRenderer phoneUi = entity.GetOrCreate <UIRenderer>("PhoneUI"); model["Phone"].Speed = model["VRPhone"].Speed = model["Note"].Speed = model["VRNote"].Speed = 0.25f; const float phoneWidth = 200.0f; phoneUi.RenderTargetBackground.Value = Microsoft.Xna.Framework.Color.White; phoneUi.RenderTargetSize.Value = new Point((int)phoneWidth, (int)(phoneWidth * 2.0f)); phoneUi.Serialize = false; phoneUi.Enabled.Value = false; #if VR if (main.VR) { phoneUi.Reticle.Tint.Value = new Color(0.0f, 0.0f, 0.0f); } #endif Model phoneModel = entity.GetOrCreate <Model>("PhoneModel"); phoneModel.Filename.Value = "Models\\phone"; phoneModel.Color.Value = new Vector3(0.13f, 0.13f, 0.13f); phoneModel.Serialize = false; phoneModel.Enabled.Value = false; Property <Matrix> phoneBone = model.GetBoneTransform("Phone"); phoneModel.Add(new Binding <Matrix>(phoneModel.Transform, () => phoneBone.Value * model.Transform, phoneBone, model.Transform)); Model screen = entity.GetOrCreate <Model>("Screen"); screen.Filename.Value = "Models\\plane"; screen.Add(new Binding <Microsoft.Xna.Framework.Graphics.RenderTarget2D>(screen.GetRenderTarget2DParameter("Diffuse" + Model.SamplerPostfix), phoneUi.RenderTarget)); screen.Add(new Binding <Matrix>(screen.Transform, x => Matrix.CreateTranslation(0.015f, 0.0f, 0.0f) * x, phoneModel.Transform)); screen.Serialize = false; screen.Enabled.Value = false; PointLight phoneLight = entity.Create <PointLight>(); phoneLight.Serialize = false; phoneLight.Enabled.Value = false; phoneLight.Attenuation.Value = 0.5f; phoneLight.Add(new Binding <Vector3, Matrix>(phoneLight.Position, x => x.Translation, screen.Transform)); PointLight noteLight = entity.Create <PointLight>(); noteLight.Serialize = false; noteLight.Enabled.Value = false; noteLight.Attenuation.Value = 1.0f; noteLight.Color.Value = new Vector3(0.3f); noteLight.Add(new Binding <Vector3>(noteLight.Position, () => Vector3.Transform(new Vector3(0.25f, 0.0f, 0.0f), phoneBone.Value * model.Transform), phoneBone, model.Transform)); const float screenScale = 0.0007f; screen.Scale.Value = new Vector3(1.0f, (float)phoneUi.RenderTargetSize.Value.Y * screenScale, (float)phoneUi.RenderTargetSize.Value.X * screenScale); // Transform screen space mouse position into 3D, then back into the 2D space of the phone UI Property <Matrix> screenTransform = new Property <Matrix>(); screen.Add(new Binding <Matrix>(screenTransform, () => Matrix.CreateScale(screen.Scale) * screen.Transform, screen.Scale, screen.Transform)); phoneUi.Setup3D(screenTransform); // Phone UI const float padding = 8.0f; const float messageWidth = phoneWidth - padding * 2.0f; Func <Property <Color>, string, float, Container> makeButton = delegate(Property <Color> color, string text, float width) { Container bg = new Container(); bg.Tint.Value = color; bg.PaddingBottom.Value = bg.PaddingLeft.Value = bg.PaddingRight.Value = bg.PaddingTop.Value = padding * 0.5f; bg.Add(new Binding <Color>(bg.Tint, () => bg.Highlighted ? new Color(color.Value.ToVector4() + new Vector4(0.2f, 0.2f, 0.2f, 0.0f)) : color, bg.Highlighted, color)); TextElement msg = new TextElement(); msg.Name.Value = "Text"; msg.FontFile.Value = main.Font; msg.Text.Value = text; msg.WrapWidth.Value = width; bg.Children.Add(msg); return(bg); }; Action <Container, float> centerButton = delegate(Container button, float width) { TextElement text = (TextElement)button.Children[0]; text.AnchorPoint.Value = new Vector2(0.5f, 0); text.Add(new Binding <Vector2>(text.Position, x => new Vector2(x.X * 0.5f, padding), button.Size)); button.ResizeHorizontal.Value = false; button.ResizeVertical.Value = false; button.Size.Value = new Vector2(width, 36.0f * main.FontMultiplier); }; Func <UIComponent, bool, Container> makeAlign = delegate(UIComponent component, bool right) { Container container = new Container(); container.Opacity.Value = 0.0f; container.PaddingBottom.Value = container.PaddingLeft.Value = container.PaddingRight.Value = container.PaddingTop.Value = 0.0f; container.ResizeHorizontal.Value = false; container.Size.Value = new Vector2(messageWidth, 0.0f); component.AnchorPoint.Value = new Vector2(right ? 1.0f : 0.0f, 0.0f); component.Position.Value = new Vector2(right ? messageWidth : 0.0f, 0.0f); container.Children.Add(component); return(container); }; Property <Color> incomingColor = new Property <Color> { Value = new Color(0.0f, 0.0f, 0.0f, 1.0f) }; Property <Color> outgoingColor = new Property <Color> { Value = new Color(0.0f, 0.175f, 0.35f, 1.0f) }; Property <Color> alternateSenderColor = new Property <Color> { Value = new Color(0.25f, 0.0f, 0.25f, 1.0f) }; Property <Color> composeColor = new Property <Color> { Value = new Color(0.5f, 0.0f, 0.0f, 1.0f) }; Property <Color> disabledColor = new Property <Color> { Value = new Color(0.35f, 0.35f, 0.35f, 1.0f) }; Property <Color> topBarColor = new Property <Color> { Value = new Color(0.15f, 0.15f, 0.15f, 1.0f) }; Container topBarContainer = new Container(); topBarContainer.ResizeHorizontal.Value = false; topBarContainer.Size.Value = new Vector2(phoneUi.RenderTargetSize.Value.X, 0.0f); topBarContainer.Tint.Value = topBarColor; phoneUi.Root.Children.Add(topBarContainer); ListContainer phoneTopBar = new ListContainer(); phoneTopBar.Orientation.Value = ListContainer.ListOrientation.Horizontal; phoneTopBar.Spacing.Value = padding; topBarContainer.Children.Add(phoneTopBar); Sprite signalIcon = new Sprite(); signalIcon.Image.Value = "Images\\signal"; phoneTopBar.Children.Add(signalIcon); TextElement noService = new TextElement(); noService.FontFile.Value = main.Font; noService.Text.Value = "\\no service"; phoneTopBar.Children.Add(noService); signalIcon.Add(new Binding <bool>(signalIcon.Visible, () => player.SignalTower.Value.Target != null || phone.ActiveAnswers.Length > 0 || phone.Schedules.Length > 0, player.SignalTower, phone.ActiveAnswers.Length, phone.Schedules.Length)); noService.Add(new Binding <bool>(noService.Visible, x => !x, signalIcon.Visible)); ListContainer tabs = new ListContainer(); tabs.Orientation.Value = ListContainer.ListOrientation.Horizontal; tabs.Spacing.Value = 0; phoneUi.Root.Children.Add(tabs); Property <Color> messageTabColor = new Property <Color> { Value = outgoingColor }; phoneUi.Add(new Binding <Color, Phone.Mode>(messageTabColor, x => x == Phone.Mode.Messages ? outgoingColor : topBarColor, phone.CurrentMode)); Container messageTab = makeButton(messageTabColor, "\\messages", phoneUi.RenderTargetSize.Value.X * 0.5f - padding); centerButton(messageTab, phoneUi.RenderTargetSize.Value.X * 0.5f); tabs.Children.Add(messageTab); messageTab.Add(new CommandBinding(messageTab.MouseLeftUp, delegate() { phone.CurrentMode.Value = Phone.Mode.Messages; })); Property <Color> photoTabColor = new Property <Color> { Value = topBarColor }; phoneUi.Add(new Binding <Color>(photoTabColor, delegate() { if (phone.CurrentMode == Phone.Mode.Photos) { return(outgoingColor); } else if (string.IsNullOrEmpty(phone.Photo)) { return(disabledColor); } else { return(topBarColor); } }, phone.CurrentMode, phone.Photo)); Container photoTab = makeButton(photoTabColor, "\\photos", phoneUi.RenderTargetSize.Value.X * 0.5f - padding); centerButton(photoTab, phoneUi.RenderTargetSize.Value.X * 0.5f); tabs.Children.Add(photoTab); photoTab.Add(new CommandBinding(photoTab.MouseLeftUp, delegate() { if (!string.IsNullOrEmpty(phone.Photo)) { phone.CurrentMode.Value = Phone.Mode.Photos; } })); tabs.Add(new Binding <Vector2>(tabs.Position, x => new Vector2(0, x.Y), topBarContainer.Size)); ListContainer messageLayout = new ListContainer(); messageLayout.Spacing.Value = padding; messageLayout.Orientation.Value = ListContainer.ListOrientation.Vertical; messageLayout.Add(new Binding <Vector2>(messageLayout.Position, () => new Vector2(padding, topBarContainer.Size.Value.Y + tabs.Size.Value.Y), topBarContainer.Size, tabs.Size)); messageLayout.Add(new Binding <Vector2>(messageLayout.Size, () => new Vector2(phoneUi.RenderTargetSize.Value.X - padding * 2.0f, phoneUi.RenderTargetSize.Value.Y - padding - topBarContainer.Size.Value.Y - tabs.Size.Value.Y), phoneUi.RenderTargetSize, topBarContainer.Size, tabs.Size)); messageLayout.Add(new Binding <bool, Phone.Mode>(messageLayout.Visible, x => x == Phone.Mode.Messages, phone.CurrentMode)); phoneUi.Root.Children.Add(messageLayout); Container photoLayout = new Container(); photoLayout.Opacity.Value = 0; photoLayout.PaddingLeft.Value = photoLayout.PaddingRight.Value = photoLayout.PaddingTop.Value = photoLayout.PaddingBottom.Value = 0; photoLayout.Add(new Binding <Vector2>(photoLayout.Position, () => new Vector2(0, topBarContainer.Size.Value.Y + tabs.Size.Value.Y), topBarContainer.Size, tabs.Size)); photoLayout.Add(new Binding <Vector2>(photoLayout.Size, () => new Vector2(phoneUi.RenderTargetSize.Value.X, phoneUi.RenderTargetSize.Value.Y - topBarContainer.Size.Value.Y - tabs.Size.Value.Y), phoneUi.RenderTargetSize, topBarContainer.Size, tabs.Size)); photoLayout.Add(new Binding <bool>(photoLayout.Visible, x => !x, messageLayout.Visible)); phoneUi.Root.Children.Add(photoLayout); Sprite photoImage = new Sprite(); photoImage.AnchorPoint.Value = new Vector2(0.5f, 0.5f); photoImage.Add(new Binding <string>(photoImage.Image, phone.Photo)); photoImage.Add(new Binding <Vector2>(photoImage.Position, x => x * 0.5f, photoLayout.Size)); photoLayout.Children.Add(photoImage); Container composeButton = makeButton(composeColor, "\\compose", messageWidth - padding * 2.0f); TextElement composeText = (TextElement)composeButton.GetChildByName("Text"); composeText.Add(new Binding <string, bool>(composeText.Text, x => x ? "\\compose gamepad" : "\\compose", main.GamePadConnected)); UIComponent composeAlign = makeAlign(composeButton, true); Scroller phoneScroll = new Scroller(); phoneScroll.ResizeVertical.Value = false; phoneScroll.Add(new Binding <Vector2>(phoneScroll.Size, () => new Vector2(messageLayout.Size.Value.X, messageLayout.Size.Value.Y - messageLayout.Spacing.Value - composeAlign.ScaledSize.Value.Y), messageLayout.Size, messageLayout.Spacing, composeAlign.ScaledSize)); messageLayout.Children.Add(phoneScroll); messageLayout.Children.Add(composeAlign); ListContainer msgList = new ListContainer(); msgList.Spacing.Value = padding * 0.5f; msgList.Orientation.Value = ListContainer.ListOrientation.Vertical; msgList.ResizePerpendicular.Value = false; msgList.Size.Value = new Vector2(messageWidth, 0.0f); phoneScroll.Children.Add(msgList); Container answerContainer = new Container(); answerContainer.PaddingBottom.Value = answerContainer.PaddingLeft.Value = answerContainer.PaddingRight.Value = answerContainer.PaddingTop.Value = padding; answerContainer.Tint.Value = incomingColor; answerContainer.AnchorPoint.Value = new Vector2(1.0f, 1.0f); answerContainer.Add(new Binding <Vector2>(answerContainer.Position, () => composeAlign.GetAbsolutePosition() + new Vector2(composeAlign.ScaledSize.Value.X, 0), composeAlign.Position, composeAlign.ScaledSize)); phoneUi.Root.Children.Add(answerContainer); answerContainer.Visible.Value = false; ListContainer answerList = new ListContainer(); answerList.Orientation.Value = ListContainer.ListOrientation.Vertical; answerList.Alignment.Value = ListContainer.ListAlignment.Max; answerContainer.Children.Add(answerList); int selectedAnswer = 0; composeButton.Add(new CommandBinding(composeButton.MouseLeftUp, delegate() { answerContainer.Visible.Value = !answerContainer.Visible; if (answerContainer.Visible && main.GamePadConnected) { selectedAnswer = 0; foreach (UIComponent answer in answerList.Children) { answer.Highlighted.Value = false; } answerList.Children[0].Highlighted.Value = true; } })); tabs.Add(new Binding <bool>(tabs.EnableInput, () => !main.Paused && !answerContainer.Visible, answerContainer.Visible, main.Paused)); msgList.Add(new Binding <bool>(msgList.EnableInput, () => !main.Paused && !answerContainer.Visible, answerContainer.Visible, main.Paused)); answerContainer.Add(new Binding <bool>(answerContainer.EnableInput, x => !x, main.Paused)); composeButton.Add(new Binding <bool>(composeButton.EnableInput, x => !x, main.Paused)); Action scrollToBottom = delegate() { // HACK Animation scroll = new Animation ( new Animation.Delay(0.01f), new Animation.Execute(delegate() { phoneScroll.ScrollToBottom(); }) ); entity.Add(scroll); }; // Note UIRenderer noteUi = entity.GetOrCreate <UIRenderer>("NoteUI"); const float noteWidth = 400.0f; noteUi.RenderTargetBackground.Value = new Microsoft.Xna.Framework.Color(0.8f, 0.75f, 0.7f); noteUi.RenderTargetSize.Value = new Point((int)noteWidth, (int)(noteWidth * 1.29f)); // 8.5x11 aspect ratio noteUi.Serialize = false; noteUi.Enabled.Value = false; Model noteModel = entity.GetOrCreate <Model>("Note"); noteModel.Filename.Value = "Models\\note"; noteModel.Add(new Binding <Microsoft.Xna.Framework.Graphics.RenderTarget2D>(noteModel.GetRenderTarget2DParameter("Diffuse" + Model.SamplerPostfix), noteUi.RenderTarget)); noteModel.Add(new Binding <Matrix>(noteModel.Transform, x => Matrix.CreateTranslation(-0.005f, 0.05f, 0.08f) * x, phoneModel.Transform)); noteModel.Serialize = false; noteModel.Enabled.Value = false; Container togglePhoneMessage = null; entity.Add(new NotifyBinding(delegate() { bool hasSignalTower = (player.SignalTower.Value.Target != null && player.SignalTower.Value.Target.Active && !string.IsNullOrEmpty(player.SignalTower.Value.Target.Get <SignalTower>().Initial)); if (hasSignalTower) { phone.Enabled.Value = true; } bool hasNoteOrSignalTower = (player.Note.Value.Target != null && player.Note.Value.Target.Active) || hasSignalTower; if (togglePhoneMessage == null && hasNoteOrSignalTower) { togglePhoneMessage = main.Menu.ShowMessage(entity, hasSignalTower ? "\\signal tower prompt" : "\\note prompt"); } else if (togglePhoneMessage != null && !hasNoteOrSignalTower && !phoneActive && !noteActive) { main.Menu.HideMessage(entity, togglePhoneMessage); togglePhoneMessage = null; } }, player.Note, player.SignalTower)); entity.Add(new CommandBinding(entity.Delete, delegate() { main.Menu.HideMessage(null, togglePhoneMessage); })); // Note UI const float notePadding = 40.0f; ListContainer noteLayout = new ListContainer(); noteLayout.Spacing.Value = padding; noteLayout.Orientation.Value = ListContainer.ListOrientation.Vertical; noteLayout.Alignment.Value = ListContainer.ListAlignment.Min; noteLayout.Position.Value = new Vector2(notePadding, notePadding); noteLayout.Add(new Binding <Vector2, Point>(noteLayout.Size, x => new Vector2(x.X - notePadding * 2.0f, x.Y - notePadding * 2.0f), noteUi.RenderTargetSize)); noteUi.Root.Children.Add(noteLayout); Sprite noteUiImage = new Sprite(); noteLayout.Children.Add(noteUiImage); TextElement noteUiText = new TextElement(); noteUiText.FontFile.Value = main.Font; noteUiText.Tint.Value = new Microsoft.Xna.Framework.Color(0.1f, 0.1f, 0.1f); noteUiText.Add(new Binding <float, Vector2>(noteUiText.WrapWidth, x => x.X, noteLayout.Size)); noteLayout.Children.Add(noteUiText); // Toggle note Animation noteAnim = null; float startRotationY = 0; Action <bool> showNote = delegate(bool show) { model.Stop("Phone", "Note", "VRPhone", "VRNote"); Entity noteEntity = player.Note.Value.Target; noteActive.Value = show && noteEntity != null; Note note = noteEntity != null?noteEntity.Get <Note>() : null; if (noteActive) { input.EnableLook.Value = input.EnableMouse.Value = false; enableWalking.Value = false; noteModel.Enabled.Value = true; noteUi.Enabled.Value = true; noteLight.Enabled.Value = true; Session.Recorder.Event(main, "Note", note.Text); noteUiImage.Image.Value = note.Image; noteUiText.Text.Value = note.Text; string noteAnimation; #if VR if (main.VR) { noteAnimation = "VRNote"; } else #endif noteAnimation = "Note"; model.StartClip(noteAnimation, 6, true, AnimatedModel.DefaultBlendTime * 2.0f); AkSoundEngine.PostEvent(AK.EVENTS.PLAY_NOTE_PICKUP, entity); if (noteAnim != null && noteAnim.Active) { noteAnim.Delete.Execute(); } else { startRotationY = input.Mouse.Value.Y; } // Level the player's view noteAnim = new Animation ( new Animation.Ease ( new Animation.Custom(delegate(float x) { input.Mouse.Value = new Vector2(input.Mouse.Value.X, startRotationY * (1.0f - x)); }, 0.5f), Animation.Ease.EaseType.OutQuadratic ) ); entity.Add(noteAnim); } else { enableWalking.Value = true; if (note != null) { Session.Recorder.Event(main, "NoteEnd"); } AkSoundEngine.PostEvent(AK.EVENTS.PLAY_NOTE_DROP, entity); if (note != null && !note.IsCollected) { note.IsCollected.Value = true; } // Return the player's view if (noteAnim != null && noteAnim.Active) { noteAnim.Delete.Execute(); } noteAnim = new Animation ( new Animation.Ease ( new Animation.Custom(delegate(float x) { input.Mouse.Value = new Vector2(input.Mouse.Value.X, startRotationY * x); }, 0.5f), Animation.Ease.EaseType.OutQuadratic ), new Animation.Execute(delegate() { noteModel.Enabled.Value = false; noteUi.Enabled.Value = false; noteLight.Enabled.Value = false; input.EnableLook.Value = input.EnableMouse.Value = true; }) ); entity.Add(noteAnim); } }; // Toggle phone Animation phoneAnim = null; Action <bool> showPhone = delegate(bool show) { if (togglePhoneMessage != null) { main.Menu.HideMessage(entity, togglePhoneMessage); togglePhoneMessage = null; } if (show || (phone.Schedules.Length == 0 && !phone.WaitForAnswer)) { phoneActive.Value = show; answerContainer.Visible.Value = false; model.Stop("Phone", "Note", "VRPhone", "VRNote"); if (phoneActive) { phoneUi.IsMouseVisible.Value = true; enableWalking.Value = false; phoneModel.Enabled.Value = true; screen.Enabled.Value = true; phoneUi.Enabled.Value = true; phoneLight.Enabled.Value = true; input.EnableLook.Value = input.EnableMouse.Value = false; Session.Recorder.Event(main, "Phone"); phoneScroll.CheckLayout(); scrollToBottom(); string phoneAnimation; #if VR if (main.VR) { phoneAnimation = "VRPhone"; } else #endif phoneAnimation = "Phone"; model.StartClip(phoneAnimation, 6, true, AnimatedModel.DefaultBlendTime * 2.0f); // Level the player's view if (phoneAnim != null && phoneAnim.Active) { phoneAnim.Delete.Execute(); } else { startRotationY = input.Mouse.Value.Y; } phoneAnim = new Animation ( new Animation.Ease ( new Animation.Custom(delegate(float x) { input.Mouse.Value = new Vector2(input.Mouse.Value.X, startRotationY * (1.0f - x)); }, 0.5f), Animation.Ease.EaseType.OutQuadratic ) ); entity.Add(phoneAnim); } else { Session.Recorder.Event(main, "PhoneEnd"); enableWalking.Value = true; phoneUi.IsMouseVisible.Value = false; // Return the player's view if (phoneAnim != null && phoneAnim.Active) { phoneAnim.Delete.Execute(); } phoneAnim = new Animation ( new Animation.Ease ( new Animation.Custom(delegate(float x) { input.Mouse.Value = new Vector2(input.Mouse.Value.X, startRotationY * x); }, 0.5f), Animation.Ease.EaseType.OutQuadratic ), new Animation.Execute(delegate() { phoneModel.Enabled.Value = false; screen.Enabled.Value = false; phoneUi.Enabled.Value = false; phoneLight.Enabled.Value = false; input.EnableLook.Value = input.EnableMouse.Value = true; }) ); entity.Add(phoneAnim); } } }; input.Bind(main.Settings.TogglePhone, PCInput.InputState.Down, delegate() { // Special hack to prevent phone toggling when you're trying to open the Steam overlay if (main.Settings.TogglePhone.Value.Key == Keys.Tab && input.GetKey(Keys.LeftShift)) { return; } if (noteActive || phoneActive || phone.CanReceiveMessages) { if (!phoneActive && (noteActive || player.Note.Value.Target != null)) { showNote(!noteActive); } else if (phone.Enabled) { showPhone(!phoneActive); } } }); phone.Add(new CommandBinding(phone.Show, delegate() { phone.Enabled.Value = true; if (!phoneActive) { showPhone(true); } })); // Gamepad code for the phone input.Add(new CommandBinding(input.GetButtonUp(Buttons.A), () => phoneActive && composeButton.Visible && phone.CurrentMode.Value == Phone.Mode.Messages, delegate() { if (answerContainer.Visible) { answerList.Children[selectedAnswer].MouseLeftUp.Execute(); } else { composeButton.MouseLeftUp.Execute(); } })); input.Add(new CommandBinding(input.GetButtonUp(Buttons.B), () => phoneActive && answerContainer.Visible, delegate() { answerContainer.Visible.Value = false; })); const float moveInterval = 0.1f; const float switchInterval = 0.2f; float lastScroll = 0; float lastModeSwitch = 0; Action <int> scrollPhone = delegate(int delta) { if (main.TotalTime - lastScroll > moveInterval && main.TotalTime - lastModeSwitch > switchInterval) { if (answerContainer.Visible) { answerList.Children[selectedAnswer].Highlighted.Value = false; selectedAnswer += delta; while (selectedAnswer < 0) { selectedAnswer += answerList.Children.Length; } while (selectedAnswer > answerList.Children.Length - 1) { selectedAnswer -= answerList.Children.Length; } answerList.Children[selectedAnswer].Highlighted.Value = true; } else { phoneScroll.MouseScrolled.Execute(delta * -4); } lastScroll = main.TotalTime; } }; Action switchMode = delegate() { if (main.TotalTime - lastScroll > switchInterval && main.TotalTime - lastModeSwitch > moveInterval) { Phone.Mode current = phone.CurrentMode; Phone.Mode nextMode = current == Phone.Mode.Messages ? Phone.Mode.Photos : Phone.Mode.Messages; if (nextMode == Phone.Mode.Photos && string.IsNullOrEmpty(phone.Photo)) { nextMode = Phone.Mode.Messages; } phone.CurrentMode.Value = nextMode; lastModeSwitch = main.TotalTime; } }; input.Add(new CommandBinding(input.GetButtonDown(Buttons.LeftThumbstickLeft), () => phoneActive && !answerContainer.Visible, switchMode)); input.Add(new CommandBinding(input.GetButtonDown(Buttons.LeftThumbstickRight), () => phoneActive && !answerContainer.Visible, switchMode)); input.Add(new CommandBinding(input.GetButtonDown(Buttons.DPadLeft), () => phoneActive && !answerContainer.Visible, switchMode)); input.Add(new CommandBinding(input.GetButtonDown(Buttons.DPadRight), () => phoneActive && !answerContainer.Visible, switchMode)); input.Add(new CommandBinding(input.GetButtonDown(Buttons.LeftThumbstickUp), () => phoneActive, delegate() { scrollPhone(-1); })); input.Add(new CommandBinding(input.GetButtonDown(Buttons.DPadUp), () => phoneActive, delegate() { scrollPhone(-1); })); input.Add(new CommandBinding(input.GetButtonDown(Buttons.LeftThumbstickDown), () => phoneActive, delegate() { scrollPhone(1); })); input.Add(new CommandBinding(input.GetButtonDown(Buttons.DPadDown), () => phoneActive, delegate() { scrollPhone(1); })); Func <Phone.Sender, Property <Color> > messageColor = delegate(Phone.Sender sender) { switch (sender) { case Phone.Sender.Player: return(outgoingColor); case Phone.Sender.A: return(incomingColor); default: return(alternateSenderColor); } }; msgList.Add(new ListBinding <UIComponent, Phone.Message> ( msgList.Children, phone.Messages, delegate(Phone.Message msg) { return(makeAlign(makeButton(messageColor(msg.Sender), "\\" + msg.Name, messageWidth - padding * 2.0f), msg.Sender == Phone.Sender.Player)); } )); Action <float, Container> animateMessage = delegate(float delay, Container msg) { msg.CheckLayout(); Vector2 originalSize = msg.Size; msg.Size.Value = new Vector2(0, originalSize.Y); entity.Add(new Animation ( new Animation.Delay(delay), new Animation.Ease(new Animation.Vector2MoveTo(msg.Size, originalSize, 0.5f), Animation.Ease.EaseType.OutExponential) )); }; Container typingIndicator = null; Action showTypingIndicator = delegate() { typingIndicator = makeAlign(makeButton(incomingColor, "\\...", messageWidth - padding * 2.0f), false); msgList.Children.Add(typingIndicator); animateMessage(0.2f, typingIndicator); }; if (phone.Schedules.Length > 0) { showTypingIndicator(); } answerList.Add(new ListBinding <UIComponent, Phone.Ans> ( answerList.Children, phone.ActiveAnswers, delegate(Phone.Ans answer) { UIComponent button = makeButton(outgoingColor, "\\" + answer.Name, messageWidth - padding * 4.0f); button.Add(new CommandBinding(button.MouseLeftUp, delegate() { if (!phone.WaitForAnswer) // If we're not waiting for an answer, the player must be initiating a conversation { // This is the start of a conversation // Disable the signal tower if we're in range Entity s = player.SignalTower.Value.Target; if (s != null) { s.Get <SignalTower>().Initial.Value = null; } } AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PHONE_SEND, entity); phone.Answer(answer); scrollToBottom(); if (phone.Schedules.Length == 0) // No more messages incoming { if (togglePhoneMessage == null) { togglePhoneMessage = main.Menu.ShowMessage(entity, "\\phone done prompt"); } } else { // More messages incoming showTypingIndicator(); } })); return(button); } )); Action refreshComposeButtonVisibility = delegate() { bool show = phone.ActiveAnswers.Length > 0 && phone.Schedules.Length == 0; answerContainer.Visible.Value &= show; composeButton.Visible.Value = show; selectedAnswer = 0; }; composeButton.Add(new ListNotifyBinding <Phone.Ans>(refreshComposeButtonVisibility, phone.ActiveAnswers)); composeButton.Add(new ListNotifyBinding <Phone.Schedule>(refreshComposeButtonVisibility, phone.Schedules)); refreshComposeButtonVisibility(); entity.Add(new CommandBinding(phone.MessageReceived, delegate() { if (typingIndicator != null) { typingIndicator.Delete.Execute(); typingIndicator = null; } if (phone.Schedules.Length > 0) { showTypingIndicator(); } float delay; if (phoneActive) { scrollToBottom(); delay = 0; } else { showPhone(true); delay = 0.5f; } // Animate the new message animateMessage(delay, (Container)msgList.Children[msgList.Children.Length - 1].Children[0]); AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PHONE_VIBRATE, entity); if (togglePhoneMessage == null && phone.Schedules.Length == 0 && phone.ActiveAnswers.Length == 0) // No more messages incoming, and no more answers to give { togglePhoneMessage = main.Menu.ShowMessage(entity, "[{{TogglePhone}}]"); } })); if (noteActive) { showNote(true); } else if (phoneActive) { showPhone(true); } }
public override Entity Create(Main main) { Entity result = new Entity(main, "Blast"); Transform transform = new Transform(); result.Add("Transform", transform); PhysicsBlock physics = new PhysicsBlock(); result.Add("Physics", physics); Model model = new Model(); result.Add("Model", model); model.Filename.Value = "Models\\blast"; model.Color.Value = new Vector3(0.75f, 2.0f, 0.75f); PointLight light = new PointLight(); light.Shadowed.Value = true; light.Color.Value = new Vector3(model.Color.Value.X, model.Color.Value.Y, model.Color.Value.Z); light.Attenuation.Value = 10.0f; result.Add("Light", light); if (ParticleSystem.Get(main, "Sparks") == null) { ParticleSystem.Add(main, "Sparks", new ParticleSystem.ParticleSettings { TextureName = "Particles\\spark", MaxParticles = 1000, Duration = TimeSpan.FromSeconds(1.0f), MinHorizontalVelocity = 0.0f, MaxHorizontalVelocity = 0.0f, MinVerticalVelocity = 0.0f, MaxVerticalVelocity = 0.0f, Gravity = new Vector3(0.0f, 0.0f, 0.0f), EndVelocity = 0.0f, MinRotateSpeed = -20.0f, MaxRotateSpeed = 20.0f, MinStartSize = 0.5f, MaxStartSize = 0.4f, MinEndSize = 0.2f, MaxEndSize = 0.1f, BlendState = Microsoft.Xna.Framework.Graphics.BlendState.Additive, MinColor = new Vector4(0.75f, 2.0f, 0.75f, 1.0f), MaxColor = new Vector4(0.75f, 2.0f, 0.75f, 1.0f), }); } ParticleEmitter emitter = new ParticleEmitter(); emitter.ParticleType.Value = "Sparks"; emitter.ParticlesPerSecond.Value = 200; emitter.Jitter.Value = new Vector3(0.25f); result.Add("Particles", emitter); Sound loopSound = new Sound(); result.Add("LoopSound", loopSound); loopSound.Cue.Value = "Blast Loop"; return result; }
public void PostProcess(RenderTarget2D result, RenderParameters parameters) { if (this.needBufferReallocation()) { return; } Vector3 originalCameraPosition = parameters.Camera.Position; Matrix originalViewMatrix = parameters.Camera.View; BoundingFrustum originalBoundingFrustum = parameters.Camera.BoundingFrustum; parameters.Camera.Position.Value = Vector3.Zero; Matrix newViewMatrix = originalViewMatrix; newViewMatrix.Translation = Vector3.Zero; parameters.Camera.View.Value = newViewMatrix; RasterizerState originalState = this.main.GraphicsDevice.RasterizerState; bool enableSSAO = this.allowSSAO && this.EnableSSAO; if (enableSSAO) { // Down-sample depth buffer this.downsampleEffect.CurrentTechnique = this.downsampleEffect.Techniques["DownsampleDepth"]; this.sources2[0] = this.depthBuffer; this.sources2[1] = this.normalBuffer; this.destinations2[0] = this.halfDepthBuffer; this.destinations2[1] = this.halfBuffer1; if (!this.preparePostProcess(this.sources2, this.destinations2, this.downsampleEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Compute SSAO parameters.Camera.SetParameters(this.ssaoEffect); this.ssaoEffect.CurrentTechnique = this.ssaoEffect.Techniques["SSAO"]; this.sources2[0] = this.halfDepthBuffer; this.sources2[1] = this.halfBuffer1; this.destinations1[0] = this.halfBuffer2; if (!this.preparePostProcess(this.sources2, this.destinations1, this.ssaoEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Blur this.ssaoEffect.CurrentTechnique = this.ssaoEffect.Techniques["BlurHorizontal"]; this.sources2[0] = this.halfBuffer2; this.sources2[1] = this.halfDepthBuffer; this.destinations1[0] = this.halfBuffer1; if (!this.preparePostProcess(this.sources2, this.destinations1, this.ssaoEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); this.ssaoEffect.CurrentTechnique = this.ssaoEffect.Techniques["Composite"]; this.sources2[0] = this.halfBuffer1; this.sources2[1] = this.halfDepthBuffer; this.destinations1[0] = this.halfBuffer2; if (!this.preparePostProcess(this.sources2, this.destinations1, this.ssaoEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); } // Global lighting this.destinations2[0] = this.lightingBuffer; this.destinations2[1] = this.specularBuffer; if (!this.setTargets(this.destinations2)) { return; } string globalLightTechnique = "GlobalLight"; if (this.lightingManager.EnableGlobalShadowMap && this.lightingManager.HasGlobalShadowLight) { if (parameters.IsMainRender) { if (this.lightingManager.HasGlobalShadowLightClouds) { if (this.lightingManager.EnableDetailGlobalShadowMap) { globalLightTechnique = "GlobalLightDetailShadowClouds"; } else { globalLightTechnique = "GlobalLightShadowClouds"; } } else { if (this.lightingManager.EnableDetailGlobalShadowMap) { globalLightTechnique = "GlobalLightDetailShadow"; } else { globalLightTechnique = "GlobalLightShadow"; } } } else { globalLightTechnique = "GlobalLightShadow"; } } Renderer.globalLightEffect.CurrentTechnique = Renderer.globalLightEffect.Techniques[globalLightTechnique]; parameters.Camera.SetParameters(Renderer.globalLightEffect); this.lightingManager.SetGlobalLightParameters(Renderer.globalLightEffect, parameters.Camera, originalCameraPosition); Renderer.globalLightEffect.Parameters["Materials"].SetValue(parameters.MaterialData); this.sources3[0] = this.depthBuffer; this.sources3[1] = this.normalBuffer; this.sources3[2] = this.colorBuffer1; this.destinations2[0] = this.lightingBuffer; this.destinations2[1] = this.specularBuffer; this.setTargetParameters(this.sources3, this.destinations2, Renderer.globalLightEffect); this.applyEffect(Renderer.globalLightEffect); Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Spot and point lights if (!parameters.ReverseCullOrder) { this.main.GraphicsDevice.RasterizerState = this.reverseCullState; } // HACK // Increase the far plane to prevent clipping back faces of huge lights float originalFarPlane = parameters.Camera.FarPlaneDistance; parameters.Camera.FarPlaneDistance.Value *= 4.0f; parameters.Camera.SetParameters(Renderer.pointLightEffect); parameters.Camera.SetParameters(Renderer.spotLightEffect); parameters.Camera.FarPlaneDistance.Value = originalFarPlane; // Spot lights Renderer.spotLightEffect.Parameters["Materials"].SetValue(parameters.MaterialData); this.setTargetParameters(this.sources3, this.destinations2, Renderer.spotLightEffect); for (int i = 0; i < SpotLight.All.Count; i++) { SpotLight light = SpotLight.All[i]; if (!light.Enabled || light.Suspended || light.Attenuation == 0.0f || light.Color.Value.LengthSquared() == 0.0f || !originalBoundingFrustum.Intersects(light.BoundingFrustum)) { continue; } this.lightingManager.SetSpotLightParameters(light, Renderer.spotLightEffect, originalCameraPosition); this.applyEffect(Renderer.spotLightEffect); this.drawModel(Renderer.spotLightModel); } // Point lights Renderer.pointLightEffect.Parameters["Materials"].SetValue(parameters.MaterialData); this.setTargetParameters(this.sources3, this.destinations2, Renderer.pointLightEffect); for (int i = 0; i < PointLight.All.Count; i++) { PointLight light = PointLight.All[i]; if (!light.Enabled || light.Suspended || light.Attenuation == 0.0f || light.Color.Value.LengthSquared() == 0.0f || !originalBoundingFrustum.Intersects(light.BoundingSphere)) { continue; } this.lightingManager.SetPointLightParameters(light, Renderer.pointLightEffect, originalCameraPosition); this.applyEffect(Renderer.pointLightEffect); this.drawModel(Renderer.pointLightModel); } if (!parameters.ReverseCullOrder) { this.main.GraphicsDevice.RasterizerState = originalState; } RenderTarget2D colorSource = this.colorBuffer1; RenderTarget2D colorDestination = this.hdrBuffer2; RenderTarget2D colorTemp = null; // Compositing this.compositeEffect.CurrentTechnique = this.compositeEffect.Techniques[enableSSAO ? "CompositeSSAO" : "Composite"]; this.lightingManager.SetCompositeParameters(this.compositeEffect); parameters.Camera.SetParameters(this.compositeEffect); this.compositeEffect.Parameters["Materials"].SetValue(parameters.MaterialData); RenderTarget2D[] compositeSources; if (enableSSAO) { compositeSources = this.sources4; compositeSources[3] = this.halfBuffer2; } else { compositeSources = this.sources3; } compositeSources[0] = colorSource; compositeSources[1] = this.lightingBuffer; compositeSources[2] = this.specularBuffer; this.destinations1[0] = colorDestination; if (!this.preparePostProcess(compositeSources, this.destinations1, this.compositeEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); bool enableBloom = this.allowBloom && this.EnableBloom; bool enableMotionBlur = this.MotionBlurAmount > 0.0f; #if VR if (this.main.VR) { enableMotionBlur = false; } #endif bool enableBlur = this.BlurAmount > 0.0f; // Swap the color buffers colorSource = this.hdrBuffer2; colorDestination = enableBloom || this.allowToneMapping || enableBlur || enableMotionBlur ? this.hdrBuffer1 : result; parameters.DepthBuffer = this.depthBuffer; parameters.FrameBuffer = colorSource; // Alpha components // Drawing to the color destination this.destinations1[0] = colorDestination; if (!this.setTargets(this.destinations1)) { return; } // Copy the color source to the destination this.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, originalState); this.spriteBatch.Draw(colorSource, Vector2.Zero, Color.White); this.spriteBatch.End(); parameters.Camera.Position.Value = originalCameraPosition; parameters.Camera.View.Value = originalViewMatrix; this.main.DrawAlphaComponents(parameters); this.main.DrawPostAlphaComponents(parameters); // Swap the color buffers colorTemp = colorDestination; colorDestination = colorSource; parameters.FrameBuffer = colorSource = colorTemp; // Bloom if (enableBloom) { this.bloomEffect.CurrentTechnique = this.bloomEffect.Techniques["Downsample"]; this.sources1[0] = colorSource; this.destinations1[0] = this.halfBuffer1; if (!this.preparePostProcess(this.sources1, this.destinations1, this.bloomEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); this.bloomEffect.CurrentTechnique = this.bloomEffect.Techniques["BlurHorizontal"]; this.sources1[0] = this.halfBuffer1; this.destinations1[0] = this.halfBuffer2; if (!this.preparePostProcess(this.sources1, this.destinations1, this.bloomEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); this.bloomEffect.CurrentTechnique = this.bloomEffect.Techniques["BlurVertical"]; this.sources1[0] = this.halfBuffer2; this.destinations1[0] = this.halfBuffer1; if (!this.preparePostProcess(this.sources1, this.destinations1, this.bloomEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); this.bloomEffect.CurrentTechnique = this.bloomEffect.Techniques["Composite"]; this.sources2[0] = colorSource; this.sources2[1] = this.halfBuffer1; this.destinations1[0] = enableBlur || enableMotionBlur ? this.colorBuffer2 : result; if (!this.preparePostProcess(this.sources2, this.destinations1, this.bloomEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Swap the color buffers colorDestination = this.colorBuffer1; colorSource = this.colorBuffer2; } else if (this.allowToneMapping) { this.bloomEffect.CurrentTechnique = this.bloomEffect.Techniques["ToneMapOnly"]; this.sources1[0] = colorSource; this.destinations1[0] = enableBlur || enableMotionBlur ? this.colorBuffer2 : result; if (!this.preparePostProcess(this.sources1, this.destinations1, this.bloomEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Swap the color buffers colorDestination = this.colorBuffer1; colorSource = this.colorBuffer2; } // Motion blur if (enableMotionBlur) { this.motionBlurEffect.CurrentTechnique = this.motionBlurEffect.Techniques["MotionBlur"]; parameters.Camera.SetParameters(this.motionBlurEffect); // If we just reallocated our buffers, don't use the velocity buffer from the last frame because it will be empty this.sources3[0] = colorSource; this.sources3[1] = this.normalBuffer; this.sources3[2] = this.justReallocatedBuffers ? this.normalBuffer : this.normalBufferLastFrame; this.destinations1[0] = enableBlur ? colorDestination : result; if (!this.preparePostProcess(this.sources3, this.destinations1, this.motionBlurEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); // Swap the velocity buffers RenderTarget2D temp = this.normalBufferLastFrame; this.normalBufferLastFrame = this.normalBuffer; this.normalBuffer = temp; // Swap the color buffers colorTemp = colorDestination; colorDestination = colorSource; colorSource = colorTemp; } if (enableBlur) { // Blur this.blurEffect.CurrentTechnique = this.blurEffect.Techniques["BlurHorizontal"]; parameters.Camera.SetParameters(this.blurEffect); this.sources1[0] = colorSource; this.destinations1[0] = colorDestination; if (!this.preparePostProcess(this.sources1, this.destinations1, this.blurEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); this.blurEffect.CurrentTechnique = this.blurEffect.Techniques["Composite"]; // Swap the color buffers colorTemp = colorDestination; colorDestination = colorSource; colorSource = colorTemp; this.sources1[0] = colorSource; this.destinations1[0] = result; if (!this.preparePostProcess(this.sources1, this.destinations1, this.blurEffect)) { return; } Renderer.quad.DrawAlpha(this.main.GameTime, RenderParameters.Default); } parameters.DepthBuffer = null; parameters.FrameBuffer = null; this.justReallocatedBuffers = false; }
public override void Bind(Entity result, Main main, bool creating = false) { if (ParticleSystem.Get(main, "SnakeSparks") == null) { ParticleSystem.Add(main, "SnakeSparks", new ParticleSystem.ParticleSettings { TextureName = "Particles\\splash", MaxParticles = 1000, Duration = TimeSpan.FromSeconds(1.0f), MinHorizontalVelocity = -7.0f, MaxHorizontalVelocity = 7.0f, MinVerticalVelocity = 0.0f, MaxVerticalVelocity = 7.0f, Gravity = new Vector3(0.0f, -10.0f, 0.0f), MinRotateSpeed = -2.0f, MaxRotateSpeed = 2.0f, MinStartSize = 0.3f, MaxStartSize = 0.7f, MinEndSize = 0.0f, MaxEndSize = 0.0f, BlendState = Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlend, MinColor = new Vector4(2.0f, 2.0f, 2.0f, 1.0f), MaxColor = new Vector4(2.0f, 2.0f, 2.0f, 1.0f), }); } result.CannotSuspendByDistance = true; Transform transform = result.Get<Transform>(); PointLight light = result.GetOrCreate<PointLight>("Light"); light.Color.Value = new Vector3(1.3f, 0.5f, 0.5f); light.Attenuation.Value = 10.0f; light.Shadowed.Value = false; light.Serialize = false; EnemyBase enemy = result.GetOrCreate<EnemyBase>("Base"); enemy.Add(new Binding<Matrix>(enemy.Transform, transform.Matrix)); enemy.Add(new CommandBinding(enemy.Delete, result.Delete)); Property<float> operationalRadius = result.GetOrMakeProperty<float>("OperationalRadius", true, 100.0f); light.Add(new Binding<Vector3>(light.Position, enemy.Position)); ListProperty<Map.Coordinate> path = result.GetOrMakeListProperty<Map.Coordinate>("PathCoordinates"); Property<Entity.Handle> targetAgent = result.GetOrMakeProperty<Entity.Handle>("TargetAgent"); AI ai = result.GetOrCreate<AI>("AI"); Agent agent = result.GetOrCreate<Agent>("Agent"); Map.CellState fillState = WorldFactory.StatesByName["Snake"]; Map.CellState criticalState = WorldFactory.StatesByName["InfectedCritical"]; Map.CellState temporaryState = WorldFactory.StatesByName["Temporary"]; VoxelChaseAI chase = null; result.Add(new PostInitialization { delegate() { if (chase.Map.Value.Target == null) chase.Position.Value = enemy.Position; } }); chase = result.GetOrCreate<VoxelChaseAI>("VoxelChaseAI"); chase.Filter = delegate(Map.CellState state) { int id = state.ID; if (id == fillState.ID || id == temporaryState.ID || id == 0) return VoxelChaseAI.Cell.Empty; if (state.Permanent || id == criticalState.ID) return VoxelChaseAI.Cell.Filled; return VoxelChaseAI.Cell.Penetrable; }; result.Add(new CommandBinding(chase.Delete, result.Delete)); PointLight positionLight = null; Property<float> positionLightRadius = result.GetOrMakeProperty<float>("PositionLightRadius", true, 20.0f); if (!main.EditorEnabled) { positionLight = new PointLight(); positionLight.Serialize = false; positionLight.Color.Value = new Vector3(1.5f, 0.5f, 0.5f); positionLight.Add(new Binding<float>(positionLight.Attenuation, positionLightRadius)); positionLight.Shadowed.Value = false; positionLight.Add(new Binding<bool, string>(positionLight.Enabled, x => x != "Suspended", ai.CurrentState)); positionLight.Add(new Binding<Vector3, string>(positionLight.Color, delegate(string state) { switch (state) { case "Chase": case "Crush": return new Vector3(1.5f, 0.5f, 0.5f); case "Alert": return new Vector3(1.5f, 1.5f, 0.5f); default: return new Vector3(1.0f, 1.0f, 1.0f); } }, ai.CurrentState)); result.Add("PositionLight", positionLight); ParticleEmitter emitter = result.GetOrCreate<ParticleEmitter>("Particles"); emitter.Editable = false; emitter.Serialize = false; emitter.ParticlesPerSecond.Value = 100; emitter.ParticleType.Value = "SnakeSparks"; emitter.Add(new Binding<Vector3>(emitter.Position, chase.Position)); emitter.Add(new Binding<bool, string>(emitter.Enabled, x => x != "Suspended", ai.CurrentState)); positionLight.Add(new Binding<Vector3>(positionLight.Position, chase.Position)); emitter.Add(new Binding<Vector3>(emitter.Position, chase.Position)); agent.Add(new Binding<Vector3>(agent.Position, chase.Position)); } AI.Task checkMap = new AI.Task { Action = delegate() { if (enemy.Map.Value.Target == null || !enemy.Map.Value.Target.Active) result.Delete.Execute(); }, }; AI.Task checkOperationalRadius = new AI.Task { Interval = 2.0f, Action = delegate() { bool shouldBeActive = (chase.Position.Value - main.Camera.Position).Length() < operationalRadius || (enemy.Map.Value.Target.Get<Map>().GetAbsolutePosition(enemy.BaseBoxes.First().GetCoords().First()) - main.Camera.Position).Length() < operationalRadius; if (shouldBeActive && ai.CurrentState == "Suspended") ai.CurrentState.Value = "Idle"; else if (!shouldBeActive && ai.CurrentState != "Suspended") ai.CurrentState.Value = "Suspended"; }, }; AI.Task checkTargetAgent = new AI.Task { Action = delegate() { Entity target = targetAgent.Value.Target; if (target == null || !target.Active) { targetAgent.Value = null; ai.CurrentState.Value = "Idle"; } }, }; chase.Add(new CommandBinding<Map, Map.Coordinate>(chase.Moved, delegate(Map m, Map.Coordinate c) { if (chase.Active) { if (m[c].ID != criticalState.ID) { bool regenerate = m.Empty(c); regenerate |= m.Fill(c, fillState); if (regenerate) m.Regenerate(); } Sound.PlayCue(main, "SnakeMove", chase.Position); if (path.Count > 0) { chase.Coord.Value = path[0]; path.RemoveAt(0); } } })); Property<Map.Coordinate> crushCoordinate = result.GetOrMakeProperty<Map.Coordinate>("CrushCoordinate"); ai.Setup ( new AI.State { Name = "Suspended", Tasks = new[] { checkOperationalRadius }, }, new AI.State { Name = "Idle", Tasks = new[] { checkMap, checkOperationalRadius, new AI.Task { Interval = 1.0f, Action = delegate() { Agent a = Agent.Query(chase.Position, 30.0f, 10.0f, x => x.Entity.Type == "Player"); if (a != null) ai.CurrentState.Value = "Alert"; }, }, }, }, new AI.State { Name = "Alert", Enter = delegate(AI.State previous) { chase.Enabled.Value = false; }, Exit = delegate(AI.State next) { chase.Enabled.Value = true; }, Tasks = new[] { checkMap, checkOperationalRadius, new AI.Task { Interval = 1.0f, Action = delegate() { if (ai.TimeInCurrentState > 3.0f) ai.CurrentState.Value = "Idle"; else { Agent a = Agent.Query(chase.Position, 30.0f, 20.0f, x => x.Entity.Type == "Player"); if (a != null) { targetAgent.Value = a.Entity; ai.CurrentState.Value = "Chase"; } } }, }, }, }, new AI.State { Name = "Chase", Enter = delegate(AI.State previousState) { chase.TargetActive.Value = true; }, Exit = delegate(AI.State nextState) { chase.TargetActive.Value = false; }, Tasks = new[] { checkMap, checkOperationalRadius, checkTargetAgent, new AI.Task { Interval = 0.07f, Action = delegate() { Vector3 targetPosition = targetAgent.Value.Target.Get<Agent>().Position; float targetDistance = (targetPosition - chase.Position).Length(); if (targetDistance > 50.0f || ai.TimeInCurrentState > 40.0f) // He got away ai.CurrentState.Value = "Alert"; else if (targetDistance < 5.0f) // We got 'im ai.CurrentState.Value = "Crush"; else chase.Target.Value = targetPosition; }, }, }, }, new AI.State { Name = "Crush", Enter = delegate(AI.State lastState) { // Set up cage Map.Coordinate center = enemy.Map.Value.Target.Get<Map>().GetCoordinate(targetAgent.Value.Target.Get<Agent>().Position); int radius = 1; // Bottom for (int x = center.X - radius; x <= center.X + radius; x++) { for (int z = center.Z - radius; z <= center.Z + radius; z++) path.Add(new Map.Coordinate { X = x, Y = center.Y - 4, Z = z }); } // Outer shell radius = 2; for (int y = center.Y - 3; y <= center.Y + 3; y++) { // Left for (int z = center.Z - radius; z <= center.Z + radius; z++) path.Add(new Map.Coordinate { X = center.X - radius, Y = y, Z = z }); // Right for (int z = center.Z - radius; z <= center.Z + radius; z++) path.Add(new Map.Coordinate { X = center.X + radius, Y = y, Z = z }); // Backward for (int x = center.X - radius; x <= center.X + radius; x++) path.Add(new Map.Coordinate { X = x, Y = y, Z = center.Z - radius }); // Forward for (int x = center.X - radius; x <= center.X + radius; x++) path.Add(new Map.Coordinate { X = x, Y = y, Z = center.Z + radius }); } // Top for (int x = center.X - radius; x <= center.X + radius; x++) { for (int z = center.Z - radius; z <= center.Z + radius; z++) path.Add(new Map.Coordinate { X = x, Y = center.Y + 3, Z = z }); } chase.EnablePathfinding.Value = false; chase.Speed.Value = 125.0f; crushCoordinate.Value = chase.Coord; }, Exit = delegate(AI.State nextState) { chase.EnablePathfinding.Value = true; chase.Speed.Value = 8.0f; chase.Coord.Value = chase.LastCoord.Value = crushCoordinate; path.Clear(); }, Tasks = new[] { checkMap, checkOperationalRadius, checkTargetAgent, new AI.Task { Interval = 0.01f, Action = delegate() { Agent a = targetAgent.Value.Target.Get<Agent>(); a.Health.Value -= 0.01f / 1.5f; // seconds to kill if (!a.Active) ai.CurrentState.Value = "Alert"; else { if ((a.Position - chase.Position.Value).Length() > 5.0f) // They're getting away ai.CurrentState.Value = "Chase"; } } } }, } ); this.SetMain(result, main); }
private static void explode(Main main, Voxel map, Voxel.Coord coord, Vector3 pos, int radius, float physicsRadius) { float distanceToCamera = (main.Camera.Position.Value - pos).Length(); // Kaboom Sound.PostEvent(distanceToCamera < physicsRadius * 1.5f ? AK.EVENTS.PLAY_EXPLOSION_CLOSE : AK.EVENTS.PLAY_EXPLOSION, pos); Entity lightEntity = Factory.Get <PointLightFactory>().CreateAndBind(main); lightEntity.Serialize = false; PointLight light = lightEntity.Get <PointLight>(); light.Color.Value = new Vector3(1.3f, 1.1f, 0.9f); light.Attenuation.Value = 20.0f; light.Position.Value = pos; lightEntity.Add(new Animation ( new Animation.FloatMoveTo(light.Attenuation, 0.0f, 1.0f), new Animation.Execute(light.Delete) )); main.Add(lightEntity); SmokeFactory smokeFactory = Factory.Get <SmokeFactory>(); for (int i = 0; i < 5; i++) { Entity smoke = smokeFactory.CreateAndBind(main); smoke.Get <Transform>().Position.Value = pos; main.Add(smoke); } ParticleEmitter.Emit(main, "Smoke", pos, physicsRadius * 0.4f, 250); Entity player = PlayerFactory.Instance; if (player != null && player.Active) { player.Get <CameraController>().Shake.Execute(pos, 50.0f); } const float physicsImpulse = 70.0f; const float minPlayerDamage = 0.1f; const float playerDamageMultiplier = 2.0f; // Remove the cells BlockFactory blockFactory = Factory.Get <BlockFactory>(); foreach (Voxel m in Voxel.ActiveVoxels.ToList()) { List <Voxel.Coord> removals = new List <Voxel.Coord>(); Voxel.Coord c = m.GetCoordinate(pos); Vector3 relativePos = m.GetRelativePosition(c); Quaternion quat = m.Entity.Get <Transform>().Quaternion; for (Voxel.Coord x = c.Move(Direction.NegativeX, radius - 1); x.X < c.X + radius; x.X++) { for (Voxel.Coord y = x.Move(Direction.NegativeY, radius - 1); y.Y < c.Y + radius; y.Y++) { for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius - 1); z.Z < c.Z + radius; z.Z++) { Voxel.State s = m[z]; if (s.ID == 0 || s.Permanent) { continue; } Vector3 cellPos = m.GetRelativePosition(z); if ((cellPos - relativePos).Length() < radius - 1) { removals.Add(z); if (random.NextDouble() > 0.5) { Entity block = blockFactory.CreateAndBind(main); Transform blockTransform = block.Get <Transform>(); blockTransform.Position.Value = m.GetAbsolutePosition(cellPos); blockTransform.Quaternion.Value = Quaternion.CreateFromYawPitchRoll(((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI); s.ApplyToBlock(block); main.Add(block); } } } } } if (removals.Count > 0) { m.Empty(removals); m.Regenerate(); } } // Damage the player if (player != null && player.Active) { Vector3 toPlayer = player.Get <Transform>().Position - pos; float d = toPlayer.Length(); if (d < physicsRadius) { float attenuation = 1.0f; if (d > 0) { Voxel.GlobalRaycast(pos, toPlayer / d, d, delegate(int x, Voxel.t c) { Voxel.State s = Voxel.States.All[c]; if (s.Permanent) { attenuation = 0.0f; return(true); } else if (s.Hard) { attenuation -= 0.6f; } else { attenuation -= 0.35f; } return(false); }); attenuation = Math.Max(0, attenuation); } player.Get <Agent>().Damage.Execute(attenuation * (minPlayerDamage + (1.0f - (d / physicsRadius)) * playerDamageMultiplier)); } } // Apply impulse to dynamic maps foreach (Voxel m in Voxel.ActiveVoxels) { DynamicVoxel dm = m as DynamicVoxel; if (dm == null) { continue; } Vector3 toMap = dm.Transform.Value.Translation - pos; float distanceToMap = toMap.Length(); toMap /= distanceToMap; toMap *= Math.Max(0.0f, 1.0f - (distanceToMap / physicsRadius)) * Math.Min(200.0f, dm.PhysicsEntity.Mass) * physicsImpulse; dm.PhysicsEntity.ApplyImpulse(dm.Transform.Value.Translation + new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f), toMap); } // Apply impulse to physics blocks foreach (Entity b in main.Get("Block")) { PhysicsBlock block = b.Get <PhysicsBlock>(); Vector3 fromExplosion = b.Get <Transform>().Position.Value - pos; float distance = fromExplosion.Length(); if (distance > 0.0f && distance < physicsRadius) { float blend = 1.0f - (distance / physicsRadius); block.LinearVelocity.Value += fromExplosion * blend * 10.0f / distance; block.AngularVelocity.Value += new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f) * blend; } } }
public override Entity Create(Main main) { Entity result = Factory.Get<DynamicMapFactory>().Create(main); result.Type = "Turret"; PointLight light = new PointLight(); light.Shadowed.Value = true; light.Color.Value = new Vector3(0.75f, 2.0f, 0.75f); light.Attenuation.Value = 0.0f; light.Editable = false; result.Add("Light", light); Sound blastChargeSound = new Sound(); blastChargeSound.Cue.Value = "Blast Charge"; result.Add("BlastChargeSound", blastChargeSound); Sound blastFireSound = new Sound(); blastFireSound.Cue.Value = "Blast Fire"; result.Add("BlastFireSound", blastFireSound); result.Add("Damage", new Property<float> { Editable = true, Value = 0.1f }); result.Add("VisibilityCheckInterval", new Property<float> { Editable = true, Value = 1.0f }); result.Add("BlastChargeTime", new Property<float> { Editable = true, Value = 1.25f }); result.Add("BlastInterval", new Property<float> { Editable = true, Value = 1.0f }); result.Add("PlayerPositionMemoryTime", new Property<float> { Editable = true, Value = 4.0f }); result.Add("BlastSpeed", new Property<float> { Editable = true, Value = 75.0f }); result.Add("PlayerDetectionRadius", new Property<float> { Editable = true, Value = 15.0f }); return result; }