diff --git a/data/magic-cockatrice-cs-ech-1.04.mse-export-template/icon.png b/data/magic-cockatrice-cs-ech-1.04.mse-export-template/icon.png
deleted file mode 100644
index 7c56e0db5..000000000
Binary files a/data/magic-cockatrice-cs-ech-1.04.mse-export-template/icon.png and /dev/null differ
diff --git a/data/magic-cockatrice-cs-ech-1.04.mse-export-template/README.txt b/data/magic-cockatrice-v2.mse-export-template/README.txt
similarity index 100%
rename from data/magic-cockatrice-cs-ech-1.04.mse-export-template/README.txt
rename to data/magic-cockatrice-v2.mse-export-template/README.txt
diff --git a/data/magic-cockatrice-cs-ech-1.04.mse-export-template/export-template b/data/magic-cockatrice-v2.mse-export-template/export-template
similarity index 56%
rename from data/magic-cockatrice-cs-ech-1.04.mse-export-template/export-template
rename to data/magic-cockatrice-v2.mse-export-template/export-template
index 7fcf37e24..380572a20 100644
--- a/data/magic-cockatrice-cs-ech-1.04.mse-export-template/export-template
+++ b/data/magic-cockatrice-v2.mse-export-template/export-template
@@ -1,9 +1,9 @@
mse version: 0.3.8
short name: Cockatrice
-full name: CS/ECH 1.04
+full name: Exporter v2.0
position hint: 007
icon: icon.png
-version: 2018-09-29
+version: 2023-02-05
installer group: magic/Export/cockatrice
depends on:
@@ -15,32 +15,26 @@ create directory: true
file type: *.xml|*.xml|*.*|*.*
# By K'yoril, edited by Advent, Updated by Reuben Covington, Updated by Cajun, Updated by Zeu
+# Updated to v4 xml by ebbit
# Based on code by Pichoro, Idle Muse, Innuendo and Seeonee
option field:
type: choice
- name: version
- choice: CS/ECH 1.04
-option field:
- type:choice
- name: Usage Guide
- choice: https://tinyurl.com/csexporter
+ name: info
+ choice: Updated 2023/02, guide: https://tinyurl.com/ctexportv2
option field:
type: text
name: cockatrice Set Type
description: The "set type" your set will appear as in Cockatrice. "Custom" should be the default.
default: Custom
-option field:
- type: boolean
- name: export Images
- description: Whether or not to export images along with the XML. These images are recommended for Cockatrice use.
- initial: yes
option field:
type: choice
- name: images File Type
- description: Which file extension you want the images exported as. JPG is lower quality but lower file size.
+ name: export Images
+ description: Export images along with the XML? Recommended for Cockatrice use. JPG is lower quality but lower file size.
+ choice: no
choice: JPG
choice: PNG
+ initial: no
option field:
type: boolean
name: tokens In Separate XML
@@ -56,49 +50,40 @@ option field:
name: append String To Names
description: Appended to the front of all card names and image names.
option field:
- type: boolean
- name: include Common
- description: Whether to include common cards or not.
- initial: yes
-option field:
- type: boolean
- name: include Uncommon
- description: Whether to include uncommon cards or not.
- initial: yes
-option field:
- type: boolean
- name: include Rare
- description: Whether to include rare cards or not.
- initial: yes
-option field:
- type: boolean
- name: include Mythic
- description: Whether to include mythic rare cards or not.
- initial: yes
-option field:
- type: boolean
- name: include Basic Land
- description: Whether to include basic land rarity cards or not.
- initial: yes
-option field:
- type: boolean
- name: include Tokens
- description: Whether to include tokens or not.
- initial: yes
-option field:
- type: boolean
- name: include Special
- description: Whether to include special rarity cards or not.
- initial: yes
-
+ type: multiple choice
+ name: rarities to export
+ choice: common
+ choice: uncommon
+ choice: rare
+ choice: mythic rare
+ choice: basic land
+ choice: special
+ choice: token
+ choice: masterpiece
+ initial: common, uncommon, rare, mythic rare, basic land, special, token, masterpiece
+option style:
+ rarities to export:
+ render style: checklist
+ direction: vertical
+ export Images:
+ render style: both
+ choice images:
+ no: {built_in_image("bool_no")}
+ JPG: {built_in_image("bool_yes")}
+ PNG: {built_in_image("bool_yes")}
script:
splitter_name := {false} ## experimental future thing for splitting dfc images
#determine if the card is a type that is a "token" i.e. it should be batched with tokens instead of with other cards
is_token := {contains(card.shape, match:"token") or contains(card.shape, match:"emblem") or contains(card.shape, match:"rulestip") }
is_double := {contains(card.shape, match:"double") }
+ file_type := {if options.export_Images == "PNG" then "png" else "jpg"}
+
#determine if the card is of a rarity that should be included
included_rarity := {
+ (is_token() and chosen(options.rarities_to_export, choice:"token")) or chosen(options.rarities_to_export, choice:card.rarity)
+ }
+ included_rarity2 := {
(is_token() and options.include_Tokens)
or (card.rarity == "basic land" and options.include_Basic_Land)
or (card.rarity == "common" and options.include_Common)
@@ -107,37 +92,53 @@ script:
or (card.rarity == "mythic rare" and options.include_Mythic)
or (card.rarity == "special" and options.include_Special)
}
-
+
#Strip bad punctuation from card names
strip_card_name :=
replace@(match: "’",replace:"'") + #replace bad apostrophe with good apostrophe
replace@(match:":", replace:"")+ #remove colons
replace@(match:";", replace:"")+ #remove semicolons
+ replace@(match:"\n", replace:"")+ #remove linebreaks
replace@(match:"\\.", replace:"") #remove periods
-
+
+ # escape special xml characters
+ xml_escape := replace@(match:"&",replace:"&") #escape ampersands
+ + replace@(match:"\"",replace:"\\"") #escape double quote
+ + replace@(match:"\'",replace:"\\'") #escape single quote
+ + replace@(match:"\<",replace:"\\<") #escape less than sign
+ #+ replace@(match:"\>",replace:"\\>") #escape greater than sign, for some reason this upsets mse and they are technically not needed to escape
+ # escaped set code
+ setcode := xml_escape(set.set_code)
+
#functions for the !exportname command
exporter_name_filter := filter_text@(match:"!exporte?r?name [^\n\<]+")
exporter_name_grabber := replace@(match:"!exporte?r?name ", replace:"")
-
+
#determining what name should be used for the card
card_name := { if exporter_name_grabber(exporter_name_filter(card.notes)) != "" then exporter_name_grabber(exporter_name_filter(card.notes)) else card.name }
-
+
+ #surround mana symbols in curly brackets
+ format_mana := replace@(match:"(CHAOS|[1-9][0-9]+(?:\\/.)?|.\\/.\\/.|.\\/.|[+-]?[^.,: ])", replace:{"\{"+_1+"}"}, in_context:""
filter_count := filter_text@(match: token_count_regex)
generate_count_XML := replace@(match:token_count_regex, replace:{" count=\"" + _1 + "\""})
add_related_count := {if filter_count(input) != "" then generate_count_XML(filter_count(input)) else ""}
-
+
#helpers to find if a auto-attachment is desired for this token relation, and generate the requisite XML
add_attachment := {if filter_text(match: "", input) != "" then " attach=\"attach\"" else ""}
+ #helpers to find if persistent is desired for this token relation, and generate the requisite XML
+ add_persistent := {if filter_text(match:"<(conjure|persistent)>", input) != "" then " persistent=\"persistent\"" else ""}
+
#helper functions for converted_related later
- related_entry_regex := "(.+?[^[:space:]]);"
-
+ related_entry_regex := "(.+?[^[:space:]])(?:;|\n|$)"
+
#convert the !related command field to XML blocks
convert_related :=
replace@(match: "!related ?\n?", replace:"")+ #blank out the related command itself
@@ -145,20 +146,55 @@ script:
replace@(match: "’",replace:"'") + #replace bad apostrophe with good apostrophe
replace@(match: "",replace:"") + #replace accidentily capital X with lowercase X
replace@(match:"!",replace: "") + #blank out the command ender
-
+
#for every other card name, surround it with reverse-related tags and put in relevant attributes
- {for each entry in (break_text(match:related_entry_regex, input)) do ("\" + strip_card_name(entry) + "\\n")}
-
+ {for each entry in (break_text(match:related_entry_regex, input)) do ("\n \" + xml_escape(strip_card_name(entry)) + "\")}
+
#remove accidentily created empty XML blocks
- remove_empty := replace@(match:"\\", replace:"")
-
+ remove_empty := replace@(match:" \<(reverse-)?related>\(reverse-)?related>", replace:"")
+
+ #convert the !token command field to XML blocks
+ convert_token :=
+ replace@(match: "!tokens? ?\n?", replace:"")+ #blank out the related command itself
+ replace@(match: "\<",replace:"<") + #replace junk Start of Header characters with proper "less than sign"s
+ replace@(match: "’",replace:"'") + #replace bad apostrophe with good apostrophe
+ replace@(match: "",replace:"") + #replace accidentily capital X with lowercase X
+ replace@(match:"!",replace: "") + #blank out the command ender
+
+ #for every other card name, surround it with reverse-related tags and put in relevant attributes
+ {for each entry in (break_text(match:related_entry_regex, input)) do ("\n \" + xml_escape(strip_card_name(entry)) + "\")}
+
+
filter_related := filter_text@(match:"!relate ?[^!]+!?")
-
+ filter_token := filter_text@(match:"!tokens? ?[^!]+!?")
+
#functions for the !tapped command
contains_tapped := contains@(match:"!tapped")
-
- CIPT := {if contains_tapped(card.notes) then "\n "+"\" + "1" + "\" else ""}
-
+
+ CIPT := {if contains_tapped(card.notes) then "\n "+"\" + "1" + "\" else ""}
+
+ # maintype, used in cockatrice's card type sorting,
+ # no longer automatically determined in v4 xml,
+ # first use the same heuristic used in "oracle" else do the same thing v3 xml did
+ # !maintype [type]! in the card notes overwrites this
+ filter_maintype := filter_text@(match:"!maintype ?[^!]+!?")
+ maintype :=
+ {
+ "\n "+"\"
+ +(
+ if filter_maintype(card.notes) != "" then xml_escape(replace(match:"!$", replace:"", replace(match:"^!maintype ?", replace:"", filter_maintype(card.notes))))
+ else if contains(card.type, match:"Planeswalker") then "Planeswalker"
+ else if contains(card.type, match:"Creature") then "Creature"
+ else if contains(card.type, match:"Land") then "Land"
+ else if contains(card.type, match:"Sorcery") then "Sorcery"
+ else if contains(card.type, match:"Instant") then "Instant"
+ else if contains(card.type, match:"Artifact") then "Artifact"
+ else if contains(card.type, match:"Enchantment") then "Enchantment"
+ else xml_escape(replace(match:"^.* ", replace:"", replace(match:"()? —.*$", replace:"", card.type)))
+ )
+ +"\"
+ }
+
card_color :=
{
if contains(card.type, match:"land") or contains(card.rule_text, match:"Devoid") then "" else
@@ -170,7 +206,7 @@ script:
+(if contains(card.card_color, match:"green") or contains(card.casting_cost, match:"G") then "G" else "")
)
}
-
+
card_color_2 :=
{
if contains(card.type, match:"land") or contains(card.rule_text_2, match:"Devoid") then "" else
@@ -182,37 +218,37 @@ script:
+(if contains(card.card_color_2, match:"green") or contains(card.casting_cost_2, match:"G") then "G" else "")
)
}
-
+
#write a normal card's XML text
write_normal := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())+"\"
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + ">"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") then "\n ")
- +(if contains(card.type, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
- +(if contains(card.type, match:"Creature") then "\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") then "2"
else if contains(card.type, match:"Land") then "0"
@@ -221,28 +257,29 @@ script:
#CIPT
+ CIPT()
# Rules Text
- +"\n "+"\"+card_rules_text()+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text())+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_token := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+strip_card_name(card_name())+(if options.append_Set_Code_To_Tokens then " " + set.set_code else "")+"\"
+ +"\n "+"\"+xml_escape(strip_card_name(card_name())+(if options.append_Set_Code_To_Tokens then " " + setcode else ""))+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ +"\n "+"\"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") then "\n ")
- +(if contains(card.type, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
- +(if contains(card.type, match:"Creature") then "\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") then "2"
else if contains(card.type, match:"Land") then "0"
@@ -251,30 +288,31 @@ script:
#CIPT
+ CIPT()
# Rules Text
- +"\n "+"\"+card_rules_text()+"\"
+ +"\n "+"\"+xml_escape(card_rules_text())+"\"
# Token
- + "\n \1\"
+ + "\n "+"\1\"
# Reverse Related
#if there is a !related block in the cards notes, set up the reverse-related XML elements
- + (if filter_related(card.notes) != "" then remove_empty("\n" + convert_related(filter_related(card.notes))))
- +"\n"+"\"
+ + (if filter_related(card.notes) != "" then remove_empty(convert_related(filter_related(card.notes))))
+ +"\n "+"\"
}
write_flip := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))
#+" // "+strip_card_name(card.name_2)
+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + ">"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.shape, match:"flip") then
(if contains(card.card_color, match:"multicolor") or contains(card.card_color, match:"hybrid") then "M"
else if contains(card.card_color, match:"white") then "W"
@@ -283,7 +321,7 @@ script:
else if contains(card.card_color, match:"red") then "R"
else if contains(card.card_color, match:"green") then "G"
else "")
- else if card.card_color != "" and card.card_color != "land" and card.card_color != "artifact" and card.card_color_2 != "" and card.card_color_2 != "land" and card.card_color_2 != "artifact"then
+ else if card.card_color != "" and card.card_color != "land" and card.card_color != "artifact" and card.card_color_2 != "" and card.card_color_2 != "land" and card.card_color_2 != "artifact"then
(if contains(card.card_color, match:"multicolor") or contains(card.card_color, match:"hybrid") or card.card_color != card.card_color_2 then "M"
else if contains(card.card_color, match:"white") and contains(card.card_color_2, match:"white") then "W"
else if contains(card.card_color, match:"blue") and contains(card.card_color_2, match:"blue") then "U"
@@ -302,150 +340,157 @@ script:
)
+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost
+ +"\n "+"\"+card.casting_cost
+(if card.casting_cost_2 != "" then " // "+card.casting_cost_2)
+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+" // "+replace(card.type_2, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-")+" // "+replace(card.type_2, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") or contains(card.type_2, match:"Creature") then "\n ")
+ +(if contains(card.type, match:"Creature") or contains(card.type_2, match:"Creature") then "\n ")
+(if contains(card.type, match:"Creature") or contains(card.type_2, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
+ +(if contains(card.type, match:"Creature") then xml_escape(card.pt))
+(if contains(card.type, match:"Creature") and contains(card.type_2, match:"Creature") then " // ")
- +(if contains(card.type_2, match:"Creature") then card.pt_2)
+ +(if contains(card.type_2, match:"Creature") then xml_escape(card.pt_2))
+(if contains(card.type, match:"Creature") or contains(card.type_2, match:"Creature") then "\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") or contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") or contains(card.type_2, match:"Creature") then "2"
else if contains(card.type, match:"Land") or contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"+card_rules_text()+"\n--- \n"+card_rules_text_2()+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text()+"\n--- \n"+card_rules_text_2())+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_double := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))
#+" | ("+strip_card_name(card.name_2)+")"
+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+options.append_String_To_Names+strip_card_name(card_name())+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
- # Name of the related card
- +"\n "+"\"+strip_card_name(card.name_2)+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") then "\n ")
- +(if contains(card.type, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
- +(if contains(card.type, match:"Creature") then "\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") then "2"
else if contains(card.type, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"+card_rules_text()
- +"\n---\n(Back): "+strip_card_name(card.name_2)+"\"
- +"\n"+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text()
+ +"\n---\n(Back): "+strip_card_name(card.name_2))+"\"
+ # Name of the related card
+ +"\n "+"\"+xml_escape(strip_card_name(card.name_2))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
+ +"\n "+"\"
# Name II
- +"\n "+"\"
+ +"\n "+"\"
#+"("+strip_card_name(card_name())+") | "
- +strip_card_name(card.name_2)
+ +xml_escape(strip_card_name(card.name_2))
+"\"
# Set II
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+strip_card_name(card.name_2)+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color II
- +"\n "+"\"
+ +"\n "+"\"
+ card_color_2()
+"\"
# Mana Cost II
- +"\n "+"\"+card.casting_cost_2+"\"
+ +"\n "+"\"+card.casting_cost_2+"\"
# Converted Mana Cost II
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type II
- +"\n "+"\"+replace(card.type_2, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type_2, match:"—", replace:"-"))+"\"
# P/T II
- +(if contains(card.type_2, match:"Creature") then "\n ")
- +(if contains(card.type_2, match:"Creature") then "\")
- +(if contains(card.type_2, match:"Creature") then card.pt_2)
- +(if contains(card.type_2, match:"Creature") then "\")
+ +(if contains(card.type_2, match:"Creature") then "\n "+"\"+xml_escape(card.pt_2)+"\")
+ +"\n "+"\"
# Tablerow II
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text II
- +"\n "+"\"+card_rules_text_2()
- +"\n---\n(Front): "+strip_card_name(card_name())+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text_2()
+ +"\n---\n(Front): "+strip_card_name(card_name()))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
-
+
# Count the number of paragraphs to detect number of walker abilities.
paragraph_count := replace@(match:"\n", replace:"•")+
filter_text@(match:"•")
-
+
write_walker := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())+"\"
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + ">"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# Loyalty
- +"\n "+"\"+card.loyalty+"\"
+ +"\n "+"\"+card.loyalty+"\"
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"+"1"+"\"
+ +"\n "+"\"+"1"+"\"
#CIPT
+ CIPT()
# Rules Text
- +"\n "+"\"
- +(if card.special_text or else "" != "" then card.special_text else
+ +"\n "+"\"
+ +xml_escape((if card.special_text or else "" != "" then card.special_text else
card.loyalty_cost_1
+(if card.loyalty_cost_1 !="" then ": ")
+split_text(match:"\n", card.rule_text).0
@@ -460,50 +505,52 @@ script:
+(if contains(paragraph_count(card.rule_text), match:"•••") then "\n")
+card.loyalty_cost_4
+(if card.loyalty_cost_4 !="" then ": ")
- +(if contains(paragraph_count(card.rule_text), match:"•••") then split_text(match:"\n", card.rule_text).3))
+ +(if contains(paragraph_count(card.rule_text), match:"•••") then split_text(match:"\n", card.rule_text).3)))
+"\"
- +"\n"+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_double_walker := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))
#+" | ("+strip_card_name(card.name_2)+")"
+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+options.append_String_To_Names+strip_card_name(card_name())+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
- # Name of the related card
- +"\n "+"\"+strip_card_name(card.name_2)+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# Loyalty
- +(if contains(card.type, match:"Planeswalker") then "\n "+"\"+card.loyalty+"\")
+ +(if contains(card.type, match:"Planeswalker") then "\n "+"\"+card.loyalty+"\")
# P/T
- +(if contains(card.type, match:"Creature") then "\n "+"\"+card.pt+"\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"
- +(if card.special_text or else "" != "" then card.special_text else
+ +"\n "+"\"
+ +xml_escape((if card.special_text or else "" != "" then card.special_text else
card.loyalty_cost_1
+(if card.loyalty_cost_1 !="" then ": ")
+split_text(match:"\n", card.rule_text).0
@@ -516,45 +563,50 @@ script:
+(if card.loyalty_cost_3 !="" then ": ")
+(if contains(paragraph_count(card.rule_text), match:"••") then split_text(match:"\n", card.rule_text).2)
+(if contains(paragraph_count(card.rule_text), match:"•••") then "\n"))
- +"\n---\n(Back): "+strip_card_name(card.name_2)+"\"
- +"\n"+"\"
- +"\n"+"\"
+ +"\n---\n(Back): "+strip_card_name(card.name_2))+"\"
+ # Name of the related card
+ +"\n "+"\"+xml_escape(strip_card_name(card.name_2))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
+ +"\n "+"\"
# Name II
- +"\n "+"\"
+ +"\n "+"\"
#+strip_card_name(card_name())+") | "
- +strip_card_name(card.name_2)+"\"
+ +xml_escape(strip_card_name(card.name_2))+"\"
# Set II
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+strip_card_name(card.name_2)+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color II
- +"\n "+"\"
+ +"\n "+"\"
+ card_color_2()
+"\"
# Mana Cost II
- +"\n "+"\"+card.casting_cost_2+"\"
+ +"\n "+"\"+card.casting_cost_2+"\"
# Converted Mana Cost II
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type II
- +"\n "+"\"+replace(card.type_2, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type_2, match:"—", replace:"-"))+"\"
# Loyalty II
- +(if contains(card.type_2, match:"Planeswalker") then "\n "+"\"+card.loyalty_2+"\")
+ +(if contains(card.type_2, match:"Planeswalker") then "\n "+"\"+card.loyalty_2+"\")
# P/T II
- +(if contains(card.type_2, match:"Creature") then "\n "+"\"+card.pt_2+"\")
+ +(if contains(card.type_2, match:"Creature") then "\n "+"\"+xml_escape(card.pt_2)+"\")
+ +"\n "+"\"
# Tablerow II
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text II
- +"\n "+"\"
- +(if card.special_text_2 or else "" != "" then card.special_text_2 else
+ +"\n "+"\"
+ +xml_escape((if card.special_text_2 or else "" != "" then card.special_text_2 else
card.loyalty_cost_4
+(if card.loyalty_cost_4 !="" then ": ")
+split_text(match:"\n", card.rule_text_2).0
@@ -567,88 +619,92 @@ script:
+(if card.loyalty_cost_6 !="" then ": ")
+(if contains(paragraph_count(card.rule_text_2), match:"••") then split_text(match:"\n", card.rule_text_2).2)
+(if contains(paragraph_count(card.rule_text_2), match:"•••") then "\n"))
- +"\n---\n(Front): "+strip_card_name(card_name())+"\"
- +"\n"+"\"
+ +"\n---\n(Front): "+strip_card_name(card_name()))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_sparker := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))
#+" | ("+strip_card_name(card.name_2)+")"
+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+options.append_String_To_Names+strip_card_name(card_name())+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
- # Name of the related card
- +"\n "+"\"+strip_card_name(card.name_2)+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") then "\n ")
- +(if contains(card.type, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
- +(if contains(card.type, match:"Creature") then "\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") then "2"
else if contains(card.type, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"+card_rules_text()
- +"\n---\n(Back): "+strip_card_name(card.name_2)+"\"
- +"\n"+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text()
+ +"\n---\n(Back): "+strip_card_name(card.name_2))+"\"
+ # Name of the related card
+ +"\n "+"\"+xml_escape(strip_card_name(card.name_2))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
+ +"\n "+"\"
# Name II
- +"\n "+"\"
+ +"\n "+"\"
#+strip_card_name(card_name())+") | "
- +strip_card_name(card.name_2)+"\"
+ +xml_escape(strip_card_name(card.name_2))+"\"
# Set II
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+strip_card_name(card.name_2)+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color II
- +"\n "+"\"
+ +"\n "+"\"
+ card_color_2()
+"\"
# Mana Cost II
- +"\n "+"\"+card.casting_cost_2+"\"
+ +"\n "+"\"+card.casting_cost_2+"\"
# Converted Mana Cost II
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type II
- +"\n "+"\"+replace(card.type_2, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type_2, match:"—", replace:"-"))+"\"
# Loyalty II
- +(if contains(card.type_2, match:"Planeswalker") then "\n "+"\"+card.loyalty_2+"\")
+ +(if contains(card.type_2, match:"Planeswalker") then "\n "+"\"+card.loyalty_2+"\")
# P/T II
- +(if contains(card.type_2, match:"Creature") then "\n "+"\"+card.pt_2+"\")
+ +(if contains(card.type_2, match:"Creature") then "\n "+"\"+xml_escape(card.pt_2)+"\")
+ +"\n "+"\"
# Tablerow II
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text II
- +"\n "+"\"
- +(if card.special_text_2 or else "" != "" then card.special_text_2 else
+ +"\n "+"\"
+ +xml_escape((if card.special_text_2 or else "" != "" then card.special_text_2 else
card.loyalty_cost_4
+(if card.loyalty_cost_4 !="" then ": ")
+split_text(match:"\n", card.rule_text_2).0
@@ -661,49 +717,51 @@ script:
+(if card.loyalty_cost_6 !="" then ": ")
+(if contains(paragraph_count(card.rule_text_2), match:"••") then split_text(match:"\n", card.rule_text_2).2)
+(if contains(paragraph_count(card.rule_text_2), match:"•••") then "\n"))
- +"\n---\n(Front): "+strip_card_name(card_name())+"\"
- +"\n"+"\"
+ +"\n---\n(Front): "+strip_card_name(card_name()))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_sacrificer := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))
#+" | ("+strip_card_name(card.name_2)+")"
+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+options.append_String_To_Names+strip_card_name(card_name())+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
- # Name of the related card
- +"\n "+"\"+strip_card_name(card.name_2)+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# Loyalty
- +(if contains(card.type, match:"Planeswalker") then "\n "+"\"+card.loyalty+"\")
+ +(if contains(card.type, match:"Planeswalker") then "\n "+"\"+card.loyalty+"\")
# P/T
- +(if contains(card.type, match:"Creature") then "\n "+"\"+card.pt+"\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"
- +(if card.special_text or else "" != "" then card.special_text else
+ +"\n "+"\"
+ +xml_escape((if card.special_text or else "" != "" then card.special_text else
card.loyalty_cost_1
+(if card.loyalty_cost_1 !="" then ": ")
+split_text(match:"\n", card.rule_text).0
@@ -716,91 +774,92 @@ script:
+(if card.loyalty_cost_3 !="" then ": ")
+(if contains(paragraph_count(card.rule_text), match:"••") then split_text(match:"\n", card.rule_text).2)
+(if contains(paragraph_count(card.rule_text), match:"•••") then "\n"))
- +"\n---\n(Back): "+strip_card_name(card.name_2)+"\"
- +"\n"+"\"
- +"\n"+"\"
+ +"\n---\n(Back): "+strip_card_name(card.name_2))+"\"
+ # Name of the related card
+ +"\n "+"\"+xml_escape(strip_card_name(card.name_2))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
+ +"\n "+"\"
# Name II
- +"\n "+"\"
+ +"\n "+"\"
#+"("+strip_card_name(card_name())+") | "
- +strip_card_name(card.name_2)
+ +xml_escape(strip_card_name(card.name_2))
+"\"
# Set II
- +"\n "+"\"+set.set_code+"\"
+ + " splitterPath=\""+"/"+strip_card_name(card.name_2)+"." + file_type() + "\" >"+setcode+"\"
+ +"\n "+"\"
# Color II
- +"\n "+"\"
+ +"\n "+"\"
+ card_color_2()
+"\"
# Mana Cost II
- +"\n "+"\"+card.casting_cost_2+"\"
+ +"\n "+"\"+card.casting_cost_2+"\"
# Converted Mana Cost II
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type II
- +"\n "+"\"+replace(card.type_2, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type_2, match:"—", replace:"-"))+"\"
# P/T II
- +(if contains(card.type_2, match:"Creature") then "\n ")
- +(if contains(card.type_2, match:"Creature") then "\")
- +(if contains(card.type_2, match:"Creature") then card.pt_2)
- +(if contains(card.type_2, match:"Creature") then "\")
+ +(if contains(card.type_2, match:"Creature") then "\n "+"\"+xml_escape(card.pt_2)+"\")
+ +"\n "+"\"
# Tablerow II
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type_2, match:"Instant") or contains(card.type_2, match:"Sorcery") then "3"
else if contains(card.type_2, match:"Creature") then "2"
else if contains(card.type_2, match:"Land") then "0"
else "1")
+"\"
# Rules Text II
- +"\n "+"\"+card_rules_text_2()
- +"\n---\n(Front): "+strip_card_name(card_name())+"\"
- +"\n"+"\"
+ +"\n "+"\"+xml_escape(card_rules_text_2()
+ +"\n---\n(Front): "+strip_card_name(card_name()))+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
write_leveler := {
- "\n"+"\"
+ "\n "+"\"
# Name
- +"\n "+"\"+options.append_String_To_Names+strip_card_name(card_name())+"\"
+ +"\n "+"\"+xml_escape(options.append_String_To_Names+strip_card_name(card_name()))+"\"
# Set
- +"\n "+"\"+set.set_code+"\"
+ + ">"+setcode+"\"
+ +"\n "+"\"
# Color
- +"\n "+"\"
+ +"\n "+"\"
+ card_color()
+"\"
# Mana Cost
- +"\n "+"\"+card.casting_cost+"\"
+ +"\n "+"\"+card.casting_cost+"\"
# Converted Mana Cost
- +"\n "+"\"+card.cmc+"\"
- # Converted Mana Cost II
- +"\n "+"\"+card.cmc+"\"
+ +"\n "+"\"+card.cmc+"\"
# Type
- +"\n "+"\"+replace(card.type, match:"—", replace:"-")+"\"
+ +"\n "+"\"+xml_escape(replace(card.type, match:"—", replace:"-"))+"\"
+ +maintype()
# P/T
- +(if contains(card.type, match:"Creature") then "\n ")
- +(if contains(card.type, match:"Creature") then "\")
- +(if contains(card.type, match:"Creature") then card.pt)
- +(if contains(card.type, match:"Creature") then "\")
+ +(if contains(card.type, match:"Creature") then "\n "+"\"+xml_escape(card.pt)+"\")
+ +"\n "+"\"
#CIPT
+ CIPT()
# Tablerow
- +"\n "+"\"
+ +"\n "+"\"
+(if contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") then "3"
else if contains(card.type, match:"Creature") then "2"
else if contains(card.type, match:"Land") then "0"
else "1")
+"\"
# Rules Text
- +"\n "+"\"
+ +"\n "+"\"
#Level I
- +card_rules_text()
+ +xml_escape(card_rules_text()
# Level II
+"\nLEVEL " + card.level_1
+(if card.pt_2 != "" then "\n"+card.pt_2)
@@ -808,11 +867,12 @@ script:
# Level III
+"\nLEVEL " + card.level_2
+(if card.pt_3 != "" then "\n"+card.pt_3)
- +"\n"+card.rule_text_3
+ +"\n"+card.rule_text_3)
+"\"
- +"\n"+"\"
+ + (if filter_token(card.notes) != "" then remove_empty(convert_token(filter_token(card.notes))))
+ +"\n "+"\"
}
-
+
write_card := { if is_token() then ""
else if not(included_rarity()) then ""
else if contains(card.shape, match:"double") and contains(card.type, match:"Planeswalker") and contains(card.type_2, match:"Planeswalker") then write_double_walker()
@@ -824,7 +884,7 @@ script:
else if contains(card.shape, match:"leveler") then write_leveler()
else write_normal()
}
-
+
#if the currently exported card is a token, write it as a token
write_token_if_token := { if is_token() then write_token() else ""}
@@ -833,23 +893,23 @@ script:
{
write_image_file(
card,
- directory: "{set.set_code}",
- file:"{options.append_String_To_Names+strip_card_name(card_name())+(if is_token() and options.append_Set_Code_To_Tokens then " " + set.set_code else "")+if splitter_name() and is_double() then "_" + card.name_2}.full." + to_lower(options.images_File_Type),
+ directory: set.set_code,
+ file: (options.append_String_To_Names+strip_card_name(card_name())+(if is_token() and options.append_Set_Code_To_Tokens then " " + set.set_code else "")+if splitter_name() and is_double() then "_" + strip_card_name(card.name_2)) + "." + file_type(),
width: (if contains(card.shape, match:"split") or contains(card.shape, match:"double") then 752 else 375),
height: 523
)
}
-
+
#if images are set to be rendered, render all images of rarities that have been selected
- write_images := if options.export_Images then for each card in filter_list(cards,filter:{included_rarity(card:input)}) do write_image() else ""
-
+ write_images := if options.export_Images != "no" then for each card in filter_list(cards,filter:{included_rarity(card:input)}) do write_image() else ""
+
write_cards := to_text(for each card in cards do write_card())
write_all_tokens := to_text(for each card in cards do write_token_if_token())
-
+
#Main export script
-
+
#tokens in Separate XML
- if (options.include_Tokens and options.tokens_In_Separate_XML) then write_text_file(file:set.set_code + " Tokens" + ".xml", to_string("\n\n\n"+write_all_tokens+"\n\n\n"))
+ if (chosen(options.rarities_to_export, choice:"token") and options.tokens_In_Separate_XML) then write_text_file(file:set.set_code + " Tokens" + ".xml", to_string("\n\n \n"+write_all_tokens+"\n\n \n"))
#other cards
- to_string("\n\n\n\n"+set.set_code+"\n"+set.title+"\n"+options.cockatrice_Set_Type+"\n\n\n\n"+write_cards+if (options.include_Tokens and not(options.tokens_In_Separate_XML)) then ("\n\nTokens-->\n"+write_all_tokens)+"\n\n\n")
+ to_string("\n\n \n \n "+setcode+"\n "+xml_escape(set.title)+"\n "+xml_escape(options.cockatrice_Set_Type)+"\n \n \n \n"+write_cards+if (chosen(options.rarities_to_export, choice:"token") and not(options.tokens_In_Separate_XML)) then ("\n\n Tokens-->\n"+write_all_tokens)+"\n\n \n")
diff --git a/data/magic-cockatrice-v2.mse-export-template/icon.png b/data/magic-cockatrice-v2.mse-export-template/icon.png
new file mode 100644
index 000000000..c356e527a
Binary files /dev/null and b/data/magic-cockatrice-v2.mse-export-template/icon.png differ