Exemplo n.º 1
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            PointLight light = result.Get<PointLight>();
            Transform transform = result.Get<Transform>();
            Property<float> attachOffset = result.GetOrMakeProperty<float>("AttachmentOffset", true);
            light.Add(new TwoWayBinding<Vector3>(light.Position, transform.Position));

            if (result.GetOrMakeProperty<bool>("Attach", true))
                MapAttachable.MakeAttachable(result, main);

            this.SetMain(result, main);
        }
Exemplo n.º 2
0
		public static void Attach(Entity entity, Main main)
		{
			Transform transform = entity.Get<Transform>();
			Property<float> attachOffset = entity.GetOrMakeProperty<float>("AttachmentOffset", true);
			Property<Entity.Handle> map = entity.GetOrMakeProperty<Entity.Handle>("AttachedMap");
			Property<Map.Coordinate> coord = entity.GetOrMakeProperty<Map.Coordinate>("AttachedCoordinate");

			if (main.EditorEnabled)
				return;

			entity.Add(new PostInitialization
			{
				delegate()
				{
					if (map.Value.Target == null)
					{
						Map closestMap = null;
						Map.Coordinate? closestCoord = null;
						int closestDistance = 3;
						float closestFloatDistance = 3.0f;
						Vector3 target = Vector3.Transform(new Vector3(0, 0, attachOffset), transform.Matrix);
						foreach (Map m in Map.Maps)
						{
							Map.Coordinate targetCoord = m.GetCoordinate(target);
							Map.Coordinate? c = m.FindClosestFilledCell(targetCoord, closestDistance);
							if (c.HasValue)
							{
								float distance = (m.GetRelativePosition(c.Value) - m.GetRelativePosition(targetCoord)).Length();
								if (distance < closestFloatDistance)
								{
									closestFloatDistance = distance;
									closestDistance = (int)Math.Floor(distance);
									closestMap = m;
									closestCoord = c;
								}
							}
						}
						if (closestMap == null)
							entity.Delete.Execute();
						else
						{
							map.Value = closestMap.Entity;
							coord.Value = closestCoord.Value;
						}
					}
					else
					{
						map.Reset();
						coord.Reset();
					}
				}
			});
		}
Exemplo n.º 3
0
		public static void AttachEditorComponents(Entity result, Main main, Property<Vector3> color = null)
		{
			Model model = new Model();
			model.Filename.Value = "Models\\cone";
			if (color != null)
				model.Add(new Binding<Vector3>(model.Color, color));
			model.Add(new Binding<bool>(model.Enabled, result.GetOrMakeProperty<bool>("EditorSelected")));
			model.Add(new Binding<Vector3, float>(model.Scale, x => new Vector3(1.0f, 1.0f, x), result.GetOrMakeProperty<float>("AttachmentOffset", true)));
			model.Editable = false;
			model.Serialize = false;

			result.Add("EditorModel2", model);

			model.Add(new Binding<Matrix>(model.Transform, result.Get<Transform>().Matrix));
		}
Exemplo n.º 4
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            this.SetMain(result, main);
            result.CannotSuspendByDistance = true;

            Transform transform = result.Get<Transform>();

            ModelAlpha model = new ModelAlpha();
            model.Color.Value = new Vector3(1.2f, 1.0f, 0.8f);
            model.Editable = false;
            model.Serialize = false;
            model.Filename.Value = "Models\\electricity";
            model.DrawOrder.Value = 11;
            result.Add("Model", model);

            result.GetOrMakeProperty<bool>("IsMapEdge", true, true);

            PhysicsBlock block = result.Get<PhysicsBlock>();
            block.Box.BecomeKinematic();
            this.boundaries.Add(result);
            result.Add(new CommandBinding(result.Delete, delegate() { this.boundaries.Remove(result); }));
            block.Add(new TwoWayBinding<Matrix>(transform.Matrix, block.Transform));
            model.Add(new Binding<Matrix>(model.Transform, transform.Matrix));
            model.Add(new Binding<Vector3>(model.Scale, x => new Vector3(x.X * 0.5f, x.Y * 0.5f, 1.0f), block.Size));

            Property<Vector2> scaleParameter = model.GetVector2Parameter("Scale");
            model.Add(new Binding<Vector2, Vector3>(scaleParameter, x => new Vector2(x.Y, x.X), model.Scale));
            model.Add(new CommandBinding(main.ReloadedContent, delegate()
            {
                scaleParameter.Reset();
            }));
        }
Exemplo n.º 5
0
		public static void AttachEditorComponents(Entity result, ListProperty<Entity.Handle> target)
		{
			Transform transform = result.Get<Transform>();

			Property<bool> selected = result.GetOrMakeProperty<bool>("EditorSelected");

			Command<Entity> toggleEntityConnected = new Command<Entity>
			{
				Action = delegate(Entity entity)
				{
					if (target.Contains(entity))
						target.Remove(entity);
					else if (entity != result)
						target.Add(entity);
				}
			};
			result.Add("ToggleEntityConnected", toggleEntityConnected);

			LineDrawer connectionLines = new LineDrawer { Serialize = false };
			connectionLines.Add(new Binding<bool>(connectionLines.Enabled, selected));

			Color connectionLineColor = new Color(1.0f, 1.0f, 1.0f, 0.5f);
			ListBinding<LineDrawer.Line, Entity.Handle> connectionBinding = new ListBinding<LineDrawer.Line, Entity.Handle>(connectionLines.Lines, target, delegate(Entity.Handle entity)
			{
				return new LineDrawer.Line
				{
					A = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(transform.Position, connectionLineColor),
					B = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(entity.Target.Get<Transform>().Position, connectionLineColor)
				};
			}, x => x.Target != null && x.Target.Active);
			result.Add(new NotifyBinding(delegate() { connectionBinding.OnChanged(null); }, selected));
			result.Add(new NotifyBinding(delegate() { connectionBinding.OnChanged(null); }, () => selected, transform.Position));
			connectionLines.Add(connectionBinding);
			result.Add(connectionLines);
		}
Exemplo n.º 6
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            if (result.GetOrMakeProperty<bool>("Attach", true))
                MapAttachable.MakeAttachable(result, main);

            this.SetMain(result, main);

            if (main.EditorEnabled)
            {
                result.Add("Spawn Here", new Command
                {
                    Action = delegate()
                    {
                        ((GameMain)main).StartSpawnPoint.Value = result.ID;
                        Editor editor = main.Get("Editor").First().Get<Editor>();
                        if (editor.NeedsSave)
                            editor.Save.Execute();
                        main.EditorEnabled.Value = false;
                        IO.MapLoader.Load(main, null, main.MapFile);
                    },
                    ShowInEditor = true,
                });
            }

            Transform transform = result.Get<Transform>();

            PlayerSpawn spawn = result.Get<PlayerSpawn>();
            spawn.Add(new TwoWayBinding<Vector3>(transform.Position, spawn.Position));
            spawn.Add(new Binding<float, Vector3>(spawn.Rotation, x => ((float)Math.PI * -0.5f) - (float)Math.Atan2(x.Z, x.X), transform.Forward));

            PlayerTrigger trigger = result.Get<PlayerTrigger>();
            trigger.Enabled.Editable = true;
            trigger.Add(new TwoWayBinding<Vector3>(transform.Position, trigger.Position));
            trigger.Add(new CommandBinding<Entity>(trigger.PlayerEntered, delegate(Entity player) { spawn.Activate.Execute(); }));
        }
Exemplo n.º 7
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            result.CannotSuspend = true;

            Script script = result.Get<Script>();

            Property<bool> executeOnLoad = result.GetProperty<bool>("ExecuteOnLoad");
            if (executeOnLoad && !main.EditorEnabled)
            {
                result.Add("Executor", new PostInitialization
                {
                    delegate()
                    {
                        if (executeOnLoad)
                            script.Execute.Execute();
                    }
                });
            }

            Property<bool> deleteOnExecute = result.GetOrMakeProperty<bool>("DeleteOnExecute", true, false);
            if (deleteOnExecute)
                result.Add(new CommandBinding(script.Execute, result.Delete));

            this.SetMain(result, main);
        }
Exemplo n.º 8
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            Transform transform = result.GetOrCreate<Transform>("Transform");
            PhysicsBlock physics = result.GetOrCreate<PhysicsBlock>();
            physics.Size.Value = Vector3.One;
            physics.Editable = false;
            ModelInstance model = result.GetOrCreate<ModelInstance>();
            model.Editable = false;

            physics.Add(new TwoWayBinding<Matrix>(transform.Matrix, physics.Transform));

            Property<string> soundCue = result.GetOrMakeProperty<string>("CollisionSoundCue", false);
            soundCue.Serialize = false;

            model.Add(new Binding<Matrix>(model.Transform, transform.Matrix));

            const float volumeMultiplier = 0.1f;

            physics.Add(new CommandBinding<Collidable, ContactCollection>(physics.Collided, delegate(Collidable collidable, ContactCollection contacts)
            {
                float volume = contacts[contacts.Count - 1].NormalImpulse * volumeMultiplier;
                if (volume > 0.1f && soundCue.Value != null)
                {
                    Sound sound = Sound.PlayCue(main, soundCue, transform.Position, volume, 0.05f);
                    if (sound != null)
                        sound.GetProperty("Pitch").Value = 1.0f;
                }
            }));

            this.SetMain(result, main);

            Property<bool> valid = result.GetOrMakeProperty<bool>("Valid", false);
            valid.Serialize = false;

            Property<string> type = result.GetOrMakeProperty<string>("Type", true);
            type.Set = delegate(string value)
            {
                Map.CellState state;
                if (WorldFactory.StatesByName.TryGetValue(value, out state))
                {
                    state.ApplyToBlock(result);
                    valid.Value = true;
                }

                type.InternalValue = value;
            };
        }
Exemplo n.º 9
0
 public override void AttachEditorComponents(Entity result, Main main)
 {
     base.AttachEditorComponents(result, main);
     Model model = result.Get<Model>("Model");
     Model editorModel = result.Get<Model>("EditorModel");
     Property<bool> editorSelected = result.GetOrMakeProperty<bool>("EditorSelected", false);
     editorSelected.Serialize = false;
     editorModel.Add(new Binding<bool>(editorModel.Enabled, () => !editorSelected || !model.IsValid, editorSelected, model.IsValid));
 }
Exemplo n.º 10
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            base.Bind(result, main, creating);
            result.CannotSuspendByDistance = true;

            ModelAlpha clouds = result.Get<ModelAlpha>("Clouds");

            Property<float> height = result.GetOrMakeProperty<float>("Height", true, 1.0f);
            result.Add(new Binding<float>(clouds.GetFloatParameter("Height"), height));

            Property<Vector2> velocity = result.GetOrMakeProperty<Vector2>("Velocity", true, Vector2.One);
            result.Add(new Binding<Vector2>(clouds.GetVector2Parameter("Velocity"), x => x * (1.0f / 60.0f), velocity));

            result.Add(new CommandBinding(main.ReloadedContent, delegate()
            {
                height.Reset();
                velocity.Reset();
            }));
        }
Exemplo n.º 11
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            Transform transform = result.Get<Transform>();
            SpotLight spotLight = result.Get<SpotLight>();

            if (result.GetOrMakeProperty<bool>("Attach", true))
                MapAttachable.MakeAttachable(result, main);

            this.SetMain(result, main);

            spotLight.Add(new TwoWayBinding<Vector3>(spotLight.Position, transform.Position));
            spotLight.Add(new TwoWayBinding<Quaternion>(spotLight.Orientation, transform.Quaternion));
        }
