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; } Voxel voxel = this.WallRunVoxel.Value; if (voxel == null || !voxel.Active) { this.Deactivate(); return; } Vector3 wallRunVector = voxel.GetAbsoluteVector(this.WallRunDirection.Value.GetVector()); Vector3 baseVelocity = voxel.LinearVelocity + Vector3.Cross(voxel.AngularVelocity, this.Position - voxel.Transform.Value.Translation); float wallRunSpeed = Vector3.Dot(this.LinearVelocity.Value - baseVelocity, 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 = voxel.GetAbsoluteVector(this.WallDirection.Value.GetVector()); Voxel.GlobalRaycastResult result = Voxel.GlobalRaycast(pos, wallRunVector + wallVector, 2.0f); if (result.Voxel != null && result.Voxel != voxel) { 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 = voxel.GetCoordinate(pos); Voxel.Coord wallCoord = coord.Move(this.WallDirection, 2); Voxel.State wallType = voxel[wallCoord]; if (!wallCoord.Equivalent(this.lastWallRunCoord)) { this.lastWallRunCoord = wallCoord; this.WalkedOn.Execute(voxel, wallCoord, this.WallDirection); } if (this.EnableEnhancedWallRun && (wallRunState == State.Left || wallRunState == State.Right) && Zone.CanBuild(this.Position) && voxel.Entity.Type != "Bouncer") { Direction up = voxel.GetRelativeDirection(Direction.PositiveY); if (up.IsPerpendicular(this.WallDirection)) { 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 && voxel[y].ID == 0) { buildCoords.Add(new EffectBlockFactory.BlockBuildOrder { Voxel = voxel, Coordinate = y, State = Voxel.States.Blue, }); } } } Factory.Get <EffectBlockFactory>().Build(main, buildCoords, this.Position); } else { this.Deactivate(); return; } } else if (wallType.ID == 0 && wallInstantiationTimer == 0.0f) // We ran out of wall to walk on { this.Deactivate(); return; } wallInstantiationTimer = Math.Max(0.0f, wallInstantiationTimer - dt); Vector3 coordPos = voxel.GetAbsolutePosition(coord); Vector3 normal = voxel.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 bool canBuild(Vector3 pos) { return(Zone.CanBuild(pos) && Water.Get(pos) == null); }
public void Update(float dt) { if (this.TargetVoxel.Target == null || !this.TargetVoxel.Target.Active) { this.Delete.Execute(); return; } this.Lifetime += dt; if (this.Lifetime < this.Delay) { return; } float blend = (this.Lifetime - this.Delay) / this.TotalLifetime; Voxel m = this.TargetVoxel.Target.Get <Voxel>(); Matrix finalOrientation = m.Transform; finalOrientation.Translation = Vector3.Zero; Quaternion finalQuat = Quaternion.CreateFromRotationMatrix(finalOrientation); Vector3 finalPosition = m.GetAbsolutePosition(this.Coord); if (blend > 1.0f) { if (this.StateId != Voxel.t.Empty) { Voxel.Coord c = this.Coord; bool blue = this.StateId == Voxel.t.Blue; bool foundAdjacentCell = false; bool foundConflict = false; if (this.CheckAdjacent) { foreach (Direction dir in DirectionExtensions.Directions) { Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = m[adjacent].ID; if (adjacentID != Voxel.t.Empty) { if (blue && (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.HardInfected || adjacentID == Voxel.t.Slider || adjacentID == Voxel.t.SliderPowered || adjacentID == Voxel.t.SocketWhite || adjacentID == Voxel.t.SocketBlue || adjacentID == Voxel.t.SocketYellow)) { foundConflict = true; } else { foundAdjacentCell = true; if (blue) { if (adjacentID == Voxel.t.Reset) { this.StateId = Voxel.t.Neutral; break; } else if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.PoweredSwitch || adjacentID == Voxel.t.HardPowered) { this.StateId = Voxel.t.Powered; break; } } else { break; } } } } } else { foundAdjacentCell = true; } if (foundAdjacentCell) { Vector3 absolutePos = m.GetAbsolutePosition(c); if (blue && !Zone.CanBuild(absolutePos)) { foundConflict = true; } if (!foundConflict) { bool isDynamic = m.GetType() == typeof(DynamicVoxel); foreach (Voxel m2 in Voxel.ActivePhysicsVoxels) { bool atLeastOneDynamic = isDynamic || m2.GetType() == typeof(DynamicVoxel); if (m2 != m && atLeastOneDynamic && m2[absolutePos].ID != 0) { foundConflict = true; break; } } } if (!foundConflict) { Voxel.State state = m[this.Coord]; if (state.Permanent || state.Hard || state.ID == this.StateId || (blue && state == Voxel.States.Powered)) { foundConflict = true; } else { if (state.ID != 0) { m.Empty(this.Coord); } m.Fill(this.Coord, Voxel.States.All[this.StateId]); m.Regenerate(); if (EffectBlock.random.Next(0, 4) == 0) { AkSoundEngine.PostEvent(AK.EVENTS.PLAY_BLOCK_BUILD, this.Entity); } this.Entity.Delete.Execute(); return; } } } // For one reason or another, we can't fill the cell // Animate nicely into oblivion this.StateId = Voxel.t.Empty; } else { // For one reason or another, we can't fill the cell // Animate nicely into oblivion if (blend > 2.0f) { this.Delete.Execute(); } else { Matrix result = Matrix.CreateFromQuaternion(finalQuat); float scale = 2.0f - blend; result.Right *= scale; result.Up *= scale; result.Forward *= scale; result.Translation = finalPosition; this.Transform.Value = result; } } } else { float scale; if (this.DoScale) { scale = blend; } else { scale = 1.0f; } float distance = (finalPosition - this.StartPosition).Length() * 0.1f * Math.Max(0.0f, 0.5f - Math.Abs(blend - 0.5f)); Matrix result = Matrix.CreateFromQuaternion(Quaternion.Lerp(this.StartOrientation, finalQuat, blend)); result.Right *= scale; result.Up *= scale; result.Forward *= scale; result.Translation = Vector3.Lerp(this.StartPosition, finalPosition, blend) + new Vector3((float)Math.Sin(blend * Math.PI) * distance); this.Transform.Value = result; } }
private bool canBuild(Vector3 pos) { return(Zone.CanBuild(pos) && !Water.IsSubmerged(pos)); }