mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-16 20:52:33 +00:00
* Small changes to some card-related debug verbs (#72361) ## About The Pull Request Test Card Distribution debug verb has been altered slightly to prevent runtimes. Backing out of any one of the menus would send null as an argument, and cause a runtime. The Validate Cards verb now returns a message if no errors are found. I kept mistakenly clicking this verb thinking it was the Cardpack Distribution one, and would get confused whenever nothing happened. Now it returns a message! Also converts some of the stuff I touch into snake case because pretty code is nice. ## Why It's Good For The Game Closes #66987. Feedback for the random debug buttons I accidentally click is good. ## Changelog 🆑 Rhials fix: backing out of the Test Card Packs debug menu will no longer cause a runtime fix: Validate Cards debug verb now gives feedback if no errors are detected. /🆑 * Small changes to some card-related debug verbs Co-authored-by: Rhials <Datguy33456@gmail.com>
191 lines
8.1 KiB
Plaintext
191 lines
8.1 KiB
Plaintext
SUBSYSTEM_DEF(trading_card_game)
|
|
name = "Trading Card Game"
|
|
flags = SS_NO_FIRE
|
|
init_order = INIT_ORDER_TCG
|
|
/// Base directory for all related string files
|
|
var/card_directory = "strings/tcg"
|
|
/// List of card files to load
|
|
var/list/card_files = list("set_one.json", "set_two.json")
|
|
/// List of keyword files
|
|
/// These allow you to add on hovor logic to parts of a card's text, displaying extra info
|
|
var/list/keyword_files = list("keywords.json")
|
|
/// What cardpack types to load
|
|
var/card_packs = list(/obj/item/cardpack/series_one, /obj/item/cardpack/resin)
|
|
var/list/cached_guar_rarity = list()
|
|
var/list/cached_rarity_table = list()
|
|
/// List of all cards by series, with cards cached by rarity to make those lookups faster
|
|
var/list/cached_cards = list()
|
|
/// List of loaded keywords matched with their hovor text
|
|
var/list/keywords = list()
|
|
var/loaded = FALSE
|
|
|
|
//Let's load the cards before the map fires, so we can load cards on the map safely
|
|
/datum/controller/subsystem/trading_card_game/Initialize()
|
|
reloadAllCardFiles()
|
|
return SS_INIT_SUCCESS
|
|
|
|
///Loads all the card files
|
|
/datum/controller/subsystem/trading_card_game/proc/loadAllCardFiles()
|
|
for(var/keyword_file in keyword_files)
|
|
loadKeywordFile(keyword_file, card_directory)
|
|
styleKeywords()
|
|
for(var/card_file in card_files)
|
|
loadCardFile(card_file, card_directory)
|
|
|
|
///Empty the rarity cache so we can safely add new cards
|
|
/datum/controller/subsystem/trading_card_game/proc/clearCards()
|
|
loaded = FALSE
|
|
cached_cards = list()
|
|
keywords = list()
|
|
|
|
///Reloads all card files
|
|
/datum/controller/subsystem/trading_card_game/proc/reloadAllCardFiles()
|
|
clearCards()
|
|
loadAllCardFiles()
|
|
loaded = TRUE
|
|
|
|
///Loads the contents of a json file into our global card list
|
|
/datum/controller/subsystem/trading_card_game/proc/loadKeywordFile(filename, directory = "strings/tcg")
|
|
var/list/keyword_data = json_decode(file2text("[directory]/[filename]"))
|
|
for(var/keyword in keyword_data)
|
|
if(keywords[keyword])
|
|
stack_trace("Dupe detected, [keyword] was defined by [directory]/[filename] after it already had a value!")
|
|
continue
|
|
keywords[keyword] = keyword_data[keyword]
|
|
|
|
///Styles our keywords, converting them from just the raw text to the output we want
|
|
/datum/controller/subsystem/trading_card_game/proc/styleKeywords()
|
|
// Add the tooltip component to our text, make it pretty
|
|
for(var/keyword in keywords)
|
|
var/tooltip_text = keywords[keyword]
|
|
keywords[keyword] = span_tooltip(tooltip_text, keyword)
|
|
|
|
///Takes a string as input. Searches it for keywords in the pattern {$keyword}, and replaces them with their expanded form, generated above
|
|
/datum/controller/subsystem/trading_card_game/proc/resolve_keywords(search_through)
|
|
var/starting_text = search_through
|
|
while(TRUE)
|
|
var/fragment_start = findtext(search_through, "{$")
|
|
if(!fragment_start)
|
|
break
|
|
var/fragment_end = findtext(search_through, "}")
|
|
if(!fragment_end)
|
|
CRASH("[starting_text] contains a {$ that denotes the start of a keyword replacement, but not a closing }!")
|
|
///Gets the keyword this string wants to use
|
|
///We offset the start by two indexes to account for
|
|
var/keyword = copytext(search_through, fragment_start + 2, fragment_end)
|
|
var/replacement = keywords[keyword]
|
|
if(!replacement)
|
|
CRASH("[starting_text] contains a non-existent keyword! \[[keyword]\]")
|
|
search_through = replacetext(search_through, "{$[keyword]}", replacement)
|
|
|
|
return search_through
|
|
|
|
///Loads the contents of a json file into our global card list
|
|
/datum/controller/subsystem/trading_card_game/proc/loadCardFile(filename, directory = "strings/tcg")
|
|
var/list/json = json_decode(file2text("[directory]/[filename]"))
|
|
var/list/cards = json["cards"]
|
|
var/list/templates = list()
|
|
for(var/list/data in json["templates"])
|
|
templates[data["template"]] = data
|
|
for(var/list/data in cards)
|
|
var/datum/card/card = new(data, templates)
|
|
//Lets cache the id by rarity, for top speed lookup later
|
|
if(!cached_cards[card.series])
|
|
cached_cards[card.series] = list()
|
|
cached_cards[card.series]["ALL"] = list()
|
|
if(!cached_cards[card.series][card.rarity])
|
|
cached_cards[card.series][card.rarity] = list()
|
|
cached_cards[card.series][card.rarity] += card.id
|
|
//Let's actually store the datum here
|
|
cached_cards[card.series]["ALL"][card.id] = card
|
|
|
|
///Because old me wanted to keep memory costs down, each cardpack type shares a rarity list
|
|
///We do the spooky stuff in here to ensure we don't have too many lists lying around
|
|
/datum/controller/subsystem/trading_card_game/proc/get_rarity_table(type, list/sample_table)
|
|
//Pass by refrance moment
|
|
//This lets us only have one rarity table per pack, badmins beware
|
|
//Yes this is horribly overengineered. No I am not sorry
|
|
if(!cached_rarity_table[type])
|
|
cached_rarity_table[type] = sample_table
|
|
return cached_rarity_table[type]
|
|
|
|
///See above
|
|
/datum/controller/subsystem/trading_card_game/proc/get_guarenteed_rarity_table(type, list/sample_table)
|
|
if(!cached_guar_rarity[type])
|
|
cached_guar_rarity[type] = sample_table
|
|
return cached_guar_rarity[type]
|
|
|
|
///Prints all the cards names
|
|
/datum/controller/subsystem/trading_card_game/proc/printAllCards()
|
|
for(var/card_set in cached_cards)
|
|
message_admins("Printing the [card_set] set")
|
|
for(var/card in cached_cards[card_set]["ALL"])
|
|
var/datum/card/toPrint = cached_cards[card_set]["ALL"][card]
|
|
message_admins(toPrint.name)
|
|
|
|
///Checks the passed type list for missing raritys, or raritys out of bounds
|
|
/datum/controller/subsystem/trading_card_game/proc/check_cardpacks(card_pack_list)
|
|
var/toReturn = ""
|
|
for(var/cardPack in card_pack_list)
|
|
var/obj/item/cardpack/pack = new cardPack()
|
|
//Lets see if someone made a type yeah?
|
|
if(!cached_cards[pack.series])
|
|
toReturn += "[pack.series] does not have any cards in it\n"
|
|
continue
|
|
for(var/card in cached_cards[pack.series]["ALL"])
|
|
var/datum/card/template = cached_cards[pack.series]["ALL"][card]
|
|
if(template.rarity == "ALL")
|
|
toReturn += "[pack.type] has a rarity [template.rarity] on the card [template.id] that needs to be changed to something that isn't \"ALL\"\n"
|
|
continue
|
|
if(!(template.rarity in pack.rarity_table))
|
|
toReturn += "[pack.type] has a rarity [template.rarity] on the card [template.id] that does not exist\n"
|
|
continue
|
|
//Lets run a check to see if all the rarities exist that we want to exist exist
|
|
for(var/pack_rarity in pack.rarity_table)
|
|
if(!cached_cards[pack.series][pack_rarity])
|
|
toReturn += "[pack.type] does not have the required rarity [pack_rarity]\n"
|
|
qdel(pack)
|
|
|
|
return toReturn
|
|
|
|
///Checks the global card list for cards that don't override all the default values of the card datum
|
|
/datum/controller/subsystem/trading_card_game/proc/check_card_datums()
|
|
var/toReturn = ""
|
|
var/datum/thing = new()
|
|
for(var/series in cached_cards)
|
|
var/cards = cached_cards[series]["ALL"]
|
|
for(var/card in cards)
|
|
var/datum/card/target = cached_cards[series]["ALL"][card]
|
|
var/toAdd = "The card [target.id] in [series] has the following default variables:"
|
|
var/shouldAdd = FALSE
|
|
for(var/current_var in (target.vars ^ thing.vars))
|
|
if(current_var == "icon" && target.vars[current_var] == DEFAULT_TCG_DMI)
|
|
continue
|
|
if(target.vars[current_var] == initial(target.vars[current_var]))
|
|
shouldAdd = TRUE
|
|
toAdd += "\n[current_var] with a value of [target.vars[current_var]]"
|
|
if(shouldAdd)
|
|
toReturn += toAdd
|
|
qdel(thing)
|
|
|
|
return toReturn
|
|
|
|
///Used to test open a large amount of cardpacks
|
|
/datum/controller/subsystem/trading_card_game/proc/check_card_distribution(cardPack, batchSize, batchCount, guaranteed)
|
|
var/totalCards = 0
|
|
//Gotta make this look like an associated list so the implicit "does this exist" checks work proper later
|
|
var/list/cardsByCount = list("" = 0)
|
|
var/obj/item/cardpack/pack = new cardPack()
|
|
for(var/index in 1 to batchCount)
|
|
var/list/cards = pack.buildCardListWithRarity(batchSize, guaranteed)
|
|
for(var/id in cards)
|
|
totalCards++
|
|
cardsByCount[id] += 1
|
|
var/toSend = "Out of [totalCards] cards"
|
|
for(var/id in sort_list(cardsByCount, GLOBAL_PROC_REF(cmp_num_string_asc)))
|
|
if(id)
|
|
var/datum/card/template = cached_cards[pack.series]["ALL"][id]
|
|
toSend += "\nID:[id] [template.name] [(cardsByCount[id] * 100) / totalCards]% Total:[cardsByCount[id]]"
|
|
message_admins(toSend)
|
|
qdel(pack)
|