Exemplo n.º 12
0
		public static void AttachEditorComponents(Entity result, Property<Entity.Handle> target)
		{
			Transform transform = result.Get<Transform>();

			Property<bool> selected = result.GetOrMakeProperty<bool>("EditorSelected");
			selected.Serialize = false;

			Command<Entity> toggleEntityConnected = new Command<Entity>
			{
				Action = delegate(Entity entity)
				{
					if (target.Value.Target == entity)
						target.Value = null;
					else if (entity != result)
						target.Value = entity;
				}
			};
			result.Add("ToggleEntityConnected", toggleEntityConnected);

			LineDrawer connectionLines = new LineDrawer { Serialize = false };
			connectionLines.Add(new Binding<bool>(connectionLines.Enabled, selected));

			Color connectionLineColor = new Color(1.0f, 1.0f, 1.0f, 0.5f);

			connectionLines.Add(new NotifyBinding(delegate()
			{
				connectionLines.Lines.Clear();
				Entity targetEntity = target.Value.Target;
				if (targetEntity != null)
				{
					connectionLines.Lines.Add
					(
						new LineDrawer.Line
						{
							A = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(transform.Position, connectionLineColor),
							B = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(targetEntity.Get<Transform>().Position, connectionLineColor)
						}
					);
				}
			}, transform.Position, target, selected));

			result.Add(connectionLines);
		}
Exemplo n.º 13
0
		public override void Bind(Entity result, Main main, bool creating = false)
		{
			this.InternalBind(result, main, creating, null, true);
			if (result.GetOrMakeProperty<bool>("Attached", true))
				MapAttachable.MakeAttachable(result, main);

			Property<Entity.Handle> target = result.GetOrMakeProperty<Entity.Handle>("Target");

			Map map = result.Get<Map>();

			Property<float> intervalMultiplier = result.GetOrMakeProperty<float>("IntervalMultiplier", true, 1.0f);

			ListProperty<CoordinateEntry> coords = result.GetOrMakeListProperty<CoordinateEntry>("Coordinates");

			Property<int> index = result.GetOrMakeProperty<int>("FillIndex");

			Action populateCoords = delegate()
			{
				if (coords.Count == 0)
				{
					Entity targetEntity = target.Value.Target;
					if (targetEntity != null && targetEntity.Active)
					{
						Map m = targetEntity.Get<Map>();
						foreach (CoordinateEntry e in map.Chunks.SelectMany(c => c.Boxes.SelectMany(x => x.GetCoords())).Select(delegate(Map.Coordinate y)
						{
							Map.Coordinate z = m.GetCoordinate(map.GetAbsolutePosition(y));
							z.Data = y.Data;
							return new CoordinateEntry { Coord = z, };
						}))
							coords.Add(e);
					}
				}
			};

			if (main.EditorEnabled)
				coords.Clear();
			else
				result.Add(new PostInitialization { populateCoords });

			Property<float> blockLifetime = result.GetOrMakeProperty<float>("BlockLifetime", true, 0.25f);

			float intervalTimer = 0.0f;
			Updater update = new Updater
			{
				delegate(float dt)
				{
					intervalTimer += dt;
					Entity targetEntity = target.Value.Target;
					if (targetEntity != null && targetEntity.Active && index < coords.Count)
					{
						float interval = 0.03f * intervalMultiplier;
						while (intervalTimer > interval && index < coords.Count)
						{
							EffectBlockFactory factory = Factory.Get<EffectBlockFactory>();
							Map m = targetEntity.Get<Map>();
							
							CoordinateEntry entry = coords[index];
							Entity block = factory.CreateAndBind(main);
							entry.Coord.Data.ApplyToEffectBlock(block.Get<ModelInstance>());
							block.GetProperty<bool>("CheckAdjacent").Value = false;
							block.GetProperty<Vector3>("Offset").Value = m.GetRelativePosition(entry.Coord);
							block.GetProperty<bool>("Scale").Value = true;

							block.GetProperty<Vector3>("StartPosition").Value = entry.Position + new Vector3(8.0f, 20.0f, 8.0f) * blockLifetime.Value;
							block.GetProperty<Matrix>("StartOrientation").Value = Matrix.CreateRotationX(0.15f * index) * Matrix.CreateRotationY(0.15f * index);

							block.GetProperty<float>("TotalLifetime").Value = blockLifetime;
							factory.Setup(block, targetEntity, entry.Coord, entry.Coord.Data.ID);
							main.Add(block);

							index.Value++;
							intervalTimer -= interval;
						}
					}
					else
						result.Delete.Execute();
				}
			};
			update.Enabled.Value = index > 0;
			result.Add("Update", update);

			Action fill = delegate()
			{
				if (index > 0 || update.Enabled)
					return; // We're already filling

				Entity targetEntity = target.Value.Target;
				if (targetEntity != null && targetEntity.Active)
				{
					populateCoords();
					Map m = targetEntity.Get<Map>();
					Vector3 focusPoint = main.Camera.Position;
					foreach (CoordinateEntry entry in coords)
					{
						entry.Position = m.GetAbsolutePosition(entry.Coord);
						entry.Distance = (focusPoint - entry.Position).LengthSquared();
					}

					List<CoordinateEntry> coordList = coords.ToList();
					coords.Clear();
					coordList.Sort(new LambdaComparer<CoordinateEntry>((x, y) => x.Distance.CompareTo(y.Distance)));
					foreach (CoordinateEntry e in coordList)
						coords.Add(e);

					update.Enabled.Value = true;
				}
			};

			result.Add("Fill", new Command
			{
				Action = fill
			});

			result.Add("Trigger", new Command<Entity>
			{
				Action = delegate(Entity p)
				{
					fill();
				}
			});
		}
Exemplo n.º 14
0
		public override void AttachEditorComponents(Entity result, Main main)
		{
			base.AttachEditorComponents(result, main);

			MapAttachable.AttachEditorComponents(result, main, result.Get<Model>().Color);

			EntityConnectable.AttachEditorComponents(result, result.GetOrMakeProperty<Entity.Handle>("Target"));
		}
Exemplo n.º 15
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            result.CannotSuspend = true;

            result.Add(new TwoWayBinding<string>(result.GetProperty<string>("LightRampTexture"), main.Renderer.LightRampTexture));
            result.Add(new TwoWayBinding<string>(result.GetOrMakeProperty<string>("EnvironmentMap", true, "Maps\\env0"), main.Renderer.EnvironmentMap));
            result.Add(new TwoWayBinding<Vector3>(result.GetOrMakeProperty<Vector3>("EnvironmentColor", true, Vector3.One), main.Renderer.EnvironmentColor));
            result.Add(new TwoWayBinding<Color>(result.GetProperty<Color>("BackgroundColor"), main.Renderer.BackgroundColor));
            result.Add(new TwoWayBinding<float>(result.GetProperty<float>("FarPlaneDistance"), main.Camera.FarPlaneDistance));

            WorldFactory.AddState(result.GetListProperty<Map.CellState>("AdditionalMaterials").ToArray());
            result.Add(new CommandBinding(result.Delete, delegate()
            {
                WorldFactory.RemoveState(result.GetListProperty<Map.CellState>("AdditionalMaterials").ToArray());
            }));

            // Zone management
            Zone currentZone = null;

            result.Add(new CommandBinding<Entity>(main.EntityAdded, delegate(Entity e)
            {
                if (!e.CannotSuspend)
                    processEntity(e, currentZone, getActiveBoundingBoxes(main.Camera, currentZone), main.Camera.Position, main.Camera.FarPlaneDistance);
            }));

            IEnumerable<NonAxisAlignedBoundingBox> boxes = getActiveBoundingBoxes(main.Camera, currentZone);
            Vector3 cameraPosition = main.Camera.Position;
            float suspendDistance = main.Camera.FarPlaneDistance;
            foreach (Entity e in main.Entities)
            {
                if (!e.CannotSuspend)
                    processEntity(e, currentZone, boxes, cameraPosition, suspendDistance);
            }

            result.Add("ProcessMap", new Command<Map>
            {
                Action = delegate(Map map)
                {
                    processMap(map, boxes);
                }
            });

            Property<float> reverbAmount = result.GetProperty<float>("ReverbAmount");
            Property<float> reverbSize = result.GetProperty<float>("ReverbSize");

            Sound.ReverbSettings(main, reverbAmount, reverbSize);

            Vector3 lastUpdatedCameraPosition = new Vector3(float.MinValue);
            bool lastFrameUpdated = false;

            Action<Zone> updateZones = delegate(Zone newZone)
            {
                currentZone = newZone;

                if (newZone != null)
                    Sound.ReverbSettings(main, newZone.ReverbAmount, newZone.ReverbSize);
                else
                    Sound.ReverbSettings(main, reverbAmount, reverbSize);

                boxes = getActiveBoundingBoxes(main.Camera, newZone);
                cameraPosition = main.Camera.Position;
                suspendDistance = main.Camera.FarPlaneDistance;
                foreach (Entity e in main.Entities)
                {
                    if (!e.CannotSuspend)
                        processEntity(e, newZone, boxes, cameraPosition, suspendDistance);
                }

                lastUpdatedCameraPosition = main.Camera.Position;
            };

            result.Add("UpdateZones", new Command
            {
                Action = delegate() { updateZones(Zone.Get(main.Camera.Position)); },
            });

            Updater update = new Updater
            {
                delegate(float dt)
                {
                    // Update every other frame
                    if (lastFrameUpdated)
                    {
                        lastFrameUpdated = false;
                        return;
                    }
                    lastFrameUpdated = true;

                    Zone newZone = Zone.Get(main.Camera.Position);

                    if (newZone != currentZone || (newZone == null && (main.Camera.Position - lastUpdatedCameraPosition).Length() > 10.0f))
                        updateZones(newZone);
                }
            };
            update.EnabledInEditMode.Value = true;
            result.Add(update);

            this.SetMain(result, main);
            WorldFactory.instance = result;
        }
