This commit is contained in:
yaoyanwei
2025-08-04 16:45:48 +08:00
parent 565aa16389
commit 2f2a601227
2296 changed files with 522745 additions and 93 deletions

View File

@@ -0,0 +1,692 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Gameplay;
namespace TcgEngine
{
/// <summary>
/// Defines all ability data
/// </summary>
[CreateAssetMenu(fileName = "ability", menuName = "TcgEngine/AbilityData", order = 5)]
public class AbilityData : ScriptableObject
{
public string id;
[Header("Trigger")]
public AbilityTrigger trigger; //WHEN does the ability trigger?
public ConditionData[] conditions_trigger; //Condition checked on the card triggering the ability (usually the caster)
[Header("Target")]
public AbilityTarget target; //WHO is targeted?
public ConditionData[] conditions_target; //Condition checked on the target to know if its a valid taget
public FilterData[] filters_target; //Condition checked on the target to know if its a valid taget
[Header("Effect")]
public EffectData[] effects; //WHAT this does?
public StatusData[] status; //Status added by this ability
public int value; //Value passed to the effect (deal X damage)
public int duration; //Duration passed to the effect (usually for status, 0=permanent)
[Header("Chain/Choices")]
public AbilityData[] chain_abilities; //Abilities that will be triggered after this one
[Header("Activated Ability")]
public int mana_cost; //Mana cost for activated abilities
public bool exhaust; //Action cost for activated abilities
[Header("FX")]
public GameObject board_fx;
public GameObject caster_fx;
public GameObject target_fx;
public GameObject projectile_fx;
public AudioClip cast_audio;
public AudioClip target_audio;
public bool charge_target;
[Header("Text")]
public string title;
[TextArea(5, 7)]
public string desc;
public static List<AbilityData> ability_list = new List<AbilityData>(); //Faster access in loops
public static Dictionary<string, AbilityData> ability_dict = new Dictionary<string, AbilityData>(); //Faster access in Get(id)
public static void Load(string folder = "")
{
if (ability_list.Count == 0)
{
ability_list.AddRange(Resources.LoadAll<AbilityData>(folder));
foreach (AbilityData ability in ability_list)
ability_dict.Add(ability.id, ability);
}
}
public string GetTitle()
{
return title;
}
public string GetDesc()
{
return desc;
}
public string GetDesc(CardData card)
{
string dsc = desc;
dsc = dsc.Replace("<name>", card.title);
dsc = dsc.Replace("<value>", value.ToString());
dsc = dsc.Replace("<duration>", duration.ToString());
return dsc;
}
//Generic condition for the ability to trigger
public bool AreTriggerConditionsMet(Game data, Card caster)
{
return AreTriggerConditionsMet(data, caster, caster); //Triggerer is the caster
}
//Some abilities are caused by another card (PlayOther), otherwise most of the time the triggerer is the caster, check condition on triggerer
public bool AreTriggerConditionsMet(Game data, Card caster, Card trigger_card)
{
foreach (ConditionData cond in conditions_trigger)
{
if (cond != null)
{
if (!cond.IsTriggerConditionMet(data, this, caster))
return false;
if (!cond.IsTargetConditionMet(data, this, caster, trigger_card))
return false;
}
}
return true;
}
//Some abilities are caused by an action on a player (OnFight when attacking the player), check condition on that player
public bool AreTriggerConditionsMet(Game data, Card caster, Player trigger_player)
{
foreach (ConditionData cond in conditions_trigger)
{
if (cond != null)
{
if (!cond.IsTriggerConditionMet(data, this, caster))
return false;
if (!cond.IsTargetConditionMet(data, this, caster, trigger_player))
return false;
}
}
return true;
}
//Check if the card target is valid
public bool AreTargetConditionsMet(Game data, Card caster, Card target_card)
{
foreach (ConditionData cond in conditions_target)
{
if (cond != null && !cond.IsTargetConditionMet(data, this, caster, target_card))
return false;
}
return true;
}
//Check if the player target is valid
public bool AreTargetConditionsMet(Game data, Card caster, Player target_player)
{
foreach (ConditionData cond in conditions_target)
{
if (cond != null && !cond.IsTargetConditionMet(data, this, caster, target_player))
return false;
}
return true;
}
//Check if the slot target is valid
public bool AreTargetConditionsMet(Game data, Card caster, Slot target_slot)
{
foreach (ConditionData cond in conditions_target)
{
if (cond != null && !cond.IsTargetConditionMet(data, this, caster, target_slot))
return false;
}
return true;
}
//Check if the card data target is valid
public bool AreTargetConditionsMet(Game data, Card caster, CardData target_card)
{
foreach (ConditionData cond in conditions_target)
{
if (cond != null && !cond.IsTargetConditionMet(data, this, caster, target_card))
return false;
}
return true;
}
//CanTarget is similar to AreTargetConditionsMet but only applies to targets on the board, with extra board-only conditions
public bool CanTarget(Game data, Card caster, Card target)
{
if (target.HasStatus(StatusType.Stealth))
return false; //Hidden
if (target.HasStatus(StatusType.SpellImmunity))
return false; //Spell immunity
bool condition_match = AreTargetConditionsMet(data, caster, target);
return condition_match;
}
//Can target check additional restrictions and is usually for SelectTarget or PlayTarget abilities
public bool CanTarget(Game data, Card caster, Player target)
{
bool condition_match = AreTargetConditionsMet(data, caster, target);
return condition_match;
}
public bool CanTarget(Game data, Card caster, Slot target)
{
return AreTargetConditionsMet(data, caster, target); //No additional conditions for slots
}
//Check if destination array has the target after being filtered, used to support filters in CardSelector
public bool IsCardSelectionValid(Game data, Card caster, Card target, ListSwap<Card> card_array = null)
{
List<Card> targets = GetCardTargets(data, caster, card_array);
return targets.Contains(target); //Card is still in array after filtering
}
public void DoEffects(GameLogic logic, Card caster)
{
foreach(EffectData effect in effects)
effect?.DoEffect(logic, this, caster);
}
public void DoEffects(GameLogic logic, Card caster, Card target)
{
foreach (EffectData effect in effects)
effect?.DoEffect(logic, this, caster, target);
foreach(StatusData stat in status)
target.AddStatus(stat, value, duration);
}
public void DoEffects(GameLogic logic, Card caster, Player target)
{
foreach (EffectData effect in effects)
effect?.DoEffect(logic, this, caster, target);
foreach (StatusData stat in status)
target.AddStatus(stat, value, duration);
}
public void DoEffects(GameLogic logic, Card caster, Slot target)
{
foreach (EffectData effect in effects)
effect?.DoEffect(logic, this, caster, target);
}
public void DoEffects(GameLogic logic, Card caster, CardData target)
{
foreach (EffectData effect in effects)
effect?.DoEffect(logic, this, caster, target);
}
public void DoOngoingEffects(GameLogic logic, Card caster, Card target)
{
foreach (EffectData effect in effects)
effect?.DoOngoingEffect(logic, this, caster, target);
foreach (StatusData stat in status)
target.AddOngoingStatus(stat, value);
}
public void DoOngoingEffects(GameLogic logic, Card caster, Player target)
{
foreach (EffectData effect in effects)
effect?.DoOngoingEffect(logic, this, caster, target);
foreach (StatusData stat in status)
target.AddOngoingStatus(stat, value);
}
public bool HasEffect<T>() where T : EffectData
{
foreach (EffectData eff in effects)
{
if (eff != null && eff is T)
return true;
}
return false;
}
public bool HasStatus(StatusType type)
{
foreach (StatusData sta in status)
{
if (sta != null && sta.effect == type)
return true;
}
return false;
}
public int GetDamage()
{
int damage = 0;
foreach (EffectData eff in effects)
{
if (eff != null && eff is EffectDamage)
{
damage += this.value;
}
}
return damage;
}
private void AddValidCards(Game data, Card caster, List<Card> source, List<Card> targets)
{
foreach (Card card in source)
{
if (AreTargetConditionsMet(data, caster, card))
targets.Add(card);
}
}
//Return cards targets, memory_array is used for optimization and avoid allocating new memory
public List<Card> GetCardTargets(Game data, Card caster, ListSwap<Card> memory_array = null)
{
if (memory_array == null)
memory_array = new ListSwap<Card>(); //Slow operation
List<Card> targets = memory_array.Get();
if (target == AbilityTarget.Self)
{
if (AreTargetConditionsMet(data, caster, caster))
targets.Add(caster);
}
if (target == AbilityTarget.AllCardsBoard || target == AbilityTarget.SelectTarget)
{
foreach (Player player in data.players)
{
foreach (Card card in player.cards_board)
{
if (AreTargetConditionsMet(data, caster, card))
targets.Add(card);
}
}
}
if (target == AbilityTarget.AllCardsHand)
{
foreach (Player player in data.players)
{
foreach (Card card in player.cards_hand)
{
if (AreTargetConditionsMet(data, caster, card))
targets.Add(card);
}
}
}
if (target == AbilityTarget.AllCardsAllPiles || target == AbilityTarget.CardSelector)
{
foreach (Player player in data.players)
{
AddValidCards(data, caster, player.cards_deck, targets);
AddValidCards(data, caster, player.cards_discard, targets);
AddValidCards(data, caster, player.cards_hand, targets);
AddValidCards(data, caster, player.cards_secret, targets);
AddValidCards(data, caster, player.cards_board, targets);
AddValidCards(data, caster, player.cards_equip, targets);
AddValidCards(data, caster, player.cards_temp, targets);
}
}
if (target == AbilityTarget.LastPlayed)
{
Card target = data.GetCard(data.last_played);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
if (target == AbilityTarget.LastDestroyed)
{
Card target = data.GetCard(data.last_destroyed);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
if (target == AbilityTarget.LastTargeted)
{
Card target = data.GetCard(data.last_target);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
if (target == AbilityTarget.LastSummoned)
{
Card target = data.GetCard(data.last_summoned);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
if (target == AbilityTarget.AbilityTriggerer)
{
Card target = data.GetCard(data.ability_triggerer);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
if (target == AbilityTarget.EquippedCard)
{
if (caster.CardData.IsEquipment())
{
//Get bearer of the equipment
Player player = data.GetPlayer(caster.player_id);
Card target = player.GetBearerCard(caster);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
else if(caster.equipped_uid != null)
{
//Get equipped card
Card target = data.GetCard(caster.equipped_uid);
if (target != null && AreTargetConditionsMet(data, caster, target))
targets.Add(target);
}
}
//Filter targets
if (filters_target != null && targets.Count > 0)
{
foreach (FilterData filter in filters_target)
{
if (filter != null)
targets = filter.FilterTargets(data, this, caster, targets, memory_array.GetOther(targets));
}
}
return targets;
}
//Return player targets, memory_array is used for optimization and avoid allocating new memory
public List<Player> GetPlayerTargets(Game data, Card caster, ListSwap<Player> memory_array = null)
{
if (memory_array == null)
memory_array = new ListSwap<Player>(); //Slow operation
List<Player> targets = memory_array.Get();
if (target == AbilityTarget.PlayerSelf)
{
Player player = data.GetPlayer(caster.player_id);
targets.Add(player);
}
else if (target == AbilityTarget.PlayerOpponent)
{
for (int tp = 0; tp < data.players.Length; tp++)
{
if (tp != caster.player_id)
{
Player oplayer = data.players[tp];
targets.Add(oplayer);
}
}
}
else if (target == AbilityTarget.AllPlayers)
{
foreach (Player player in data.players)
{
if (AreTargetConditionsMet(data, caster, player))
targets.Add(player);
}
}
//Filter targets
if (filters_target != null && targets.Count > 0)
{
foreach (FilterData filter in filters_target)
{
if (filter != null)
targets = filter.FilterTargets(data, this, caster, targets, memory_array.GetOther(targets));
}
}
return targets;
}
//Return slot targets, memory_array is used for optimization and avoid allocating new memory
public List<Slot> GetSlotTargets(Game data, Card caster, ListSwap<Slot> memory_array = null)
{
if (memory_array == null)
memory_array = new ListSwap<Slot>(); //Slow operation
List<Slot> targets = memory_array.Get();
if (target == AbilityTarget.AllSlots)
{
List<Slot> slots = Slot.GetAll();
foreach (Slot slot in slots)
{
if (AreTargetConditionsMet(data, caster, slot))
targets.Add(slot);
}
}
//Filter targets
if (filters_target != null && targets.Count > 0)
{
foreach (FilterData filter in filters_target)
{
if (filter != null)
targets = filter.FilterTargets(data, this, caster, targets, memory_array.GetOther(targets));
}
}
return targets;
}
public List<CardData> GetCardDataTargets(Game data, Card caster, ListSwap<CardData> memory_array = null)
{
if (memory_array == null)
memory_array = new ListSwap<CardData>(); //Slow operation
List<CardData> targets = memory_array.Get();
if (target == AbilityTarget.AllCardData)
{
foreach (CardData card in CardData.GetAll())
{
if (AreTargetConditionsMet(data, caster, card))
targets.Add(card);
}
}
//Filter targets
if (filters_target != null && targets.Count > 0)
{
foreach (FilterData filter in filters_target)
{
if (filter != null)
targets = filter.FilterTargets(data, this, caster, targets, memory_array.GetOther(targets));
}
}
return targets;
}
// Check if there is any valid target, if not, AI wont try to cast activated ability
public bool HasValidSelectTarget(Game game_data, Card caster)
{
if (target == AbilityTarget.SelectTarget)
{
if (HasValidBoardCardTarget(game_data, caster))
return true;
if (HasValidPlayerTarget(game_data, caster))
return true;
if (HasValidSlotTarget(game_data, caster))
return true;
return false;
}
if (target == AbilityTarget.CardSelector)
{
if (HasValidCardTarget(game_data, caster))
return true;
return false;
}
if (target == AbilityTarget.ChoiceSelector)
{
foreach (AbilityData choice in chain_abilities)
{
if(choice.AreTriggerConditionsMet(game_data, caster))
return true;
}
return false;
}
return true; //Not selecting, valid
}
public bool HasValidBoardCardTarget(Game game_data, Card caster)
{
for (int p = 0; p < game_data.players.Length; p++)
{
Player player = game_data.players[p];
for (int c = 0; c < player.cards_board.Count; c++)
{
Card card = player.cards_board[c];
if (CanTarget(game_data, caster, card))
return true;
}
}
return false;
}
public bool HasValidCardTarget(Game game_data, Card caster)
{
for (int p = 0; p < game_data.players.Length; p++)
{
Player player = game_data.players[p];
bool v1 = HasValidCardTarget(game_data, caster, player.cards_deck);
bool v2 = HasValidCardTarget(game_data, caster, player.cards_discard);
bool v3 = HasValidCardTarget(game_data, caster, player.cards_hand);
bool v4 = HasValidCardTarget(game_data, caster, player.cards_board);
bool v5 = HasValidCardTarget(game_data, caster, player.cards_equip);
bool v6 = HasValidCardTarget(game_data, caster, player.cards_secret);
bool v7 = HasValidCardTarget(game_data, caster, player.cards_temp);
if (v1 || v2 || v3 || v4 || v5 || v6 || v7)
return true;
}
return false;
}
public bool HasValidCardTarget(Game game_data, Card caster, List<Card> list)
{
for (int c = 0; c < list.Count; c++)
{
Card card = list[c];
if (AreTargetConditionsMet(game_data, caster, card))
return true;
}
return false;
}
public bool HasValidPlayerTarget(Game game_data, Card caster)
{
for (int p = 0; p < game_data.players.Length; p++)
{
Player player = game_data.players[p];
if (CanTarget(game_data, caster, player))
return true;
}
return false;
}
public bool HasValidSlotTarget(Game game_data, Card caster)
{
foreach (Slot slot in Slot.GetAll())
{
if (CanTarget(game_data, caster, slot))
return true;
}
return false;
}
public bool IsSelector()
{
return target == AbilityTarget.SelectTarget || target == AbilityTarget.CardSelector || target == AbilityTarget.ChoiceSelector;
}
public static AbilityData Get(string id)
{
if (id == null)
return null;
bool success = ability_dict.TryGetValue(id, out AbilityData ability);
if (success)
return ability;
return null;
}
public static List<AbilityData> GetAll()
{
return ability_list;
}
}
public enum AbilityTrigger
{
None = 0,
Ongoing = 2, //Always active (does not work with all effects)
Activate = 5, //Action
OnPlay = 10, //When playeds
OnPlayOther = 12, //When another card played
StartOfTurn = 20, //Every turn
EndOfTurn = 22, //Every turn
OnBeforeAttack = 30, //When attacking, before damage
OnAfterAttack = 31, //When attacking, after damage if still alive
OnBeforeDefend = 32, //When being attacked, before damage
OnAfterDefend = 33, //When being attacked, after damage if still alive
OnKill = 35, //When killing another card during an attack
OnDeath = 40, //When dying
OnDeathOther = 42, //When another dying
}
public enum AbilityTarget
{
None = 0,
Self = 1,
PlayerSelf = 4,
PlayerOpponent = 5,
AllPlayers = 7,
AllCardsBoard = 10,
AllCardsHand = 11,
AllCardsAllPiles = 12,
AllSlots = 15,
AllCardData = 17, //For card Create effects only
PlayTarget = 20, //The target selected at the same time the spell was played (spell only)
AbilityTriggerer = 25, //The card that triggered the trap
EquippedCard = 27, //If equipment, the bearer, if character, the item equipped
SelectTarget = 30, //Select a card, player or slot on board
CardSelector = 40, //Card selector menu
ChoiceSelector = 50, //Choice selector menu
LastPlayed = 70, //Last card that was played
LastTargeted = 72, //Last card that was targeted with an ability
LastDestroyed = 74, //Last card that was killed
LastSummoned = 77, //Last card that was summoned or created
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ce5f81e5cc37f547af6923758602c8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
//Default fx and audio, some can be overrided on each individual card
[CreateAssetMenu(fileName = "AssetData", menuName = "TcgEngine/AssetData", order = 0)]
public class AssetData : ScriptableObject
{
[Header("FX")]
public GameObject card_spawn_fx;
public GameObject card_destroy_fx;
public GameObject card_attack_fx;
public GameObject card_damage_fx;
public GameObject card_exhausted_fx;
public GameObject player_damage_fx;
public GameObject damage_fx;
public GameObject play_card_fx;
public GameObject play_card_other_fx;
public GameObject play_secret_fx;
public GameObject play_secret_other_fx;
public GameObject dice_roll_fx;
public GameObject hover_text_box;
public GameObject new_turn_fx;
public GameObject win_fx;
public GameObject lose_fx;
public GameObject tied_fx;
[Header("Audio")]
public AudioClip card_spawn_audio;
public AudioClip card_destroy_audio;
public AudioClip card_attack_audio;
public AudioClip card_move_audio;
public AudioClip card_damage_audio;
public AudioClip player_damage_audio;
public AudioClip hand_card_click_audio;
public AudioClip new_turn_audio;
public AudioClip win_audio;
public AudioClip defeat_audio;
public AudioClip win_music;
public AudioClip defeat_music;
public static AssetData Get()
{
return DataLoader.Get().assets;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cca20da9cbfd28a449b51ac452845bc8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all avatar data
/// </summary>
[CreateAssetMenu(fileName = "Avatar", menuName = "TcgEngine/Avatar", order = 10)]
public class AvatarData : ScriptableObject
{
public string id;
public Sprite avatar;
public int sort_order;
public static List<AvatarData> avatar_list = new List<AvatarData>();
public static void Load(string folder = "")
{
if (avatar_list.Count == 0)
avatar_list.AddRange(Resources.LoadAll<AvatarData>(folder));
avatar_list.Sort((AvatarData a, AvatarData b) => {
if (a.sort_order == b.sort_order)
return a.id.CompareTo(b.id);
else
return a.sort_order.CompareTo(b.sort_order);
});
}
public static AvatarData Get(string id)
{
foreach (AvatarData avatar in GetAll())
{
if (avatar.id == id)
return avatar;
}
return null;
}
public static List<AvatarData> GetAll()
{
return avatar_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c92c9d3c273cc8940be4b9e940d8933e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,316 @@
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
public enum CardType
{
None = 0,
Hero = 5,
Character = 10,
Spell = 20,
Artifact = 30,
Secret = 40,
Equipment = 50,
}
/// <summary>
/// Defines all card data
/// </summary>
[CreateAssetMenu(fileName = "card", menuName = "TcgEngine/CardData", order = 5)]
public class CardData : ScriptableObject
{
public string id;
[Header("Display")]
public string title;
public Sprite art_full;
public Sprite art_board;
[Header("Stats")]
public CardType type;
public TeamData team;
public RarityData rarity;
public int mana;
public int attack;
public int hp;
[Header("Traits")]
public TraitData[] traits;
public TraitStat[] stats;
[Header("Abilities")]
public AbilityData[] abilities;
[Header("Card Text")]
[TextArea(3, 5)]
public string text;
[Header("Description")]
[TextArea(5, 10)]
public string desc;
[Header("FX")]
public GameObject spawn_fx;
public GameObject death_fx;
public GameObject attack_fx;
public GameObject damage_fx;
public GameObject idle_fx;
public AudioClip spawn_audio;
public AudioClip death_audio;
public AudioClip attack_audio;
public AudioClip damage_audio;
[Header("Availability")]
public bool deckbuilding = false;
public int cost = 100;
public PackData[] packs;
public static List<CardData> card_list = new List<CardData>(); //Faster access in loops
public static Dictionary<string, CardData> card_dict = new Dictionary<string, CardData>(); //Faster access in Get(id)
public static void Load(string folder = "")
{
if (card_list.Count == 0)
{
card_list.AddRange(Resources.LoadAll<CardData>(folder));
foreach (CardData card in card_list)
card_dict.Add(card.id, card);
}
}
public Sprite GetBoardArt(VariantData variant)
{
return art_board;
}
public Sprite GetFullArt(VariantData variant)
{
return art_full;
}
public string GetTitle()
{
return title;
}
public string GetText()
{
return text;
}
public string GetDesc()
{
return desc;
}
public string GetTypeId()
{
if (type == CardType.Hero)
return "hero";
if (type == CardType.Character)
return "character";
if (type == CardType.Artifact)
return "artifact";
if (type == CardType.Spell)
return "spell";
if (type == CardType.Secret)
return "secret";
if (type == CardType.Equipment)
return "equipment";
return "";
}
public string GetAbilitiesDesc()
{
string txt = "";
foreach (AbilityData ability in abilities)
{
if (!string.IsNullOrWhiteSpace(ability.desc))
txt += "<b>" + ability.GetTitle() + ":</b> " + ability.GetDesc(this) + "\n";
}
return txt;
}
public bool IsCharacter()
{
return type == CardType.Character;
}
public bool IsSecret()
{
return type == CardType.Secret;
}
public bool IsBoardCard()
{
return type == CardType.Character || type == CardType.Artifact;
}
public bool IsRequireTarget()
{
return type == CardType.Equipment || IsRequireTargetSpell();
}
public bool IsRequireTargetSpell()
{
return type == CardType.Spell && HasAbility(AbilityTrigger.OnPlay, AbilityTarget.PlayTarget);
}
public bool IsEquipment()
{
return type == CardType.Equipment;
}
public bool IsDynamicManaCost()
{
return mana > 99;
}
public bool HasTrait(string trait)
{
foreach (TraitData t in traits)
{
if (t.id == trait)
return true;
}
return false;
}
public bool HasTrait(TraitData trait)
{
if(trait != null)
return HasTrait(trait.id);
return false;
}
public bool HasStat(string trait)
{
if (stats == null)
return false;
foreach (TraitStat stat in stats)
{
if (stat.trait.id == trait)
return true;
}
return false;
}
public bool HasStat(TraitData trait)
{
if(trait != null)
return HasStat(trait.id);
return false;
}
public int GetStat(string trait_id)
{
if (stats == null)
return 0;
foreach (TraitStat stat in stats)
{
if (stat.trait.id == trait_id)
return stat.value;
}
return 0;
}
public int GetStat(TraitData trait)
{
if(trait != null)
return GetStat(trait.id);
return 0;
}
public bool HasAbility(AbilityData tability)
{
foreach (AbilityData ability in abilities)
{
if (ability && ability.id == tability.id)
return true;
}
return false;
}
public bool HasAbility(AbilityTrigger trigger)
{
foreach (AbilityData ability in abilities)
{
if (ability && ability.trigger == trigger)
return true;
}
return false;
}
public bool HasAbility(AbilityTrigger trigger, AbilityTarget target)
{
foreach (AbilityData ability in abilities)
{
if (ability && ability.trigger == trigger && ability.target == target)
return true;
}
return false;
}
public AbilityData GetAbility(AbilityTrigger trigger)
{
foreach (AbilityData ability in abilities)
{
if (ability && ability.trigger == trigger)
return ability;
}
return null;
}
public bool HasPack(PackData pack)
{
foreach (PackData apack in packs)
{
if (apack == pack)
return true;
}
return false;
}
public static CardData Get(string id)
{
if (id == null)
return null;
bool success = card_dict.TryGetValue(id, out CardData card);
if (success)
return card;
return null;
}
public static List<CardData> GetAllDeckbuilding()
{
List<CardData> multi_list = new List<CardData>();
foreach (CardData acard in GetAll())
{
if (acard.deckbuilding)
multi_list.Add(acard);
}
return multi_list;
}
public static List<CardData> GetAll(PackData pack)
{
List<CardData> multi_list = new List<CardData>();
foreach (CardData acard in GetAll())
{
if (acard.HasPack(pack))
multi_list.Add(acard);
}
return multi_list;
}
public static List<CardData> GetAll()
{
return card_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 843a21f7f6f205741a0a7341aec8e84d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all cardback data
/// </summary>
[CreateAssetMenu(fileName = "Cardback", menuName = "TcgEngine/Cardback", order = 10)]
public class CardbackData : ScriptableObject
{
public string id;
public Sprite cardback;
public Sprite deck;
public int sort_order;
public static List<CardbackData> cardback_list = new List<CardbackData>();
public static void Load(string folder = "")
{
if (cardback_list.Count == 0)
cardback_list.AddRange(Resources.LoadAll<CardbackData>(folder));
cardback_list.Sort((CardbackData a, CardbackData b) => {
if (a.sort_order == b.sort_order)
return a.id.CompareTo(b.id);
else
return a.sort_order.CompareTo(b.sort_order);
});
}
public static CardbackData Get(string id)
{
foreach (CardbackData cardback in GetAll())
{
if (cardback.id == id)
return cardback;
}
return null;
}
public static List<CardbackData> GetAll()
{
return cardback_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b848b003e799d264cba32a383c514e74
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Base class for all ability conditions, override the IsConditionMet function
/// </summary>
public class ConditionData : ScriptableObject
{
public virtual bool IsTriggerConditionMet(Game data, AbilityData ability, Card caster)
{
return true; //Override this, applies to any target, always checked
}
public virtual bool IsTargetConditionMet(Game data, AbilityData ability, Card caster, Card target)
{
return true; //Override this, condition targeting card
}
public virtual bool IsTargetConditionMet(Game data, AbilityData ability, Card caster, Player target)
{
return true; //Override this, condition targeting player
}
public virtual bool IsTargetConditionMet(Game data, AbilityData ability, Card caster, Slot target)
{
return true; //Override this, condition targeting slot
}
public virtual bool IsTargetConditionMet(Game data, AbilityData ability, Card caster, CardData target)
{
return true; //Override this, for effects that create new cards
}
public bool CompareBool(bool condition, ConditionOperatorBool oper)
{
if (oper == ConditionOperatorBool.IsFalse)
return !condition;
return condition;
}
public bool CompareInt(int ival1, ConditionOperatorInt oper, int ival2)
{
if (oper == ConditionOperatorInt.Equal)
{
return ival1 == ival2;
}
if (oper == ConditionOperatorInt.NotEqual)
{
return ival1 != ival2;
}
if (oper == ConditionOperatorInt.GreaterEqual)
{
return ival1 >= ival2;
}
if (oper == ConditionOperatorInt.LessEqual)
{
return ival1 <= ival2;
}
if (oper == ConditionOperatorInt.Greater)
{
return ival1 > ival2;
}
if (oper == ConditionOperatorInt.Less)
{
return ival1 < ival2; ;
}
return false;
}
}
public enum ConditionOperatorInt
{
Equal,
NotEqual,
GreaterEqual,
LessEqual,
Greater,
Less,
}
public enum ConditionOperatorBool
{
IsTrue,
IsFalse,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 110953428c5a7d942bb601a0ac3acf65
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Client;
namespace TcgEngine
{
/// <summary>
/// This script initiates loading all the game data
/// </summary>
public class DataLoader : MonoBehaviour
{
public GameplayData data;
public AssetData assets;
private HashSet<string> card_ids = new HashSet<string>();
private HashSet<string> ability_ids = new HashSet<string>();
private HashSet<string> deck_ids = new HashSet<string>();
private static DataLoader instance;
void Awake()
{
instance = this;
LoadData();
}
public void LoadData()
{
//To make loading faster, add a path inside each Load() function, relative to Resources folder
//For example CardData.Load("Cards"); to only load data inside the Resources/Cards folder
CardData.Load();
TeamData.Load();
RarityData.Load();
TraitData.Load();
VariantData.Load();
PackData.Load();
LevelData.Load();
DeckData.Load();
AbilityData.Load();
StatusData.Load();
AvatarData.Load();
CardbackData.Load();
RewardData.Load();
CheckCardData();
CheckAbilityData();
CheckDeckData();
CheckVariantData();
}
//Make sure the data is valid
private void CheckCardData()
{
card_ids.Clear();
foreach (CardData card in CardData.GetAll())
{
if (string.IsNullOrEmpty(card.id))
Debug.LogError(card.name + " id is empty");
if (card_ids.Contains(card.id))
Debug.LogError("Dupplicate Card ID: " + card.id);
if (card.team == null)
Debug.LogError(card.id + " team is null");
if (card.rarity == null)
Debug.LogError(card.id + " rarity is null");
foreach (TraitData trait in card.traits)
{
if (trait == null)
Debug.LogError(card.id + " has null trait");
}
if (card.stats != null)
{
foreach (TraitStat stat in card.stats)
{
if (stat.trait == null)
Debug.LogError(card.id + " has null stat trait");
}
}
foreach (AbilityData ability in card.abilities)
{
if(ability == null)
Debug.LogError(card.id + " has null ability");
}
card_ids.Add(card.id);
}
}
//Make sure the data is valid
private void CheckAbilityData()
{
ability_ids.Clear();
foreach (AbilityData ability in AbilityData.GetAll())
{
if (string.IsNullOrEmpty(ability.id))
Debug.LogError(ability.name + " id is empty");
if (ability_ids.Contains(ability.id))
Debug.LogError("Dupplicate Ability ID: " + ability.id);
foreach (AbilityData chain in ability.chain_abilities)
{
if (chain == null)
Debug.LogError(ability.id + " has null chain ability");
}
ability_ids.Add(ability.id);
}
}
//Make sure the data is valid
private void CheckDeckData()
{
GameplayData gdata = GameplayData.Get();
CheckDeckArray(gdata.ai_decks);
CheckDeckArray(gdata.free_decks);
CheckDeckArray(gdata.starter_decks);
if(gdata.test_deck == null || gdata.test_deck_ai == null)
Debug.Log("Deck is null in Resources/GameplayData");
deck_ids.Clear();
foreach (DeckData deck in DeckData.GetAll())
{
if (string.IsNullOrEmpty(deck.id))
Debug.LogError(deck.name + " id is empty");
if (deck_ids.Contains(deck.id))
Debug.LogError("Dupplicate Deck ID: " + deck.id);
foreach (CardData card in deck.cards)
{
if (card == null)
Debug.LogError(deck.id + " has null card");
}
deck_ids.Add(deck.id);
}
}
private void CheckDeckArray(DeckData[] decks)
{
foreach (DeckData deck in decks)
{
if (deck == null)
Debug.Log("Deck is null in Resources/GameplayData");
}
}
private void CheckVariantData()
{
VariantData dvariant = VariantData.GetDefault();
if(dvariant == null)
Debug.LogError("No default variant data found, make sure you have a default VariantData");
}
public static DataLoader Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b8b650ea59aaba4a81d2630d662eabc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all fixed deck data (for user custom decks, check UserData.cs)
/// </summary>
[CreateAssetMenu(fileName = "DeckData", menuName = "TcgEngine/DeckData", order = 7)]
public class DeckData : ScriptableObject
{
public string id;
[Header("Display")]
public string title;
[Header("Cards")]
public CardData hero;
public CardData[] cards;
public static List<DeckData> deck_list = new List<DeckData>();
public static void Load(string folder = "")
{
if(deck_list.Count == 0)
deck_list.AddRange(Resources.LoadAll<DeckData>(folder));
}
public int GetQuantity()
{
return cards.Length;
}
public bool IsValid()
{
return cards.Length >= GameplayData.Get().deck_size;
}
public static DeckData Get(string id)
{
foreach (DeckData deck in GetAll())
{
if (deck.id == id)
return deck;
}
return null;
}
public static List<DeckData> GetAll()
{
return deck_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87ecef176d27eb040a9770e0eefea2ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Deck with more fields for having specific cards or starting board cards
/// </summary>
[System.Serializable]
public class DeckCardSlot
{
public CardData card;
public SlotXY slot;
}
[CreateAssetMenu(fileName = "DeckPuzzleData", menuName = "TcgEngine/DeckPuzzleData", order = 7)]
public class DeckPuzzleData : DeckData
{
public DeckCardSlot[] board_cards;
public int start_cards = 5;
public int start_mana = 2;
public int start_hp = 20;
public bool dont_shuffle_deck;
public static new DeckPuzzleData Get(string id)
{
foreach (DeckData deck in GetAll())
{
if (deck.id == id && deck is DeckPuzzleData)
return (DeckPuzzleData) deck;
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 069f5be85a1dcec46b083fc9c26e6870
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Gameplay;
namespace TcgEngine
{
/// <summary>
/// Base class for all ability effects, override the IsConditionMet function
/// </summary>
public class EffectData : ScriptableObject
{
public virtual void DoEffect(GameLogic logic, AbilityData ability, Card caster)
{
//Server side gameplay logic
}
public virtual void DoEffect(GameLogic logic, AbilityData ability, Card caster, Card target)
{
//Server side gameplay logic
}
public virtual void DoEffect(GameLogic logic, AbilityData ability, Card caster, Player target)
{
//Server side gameplay logic
}
public virtual void DoEffect(GameLogic logic, AbilityData ability, Card caster, Slot target)
{
//Server side gameplay logic
}
public virtual void DoEffect(GameLogic logic, AbilityData ability, Card caster, CardData target)
{
//Server side gameplay logic
}
public virtual void DoOngoingEffect(GameLogic logic, AbilityData ability, Card caster, Card target)
{
//Ongoing effect only
}
public virtual void DoOngoingEffect(GameLogic logic, AbilityData ability, Card caster, Player target)
{
//Ongoing effect only
}
public int AddOrSet(int original_val, EffectOperatorInt oper, int add_value)
{
if (oper == EffectOperatorInt.Add)
return original_val + add_value;
if (oper == EffectOperatorInt.Set)
return add_value;
return original_val;
}
}
public enum EffectOperatorInt
{
Add,
Set,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9b30fc8e458fec41a859f97cd4db714
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Base class for target filters
/// Let you filter targets after they have already been picked by conditions but before effects are applied
/// </summary>
public class FilterData : ScriptableObject
{
public virtual List<Card> FilterTargets(Game data, AbilityData ability, Card caster, List<Card> source, List<Card> dest)
{
return source; //Override this, filter targeting card
}
public virtual List<Player> FilterTargets(Game data, AbilityData ability, Card caster, List<Player> source, List<Player> dest)
{
return source; //Override this, filter targeting player
}
public virtual List<Slot> FilterTargets(Game data, AbilityData ability, Card caster, List<Slot> source, List<Slot> dest)
{
return source; //Override this, filter targeting slot
}
public virtual List<CardData> FilterTargets(Game data, AbilityData ability, Card caster, List<CardData> source, List<CardData> dest)
{
return source; //Override this, for filters that create new cards
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 509d9203e79c1c14a8889f13b2a9cc20
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,82 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.AI;
namespace TcgEngine
{
/// <summary>
/// Generic gameplay settings, such as starting stats, decks limit, scenes, and ai level
/// </summary>
[CreateAssetMenu(fileName = "GameplayData", menuName = "TcgEngine/GameplayData", order = 0)]
public class GameplayData : ScriptableObject
{
[Header("Gameplay")]
public int hp_start = 20;
public int mana_start = 1;
public int mana_per_turn = 1;
public int mana_max = 10;
public int cards_start = 5;
public int cards_per_turn = 1;
public int cards_max = 10;
public float turn_duration = 30f;
public CardData second_bonus;
public bool mulligan;
[Header("Deckbuilding")]
public int deck_size = 30;
public int deck_duplicate_max = 2;
[Header("Buy/Sell")]
public float sell_ratio = 0.8f;
[Header("AI")]
public AIType ai_type; //AI algorythm
public int ai_level = 10; //AI level, 10=best, 1=weakest
[Header("Decks")]
public DeckData[] free_decks; //These decks are always available in menu, useful for tests
public DeckData[] starter_decks; //When API is enabled, each player can select ONE of those
public DeckData[] ai_decks; //When player solo, AI will pick one of these at random
[Header("Scenes")]
public string[] arena_list; //List of game scenes
[Header("Test")]
public DeckData test_deck; //For when starting the game directly from Unity game scene
public DeckData test_deck_ai; //For when starting the game directly from Unity game scene
public bool ai_vs_ai;
public int GetPlayerLevel(int xp)
{
return Mathf.FloorToInt(xp / 1000f) + 1;
}
public string GetRandomArena()
{
if (arena_list.Length > 0)
return arena_list[Random.Range(0, arena_list.Length)];
return "Game";
}
public DeckData GetRandomFreeDeck()
{
if (free_decks.Length > 0)
return free_decks[Random.Range(0, free_decks.Length)];
return null;
}
public DeckData GetRandomAIDeck()
{
if (ai_decks.Length > 0)
return ai_decks[Random.Range(0, ai_decks.Length)];
return null;
}
public static GameplayData Get()
{
return DataLoader.Get().data;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 080ba8f3b7a08e34ba0648e5340f9bf4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
[CreateAssetMenu(fileName = "LevelData", menuName = "TcgEngine/LevelData", order = 7)]
public class LevelData : ScriptableObject
{
public string id;
public int level;
[Header("Display")]
public string title;
[Header("Gameplay")]
public string scene;
public DeckData player_deck;
public DeckData ai_deck;
public int ai_level = 10; //From 1 to 10
public LevelFirst first_player;
public GameObject tuto_prefab;
public bool mulligan = true;
[Header("Rewards")]
public int reward_xp = 100;
public int reward_coins = 100;
public PackData[] reward_packs;
public CardData[] reward_cards;
public DeckData[] reward_decks;
public static List<LevelData> level_list = new List<LevelData>();
public static void Load(string folder = "")
{
if (level_list.Count == 0)
{
level_list.AddRange(Resources.LoadAll<LevelData>(folder));
level_list.Sort((LevelData a, LevelData b) => { return a.level.CompareTo(b.level); });
}
}
public string GetTitle()
{
return title;
}
public static LevelData Get(string id)
{
foreach (LevelData level in GetAll())
{
if (level.id == id)
return level;
}
return null;
}
public static List<LevelData> GetAll()
{
return level_list;
}
}
public enum LevelFirst
{
Random = 0,
Player = 10,
AI = 20,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59e39d99af93c37489aff5e1e1333e20
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all packs data
/// </summary>
[CreateAssetMenu(fileName = "PackData", menuName = "TcgEngine/PackData", order = 5)]
public class PackData : ScriptableObject
{
public string id;
[Header("Content")]
public PackType type;
public int cards = 5; //Cards per pack
public PackRarity[] rarities_1st; //Probability of each rarity, for first card
public PackRarity[] rarities; //Probability of each rarity, for other cards
public PackVariant[] variants; //Probability of each variant, for other cards
[Header("Display")]
public string title;
public Sprite pack_img;
public Sprite cardback_img;
[TextArea(5, 10)]
public string desc;
public int sort_order;
[Header("Availability")]
public bool available = true;
public int cost = 100; //Cost to buy
public static List<PackData> pack_list = new List<PackData>();
public static void Load(string folder = "")
{
if (pack_list.Count == 0)
pack_list.AddRange(Resources.LoadAll<PackData>(folder));
pack_list.Sort((PackData a, PackData b) => {
if (a.sort_order == b.sort_order)
return a.id.CompareTo(b.id);
else
return a.sort_order.CompareTo(b.sort_order);
});
}
public string GetTitle()
{
return title;
}
public string GetDesc()
{
return desc;
}
public static PackData Get(string id)
{
foreach (PackData pack in GetAll())
{
if (pack.id == id)
return pack;
}
return null;
}
public static List<PackData> GetAllAvailable()
{
List<PackData> valid_list = new List<PackData>();
foreach (PackData apack in GetAll())
{
if (apack.available)
valid_list.Add(apack);
}
return valid_list;
}
public static List<PackData> GetAll()
{
return pack_list;
}
}
public enum PackType
{
Random = 0,
Fixed = 10,
}
[System.Serializable]
public struct PackRarity
{
public RarityData rarity;
public int probability;
}
[System.Serializable]
public struct PackVariant
{
public VariantData variant;
public int probability;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 137187ae111118548b8cdc17eed44c86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all rarities data (common, uncommon, rare, mythic)
/// </summary>
[CreateAssetMenu(fileName = "RarityData", menuName = "TcgEngine/RarityData", order = 1)]
public class RarityData : ScriptableObject
{
public string id;
public string title;
public Sprite icon;
public int rank; //Index of the rarity, should start at 1 (common) and increase sequentially
public static List<RarityData> rarity_list = new List<RarityData>();
public static void Load(string folder = "")
{
if (rarity_list.Count == 0)
rarity_list.AddRange(Resources.LoadAll<RarityData>(folder));
}
public static RarityData GetFirst()
{
int lowest = 99999;
RarityData first = null;
foreach (RarityData rarity in GetAll())
{
if (rarity.rank < lowest)
{
first = rarity;
lowest = rarity.rank;
}
}
return first;
}
public static RarityData Get(string id)
{
foreach (RarityData rarity in GetAll())
{
if (rarity.id == id)
return rarity;
}
return null;
}
public static List<RarityData> GetAll()
{
return rarity_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5567fab726837e542a517fb5b4079949
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Define reward to upload easily on the api
/// </summary>
[CreateAssetMenu(fileName = "RewardData", menuName = "TcgEngine/RewardData", order = 5)]
public class RewardData : ScriptableObject
{
public string id;
public string group;
public int coins;
public int xp;
public PackData[] packs;
public CardData[] cards;
public DeckData[] decks;
public bool repeat = true;
public static List<RewardData> reward_list = new List<RewardData>();
public static void Load(string folder = "")
{
if (reward_list.Count == 0)
reward_list.AddRange(Resources.LoadAll<RewardData>(folder));
}
public static RewardData Get(string id)
{
foreach (RewardData reward in GetAll())
{
if (reward.id == id)
return reward;
}
return null;
}
public static List<RewardData> GetAll()
{
return reward_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e118c8f1ed8739c4ab1328789e6a0b03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
public enum StatusType
{
None = 0,
AddAttack = 4, //Attack status can be used for attack boost limited for X turns
AddHP = 5, //HP status can be used for hp boost limited for X turns
AddManaCost = 6, //Mana Cost status can be used for mana cost increase/reduction limited for X turns
Stealth = 10, //Cant be attacked until do action
Invincibility = 12, //Cant be attacked for X turns
Shell = 13, //Receives no damage the first time
Protection = 14, //Taunt, gives Protected to other cards
Protected = 15, //Cards that are protected by taunt
Armor = 16, //Receives less damage
SpellImmunity = 18, //Cant be targeted/damaged by spells
Deathtouch = 20, //Kills when attacking a character
Fury = 22, //Can attack twice per turn
Intimidate = 23, //Target doesnt counter when attacking
Flying = 24, //Can ignore taunt
Trample = 26, //Extra damage is assigned to player
LifeSteal = 28, //Heal player when fighting
Silenced = 30, //All abilities canceled
Paralysed = 32, //Cant do any actions for X turns
Poisoned = 34, //Lose hp each start of turn
Sleep = 36, //Doesnt untap at the start of turn
}
/// <summary>
/// Defines all status effects data
/// Status are effects that can be gained or lost with abilities, and that will affect gameplay
/// Status can have a duration
/// </summary>
[CreateAssetMenu(fileName = "status", menuName = "TcgEngine/StatusData", order = 7)]
public class StatusData : ScriptableObject
{
public StatusType effect;
[Header("Display")]
public string title;
public Sprite icon;
[TextArea(3, 5)]
public string desc;
[Header("FX")]
public GameObject status_fx;
[Header("AI")]
public int hvalue;
public static List<StatusData> status_list = new List<StatusData>();
public string GetTitle()
{
return title;
}
public string GetDesc()
{
return GetDesc(1);
}
public string GetDesc(int value)
{
string des = desc.Replace("<value>", value.ToString());
return des;
}
public static void Load(string folder = "")
{
if (status_list.Count == 0)
status_list.AddRange(Resources.LoadAll<StatusData>(folder));
}
public static StatusData Get(StatusType effect)
{
foreach (StatusData status in GetAll())
{
if (status.effect == effect)
return status;
}
return null;
}
public static List<StatusData> GetAll()
{
return status_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7edf116efdfa73646a6de43812f81a4a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all factions data
/// </summary>
[CreateAssetMenu(fileName = "TeamData", menuName = "TcgEngine/TeamData", order = 1)]
public class TeamData : ScriptableObject
{
public string id;
public string title;
public Sprite icon;
public Color color;
public static List<TeamData> team_list = new List<TeamData>();
public static void Load(string folder = "")
{
if (team_list.Count == 0)
team_list.AddRange(Resources.LoadAll<TeamData>(folder));
}
public static TeamData Get(string id)
{
foreach (TeamData team in GetAll())
{
if (team.id == id)
return team;
}
return null;
}
public static List<TeamData> GetAll()
{
return team_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 55e41d6c5fb036a40bc0a37bfe1f52ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines all traits and stats data
/// </summary>
[CreateAssetMenu(fileName = "TraitData", menuName = "TcgEngine/TraitData", order = 1)]
public class TraitData : ScriptableObject
{
public string id;
public string title;
public Sprite icon;
public static List<TraitData> trait_list = new List<TraitData>();
public string GetTitle()
{
return title;
}
public static void Load(string folder = "")
{
if (trait_list.Count == 0)
trait_list.AddRange(Resources.LoadAll<TraitData>(folder));
}
public static TraitData Get(string id)
{
foreach (TraitData team in GetAll())
{
if (team.id == id)
return team;
}
return null;
}
public static List<TraitData> GetAll()
{
return trait_list;
}
}
[System.Serializable]
public struct TraitStat
{
public TraitData trait;
public int value;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 510a78cb12497a646b6e2a8ba36b4dcf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine
{
/// <summary>
/// Defines card variants
/// </summary>
[CreateAssetMenu(fileName = "VariantData", menuName = "TcgEngine/VariantData", order = 5)]
public class VariantData : ScriptableObject
{
public string id;
public string title;
public Sprite frame;
public Sprite frame_board;
public Color color = Color.white;
public int cost_factor = 1;
public bool is_default;
public static List<VariantData> variant_list = new List<VariantData>();
public string GetSuffix()
{
return "_" + id;
}
public static void Load(string folder = "")
{
if (variant_list.Count == 0)
variant_list.AddRange(Resources.LoadAll<VariantData>(folder));
}
public static VariantData GetDefault()
{
foreach (VariantData variant in GetAll())
{
if (variant.is_default)
return variant;
}
return null;
}
public static VariantData GetSpecial()
{
foreach (VariantData variant in GetAll())
{
if (!variant.is_default)
return variant;
}
return null;
}
public static VariantData Get(string id)
{
foreach (VariantData variant in GetAll())
{
if (variant.id == id)
return variant;
}
return GetDefault();
}
public static List<VariantData> GetAll()
{
return variant_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c73830b52f888545a0cf8aac8d4b21e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: