cards/CardWizard.cs
using System.Threading.Tasks;
public class CardWizard : Card
{
public override bool IsAlive => true;
public static int NumWizards { get; set; }
public int WizardNum { get; set; }
public override void Init( CardType cardType )
{
base.Init( cardType );
HP = GetMaxHP( CardType );
WizardNum = CardWizard.NumWizards++;
}
public override bool ShouldHandleEvent( EventType eventType )
{
if ( eventType == EventType.TurnStart )
{
var turnVal = Manager.Instance.Stats[StatType.TurnNum] % 4 < 2 ? 0 : 1;
return (Manager.Instance.Stats[StatType.TurnNum] % 3 == 2) && (turnVal == WizardNum % 2) && Manager.Instance.Cards.Count > 2;
}
return (eventType == EventType.LevelStartBoss && CardTypeID == 0) || (eventType == EventType.HurtCards && Manager.Instance.ChosenCards[0] == this);
}
public override async Task HandleEventAsync( EventType eventType )
{
if ( eventType == EventType.LevelStartBoss )
{
var camera = Scene.Camera;
var ray = camera.ScreenPixelToRay( new Vector3( Screen.Width / 2, Screen.Height * 0.65f, 0f ) );
var tr = Scene.Trace.Ray( ray, 10000f ).Run();
Manager.Instance.SpawnFloaterImage(
pos: tr.EndPosition,
filename: Card.GetIconFilename( CardType.Wizard ),
lifetime: 1f,
velocity: new Vector2( 0f, 100f ),
deceleration: 0.5f
);
Manager.Instance.SpawnFloaterText(
pos: tr.EndPosition + new Vector3( 0f, -70f, 0f ),
text: $"Final Boss",
emojiText: "",
lifetime: 1f,
color: new Color( 1f, 1f, 1f ),
velocity: new Vector2( 0f, 100f ),
deceleration: 0.5f,
fontSize: 45f
);
Manager.Instance.SpawnFloaterText(
pos: tr.EndPosition + new Vector3( 0f, -86f, 0f ),
text: $"{Card.GetName( CardType.Wizard )}",
emojiText: "",
lifetime: 1f,
color: new Color( 0.6f, 0.2f, 1f ),
velocity: new Vector2( 0f, 100f ),
deceleration: 0.5f,
fontSize: 60f
);
var hpText = "";
for ( int i = 0; i < Card.GetMaxHP( CardType.Wizard ); i++ )
hpText += "❤️";
Manager.Instance.SpawnFloaterText(
pos: tr.EndPosition + new Vector3( 0f, -103f, 0f ),
text: $"",
emojiText: hpText,
lifetime: 1f,
color: new Color( 1f, 1f, 1f ),
velocity: new Vector2( 0f, 100f ),
deceleration: 0.5f,
fontSize: 35f
);
Manager.Instance.PlaySfxCenter( "wizard_laugh", volume: 1f, pitch: Game.Random.Float( 0.9f, 0.95f ) );
await Task.DelayRealtime( 875 );
}
else if (eventType == EventType.TurnStart)
{
Manager.Instance.PushEventMessage( this, eventType );
await Task.DelayRealtime( 200 );
Manager.Instance.PlayCardSfx( "wizard_laugh", this, volume: 1f, pitch: Game.Random.Float( 0.97f, 1.03f ) );
await Manager.Instance.RevealCard( this );
await Task.DelayRealtime( 400 );
MoveToPos( Manager.GetCardPos( GridPos ).WithZ( 100f ), 0.3f, EasingType.SineOut );
await Task.DelayRealtime( 300 );
Manager.Instance.PlayCardSfx( "wizard_spell_0", this, volume: 1.3f, pitch: Game.Random.Float( 0.85f, 0.95f ) );
// choose other cards
int numOtherCards = Math.Min( 5 - HP, Manager.Instance.Cards.Count - 1 );
List<Card> cardsToShuffle = new() { this };
for ( int i = 0; i < numOtherCards; i++ )
{
var card = Manager.Instance.GetRandomCard( except: cardsToShuffle );
cardsToShuffle.Add( card );
}
// move other cards to self
int cardNum = 0;
foreach ( var card in cardsToShuffle )
{
if ( card == this )
continue;
card.MoveToPos( Manager.GetCardPos( GridPos ).WithZ( 50f - cardNum * 0.1f ), 0.7f, EasingType.SineInOut );
cardNum++;
}
await Task.DelayRealtime( 850 );
Manager.Instance.HideCard( this );
Manager.Instance.PlayCardSfx( "card_flip", this, volume: 0.9f, pitch: Game.Random.Float( 0.65f, 0.75f ) );
await Task.DelayRealtime( 200 );
MoveToPos( Manager.GetCardPos( GridPos ).WithZ( Game.Random.Float( 45f, 50f ) ), 0.3f, EasingType.SineOut );
await Task.DelayRealtime( 400 );
List<IntVector2> newGridPositions = new();
foreach ( var card in cardsToShuffle )
newGridPositions.Add( card.GridPos );
newGridPositions.Shuffle();
foreach ( var card in cardsToShuffle )
Manager.Instance.RemoveCardGridPos( card );
// move self and others to new positions
int count = 0;
foreach ( Card card in cardsToShuffle )
{
card.MoveToPos( Manager.GetCardPos( newGridPositions[count] ), Game.Random.Float( 0.4f, 0.8f ), EasingType.QuadInOut );
count++;
}
Manager.Instance.PlayCardSfx( "wizard_spell_1", this, volume: 1f, pitch: Game.Random.Float( 1.13f, 1.18f ) );
await Task.DelayRealtime( 900 );
count = 0;
foreach ( Card card in cardsToShuffle )
{
await Manager.Instance.SetCardGridPos( card, newGridPositions[count] );
card.IsMovementControlled = false;
count++;
}
await Task.DelayRealtime( 200 );
Manager.Instance.PopEventMessage();
await Manager.Instance.EventHappened( EventType.AfterCardsMoved );
}
else if(eventType == EventType.HurtCards)
{
if(HP > 0)
{
Manager.Instance.PushEventMessage( this, eventType );
await Task.DelayRealtime( 800 );
var wizard0 = Manager.Instance.ChosenCards[0];
var wizard1 = Manager.Instance.ChosenCards[1];
List<Card> respawnedCards = new();
if ( Manager.Instance.CardPairsMatched.Count > 0 )
{
var cardTypeToRespawn = Manager.Instance.CardPairsMatched.Keys.ElementAt( Game.Random.Int( 0, Manager.Instance.CardPairsMatched.Count - 1 ) );
Manager.Instance.CardPairsMatched[cardTypeToRespawn]--;
if ( Manager.Instance.CardPairsMatched[cardTypeToRespawn] == 0 )
Manager.Instance.CardPairsMatched.Remove( cardTypeToRespawn );
Manager.Instance.CardTypePanelHash++;
var emptyGridPositions = Manager.Instance.GetRandomEmptyGridPositions( 2 );
respawnedCards.AddRange( RespawnCardType( cardTypeToRespawn, emptyGridPositions[0], emptyGridPositions[1], offset: 0f ) );
}
for ( int i = 0; i < 2; i++ )
{
var wizard = Manager.Instance.ChosenCards[i];
wizard.MoveToPos( Manager.GetCardPos( wizard.GridPos ).WithZ( 100f ), 0.3f, EasingType.SineOut );
}
await Task.DelayRealtime( 300 );
List<Card> cardsToShuffle = new() { wizard0, wizard1 };
if ( respawnedCards.Count > 0 )
{
Manager.Instance.PlayCardSfxBetween( "wizard_spell_0", wizard0, wizard1, volume: 1.3f, pitch: Game.Random.Float( 0.65f, 0.75f ) );
await Task.DelayRealtime( 1300 );
foreach ( var card in respawnedCards )
Manager.Instance.HideCard( card );
Manager.Instance.PlayCardSfxBetween( "card_flip", wizard0, wizard1, volume: 0.7f, pitch: Game.Random.Float( 0.65f, 0.75f ) );
await Task.DelayRealtime( 800 );
foreach ( var card in respawnedCards )
cardsToShuffle.Add( card );
}
// non-respawned cards to shuffle
Manager.Instance.PlayCardSfx( "wizard_spell_0", this, volume: 1.3f, pitch: Game.Random.Float( 0.85f, 0.95f ) );
int numOtherCards = 5 - HP;
for ( int i = 0; i < Math.Min(numOtherCards, Manager.Instance.Cards.Count - 2); i++ )
{
var card = Manager.Instance.GetRandomCard( except: cardsToShuffle );
if(card != null)
cardsToShuffle.Add( card );
}
// move non-respawned cards cards to wizards
int cardNum = 0;
foreach ( var card in cardsToShuffle )
{
if ( card == wizard0 || card == wizard1 )
continue;
card.MoveToPos( Manager.GetCardPos( (cardNum % 2 == 0 ? wizard0 : wizard1).GridPos ).WithZ( 50f - cardNum * 0.1f ), 0.7f, EasingType.SineInOut );
cardNum++;
}
await Task.DelayRealtime( 850 );
Manager.Instance.HideCard( wizard0 );
Manager.Instance.HideCard( wizard1 );
Manager.Instance.PlayCardSfxBetween( "card_flip", wizard0, wizard1, volume: 0.9f, pitch: Game.Random.Float( 0.65f, 0.75f ) );
wizard0.MoveToPos( Manager.GetCardPos( wizard0.GridPos ).WithZ( Game.Random.Float( 45f, 50f ) ), 0.3f, EasingType.SineOut );
wizard1.MoveToPos( Manager.GetCardPos( wizard1.GridPos ).WithZ( Game.Random.Float( 45f, 50f ) ), 0.3f, EasingType.SineOut );
await Task.DelayRealtime( 600 );
List<IntVector2> newGridPositions = new();
foreach ( var card in cardsToShuffle )
newGridPositions.Add( card.GridPos );
newGridPositions.Shuffle();
foreach ( var card in cardsToShuffle )
Manager.Instance.RemoveCardGridPos( card );
int count = 0;
foreach ( Card card in cardsToShuffle )
{
card.MoveToPos( Manager.GetCardPos( newGridPositions[count] ), Game.Random.Float( 0.4f, 0.8f ), EasingType.QuadInOut );
count++;
}
Manager.Instance.PlayCardSfxBetween( "wizard_spell_1", wizard0, wizard1, volume: 1f, pitch: Game.Random.Float( 1.13f, 1.18f ) );
await Task.DelayRealtime( 900 );
count = 0;
foreach ( Card card in cardsToShuffle )
{
await Manager.Instance.SetCardGridPos( card, newGridPositions[count] );
card.IsMovementControlled = false;
count++;
}
await Task.DelayRealtime( 200 );
Manager.Instance.PopEventMessage();
await Manager.Instance.EventHappened( EventType.AfterCardsMoved );
}
else
{
await Task.DelayRealtime( 800 );
// todo: death sfx
}
}
}
List<Card> RespawnCardType(CardType cardType, IntVector2 gridPos0, IntVector2 gridPos1, float offset)
{
List<Card> cards = new();
for ( int i = 0; i < 2; i++ )
{
var wizard = Manager.Instance.ChosenCards[i];
var card = Manager.Instance.CreateCard( i == 0 ? gridPos0 : gridPos1, cardType, cardTypeID: i, createOutline: false );
var randomVec2 = Utils.GetRandomVector();
card.LocalPosition = (wizard.LocalPosition + new Vector3( randomVec2.x, randomVec2.y, 0f ) * 300f).WithZ( wizard.LocalPosition.z - 10f );
card.SetRevealedInstant();
card.MoveToPos( Manager.GetCardPos( wizard.GridPos ).WithZ( 50f - i * 0.1f - offset ), 2f, EasingType.SineOut );
cards.Add( card );
}
return cards;
}
public override string GetEventText( EventType eventType )
{
if(eventType == EventType.TurnStart)
{
return "⏩Every 3 turns: shuffle some cards";
}
else
{
return "💔Damage Wizard: respawn some cards and shuffle them";
}
}
public override void PlayHurtSfx( Card card0, Card card1 )
{
Manager.Instance.PlayCardSfxBetween( "wizard_hurt", card0, card1, volume: 2.6f, pitch: Utils.Map(HP, GetMaxHP(CardType), 0, 1.2f, 0.7f));
}
}