Exemplo n.º 16
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            Property<float> maxForce = result.GetOrMakeProperty<float>("MaxForce", true, 150.0f);
            Property<float> damping = result.GetOrMakeProperty<float>("Damping", true, 1.5f);
            Property<float> stiffness = result.GetOrMakeProperty<float>("Stiffness", true, 15.0f);

            NoRotationJoint joint = null;
            EntityMover mover = null;

            Action setMaxForce = delegate()
            {
                if (mover != null)
                {
                    if (maxForce > 0.001f)
                        mover.LinearMotor.Settings.MaximumForce = maxForce * result.Get<DynamicMap>().PhysicsEntity.Mass;
                    else
                        mover.LinearMotor.Settings.MaximumForce = float.MaxValue;
                }
            };
            result.Add(new NotifyBinding(setMaxForce, maxForce));
            result.Add(new CommandBinding(result.Get<DynamicMap>().PhysicsUpdated, setMaxForce));

            Action setDamping = delegate()
            {
                if (mover != null && damping != 0)
                    mover.LinearMotor.Settings.Servo.SpringSettings.DampingConstant = damping;
            };
            result.Add(new NotifyBinding(setDamping, damping));

            Action setStiffness = delegate()
            {
                if (mover != null && stiffness != 0)
                    mover.LinearMotor.Settings.Servo.SpringSettings.StiffnessConstant = stiffness * result.Get<DynamicMap>().PhysicsEntity.Mass;
            };
            result.Add(new NotifyBinding(setStiffness, stiffness));
            result.Add(new CommandBinding(result.Get<DynamicMap>().PhysicsUpdated, setStiffness));

            Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint = delegate(BEPUphysics.Entities.Entity entity1, BEPUphysics.Entities.Entity entity2, Vector3 pos, Vector3 direction, Vector3 anchor)
            {
                joint = new NoRotationJoint(entity1, entity2);
                if (mover != null && mover.Space != null)
                    main.Space.Remove(mover);
                mover = new EntityMover(entity1);
                main.Space.Add(mover);
                setMaxForce();
                setDamping();
                setStiffness();
                return joint;
            };

            JointFactory.Bind(result, main, createJoint, true, creating);

            result.Add(new CommandBinding(result.Get<DynamicMap>().OnSuspended, delegate()
            {
                if (mover != null && mover.Space != null)
                    main.Space.Remove(mover);
            }));

            result.Add(new CommandBinding(result.Get<DynamicMap>().OnResumed, delegate()
            {
                if (mover != null && mover.Space == null)
                    main.Space.Add(mover);
            }));

            result.Add(new CommandBinding(result.Delete, delegate()
            {
                if (mover != null && mover.Space != null)
                {
                    main.Space.Remove(mover);
                    mover = null;
                }
            }));

            Property<Entity.Handle> parent = result.GetOrMakeProperty<Entity.Handle>("Parent");
            Property<Map.Coordinate> coord = result.GetOrMakeProperty<Map.Coordinate>("Coord");
            Updater updater = null;
            updater = new Updater
            {
                delegate(float dt)
                {
                    Entity parentEntity = parent.Value.Target;
                    if (parentEntity != null && parentEntity.Active)
                        mover.TargetPosition = parentEntity.Get<Map>().GetAbsolutePosition(coord) + new Vector3(0, -0.01f, 0);
                    else
                    {
                        updater.Delete.Execute();
                        parent.Value = null;
                        if (mover != null && mover.Space != null)
                        {
                            main.Space.Remove(mover);
                            mover = null;
                        }
                    }
                }
            };
            result.Add(updater);
        }
Exemplo n.º 17
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            Property<Direction> dir = result.GetOrMakeProperty<Direction>("Direction", true);
            Property<float> minimum = result.GetOrMakeProperty<float>("Minimum", true);
            Property<float> maximum = result.GetOrMakeProperty<float>("Maximum", true);
            Property<bool> locked = result.GetOrMakeProperty<bool>("Locked", true);
            Property<bool> servo = result.GetOrMakeProperty<bool>("Servo", true, true);
            Property<float> speed = result.GetOrMakeProperty<float>("Speed", true, 5);
            Property<float> goal = result.GetOrMakeProperty<float>("Goal", true);

            RevoluteJoint joint = null;

            Action setLimits = delegate()
            {
                if (joint != null)
                {
                    float min = minimum, max = maximum;
                    if (max > min)
                    {
                        joint.Limit.IsActive = true;
                        joint.Limit.MinimumAngle = minimum;
                        joint.Limit.MaximumAngle = maximum;
                    }
                    else
                        joint.Limit.IsActive = false;
                }
            };
            result.Add(new NotifyBinding(setLimits, minimum, maximum));

            Action setSpeed = delegate()
            {
                if (joint != null)
                {
                    joint.Motor.Settings.Servo.BaseCorrectiveSpeed = joint.Motor.Settings.Servo.MaxCorrectiveVelocity = speed;
                    joint.Motor.Settings.VelocityMotor.GoalVelocity = speed;
                }
            };
            result.Add(new NotifyBinding(setSpeed, speed));

            Action setGoal = delegate()
            {
                if (joint != null)
                    joint.Motor.Settings.Servo.Goal = goal;
            };
            result.Add(new NotifyBinding(setGoal, goal));

            Action setLocked = delegate()
            {
                if (joint != null)
                    joint.Motor.IsActive = locked;
            };
            result.Add(new NotifyBinding(setLocked, locked));

            DynamicMap map = result.Get<DynamicMap>();

            Action setServo = delegate()
            {
                if (joint != null)
                    joint.Motor.Settings.Mode = servo ? MotorMode.Servomechanism : MotorMode.VelocityMotor;
            };
            result.Add(new NotifyBinding(setServo, servo));

            Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint = delegate(BEPUphysics.Entities.Entity entity1, BEPUphysics.Entities.Entity entity2, Vector3 pos, Vector3 direction, Vector3 anchor)
            {
                joint = new RevoluteJoint(entity1, entity2, pos, direction);
                float multiplier = Math.Max(1.0f, map.PhysicsEntity.Mass);
                joint.AngularJoint.SpringSettings.StiffnessConstant *= multiplier;
                joint.Limit.SpringSettings.StiffnessConstant *= multiplier;
                joint.Motor.Settings.Mode = MotorMode.Servomechanism;
                setLimits();
                setLocked();
                setSpeed();
                setServo();
                setGoal();
                return joint;
            };

            JointFactory.Bind(result, main, createJoint, true, creating);

            result.Add("On", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                        servo.Value = false;
                },
            });

            result.Add("Off", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                    {
                        BEPUphysics.Constraints.JointBasis2D basis = joint.Motor.Basis;
                        basis.RotationMatrix = joint.Motor.ConnectionA.OrientationMatrix;

                        Vector3 localTestAxis = joint.Motor.LocalTestAxis;
                        Vector3 worldTestAxis;
                        BEPUutilities.Matrix3x3 orientationMatrix = joint.Motor.ConnectionB.OrientationMatrix;
                        BEPUutilities.Matrix3x3.Transform(ref localTestAxis, ref orientationMatrix, out worldTestAxis);

                        float y, x;
                        Vector3 yAxis = Vector3.Cross(basis.PrimaryAxis, basis.XAxis);
                        Vector3.Dot(ref worldTestAxis, ref yAxis, out y);
                        x = Vector3.Dot(worldTestAxis, basis.XAxis);
                        goal.Value = (float)Math.Atan2(y, x);
                        servo.Value = true;
                    }
                },
            });

            result.Add("Forward", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                        joint.Motor.Settings.Servo.Goal = maximum;
                },
            });

            result.Add("Backward", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                        joint.Motor.Settings.Servo.Goal = minimum;
                },
            });

            Command hitMax = new Command();
            result.Add("HitMax", hitMax);
            Command hitMin = new Command();
            result.Add("HitMin", hitMin);

            bool lastLimitExceeded = false;
            result.Add(new Updater
            {
                delegate(float dt)
                {
                    if (joint != null)
                    {
                        bool limitExceeded = joint.Limit.IsLimitExceeded;
                        if (limitExceeded && !lastLimitExceeded)
                        {
                            if (joint.Limit.Error.X > 0)
                                hitMin.Execute();
                            else
                                hitMax.Execute();
                        }
                        lastLimitExceeded = limitExceeded;
                    }
                }
            });
        }
Exemplo n.º 18
0
        public static void MakeAttachable(Entity entity, Main main)
        {
            Transform transform = entity.Get<Transform>();
            Property<float> attachOffset = entity.GetOrMakeProperty<float>("AttachmentOffset", true);
            Property<Entity.Handle> map = entity.GetOrMakeProperty<Entity.Handle>("AttachedMap");
            Property<Map.Coordinate> coord = entity.GetOrMakeProperty<Map.Coordinate>("AttachedCoordinate");

            if (main.EditorEnabled)
                return;

            Binding<Matrix> attachmentBinding = null;
            CommandBinding deleteBinding = null;
            CommandBinding<IEnumerable<Map.Coordinate>, Map> cellEmptiedBinding = null;

            entity.Add(new NotifyBinding(delegate()
            {
                if (attachmentBinding != null)
                {
                    entity.Remove(attachmentBinding);
                    entity.Remove(deleteBinding);
                    entity.Remove(cellEmptiedBinding);
                }

                Map m = map.Value.Target.Get<Map>();
                coord.Value = m.GetCoordinate(Vector3.Transform(new Vector3(0, 0, attachOffset), transform.Matrix));

                Matrix offset = transform.Matrix * Matrix.Invert(Matrix.CreateTranslation(m.Offset) * m.Transform);

                attachmentBinding = new Binding<Matrix>(transform.Matrix, () => offset * Matrix.CreateTranslation(m.Offset) * m.Transform, m.Transform, m.Offset);
                entity.Add(attachmentBinding);

                deleteBinding = new CommandBinding(m.Delete, entity.Delete);
                entity.Add(deleteBinding);

                cellEmptiedBinding = new CommandBinding<IEnumerable<Map.Coordinate>, Map>(m.CellsEmptied, delegate(IEnumerable<Map.Coordinate> coords, Map newMap)
                {
                    foreach (Map.Coordinate c in coords)
                    {
                        if (c.Equivalent(coord))
                        {
                            if (newMap == null)
                                entity.Delete.Execute();
                            else
                                map.Value = newMap.Entity;
                            break;
                        }
                    }
                });
                entity.Add(cellEmptiedBinding);
            }, map));

            entity.Add(new PostInitialization
            {
                delegate()
                {
                    if (map.Value.Target == null)
                    {
                        Map closestMap = null;
                        int closestDistance = 3;
                        float closestFloatDistance = 3.0f;
                        Vector3 target = Vector3.Transform(new Vector3(0, 0, attachOffset), transform.Matrix);
                        foreach (Map m in Map.Maps)
                        {
                            Map.Coordinate targetCoord = m.GetCoordinate(target);
                            Map.Coordinate? c = m.FindClosestFilledCell(targetCoord, closestDistance);
                            if (c.HasValue)
                            {
                                float distance = (m.GetRelativePosition(c.Value) - m.GetRelativePosition(targetCoord)).Length();
                                if (distance < closestFloatDistance)
                                {
                                    closestFloatDistance = distance;
                                    closestDistance = (int)Math.Floor(distance);
                                    closestMap = m;
                                }
                            }
                        }
                        if (closestMap == null)
                            entity.Delete.Execute();
                        else
                            map.Value = closestMap.Entity;
                    }
                    else
                        map.Reset();
                }
            });
        }
