mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Add update_cards_scripts
This commit is contained in:
@@ -87,6 +87,31 @@ void AddCardAction::perform(bool to_undo) {
|
||||
set.buildUIDMap();
|
||||
}
|
||||
|
||||
UpdateCardAction::UpdateCardAction(Set& set, const vector<CardP>& cards_to_add, const vector<CardP>& cards_to_remove)
|
||||
: CardListAction(set)
|
||||
, action_add(ADD, set, cards_to_add)
|
||||
, action_remove(REMOVE, set, cards_to_remove)
|
||||
{}
|
||||
|
||||
String UpdateCardAction::getName(bool to_undo) const {
|
||||
return _ACTION_("update card");
|
||||
}
|
||||
|
||||
void UpdateCardAction::perform(bool to_undo) {
|
||||
if (to_undo) {
|
||||
action_remove.perform(to_undo);
|
||||
set.actions.tellListeners(action_remove, to_undo);
|
||||
action_add.perform(to_undo);
|
||||
set.actions.tellListeners(action_add, to_undo);
|
||||
}
|
||||
else {
|
||||
action_add.perform(to_undo);
|
||||
set.actions.tellListeners(action_add, to_undo);
|
||||
action_remove.perform(to_undo);
|
||||
set.actions.tellListeners(action_remove, to_undo);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Reorder cards
|
||||
|
||||
ReorderCardsAction::ReorderCardsAction(Set& set, size_t card_id1, size_t card_id2)
|
||||
|
||||
@@ -50,6 +50,18 @@ public:
|
||||
vector<ActionP> card_link_actions;
|
||||
};
|
||||
|
||||
/// Update one or more cards from a set by replacing them with other cards
|
||||
class UpdateCardAction : public CardListAction {
|
||||
public:
|
||||
UpdateCardAction(Set& set, const vector<CardP>& cards_to_add, const vector<CardP>& cards_to_remove);
|
||||
|
||||
String getName(bool to_undo) const override;
|
||||
void perform(bool to_undo) override;
|
||||
|
||||
AddCardAction action_add;
|
||||
AddCardAction action_remove;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Reorder cards
|
||||
|
||||
/// Change the position of a card in the card list by swapping two cards
|
||||
|
||||
@@ -400,8 +400,10 @@ String BulkAction::getName(bool to_undo) const {
|
||||
return to_undo ? name_undo : name_do;
|
||||
}
|
||||
|
||||
void BulkAction::perform(bool to_undo) {
|
||||
FOR_EACH(action, actions) {
|
||||
void BulkAction::perform(bool to_undo) {
|
||||
size_t size = actions.size();
|
||||
for (size_t i = 0 ; i < size ; ++i) {
|
||||
ActionP& action = actions[to_undo ? size - i - 1 : i];
|
||||
action->perform(to_undo);
|
||||
set->actions.tellListeners(*action, to_undo);
|
||||
}
|
||||
|
||||
@@ -25,18 +25,22 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(AddCardsScript) {
|
||||
|
||||
void AddCardsScript::perform(Set& set, vector<CardP>& out) {
|
||||
// Perform script
|
||||
Context& ctx = set.getContext();
|
||||
Context& ctx = set.getContext();
|
||||
if (enabled.hasBeenRead()) {
|
||||
enabled.update(ctx);
|
||||
if (!enabled()) return;
|
||||
}
|
||||
ScriptValueP result = script.invoke(ctx);
|
||||
// Add cards to out
|
||||
ScriptValueP it = result->makeIterator();
|
||||
while (ScriptValueP item = it->next()) {
|
||||
CardP card = from_script<CardP>(item);
|
||||
CardP new_card = from_script<CardP>(item);
|
||||
// is this a new card?
|
||||
if (contains(set.cards,card) || contains(out,card)) {
|
||||
if (contains(set.cards,new_card) || contains(out,new_card)) {
|
||||
// make copy
|
||||
card = make_intrusive<Card>(*card);
|
||||
new_card = make_intrusive<Card>(&set, new_card);
|
||||
}
|
||||
out.push_back(card);
|
||||
out.push_back(new_card);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-2
@@ -42,7 +42,38 @@ Card::Card(Game& game)
|
||||
, has_styling(false)
|
||||
{
|
||||
data.init(game.card_fields);
|
||||
}
|
||||
}
|
||||
|
||||
Card::Card(Set* set, const CardP& card)
|
||||
: game(card->game)
|
||||
, time_created (wxDateTime::Now())
|
||||
, time_modified(wxDateTime::Now())
|
||||
, notes(card->notes)
|
||||
, uid(generate_uid())
|
||||
, linked_card_1(card->linked_card_1)
|
||||
, linked_card_2(card->linked_card_2)
|
||||
, linked_card_3(card->linked_card_3)
|
||||
, linked_card_4(card->linked_card_4)
|
||||
, linked_relation_1(card->linked_relation_1)
|
||||
, linked_relation_2(card->linked_relation_2)
|
||||
, linked_relation_3(card->linked_relation_3)
|
||||
, linked_relation_4(card->linked_relation_4)
|
||||
, has_styling(card->has_styling)
|
||||
, stylesheet_version(card->stylesheet_version)
|
||||
, stylesheet(card->stylesheet)
|
||||
{
|
||||
if (!stylesheet && set) {
|
||||
stylesheet = set->stylesheetForP(card);
|
||||
}
|
||||
if (has_styling) {
|
||||
styling_data.cloneFrom(card->styling_data);
|
||||
}
|
||||
else {
|
||||
if (stylesheet && set) styling_data.cloneFrom(set->stylingDataFor(*stylesheet));
|
||||
}
|
||||
data.cloneFrom(card->data);
|
||||
extra_data.cloneFrom(card->extra_data);
|
||||
}
|
||||
|
||||
String Card::identification() const {
|
||||
// an identifying field
|
||||
@@ -344,7 +375,12 @@ void reflect_version_check(GetDefaultMember& handler, const Char* key, intrusive
|
||||
|
||||
IMPLEMENT_REFLECTION(Card) {
|
||||
REFLECT(stylesheet);
|
||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||
if (Handler::isReading) {
|
||||
REFLECT_NO_SCRIPT(stylesheet_version);
|
||||
}
|
||||
else {
|
||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||
}
|
||||
REFLECT(has_styling);
|
||||
if (has_styling) {
|
||||
if (stylesheet) {
|
||||
|
||||
+5
-1
@@ -35,6 +35,8 @@ public:
|
||||
Card();
|
||||
/// Creates a card using the given game
|
||||
Card(Game& game);
|
||||
/// Copy constructor, makes a deep copy
|
||||
Card(Set* set, const CardP& card);
|
||||
|
||||
/// The game this card is made for
|
||||
Game* game;
|
||||
@@ -60,7 +62,9 @@ public:
|
||||
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;
|
||||
StyleSheetP stylesheet;
|
||||
/// What version of the stylesheet was this card using when it was last saved?
|
||||
Version stylesheet_version;
|
||||
/// 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
|
||||
|
||||
+6
-3
@@ -16,6 +16,7 @@
|
||||
#include <data/pack.hpp>
|
||||
#include <data/word_list.hpp>
|
||||
#include <data/add_cards_script.hpp>
|
||||
#include <data/update_cards_script.hpp>
|
||||
#include <util/io/package_manager.hpp>
|
||||
#include <script/script.hpp>
|
||||
|
||||
@@ -55,7 +56,6 @@ IMPLEMENT_REFLECTION(Game) {
|
||||
REFLECT_NO_SCRIPT(json_paths);
|
||||
REFLECT_NO_SCRIPT(statistics_dimensions);
|
||||
REFLECT_NO_SCRIPT(statistics_categories);
|
||||
REFLECT_COMPAT(<308, "pack_item", pack_types);
|
||||
REFLECT_NO_SCRIPT(pack_types);
|
||||
REFLECT_NO_SCRIPT(keyword_match_script);
|
||||
REFLECT(has_keywords);
|
||||
@@ -63,7 +63,8 @@ IMPLEMENT_REFLECTION(Game) {
|
||||
REFLECT(keyword_parameter_types);
|
||||
REFLECT_NO_SCRIPT(keywords);
|
||||
REFLECT_NO_SCRIPT(word_lists);
|
||||
REFLECT_NO_SCRIPT(add_cards_scripts);
|
||||
REFLECT_NO_SCRIPT(add_cards_scripts);
|
||||
REFLECT_NO_SCRIPT(update_cards_scripts);
|
||||
REFLECT_NO_SCRIPT(auto_replaces);
|
||||
}
|
||||
|
||||
@@ -205,7 +206,9 @@ void Game::validate(Version v) {
|
||||
}
|
||||
card_links_alt_names.emplace(linked_tr, linked_default);
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort the update_cards_scripts from oldest to newest
|
||||
std::sort(update_cards_scripts.begin(), update_cards_scripts.end());
|
||||
}
|
||||
|
||||
void Game::initCardListColorScript() {
|
||||
|
||||
+23
-21
@@ -26,6 +26,7 @@ DECLARE_POINTER_TYPE(KeywordMode);
|
||||
DECLARE_POINTER_TYPE(Keyword);
|
||||
DECLARE_POINTER_TYPE(WordList);
|
||||
DECLARE_POINTER_TYPE(AddCardsScript);
|
||||
DECLARE_POINTER_TYPE(UpdateCardsScript);
|
||||
DECLARE_POINTER_TYPE(AutoReplace);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Game
|
||||
@@ -38,27 +39,28 @@ class Game : public Packaged {
|
||||
public:
|
||||
Game();
|
||||
|
||||
OptionalScript init_script; ///< Script of variables available to other scripts in this game
|
||||
vector<FieldP> set_fields; ///< Fields for set information
|
||||
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
||||
vector<FieldP> card_fields; ///< Fields on each card
|
||||
vector<CardLinkP> card_links; ///< Possible links between cards
|
||||
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
||||
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
||||
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
||||
vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions
|
||||
vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories
|
||||
vector<PackTypeP> pack_types; ///< Types of random card packs to generate
|
||||
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
||||
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
||||
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
||||
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
||||
map<String,String> card_links_alt_names; ///< Localized names that card links go by
|
||||
bool has_keywords; ///< Does this game use keywords?
|
||||
OptionalScript keyword_match_script; ///< For the keyword editor
|
||||
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
||||
vector<KeywordModeP> keyword_modes; ///< Modes of keywords
|
||||
vector<KeywordP> keywords; ///< Keywords for use in text
|
||||
OptionalScript init_script; ///< Script of variables available to other scripts in this game
|
||||
vector<FieldP> set_fields; ///< Fields for set information
|
||||
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
||||
vector<FieldP> card_fields; ///< Fields on each card
|
||||
vector<CardLinkP> card_links; ///< Possible links between cards
|
||||
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
||||
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
||||
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
||||
vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions
|
||||
vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories
|
||||
vector<PackTypeP> pack_types; ///< Types of random card packs to generate
|
||||
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
||||
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
||||
vector<UpdateCardsScriptP> update_cards_scripts; ///< Scripts for updating cards made with an earlier version of this game
|
||||
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
||||
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
||||
map<String,String> card_links_alt_names; ///< Localized names that card links go by
|
||||
bool has_keywords; ///< Does this game use keywords?
|
||||
OptionalScript keyword_match_script; ///< For the keyword editor
|
||||
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
||||
vector<KeywordModeP> keyword_modes; ///< Modes of keywords
|
||||
vector<KeywordP> keywords; ///< Keywords for use in text
|
||||
|
||||
Dependencies dependent_scripts_cards; ///< scripts that depend on the card list
|
||||
Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords
|
||||
|
||||
@@ -85,7 +85,6 @@ bool Keyword::contains(QuickFilterPart const& query) const {
|
||||
|
||||
IMPLEMENT_REFLECTION(Keyword) {
|
||||
REFLECT(keyword);
|
||||
if (handler.formatVersion() < 301) read_compat(handler, this);
|
||||
REFLECT(match);
|
||||
REFLECT(reminder);
|
||||
REFLECT(rules);
|
||||
|
||||
+56
-9
@@ -14,6 +14,7 @@
|
||||
#include <data/keyword.hpp>
|
||||
#include <data/pack.hpp>
|
||||
#include <data/field.hpp>
|
||||
#include <data/update_cards_script.hpp>
|
||||
#include <data/field/text.hpp> // for 0.2.7 fix
|
||||
#include <data/field/information.hpp>
|
||||
#include <data/field/image.hpp>
|
||||
@@ -172,7 +173,7 @@ void fix_value_207(const ValueP& value) {
|
||||
|
||||
void Set::validate(Version file_app_version) {
|
||||
Packaged::validate(file_app_version);
|
||||
// are the
|
||||
// are the game and stylesheet defined?
|
||||
if (!game) {
|
||||
throw Error(_ERROR_1_("no game specified",_TYPE_("set")));
|
||||
}
|
||||
@@ -183,7 +184,9 @@ void Set::validate(Version file_app_version) {
|
||||
if (stylesheet->game != game) {
|
||||
throw Error(_ERROR_("stylesheet and set refer to different game"));
|
||||
}
|
||||
|
||||
|
||||
// We can probably retire this
|
||||
/*
|
||||
// This is our chance to fix version incompatabilities
|
||||
if (file_app_version < 207) {
|
||||
// Since 0.2.7 we use </tag> style close tags, in older versions it was </>
|
||||
@@ -192,16 +195,52 @@ void Set::validate(Version file_app_version) {
|
||||
FOR_EACH(v, c->data) fix_value_207(v);
|
||||
}
|
||||
FOR_EACH(v, data) fix_value_207(v);
|
||||
/* FOR_EACH(s, styleData) {
|
||||
FOR_EACH(s, styleData) {
|
||||
FOR_EACH(v, s.second->data) fix_value_207(v);
|
||||
}
|
||||
*/ }
|
||||
}
|
||||
*/
|
||||
|
||||
// we want at least one card
|
||||
if (cards.empty()) cards.push_back(make_intrusive<Card>(*game));
|
||||
// update scripts
|
||||
script_manager->updateAll();
|
||||
// build uid map
|
||||
buildUIDMap();
|
||||
buildUIDMap();
|
||||
// update cards with game update_cards_scripts
|
||||
for (int j = 0; j < game->update_cards_scripts.size(); ++j) {
|
||||
UpdateCardsScriptP& script = game->update_cards_scripts[j];
|
||||
if (game_version >= script->before_version) continue;
|
||||
size_t size = cards.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
CardP& card = cards[i];
|
||||
vector<CardP> new_cards = script->perform(*this, card);
|
||||
if (!new_cards.empty()) {
|
||||
--i;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
}
|
||||
// update cards with stylesheet update_cards_scripts
|
||||
for (int i = 0; i < cards.size(); ++i) {
|
||||
CardP& card = cards[i];
|
||||
StyleSheetP stylesheet = stylesheetForP(card);
|
||||
for (int j = 0; j < stylesheet->update_cards_scripts.size(); ++j) {
|
||||
UpdateCardsScriptP& script = stylesheet->update_cards_scripts[j];
|
||||
if (card->stylesheet_version >= script->before_version) continue;
|
||||
vector<CardP> new_cards = script->perform(*this, card);
|
||||
if (!new_cards.empty()) {
|
||||
FOR_EACH(new_card, new_cards) {
|
||||
// Initialize the stylesheet_version if it wasn't defined, to prevent this script from applying again
|
||||
if (stylesheet == stylesheetForP(new_card) && new_card->stylesheet_version < script->before_version) {
|
||||
new_card->stylesheet_version = script->before_version;
|
||||
}
|
||||
}
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reflect_version_check(Reader& handler, const Char* key, intrusive_ptr<Packaged> const& package) {
|
||||
@@ -225,15 +264,23 @@ IMPLEMENT_REFLECTION(Set) {
|
||||
REFLECT_IF_READING {
|
||||
data.init(game->set_fields);
|
||||
}
|
||||
reflect_version_check(handler, _("game_version"), game);
|
||||
if (Handler::isReading) {
|
||||
REFLECT_NO_SCRIPT(game_version);
|
||||
}
|
||||
else {
|
||||
reflect_version_check(handler, _("game_version"), game);
|
||||
}
|
||||
WITH_DYNAMIC_ARG(game_for_reading, game.get());
|
||||
REFLECT(stylesheet);
|
||||
REFLECT_COMPAT(<300, "style", stylesheet);
|
||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||
if (Handler::isReading) {
|
||||
REFLECT_NO_SCRIPT(stylesheet_version);
|
||||
}
|
||||
else {
|
||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||
}
|
||||
WITH_DYNAMIC_ARG(stylesheet_for_reading, stylesheet.get());
|
||||
REFLECT_N("set_info", data);
|
||||
if (stylesheet) {
|
||||
REFLECT_COMPAT(<300, "extra_set_info", styling_data);
|
||||
REFLECT_N("styling", styling_data);
|
||||
}
|
||||
// Experimental: save each card to a different file
|
||||
|
||||
+5
-1
@@ -61,7 +61,11 @@ public:
|
||||
ActionStack actions; ///< Actions performed on this set and the cards in it
|
||||
KeywordDatabase keyword_db; ///< Database for matching keywords, must be cleared when keywords change
|
||||
VCSP vcs; ///< The version control system to use
|
||||
|
||||
/// What version of the game was this set using when it was last saved?
|
||||
Version game_version;
|
||||
/// What version of the default stylesheet was this set using when it was last saved?
|
||||
Version stylesheet_version;
|
||||
|
||||
/// A context for performing scripts
|
||||
/** Should only be used from the main thread! */
|
||||
Context& getContext();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <data/game.hpp>
|
||||
#include <data/field.hpp>
|
||||
#include <data/update_cards_script.hpp>
|
||||
#include <util/io/package_manager.hpp>
|
||||
#include <gui/new_window.hpp> // for selecting stylesheets on load error
|
||||
|
||||
@@ -75,7 +76,11 @@ void StyleSheet::validate(Version ver) {
|
||||
throw Error(_ERROR_1_("no game specified",_TYPE_("stylesheet")));
|
||||
}
|
||||
// a stylesheet depends on the game it is made for
|
||||
requireDependency(game.get());
|
||||
requireDependency(game.get());
|
||||
// sort the update_cards_scripts from oldest to newest
|
||||
std::sort(update_cards_scripts.begin(), update_cards_scripts.end(), [](const auto& a, const auto& b) {
|
||||
return *a < *b;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +130,7 @@ IMPLEMENT_REFLECTION(StyleSheet) {
|
||||
extra_card_style.init(extra_card_fields);
|
||||
}
|
||||
REFLECT(extra_card_style);
|
||||
REFLECT_NO_SCRIPT(update_cards_scripts);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ DECLARE_POINTER_TYPE(StyleSheet);
|
||||
DECLARE_POINTER_TYPE(Field);
|
||||
DECLARE_POINTER_TYPE(Style);
|
||||
DECLARE_POINTER_TYPE(CardRegion);
|
||||
DECLARE_POINTER_TYPE(UpdateCardsScript);
|
||||
|
||||
// ----------------------------------------------------------------------------- : StyleSheet
|
||||
|
||||
@@ -33,12 +34,13 @@ class StyleSheet : public Packaged {
|
||||
public:
|
||||
StyleSheet();
|
||||
|
||||
GameP game; ///< The game this stylesheet is made for
|
||||
OptionalScript init_script; ///< Script of variables available to other scripts in this stylesheet
|
||||
double card_width; ///< The width of a card in pixels
|
||||
double card_height; ///< The height of a card in pixels
|
||||
double card_dpi; ///< The resolution of a card in dots per inch
|
||||
Color card_background; ///< The background color of cards
|
||||
GameP game; ///< The game this stylesheet is made for
|
||||
OptionalScript init_script; ///< Script of variables available to other scripts in this stylesheet
|
||||
vector<UpdateCardsScriptP> update_cards_scripts; ///< Scripts for updating cards made with an earlier version of this stylesheet
|
||||
double card_width; ///< The width of a card in pixels
|
||||
double card_height; ///< The height of a card in pixels
|
||||
double card_dpi; ///< The resolution of a card in dots per inch
|
||||
Color card_background; ///< The background color of cards
|
||||
vector<CardRegionP> card_regions;
|
||||
/// The styling for card fields
|
||||
/** The indices should correspond to the card_fields in the Game */
|
||||
|
||||
@@ -178,7 +178,6 @@ IMPLEMENT_REFLECTION(SymbolInFont) {
|
||||
REFLECT(draw_text);
|
||||
REFLECT(text_font);
|
||||
REFLECT(text_alignment);
|
||||
REFLECT_COMPAT(<300,"text_align",text_alignment);
|
||||
REFLECT(text_margin_left);
|
||||
REFLECT(text_margin_right);
|
||||
REFLECT(text_margin_top);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make card games |
|
||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <data/update_cards_script.hpp>
|
||||
#include <data/action/set.hpp>
|
||||
#include <data/set.hpp>
|
||||
#include <data/card.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <data/action/value.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : UpdateCardsScript
|
||||
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(UpdateCardsScript) {
|
||||
REFLECT(before_version);
|
||||
REFLECT(description);
|
||||
REFLECT(enabled);
|
||||
REFLECT(script);
|
||||
}
|
||||
|
||||
|
||||
void UpdateCardsScript::perform(Set& set, CardP& card, vector<CardP>& out) {
|
||||
// Perform script
|
||||
Context& ctx = set.getContext(card);
|
||||
if (enabled.hasBeenRead()) {
|
||||
enabled.update(ctx);
|
||||
if (!enabled()) return;
|
||||
}
|
||||
ScriptValueP result = script.invoke(ctx);
|
||||
// Add cards to out
|
||||
ScriptValueP it = result->makeIterator();
|
||||
while (ScriptValueP item = it->next()) {
|
||||
CardP new_card = from_script<CardP>(item);
|
||||
// is this a new card?
|
||||
if (contains(set.cards,new_card) || contains(out,new_card)) {
|
||||
// make copy
|
||||
new_card = make_intrusive<Card>(&set, new_card);
|
||||
}
|
||||
out.push_back(new_card);
|
||||
}
|
||||
}
|
||||
|
||||
vector<CardP> UpdateCardsScript::perform(Set& set, CardP card) {
|
||||
// Perform script
|
||||
vector<CardP> cards;
|
||||
perform(set, card, cards);
|
||||
// Add to set
|
||||
if (!cards.empty()) {
|
||||
set.actions.addAction(make_unique<UpdateCardAction>(set, cards, vector<CardP>{card}), false);
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make card games |
|
||||
//| 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 <util/prec.hpp>
|
||||
#include <script/scriptable.hpp>
|
||||
|
||||
class Set;
|
||||
DECLARE_POINTER_TYPE(Card);
|
||||
|
||||
// ----------------------------------------------------------------------------- : UpdateCardsScript
|
||||
|
||||
/// A script to add one or more cards to a set
|
||||
class UpdateCardsScript : public IntrusivePtrBase<UpdateCardsScript> {
|
||||
public:
|
||||
Version before_version;
|
||||
String description;
|
||||
Scriptable<bool> enabled;
|
||||
OptionalScript script;
|
||||
|
||||
bool operator < (const UpdateCardsScript& other) const {
|
||||
return before_version < other.before_version;
|
||||
}
|
||||
|
||||
/// Perform the script; return the cards (if any)
|
||||
void perform(Set& set, CardP& card, vector<CardP>& out);
|
||||
/// Perform the script; add cards to the set
|
||||
vector<CardP> perform(Set& set, CardP card); // don't use CardP& here, because set.cards may get reallocated which would invalidate the ref
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user