public static IEnumerable<Zone> GetConnectedZones(Zone zone) { IEnumerable<Zone> result = new Zone[] { zone }; foreach (Entity e in zone.ConnectedEntities) { Zone z; if (e != null && (z = e.Get<Zone>()) != null) result = result.Concat(Zone.GetConnectedZones(z)); } return result; }
private static void processEntity(Entity entity, Zone currentZone, IEnumerable<NonAxisAlignedBoundingBox> boxes, Vector3 cameraPosition, float suspendDistance) { Map map = entity.Get<Map>(); if (map != null && !typeof(DynamicMap).IsAssignableFrom(map.GetType())) processMap(map, boxes); else { Transform transform = entity.Get<Transform>(); bool hasPosition = transform != null; Vector3 pos = Vector3.Zero; if (hasPosition) pos = transform.Position; if (map != null && typeof(DynamicMap).IsAssignableFrom(map.GetType())) { hasPosition = true; pos = Vector3.Transform(Vector3.Zero, map.Transform); } bool suspended; if (currentZone != null && currentZone.Exclusive) // Suspend everything outside the current zone, unless it's connected suspended = !currentZone.ConnectedEntities.Contains(entity) && hasPosition && !boxesContain(boxes, pos); else { // Only suspend things that are in a different (exclusive) zone, or that are just too far away suspended = false; if (hasPosition) { if (!entity.CannotSuspendByDistance && !boxesContain(boxes, pos) && (pos - cameraPosition).Length() > suspendDistance) suspended = true; else { foreach (Zone z in Zone.Zones) { if (z != currentZone && z.Exclusive && z.BoundingBox.Value.Contains(Vector3.Transform(pos, Matrix.Invert(z.Transform))) != ContainmentType.Disjoint) { suspended = true; break; } } } } // Allow the editor to reverse the decision if (currentZone != null && currentZone.ConnectedEntities.Contains(entity)) suspended = !suspended; } entity.SetSuspended(suspended); } }
public void Update(float dt) { State wallRunState = this.CurrentState; if (wallRunState != State.None) { this.Vault.Execute(); // Try to vault up if (this.CurrentState.Value == State.None) // We vaulted { return; } if (!this.WallRunVoxel.Value.Active || this.IsSupported) { this.Deactivate(); return; } Vector3 wallRunVector = this.WallRunVoxel.Value.GetAbsoluteVector(this.WallRunDirection.Value.GetVector()); float wallRunSpeed = Vector3.Dot(this.LinearVelocity.Value, wallRunVector); Vector3 pos = this.Position + new Vector3(0, this.Height * -0.5f, 0); if (wallRunState == State.Straight) { if (wallRunSpeed < 0.0f) { // Start sliding down this.CurrentState.Value = wallRunState = State.Down; AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_SLIDE_LOOP, this.Entity); } } else if (wallRunState == State.Left || wallRunState == State.Right) { if (this.IsSupported || wallRunSpeed < minWallRunSpeed) { // We landed on the ground or we're going too slow to continue wall-running this.Deactivate(); return; } else { // Check if we should switch to another wall Vector3 wallVector = this.WallRunVoxel.Value.GetAbsoluteVector(this.WallDirection.Value.GetVector()); Voxel.GlobalRaycastResult result = Voxel.GlobalRaycast(pos, wallRunVector + wallVector, 2.0f); if (result.Voxel != null && result.Voxel != this.WallRunVoxel.Value) { float dot = Vector3.Dot(result.Voxel.GetAbsoluteVector(result.Normal.GetReverse().GetVector()), wallVector); if (dot > 0.7f) { Matrix matrix = Matrix.CreateRotationY(this.Rotation); Vector3 forwardVector = -matrix.Forward; this.setup(result.Voxel, result.Normal.GetReverse(), wallRunState, forwardVector, false, true); } } } } Voxel.Coord coord = this.WallRunVoxel.Value.GetCoordinate(pos); Voxel.Coord wallCoord = coord.Move(this.WallDirection, 2); Voxel.State wallType = this.WallRunVoxel.Value[wallCoord]; this.WalkedOn.Execute(this.WallRunVoxel, wallCoord, this.WallDirection); if (this.EnableEnhancedWallRun && (wallRunState == State.Left || wallRunState == State.Right) && Zone.CanBuild(this.Position)) { Direction up = this.WallRunVoxel.Value.GetRelativeDirection(Direction.PositiveY); Direction right = this.WallDirection.Value.Cross(up); List <EffectBlockFactory.BlockBuildOrder> buildCoords = new List <EffectBlockFactory.BlockBuildOrder>(); const int radius = 5; int upwardRadius = wallRunState == State.Down ? 0 : radius; for (Voxel.Coord x = wallCoord.Move(right, -radius); x.GetComponent(right) < wallCoord.GetComponent(right) + radius; x = x.Move(right)) { int dx = x.GetComponent(right) - wallCoord.GetComponent(right); for (Voxel.Coord y = x.Move(up, -radius); y.GetComponent(up) < wallCoord.GetComponent(up) + upwardRadius; y = y.Move(up)) { int dy = y.GetComponent(up) - wallCoord.GetComponent(up); if ((float)Math.Sqrt(dx * dx + dy * dy) < radius && this.WallRunVoxel.Value[y].ID == 0) { buildCoords.Add(new EffectBlockFactory.BlockBuildOrder { Voxel = this.WallRunVoxel, Coordinate = y, State = Voxel.States.Blue, }); } } } Factory.Get <EffectBlockFactory>().Build(main, buildCoords, this.Position); } else if (wallType.ID == 0 && wallInstantiationTimer == 0.0f) // We ran out of wall to walk on { this.Deactivate(); return; } if (this.WallRunVoxel.Value == null || !this.WallRunVoxel.Value.Active) { return; } wallInstantiationTimer = Math.Max(0.0f, wallInstantiationTimer - dt); Vector3 coordPos = this.WallRunVoxel.Value.GetAbsolutePosition(coord); Vector3 normal = this.WallRunVoxel.Value.GetAbsoluteVector(this.WallDirection.Value.GetVector()); // Equation of a plane // normal (dot) point = d float d = Vector3.Dot(normal, coordPos) + (wallRunState == State.Down ? 0.3f : 0.4f); // Distance along the normal to keep the player glued to the wall float snapDistance = d - Vector3.Dot(pos, normal); this.Position.Value += normal * snapDistance; Vector3 velocity = this.LinearVelocity; // Also fix the velocity so we don't jitter away from the wall velocity -= Vector3.Dot(velocity, normal) * normal; // Slow our descent velocity += new Vector3(0, (wallRunState == State.Straight ? 3.0f : 10.0f) * dt, 0); this.LinearVelocity.Value = velocity; } }
private static IEnumerable<NonAxisAlignedBoundingBox> getActiveBoundingBoxes(Camera camera, Zone currentZone) { if (currentZone == null) { Vector3 pos = camera.Position; float radius = camera.FarPlaneDistance; return new[] { new NonAxisAlignedBoundingBox { BoundingBox = new BoundingBox(pos - new Vector3(radius), pos + new Vector3(radius)), Transform = Matrix.Identity } }; } else return Zone.GetConnectedZones(currentZone).Select(x => new NonAxisAlignedBoundingBox { BoundingBox = x.BoundingBox, Transform = Matrix.Invert(x.Transform) }).ToList(); }
public static bool CanSpawnAt(Vector3 x) { Zone z = Zone.Get(x); return(z == null || z.CanSpawn.Value); }