Exemplo n.º 19
0
		public static void Attach(Main main, Entity result, AnimatedModel model, FPSInput input, Phone phone, Property<bool> enableWalking, Property<bool> enableMoves)
		{
			Property<bool> phoneActive = result.GetOrMakeProperty<bool>("PhoneActive");
			Property<bool> noteActive = result.GetOrMakeProperty<bool>("NoteActive");

			UIRenderer phoneUi = result.GetOrCreate<UIRenderer>("PhoneUI");

			Property<Entity.Handle> signalTower = result.GetOrMakeProperty<Entity.Handle>("SignalTower");

			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;

			Model phoneModel = result.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 = result.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 = result.GetOrCreate<PointLight>("PhoneLight");
			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));

			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<Color, string, float, Container> makeButton = delegate(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;
				Color highlightColor = new Color(color.ToVector4() + new Vector4(0.2f, 0.2f, 0.2f, 0.0f));
				bg.Add(new Binding<Color, bool>(bg.Tint, x => x ? highlightColor : color, bg.Highlighted));

				TextElement msg = new TextElement();
				msg.Name.Value = "Text";
				msg.FontFile.Value = "Font";
				msg.Text.Value = text;
				msg.WrapWidth.Value = width;
				bg.Children.Add(msg);
				return bg;
			};

			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;
			};

			Color incomingColor = new Color(0.0f, 0.0f, 0.0f, 1.0f);
			Color outgoingColor = new Color(0.0f, 0.175f, 0.35f, 1.0f);

			Container topBarContainer = new Container();
			topBarContainer.ResizeHorizontal.Value = false;
			topBarContainer.Size.Value = new Vector2(phoneUi.RenderTargetSize.Value.X, 0.0f);
			topBarContainer.Tint.Value = new Color(0.15f, 0.15f, 0.15f, 1.0f);
			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 = "Font";
			noService.Text.Value = "\\no service";
			phoneTopBar.Children.Add(noService);

			signalIcon.Add(new Binding<bool, Entity.Handle>(signalIcon.Visible, x => x.Target != null && x.Target.Active, signalTower));
			noService.Add(new Binding<bool, Entity.Handle>(noService.Visible, x => x.Target == null || !x.Target.Active, signalTower));

			ListContainer phoneLayout = new ListContainer();
			phoneLayout.Spacing.Value = padding;
			phoneLayout.Orientation.Value = ListContainer.ListOrientation.Vertical;
			phoneLayout.Add(new Binding<Vector2>(phoneLayout.Position, x => new Vector2(padding, x.Y), topBarContainer.Size));
			phoneLayout.Add(new Binding<Vector2>(phoneLayout.Size, () => new Vector2(phoneUi.RenderTargetSize.Value.X - padding * 2.0f, phoneUi.RenderTargetSize.Value.Y - padding - topBarContainer.Size.Value.Y), phoneUi.RenderTargetSize, topBarContainer.Size));
			phoneUi.Root.Children.Add(phoneLayout);

			Container composeButton = makeButton(new Color(0.5f, 0.0f, 0.0f, 1.0f), "\\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(phoneLayout.Size.Value.X, phoneLayout.Size.Value.Y - phoneLayout.Spacing.Value - composeAlign.ScaledSize.Value.Y), phoneLayout.Size, phoneLayout.Spacing, composeAlign.ScaledSize));

			phoneLayout.Children.Add(phoneScroll);
			phoneLayout.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.Position.Value + new Vector2(composeAlign.ScaledSize.Value.X + padding, padding * 3.0f), 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<Point>(composeButton.MouseLeftUp, delegate(Point p)
			{
				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;
				}
			}));

			Action scrollToBottom = delegate()
			{
				// HACK
				main.AddComponent(new Animation
				(
					new Animation.Delay(0.01f),
					new Animation.Execute(delegate()
					{
						phoneScroll.ScrollToBottom();
					})
				));
			};

			// Note

			UIRenderer noteUi = result.GetOrCreate<UIRenderer>("NoteUI");

			const float noteWidth = 400.0f;
			const float noteScale = 0.0009f;

			noteUi.RenderTargetBackground.Value = new Microsoft.Xna.Framework.Color(1.0f, 0.95f, 0.9f);
			noteUi.RenderTargetSize.Value = new Point((int)noteWidth, (int)(noteWidth * 1.29f)); // 8.5x11 aspect ratio
			noteUi.Serialize = false;
			noteUi.Enabled.Value = false;

			Model noteModel = result.GetOrCreate<Model>("Note");
			noteModel.Filename.Value = "Models\\plane";
			noteModel.EffectFile.Value = "Effects\\Default";
			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.Scale.Value = new Vector3(1.0f, (float)noteUi.RenderTargetSize.Value.Y * noteScale, (float)noteUi.RenderTargetSize.Value.X * noteScale);
			noteModel.Serialize = false;
			noteModel.Enabled.Value = false;
			Property<Entity.Handle> note = result.GetOrMakeProperty<Entity.Handle>("Note");

			Container togglePhoneMessage = null;

			result.Add(new NotifyBinding(delegate()
			{
				bool hasNoteOrSignalTower = (note.Value.Target != null && note.Value.Target.Active)
					|| (signalTower.Value.Target != null && signalTower.Value.Target.Active);

				if (togglePhoneMessage == null && hasNoteOrSignalTower)
					togglePhoneMessage = ((GameMain)main).Menu.ShowMessage(result, "[{{TogglePhone}}]");
				else if (togglePhoneMessage != null && !hasNoteOrSignalTower && !phoneActive && !noteActive)
				{
					((GameMain)main).Menu.HideMessage(result, togglePhoneMessage);
					togglePhoneMessage = null;
				}
			}, note, signalTower));

			result.Add(new CommandBinding(result.Delete, delegate()
			{
				((GameMain)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 = "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

			Action<bool> showNote = delegate(bool show)
			{
				noteActive.Value = show;
				input.EnableLook.Value = input.EnableMouse.Value = !noteActive;
				main.IsMouseVisible.Value = false;
				enableWalking.Value = enableMoves.Value = !noteActive;
				noteModel.Enabled.Value = noteActive;
				noteUi.Enabled.Value = noteActive;

				model.Stop("Phone", "Note");
				Entity noteEntity = note.Value.Target;
				if (noteEntity != null && noteEntity.Active)
				{
					if (noteActive)
					{
						noteUiImage.Image.Value = noteEntity.GetOrMakeProperty<string>("Image");
						noteUiText.Text.Value = noteEntity.GetOrMakeProperty<string>("Text");
						model.StartClip("Note", 6, true, AnimatedModel.DefaultBlendTime * 2.0f);
						float startRotationY = input.Mouse.Value.Y;
						// Level the player's view
						result.Add(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.Type.OutQuadratic
							)
						));
					}
					else
					{
						Property<bool> collected = noteEntity.GetOrMakeProperty<bool>("Collected");
						if (!collected)
							collected.Value = true;
					}
				}
			};

			// Toggle phone

			Container phoneTutorialMessage = null;

			Action<bool> showPhone = delegate(bool show)
			{
				if (togglePhoneMessage != null)
				{
					((GameMain)main).Menu.HideMessage(result, togglePhoneMessage);
					togglePhoneMessage = null;
				}

				if (phoneTutorialMessage != null)
				{
					((GameMain)main).Menu.HideMessage(result, phoneTutorialMessage);
					phoneTutorialMessage = null;
				}

				if (show || (phone.Schedules.Count == 0 && !phone.WaitForAnswer))
				{
					phoneActive.Value = show;
					input.EnableLook.Value = input.EnableMouse.Value = !phoneActive;
					main.IsMouseVisible.Value = phoneActive;
					enableWalking.Value = enableMoves.Value = !phoneActive;
					phoneModel.Enabled.Value = phoneActive;
					screen.Enabled.Value = phoneActive;
					phoneUi.Enabled.Value = phoneActive;
					phoneLight.Enabled.Value = phoneActive;
					answerContainer.Visible.Value = false;

					model.Stop("Phone", "Note");
					if (phoneActive)
					{
						if (!phone.TutorialShown)
						{
							phone.TutorialShown.Value = true;
							phoneTutorialMessage = ((GameMain)main).Menu.ShowMessage(result, "\\scroll for more");
						}
						phoneScroll.CheckLayout();
						scrollToBottom();

						model.StartClip("Phone", 6, true, AnimatedModel.DefaultBlendTime * 2.0f);

						// Level the player's view
						float startRotationY = input.Mouse.Value.Y;
						result.Add(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.Type.OutQuadratic
							)
						));
					}
				}
			};

			input.Bind(((GameMain)main).Settings.TogglePhone, PCInput.InputState.Up, delegate()
			{
				if (noteActive || phoneActive || phone.CanReceiveMessages)
				{
					if (!phoneActive && (noteActive || note.Value.Target != null && note.Value.Target.Active))
						showNote(!noteActive);
					else if (phone.Enabled)
						showPhone(!phoneActive);
				}
			});

			// Gamepad code for the phone

			input.Add(new CommandBinding(input.GetButtonUp(Buttons.A), () => phoneActive && composeButton.Visible, delegate()
			{
				if (answerContainer.Visible)
					answerList.Children[selectedAnswer].MouseLeftUp.Execute(new Point());
				else
					answerContainer.Visible.Value = true;
			}));

			input.Add(new CommandBinding(input.GetButtonUp(Buttons.B), () => phoneActive && answerContainer.Visible, delegate()
			{
				answerContainer.Visible.Value = false;
			}));

			Action<int> scrollPhone = delegate(int delta)
			{
				if (answerContainer.Visible)
				{
					answerList.Children[selectedAnswer].Highlighted.Value = false;
					selectedAnswer += delta;
					while (selectedAnswer < 0)
						selectedAnswer += answerList.Children.Count;
					while (selectedAnswer > answerList.Children.Count - 1)
						selectedAnswer -= answerList.Children.Count;
					answerList.Children[selectedAnswer].Highlighted.Value = true;
				}
				else
					phoneScroll.MouseScrolled.Execute(new Point(), delta * -4);
			};

			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);
			}));

			msgList.Add(new ListBinding<UIComponent, Phone.Message>
			(
				msgList.Children,
				phone.Messages,
				delegate(Phone.Message msg)
				{
					return makeAlign(makeButton(msg.Incoming ? incomingColor : outgoingColor, "\\" + (msg.Text == null ? msg.ID : msg.Text), messageWidth - padding * 2.0f), !msg.Incoming);
				}
			));

			answerList.Add(new ListBinding<UIComponent, Phone.Ans>
			(
				answerList.Children,
				phone.ActiveAnswers,
				delegate(Phone.Ans answer)
				{
					UIComponent button = makeButton(outgoingColor, "\\" + (answer.Text == null ? answer.ID : answer.Text), messageWidth - padding * 4.0f);
					button.Add(new CommandBinding<Point>(button.MouseLeftUp, delegate(Point p)
					{
						phone.Answer(answer);
						
						// Disable the signal tower
						Entity s = signalTower.Value.Target;
						if (s != null && s.Active)
							s.Get<SignalTower>().Initial.Value = null;

						scrollToBottom();
						if (togglePhoneMessage == null && phone.Schedules.Count == 0) // No more messages incoming
							togglePhoneMessage = ((GameMain)main).Menu.ShowMessage(result, "[{{TogglePhone}}]");
					}));
					return button;
				}
			));

			Action refreshComposeButtonVisibility = delegate()
			{
				bool show = phone.ActiveAnswers.Count > 0 && phone.Schedules.Count == 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();

			result.Add(new CommandBinding(phone.MessageReceived, delegate()
			{
				if (phoneActive)
					scrollToBottom();
				else
					showPhone(true);
				
				// Animate the new message
				Container lastMessage = (Container)msgList.Children[msgList.Children.Count - 1].Children[0];
				lastMessage.CheckLayout();
				Vector2 originalSize = lastMessage.Size;
				lastMessage.Size.Value = new Vector2(0, originalSize.Y);
				main.AddComponent(new Animation
				(
					new Animation.Ease(new Animation.Vector2MoveTo(lastMessage.Size, originalSize, 0.5f), Animation.Ease.Type.OutExponential)
				));

				AkSoundEngine.PostEvent("Phone_Play", result);
				if (togglePhoneMessage == null && phone.Schedules.Count == 0 && phone.ActiveAnswers.Count == 0) // No more messages incoming, and no more answers to give
					togglePhoneMessage = ((GameMain)main).Menu.ShowMessage(result, "[{{TogglePhone}}]");
			}));

			if (noteActive)
				showNote(true);
			else if (phoneActive)
				showPhone(true);
		}
