2274 lines
98 KiB
Plaintext
2274 lines
98 KiB
Plaintext
############################################################## Localization
|
||
|
||
include file: language
|
||
|
||
# needed by all style files anyway
|
||
include file: /magic-blends.mse-include/new-blends
|
||
include file: statistics_script
|
||
|
||
############################################################## version check
|
||
version_date := {"2023-02-21"}
|
||
############################################################## Sorting mana symbols
|
||
|
||
# correctly sort a mana symbol (no guild mana)
|
||
mana_sort := sort_text@(order: "\\?XYZI[0123456789]VLHSFCAIE[TK](WUBRG)")
|
||
# correctly sort wedge mana
|
||
mana_sort_wedge := sort_text@(order: "\\?XYZI[0123456789]VLHSFCAIE[TK](WBGUR)")
|
||
mana_unsort := sort_text@(order:"[/\\?XYZI0123456789VLHSCAIETKWUBRG]")
|
||
# correctly sort guild mana
|
||
mana_sort_guild := sort_text@(order: "[\\?XYZI01234567890VLHSFCAIETKWUBRG/|]") +
|
||
replace@(
|
||
# No lookbehind :(
|
||
#match: "(?<!/)(./.|././.|./././.|.[|])(?!/)",
|
||
match: "./.|././.|./././.|.[|]",
|
||
in_context: "(^|[^/])<match>($|[^/])",
|
||
replace: {sort_text(order:"in_place((WUBRG))")}
|
||
)
|
||
mana_has_guild := match@(match: "[/|]") # Is there guild or half mana in the input?
|
||
mana_is_wedge := { chosen(set.mana_cost_sorting, choice: "tarkir wedge sorting") and ( number_of_items(in: sort_text(order:"<WUBRG>", input), filter: "<WUBRG>") == 3 ) }
|
||
mana_has_wedge := { mana_is_wedge() and (sort_text(order:"<WUBRG>", input) == "WUR" or sort_text(order:"<WUBRG>", input) == "WBR" or sort_text(order:"<WUBRG>", input) == "WBG" or sort_text(order:"<WUBRG>", input) == "UBG" or sort_text(order:"<WUBRG>", input) == "URG")}
|
||
# convert card.card_color to WUBRG
|
||
card_color_to_letters := {
|
||
color_string := trim_colors(input)
|
||
out_string := (if contains(color_string, match:"white") then "W" else "")+(if contains(color_string, match:"blue") then "U" else "")+(if contains(color_string, match:"black") then "B" else "")+(if contains(color_string, match:"red") then "R" else "")+(if contains(color_string, match:"green") then "G" else "")
|
||
out_string
|
||
}
|
||
card_is_wedge := {
|
||
color_string := card_color_to_letters(input)
|
||
if color_string == "WUR" or color_string == "WBR" or color_string == "WBG" or color_string == "UBG" or color_string == "URG" then true else false
|
||
}
|
||
list_colors := {
|
||
list := trim_colors(input)
|
||
cc := length(comma_count(list))
|
||
if cc == 1 then
|
||
list := replace(list, match:", ", replace:" and ")
|
||
if cc > 1 then
|
||
list := replace(list, match:", ", replace:", and ", in_context:"<match>[^ ]+$")
|
||
list
|
||
}
|
||
# A mana cost can contain both normal and guild mana
|
||
mana_filter := to_upper + {
|
||
if chosen(set.mana_cost_sorting, choice: "unsorted") then mana_unsort()
|
||
else if mana_has_guild() then mana_sort_guild()
|
||
else if mana_has_wedge(input) then mana_sort_wedge(input)
|
||
else mana_sort()
|
||
}
|
||
# Like mana filter, only also allow tap symbols:
|
||
tap_reduction :=
|
||
replace@(match:"(TK)+", replace:"")+
|
||
replace@(match:"T+", replace:"T")+
|
||
replace@(match:"Q+", replace:"Q")
|
||
tap_filter := filter_text@(match: "[TKQ]")
|
||
mana_filter_t := replace@( # Remove [] used for forcing mana symbols
|
||
match: "[\\[\\]]",
|
||
replace: ""
|
||
) + { tap_reduction(tap_filter()) + mana_filter() }
|
||
|
||
############################################################## Determine card color
|
||
|
||
# Names of colors
|
||
color_name := {
|
||
if input == "W" then "white"
|
||
else if input == "U" then "blue"
|
||
else if input == "B" then "black"
|
||
else if input == "R" then "red"
|
||
else if input == "G" then "green"
|
||
else ""
|
||
}
|
||
mana_name := {
|
||
if input == "white" then "W"
|
||
else if input == "blue" then "U"
|
||
else if input == "black" then "B"
|
||
else if input == "red" then "R"
|
||
else if input == "green" then "G"
|
||
else "C"
|
||
}
|
||
color_names_1 := { color_name(colors.0) }
|
||
color_names_2 := { color_name(colors.0) + ", " + color_name(colors.1) }
|
||
color_names_3 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) }
|
||
color_names_4 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) }
|
||
color_names_5 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) + ", " + color_name(colors.4) }
|
||
# color based on mana cost, input == a mana cost
|
||
color_filter := sort_text@(order: "<WUBRG>")
|
||
color_filterH := sort_text@(order: "</>")
|
||
mana_to_color := {
|
||
count := number_of_items(in: colors)
|
||
if hybrid == "" and contains(type, match:"Artifact") then
|
||
# not a hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if set.set_info.use_gradient_multicolor == "no" then "artifact, multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", artifact, multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "artifact, multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", artifact, multicolor"
|
||
else if count == 4 then color_names_4() + ", artifact, multicolor"
|
||
else if count == 5 then color_names_5() + ", artifact, multicolor"
|
||
else "artifact, multicolor"
|
||
else if hybrid == "" then
|
||
# not a hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if set.set_info.use_gradient_multicolor == "no" then "multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", multicolor"
|
||
else if count == 4 then color_names_4() + ", multicolor"
|
||
else if count == 5 then color_names_5() + ", multicolor"
|
||
else "multicolor"
|
||
else if contains(type, match:"Artifact") then
|
||
# hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if count == 2 then color_names_2() + ", artifact"
|
||
else "artifact, multicolor"
|
||
else
|
||
# hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if count == 2 then color_names_2() + ", hybrid"
|
||
else "multicolor"
|
||
}
|
||
|
||
# color based on land text box, input == textbox contents
|
||
color_text_filter :=
|
||
# remove activation costs
|
||
replace@(
|
||
match: "<sym[^>]*>[^<]+</sym[^>]*>"
|
||
in_context: "(?ix) (\\n|^)[^:]*<match>(,|:) | (pays?|additional|costs?)[ ]<match>",
|
||
replace: ""
|
||
) +
|
||
# keep only mana
|
||
filter_text@(match: "<sym[^>]*>([^<]+)") + color_filter;
|
||
# get the land frame for a "WUBRG"-style input.
|
||
land_multicolor := {
|
||
count := number_of_items(in: colors)
|
||
if count == 0 then "land"
|
||
else if count == 1 then color_names_1() + ", land"
|
||
else if count == 2 then color_names_2() + ", land"
|
||
else "land, multicolor"
|
||
}
|
||
land_to_color := {
|
||
# Based on watermark
|
||
if watermark == "mana symbol white" then "white, land"
|
||
else if watermark == "mana symbol blue" then "blue, land"
|
||
else if watermark == "mana symbol black" then "black, land"
|
||
else if watermark == "mana symbol red" then "red, land"
|
||
else if watermark == "mana symbol green" then "green, land"
|
||
else land_multicolor(colors:color_text_filter(input: rules))
|
||
}@(rules:card.rule_text)
|
||
|
||
# Look for a CDA that defines colors
|
||
text_to_color := {
|
||
# Note: running filter_text is quite slow, do a quick 'contains' check first
|
||
if contains(match: card_name + " is") then (
|
||
text := filter_text(match: "is (colorless|all colors|((blue|white|green|red|black)((,|,? and) (blue|white|green|red|black))*))", in_context: regex_escape(card_name)+"(</[-a-z]+>)* <match>\\.")
|
||
if text != "" then (
|
||
if contains(text, match: "all colors") then (
|
||
colors := "WUBRG"
|
||
if land == "true" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
) else (
|
||
colors := ""
|
||
if contains(text, match: "white") then colors := colors + "W"
|
||
if contains(text, match: "blue") then colors := colors + "U"
|
||
if contains(text, match: "black") then colors := colors + "B"
|
||
if contains(text, match: "red") then colors := colors + "R"
|
||
if contains(text, match: "green") then colors := colors + "G"
|
||
if land == "true" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
)
|
||
)
|
||
else ""
|
||
)
|
||
else ""
|
||
}
|
||
|
||
is_creature := match@(match: "(?i)Creature")
|
||
is_creaturish := match@(match: "(?i)(Creature|Vehicle)")
|
||
is_tribal := match@(match: "(?i)Tribal")
|
||
is_artifact := match@(match: "(?i)Artifact")
|
||
is_land := match@(match: "(?i)Land")
|
||
is_enchantment := match@(match: "(?i)Enchantment")
|
||
is_aura := match@(match: "(?i)Aura")
|
||
is_spell := match@(match: "(?i)Instant|Sorcery")
|
||
is_sorcery := match@(match: "(?i)Sorcery")
|
||
is_instant := match@(match: "(?i)Instant")
|
||
is_planeswalker := match@(match: "(?i)Planeswalker")
|
||
is_legendary := match@(match: "(?i)Legendary")
|
||
match_vehicle := contains@(match:"Vehicle")
|
||
match_snow := contains@(match:"Snow")
|
||
|
||
# The color of a card
|
||
card_color := {
|
||
# usually the color of mana
|
||
text_color := text_to_color(rules_text, land: is_land(type));
|
||
if text_color == "" then (
|
||
mana_color := mana_to_color(colors: color_filter(casting_cost), hybrid: color_filterH(casting_cost))
|
||
if mana_color == "colorless" and is_land (type) then land_to_color(watermark, rules:rules_text)
|
||
else if mana_color == "colorless" and is_artifact(type) then "artifact"
|
||
else if mana_color == "colorless" and contains(card.shape, match:"flip") then default
|
||
else mana_color
|
||
)
|
||
else text_color
|
||
};
|
||
##todo check nil
|
||
has_two_names := {contains(card.shape, match:"split") or contains(card.shape, match:"adventure") or contains(card.shape, match:"flip") or contains(card.shape, match:"double faced") or contains(card.shape, match:"aftermath")}
|
||
# Number of colors in a card_color
|
||
card_color_color_count := count_chosen@(choices: "white,blue,black,red,green,artifact")
|
||
# Clean up color field
|
||
card_color_filter := {
|
||
colors := card_color_color_count()
|
||
if colors > 2 then
|
||
input := remove_choice(choice: "overlay")
|
||
if colors > 1 then (
|
||
input := require_choice(choices: "multicolor, hybrid, land, artifact")
|
||
input := exclusive_choice(choices: "multicolor, hybrid")
|
||
input := require_exclusive_choice(choices: "horizontal, vertical, radial, overlay")
|
||
) else
|
||
input := remove_choice(choices: "radial, horizontal, vertical, overlay, hybrid, reversed")
|
||
if chosen(choice:"overlay") then
|
||
input := remove_choice(choice: "reversed")
|
||
input
|
||
}
|
||
|
||
|
||
############################################################## Card number
|
||
# exportname
|
||
exporter_name_filter := filter_text@(match:"!exporte?r?name [^\n!]+")
|
||
exporter_name_grabber := replace@(match:"!exporte?r?name ", replace:"")
|
||
export_name := { exporter_name_grabber(exporter_name_filter(card.notes))}
|
||
|
||
# Index for sorting, white cards are first, so white->A, blue->B, .. ,
|
||
# The code consists of 3 parts:
|
||
# color, shifted, split
|
||
sort_index := {
|
||
color_of_card() +
|
||
(if contains(card.shape, match:"shifted") then "S" else " ") + # planeshifted cards come after normal ones
|
||
(if contains(card.shape, match:"split") then "S" else " ") + # split cards come after normal ones
|
||
":"
|
||
}
|
||
# Process the name for sorting rules
|
||
sort_name :=
|
||
# Remove "The", "A", and "An" at the beginning
|
||
replace@(match: "^(The|An?) ", replace: "") +
|
||
# Remove commas and apostrophes
|
||
replace@(match: "(,|'|’)", replace: "") +
|
||
# Remove bold and italic tags
|
||
replace@(match: "(<b>|<i>|</b>|</i>)", replace: "") +
|
||
# Make lowercase
|
||
to_lower
|
||
|
||
is_multicolor := { chosen(choice: "multicolor") and input != "artifact, multicolor" }
|
||
is_null_cost := { input == "" or input == "0" }
|
||
is_hybrid_cost := { contains(card.casting_cost, match: "W/") or contains(card.casting_cost, match: "U/") or contains(card.casting_cost, match: "B/") or contains(card.casting_cost, match: "R/") or contains(card.casting_cost, match: "G/") }
|
||
basic_land_sort := {
|
||
if contains(card.name, match:"Plains") then "MB" # Plains
|
||
else if contains(card.name, match:"Island") then "MC" # Islands
|
||
else if contains(card.name, match:"Swamp") then "MD" # Swamps
|
||
else if contains(card.name, match:"Mountain") then "ME" # Mountains
|
||
else if contains(card.name, match:"Forest") then "MF" # Forests
|
||
else "MA" # other basic lands
|
||
}
|
||
hybrid_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if not set.sort_hybrid_in_pairs then "HK"
|
||
else if colors == "WU" then "HA"
|
||
else if colors == "UB" then "HB"
|
||
else if colors == "BR" then "HC"
|
||
else if colors == "RG" then "HD"
|
||
else if colors == "WG" then "HE"
|
||
else if colors == "WB" then "HF"
|
||
else if colors == "UR" then "HG"
|
||
else if colors == "BG" then "HH"
|
||
else if colors == "WR" then "HI"
|
||
else if colors == "UG" then "HJ"
|
||
else "HK"
|
||
}
|
||
multi_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if not set.sort_multicolor_in_pairs then "GK"
|
||
else if colors == "WU" then "GA"
|
||
else if colors == "UB" then "GB"
|
||
else if colors == "BR" then "GC"
|
||
else if colors == "RG" then "GD"
|
||
else if colors == "WG" then "GE"
|
||
else if colors == "WB" then "GF"
|
||
else if colors == "UR" then "GG"
|
||
else if colors == "BG" then "GH"
|
||
else if colors == "WR" then "GI"
|
||
else if colors == "UG" then "GJ"
|
||
else if contains(card.casting_cost, match:"/") then "GL"
|
||
else "GK"
|
||
}
|
||
# A code for the color of the card
|
||
color_of_card := {
|
||
card_color := card.card_color
|
||
casting_cost := card.casting_cost
|
||
type := card.super_type
|
||
if contains(card.shape, match: "split") and
|
||
card_color != card.card_color_2 then "I" # Diff Color Splits
|
||
else if chosen(choice: "land", card_color) then ( # Lands
|
||
if card.rarity != "basic land" then "L" # Nonbasic Land
|
||
else basic_land_sort() # Basic Land
|
||
) else if is_null_cost(casting_cost) then ( # Non-Land Cards with no or zero costs.
|
||
if chosen(choice: "colorless", card_color) then "A" # Clear Colorless
|
||
else if chosen(choice: "hybrid", card_color) then "HK" # Hybrids
|
||
else if is_multicolor(card_color) then "GK" # Multicolor
|
||
else if chosen(choice:"white", card_color) then "B" # White
|
||
else if chosen(choice:"blue", card_color) then "C" # Blue
|
||
else if chosen(choice:"black", card_color) then "D" # Black
|
||
else if chosen(choice:"red", card_color) then "E" # Red
|
||
else if chosen(choice:"green", card_color) then "F" # Green
|
||
else "J" # Artifact
|
||
) else (
|
||
# Cards with costs.
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if colors == "" and contains(type, match:"Artifact") then "J" # Artifact
|
||
else if colors == "" then "A" # Clear Colorless
|
||
else if colors == "W" then "B" # White
|
||
else if colors == "U" then "C" # Blue
|
||
else if colors == "B" then "D" # Black
|
||
else if colors == "R" then "E" # Red
|
||
else if colors == "G" then "F" # Green
|
||
else if is_hybrid_cost() then hybrid_color_pair_sort() # Hybrid (by pairs)
|
||
else if contains(casting_cost, match:"/") and contains(type, match:"Artifact") then "I" # Hybrid Artifacts
|
||
else multi_color_pair_sort() # Multicolor (by pairs)
|
||
)
|
||
}
|
||
|
||
rarity_sort := {
|
||
if card.shape == "token" then "T1"
|
||
else if card.shape == "emblem" then "T2"
|
||
else if card.shape == "rulestip" then "T3"
|
||
else if card.shape == "counter" then "T4"
|
||
else if card.shape == "checklist" then "T5"
|
||
else if is_masterpiece() then "T6"
|
||
else if set.sort_special_rarity == "with the rest" or card.rarity != "special" then " "
|
||
else "S"
|
||
}
|
||
card_partition := {"A"}
|
||
over_partition := {
|
||
my_pos := number_partition()
|
||
mn_pos := if set.last_main_partition == "" then "M" else to_upper(substring(set.last_main_partition, end:1))
|
||
posis := [my_pos, mn_pos]
|
||
higher := sort_list(posis).0
|
||
my_pos != higher
|
||
}
|
||
number_partition := { to_upper(substring(card_partition(), end:1)) }
|
||
set_filter := {
|
||
# TODO: what about rulestips?
|
||
if is_unsorted() then
|
||
{ is_unsorted() }
|
||
else if card.shape == "token" or card.shape == "emblem" then
|
||
{ card.shape == "token" or card.shape == "emblem" }
|
||
else if card.shape == "rulestip" then
|
||
{ card.shape == "rulestip" }
|
||
else if card.shape == "counter" then
|
||
{ card.shape == "counter" }
|
||
else if card.shape == "checklist" then
|
||
{ card.shape == "checklist" }
|
||
else if is_masterpiece() and card.shape != "token" and card.shape != "emblem" then
|
||
{ is_masterpiece() and card.shape != "token" and card.shape != "emblem" }
|
||
else if set.sort_special_rarity != "separate numbering" then
|
||
{ not over_partition() and not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist"}
|
||
else if card.rarity == "special" then
|
||
{ not over_partition() and not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist" and card.rarity == "special" }
|
||
else
|
||
{ not over_partition() and not is_unsorted() and card.shape != "token" and not is_masterpiece() and card.shape != "emblem" and card.shape != "rulestip" and card.shape != "counter" and card.shape != "checklist" and card.rarity != "special" }
|
||
}
|
||
card_number_offset := {pull_comma_array(set.card_number_offsets, cell:0, end:false, default:0)}
|
||
set_number_offset := {pull_comma_array(set.card_number_offsets, cell:1, end:false, default:0)}
|
||
card_number := {
|
||
position (
|
||
of: card
|
||
in: set
|
||
order_by: { number_partition() + rarity_sort() + sort_index() + sort_name(card.name) + sort_name(export_name())}
|
||
filter: set_filter()
|
||
) + 1 + to_number(card_number_offset())
|
||
}
|
||
card_count := {
|
||
number_of_items(in: set, filter: set_filter()) + to_number(set_number_offset())
|
||
}
|
||
|
||
#Starting with M15, zero digits in card numbers should be shown up to three.
|
||
card_number_m15 := { (if card_number() < 100 then "0" else "") + (if card_number() < 10 then "0" else "") + card_number() }
|
||
card_count_m15 := { (if card_count() < 100 then "0" else "") + (if card_count() < 10 then "0" else "") + card_count() }
|
||
#Starting with MOM, zero digits in card numbers should be shown up to four
|
||
card_number_mom := { (if card_number() < 1000 then "0" else "") + (if card_number() < 100 then "0" else "") + (if card_number() < 10 then "0" else "") + card_number() }
|
||
|
||
card_number_script_core := {
|
||
if is_unsorted() or not set.automatic_card_numbers then
|
||
combined_editor(field1: card.custom_card_number, separator: " " + rarity_code() + " ", field2: card.card_code_text)
|
||
else if set.card_number_style == "0001" then
|
||
forward_editor(prefix: rarity_code() + " " + card_number_mom() + " ", field: card.card_code_text)
|
||
else if set.card_number_style == "001/099" then
|
||
forward_editor(prefix: card_number_m15() + (if over_partition() then "" else "/" + card_count_m15()) + " " + rarity_code() + " ", field: card.card_code_text)
|
||
else if set.card_number_style == "001" then
|
||
forward_editor(prefix: card_number_m15() + " " + rarity_code() + " ", field: card.card_code_text)
|
||
else if set.card_number_style == "1/99" then
|
||
forward_editor(prefix: card_number() + (if over_partition() then "" else "/" + card_count()) + " " + rarity_code() + " ", field: card.card_code_text)
|
||
else
|
||
forward_editor(prefix: card_number() + " " + rarity_code() + " ", field: card.card_code_text)
|
||
}
|
||
|
||
# used by pack scripts
|
||
is_token_card := { card.shape == "token" or card.shape == "rulestip" or card.shape == "counter" or card.shape == "checklist" or card.shape == "emblem"}
|
||
is_shifted_card := { contains(card.shape, match:"shifted") }
|
||
is_masterpiece := { card.rarity == "masterpiece" }
|
||
is_nightbreak := { card.shape == "nightbreak" }
|
||
|
||
|
||
############################################################## Utilities for keywords
|
||
|
||
comma_count := filter_text@(match:",")
|
||
# Replace spaces by a spacer
|
||
separate_words := remove_tags + trim + replace@(match:" ", replace: {spacer})
|
||
|
||
# replaces — correctly
|
||
add := "" # default is nothing
|
||
|
||
trim_reminder_x := replace@(match: ". X can’t be 0.", replace: "")
|
||
|
||
# If the 'input' parameter is a mana costs, then adds 'add'
|
||
for_mana_costs := {
|
||
if input.separator_before == "—" and contains(input.param, match: " ") then ( ##multi word
|
||
if comma_count(input.param) == "," then ( ##two part
|
||
if match(match: "^[VLHSCAIETKQ\\?XYZIWUBRG0-9/|]+,", input.param) then ##starts with mana
|
||
"{add}<param-cost>{alternative_cost(input.param, trim:combined_cost, s:action)}</param-cost>" ##"add" mana
|
||
else "<param-cost>{alternative_cost(input.param, trim:combined_cost, s:action)}</param-cost>{non}" ## else cost "non"
|
||
) else if contains(input.param, match: ",") then ( ##three+ parts
|
||
if match(match: "^[VLHSCAIETKQ\\?XYZIWUBRG0-9/|]+,", input.param) then ##starts with mana
|
||
"{add}<param-cost>{alternative_cost(input.param, trim:long_cost, s:action)}</param-cost>" ##"add" mana with long formatting
|
||
else "<param-cost>{alternative_cost(input.param, trim:long_nomana_cost, s:action)}</param-cost>{non}" ## else cost "non" with long formatting
|
||
) else
|
||
"<param-cost>{alternative_cost(input.param, s:action, trim:lower_first)}{non}</param-cost>" ##one, nonmana, part
|
||
) else if match(match: "^[VLHSCAIETKQ\\?XYZIWUBRG0-9/|]+$", input.param) then ##one word
|
||
"{add}<param-mana>{input.param}</param-mana>" ##mana
|
||
else
|
||
"<param-cost>{alternative_cost(input.param, trim:combined_cost, s:action)}</param-cost>{non}" ##nonmana
|
||
}@(non:" in addition to any other costs", action:false)
|
||
|
||
# Convert extra costs
|
||
long_cost := replace@(match:", [A-Z]", replace: { to_lower() } )
|
||
long_nomana_cost := replace@(match:"[A-Z]", replace: { to_lower() })
|
||
# Convert first character to lower case
|
||
lower_first := replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
combined_cost := replace@(match:", [A-Z]", replace: { to_lower() })+
|
||
replace@(match:",", replace:" and")+
|
||
replace@(match:"^[VLHSCETKQ\\?XYZIWUBRG0-9/|]+", in_context: "(^|[[:space:]])<match>(?![a-z])", replace: "<sym-auto>&</sym-auto>")+
|
||
replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
alternative_cost := {
|
||
input := trim(input)
|
||
if s then
|
||
input := actionize(input)
|
||
input
|
||
}@(trim: lower_first, s:false, trim:{input})
|
||
actionize := replace@(match:"(activate|ante|cast|choose|create|destroy|discard|double|draw|exchange|exile|fight|mill|play|put|regenerate|return|reveal|sacrifice|shuffle|tap|untap|transform|vote|exert|pay)(?=($| |,|\\.))", replace:"\\1s")
|
||
+replace@(match:"(attach)", replace:"\\1es")
|
||
+replace@(match:"scry", replace:"scries")
|
||
+replace@(match:"your", replace:"their")
|
||
#
|
||
protection_code := {
|
||
output := if match(input, match:"(artifacts|creatures|enchantments|instants|lands|planeswalkers|sorceries|tribals|planes|schemes|emblems|conspiracies|^[A-Z]|^[^ ]* named)") then replace(input, match:"and from", replace:"or", in_context:" <match> ")
|
||
else if match(input, match:"^(converted|mana|power|toughness)") then "anything with " + replace(input, match:"and from", replace:"or", in_context:" <match> ")
|
||
else if contains(input, match:"the chosen player") then "anything " + replace(input, match:"the chosen", replace:"controlled by that")
|
||
else if contains(input, match:"the chosen") then "anything with " + replace(input, match:"the chosen", replace:"that")
|
||
else if contains(input, match:"all colors") then "anything " + replace(input, match:"all colors", replace:"that's white, blue, black, red, or green")
|
||
else if match(input, match:"^you$") then "anything you control"
|
||
else if match(input, match:"^its owner$") then "anything its owner controls"
|
||
else if match(input, match:"^(each of )?your opponents$") then "anything " + replace(input, match:"(each of )?your opponents", replace:"controlled by those players")
|
||
else if match(input, match:"(the|a) [^\n]* of your choice") then "anything " + replace(input, match:"(the|a) ([^\n]*) of your choice", replace:"of that \\2")
|
||
else if input == "colorless" then "anything colorless"
|
||
else "anything " + replace(english_singular(input), match:"and from", replace:"or", in_context:" <match> ")
|
||
output := " targeted, dealt damage, enchanted, equipped by " + output
|
||
if match(output, match:"(artifacts|creatures|instants|lands|planeswalkers|sorceries|tribals|planes|schemes|emblems|conspiracies|by [A-Z])") and not match(output, match:"(enchantmentsAura|Curse)") then
|
||
output := replace(output, match:", enchanted", replace:"")
|
||
else output := output
|
||
if match(output, match:"(enchantments|creatures|instants|lands|planeswalkers|sorceries|tribals|planes|schemes|emblems|conspiracies|by [A-Z])") and not match(output, match:"(artifacts|Equipment)") then
|
||
output := replace(output, match:" equipped", replace:"")
|
||
else output := output
|
||
if match(output, match:"equipped by") then output := replace(output, match:"equipped by", replace:"or equipped by")
|
||
else if match(output, match:"enchanted, by") then output := replace(output, match:"enchanted, by", replace:"or enchanted by")
|
||
else if match(output, match:"dealt damage, by") then output := replace(output, match:"dealt damage, by", replace:"or dealt damage by")
|
||
else ""
|
||
if match(output, match:"^ targeted, or dealt damage by") then output := replace(output, match:"^ targeted, or dealt damage by", replace:" targeted or dealt damage by")
|
||
if match(output, match:"anything [A-Z]") then output := replace(output, match:"anything ", replace:"")
|
||
if match(output, match:"or les") then output := replace(output, match:"or les$", replace:"or less")
|
||
if match(output, match:"(anything )?everything") then output := replace(output, match:"(anything )?everything", replace:"anything")
|
||
output := (if self_pro_check(card.text) then "You can't be" else if is_spell(card.type) then "It can't be blocked," else if is_creaturish(card.type) then "This creature can't be blocked," else "This permanent can't be") + output
|
||
output
|
||
}
|
||
self_pro_check := match@(match:"You ha(ve|s) <kw-A><nospellcheck>protection")
|
||
craft_code := {
|
||
[
|
||
"en": {
|
||
## beginning
|
||
rem := param2.value + ", Exile this artifact, Exile ";
|
||
|
||
## check if a number is given
|
||
count := filter_text(param1.value, match:"^(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|[0-9]+)(-(one|two|three|four|five|six|seven|eight|nine))? (or more)?");
|
||
|
||
## replace trailing space
|
||
count := trim(count)
|
||
|
||
## check how many commas are given
|
||
commas := filter_text(param1.value, match:",");
|
||
|
||
## check if this starts with a vowel
|
||
vowel := match(param1.value, match:"^[aeiouAEIOU]");
|
||
|
||
## if we have a comma separated list, use the number of elements as the count
|
||
## this doesn't support like, Craft with two Islands and two Mountains
|
||
## you've done that to yourself
|
||
if commas != "" then count := english_number(length(commas)+1);
|
||
|
||
## unused style (craft with three)
|
||
#### param1 == "three" count == "three"
|
||
## counting style (craft with one or more); (craft with six artifacts)
|
||
#### param1 == "one or more" count == "one"; param1 == "six artifacts" count == "six"
|
||
## singular style (craft with creature)
|
||
#### param1 == "creature" count == ""
|
||
if count == param1.value then
|
||
(
|
||
## Exile three other...
|
||
rem := rem
|
||
+ param1.value
|
||
+ " other permanents you control and/or cards from your graveyard: "
|
||
)
|
||
else if count != "" then
|
||
(
|
||
## Exile one or more from among...
|
||
## Exile the six from among...
|
||
rem := rem
|
||
+ (if count == "one or more" then param1.value else "the " + count)
|
||
+ " from among other permanents you control and/or cards in your graveyard: "
|
||
)
|
||
else
|
||
(
|
||
## Exile another creature you control or...
|
||
rem := rem
|
||
+ "another " + param1.value + " you control or "
|
||
+ (if vowel then "an " else "a ") + param1.value + " card from your graveyard: "
|
||
)
|
||
|
||
## ending and return
|
||
rem := rem + "Return this card transformed under its owner's control. Craft only as a sorcery."
|
||
rem
|
||
},
|
||
"de": {
|
||
## beginning
|
||
rem := param2.value + ", schnicke dieses Artefakt ins Exil, schicke ";
|
||
|
||
## check if a number is given
|
||
count := filter_text(param1.value, match:"^(zwanzig|dreiβig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig|eine[mr]|eins?|zwei|drei|vier|fünf|sechs?|sieben|sieb|acht|neun|zehn|elf|zwölf|[0-9]+)(und)?(zehn|zwanzig|dreiβig|vierzig|fünfzig|sechzig|siebzig|achtzig|neunzig)?( oder mehr(eren)?)? ?");
|
||
|
||
## save the thing we're exiling
|
||
target := trim(replace(param1.value, match:count, replace:""))
|
||
alt_target := if length(target) > 15 then "Permanente" else target
|
||
|
||
## format count
|
||
count := replace(count, match:"eine[mr]", replace:"eins")
|
||
count := trim(count)
|
||
|
||
## check how many commas are given
|
||
commas := filter_text(param1.value, match:",");
|
||
|
||
## check if this starts with a vowel
|
||
vowel := match(target, match:"^[aäeiouüAÄEIOUÜ]");
|
||
|
||
## if we have a comma separated list, use the number of elements as the count
|
||
## this doesn't support eg Craft with two Islands and two Mountains
|
||
## you've done that to yourself
|
||
if commas != "" then (
|
||
count := german_number(length(commas)+2);
|
||
alt_target := "Permanente"
|
||
)
|
||
|
||
## unused style (craft with three)
|
||
#### param1 == "three" count == "three"
|
||
## counting style (craft with one or more); (craft with six artifacts)
|
||
#### param1 == "one or more" count == "one"; param1 == "six artifacts" count == "six"
|
||
## singular style (craft with creature)
|
||
#### param1 == "creature" count == ""
|
||
|
||
if count == param1.value then
|
||
(
|
||
## Exile three other...
|
||
rem := rem
|
||
+ param1.value
|
||
+ " weiteren Permanente, die du kontrollierst und/oder Karten aus deinem Friedhof ins Exil: "
|
||
)
|
||
else if count != "eins" then
|
||
(
|
||
## with one or more...
|
||
## with four or more
|
||
## with two+...
|
||
rem := rem
|
||
+ (
|
||
if count == "eins oder mehreren" then "ein oder mehrere weitere "
|
||
else if contains(count, match:"oder") then "die " + count + " weireren "
|
||
else "die " + count + " oder mehr weiteren "
|
||
## todo this should list the denumbered param1.value instead
|
||
)
|
||
+ alt_target
|
||
+ (if vowel then ", das du" else ", die du")
|
||
+ " kontrollierst und/oder Karten aus deinem Friedhof ins Exil: "
|
||
)
|
||
else
|
||
(
|
||
## with einem Artefakt
|
||
## with einem Kreatur
|
||
rem := rem
|
||
+ (if target == "Artefakt" then "ein weiteres " else "ein ")
|
||
+ target
|
||
+ ", "
|
||
+ (if vowel then "das du" else "die du")
|
||
+ " kontrollierst, oder "
|
||
+ (if vowel then "eines " else "eine ") + target
|
||
+ (if target == "Kreatur" then "en-karte" else "-karte")
|
||
+" aus deinem Friedhof ins Exile: "
|
||
)
|
||
|
||
## ending and return
|
||
rem := rem + "Bringe diese Karte transformiert unter der Kontrolle ihres Besitzers ins Spiel zurück. Spiele Anfertigung wie eine Herexi."
|
||
rem
|
||
}
|
||
][lang_setting("code") or else "en"]()
|
||
}
|
||
|
||
long_dash := replace@(match:"-", replace:"—")
|
||
|
||
# Utilities for keywords
|
||
|
||
has_cc := { card.casting_cost != "" }
|
||
|
||
has_pt := { card.power != "" or card.toughness != "" }
|
||
|
||
contains_target := match@(match:"(?i)([^a-z]|^)targets?([^a-z]|$)")
|
||
|
||
is_spell := { contains(card.type, match:"Instant") or contains(card.type, match:"Sorcery") }
|
||
|
||
is_targeted := { contains_target(card.rule_text) }
|
||
|
||
color_to_mana := replace@(match: "white", replace: "[W]")+
|
||
replace@(match: "blue", replace: "[U]")+
|
||
replace@(match: "black", replace: "[B]")+
|
||
replace@(match: "red", replace: "[R]")+
|
||
replace@(match: "green", replace: "[G]")
|
||
|
||
digital_map := [
|
||
"zero": 0,
|
||
"one": 1,
|
||
"once": 1,
|
||
"a": 1,
|
||
"an": 1,
|
||
"two": 2,
|
||
"twice": 2,
|
||
"three": 3,
|
||
"thrice": 3,
|
||
"four": 4,
|
||
"five": 5,
|
||
"six": 6,
|
||
"seven": 7,
|
||
"eight": 8,
|
||
"nine": 9,
|
||
"ten": 10,
|
||
"eleven": 11,
|
||
"twelve": 12,
|
||
"thirteen": 13,
|
||
"fourteen": 14,
|
||
"fifteen": 15,
|
||
"sixteen": 16,
|
||
"seventeen": 17,
|
||
"eighteen": 18,
|
||
"nineteen": 19,
|
||
"twenty": 20,
|
||
"thirty": 30,
|
||
"forty": 40,
|
||
"fifty": 50,
|
||
"sixty": 60,
|
||
"seventy": 70,
|
||
"eighty": 80,
|
||
"ninety": 90
|
||
]
|
||
iterate_fix := remove_tags
|
||
+replace@(match: "^\\.", replace:"")
|
||
+replace@(match: "^,", replace:"")
|
||
+replace@(match: "^[ ]", replace:"")
|
||
+replace@(match:" times", replace:"")
|
||
iterate_digits := {
|
||
trimmed := iterate_fix(input)
|
||
if trimmed == "" then 1 else digital_map[trimmed] or else trimmed
|
||
}
|
||
digital_number := {
|
||
input := replace(input, match:"up to ", replace:"")
|
||
result := input
|
||
two_part := filter_text(input, match:"(twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)")
|
||
one_part := filter_text(input, match:"(zero|a|an|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen)\\b")
|
||
if two_part != "" and one_part != "" then
|
||
result := (digital_map[two_part] + digital_map[one_part]) or else input
|
||
else if two_part != "" then
|
||
result := digital_map[two_part] or else input
|
||
else if one_part != "" then
|
||
result := digital_map[input] or else input
|
||
result
|
||
}
|
||
reverse_elements := {for element from 1 to length(input) do input[length(input) - element] + " "}
|
||
######################## Level Margins
|
||
#### these will be determined by the style affecting the margins and otherwise be 0
|
||
margin_left := {0}
|
||
margin_right := {0}
|
||
margin_top := {0}
|
||
remove_margins := replace@(
|
||
match: "</?margin:[0-9]+(:+[0-9]+)?(:+[0-9]+)?>",
|
||
replace:""
|
||
)
|
||
##remove 0 margins and margins with no text
|
||
cull_margins := replace@(match:"</?margin:0(:+0)?(:+0)?>", replace:"")+
|
||
replace@(match:"<margin:[0-9]+:?[0-9]*:?[0-9]*></margin:[0-9]+:?[0-9]*:?[0-9]*>", replace:"")
|
||
|
||
#### this gives a big array so we can grab_margins["lv1"] etc anywhere
|
||
grab_margins := {[ lv1: [margin_left("lv1"), margin_right("lv1"), margin_top("lv1")],
|
||
lv2: [margin_left("lv2"), margin_right("lv2"), margin_top("lv2")],
|
||
lv3: [margin_left("lv3"), margin_right("lv3"), margin_top("lv3")],
|
||
lv4: [margin_left("lv4"), margin_right("lv4"), margin_top("lv4")],
|
||
lv5: [margin_left("lv5"), margin_right("lv5"), margin_top("lv5")],
|
||
lv6: [margin_left("lv6"), margin_right("lv6"), margin_top("lv6")],
|
||
lv7: [margin_left("lv7"), margin_right("lv7"), margin_top("lv7")],
|
||
lv8: [margin_left("lv8"), margin_right("lv8"), margin_top("lv8")],
|
||
text: [margin_left("text"), margin_right("text"), margin_top("text")],
|
||
text2: [margin_left("text2"), margin_right("text2"), margin_top("text2")],
|
||
text3: [margin_left("text3"), margin_right("text3"), margin_top("text3")],
|
||
text4: [margin_left("text4"), margin_right("text4"), margin_top("text4")],
|
||
text5: [margin_left("text5"), margin_right("text5"), margin_top("text5")],
|
||
text6: [margin_left("text6"), margin_right("text6"), margin_top("text6")],
|
||
unknown: [0,0,0]
|
||
]}
|
||
#### then with apply_margins(field, name:fieldname), add the margins into the text
|
||
apply_margins := {
|
||
margin_data := grab_margins()[name] or else [0,0,0]
|
||
cull_margins("<margin:" + margin_data[0] + ":" + margin_data[1] + ":" + margin_data[2] + ">" + remove_margins(input) + "</margin:" + margin_data[0] + ":" + margin_data[1] + ":" + margin_data[2] + ">")
|
||
}
|
||
is_modal := contains@(match:"<li>")
|
||
|
||
bump_text := {
|
||
blocks := split_text(input, match:"\n");
|
||
new_text := blocks[0];
|
||
for x from 1 to length(blocks)-1 do new_text := new_text + "\n" + bumper(blocks[x])
|
||
new_text
|
||
}
|
||
bumper := {
|
||
#if this text isn't modal, at a 5 px margin
|
||
if is_modal(input) then input else
|
||
cull_margins("<margin:0:0:5>" + remove_margins(input) + "</margin:0:0:5>")
|
||
|
||
}
|
||
inserts_values := {
|
||
split_text(set.inserts+";;;;;;;;;", match:";")
|
||
}
|
||
############################################################## The text box
|
||
# Filters for the text box
|
||
# context in which mana symbols are found
|
||
mana_context :=
|
||
"(?ix) # case insensitive, ignore whitespace
|
||
(^|[[:space:]\"(“']) # start of a word
|
||
(
|
||
<match>: # G: something
|
||
| <match>, # G, tap: something
|
||
| or[ ]<match> # Add X, Y, or Z.
|
||
| <match>[ ]to[ ]your # Add X, Y, or Z to your mana pool.
|
||
| <match>[ ]was[ ]spent # if G was spent to cast
|
||
| <match>[ ]can[ ]be[ ]paid
|
||
| (pays?|additional|costs?|the|adds?|pay(ed)?[ ](with|using)) # pay X. creatures cost 1 less. pay an additional G.
|
||
([ ]either)? # pay either X or Y
|
||
([ ](<sym[^>]*>)?[-+=]?[VLHSCETKQ\\?XYZIEWUBRG0-9/|]+(</sym[^>]*>)?,)* # pay X, Y or Z
|
||
([ ](<sym[^>]*>)?[-+=]?[VLHSCETKQ\\?XYZIEWUBRG0-9/|]+(</sym[^>]*>)?[ ](and|or|and/or))* # pay X or Y
|
||
[ ]<match>
|
||
([,.)\"”]|$ # (end of word)
|
||
|[ ][^ .,]*$ # still typing...
|
||
|[ ]( or | and | in | less | more | to ) # or next word is ...
|
||
)
|
||
)
|
||
| <param-mana><match></param-mana> # keyword argument that is declared as mana
|
||
| <param-cost>[ ]*<match></param-cost> # keyword argument that is declared as cost
|
||
| <param-cost><match>, # keyword argument that is declared as cost
|
||
";
|
||
mana_un_context := "(converted mana costs? <match>|<match> life)"
|
||
|
||
# truncates the name of legends
|
||
legend_filter := replace@(match:"(, | of | the | \"| “).*", replace: "" )
|
||
|
||
# does this frame support Alchemy Rebalanced name symbol?
|
||
alch_compatible := {false}
|
||
|
||
# these are considered a correct 'word' for spellchecking in the text box:
|
||
additional_text_words := match@(match:
|
||
"(?ix)^(?: # match whole word
|
||
<atom-[^>]*>.*?</atom-[^>]*> # cardnames and stuff
|
||
| [+-]?[0-9X]+ / [+-]?[0-9X]+ # '3/3', '+X/+X'
|
||
)$")
|
||
|
||
# the rule text filter
|
||
# - adds mana symbols
|
||
# - makes text in parentheses italic
|
||
equip_filter :=
|
||
replace@(match:"This creature", replace:"It")
|
||
+replace@(match:"this creature", replace:"it")
|
||
this_or_that := {
|
||
this := "this"
|
||
that := "that"
|
||
type := input
|
||
if input == "type" then type := to_lower(main_type(card.type))
|
||
else if is_creaturish(card.type) then type := "creature"
|
||
if type == "" then type := "permanent"
|
||
if upper then (
|
||
this := "This"
|
||
that := "That"
|
||
)
|
||
if(type == "land" and not is_land(card.type)) then type := "permanent"
|
||
this_that := this
|
||
if ((input == "creature" and not is_creaturish(card.type)) or is_spell(card.type))
|
||
then this_that := that
|
||
this_that + " " + type
|
||
}@(upper:false)
|
||
softline_ripper :=
|
||
replace@(match:"</?soft-line>", replace:"")
|
||
auto_correct :=
|
||
replace@(match:" it’s (controller|owner|power|toughness|converted|other)", replace:" its \\1")
|
||
+replace@(match:"Then, if" replace:"Then if")
|
||
+replace@(match:"([Ff]irst|[Dd]ouble) Strike" replace:"\\1 strike")
|
||
+replace@(match:"Splice (Ont|unt|int)" replace:"Splice ont")
|
||
+replace@(match:"(ecomes?) the Monarch" replace:"\\1 the monarch")
|
||
+replace@(match:"does (combat|[X0-9]+) damage" replace:"deals \\1 damage")
|
||
+replace@(
|
||
match: "(gains |gain |have |has )" # preceded by this
|
||
+ "(<kw-[^<]><nospellcheck>)" # inside a kw
|
||
+ "([A-Z])" # match this
|
||
replace: { _1 + _2 + to_lower(_3)})
|
||
auto_errata :=
|
||
replace@(match:"converted mana cost", replace:"mana value")
|
||
+replace@(match:"(?i)(Totem armor|Totembeistand|Armadura tótem|totémique|Armatura totem|Armadura de totem|族霊鎧|替身甲)", replace:{errata_map[_1] or else _1})
|
||
+replace@(match:"hen shuffle your library", replace:"hen shuffle")
|
||
+replace@(match:"this (?:ability )?(?:only )?(?:any ?time you could cast|as) a", in_context: "(Activate|Play) <match>n? (instant|sorcery)", replace:"only as a")
|
||
|
||
errata_map := [
|
||
"Totem armor": "Umbra armor",
|
||
"Totem Armor": "Umbra armor",
|
||
"totem armor": "umbra armor",
|
||
"Totembeistand": "Schattenbeistand",
|
||
"totembeistand": "schattenbeistand",
|
||
"Armadura tótem": "Armadura umbra",
|
||
"armadura tótem": "armadura umbra",
|
||
"Armure totémique": "Armure d’ombre",
|
||
"armure totémique": "armure d’ombre",
|
||
"Armatura totem": "Armatura essenza",
|
||
"armatura totem": "armatura essenza",
|
||
"族霊鎧": "陰影鎧",
|
||
"替身甲": "本影甲",
|
||
"Armadura de totem": "Armadura de sombra",
|
||
"armadura de totem": "armadura de sombra"
|
||
]
|
||
ex_test := {
|
||
expand_keywords(
|
||
input,
|
||
condition: {
|
||
correct_case or (mode != "pseudo" and not used_placeholders)
|
||
}
|
||
default_expand: {
|
||
chosen(choice:if correct_case or mode == "action" then mode else "lower case", set.automatic_reminder_text) and chosen(choice:mode, set.automatic_reminder_text)
|
||
},
|
||
combine: {
|
||
keyword := "<nospellcheck>{keyword}</nospellcheck>"
|
||
reminder := process_english_hints(if has_pt() then reminder else equip_filter(reminder))
|
||
if mode == "pseudo" then "<i-auto>{keyword}</i-auto>"
|
||
else keyword + if expand then "<atom-reminder-{mode}> ({reminder})</atom-reminder-{mode}>" else ""
|
||
|
||
},
|
||
margin_code: margin_code
|
||
)
|
||
}
|
||
text_filter :=
|
||
# step 1 : remove all automatic tags
|
||
remove_tag@(tag: "<sym-auto>") +
|
||
remove_tag@(tag: "<i-auto>") +
|
||
remove_tag@(tag: "<b-auto>") +
|
||
remove_tag@(tag: "<error-spelling") +
|
||
remove_tag@(tag: "<nospellcheck") +
|
||
remove_tag@(tag: "<li>") +
|
||
remove_tag@(tag: "<bullet>") +
|
||
remove_tag@(tag: "<align") +
|
||
remove_tag@(tag: "<margin") +
|
||
# step 1b : remove zero-width space used for level spacers
|
||
replace@(match:"", replace:"")+
|
||
# step 2a : temp fix for formatting buttons
|
||
replace@(
|
||
match:"<b></b>",
|
||
replace:"BOLDAROUND"
|
||
)+
|
||
replace@(
|
||
match:"<i></i>",
|
||
replace:"ITALAROUND"
|
||
)+
|
||
replace@(
|
||
match:"<sym></sym>",
|
||
replace:"SYMAROUND"
|
||
)+
|
||
# step 2 : reminder text for keywords
|
||
expand_keywords@(
|
||
condition: {
|
||
correct_case or (mode != "pseudo" and not used_placeholders)
|
||
}
|
||
default_expand: {
|
||
chosen(choice:if correct_case or mode == "action" then mode else "lower case", set.automatic_reminder_text) and chosen(choice:mode, set.automatic_reminder_text)
|
||
},
|
||
combine: {
|
||
keyword := "<nospellcheck>{keyword}</nospellcheck>"
|
||
reminder := process_english_hints(reminder)
|
||
if mode == "pseudo" then "<i-auto>{keyword}</i-auto>"
|
||
else keyword + if expand then "<atom-reminder-{mode}> ({reminder})</atom-reminder-{mode}>" else ""
|
||
}) +
|
||
# step 2ba : apply face_code
|
||
replace@(
|
||
match: "face_(.*?)_end",
|
||
replace: {face_code(_1)}
|
||
)+
|
||
# step 2b : move action keywords' reminder text to the end of the line
|
||
replace@(
|
||
match: "(<atom-reminder-[^>]+> (?:(?!</kw).*?)</atom-reminder-[^>]+></kw[^>]*>)([^\n]*)", #######removed "| ?<kw-" from lookahead
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 2c : when there's an action keyword and another one, then move that to the end of the line
|
||
replace@(
|
||
match: "(<atom-reminder-[^>]+> (?:(?!</kw)[^\n]*?)</atom-reminder-[^>]+></kw[^>]*>)([^\n]*?)(<atom-reminder-[^>]+> (?:(?!</kw).*?)</atom-reminder-[^>]+></kw[^>]*>)([^\n]*)",
|
||
replace: "\\2\\4\\3\\1"
|
||
) +
|
||
# step 2c : allow a sentence after lowercase reminder text for equips etc.
|
||
#replace@(
|
||
# match: "(<kw[^>]+><nospellcheck>[a-z][^<]+</nospellcheck>)(<atom-reminder-(?:expert|custom|old|core)>(?:(?!<kw-).)*</atom-reminder-(?:expert|custom|old|core)></kw[^>]*>)([^\n]+)$",
|
||
# replace: "\\1\\3\\2"
|
||
# ) +
|
||
# step 2d : remove duplicate reminder text
|
||
replace@(
|
||
match: "(<atom-reminder-[^>]*>[^)]+[)]</atom-reminder-[^>]*>)([^\n]+)\\1"
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 2e : combine reminder texts
|
||
replace@(
|
||
match: "[)](</atom-reminder-[^>]+></kw-[^>]><atom-reminder-[^>]+> )[(]"
|
||
replace: "\\1"
|
||
) +
|
||
# step 2f : temp fix for formatting buttons
|
||
replace@(
|
||
match:"BOLDAROUND",
|
||
replace:"<b></b>"
|
||
)+
|
||
replace@(
|
||
match:"ITALAROUND",
|
||
replace:"<i></i>"
|
||
)+
|
||
replace@(
|
||
match:"SYMAROUND",
|
||
replace:"<sym></sym>"
|
||
)+
|
||
replace@(
|
||
match:"-\n-"
|
||
replace:"<soft-line>\n</soft-line>"
|
||
)+
|
||
# step 3a : expand shortcut word CARDNAME
|
||
replace@(
|
||
match: "CARDNAME>?",
|
||
in_context: "(^|[[:space:]]|\\(|,|\\.|:|“|\"|'|‘|-|—|/|)<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-cardname></atom-cardname>"
|
||
) +
|
||
# step 3b : expand shortcut word LEGENDNAME
|
||
replace@(
|
||
match: "LEGENDNAME>?",
|
||
in_context: "(^|[[:space:]]|\\(|,|\\.|:|“|\"|'|‘|/|)<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-legname></atom-legname>"
|
||
) +
|
||
# step 3c : fill in atom fields
|
||
tag_contents@(
|
||
tag: "<atom-cardname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "CARDNAME" else strip_card_codes(card_name)) + "</nospellcheck>" }
|
||
) +
|
||
tag_contents@(
|
||
tag: "<atom-legname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "LEGENDNAME" else legend_filter(strip_card_codes(card_name))) + "</nospellcheck>" }
|
||
) +
|
||
replace@(
|
||
match: "INS([1-9])",
|
||
in_context: "(^|[[:space:]]|\\(|,|\\.|:|“|\"|'|‘|/|)<match>",
|
||
replace: "<atom-insert\\1></atom-insert\\1>"
|
||
) +
|
||
{
|
||
out := input
|
||
for x from 1 to 9 do
|
||
out := tag_contents(out,
|
||
tag: "<atom-insert"+x+">",
|
||
contents: { "<nospellcheck>" + (if inserts_values()[x-1] == "" then "INS"+x else inserts_values()[x-1]) + "</nospellcheck>" }
|
||
)
|
||
out
|
||
} +
|
||
# step 4 : explict non mana symbols
|
||
replace@(
|
||
match: "\\][-+=]?[VLHSCETKQ\\?XYZIWUBRG0-9/|]+\\[",
|
||
replace: {"<nosym>" + mana_filter_t() + "</nosym>"} ) +
|
||
# step 5 : add mana & tap symbols
|
||
replace@(
|
||
match: "([+=-][XYZ0-9/|]+)",
|
||
in_context: mana_context,
|
||
replace: {"<sym-auto>" + _1 + "</sym-auto>"} ) +
|
||
replace@(
|
||
match: "\\b[VLHSCETKQ\\?XYZIWUBRG0-9/|]+\\b",
|
||
in_context: mana_context,
|
||
replace: {"<sym-auto>" + mana_filter_t() + "</sym-auto>"} ) +
|
||
# step 5b : remove false positive mana & tap symbols
|
||
replace@(
|
||
match: "<sym-auto>([VLHSCETKQ\\?XYZIWUBRG0-9/|]+)</sym-auto>",
|
||
in_context: mana_un_context,
|
||
replace: "\\1" ) +
|
||
# step 5c : add explicit mana symbols
|
||
replace@(
|
||
match: "\\[[-+=]?[VLHSCETKQE\\?XYZIWUBRG0-9/|]+\\]",
|
||
replace: {"<sym>" + mana_filter_t() + "</sym>"} ) +
|
||
# step 6 : curly quotes
|
||
{if set.curly_quotes then curly_quotes(input) else input} +
|
||
# step 7 : italicize text in parenthesis
|
||
replace@(
|
||
match: "[(]([^)\n]|[(][^)\n]*[)])*[)]?",
|
||
in_context: "(^|[[:space:]])<match>|<atom-keyword><match></",
|
||
replace: "<i-auto>&</i-auto>") +
|
||
# step 7b : indent bullets
|
||
replace@(
|
||
match: "^(• )([^•]+)",
|
||
replace: {"<li><bullet>" + _1 + "</bullet>" + _2 + "</li>"}
|
||
)+
|
||
# step 7c : clean up modals
|
||
{
|
||
if is_modal(input)
|
||
then bump_text(softline_ripper(input))
|
||
else input
|
||
}+
|
||
# step 8 : automatic capitalization, but not after "("
|
||
replace@(
|
||
match: "([ ]*: |—| — )" # preceded by this
|
||
+ "([[:lower:]])" # match this
|
||
+ "(?![)])", # not followed by this
|
||
replace: { _1 + to_upper(_2) }) +
|
||
# step 9 : spellcheck
|
||
{
|
||
if set.auto_correct then
|
||
auto_correct(input)
|
||
else input } +
|
||
{
|
||
if set.auto_errata then
|
||
auto_errata(input)
|
||
else input } +
|
||
{
|
||
if language().code == "ja" or language().code == "zht" or language().code == "zhs" then input
|
||
else if set.mark_errors then
|
||
check_spelling(
|
||
language: language().spellcheck_code,
|
||
extra_dictionary: "/magic.mse-game/dictionary/magic-words",
|
||
extra_match: additional_text_words
|
||
)
|
||
else input
|
||
}
|
||
|
||
modal_lines := replace@(match:"</?soft-line>", replace:"")
|
||
+replace@(match:"(.+)", replace:"<soft-line>\\1</soft-line>")
|
||
|
||
modal_text_filter := text_filter + modal_lines
|
||
|
||
############################################################## Other boxes
|
||
|
||
# the flavor text filter
|
||
# - makes all text italic
|
||
flavor_text_filter :=
|
||
# step 1 : remove italic tags
|
||
remove_tag@(tag: "<i-flavor>") +
|
||
# step 2 : surround by <i> tags
|
||
{ "<i-flavor>" + input + "</i-flavor>" } +
|
||
# curly quotes
|
||
{if set.curly_quotes then curly_quotes(input) else input} +
|
||
# spellcheck
|
||
{ if set.mark_errors
|
||
then check_spelling(language:language().spellcheck_code)
|
||
else input
|
||
}
|
||
|
||
# Move the cursor past the separator in the p/t and type boxes
|
||
type_over_pt := replace@(match:"/$", replace:"")
|
||
type_over_type := replace@(match:" ?[-:]$", replace:"")
|
||
super_type_filter := {
|
||
input := remove_tag(tag: "<word-list-")
|
||
input := type_over_type()
|
||
tag := "word-list-type-" + lang_setting("code")
|
||
"<{tag}>{input}</{tag}>"
|
||
}
|
||
|
||
break_subtypes := split_text@(match: "<atom-sep>[^<]*</atom-sep>|</?word-list-[^>]*>", include_empty:false) # splitting at word-list tags is for backwards compatibility, when atom-sep was not yet inserted everywhere.
|
||
break_supertypes := split_text@(match: "<atom-sep>[^<]*</atom-sep>", include_empty:false)
|
||
sub_type_filter := {
|
||
input := remove_tag(tag: "<soft")
|
||
# What word list to use?
|
||
list_type_rest := if lang_setting("is_creature")(type) or lang_setting("is_kindred")(type) then "class-"+lang_setting("code")
|
||
else if lang_setting("is_land")(type) then "land"
|
||
else if lang_setting("is_artifact")(type) then "artifact"
|
||
else if lang_setting("is_enchantment")(type) then "enchantment"
|
||
else if lang_setting("is_spell")(type) then "spell"
|
||
else if lang_setting("is_planeswalker")(type) or lang_setting("is_emblem")(type) then "planeswalker"
|
||
else if lang_setting("is_plane")(type) then "plane-"+lang_setting("code")
|
||
else if lang_setting("is_battle")(type) then "battle"
|
||
else if lang_setting("is_dungeon")(type) then "dungeon"
|
||
else nil
|
||
if list_type_rest != nil then (
|
||
if lang_setting("is_creature")(type) or lang_setting("is_kindred")(type) then (
|
||
list_type_first := "race-"+lang_setting("code")
|
||
) else (
|
||
list_type_first := list_type_rest
|
||
);
|
||
# wrap wordlist tag around each part
|
||
parts := break_subtypes()
|
||
checked_first := false
|
||
(for each part in parts do
|
||
if trim(part) == "" then ""
|
||
else if not checked_first then
|
||
(checked_first := true; "<word-list-{list_type_first}>{part}</word-list-{list_type_first}>")
|
||
else
|
||
languages[lang_name()].subtype_separator + "<word-list-{list_type_rest}>{part}</word-list-{list_type_rest}>"
|
||
) +
|
||
(if length(parts) > 0 then
|
||
# Add a new box at the end
|
||
"<soft>{languages[lang_name()].subtype_separator}</soft><word-list-{list_type_rest}></word-list-{list_type_rest}>"
|
||
else
|
||
"<word-list-{list_type_first}></word-list-{list_type_first}>"
|
||
)
|
||
) else input # do nothing
|
||
}
|
||
|
||
# all sub types, for word list
|
||
space_to_comma := replace@(match:" ", replace:",")
|
||
only_first := replace@(match:" .*", replace:"")
|
||
only_next := replace@(match:"^[^ ]* ?", replace:"")
|
||
all_sub_types := {
|
||
for each card in set do
|
||
if lang_setting(setting)(card.super_type) then "," + space_to_comma(to_text(card.sub_type)) else ""
|
||
}
|
||
all_races := {
|
||
for each card in set do
|
||
if lang_setting("is_creature")(card.super_type) or lang_setting("is_kindred")(card.super_type) then
|
||
"," + only_first(to_text(card.sub_type))
|
||
else ""
|
||
}
|
||
all_classes := {
|
||
for each card in set do
|
||
if lang_setting("is_creature")(card.super_type) then
|
||
"," + space_to_comma(only_next(to_text(card.sub_type)))
|
||
else ""
|
||
}
|
||
|
||
# Determine a rarity code for M15 styles.
|
||
rarity_code := {
|
||
if not set.rarity_codes then ""
|
||
else if is_promo() then "P"
|
||
else if is_masterpiece() then "S"
|
||
else if contains(card.shape, match:"token") then "T"
|
||
else if contains(card.shape, match:"emblem") then "E"
|
||
else if card.rarity == "common" then "C"
|
||
else if card.rarity == "uncommon" then "U"
|
||
else if card.rarity == "rare" then "R"
|
||
else if card.rarity == "mythic rare" then "M"
|
||
else if card.rarity == "special" then "S"
|
||
else if card.rarity == "basic land" then "L"
|
||
else ""}
|
||
|
||
# Determine if the card is a promo card.
|
||
is_promo := { "false" }
|
||
|
||
# Determine if the card is a rare.
|
||
is_rare := { card.rarity == "rare" or card.rarity == "mythic rare" or card.rarity == "masterpiece" }
|
||
|
||
# Shape of cards, can be changed in style files
|
||
card_shape := { "normal" }
|
||
|
||
typesymbol_for :=
|
||
to_text +
|
||
replace@(match: "(Legendary|Basic|Snow|World| )", replace: "") +
|
||
{ if input == "Creature" then "creature"
|
||
else if input == "Sorcery" then "sorcery"
|
||
else if input == "Instant" then "instant"
|
||
else if input == "Artifact" then "artifact"
|
||
else if input == "Enchantment" then "enchantment"
|
||
else if input == "Land" then "land"
|
||
else if input == "Planeswalker" then "planeswalker"
|
||
else "multitype"
|
||
}
|
||
typesymbol_type := { typesymbol_for(type) }
|
||
|
||
#Script to make magic-mana-future compatible w/ other templates
|
||
colorless_color := {
|
||
if contains(card.card_color, match:"hybrid") or contains(card.card_color, match:"multicolor") then "c"
|
||
else if card.card_color=="white" then "w"
|
||
else if card.card_color=="blue" then "u"
|
||
else if card.card_color=="black" then "b"
|
||
else if card.card_color=="red" then "r"
|
||
else if card.card_color=="green" then "g"
|
||
else "c"
|
||
}
|
||
|
||
#Indicators never appear if the indicator would be colorless, colorless land, or colorless artifact.
|
||
#Indicators do appear if the chosen frame doesn't match the default.
|
||
#Indicators do appear if the chosen color for the indicator doesn't match the default.
|
||
|
||
has_identity := { ( ( card.card_color != card_color(casting_cost: card.casting_cost, rules_text: card.rule_text, type: card.super_type, watermark: card.watermark, card_name: card.name, default: "colorless") ) or ( card.indicator != card_color(casting_cost: card.casting_cost, rules_text: card.rule_text, type: card.super_type, watermark: card.watermark, card_name: card.name, default: "colorless") ) ) and card.indicator != "colorless" and card.indicator != "artifact" and card.indicator != "land"}
|
||
|
||
has_identity_2 := { ( ( card.card_color_2 != card_color(casting_cost: card.casting_cost_2, rules_text: card.rule_text_2, type: card.super_type_2, watermark: card.watermark_2, card_name: card.name_2, default: "colorless") ) or ( card.indicator_2 != card_color(casting_cost: card.casting_cost_2, rules_text: card.rule_text_2, type: card.super_type_2, watermark: card.watermark_2, card_name: card.name_2, default: "colorless") ) ) and card.indicator_2 != "colorless" and card.indicator_2 != "artifact" and card.indicator_2 != "land"}
|
||
|
||
############################################################## Statistics utilities
|
||
|
||
# Converted mana cost
|
||
is_half_mana := match@(match: "1/2|[|][WUBRGS]")
|
||
is_half_generic := match@(match: "1/2")
|
||
is_colored_mana := match@(match: "[WUBRG]")
|
||
only_numbers := filter_text@(match: "^[0123456789]+")
|
||
cmc_split := break_text@(match: "(?ix) 1/2 | [|][WUBRGC] | TK | [0-9](/[WUBRGCVLHSCETQ2]) | [0-9]+(?!/[WUBRGCVLHSCETQ2]) | [WUBRGCVLHS0-9](/[WUBRGCVLHS])\{0,4} ")
|
||
cmc := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_half_mana(sym) then 0.5
|
||
else if numbers != "" then to_int(numbers)
|
||
else 1 # all other symbols are 1
|
||
))
|
||
}
|
||
mana_value := cmc
|
||
write_wubrg := {
|
||
(if match(input, match:"white") then "W" else "")+
|
||
(if match(input, match:"blue") then "U" else "")+
|
||
(if match(input, match:"black") then "B" else "")+
|
||
(if match(input, match:"red") then "R" else "")+
|
||
(if match(input, match:"green") then "G" else "")
|
||
}
|
||
colored_mana := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_colored_mana(sym) then
|
||
if is_half_mana(sym) then 0.5 else 1
|
||
else 0
|
||
))
|
||
}
|
||
generic_mana := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_half_generic(sym) then 0.5
|
||
else if numbers != "" then to_int(numbers)
|
||
else 0 # all other symbols are 1
|
||
))
|
||
}
|
||
|
||
primary_card_color := {
|
||
artifact := chosen(choice:"artifact") and not (chosen(choice:"white") or chosen(choice:"blue") or chosen(choice:"black") or chosen(choice:"red") or chosen(choice:"green"))
|
||
land := chosen(choice:"land")
|
||
multi := chosen(choice:"multicolor")
|
||
hybrid := chosen(choice:"hybrid")
|
||
white := chosen(choice:"white")
|
||
blue := chosen(choice:"blue")
|
||
black := chosen(choice:"black")
|
||
red := chosen(choice:"red")
|
||
green := chosen(choice:"green")
|
||
multi_color := count_chosen(choices:"white, blue, black, red, green")
|
||
if land then "land"
|
||
else if multi then "multicolor"
|
||
else if multi_color == 2 and chosen(choice:"artifact") then "hybrid" ##hybrid artifacts would show as their first color
|
||
else if hybrid then "hybrid"
|
||
else if artifact then "artifact"
|
||
else if white then "white"
|
||
else if blue then "blue"
|
||
else if black then "black"
|
||
else if red then "red"
|
||
else if green then "green"
|
||
else input
|
||
}
|
||
mainframe_stat_color := {
|
||
artifact := chosen(choice:"artifact") and not (chosen(choice:"white") or chosen(choice:"blue") or chosen(choice:"black") or chosen(choice:"red") or chosen(choice:"green"))
|
||
land := chosen(choice:"land")
|
||
multi := chosen(choice:"multicolor")
|
||
hybrid := chosen(choice:"hybrid")
|
||
white := chosen(choice:"white")
|
||
blue := chosen(choice:"blue")
|
||
black := chosen(choice:"black")
|
||
red := chosen(choice:"red")
|
||
green := chosen(choice:"green")
|
||
pink := chosen(choice:"pink")
|
||
purple := chosen(choice:"purple")
|
||
if land then "land"
|
||
else if multi then "multicolor"
|
||
else if hybrid then "hybrid"
|
||
else if artifact then "artifact"
|
||
else if white then "white"
|
||
else if blue then "blue"
|
||
else if black then "black"
|
||
else if red then "red"
|
||
else if green then "green"
|
||
else if pink then "pink"
|
||
else if purple then "purple"
|
||
else input
|
||
}
|
||
is_mainframe := { false }
|
||
is_walker := { contains(card.super_type, match:"Planeswalker") }
|
||
is_legend := { true }
|
||
mainframe_walker := {false}
|
||
mainframe_walker_text_script := {combined_editor(field1: card.level_1_text, separator1: "<line>\n</line>", field2: card.level_2_text, separator2: "<line>\n</line>", field3: card.level_3_text)}
|
||
mainframe_walkerb := {false}
|
||
mainframe_walker_text_scriptb := {combined_editor(field1: card.level_5_text, separator1: "<line>\n</line>", field2: card.level_6_text, separator2: "<line>\n</line>", field3: card.level_7_text)}
|
||
alt_text := {false}
|
||
alt_text_script := {false}
|
||
alt_textb := {false}
|
||
alt_text_scriptb := {false}
|
||
|
||
mainframe_power := { card.power }
|
||
mainframe_toughness := { card.toughness }
|
||
|
||
word_count := break_text@(match:"[^[:space:]]+") + length
|
||
line_count := split_text@(match:"\n+",include_empty:false) + length
|
||
|
||
#Remove supertypes or types to look at parts of the super_type field by themselves.
|
||
remove_supertype := replace@(match: "(Legendary|Basic|Snow|World|Tribal|Token)", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "^<match>", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "<match>$", replace: "")
|
||
remove_type := replace@(match: "(Artifact|Creature|Enchantment|Instant|Land|Planeswalker|Sorcery)", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "^<match>", replace: "")+
|
||
replace@(match: "[ ]+", in_context: "<match>$", replace: "")
|
||
node_script := { if card.shape == "double faced" then "transform day" else "none" }
|
||
|
||
card_new_color := {
|
||
if card.card_color == "white" then "w"
|
||
else if card.card_color == "blue" then "u"
|
||
else if card.card_color == "black" then "b"
|
||
else if card.card_color == "red" then "r"
|
||
else if card.card_color == "green" then "g"
|
||
else if contains(card.card_color, match:"artifact") then "a"
|
||
else if contains(card.card_color, match:"multi") or contains(card.card_color, match:"hybrid") then "m"
|
||
else "c"
|
||
}
|
||
spark_color := {
|
||
if card.card_color == "white" then "w"
|
||
else if card.card_color == "blue" then "u"
|
||
else if card.card_color == "black" then "b"
|
||
else if card.card_color == "red" then "r"
|
||
else if card.card_color == "green" then "g"
|
||
else if contains(card.card_color, match:"multi") or contains(card.card_color, match:"hybrid") then "m"
|
||
else ""
|
||
}
|
||
|
||
ancestral_mana := { card.pt != "" and card.pt == "" }
|
||
is_unsorted := {"false"}
|
||
special_text := { "" }
|
||
special_text2 := { "" }
|
||
exporter_name_filter := filter_text@(match:"!exporte?r?name [^\n!(]+")
|
||
exporter_name_grabber := replace@(match:"!exporte?r?name ", replace:"")
|
||
clean_name := remove_tags +
|
||
replace@(match:"(\n| +$|^ +)", replace:"") +
|
||
replace@(match:"’", replace:"'")
|
||
|
||
card_name := {
|
||
test_name := exporter_name_grabber(exporter_name_filter(card.notes))
|
||
if test_name == "" then test_name := card.name
|
||
clean_name(test_name)
|
||
}
|
||
dfc_splitter_name := {
|
||
back_name := card.name_2
|
||
full_name := card_name()
|
||
if back_name != "" then full_name := full_name + "_" + clean_name(back_name)
|
||
full_name
|
||
}
|
||
exporter_num_filter := filter_text@(match:"!num [^\n!]+")
|
||
exporter_num_grabber := replace@(match:"!num ", replace:"")
|
||
trim_zeroes := replace@(match: "^00?", replace: "")+
|
||
replace@(match: "a?/[0-9b]+", replace: "")
|
||
corrected_card_number := { if exporter_num_grabber(exporter_num_filter(card.notes)) != "" then exporter_num_grabber(exporter_num_filter(card.notes)) else if card.custom_card_number != "" then trim_zeroes(card.custom_card_number) else card_number() }
|
||
|
||
comma_count := filter_text@(match:",")
|
||
round_up := {to_int(0.99999999999998+input)}
|
||
round_near := {to_int(0.5+input)}
|
||
to_title := replace@(match:"(^| )([A-z])([^ ]*)", replace:{_1+ to_upper(_2) + to_lower(_3)})
|
||
to_sentence := replace@(match:"(^|\n)([A-z])([^\n]*)", replace:{_1+ to_upper(_2) + to_lower(_3)})
|
||
join_arrays := {
|
||
a1 + for x from 0 to length(a2)-1 do [a2[x]]
|
||
}
|
||
join_list := {
|
||
string := ""
|
||
if length(input) == 2 then spacer := " "
|
||
if length(input) == 1 then closing := ""
|
||
for x from 0 to length(input)-1 do
|
||
string := string + (if x == length(input)-1 then closing else "") + input[x] + (if x == length(input)-1 then "" else spacer)
|
||
string
|
||
}@(spacer:", ", closing:"and ")
|
||
join := {
|
||
if i >= length(input) then ""
|
||
else if i == length(input)-1 then input[i]
|
||
else input[i]+sep+join(input, i: i+1, sep: sep)
|
||
}@(i: 0, sep:"")
|
||
|
||
# workaround cause position() is broken for text arrays
|
||
contains_element := {
|
||
if input == [] then false else length(filter_list(input, filter:{input == element})) > 0
|
||
}
|
||
ar_position := {
|
||
pos := -1
|
||
for x from 0 to length(in)-1 do (
|
||
if in[x] == of then pos := x;
|
||
)
|
||
pos
|
||
}
|
||
unique_elements := {
|
||
e1 := []
|
||
e2 := []
|
||
e1 := e1 + for x from 0 to length(of)-1 do if ar_position(of:of[x], in:from) == -1 then [of[x]]
|
||
}
|
||
includes := {ar_position(of:input in:array) != -1}
|
||
|
||
pull_comma_array := {
|
||
array := split_text(input, match:divider)
|
||
length := length(comma_count(input))
|
||
ending := to_number(end)
|
||
if (cell >= (length + (1-ending)))
|
||
then default
|
||
else if array[cell] == "" or array[cell] == nil or array[cell] == "-"
|
||
then default
|
||
else array[cell]
|
||
}@(default:0, end: 1, divider:",", cell:0)
|
||
##todo check nil
|
||
#### standard is pull_comma_array("X,Y,Z,", cell: 0)
|
||
#### returns "X"
|
||
#### ending true for coordinates (requires a final divider to ensure element is complete)
|
||
#### ending false for moving (doesn't require divider, moving 1 then 11 is fine)
|
||
#### divider is "," by default, can change
|
||
#### can also add default to return in case of errors
|
||
|
||
##a workaround for the crop offset function that doesn't appear to work
|
||
##slice_chop(input:image, height:(final height), width:(final width), distance:(length from bottom to top of final image))
|
||
slice_crop := {
|
||
img := flip_vertical(input)
|
||
img := crop(img, height:distance, width:width, offset_x:0, offset_y:0)
|
||
img := flip_vertical(img)
|
||
img
|
||
if(height != 0 and height != distance) then
|
||
img := crop(img, height:height, width:width, offset_x:0, offset_y:0)
|
||
img
|
||
}@(height:0)
|
||
|
||
#juryrig fix for level defaults. janky because MSE hates {true}
|
||
transfer_levels := {true}
|
||
transfer_levels_2 := {true}
|
||
a_saga := {false}
|
||
saga_reminder := { "As this Saga enters and after your draw step, add a lore counter. Sacrifice after III." }
|
||
b_saga := {false}
|
||
saga_reminderb := { "As this Saga enters and after your draw step, add a lore counter. Sacrifice after III." }
|
||
############################################################## Watermark Updates
|
||
card_spotlight := { "/magic-mainframe-watermarks.mse-include/spotlight/" + card_new_color() + "spotlight.png" }
|
||
custom_watermark_1 := { if set.custom_watermark_1 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_1 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_2 := { if set.custom_watermark_2 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_2 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_3 := { if set.custom_watermark_3 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_3 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_4 := { if set.custom_watermark_4 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_4 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_5 := { if set.custom_watermark_5 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_5 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_6 := { if set.custom_watermark_6 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_6 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_7 := { if set.custom_watermark_7 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_7 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_8 := { if set.custom_watermark_8 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_8 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_9 := { if set.custom_watermark_9 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_9 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_10 := { if set.custom_watermark_10 != "" then "/magic-watermarks.mse-include/" + set.custom_watermark_10 else "/magic-watermarks.mse-include/planeswalker.png" }
|
||
custom_watermark_a := {"/magic-watermarks.mse-include/planeswalker.png"}
|
||
custom_watermark_b := {"/magic-watermarks.mse-include/planeswalker.png"}
|
||
############################################################## Flavor Bar Equation
|
||
|
||
|
||
chop_top := {0}
|
||
chop_bot := {0}
|
||
bar_offset := {0}
|
||
offset_lines := {0}
|
||
chop_top2 := {0}
|
||
chop_bot2 := {0}
|
||
bar_offset2 := {0}
|
||
offset_lines2 := {0}
|
||
|
||
##### Set chop_top(), chop_bot(), bar_offset(), and offset_lines to 0 to reduce replacements in chopping frames
|
||
##### Full equations to use in chopping templates below
|
||
##### chop_top := {if styling.chop_top == "" then 0 else if comma_count(styling.chop_top) == "," or comma_count(styling.chop_top) == ",," then split_text(match:",", styling.chop_top).0 else styling.chop_top}
|
||
##### chop_bot := {if comma_count(styling.chop_top) == ",," then split_text(match:",", styling.chop_top).1 else if styling.chop_bottom == "" then 0 else styling.chop_bottom}
|
||
##### bar_offset := {if styling.flavor_bar_offset == "-" or styling.flavor_bar_offset == "+" then 0 else to_number(styling.flavor_bar_offset)}
|
||
##### offset_lines := {offset_counter(styling.flavor_bar_offset)}
|
||
|
||
top_of_textbox := {card_style.text.top }
|
||
bottom_of_textbox := {card_style.text.bottom }
|
||
top_of_textbox2 := {card_style.text_2.top }
|
||
bottom_of_textbox2 := {card_style.text_2.bottom }
|
||
offset_counter := {length(filter_text(input, match:"u")) - length(filter_text(input, match:"d"))}
|
||
paragraph_count := filter_text@(match:"\n")
|
||
hard_paragraph_count :=
|
||
replace@(match:"<soft-line>\n", replace:"")+ #count hard breaks for their extra space
|
||
filter_text@(match:"\n")
|
||
soft_break_filter :=
|
||
filter_text @(match:"<", in_context: "<match>soft-line>") #count soft breaks for quotes
|
||
word_split := split_text@(match:" ") #split words to better calculate line lengths
|
||
small_filter := filter_text@(match:"[\\.,\\?!il’]") #grab the tiny characters
|
||
fb_length := {length(input) - 0.3 * length(small_filter(input))}#reduce the effect of tiny characters
|
||
calc_lines := { sum := 0 #estimate lines by character limit
|
||
lines := 1 #minimum of 1
|
||
for e from 0 to length(input)-1 do (
|
||
sum := sum + fb_length(input[e]);
|
||
if sum > char then ( #if new word is over the limit
|
||
lines := lines + 1; #add new line
|
||
sum := fb_length(input[e])) #reset the sum
|
||
else
|
||
sum := sum + 1; #else add it and a space to the sum
|
||
)
|
||
lines #return number of lines
|
||
}
|
||
lines_of_text := { #estimate lines in break blocks
|
||
lines := 0 #further improves the previous eq
|
||
for x from 0 to length(input)-1 do
|
||
if input[x] or else "" != "" then #if the break isn't empty, check it
|
||
lines := lines + calc_lines(word_split(input[x]), char:char)
|
||
lines
|
||
}
|
||
flavor_text := {split_text(match:"\n", remove_tags(card.flavor_text+"\n"))} #remove tags, add \n so .1 doesn't explode
|
||
hard_flavor_break := { if not contains(card.flavor_text, match:"\n") then 0 else if contains(card.flavor_text, match:"<soft-line>\n") then 0 else if lines_of_rules() >= 3 then -3 else -2}
|
||
font_size := {min(14,round_near(card_style.text.content_height / card_style.text.content_lines) - 8)} #approximate font size
|
||
adj_char_width := {7.35 * min(14, font_size()+0.95) / 14} #average char width, adjusted for font size
|
||
char_per_line := {min(52,round_up(card_style.text.content_width / adj_char_width())+1.5)} #approximate character limit. very rarely over 52 but standard eq can reach 60+
|
||
lines_of_flavor := {lines_of_text(flavor_text(), char:char_per_line())}
|
||
lines_of_rules := { card_style.text.content_lines - lines_of_flavor() } #rules of lines for ratio weirdness
|
||
line_height := {(card_style.text.content_height / card_style.text.content_lines)}
|
||
padding_height := { 0.5*(bottom_of_textbox() - top_of_textbox() - card_style.text.content_height) } #space between top of textbox and text
|
||
linebreak_height := { 2*length(hard_paragraph_count(card.rule_text)) }
|
||
###correction for ratio of rules/flavor causing weirdness
|
||
uneven_correction := { if lines_of_flavor() == 1 then max(4, (card_style.text.content_lines - (2*lines_of_flavor()))) else (card_style.text.content_lines - (2*lines_of_flavor())) }
|
||
###add it all up
|
||
###old_bar_equation is compatibilty for 2.0.0
|
||
old_bar_equation := { top_of_textbox() + padding_height() + card_style.text.content_height - line_height()*(lines_of_flavor() + offset_lines()) + linebreak_height() - uneven_correction() + front_corr() + bar_offset() + hard_flavor_break() +1 }
|
||
bar_equation := {if card_style.text.layout.blocks[1].bottom or else 0 > 0 then card_style.text.top + 0.5*(card_style.text.layout.blocks[0].bottom+card_style.text.layout.blocks[1].top) else old_bar_equation()}
|
||
|
||
flavor_text2 := {split_text(match:"\n", remove_tags(card.flavor_text_2+"\n"))} #remove tags, add \n so .1 doesn't explode
|
||
hard_flavor_break2 := { if not contains(card.flavor_text_2, match:"\n") then 0 else if contains(card.flavor_text_2, match:"<soft-line>\n") then 0 else if lines_of_rules2() >= 3 then -3 else -2}
|
||
font_size2 := {min(14,round_near(card_style.text_2.content_height / card_style.text_2.content_lines) - 8)} #approximate font size
|
||
adj_char_width2 := {7.35 * min(14, font_size2()+0.95) / 14} #average char width, adjusted for font size
|
||
char_per_line2 := {min(52,round_up(card_style.text_2.content_width / adj_char_width2())+1.5)} #approximate character limit. very rarely over 52 but standard eq can reach 60+
|
||
lines_of_flavor2 := {lines_of_text(flavor_text2(), char:char_per_line2())}
|
||
lines_of_rules2 := { card_style.text_2.content_lines - lines_of_flavor2() } #rules of lines for ratio weirdness
|
||
line_height2 := {(card_style.text_2.content_height / card_style.text_2.content_lines)}
|
||
padding_height2 := { 0.5*(bottom_of_textbox2() - top_of_textbox2() - card_style.text_2.content_height) } #space between top of textbox and text
|
||
linebreak_height2 := { 2*length(hard_paragraph_count(card.rule_text_2)) }
|
||
###correction for ratio of rules/flavor causing weirdness
|
||
uneven_correction2 := { if lines_of_flavor2() == 1 then max(4, (card_style.text_2.content_lines - (2*lines_of_flavor2()))) else (card_style.text_2.content_lines - (2*lines_of_flavor2())) }
|
||
###add it all up
|
||
old_bar_equation2 := { top_of_textbox2() + padding_height2() + card_style.text_2.content_height - line_height2()*(lines_of_flavor2() + offset_lines2()) + linebreak_height2() - uneven_correction2() + back_corr() + bar_offset2() + hard_flavor_break2() +1 }
|
||
bar_equation2 := {if card_style.text_2.layout.blocks[0].bottom or else 0 > 0 then card_style.text_2.top + 0.5*(card_style.text_2.layout.blocks[0].bottom+card_style.text_2.layout.blocks[1].top) else old_bar_equation2()}
|
||
|
||
##### long correction coefficient based off several sets of data
|
||
front_corr := {correction_coeff(lof:lines_of_flavor(), lor:lines_of_rules(), lbh:linebreak_height())}
|
||
back_corr := {correction_coeff(lof:lines_of_flavor2(), lor:lines_of_rules2(), lbh:linebreak_height2())}
|
||
correction_coeff := {
|
||
(if lor == 1 then
|
||
(if lof == 1 then 3
|
||
else if lof == 2 then 1
|
||
else if lof == 3 then 1.5
|
||
else if lof == 4 then 0
|
||
else 5 - lof)
|
||
else if lor == 2 and lbh == 2 then
|
||
(if lof == 1 then 1
|
||
else if lof == 2 then 1
|
||
else if lof == 3 then 2
|
||
else if lof == 4 then 2
|
||
else 3)
|
||
else if lor == 2 then
|
||
(if lof == 1 then 1
|
||
else if lof == 2 then 0
|
||
else if lof == 3 then 0
|
||
else if lof == 4 then 0
|
||
else -1)
|
||
else if lor == 3 and lbh == 2 then
|
||
(if lof == 1 then 0
|
||
else if lof == 2 then 0
|
||
else if lof == 3 then 1
|
||
else if lof == 4 then 1
|
||
else 2)
|
||
else if lor == 3 then
|
||
(if lof == 1 then 0
|
||
else if lof == 2 then -1
|
||
else if lof == 3 then -0.5
|
||
else if lof == 4 then -1
|
||
else 0)
|
||
else if lor == 4 and lbh == 2 then
|
||
(-2 + lof)
|
||
else if lor == 4 then
|
||
(if lof == 1 then -1
|
||
else if lof == 2 then 0
|
||
else if lof == 3 then -0.5
|
||
else -1)
|
||
else if lor == 5 and lbh == 4 then
|
||
(-5 + lof)
|
||
else if lor == 5 and lbh == 2 then
|
||
(-2 + lof)
|
||
else if lor == 5 then
|
||
(2 - lof)
|
||
else if lor == 6 and lbh == 2 then
|
||
(-1 - lof)
|
||
else if lor == 6 then
|
||
(2 - lof)
|
||
else 0) + (if lbh >= 4 then 0.5*lbh-1)
|
||
}
|
||
######################## Modal DFC hints
|
||
auto_flags := {true}
|
||
front_modal_hint := {
|
||
if not auto_flags() then ["", "", 10.5]
|
||
else if remove_tags(card.sub_type_2) != "" then [card.sub_type_2, "<sym>"+card.casting_cost_2+"</sym>", 10.5]
|
||
else if card.casting_cost_2 != "" then [main_type(card.super_type_2), "<sym>"+card.casting_cost_2+"</sym>", 10.5]
|
||
else [main_type(card.super_type_2), mana_ability(card.rule_text_2), 10.5]
|
||
}
|
||
back_modal_hint := {
|
||
if not auto_flags() then ["", "", 10.5]
|
||
else if remove_tags(card.sub_type) != "" then [card.sub_type, "<sym>"+card.casting_cost+"</sym>", 10.5]
|
||
else if card.casting_cost != "" then [main_type(card.super_type), "<sym>"+card.casting_cost+"</sym>", 10.5]
|
||
else [main_type(card.super_type), mana_ability(card.rule_text), 10.5]
|
||
}
|
||
mana_ability := {
|
||
abils := break_text(input, match:"(</?sym(-auto)?>)?T(</?sym(-auto)?>)?: Add (</?sym(-auto)?>)?(W|U|B|R|G|C)(</?sym(-auto)?>)?(, | or )?(</?sym(-auto)?>)?(W|U|B|R|G|C)?(</?sym(-auto)?>)?(, or )?(</?sym(-auto)?>)?(W|U|B|R|G|C)?(</?sym(-auto)?>)?.")
|
||
abils[0] or else ""
|
||
}
|
||
main_type := {
|
||
types := main_types(input)
|
||
if length(types) == 0 then ""
|
||
else if includes("Creature", array:types)
|
||
then "Creature"
|
||
else if includes("Land", array:types)
|
||
then "Land"
|
||
else types[0]
|
||
}
|
||
main_types := {
|
||
types := break_text(input, match:"(Land|Instant|Sorcery|Artifact|Enchantment|Creature|Planeswalker)")
|
||
types or else [""]
|
||
}
|
||
######################## Mainframe mana
|
||
use_v_mana := {contains(set.custom_mana_symbol_name, match:".png")}
|
||
use_large_v_mana := { use_v_mana() and chosen(set.mana_symbol_options, choice:"enable in casting costs")}
|
||
use_small_v_mana := { use_v_mana() and chosen(set.mana_symbol_options, choice:"enable in text boxes")}
|
||
use_color_v_mana := { use_v_mana() and chosen(set.mana_symbol_options, choice:"colored mana symbols") and not use_hybrid_v_mana()}
|
||
use_hybrid_v_mana := { use_v_mana() and chosen(set.mana_symbol_options, choice:"hybrid with colors")}
|
||
v_mana_name := {if not use_v_mana() then "" else replace(set.custom_mana_symbol_name, match:"(.+/|\\.png)", replace:"")}
|
||
v_mana_loc := {if not use_v_mana() then "" else replace(set.custom_mana_symbol_name, match:"{v_mana_name()}\\.png", replace:"")}
|
||
v_mana_num := {max(to_number(set.number_hybrid_variants),0) or else -1}
|
||
|
||
ub_stamp := { card.card_stamp == "universes beyond" }
|
||
use_custom_stamp := {contains(set.custom_stamp_name, match:".png")}
|
||
c_stamp_name := {
|
||
if not use_custom_stamp() then ""
|
||
else if card.stamp == "custom" then set.custom_stamp_name
|
||
else if card.stamp == "custom color" then replace(set.custom_stamp_name, match:"(.+/|\\.png)", replace:"")
|
||
else ""
|
||
}
|
||
c_stamp_loc := {
|
||
if card.stamp != "custom color" or not use_custom_stamp() then ""
|
||
else replace(set.custom_stamp_name, match:"{c_stamp_name()}\\.png", replace:"")
|
||
}
|
||
|
||
searchPull := filter_text@(match:"search(name|mana|type|rules|flavor|text|notes)")
|
||
searchSnip := replace@(match:"search(name|mana|type|rules|flavor|text|notes)_", replace:"")
|
||
|
||
custom_index := {
|
||
sortIndex := split_text(set.custom_index, match:",")
|
||
for each field in sortIndex do
|
||
applyIndex(to_lower(field))
|
||
or else (
|
||
searchIndex(to_lower(searchPull(field)), query:searchSnip(field))
|
||
)
|
||
or else ""
|
||
}
|
||
applyIndex := {
|
||
[
|
||
name: {
|
||
fill_len(to_string(position (
|
||
of: card
|
||
in: set
|
||
order_by: { sort_name(card.name) + sort_name(export_name())}
|
||
filter: set_filter()
|
||
)), lead:"0", fill_to:3)
|
||
},
|
||
alias: {
|
||
fill_len(to_string(position (
|
||
of: card
|
||
in: set
|
||
order_by: { sort_name(card.alias) + sort_name(export_name())}
|
||
filter: set_filter()
|
||
)), lead:"0", fill_to:3)
|
||
}
|
||
name2: {
|
||
fill_len(to_string(position (
|
||
of: card
|
||
in: set
|
||
order_by: { sort_name(card.name_2) + sort_name(export_name())}
|
||
filter: set_filter()
|
||
)), lead:"0", fill_to:3)
|
||
},
|
||
alias2: {
|
||
fill_len(to_string(position (
|
||
of: card
|
||
in: set
|
||
order_by: { sort_name(card.alias_2) + sort_name(export_name())}
|
||
filter: set_filter()
|
||
)), lead:"0", fill_to:3)
|
||
}
|
||
color: {fill_len(color_of_card(), lead:"A")},
|
||
artist: {fill_len(substring(card.illustrator, end:7), follow:" ", fill_to:7)},
|
||
artist2: {fill_len(substring(card.illustrator_2, end:7), follow:" ", fill_to:7)},
|
||
design: {fill_len(substring(card.card_code_text, end:7), follow:" ", fill_to:7)},
|
||
mv: {fill_len(to_string(cmc(card.casting_cost)), lead:"0")},
|
||
"mana value": {fill_len(to_string(cmc(card.casting_cost)), lead:"0")},
|
||
cmc: {fill_len(to_string(cmc(card.casting_cost)), lead:"0")},
|
||
"converted mana cost": {fill_len(to_string(cmc(card.casting_cost)), lead:"0")},
|
||
rarity: {index_of_rarity()},
|
||
power: {fill_len(card.power, lead:"0")},
|
||
toughness: {fill_len(card.toughness, lead:"0")},
|
||
pt: {fill_len(card.power, lead:"0") + fill_len(card.toughness, lead:"0")},
|
||
loyalty: {fill_len(card.loyalty, lead:"0")},
|
||
type: {fill_len(filter_text(match:"[A-Z][A-Z]?[A-Z]?", filter_text(match:"[A-Z]", card.super_type)), follow:"0", fill_to:3)},
|
||
hasrules: {if remove_tags(card.rule_text) != "" then "A" else "B"},
|
||
hasflavor: {if remove_tags(card.flavor_text) != "" then "A" else "B"},
|
||
hasrules2: {if remove_tags(card.rule_text_2) != "" then "A" else "B"},
|
||
hasflavor2: {if remove_tags(card.flavor_text_2) != "" then "A" else "B"},
|
||
][input]()
|
||
}
|
||
searchIndex := {
|
||
[
|
||
searchname: { if contains(card.name, match:query) or contains(card.name_2, match:query) then "A" else "B"},
|
||
searchmana: { if contains(card.casting_cost, match:query) or contains(card.casting_cost_2, match:query) then "A" else "B"},
|
||
searchtype: { if contains(card.type, match:query) or contains(card.type_2, match:query) then "A" else "B"},
|
||
searchrules: { if contains(card.rule_text, match:query) or contains(card.rule_text_2, match:query) then "A" else "B"},
|
||
searchflavor: { if contains(card.flavor_text, match:query) or contains(card.flavor_text_2, match:query) then "A" else "B"},
|
||
searchartist: { if contains(card.illustrator, match:query) or contains(card.illustrator_2, match:query) then "A" else "B"},
|
||
searchdesign: { if contains(card.card_code_text, match:query) then "A" else "B"},
|
||
searchtext: { if contains(card.text, match:query) or contains(card.text_2, match:query) then "A" else "B"},
|
||
searchnotes: { if contains(card.notes, match:query) then "A" else "B"},
|
||
unsearchname: { if contains(card.name, match:query) or contains(card.name_2, match:query) then "B" else "A"},
|
||
unsearchmana: { if contains(card.casting_cost, match:query) or contains(card.casting_cost_2, match:query) then "B" else "A"},
|
||
unsearchtype: { if contains(card.type, match:query) or contains(card.type_2, match:query) then "B" else "A"},
|
||
unsearchrules: { if contains(card.rule_text, match:query) or contains(card.rule_text_2, match:query) then "B" else "A"},
|
||
unsearchflavor: { if contains(card.flavor_text, match:query) or contains(card.flavor_text_2, match:query) then "B" else "A"},
|
||
unsearchartist: { if contains(card.illustrator, match:query) or contains(card.illustrator_2, match:query) then "B" else "A"},
|
||
unsearchdesign: { if contains(card.card_code_text, match:query) then "B" else "A"},
|
||
unsearchtext: { if contains(card.text, match:query) or contains(card.text_2, match:query) then "B" else "A"},
|
||
unsearchnotes: { if contains(card.notes, match:query) then "B" else "A"}
|
||
][input]()
|
||
}
|
||
index_of_rarity := {
|
||
if card.rarity == "basic land" then "A"
|
||
else if card.rarity == "common" then "C"
|
||
else if card.rarity == "uncommon" then "D"
|
||
else if card.rarity == "rare" then "E"
|
||
else if card.rarity == "mythic rare" then "F"
|
||
else if card.rarity == "special" then "G"
|
||
else "J"
|
||
}
|
||
fill_len := {
|
||
output := to_string(input)
|
||
if output == "" then output := "0"
|
||
fill := max(0,fill_to - length(output))
|
||
for x from 1 to fill do output := lead + output + follow;
|
||
output
|
||
}@(fill_to:2, lead:"", follow:"")
|
||
|
||
skeleton_commons := 19
|
||
skeleton_uncommons := 11
|
||
skeleton_rares := 7
|
||
skeleton_mythics := 2
|
||
skeleton_land_commons := 1
|
||
skeleton_land_uncommons := 5
|
||
skeleton_land_rares := 0
|
||
skeleton_gold_commons := 0
|
||
skeleton_gold_uncommons := 1
|
||
skeleton_gold_rares := 1
|
||
skeleton_shard_commons := 0
|
||
skeleton_shard_uncommons := 0
|
||
skeleton_shard_rares := 0
|
||
skeleton_wedge_commons := 0
|
||
skeleton_wedge_uncommons := 0
|
||
skeleton_wedge_rares := 0
|
||
skeleton_artifact_commons := 5
|
||
skeleton_artifact_uncommons := 5
|
||
skeleton_artifact_rares := 0
|
||
skeleton_blank_commons := 0
|
||
skeleton_blank_uncommons := 5
|
||
skeleton_blank_rares := 8
|
||
skeleton_blank_mythics := 5
|
||
#### generates a set of CC00 Skeleton cards for each color
|
||
#### by insertnamehere and cajun
|
||
skeleton_runner := {
|
||
cards:=[]
|
||
for x from 0 to length(letter_list)-1 do
|
||
(
|
||
for y from 1 to count do
|
||
if mana_list == "nope" then
|
||
(cards := cards + [new_card([name:prefix+letter_list[x]+fill_len(y, lead:"0"), rarity:rarity, card_color:color_list[x], super_type:super_type])];)
|
||
else
|
||
(cards := cards + [new_card([name:prefix+letter_list[x]+fill_len(y, lead:"0"), rarity:rarity, super_type:super_type, casting_cost:mana_list[x]])];)
|
||
)
|
||
cards
|
||
}@(count:1, rarity:"common", type:"", prefix:"C", super_type:"", color_list:["white", "blue", "black", "red", "green"], letter_list:["W", "U", "B", "R", "G"], mana_list:"nope")
|
||
###outside to make singleton scripts easier
|
||
blank_list_5 := ["","","","",""]
|
||
blank_list_10 := ["","","","","","","","","",""]
|
||
mana_list_ally := ["WU","UB","BR","RG","GW"]
|
||
mana_list_enemy := ["WB","UR","BG","RW","GU"]
|
||
mana_list_shard := ["WUB","UBR","BRG","RGW","GWU"]
|
||
mana_list_wedge := ["WBG","URW","BGU","RWB","GUR"]
|
||
skeleton_script := {
|
||
cards := [];
|
||
cards := cards + skeleton_runner(count:skeleton_commons);
|
||
cards := cards + skeleton_runner(count:skeleton_uncommons, prefix:"U", rarity:"uncommon");
|
||
cards := cards + skeleton_runner(count:skeleton_rares, prefix:"R", rarity:"rare");
|
||
cards := cards + skeleton_runner(count:skeleton_mythics, prefix:"M", rarity:"mythic rare");
|
||
cards := cards + skeleton_runner(count:skeleton_gold_commons, prefix:"CM", rarity:"common", letter_list:blank_list_10, mana_list:mana_list_ally+mana_list_enemy);
|
||
cards := cards + skeleton_runner(count:skeleton_gold_uncommons, prefix:"UM", rarity:"uncommon", letter_list:blank_list_10, mana_list:mana_list_ally+mana_list_enemy);
|
||
cards := cards + skeleton_runner(count:skeleton_gold_rares, prefix:"RM", rarity:"rare", letter_list:blank_list_10, mana_list:mana_list_ally+mana_list_enemy);
|
||
cards := cards + skeleton_runner(count:skeleton_shard_commons, prefix:"CM", rarity:"common", letter_list:blank_list_5, mana_list:mana_list_shard);
|
||
cards := cards + skeleton_runner(count:skeleton_shard_uncommons, prefix:"UM", rarity:"uncommon", letter_list:blank_list_5, mana_list:mana_list_shard);
|
||
cards := cards + skeleton_runner(count:skeleton_shard_rares, prefix:"RM", rarity:"rare", letter_list:blank_list_5, mana_list:mana_list_shard);
|
||
cards := cards + skeleton_runner(count:skeleton_wedge_commons, prefix:"CM", rarity:"common", letter_list:blank_list_5, mana_list:mana_list_wedge);
|
||
cards := cards + skeleton_runner(count:skeleton_wedge_uncommons, prefix:"UM", rarity:"uncommon", letter_list:blank_list_5, mana_list:mana_list_wedge);
|
||
cards := cards + skeleton_runner(count:skeleton_wedge_rares, prefix:"RM", rarity:"rare", letter_list:blank_list_5, mana_list:mana_list_wedge);
|
||
for i from 1 to skeleton_artifact_commons do cards := cards + [new_card([name:"CA"+fill_len(i, lead:"0"), rarity:"common", super_type:"Artifact"])];
|
||
for i from 1 to skeleton_artifact_uncommons do cards := cards + [new_card([name:"UA"+fill_len(i, lead:"0"), rarity:"uncommon", super_type:"Artifact"])];
|
||
for i from 1 to skeleton_artifact_rares do cards := cards + [new_card([name:"RA"+fill_len(i, lead:"0"), rarity:"rare", super_type:"Artifact"])];
|
||
for i from 1 to skeleton_land_commons do cards := cards + [new_card([name:"CL"+fill_len(i, lead:"0"), super_type:"Land", rarity:"common"])];
|
||
for i from 1 to skeleton_land_uncommons do cards := cards + [new_card([name:"UL"+fill_len(i, lead:"0"), super_type:"Land", rarity:"uncommon"])];
|
||
for i from 1 to skeleton_land_rares do cards := cards + [new_card([name:"RL"+fill_len(i, lead:"0"), super_type:"Land", rarity:"rare"])];
|
||
for i from 1 to skeleton_blank_commons do cards := cards + [new_card([name:"CX"+fill_len(i, lead:"0"), rarity:"common"])];
|
||
for i from 1 to skeleton_blank_uncommons do cards := cards + [new_card([name:"UX"+fill_len(i, lead:"0"), rarity:"uncommon"])];
|
||
for i from 1 to skeleton_blank_rares do cards := cards + [new_card([name:"RX"+fill_len(i, lead:"0"), rarity:"rare"])];
|
||
for i from 1 to skeleton_blank_mythics do cards := cards + [new_card([name:"MX"+fill_len(i, lead:"0"), rarity:"mythic rare"])];
|
||
cards
|
||
}
|
||
skeleton_info := {
|
||
trace("Set Skeleton Generator Help:"
|
||
+"\nSet variables here to modify the Skeleton Add Cards script, for example 'skeleton_commons := 10'"
|
||
+"\nCurrent variables:\n"
|
||
+"skeleton_commons: " + skeleton_commons + " (of each color)\n"
|
||
+"skeleton_uncommons: " + skeleton_uncommons + " (of each color)\n"
|
||
+"skeleton_rares: " + skeleton_rares + " (of each color)\n"
|
||
+"skeleton_mythics: " + skeleton_mythics + " (of each color)\n"
|
||
+"skeleton_gold_commons: " + skeleton_gold_commons + " (of each color pair)\n"
|
||
+"skeleton_gold_uncommons: " + skeleton_gold_uncommons + " (of each color pair)\n"
|
||
+"skeleton_gold_rares: " + skeleton_gold_rares + " (of each color pair)\n"
|
||
+"skeleton_artifact_commons: " + skeleton_artifact_commons + "\n"
|
||
+"skeleton_artifact_uncommons: " + skeleton_artifact_uncommons + "\n"
|
||
+"skeleton_artifact_rares: " + skeleton_artifact_rares + "\n"
|
||
+"skeleton_land_commons: " + skeleton_land_commons + "\n"
|
||
+"skeleton_land_uncommons: " + skeleton_land_uncommons + "\n"
|
||
+"skeleton_land_rares: " + skeleton_land_rares + "\n"
|
||
+"skeleton_blank_commons: " + skeleton_blank_commons + "\n"
|
||
+"skeleton_blank_uncommons: " + skeleton_blank_uncommons + "\n"
|
||
+"skeleton_blank_rares: " + skeleton_blank_rares + "\n"
|
||
+"skeleton_blank_mythics: " + skeleton_blank_mythics + "\n"
|
||
+"skeleton_shard_commons: " + skeleton_shard_commons + "\n"
|
||
+"skeleton_shard_uncommons: " + skeleton_shard_uncommons + "\n"
|
||
+"skeleton_shard_rares: " + skeleton_shard_rares + "\n"
|
||
+"skeleton_wedge_commons: " + skeleton_wedge_commons + "\n"
|
||
+"skeleton_wedge_uncommons: " + skeleton_wedge_uncommons + "\n"
|
||
+"skeleton_wedge_rares: " + skeleton_wedge_rares)
|
||
}
|
||
##number of chapter symbols each chapter textbox has
|
||
##example, symbols on abilities 2,2,3 returns [0,2,1]
|
||
saga_lore_count := {
|
||
one := 0
|
||
two := 0
|
||
three := 0
|
||
four := 0
|
||
five := 0
|
||
six := 0
|
||
seven := 0
|
||
eight := 0
|
||
for x from 0 to length(input)-1 do
|
||
if input[x] == "1" then one := one +1
|
||
else if input[x] == "2" then two := two +1
|
||
else if input[x] == "3" then three := three +1
|
||
else if input[x] == "4" then four := four +1
|
||
else if input[x] == "5" then five := five +1
|
||
else if input[x] == "6" then six := six +1
|
||
else if input[x] == "7" then seven := seven +1
|
||
else eight := eight +1
|
||
[one, two, three, four, five, six, seven]
|
||
}
|
||
##index of given chapter number in above array
|
||
##example, 2,2,3, returns 1,2,1
|
||
##i tried to make this shorter but this is the only one that deigned to function
|
||
saga_ch_placement := {
|
||
box1 := 0
|
||
box2 := 0
|
||
box3 := 0
|
||
box4 := 0
|
||
one := 0
|
||
two := 0
|
||
three := 0
|
||
four := 0
|
||
five := 0
|
||
six := 0
|
||
seven := 0
|
||
len := length(input)
|
||
if len >= 1 then (
|
||
if input[0] == "1" then (
|
||
box1 := box1 +1
|
||
one := box1+0
|
||
)else if input[0] == "2" then (
|
||
box2 := box2 +1
|
||
one := box2+0
|
||
)else if input[0] == "3" then (
|
||
box3 := box3 +1
|
||
one := box3+0
|
||
)else if input[0] == "4" then (
|
||
box4 := box4 +1
|
||
one := box4+0
|
||
)else (one := one)
|
||
)else (one := one)
|
||
if len >= 2 then (
|
||
if input[1] == "1" then (
|
||
box1 := box1 +1
|
||
two := box1+0
|
||
)else if input[1] == "2" then (
|
||
box2 := box2 +1
|
||
two := box2+0
|
||
)else if input[1] == "3" then (
|
||
box3 := box3 +1
|
||
two := box3+0
|
||
)else if input[1] == "4" then (
|
||
box4 := box4 +1
|
||
two := box4+0
|
||
)else (two := two)
|
||
)else (two := two)
|
||
if len >= 3 then (
|
||
if input[2] == "1" then (
|
||
box1 := box1 +1
|
||
three := box1+0
|
||
)else if input[2] == "2" then (
|
||
box2 := box2 +1
|
||
three := box2+0
|
||
)else if input[2] == "3" then (
|
||
box3 := box3 +1
|
||
three := box3+0
|
||
)else if input[2] == "4" then (
|
||
box4 := box4 +1
|
||
three := box4+0
|
||
)else (three := three)
|
||
)else (three := three)
|
||
if len >= 4 then (
|
||
if input[3] == "1" then (
|
||
box1 := box1 +1
|
||
four := box1+0
|
||
)else if input[3] == "2" then (
|
||
box2 := box2 +1
|
||
four := box2+0
|
||
)else if input[3] == "3" then (
|
||
box3 := box3 +1
|
||
four := box3+0
|
||
)else if input[3] == "4" then (
|
||
box4 := box4 +1
|
||
four := box4+0
|
||
)else (four := four)
|
||
)else (four := four)
|
||
if len >= 5 then (
|
||
if input[4] == "1" then (
|
||
box1 := box1 +1
|
||
five := box1+0
|
||
)else if input[4] == "2" then (
|
||
box2 := box2 +1
|
||
five := box2+0
|
||
)else if input[4] == "3" then (
|
||
box3 := box3 +1
|
||
five := box3+0
|
||
)else if input[4] == "4" then (
|
||
box4 := box4 +1
|
||
five := box4+0
|
||
)else (five := five)
|
||
)else (five := five)
|
||
if len >= 6 then (
|
||
if input[5] == "1" then (
|
||
box1 := box1 +1
|
||
six := box1+0
|
||
)else if input[5] == "2" then (
|
||
box2 := box2 +1
|
||
six := box2+0
|
||
)else if input[5] == "3" then (
|
||
box3 := box3 +1
|
||
six := box3+0
|
||
)else if input[5] == "4" then (
|
||
box4 := box4 +1
|
||
six := box4+0
|
||
)else (six := six)
|
||
)else (six := six)
|
||
if len >= 7 then (
|
||
if input[6] == "1" then (
|
||
box1 := box1 +1
|
||
seven := box1+0
|
||
)else if input[6] == "2" then (
|
||
box2 := box2 +1
|
||
seven := box2+0
|
||
)else if input[6] == "3" then (
|
||
box3 := box3 +1
|
||
seven := box3+0
|
||
)else if input[6] == "4" then (
|
||
box4 := box4 +1
|
||
seven := box4+0
|
||
)else (seven := seven)
|
||
)else (seven := seven)
|
||
[one, two, three, four, five, six, seven]
|
||
}
|
||
|
||
card_face := {
|
||
front := card[input]
|
||
back := if card[input+"_2"] or else "" != "" then card[input+"_2"] else card[input]
|
||
if match(margin_code, match:"(text[2456]|lv[5678])") then back else front
|
||
}
|
||
cc_filter := replace@(match:"^[CURMSL][WUBRGMZACL][0-9]+ ?[-—]? ?", replace:"")
|
||
strip_card_codes := {
|
||
save := input
|
||
input := cc_filter(input)
|
||
input := if input == "" or input == " " then save else input
|
||
if alch_compatible() and card.card_symbol == "alchemy"
|
||
then "<sym>A-</sym>" + input
|
||
else input
|
||
}
|
||
name_checker := {if not set.remove_card_codes then input else strip_card_codes(input)}
|
||
|
||
face_code := {
|
||
face := ""
|
||
if margin_code == "text2" or margin_code == "lv5" or margin_code == "lv6" or margin_code == "lv7" or margin_code == "lv8" then face := "_2"
|
||
output := face_scripts[input](face) or else if_parse(input, face:face) or else input
|
||
output
|
||
}
|
||
flip_face := {
|
||
if input == "_2" then "" else "_2"
|
||
}
|
||
face_scripts := [
|
||
iscreature: {is_creature(card["type"+face])},
|
||
iscreaturish: {is_creaturish(card["type"+face])},
|
||
isenchantment: {is_enchantment(card["type"+face])},
|
||
isartifact: {is_artifact(card["type"+face])},
|
||
island: {is_land(card["type"+face])},
|
||
isspell: {is_spell(card["type"+face])},
|
||
istarget: {is_targeted(card["text"+face])},
|
||
subtypes: {separate_words(card["sub_type"+face], spacer: " ")}
|
||
contains: {
|
||
contains(card[field+face], match:query)
|
||
},
|
||
notcontains: {not contains(card[field+face], match:query)},
|
||
name: {card["name"+face]},
|
||
cost: {card["casting_cost"+face]},
|
||
altname: {card["name"+flip_face(face)]},
|
||
altcost: {card["casting_cost"+flip_face(face)]},
|
||
]
|
||
expand_facecodes := [
|
||
subtype: "sub_type",
|
||
castingcost: "casting_cost",
|
||
manacost: "casting_cost"
|
||
]
|
||
if_parse := replace@(
|
||
match: "if_(.*)_then_(.*)_else_(.*)",
|
||
replace: {if_scripts(_1, t:_2, f:_3)}
|
||
)
|
||
if_scripts := {
|
||
contCheck := split_text(input, match:"_")
|
||
func := contCheck[0]
|
||
field := ""
|
||
query := "^$"
|
||
if length(contCheck) == 3 then (
|
||
field := contCheck[0]
|
||
func := contCheck[1]
|
||
query := contCheck[2]
|
||
)
|
||
field := expand_facecodes[field] or else field
|
||
if face_scripts[func](face, field:field, query:query) or else false then t else f
|
||
}
|
||
|
||
white_text := {false}
|
||
phy_reminder := {
|
||
phy_match := filter_text(input, match:"(/[WUBRG])+", in_context:"H<match>")
|
||
letters := split_text(phy_match, match:"/")
|
||
reminder_text := ""
|
||
if length(letters) == 2 then
|
||
reminder_text := "[H/" + letters[1] + "] can be paid with [" + letters[1] + "] or 2 life."
|
||
else if length(letters) > 2 then
|
||
reminder_text := "[H/" + letters[1] + "/" + letters[2] + "] can be paid with [" + letters[1] + "], " + "[" + letters[2] + "], or 2 life."
|
||
else
|
||
reminder_text := ""
|
||
reminder_text
|
||
}
|
||
|
||
###### Print Fix
|
||
rare_width := {
|
||
cw := card_style.rarity.content_width
|
||
cw := if cw > 44 then (if set.print_fix != "" then set.print_fix else 22) else if cw < 22 then 22 else cw
|
||
if card_style.rarity.width == 0 then 0 else cw
|
||
}
|
||
|
||
### Customize fonts
|
||
swap_font := {false} ##{styling.apply_custom_fonts}
|
||
split_font := split_text@(match:";")
|
||
pop_font_name := {split_font(input).0 or else ""}
|
||
pop_font_size := {split_font(input).1 or else ""}
|
||
pop_font_color := {split_font(input).2 or else ""}
|
||
pop_font_vertical := {split_font(input).3 or else ""}
|
||
pop_font_italic := {split_font(input).4 or else ""}
|
||
|
||
swap_font_name := {
|
||
if swap_font() then (
|
||
test := pop_font_name(src)
|
||
if test != "" then font_name := test
|
||
)
|
||
|
||
font_name
|
||
}@(font_name:"", src:"")
|
||
swap_font_size := {
|
||
if swap_font() then (
|
||
test := pop_font_size(src)
|
||
if test != "" then font_size := test
|
||
)
|
||
|
||
font_size
|
||
}@(font_size:16, src:"")
|
||
swap_font_color := {
|
||
if swap_font() then (
|
||
test := pop_font_color(src)
|
||
nums := split_text(test, match:",")
|
||
test_color := nil
|
||
|
||
if length(nums) >= 4 then test_color := rgba(nums.0, nums.1, nums.2, nums.3) or else nil
|
||
if test_color == nil and length(nums) >= 3 then test_color := rgb(nums.0, nums.1, nums.2) or else nil
|
||
if test_color == nil and test != "" then test_color := to_color(test) or else nil
|
||
if test_color != nil then font_color := test_color
|
||
) else ""
|
||
|
||
font_color
|
||
}@(font_color:"", src:"")
|
||
swap_font_vertical := {
|
||
if swap_font() then (
|
||
test := pop_font_vertical(src)
|
||
if test != "" then vertical := to_number(test)
|
||
)
|
||
|
||
vertical
|
||
}@(vertical:0, src:"")
|
||
swap_font_italic := {
|
||
font_name := "MPlantin-Italic"
|
||
if swap_font() then (
|
||
test := pop_font_italic(styling.custom_body_font)
|
||
test2 := pop_font_name(styling.custom_body_font)
|
||
if test != "" then font_name := test
|
||
else if test2 != "" then font_name := ""
|
||
)
|
||
|
||
font_name
|
||
}@(font_name:"", src:"")
|
||
|
||
#### Customize rarity symbol
|
||
alt_rarity := {""} ##{styling.alt_rarity_color}
|
||
use_alt_rarity := {alt_rarity() != ""}
|
||
alt_rarity_color := {
|
||
string := "83,67,53:177,150,131:0,0,0:0,0,0:0.07:"
|
||
src := alt_rarity()
|
||
if match(src, match:":$") then string := src
|
||
colons := length(filter_text(string, match:":"))
|
||
output := split_text(string, match:",|:")
|
||
splits := split_text(string, match:":")
|
||
final_num := to_real(splits[length(splits)-2]) or else 0
|
||
final_border := final_num > 0 and final_num < 1
|
||
final_num := if not final_border then "0.07" else to_string(final_num);
|
||
if final_border then (
|
||
colons := colons - 1;
|
||
string := replace(string, match:"{final_num}:", replace:"")
|
||
)
|
||
if colons == 4
|
||
then output := split_text(string+final_num+":", match:",|:")
|
||
if colons == 3
|
||
then output := split_text(string+splits[2]+":"+final_num+":", match:",|:")
|
||
else if colons == 2
|
||
then output := split_text(string+"0,0,0:0,0,0:"+final_num+":", match:",|:")
|
||
else if colons == 1
|
||
then output := split_text(string+splits[0]+":0,0,0:0,0,0:"+final_num+":", match:",|:")
|
||
|
||
output
|
||
}
|
||
alt_symbol := {
|
||
alt_array := alt_rarity_color()
|
||
symbol_variation(
|
||
symbol:set.symbol,
|
||
border_radius: alt_array.12,
|
||
fill_type: "linear gradient",
|
||
fill_color_1: rgb(alt_array.0, alt_array.1, alt_array.2),
|
||
fill_color_2: rgb(alt_array.3, alt_array.4, alt_array.5),
|
||
border_color_1: rgb(alt_array.6, alt_array.7, alt_array.8),
|
||
border_color_2: rgb(alt_array.9, alt_array.10, alt_array.11),
|
||
center_x:0.5, center_y:0.5, end_x:1, end_y:1
|
||
)
|
||
}
|
||
|
||
|
||
|
||
# rough type_of script
|
||
# fine for nil, boolean, color, date, string, number, and array
|
||
# map and image are trickier
|
||
# if you don't care about the difference use as normal, will return "map or image"
|
||
# if you do, include key:"" parameter that's a key of the potential map
|
||
# ex if you want to know if some_object is an image or [x:1]
|
||
# use type_of(some_object, key:"x")
|
||
type_of := {
|
||
test := to_string(input) or else nil
|
||
type := "idk"
|
||
if test == "" and input == nil then type := "nil"
|
||
else if test != nil and (input == true or input == false) then type := "boolean"
|
||
else if (test != nil and test + 0 == input + 0) then (
|
||
if to_color(test) or else nil == input
|
||
then type := "color"
|
||
else if to_date(test) or else nil == input
|
||
then type := "date"
|
||
else type := "string"
|
||
)
|
||
else if test != nil then type := "number"
|
||
else if input[0] or else nil != nil then type := "array"
|
||
else if key == "" then type := "map or image"
|
||
else if input[key] or else nil == nil then type := "image"
|
||
else type := "map"
|
||
type
|
||
}@(key:"")
|
||
|
||
is_string := {
|
||
test := to_string(input) or else nil
|
||
if test == "" and input == nil then false
|
||
else if test == nil then false
|
||
else test == input
|
||
}
|
||
|
||
# mapping := ["up":"test/up.png" "down":"test/down.png" "left":"test/left.png" "right":"test/right.png"]
|
||
multi_choice_image := {
|
||
## input = option string
|
||
##img_map = map of image links
|
||
coll := split_text(input, match:", ?")
|
||
imgs := for each x in coll do if img_map[x] or else false != false then [img_map[x]]
|
||
len := length(imgs)
|
||
if len == 0 then
|
||
""
|
||
else if len == 1 then
|
||
imgs[0]
|
||
else if len == 2 then
|
||
combine_blend(image1:imgs[0] image2:imgs[1], combine:combine)
|
||
else mass_combine(imgs:imgs, combine:combine)
|
||
|
||
}@(combine:"and")
|
||
mass_combine := {
|
||
base := combine_blend(image1:imgs[0] image2:imgs[1], combine:combine)
|
||
for x from 2 to length(imgs)-1 do (
|
||
base := combine_blend(image1:base image2:imgs[x] combine:combine)
|
||
"" # this is junk output so it doesn't try to add the images as strings
|
||
)
|
||
base
|
||
}@(combine:"and")
|
||
|
||
zwsp := ""
|