protected BufferZoneInfo GetBufferZoneInfo(float gravityScale, Direction.Vertical verticalDirection) { BufferZoneInfo bufferZoneInfo = new BufferZoneInfo(); bool willSnapToLedgeHeight = wallClimb.enableClimbing || ledgeGrab.enableLedgeGrab; if(willSnapToLedgeHeight) { RaycastHelper.LedgeInfo ledgeInfo = RaycastHelper.DetectLedgeOnWall(controller.direction.horizontal, (Direction.Vertical)((int)verticalDirection * gravityScale), controller.slots.actor.GetComponent<BoxCollider2D>(), controller.slots.physicsObject.properties.velocity.y * PhysicsManager.Instance.fixedDeltaTime * -(int)verticalDirection); if(!ledgeInfo.didHit) { ledgeInfo = RaycastHelper.DetectLedgeOnWall(controller.direction.horizontal, (Direction.Vertical)((int)verticalDirection * gravityScale), controller.slots.actor.GetComponent<BoxCollider2D>(), controller.slots.physicsObject.properties.velocity.y * PhysicsManager.Instance.fixedDeltaTime * -(int)verticalDirection, 0.0f); } if(ledgeInfo.didHit) { bufferZoneInfo.isLedgeDetected = true; bufferZoneInfo.bufferCutoff = ledgeInfo.hitY - (controller.slots.actor.GetComponent<BoxCollider2D>().size.y * 0.5f * gravityScale * -(int)verticalDirection); float adjustedPositionY = transform.position.y + controller.slots.physicsObject.properties.velocity.y * PhysicsManager.Instance.fixedDeltaTime * -(int)verticalDirection; if(verticalDirection == Direction.Vertical.Down && ((gravityScale < 0.0f && adjustedPositionY < bufferZoneInfo.bufferCutoff) || (gravityScale > 0.0f && adjustedPositionY > bufferZoneInfo.bufferCutoff))) //At top of wall { bufferZoneInfo.isInBufferZone = true; } else if(verticalDirection == Direction.Vertical.Up && ((gravityScale < 0.0f && adjustedPositionY > bufferZoneInfo.bufferCutoff) || (gravityScale > 0.0f && adjustedPositionY < bufferZoneInfo.bufferCutoff))) { bufferZoneInfo.isInBufferZone = true; } } } return bufferZoneInfo; }
void FixedUpdate() { if(!isEnabled || (controller.slots.actor.currentAttack != null && controller.slots.actor.currentAttack.cancels.wallClinging)) { currentWallJumpGraceFrame = 0; currentCooldownFrame = 0; isClingingToWall = false; return; } if(controller.StateID() != FallingState.idString && !controller.isKnockbackActive && !controller.isStunned) { isDropping = false; } CheckForWallCling(); bool isPressingIntoWall = IsPressingIntoWall(); float gravityScale = controller.GravityScaleMultiplier(); BufferZoneInfo bufferZoneInfo_Top = GetBufferZoneInfo(gravityScale, Direction.Vertical.Down); BufferZoneInfo bufferZoneInfo_Bottom = GetBufferZoneInfo(gravityScale, Direction.Vertical.Up); if(isPressingIntoWall && IsClingAllowed() && !isDropping) { if(!(IsJumpActive() && !enableClingWhileJumping)) { if(bufferZoneInfo_Top.isLedgeDetected && !bufferZoneInfo_Top.isInBufferZone) { if((controller.slots.physicsObject.properties.velocity.y * gravityScale) < 0.0f && controller.StateID() != this.id) { controller.slots.actor.SetPosition(new Vector2(controller.slots.actor.transform.position.x, bufferZoneInfo_Top.bufferCutoff)); if(ledgeGrab.enableLedgeGrab) { if(substate != Substate.LedgeHanging) { PlaySecondaryAnimation(animations.ledgeHang); } substate = Substate.LedgeHanging; } } } else if(bufferZoneInfo_Bottom.isLedgeDetected && !bufferZoneInfo_Bottom.isInBufferZone && wallClimb.enableClimbing) { if(!(bufferZoneInfo_Top.isLedgeDetected && bufferZoneInfo_Bottom.isLedgeDetected)) { if((controller.slots.physicsObject.properties.velocity.y * gravityScale) > 0.0f && controller.StateID() != this.id) { controller.slots.actor.SetPosition(new Vector2(controller.slots.actor.transform.position.x, bufferZoneInfo_Bottom.bufferCutoff)); } } } } } float climbableArea = GetComponent<BoxCollider2D>().size.y; if(bufferZoneInfo_Top.isLedgeDetected && bufferZoneInfo_Bottom.isLedgeDetected) { climbableArea = (bufferZoneInfo_Top.bufferCutoff - bufferZoneInfo_Bottom.bufferCutoff) * gravityScale; } if((bufferZoneInfo_Top.isLedgeDetected && bufferZoneInfo_Top.isInBufferZone && controller.slots.physicsObject.properties.velocity.y * gravityScale < 0.0f) || (bufferZoneInfo_Bottom.isLedgeDetected && bufferZoneInfo_Bottom.isInBufferZone && controller.slots.physicsObject.properties.velocity.y * gravityScale >= 0.0f)) { bool isInBothBufferZones = false; if(bufferZoneInfo_Top.isLedgeDetected && bufferZoneInfo_Bottom.isLedgeDetected) { climbableArea = (bufferZoneInfo_Top.bufferCutoff - bufferZoneInfo_Bottom.bufferCutoff) * gravityScale; if(climbableArea < 0.0f && ((transform.position.y <= bufferZoneInfo_Top.bufferCutoff && gravityScale > 0.0f) || (transform.position.y >= bufferZoneInfo_Top.bufferCutoff && gravityScale < 0.0f))) { isInBothBufferZones = true; } } if(!isInBothBufferZones || !IsCooldownComplete() || isDropping) //Ordinarily, disengage from the wall; however, if we're in a buffer zone only because the entire wall is a buffer zone, don't disengage; allow us to stay at the top { isClingingToWall = false; } } if(wallSlideSpeed == 0.0f && !wallClimb.enableClimbing && substate != Substate.LedgeHanging) { isClingingToWall = false; } if(isClingingToWall) { currentWallJumpGraceFrame = wallJump.wallJumpGraceFrames; if(controller.StateID() != idString && !(IsJumpActive() && !enableClingWhileJumping)) { if(controller.StateID() != LadderState.idString && IsCooldownComplete() && !bufferZoneInfo_Top.isInBufferZone) { if(!(bufferZoneInfo_Bottom.isLedgeDetected && bufferZoneInfo_Bottom.isInBufferZone && wallClimb.enableClimbing) || climbableArea < 0.0f) { Begin(); controller.slots.physicsObject.SetVelocityX(0); } } } if(controller.currentState == this) { if(Mathf.Abs(wallSlideSpeed) > 0.0f) { controller.slots.physicsObject.FreezeGravityForSingleFrame(); controller.slots.physicsObject.SetVelocityY(wallSlideSpeed * gravityScale * -1.0f); if(!wallClimb.enableClimbing && substate != Substate.LedgeHanging && !controller.slots.actor.IsAttacking()) { if(substate != Substate.LedgeHanging) { PlayAnimation(); } substate = Substate.Sliding; } } if(wallClimb.enableClimbing || substate == Substate.LedgeHanging) { controller.slots.physicsObject.FreezeGravityForSingleFrame(); controller.slots.physicsObject.SetVelocityY(0.0f); } } if(wallClimb.enableClimbing && Mathf.Abs(controller.slots.input.verticalAxis) > 0.0f && controller.StateID() == idString) { float climbVelocity = controller.slots.input.verticalAxis * wallClimb.climbSpeed * gravityScale; if(climbableArea < GetComponent<BoxCollider2D>().size.y) { climbVelocity = 0.0f; } if(bufferZoneInfo_Top.isLedgeDetected) { if((gravityScale < 0.0f && transform.position.y + (climbVelocity * PhysicsManager.Instance.fixedDeltaTime) < bufferZoneInfo_Top.bufferCutoff) || (gravityScale > 0.0f && transform.position.y + (climbVelocity * PhysicsManager.Instance.fixedDeltaTime) > bufferZoneInfo_Top.bufferCutoff)) { controller.slots.actor.SetPosition(new Vector2(controller.slots.actor.transform.position.x, bufferZoneInfo_Top.bufferCutoff)); climbVelocity = 0.0f; if(ledgeGrab.enableLedgeGrab) { if(substate != Substate.LedgeHanging && !controller.slots.actor.IsAttacking()) { PlaySecondaryAnimation(animations.ledgeHang); } substate = Substate.LedgeHanging; } } } else if(bufferZoneInfo_Bottom.isLedgeDetected) { if((gravityScale < 0.0f && transform.position.y + (climbVelocity * PhysicsManager.Instance.fixedDeltaTime) > bufferZoneInfo_Bottom.bufferCutoff) || (gravityScale > 0.0f && transform.position.y + (climbVelocity * PhysicsManager.Instance.fixedDeltaTime) < bufferZoneInfo_Bottom.bufferCutoff)) { controller.slots.actor.SetPosition(new Vector2(controller.slots.actor.transform.position.x, bufferZoneInfo_Bottom.bufferCutoff)); climbVelocity = 0.0f; } } if(controller.currentState == this) { controller.slots.physicsObject.SetVelocityY(climbVelocity); } if(!(substate == Substate.LedgeHanging && controller.slots.input.verticalAxis > 0.0f)) { if(substate != Substate.Climbing && !controller.slots.actor.IsAttacking()) { PlaySecondaryAnimation(animations.climbWallMoving); } substate = Substate.Climbing; } } else if(wallClimb.enableClimbing) { if(!bufferZoneInfo_Top.isInBufferZone && substate != Substate.LedgeHanging && substate != Substate.Sliding) { if(substate != Substate.Stopped && !controller.slots.actor.IsAttacking()) { PlaySecondaryAnimation(animations.climbWallStopped); } substate = Substate.Stopped; } } } else { if(controller.StateID() == this.id) { controller.SetStateToDefault(); } } UpdateCooldownFrames(); }