Exemplo n.º 20
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            PointLight light = result.GetOrCreate<PointLight>("PointLight");
            light.Serialize = false;

            const float defaultLightAttenuation = 15.0f;
            light.Attenuation.Value = defaultLightAttenuation;

            Transform transform = result.GetOrCreate<Transform>("Transform");
            light.Add(new Binding<Vector3>(light.Position, transform.Position));

            VoxelChaseAI chase = result.GetOrCreate<VoxelChaseAI>("VoxelChaseAI");

            chase.Filter = delegate(Map.CellState state)
            {
                return state.ID == 0 ? VoxelChaseAI.Cell.Empty : VoxelChaseAI.Cell.Filled;
            };

            chase.Add(new TwoWayBinding<Vector3>(transform.Position, chase.Position));
            result.Add(new CommandBinding(chase.Delete, result.Delete));

            Sound sound = result.GetOrCreate<Sound>("LoopSound");
            sound.Serialize = false;
            sound.Cue.Value = "Orb Loop";
            sound.Is3D.Value = true;
            sound.IsPlaying.Value = true;
            sound.Add(new Binding<Vector3>(sound.Position, chase.Position));
            Property<float> volume = sound.GetProperty("Volume");
            Property<float> pitch = sound.GetProperty("Pitch");

            const float defaultVolume = 0.5f;
            volume.Value = defaultVolume;

            AI ai = result.GetOrCreate<AI>();

            Model model = result.GetOrCreate<Model>();
            model.Add(new Binding<Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value = "Models\\sphere";
            model.Editable = false;
            model.Serialize = false;

            const float defaultModelScale = 0.25f;
            model.Scale.Value = new Vector3(defaultModelScale);

            model.Add(new Binding<Vector3, string>(model.Color, delegate(string state)
            {
                switch (state)
                {
                    case "Alert":
                        return new Vector3(1.5f, 1.5f, 0.5f);
                    case "Chase":
                        return new Vector3(1.5f, 0.5f, 0.5f);
                    case "Explode":
                        return new Vector3(2.0f, 1.0f, 0.5f);
                    case "Idle":
                        return new Vector3(1.0f, 1.0f, 1.0f);
                    default:
                        return new Vector3(0.0f, 0.0f, 0.0f);
                }
            }, ai.CurrentState));

            Random random = new Random();
            result.Add(new Updater
            {
                delegate(float dt)
                {
                    float source = ((float)random.NextDouble() - 0.5f) * 2.0f;
                    model.Scale.Value = new Vector3(defaultModelScale * (1.0f + (source * 0.5f)));
                    light.Attenuation.Value = defaultLightAttenuation * (1.0f + (source * 0.05f));
                }
            });

            model.Add(new Binding<bool, string>(model.Enabled, x => x != "Exploding", ai.CurrentState));

            light.Add(new Binding<Vector3>(light.Color, model.Color));

            Agent agent = result.GetOrCreate<Agent>();
            agent.Add(new Binding<Vector3>(agent.Position, chase.Position));

            Property<int> operationalRadius = result.GetOrMakeProperty<int>("OperationalRadius", true, 100);

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action = delegate()
                {
                    bool shouldBeActive = (chase.Position.Value - main.Camera.Position).Length() < operationalRadius;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                        ai.CurrentState.Value = "Idle";
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                        ai.CurrentState.Value = "Suspended";
                },
            };

            const float sightDistance = 30.0f;
            const float hearingDistance = 15.0f;

            ai.Add(new AI.State
            {
                Name = "Idle",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 3.0f;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action = delegate()
                        {
                            Agent a = Agent.Query(chase.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                                ai.CurrentState.Value = "Alert";
                        },
                    },
                },
            });

            Property<Entity.Handle> targetAgent = result.GetOrMakeProperty<Entity.Handle>("TargetAgent");

            ai.Add(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[]
                {
                    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, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    targetAgent.Value = a.Entity;
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            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";
                    }
                },
            };

            ai.Add(new AI.State
            {
                Name = "Chase",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 10.0f;
                    chase.TargetActive.Value = true;
                },
                Exit = delegate(AI.State next)
                {
                    chase.TargetActive.Value = false;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            Entity target = targetAgent.Value.Target;
                            Vector3 targetPosition = target.Get<Transform>().Position;
                            chase.Target.Value = targetPosition;
                            if ((targetPosition - chase.Position).Length() < 10.0f)
                                ai.CurrentState.Value = "Explode";
                        }
                    }
                },
            });

            ListProperty<Map.Coordinate> coordQueue = result.GetOrMakeListProperty<Map.Coordinate>("CoordQueue");

            Property<Map.Coordinate> explosionOriginalCoord = result.GetOrMakeProperty<Map.Coordinate>("ExplosionOriginalCoord");

            ai.Add(new AI.State
            {
                Name = "Explode",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 5.0f;
                    coordQueue.Clear();
                    chase.EnablePathfinding.Value = false;

                    Map map = chase.Map.Value.Target.Get<Map>();

                    Map.Coordinate coord = chase.Coord.Value;

                    Direction toSupport = Direction.None;

                    foreach (Direction dir in DirectionExtensions.Directions)
                    {
                        if (map[coord.Move(dir)].ID != 0)
                        {
                            toSupport = dir;
                            break;
                        }
                    }

                    if (toSupport == Direction.None)
                    {
                        // Try again with the last coord
                        coord = chase.LastCoord.Value;
                        foreach (Direction dir in DirectionExtensions.Directions)
                        {
                            if (map[coord.Move(dir)].ID != 0)
                            {
                                toSupport = dir;
                                break;
                            }
                        }
                        if (toSupport == Direction.None)
                        {
                            ai.CurrentState.Value = "Idle";
                            return;
                        }
                    }

                    Direction up = toSupport.GetReverse();

                    explosionOriginalCoord.Value = coord;

                    Direction right;
                    if (up.IsParallel(Direction.PositiveX))
                        right = Direction.PositiveZ;
                    else
                        right = Direction.PositiveX;
                    Direction forward = up.Cross(right);

                    for (Map.Coordinate y = coord.Clone(); y.GetComponent(up) < coord.GetComponent(up) + 3; y = y.Move(up))
                    {
                        for (Map.Coordinate x = y.Clone(); x.GetComponent(right) < coord.GetComponent(right) + 2; x = x.Move(right))
                        {
                            for (Map.Coordinate z = x.Clone(); z.GetComponent(forward) < coord.GetComponent(forward) + 2; z = z.Move(forward))
                                coordQueue.Add(z);
                        }
                    }
                },
                Exit = delegate(AI.State next)
                {
                    coordQueue.Clear();
                    chase.EnablePathfinding.Value = true;
                    chase.LastCoord.Value = chase.Coord.Value = explosionOriginalCoord;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            volume.Value = MathHelper.Lerp(defaultVolume, 1.0f, ai.TimeInCurrentState.Value / 2.0f);
                            pitch.Value = MathHelper.Lerp(0.0f, 0.5f, ai.TimeInCurrentState.Value / 2.0f);
                            if (coordQueue.Count == 0)
                            {
                                // Explode
                                ai.CurrentState.Value = "Exploding";
                            }
                        },
                    },
                },
            });

            Property<bool> exploded = result.GetOrMakeProperty<bool>("Exploded");

            ai.Add(new AI.State
            {
                Name = "Exploding",
                Enter = delegate(AI.State previous)
                {
                    chase.EnablePathfinding.Value = false;
                    exploded.Value = false;
                    sound.Stop.Execute(AudioStopOptions.AsAuthored);
                },
                Exit = delegate(AI.State next)
                {
                    chase.EnablePathfinding.Value = true;
                    exploded.Value = false;
                    volume.Value = defaultVolume;
                    pitch.Value = 0.0f;
                    sound.Play.Execute();
                },
                Tasks = new[]
                {
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action = delegate()
                        {
                            const int radius = 8;

                            float timeInCurrentState = ai.TimeInCurrentState;
                            if (timeInCurrentState > 1.0f && !exploded)
                            {
                                Map map = chase.Map.Value.Target.Get<Map>();
                                Explosion.Explode(main, map, chase.Coord, radius, 18.0f);
                                exploded.Value = true;
                            }

                            if (timeInCurrentState > 2.0f)
                            {
                                Map map = chase.Map.Value.Target.Get<Map>();
                                Map.Coordinate? closestCell = map.FindClosestFilledCell(chase.Coord, radius + 1);
                                if (closestCell.HasValue)
                                {
                                    chase.Blend.Value = 0.0f;
                                    chase.Coord.Value = closestCell.Value;
                                    ai.CurrentState.Value = "Alert";
                                }
                                else
                                    result.Delete.Execute();
                            }
                        },
                    },
                },
            });

            EffectBlockFactory factory = Factory.Get<EffectBlockFactory>();
            Map.CellState snakeState = WorldFactory.StatesByName["Snake"];
            chase.Add(new CommandBinding<Map, Map.Coordinate>(chase.Moved, delegate(Map m, Map.Coordinate c)
            {
                if (chase.Active)
                {
                    if (coordQueue.Count > 0)
                    {
                        Map.Coordinate coord = chase.Coord.Value = coordQueue[0];
                        coordQueue.RemoveAt(0);

                        Entity block = factory.CreateAndBind(main);
                        snakeState.ApplyToEffectBlock(block.Get<ModelInstance>());

                        Map map = chase.Map.Value.Target.Get<Map>();

                        block.GetProperty<Vector3>("Offset").Value = map.GetRelativePosition(coord);

                        Vector3 absolutePos = map.GetAbsolutePosition(coord);

                        block.GetProperty<Vector3>("StartPosition").Value = absolutePos + new Vector3(0.05f, 0.1f, 0.05f);
                        block.GetProperty<Matrix>("StartOrientation").Value = Matrix.CreateRotationX(0.15f) * Matrix.CreateRotationY(0.15f);
                        block.GetProperty<float>("TotalLifetime").Value = 0.05f;
                        factory.Setup(block, chase.Map.Value.Target, coord, snakeState.ID);
                        main.Add(block);
                    }
                }
            }));

            this.SetMain(result, main);
        }
Exemplo n.º 21
0
        public override void AttachEditorComponents(Entity result, Main main)
        {
            base.AttachEditorComponents(result, main);

            result.Add(new Binding<bool>(result.Get<Model>("EditorModel").Enabled, x => !x, result.GetOrMakeProperty<bool>("Valid")));
        }
Exemplo n.º 22
0
        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);
        }
