//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) Twan van Laarhoven and the other MSE developers | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #pragma once // ----------------------------------------------------------------------------- : Includes #include #include #include #include #include // for Card::value class Game; class Dependency; class Keyword; DECLARE_POINTER_TYPE(Set); DECLARE_POINTER_TYPE(Card); DECLARE_POINTER_TYPE(Field); DECLARE_POINTER_TYPE(Value); DECLARE_POINTER_TYPE(StyleSheet); #define THIS_LINKED_PAIRS(var) vector, reference_wrapper>> var { make_pair(ref(linked_card_1), ref(linked_relation_1)), make_pair(ref(linked_card_2), ref(linked_relation_2)), make_pair(ref(linked_card_3), ref(linked_relation_3)), make_pair(ref(linked_card_4), ref(linked_relation_4)) } #define OTHER_LINKED_PAIRS(var, other_card) vector, reference_wrapper>> var { make_pair(ref(other_card->linked_card_1), ref(other_card->linked_relation_1)), make_pair(ref(other_card->linked_card_2), ref(other_card->linked_relation_2)), make_pair(ref(other_card->linked_card_3), ref(other_card->linked_relation_3)), make_pair(ref(other_card->linked_card_4), ref(other_card->linked_relation_4)) } // ----------------------------------------------------------------------------- : Card /// A card from a card Set class Card : public IntrusivePtrVirtualBase, public IntrusiveFromThis { public: /// Default constructor, uses game_for_new_cards to make the game Card(); /// Creates a card using the given game Card(const Game& game); /// The values on the fields of the card. /** The indices should correspond to the card_fields in the Game */ IndexMap data; /// Notes for this card String notes; /// Unique identifier for this card, so other cards can refer to it, and be linked to it String uid; /// Up to four uid of other cards, to encode relations such as front face/back face, or generator/token, etc... String linked_card_1; String linked_card_2; String linked_card_3; String linked_card_4; /// Nature of the relatation with the respective linked card, such as back face, or token, etc... String linked_relation_1; String linked_relation_2; String linked_relation_3; String linked_relation_4; /// Time the card was created/last modified wxDateTime time_created, time_modified; /// Alternative style to use for this card /** Optional; if not set use the card style from the set */ StyleSheetP stylesheet; /// Alternative options to use for this card, for this card's stylesheet /** Optional; if not set use the styling data from the set. * If stylesheet is set then contains data for the this->stylesheet, otherwise for set->stylesheet */ IndexMap styling_data; /// Is the styling_data set? bool has_styling; /// Extra values for specitic stylesheets, indexed by stylesheet name DelayedIndexMaps extra_data; /// Styling information for a particular stylesheet IndexMap& extraDataFor(const StyleSheet& stylesheet); /// Keyword usage statistics vector> keyword_usage; /// Get the identification of this card, an identification is something like a name, title, etc. /** May return "" */ String identification() const; /// Does any field contains the given query string? bool contains(QuickFilterPart const& query) const; /// Link or unlink other cards to this card void link(const Set& set, const vector& linked_cards, const String& selected_relation, const String& linked_relation); void link(const Set& set, CardP& linked_card, const String& selected_relation, const String& linked_relation); void unlink(const vector& linked_cards); pair unlink(CardP& unlinked_card); // Returns the relations that were deleted, so we can undo void copyLink(const Set& set, String old_uid, String new_uid); void updateLink(String old_uid, String new_uid); vector> getLinkedCards(const vector& cards); vector> getLinkedCards(const Set& set); vector getLinkedCardsFromLink(const vector& cards, const String& link, bool erase_if_no_card); vector getLinkedCardsFromLink(const Set& set, const String& link, bool erase_if_no_card); CardP getLinkedOtherFace(const vector& cards); CardP getLinkedOtherFace(const Set& set); static CardP getCardFromUid(const vector& cards, const String& uid); static CardP getCardFromUid(const Set& set, const String& uid); /// Find a value in the data by name and type template T& value(const String& name) { for(IndexMap::iterator it = data.begin() ; it != data.end() ; ++it) { if ((*it)->fieldP->name == name) { T* ret = dynamic_cast(it->get()); if (!ret) throw InternalError(_("Card field with name '")+name+_("' doesn't have the right type")); return *ret; } } throw InternalError(_("Expected a card field with name '")+name+_("'")); } template const T& value(const String& name) const { for(IndexMap::const_iterator it = data.begin() ; it != data.end() ; ++it) { if ((*it)->fieldP->name == name) { const T* ret = dynamic_cast(it->get()); if (!ret) throw InternalError(_("Card field with name '")+name+_("' doesn't have the right type")); return *ret; } } throw InternalError(_("Expected a card field with name '")+name+_("'")); } DECLARE_REFLECTION(); }; inline String type_name(const Card&) { return _TYPE_("card"); } inline String type_name(const vector&) { return _TYPE_("cards"); // not actually used, only for locale.pl script } void mark_dependency_member(const Card& value, const String& name, const Dependency& dep);