public enum AbilityTrigger {
//...
StartOfGame = 19, // On-time
//...
}
public virtual void TriggerPlayerDeckCardsAbilityType(Player player, AbilityTrigger type)
{
if (player.hero != null)
TriggerCardAbilityType(type, player.hero, player.hero);
foreach (Card card in player.cards_deck)
{
TriggerCardAbilityType(type, card, card);
}
}
2.2 Call the new method before the starting cards are drawn (avoiding bugs if you draw a card with StartOfGame effect)
public virtual void StartGame()
{
//...
//Init each player
foreach (Player player in game_data.players)
{
//...
TriggerPlayerDeckCardsAbilityType(player, AbilityTrigger.StartOfGame); // <-- NEW LINE CALLING THE NEW METHOD
//Draw starting cards
//...
}
}
public virtual void StartGame()
{
//...
resolve_queue.ResolveAll(0.2f); // <-- NEW LINE RESOLVING THE QUEUE
//Start state
onGameStart?.Invoke();
resolve_queue.AddCallback(StartTurn); // <-- CHANGED TO BE ADD TO QUEUE
//...
}
In my case I'll add +1 spell damage for the player, so:
Change the trigger to be Start of Game
Change the target to be Player Self
Add the effect add_spell_damage
I just added it to the Unicorn card.
First we'll add a new delay to be able to have delay between ability activations
public class ResolveQueue {
//...
private float resolve_between_delay = 0f;
private float resolve_between_delay_max = 0f;
//...
public virtual voidUpdate(float delta)
{
//...
if (resolve_delay > 0f || resolve_between_delay > 0f) {
resolve_delay -= delta;
resolve_between_delay -= delta;
if (resolve_delay <= 0f && resolve_between_delay <= 0)
ResolveAll();
}
//...
}
//...
public virtual void ResolveAll(float delay, float delayBetween)
{
SetBetweenDelay(delayBetween);
ResolveAll(delay);
}
public virtual void ResolveAll()
{
//...
while (CanResolve())
{
Resolve();
resolve_between_delay = resolve_between_delay_max;
}
}
public virtual void SetBetweenDelay(float delay)
{
if (!skip_delay)
{
resolve_between_delay_max = delay;
}
}
public virtual bool CanResolve()
{
if (resolve_between_delay > 0f)
return false; // Is waiting between effects
}
public virtual bool IsResolving()
{
return is_resolving || resolve_delay > 0f || resolve_between_delay > 0f;
}
}
Create the new Action so server and client should know what expect
public const ushort CardActivated = 2019;
Add the new Action to GameLogic, and change the ResolveAll to have the new Delay, invoking the event when resolving a card with StartOfGame ability
public class GameLogic {
//...
public UnityAction<Card> onCardActivated;
//...
public virtual void StartGame()
{
//Init each players
foreach (Player player in game_data.players)
{
resolve_queue.ResolveAll(1f, 3f);
}
}
public virtual void StartTurn()
{
//...
resolve_queue.SetBetweenDelay(0);
//...
}
protected virtual void ResolveCardAbility(AbilityData iability, Card caster, Card triggerer)
{
//...
if (iability.trigger == AbilityTrigger.StartOfGame)
onCardActivated?.Invoke(caster);
}
}
Setup the server to send a message to the client when onCardActivated is called
public class GameServer
{
protected virtual void Init(string uid, int players, bool online)
{
//...
gameplay.onCardActivated += OnCardActivated;
//...
}
protected virtual void Clear()
{
//...
gameplay.onCardActivated -= OnCardActivated;
//...
}
protected virtual void OnCardActivated(Card card)
{
MsgCard mdata = new MsgCard();
mdata.card_uid = card.uid;
SendToAll(GameAction.CardActivated, mdata, NetworkDelivery.Reliable);
}
}
Setup the client to listen to CardActivated action and invoking it owns UnityAction to notify listeners, example the board.
public class GameClient : MonoBehaviour
{
//...
public UnityAction<Card> onCardActivated;
//...
protected virtual void Start()
{
//...
RegisterRefresh(GameAction.CardActivated, OnCardActivated);
//...
}
private void OnCardActivated(SerializedData sdata)
{
MsgCard msg = sdata.Get<MsgCard>();
Card card = game_data.GetCard(msg.card_uid);
onCardActivated?.Invoke(card);
}
}
And finally listen to the Game Client UnityEvent and show the card prefab to both players.
public class GameBoardFX : MonoBehaviour
{
void Start()
{
//...
client.onCardActivated += OnActivatedCard;
//...
}
void OnActivatedCard(Card card)
{
if (card != null)
{
int player_id = GameClient.Get().GetPlayerID();
CardData icard = CardData.Get(card.card_id);
GameObject prefab = player_id == card.player_id ? AssetData.Get().play_card_fx : AssetData.Get().play_card_other_fx;
GameObject obj = FXTool.DoFX(prefab, Vector3.zero);
CardUI ui = obj.GetComponentInChildren<CardUI>();
ui.SetCard(icard, card.VariantData);
ui.SetText(ui.EnhancedText(card));
}
}
}
https://im.ezgif.com/tmp/ezgif-1-4506387715.gif
Notes:
- You MUST have TCG Engine to add the changes showned above;
- This gist was created using 1.09, so is possible that in the future you will need to change minor details to make it work;
- The CardEditor and Inspector are edited by me, so if you just installed TCG Engine, please consider that are differences in the UI, but are just visual.