Exemplo n.º 23
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            PointLight light = result.GetOrCreate<PointLight>("PointLight");
            light.Serialize = false;

            const float defaultLightAttenuation = 15.0f;
            light.Attenuation.Value = defaultLightAttenuation;

            Transform transform = result.GetOrCreate<Transform>("Transform");
            light.Add(new Binding<Vector3>(light.Position, transform.Position));

            VoxelChaseAI chase = result.GetOrCreate<VoxelChaseAI>("VoxelChaseAI");

            chase.Filter = delegate(Map.CellState state)
            {
                return state.ID == 0 ? VoxelChaseAI.Cell.Empty : VoxelChaseAI.Cell.Filled;
            };

            chase.Add(new TwoWayBinding<Vector3>(transform.Position, chase.Position));
            result.Add(new CommandBinding(chase.Delete, result.Delete));

            Sound sound = result.GetOrCreate<Sound>("LoopSound");
            sound.Serialize = false;
            sound.Cue.Value = "Orb Loop";
            sound.Is3D.Value = true;
            sound.IsPlaying.Value = true;
            sound.Add(new Binding<Vector3>(sound.Position, chase.Position));
            Property<float> volume = sound.GetProperty("Volume");
            Property<float> pitch = sound.GetProperty("Pitch");

            const float defaultVolume = 0.5f;
            volume.Value = defaultVolume;

            AI ai = result.GetOrCreate<AI>();

            Model model = result.GetOrCreate<Model>();
            model.Add(new Binding<Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value = "Models\\sphere";
            model.Editable = false;
            model.Serialize = false;

            const float defaultModelScale = 0.25f;
            model.Scale.Value = new Vector3(defaultModelScale);

            model.Add(new Binding<Vector3, string>(model.Color, delegate(string state)
            {
                switch (state)
                {
                    case "Alert":
                        return new Vector3(1.5f, 1.5f, 0.5f);
                    case "Chase":
                        return new Vector3(1.5f, 0.5f, 0.5f);
                    case "Levitating":
                        return new Vector3(2.0f, 1.0f, 0.5f);
                    case "Idle":
                        return new Vector3(1.0f, 1.0f, 1.0f);
                    default:
                        return new Vector3(0.0f, 0.0f, 0.0f);
                }
            }, ai.CurrentState));

            Random random = new Random();
            result.Add(new Updater
            {
                delegate(float dt)
                {
                    float source = ((float)random.NextDouble() - 0.5f) * 2.0f;
                    model.Scale.Value = new Vector3(defaultModelScale * (1.0f + (source * 0.5f)));
                    light.Attenuation.Value = defaultLightAttenuation * (1.0f + (source * 0.05f));
                }
            });

            model.Add(new Binding<bool, string>(model.Enabled, x => x != "Exploding", ai.CurrentState));

            light.Add(new Binding<Vector3>(light.Color, model.Color));

            Agent agent = result.GetOrCreate<Agent>();
            agent.Add(new Binding<Vector3>(agent.Position, chase.Position));

            Property<int> operationalRadius = result.GetOrMakeProperty<int>("OperationalRadius", true, 100);

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action = delegate()
                {
                    bool shouldBeActive = (chase.Position.Value - main.Camera.Position).Length() < operationalRadius;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                        ai.CurrentState.Value = "Idle";
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                        ai.CurrentState.Value = "Suspended";
                },
            };

            const float sightDistance = 30.0f;
            const float hearingDistance = 15.0f;

            ai.Add(new AI.State
            {
                Name = "Idle",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 3.0f;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action = delegate()
                        {
                            Agent a = Agent.Query(chase.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                                ai.CurrentState.Value = "Alert";
                        },
                    },
                },
            });

            Property<Entity.Handle> targetAgent = result.GetOrMakeProperty<Entity.Handle>("TargetAgent");

            ai.Add(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[]
                {
                    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, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    targetAgent.Value = a.Entity;
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            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";
                    }
                },
            };

            // Levitate

            Property<Entity.Handle> levitatingMap = result.GetOrMakeProperty<Entity.Handle>("LevitatingMap");
            Property<Map.Coordinate> grabCoord = result.GetOrMakeProperty<Map.Coordinate>("GrabCoord");

            const int levitateRipRadius = 4;

            Func<bool> tryLevitate = delegate()
            {
                Map map = chase.Map.Value.Target.Get<Map>();
                Map.Coordinate? candidate = map.FindClosestFilledCell(chase.Coord, 3);

                if (!candidate.HasValue)
                    return false;

                Map.Coordinate center = candidate.Value;
                if (!map[center].Permanent)
                {
                    // Break off a chunk of this map into a new DynamicMap.

                    List<Map.Coordinate> edges = new List<Map.Coordinate>();

                    Map.Coordinate ripStart = center.Move(-levitateRipRadius, -levitateRipRadius, -levitateRipRadius);
                    Map.Coordinate ripEnd = center.Move(levitateRipRadius, levitateRipRadius, levitateRipRadius);

                    Dictionary<Map.Box, bool> permanentBoxes = new Dictionary<Map.Box, bool>();
                    foreach (Map.Coordinate c in ripStart.CoordinatesBetween(ripEnd))
                    {
                        Map.Box box = map.GetBox(c);
                        if (box != null && box.Type.Permanent)
                            permanentBoxes[box] = true;
                    }

                    foreach (Map.Box b in permanentBoxes.Keys)
                    {
                        // Top and bottom
                        for (int x = b.X - 1; x <= b.X + b.Width; x++)
                        {
                            for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = x, Y = b.Y + b.Height, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = x, Y = b.Y - 1, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }
                        }

                        // Outer shell
                        for (int y = b.Y; y < b.Y + b.Height; y++)
                        {
                            // Left and right
                            for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = b.X - 1, Y = y, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = b.X + b.Width, Y = y, Z = z };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }

                            // Backward and forward
                            for (int x = b.X; x < b.X + b.Width; x++)
                            {
                                Map.Coordinate coord = new Map.Coordinate { X = x, Y = y, Z = b.Z - 1 };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);

                                coord = new Map.Coordinate { X = x, Y = y, Z = b.Z + b.Depth };
                                if (coord.Between(ripStart, ripEnd))
                                    edges.Add(coord);
                            }
                        }
                    }

                    if (edges.Contains(center))
                        return false;

                    // Top and bottom
                    for (int x = ripStart.X; x <= ripEnd.X; x++)
                    {
                        for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                        {
                            edges.Add(new Map.Coordinate { X = x, Y = ripStart.Y, Z = z });
                            edges.Add(new Map.Coordinate { X = x, Y = ripEnd.Y, Z = z });
                        }
                    }

                    // Sides
                    for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
                    {
                        // Left and right
                        for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                        {
                            edges.Add(new Map.Coordinate { X = ripStart.X, Y = y, Z = z });
                            edges.Add(new Map.Coordinate { X = ripEnd.X, Y = y, Z = z });
                        }

                        // Backward and forward
                        for (int x = ripStart.X; x <= ripEnd.X; x++)
                        {
                            edges.Add(new Map.Coordinate { X = x, Y = y, Z = ripStart.Z });
                            edges.Add(new Map.Coordinate { X = x, Y = y, Z = ripEnd.Z });
                        }
                    }

                    map.Empty(edges);
                    map.Regenerate(delegate(List<DynamicMap> spawnedMaps)
                    {
                        foreach (DynamicMap spawnedMap in spawnedMaps)
                        {
                            if (spawnedMap[center].ID != 0)
                            {
                                levitatingMap.Value = spawnedMap.Entity;
                                break;
                            }
                        }
                    });

                    grabCoord.Value = center;
                    return true;
                }
                return false;
            };

            Action delevitateMap = delegate()
            {
                Entity levitatingMapEntity = levitatingMap.Value.Target;
                if (levitatingMapEntity == null || !levitatingMapEntity.Active)
                    return;

                DynamicMap dynamicMap = levitatingMapEntity.Get<DynamicMap>();

                int maxDistance = levitateRipRadius + 7;
                Map closestMap = null;
                Map.Coordinate closestCoord = new Map.Coordinate();
                foreach (Map m in Map.ActivePhysicsMaps)
                {
                    if (m == dynamicMap)
                        continue;

                    Map.Coordinate relativeCoord = m.GetCoordinate(dynamicMap.Transform.Value.Translation);
                    Map.Coordinate? closestFilled = m.FindClosestFilledCell(relativeCoord, maxDistance);
                    if (closestFilled != null)
                    {
                        maxDistance = Math.Min(Math.Abs(relativeCoord.X - closestFilled.Value.X), Math.Min(Math.Abs(relativeCoord.Y - closestFilled.Value.Y), Math.Abs(relativeCoord.Z - closestFilled.Value.Z)));
                        closestMap = m;
                        closestCoord = closestFilled.Value;
                    }
                }
                if (closestMap != null)
                {
                    // Combine this map with the other one

                    Direction x = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Right));
                    Direction y = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Up));
                    Direction z = closestMap.GetRelativeDirection(dynamicMap.GetAbsoluteVector(Vector3.Backward));

                    if (x.IsParallel(y))
                        x = y.Cross(z);
                    else if (y.IsParallel(z))
                        y = x.Cross(z);

                    Map.Coordinate offset = new Map.Coordinate();
                    float closestCoordDistance = float.MaxValue;
                    Vector3 closestCoordPosition = closestMap.GetAbsolutePosition(closestCoord);
                    foreach (Map.Coordinate c in dynamicMap.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()))
                    {
                        float distance = (dynamicMap.GetAbsolutePosition(c) - closestCoordPosition).LengthSquared();
                        if (distance < closestCoordDistance)
                        {
                            closestCoordDistance = distance;
                            offset = c;
                        }
                    }
                    Vector3 toLevitatingMap = dynamicMap.Transform.Value.Translation - closestMap.GetAbsolutePosition(closestCoord);
                    offset = offset.Move(dynamicMap.GetRelativeDirection(-toLevitatingMap));

                    Matrix orientation = dynamicMap.Transform.Value;
                    orientation.Translation = Vector3.Zero;

                    EffectBlockFactory blockFactory = Factory.Get<EffectBlockFactory>();

                    int index = 0;
                    foreach (Map.Coordinate c in dynamicMap.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()).OrderBy(c2 => new Vector3(c2.X - offset.X, c2.Y - offset.Y, c2.Z - offset.Z).LengthSquared()))
                    {
                        Map.Coordinate offsetFromCenter = c.Move(-offset.X, -offset.Y, -offset.Z);
                        Map.Coordinate targetCoord = new Map.Coordinate();
                        targetCoord.SetComponent(x, offsetFromCenter.GetComponent(Direction.PositiveX));
                        targetCoord.SetComponent(y, offsetFromCenter.GetComponent(Direction.PositiveY));
                        targetCoord.SetComponent(z, offsetFromCenter.GetComponent(Direction.PositiveZ));
                        targetCoord = targetCoord.Move(closestCoord.X, closestCoord.Y, closestCoord.Z);
                        if (closestMap[targetCoord].ID == 0)
                        {
                            Entity block = blockFactory.CreateAndBind(main);
                            c.Data.ApplyToEffectBlock(block.Get<ModelInstance>());
                            block.GetProperty<Vector3>("Offset").Value = closestMap.GetRelativePosition(targetCoord);
                            block.GetProperty<bool>("Scale").Value = false;
                            block.GetProperty<Vector3>("StartPosition").Value = dynamicMap.GetAbsolutePosition(c);
                            block.GetProperty<Matrix>("StartOrientation").Value = orientation;
                            block.GetProperty<float>("TotalLifetime").Value = 0.05f + (index * 0.0075f);
                            blockFactory.Setup(block, closestMap.Entity, targetCoord, c.Data.ID);
                            main.Add(block);
                            index++;
                        }
                    }

                    // Delete the map
                    levitatingMapEntity.Delete.Execute();
                }
            };

            // Chase AI state

            ai.Add(new AI.State
            {
                Name = "Chase",
                Enter = delegate(AI.State previous)
                {
                    chase.Speed.Value = 10.0f;
                    chase.TargetActive.Value = true;
                },
                Exit = delegate(AI.State next)
                {
                    chase.TargetActive.Value = false;
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action = delegate()
                        {
                            Entity target = targetAgent.Value.Target;
                            Vector3 targetPosition = target.Get<Transform>().Position;
                            chase.Target.Value = targetPosition;
                            Entity levitatingMapEntity = levitatingMap.Value.Target;
                            if ((targetPosition - chase.Position).Length() < 10.0f && (levitatingMapEntity == null || !levitatingMapEntity.Active))
                            {
                                if (tryLevitate())
                                    ai.CurrentState.Value = "Levitating";
                            }
                        }
                    }
                },
            });

            Property<Vector3> lastPosition = result.GetOrMakeProperty<Vector3>("LastPosition");
            Property<Vector3> nextPosition = result.GetOrMakeProperty<Vector3>("NextPosition");
            Property<float> positionBlend = result.GetOrMakeProperty<float>("PositionBlend");

            Action findNextPosition = delegate()
            {
                lastPosition.Value = chase.Position.Value;
                nextPosition.Value = targetAgent.Value.Target.Get<Transform>().Position + new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble(), (float)random.NextDouble() - 0.5f) * 5.0f;
                positionBlend.Value = 0.0f;
            };

            ai.Add(new AI.State
            {
                Name = "Levitating",
                Enter = delegate(AI.State previous)
                {
                    chase.Enabled.Value = false;
                    findNextPosition();
                },
                Exit = delegate(AI.State next)
                {
                    delevitateMap();
                    levitatingMap.Value = null;

                    Map map = chase.Map.Value.Target.Get<Map>();
                    Map.Coordinate currentCoord = map.GetCoordinate(chase.Position);
                    Map.Coordinate? closest = map.FindClosestFilledCell(currentCoord, 10);
                    if (closest.HasValue)
                    {
                        chase.LastCoord.Value = currentCoord;
                        chase.Coord.Value = closest.Value;
                        chase.Blend.Value = 0.0f;
                    }
                    chase.Enabled.Value = true;
                    volume.Value = defaultVolume;
                    pitch.Value = 0.0f;
                },
                Tasks = new[]
                {
                    checkTargetAgent,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            volume.Value = 1.0f;
                            pitch.Value = 1.0f;
                            Entity levitatingMapEntity = levitatingMap.Value.Target;
                            if (!levitatingMapEntity.Active || ai.TimeInCurrentState.Value > 8.0f)
                            {
                                ai.CurrentState.Value = "Alert";
                                return;
                            }

                            DynamicMap dynamicMap = levitatingMapEntity.Get<DynamicMap>();

                            positionBlend.Value += (main.ElapsedTime.Value / 1.0f);
                            if (positionBlend > 1.0f)
                                findNextPosition();

                            chase.Position.Value = Vector3.Lerp(lastPosition, nextPosition, positionBlend);

                            Vector3 grabPoint = dynamicMap.GetAbsolutePosition(grabCoord);
                            Vector3 diff = chase.Position.Value - grabPoint;
                            if (diff.Length() > 15.0f)
                            {
                                ai.CurrentState.Value = "Chase";
                                return;
                            }

                            diff *= (float)Math.Sqrt(dynamicMap.PhysicsEntity.Mass) * 0.5f;
                            dynamicMap.PhysicsEntity.ApplyImpulse(ref grabPoint, ref diff);
                        },
                    },
                },
            });

            this.SetMain(result, main);
        }
