cards/CardBodybuilder.cs
using Sandbox;
using System.Threading.Tasks;
public class CardBodybuilder : Card
{
public override bool IsAlive => true;
private Dictionary<IntVector2, Card> _cardAbovePositions = new();
public override bool ValidateStartingGridPos()
{
if ( GridPos.y < Manager.Instance.GridHeight - 1 )
return true;
int NUM_TRIES = 100;
for ( int i = 0; i < NUM_TRIES; i++ )
{
var newGridPos = Manager.Instance.GetRandomGridPos( except: GridPos );
var otherCard = Manager.Instance.GetCardAtGridPos( newGridPos );
if ( newGridPos.y < Manager.Instance.GridHeight - 1 && otherCard.CardType != CardType.Balloon && otherCard.CardType != CardType.Rock && otherCard.CardType != CardType.Pawn )
{
Manager.Instance.SwapCardPositionsNonAsync( this, otherCard );
break;
}
}
return false;
}
public override bool ShouldHandleEvent( EventType eventType )
{
if ( eventType == EventType.TurnStart )
{
foreach( var card in Manager.Instance.GetNearbyCards(GridPos))
{
if ( CanRise( card ) )
return true;
}
}
return false;
}
public override async Task HandleEventAsync( EventType eventType )
{
List<Card> potentialCards = new();
foreach ( var card in Manager.Instance.GetNearbyCards( GridPos, adjacentOnly: true ) )
{
if ( CanRise( card ) )
potentialCards.Add( card );
}
if ( potentialCards.Count == 0 )
return;
var cardToLift = potentialCards[Game.Random.Int(0, potentialCards.Count - 1)];
await Task.DelayRealtime( 500 );
Manager.Instance.PlayCardSfx( "card_move", cardToLift, volume: 1.1f, pitch: Game.Random.Float( 0.85f, 1.15f ) );
_cardAbovePositions.Clear();
RemoveCurrentGridPositions( cardToLift );
await MoveUpward( cardToLift, setGridPos: false );
await MoveUpward( cardToLift, setGridPos: true );
await Task.DelayRealtime( 400 );
await Manager.Instance.EventHappened( EventType.AfterCardsMoved );
}
bool CanRise(Card card)
{
// don't lift card directly below
if ( card.GridPos.y == GridPos.y - 1 )
return false;
var currGridPos = card.GridPos + new IntVector2( 0, 1 );
while ( Manager.Instance.IsGridPosInBounds( currGridPos ) )
{
if ( Manager.Instance.IsGridPosEmpty( currGridPos ) )
return true;
currGridPos += new IntVector2( 0, 1 );
}
return false;
}
async Task MoveUpward(Card card, bool setGridPos)
{
var gridPosAbove = card.GridPos + new IntVector2( 0, 1 );
Card cardAbove = _cardAbovePositions.ContainsKey( gridPosAbove ) ? _cardAbovePositions[gridPosAbove] : null;
if( setGridPos )
{
await Manager.Instance.SetCardGridPos( card, gridPosAbove );
card.IsMovementControlled = false;
}
else
{
card.MoveToPos( Manager.GetCardPos( gridPosAbove ), 0.3f, EasingType.SineOut );
}
if(cardAbove != null )
{
await MoveUpward(cardAbove, setGridPos);
}
}
void RemoveCurrentGridPositions(Card card)
{
var currGridPos = card.GridPos;
while ( Manager.Instance.IsGridPosInBounds( currGridPos ) )
{
var currCard = Manager.Instance.GetCardAtGridPos( currGridPos );
_cardAbovePositions.Add( currGridPos, currCard );
Manager.Instance.RemoveCardGridPos( currCard );
currGridPos += new IntVector2( 0, 1 );
var cardAbove = Manager.Instance.GetCardAtGridPos( currGridPos );
if ( cardAbove == null )
break;
}
}
}