Exemplo n.º 24
0
        private static void attachEditorComponents(Entity result, Main main)
        {
            Transform transform = result.Get<Transform>();

            Property<bool> selected = new Property<bool> { Value = false, Editable = false, Serialize = false };
            result.Add("EditorSelected", selected);

            Property<Entity.Handle> parentMap = result.GetOrMakeProperty<Entity.Handle>("Parent");

            Command<Entity> toggleEntityConnected = new Command<Entity>
            {
                Action = delegate(Entity entity)
                {
                    parentMap.Value = entity;
                }
            };
            result.Add("ToggleEntityConnected", toggleEntityConnected);

            LineDrawer connectionLines = new LineDrawer { Serialize = false };
            connectionLines.Add(new Binding<bool>(connectionLines.Enabled, selected));

            Color connectionLineColor = new Color(1.0f, 1.0f, 1.0f, 0.5f);

            Action recalculateLine = delegate()
            {
                connectionLines.Lines.Clear();
                Entity parent = parentMap.Value.Target;
                if (parent != null)
                {
                    connectionLines.Lines.Add(new LineDrawer.Line
                    {
                        A = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(transform.Position, connectionLineColor),
                        B = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(parent.Get<Transform>().Position, connectionLineColor)
                    });
                }
            };

            Model model = new Model();
            model.Filename.Value = "Models\\cone";
            model.Editable = false;
            model.Serialize = false;
            result.Add("DirectionModel", model);

            Property<Direction> dir = result.GetProperty<Direction>("Direction");
            Transform mapTransform = result.Get<Transform>("MapTransform");
            model.Add(new Binding<Matrix>(model.Transform, delegate()
            {
                Matrix m = Matrix.Identity;
                m.Translation = transform.Position;

                if (dir == Direction.None)
                    m.Forward = m.Right = m.Up = Vector3.Zero;
                else
                {
                    Vector3 normal = Vector3.TransformNormal(dir.Value.GetVector(), mapTransform.Matrix);

                    m.Forward = -normal;
                    if (normal.Equals(Vector3.Up))
                        m.Right = Vector3.Left;
                    else if (normal.Equals(Vector3.Down))
                        m.Right = Vector3.Right;
                    else
                        m.Right = Vector3.Normalize(Vector3.Cross(normal, Vector3.Down));
                    m.Up = Vector3.Cross(normal, m.Left);
                }
                return m;
            }, transform.Matrix, mapTransform.Matrix));

            NotifyBinding recalculateBinding = null;
            Action rebuildBinding = delegate()
            {
                if (recalculateBinding != null)
                {
                    connectionLines.Remove(recalculateBinding);
                    recalculateBinding = null;
                }
                if (parentMap.Value.Target != null)
                {
                    recalculateBinding = new NotifyBinding(recalculateLine, parentMap.Value.Target.Get<Transform>().Matrix);
                    connectionLines.Add(recalculateBinding);
                }
                recalculateLine();
            };
            connectionLines.Add(new NotifyBinding(rebuildBinding, parentMap));

            connectionLines.Add(new NotifyBinding(recalculateLine, selected));
            connectionLines.Add(new NotifyBinding(recalculateLine, () => selected, transform.Position));
            result.Add(connectionLines);
        }
Exemplo n.º 25
0
        public static void Bind(Entity result, Main main, Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint, bool allowRotation, bool creating = false)
        {
            Transform mapTransform = result.GetOrCreate<Transform>("MapTransform");

            Transform transform = result.GetOrCreate<Transform>("Transform");

            Factory.Get<DynamicMapFactory>().InternalBind(result, main, creating, mapTransform);

            DynamicMap map = result.Get<DynamicMap>();

            Property<Entity.Handle> parentMap = result.GetOrMakeProperty<Entity.Handle>("Parent");
            Property<Map.Coordinate> coord = result.GetOrMakeProperty<Map.Coordinate>("Coord");
            Property<Direction> dir = result.GetOrMakeProperty<Direction>("Direction", true);

            Action refreshMapTransform = delegate()
            {
                Entity parent = parentMap.Value.Target;
                if (parent != null)
                {
                    if (!parent.Active)
                        parent = null;
                    else
                    {
                        Map staticMap = parent.Get<Map>();
                        coord.Value = staticMap.GetCoordinate(transform.Position);
                        mapTransform.Position.Value = staticMap.GetAbsolutePosition(staticMap.GetRelativePosition(coord) - new Vector3(0.5f) + staticMap.Offset + map.Offset);
                        if (!allowRotation)
                            mapTransform.Orientation.Value = parent.Get<Transform>().Orientation;
                    }
                }
                else
                    mapTransform.Matrix.Value = transform.Matrix;
            };
            if (main.EditorEnabled)
                result.Add(new NotifyBinding(refreshMapTransform, transform.Matrix, map.Offset));

            ISpaceObject joint = null;
            CommandBinding jointDeleteBinding = null, physicsUpdateBinding = null;

            Action rebuildJoint = null;
            rebuildJoint = delegate()
            {
                if (joint != null)
                {
                    if (joint.Space != null)
                        main.Space.Remove(joint);
                    result.Remove(jointDeleteBinding);
                    if (physicsUpdateBinding != null)
                        result.Remove(physicsUpdateBinding);
                    physicsUpdateBinding = null;
                    joint = null;
                    jointDeleteBinding = null;
                }

                Entity parent = parentMap.Value.Target;

                if (main.EditorEnabled)
                {
                    refreshMapTransform();
                    return;
                }

                if (parent != null)
                {
                    if (!parent.Active)
                        parent = null;
                    else
                    {
                        Map staticMap = parent.Get<Map>();

                        map.PhysicsEntity.Position = mapTransform.Position;
                        if (!allowRotation)
                            map.PhysicsEntity.Orientation = mapTransform.Quaternion;

                        if (dir != Direction.None && !main.EditorEnabled)
                        {
                            Vector3 relativeLineAnchor = staticMap.GetRelativePosition(coord) - new Vector3(0.5f) + staticMap.Offset + map.Offset;
                            Vector3 lineAnchor = staticMap.GetAbsolutePosition(relativeLineAnchor);
                            DynamicMap dynamicMap = parent.Get<DynamicMap>();
                            joint = createJoint(map.PhysicsEntity, dynamicMap == null ? null : dynamicMap.PhysicsEntity, map.PhysicsEntity.Position, staticMap.GetAbsoluteVector(dir.Value.GetVector()), lineAnchor);
                            main.Space.Add(joint);
                            map.PhysicsEntity.ActivityInformation.Activate();

                            if (dynamicMap != null)
                            {
                                physicsUpdateBinding = new CommandBinding(dynamicMap.PhysicsUpdated, rebuildJoint);
                                result.Add(physicsUpdateBinding);
                            }

                            jointDeleteBinding = new CommandBinding(parent.Delete, delegate()
                            {
                                parentMap.Value = null;
                            });
                            result.Add(jointDeleteBinding);
                        }
                    }
                }
            };
            result.Add(new NotifyBinding(rebuildJoint, parentMap));
            result.Add(new CommandBinding(result.Delete, delegate()
            {
                if (joint != null && joint.Space != null)
                {
                    main.Space.Remove(joint);
                    joint = null;
                }
            }));
            result.Add(new CommandBinding(map.OnSuspended, delegate()
            {
                if (joint != null && joint.Space != null)
                    main.Space.Remove(joint);
            }));
            result.Add(new CommandBinding(map.OnResumed, delegate()
            {
                if (joint != null && joint.Space == null)
                    main.Space.Add(joint);
            }));
            rebuildJoint();
            Command rebuildJointCommand = new Command();
            result.Add(new CommandBinding(rebuildJointCommand, rebuildJoint));
            result.Add("RebuildJoint", rebuildJointCommand);

            if (main.EditorEnabled)
                JointFactory.attachEditorComponents(result, main);
        }
Exemplo n.º 26
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            Property<Direction> dir = result.GetOrMakeProperty<Direction>("Direction", true);
            Property<int> minimum = result.GetOrMakeProperty<int>("Minimum", true);
            Property<int> maximum = result.GetOrMakeProperty<int>("Maximum", true);
            Property<bool> locked = result.GetOrMakeProperty<bool>("Locked", true);
            Property<float> speed = result.GetOrMakeProperty<float>("Speed", true, 5);
            Property<float> maxForce = result.GetOrMakeProperty<float>("MaxForce", true);
            Property<float> damping = result.GetOrMakeProperty<float>("Damping", true);
            Property<float> stiffness = result.GetOrMakeProperty<float>("Stiffness", true);
            Property<int> goal = result.GetOrMakeProperty<int>("Goal", true);

            PrismaticJoint joint = null;

            Action setLimits = delegate()
            {
                if (joint != null)
                {
                    int min = minimum, max = maximum;
                    if (max > min)
                    {
                        joint.Limit.IsActive = true;
                        joint.Limit.Minimum = minimum;
                        joint.Limit.Maximum = maximum;
                    }
                    else
                        joint.Limit.IsActive = false;
                }
            };
            result.Add(new NotifyBinding(setLimits, minimum, maximum));

            Action setMaxForce = delegate()
            {
                if (joint != null)
                {
                    if (maxForce > 0.001f)
                        joint.Motor.Settings.MaximumForce = maxForce * result.Get<DynamicMap>().PhysicsEntity.Mass;
                    else
                        joint.Motor.Settings.MaximumForce = float.MaxValue;
                }
            };
            result.Add(new NotifyBinding(setMaxForce, maxForce));

            Action setSpeed = delegate()
            {
                if (joint != null)
                    joint.Motor.Settings.Servo.BaseCorrectiveSpeed = speed;
            };
            result.Add(new NotifyBinding(setSpeed, speed));

            Action setLocked = delegate()
            {
                if (joint != null)
                    joint.Motor.IsActive = locked;
            };
            result.Add(new NotifyBinding(setLocked, locked));

            Action setGoal = delegate()
            {
                if (joint != null)
                    joint.Motor.Settings.Servo.Goal = goal;
            };
            result.Add(new NotifyBinding(setGoal, goal));

            Action setDamping = delegate()
            {
                if (joint != null && damping != 0)
                    joint.Motor.Settings.Servo.SpringSettings.DampingConstant = damping;
            };
            result.Add(new NotifyBinding(setDamping, damping));

            Action setStiffness = delegate()
            {
                if (joint != null && stiffness != 0)
                    joint.Motor.Settings.Servo.SpringSettings.StiffnessConstant = stiffness;
            };
            result.Add(new NotifyBinding(setStiffness, stiffness));

            Func<BEPUphysics.Entities.Entity, BEPUphysics.Entities.Entity, Vector3, Vector3, Vector3, ISpaceObject> createJoint = delegate(BEPUphysics.Entities.Entity entity1, BEPUphysics.Entities.Entity entity2, Vector3 pos, Vector3 direction, Vector3 anchor)
            {
                joint = new PrismaticJoint(entity1, entity2, pos, -direction, anchor);
                joint.Motor.Settings.Mode = MotorMode.Servomechanism;
                setLimits();
                setLocked();
                setSpeed();
                setMaxForce();
                setGoal();
                setDamping();
                setStiffness();
                return joint;
            };

            JointFactory.Bind(result, main, createJoint, false, creating);

            result.Add("Forward", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                        goal.Value = maximum;
                },
            });
            result.Add("Backward", new Command
            {
                Action = delegate()
                {
                    if (joint != null && locked)
                        goal.Value = minimum;
                },
            });

            Command hitMax = new Command();
            result.Add("HitMax", hitMax);
            Command hitMin = new Command();
            result.Add("HitMin", hitMin);

            bool lastLimitExceeded = false;
            result.Add(new Updater
            {
                delegate(float dt)
                {
                    if (joint != null)
                    {
                        bool limitExceeded = joint.Limit.IsLimitExceeded;
                        if (limitExceeded && !lastLimitExceeded)
                        {
                            if (joint.Limit.Error < 0)
                                hitMin.Execute();
                            else
                                hitMax.Execute();
                        }
                        lastLimitExceeded = limitExceeded;
                    }
                }
            });
        }
Exemplo n.º 27
0
        public override void Bind(Entity result, Main main, bool creating = false)
        {
            result.CannotSuspendByDistance = true;

            const float kernelSpacing = 8.0f;
            const int kernelSize = 10;
            const float raycastHeight = 30.0f;
            const float rainStartHeight = 25.0f;
            const float raycastInterval = 0.25f;
            const float verticalSpeed = 90.0f;
            const float maxLifetime = 1.0f;

            ParticleEmitter emitter = result.Get<ParticleEmitter>("Emitter");
            emitter.Jitter.Value = new Vector3(kernelSpacing * kernelSize * 0.5f, 0.0f, kernelSpacing * kernelSize * 0.5f);
            Transform transform = result.Get<Transform>();

            Sound rainSound = result.GetOrCreate<Sound>("RainSound");
            rainSound.Cue.Value = "Rain";
            rainSound.Is3D.Value = false;
            rainSound.IsPlaying.Value = true;
            Property<float> rainSoundVolume = rainSound.GetProperty("Volume");

            Components.DirectionalLight lightning = result.GetOrCreate<Components.DirectionalLight>("Lightning");
            lightning.Enabled.Value = false;
            Vector3 originalLightningColor = lightning.Color;

            float[,] audioKernel = new float[kernelSize, kernelSize];
            float sum = 0.0f;
            for (int x = 0; x < kernelSize; x++)
            {
                for (int y = 0; y < kernelSize; y++)
                {
                    float cell = (kernelSize / 2) - new Vector2(x - (kernelSize / 2), y - (kernelSize / 2)).Length();
                    audioKernel[x, y] = cell;
                    sum += cell;
                }
            }

            for (int x = 0; x < kernelSize; x++)
            {
                for (int y = 0; y < kernelSize; y++)
                    audioKernel[x, y] /= sum;
            }

            float[,] raycastHeights = new float[kernelSize, kernelSize];

            float raycastTimer = raycastInterval;
            Vector3 kernelOffset = Vector3.Zero;
            Updater updater = new Updater
            {
                delegate(float dt)
                {
                    raycastTimer += dt;
                    if (raycastTimer > raycastInterval)
                    {
                        raycastTimer = 0.0f;
                        Vector3 cameraPos = main.Camera.Position;
                        float averageHeight = 0.0f;
                        kernelOffset = main.Camera.Position + new Vector3(kernelSize * kernelSpacing * -0.5f, raycastHeight + rainStartHeight, kernelSize * kernelSpacing * -0.5f);
                        for (int x = 0; x < kernelSize; x++)
                        {
                            for (int y = 0; y < kernelSize; y++)
                            {
                                Vector3 pos = kernelOffset + new Vector3(x * kernelSpacing, 0, y * kernelSpacing);
                                Map.GlobalRaycastResult raycast = Map.GlobalRaycast(pos, Vector3.Down, rainStartHeight + raycastHeight + (verticalSpeed * maxLifetime));
                                float height = raycast.Map == null ? float.MinValue : raycast.Position.Y;
                                raycastHeights[x, y] = height;
                                averageHeight += Math.Max(cameraPos.Y, Math.Min(height, cameraPos.Y + rainStartHeight)) * audioKernel[x, y];
                            }
                        }
                        rainSoundVolume.Value = 1.0f - ((averageHeight - cameraPos.Y) / rainStartHeight);
                    }
                }
            };
            updater.EnabledInEditMode.Value = true;
            result.Add(updater);

            Random random = new Random();
            Property<float> thunderIntervalMin = result.GetOrMakeProperty<float>("ThunderIntervalMin", true, 12.0f);
            Property<float> thunderIntervalMax = result.GetOrMakeProperty<float>("ThunderIntervalMax", true, 36.0f);
            Property<float> thunderMaxDelay = result.GetOrMakeProperty<float>("ThunderMaxDelay", true, 5.0f);
            Timer timer = result.GetOrCreate<Timer>();
            timer.Serialize = false;
            timer.Repeat.Value = true;
            timer.Interval.Value = (float)random.NextDouble() * thunderIntervalMax;
            timer.Add(new CommandBinding(timer.Command, delegate()
            {
                float volume = 0.5f + ((float)random.NextDouble() * 0.5f);
                result.Add(new Animation
                (
                    new Animation.Set<bool>(lightning.Enabled, true),
                    new Animation.Vector3MoveTo(lightning.Color, originalLightningColor * volume, 0.2f),
                    new Animation.Vector3MoveTo(lightning.Color, Vector3.Zero, 0.25f),
                    new Animation.Set<bool>(lightning.Enabled, false),
                    new Animation.Delay((1.0f - volume) * thunderMaxDelay),
                    new Animation.Execute(delegate()
                    {
                        Sound thunder = Sound.PlayCue(main, "Thunder", main.Camera.Position + Vector3.Normalize(new Vector3(2.0f * ((float)random.NextDouble() - 0.5f), 1.0f, 2.0f * ((float)random.NextDouble() - 0.5f))) * 1000.0f, volume);
                        if (thunder != null)
                            result.Add(thunder);
                    })
                ));
                timer.Interval.Value = thunderIntervalMin + ((float)random.NextDouble() * (thunderIntervalMax - thunderIntervalMin));
            }));

            if (ParticleSystem.Get(main, "Rain") == null)
            {
                ParticleSystem.Add(main, "Rain",
                new ParticleSystem.ParticleSettings
                {
                    TextureName = "Particles\\default",
                    EffectFile = "Effects\\ParticleRain",
                    MaxParticles = 25000,
                    Duration = TimeSpan.FromSeconds(maxLifetime),
                    MinHorizontalVelocity = 0.0f,
                    MaxHorizontalVelocity = 0.0f,
                    MinVerticalVelocity = -verticalSpeed,
                    MaxVerticalVelocity = -verticalSpeed,
                    Gravity = new Vector3(0.0f, 0.0f, 0.0f),
                    MinRotateSpeed = 0.0f,
                    MaxRotateSpeed = 0.0f,
                    MinStartSize = 0.3f,
                    MaxStartSize = 0.3f,
                    MinEndSize = 0.3f,
                    MaxEndSize = 0.3f,
                    BlendState = BlendState.Opaque,
                    MinColor = new Vector4(0.5f, 0.6f, 0.7f, 1.0f),
                    MaxColor = new Vector4(0.5f, 0.6f, 0.7f, 1.0f),
                });
                emitter.ParticleType.Reset();
            }

            emitter.AddParticle = delegate(Vector3 position, Vector3 velocity)
            {
                Vector3 kernelCoord = (position - kernelOffset) / kernelSpacing;
                float height = raycastHeights[Math.Max(0, Math.Min(kernelSize - 1, (int)kernelCoord.X)), Math.Max(0, Math.Min(kernelSize - 1, (int)kernelCoord.Z))];
                if (height < position.Y)
                    emitter.ParticleSystem.AddParticle(position, Vector3.Zero, Math.Min((position.Y - height) / verticalSpeed, maxLifetime));
            };

            emitter.Add(new Binding<Vector3>(emitter.Position, x => x + new Vector3(0.0f, rainStartHeight, 0.0f), main.Camera.Position));

            this.SetMain(result, main);
        }
Exemplo n.º 28
0
		private static void attachEditorComponents(Entity result, Main main)
		{
			Transform transform = result.Get<Transform>();

			Property<Entity.Handle> parentMap = result.GetOrMakeProperty<Entity.Handle>("Parent");

			EntityConnectable.AttachEditorComponents(result, parentMap);
			Model model = new Model();
			model.Filename.Value = "Models\\cone";
			model.Editable = false;
			model.Serialize = false;
			result.Add("DirectionModel", model);

			Property<Direction> dir = result.GetProperty<Direction>("Direction");
			Transform mapTransform = result.Get<Transform>("MapTransform");
			model.Add(new Binding<Matrix>(model.Transform, delegate()
			{
				Matrix m = Matrix.Identity;
				m.Translation = transform.Position;

				if (dir == Direction.None)
					m.Forward = m.Right = m.Up = Vector3.Zero;
				else
				{
					Vector3 normal = Vector3.TransformNormal(dir.Value.GetVector(), mapTransform.Matrix);

					m.Forward = -normal;
					if (normal.Equals(Vector3.Up))
						m.Right = Vector3.Left;
					else if (normal.Equals(Vector3.Down))
						m.Right = Vector3.Right;
					else
						m.Right = Vector3.Normalize(Vector3.Cross(normal, Vector3.Down));
					m.Up = Vector3.Cross(normal, m.Left);
				}
				return m;
			}, transform.Matrix, mapTransform.Matrix));
		}