mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-27 17:41:50 +00:00
## About The Pull Request <details> - renamed ai folder to announcer -- announcer -- - moved vox_fem to announcer - moved approachingTG to announcer - separated the ambience folder into ambience and instrumental -- ambience -- - created holy folder moved all related sounds there - created engineering folder and moved all related sounds there - created security folder and moved ambidet there - created general folder and moved ambigen there - created icemoon folder and moved all icebox-related ambience there - created medical folder and moved all medbay-related ambi there - created ruin folder and moves all ruins ambi there - created beach folder and moved seag and shore there - created lavaland folder and moved related ambi there - created aurora_caelus folder and placed its ambi there - created misc folder and moved the rest of the files that don't have a specific category into it -- instrumental -- - moved traitor folder here - created lobby_music folder and placed our songs there (title0 not used anywhere? - server-side modification?) -- items -- - moved secdeath to hailer - moved surgery to handling -- effects -- - moved chemistry into effects - moved hallucinations into effects - moved health into effects - moved magic into effects -- vehicles -- - moved mecha into vehicles created mobs folder -- mobs -- - moved creatures folder into mobs - moved voice into mobs renamed creatures to non-humanoids renamed voice to humanoids -- non-humanoids-- created cyborg folder created hiss folder moved harmalarm.ogg to cyborg -- humanoids -- -- misc -- moved ghostwhisper to misc moved insane_low_laugh to misc I give up trying to document this. </details> - [X] ambience - [x] announcer - [x] effects - [X] instrumental - [x] items - [x] machines - [x] misc - [X] mobs - [X] runtime - [X] vehicles - [ ] attributions ## Why It's Good For The Game This folder is so disorganized that it's vomit inducing, will make it easier to find and add new sounds, providng a minor structure to the sound folder. ## Changelog 🆑 grungussuss refactor: the sound folder in the source code has been reorganized, please report any oddities with sounds playing or not playing server: lobby music has been repathed to sound/music/lobby_music /🆑
531 lines
19 KiB
Plaintext
531 lines
19 KiB
Plaintext
#define TAPPED_ANGLE 90
|
|
#define UNTAPPED_ANGLE 0
|
|
|
|
/obj/item/tcgcard
|
|
name = "Coder"
|
|
desc = "Wow, a mint condition coder card! Better tell the GitHub all about this!"
|
|
icon = DEFAULT_TCG_DMI_ICON
|
|
icon_state = "runtime"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
///Unique ID, for use in lookups and storage, used to index the global datum list where the rest of the card's info is stored
|
|
var/id = "code"
|
|
///Used along with the id for lookup
|
|
var/series = "coderbus"
|
|
///Is the card flipped?
|
|
var/flipped = FALSE
|
|
///Has this card been "tapped"? AKA, is it horizontal?
|
|
var/tapped = FALSE
|
|
///Cached icon used for inspecting the card
|
|
var/icon/cached_flat_icon
|
|
|
|
/obj/item/tcgcard/Initialize(mapload, datum_series, datum_id)
|
|
. = ..()
|
|
AddElement(/datum/element/item_scaling, 0.3, 1)
|
|
//If they are passed as null let's replace them with the vars on the card. this also means we can allow for map loaded ccards
|
|
if(!datum_series)
|
|
datum_series = series
|
|
if(!datum_id)
|
|
datum_id = id
|
|
var/list/temp_list = SStrading_card_game.cached_cards[datum_series]
|
|
if(!temp_list)
|
|
return
|
|
var/datum/card/temp = temp_list["ALL"][datum_id]
|
|
if(!temp)
|
|
return
|
|
name = temp.name
|
|
desc = "<i>[temp.desc]</i>"
|
|
icon = icon(temp.icon)
|
|
icon_state = temp.icon_state
|
|
id = temp.id
|
|
series = temp.series
|
|
|
|
// This totally isn't overengineered to hell, shut up
|
|
/**
|
|
* Alright so some brief details here, we store all "immutable" (Think like power) card variables in a global list, indexed by id
|
|
* This proc gets the card's associated card datum to play with
|
|
*/
|
|
/obj/item/tcgcard/proc/extract_datum()
|
|
var/list/cached_cards = SStrading_card_game.cached_cards[series]
|
|
if(!cached_cards)
|
|
return null
|
|
if(!cached_cards["ALL"][id])
|
|
CRASH("A card without a datum has appeared, either the global list is empty, or you fucked up bad. Series{[series]} ID{[id]} Len{[SStrading_card_game.cached_cards.len]}")
|
|
return cached_cards["ALL"][id]
|
|
|
|
/obj/item/tcgcard/get_name_chaser(mob/user, list/name_chaser = list())
|
|
if(flipped)
|
|
return ..()
|
|
var/datum/card/data_holder = extract_datum()
|
|
|
|
name_chaser += "Faction: [data_holder.faction]"
|
|
name_chaser += "Cost: [data_holder.summoncost]"
|
|
name_chaser += "Type: [data_holder.cardtype] - [data_holder.cardsubtype]"
|
|
name_chaser += "Power/Resolve: [data_holder.power]/[data_holder.resolve]"
|
|
if(data_holder.rules) //This can sometimes be empty
|
|
name_chaser += "Ruleset: [data_holder.rules]"
|
|
name_chaser += list("[icon2html(get_cached_flat_icon(), user, "extra_classes" = "hugeicon")]")
|
|
|
|
return name_chaser
|
|
|
|
/obj/item/tcgcard/proc/get_cached_flat_icon()
|
|
if(!cached_flat_icon)
|
|
cached_flat_icon = getFlatIcon(src)
|
|
return cached_flat_icon
|
|
|
|
GLOBAL_LIST_EMPTY(tcgcard_radial_choices)
|
|
|
|
/obj/item/tcgcard/attack_hand(mob/user, list/modifiers)
|
|
if(!isturf(loc))
|
|
return ..()
|
|
var/list/choices = GLOB.tcgcard_radial_choices
|
|
if(!length(choices))
|
|
choices = GLOB.tcgcard_radial_choices = list(
|
|
"Pickup" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_pickup"),
|
|
"Tap" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_tap"),
|
|
"Flip" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_flip"),
|
|
)
|
|
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
|
|
if(!check_menu(user))
|
|
return
|
|
switch(choice)
|
|
if("Tap")
|
|
tap_card(user)
|
|
if("Pickup")
|
|
user.put_in_hands(src)
|
|
if("Flip")
|
|
flip_card(user)
|
|
if(null)
|
|
return
|
|
|
|
/obj/item/tcgcard/attack_self(mob/user)
|
|
. = ..()
|
|
flip_card(user)
|
|
|
|
/obj/item/tcgcard/update_name(updates)
|
|
. = ..()
|
|
if(!flipped)
|
|
var/datum/card/template = extract_datum()
|
|
name = template.name
|
|
else
|
|
name = "Trading Card"
|
|
|
|
/obj/item/tcgcard/update_desc(updates)
|
|
. = ..()
|
|
if(!flipped)
|
|
var/datum/card/template = extract_datum()
|
|
desc = "<i>[template.desc]</i>"
|
|
else
|
|
desc = "It's the back of a trading card... no peeking!"
|
|
|
|
/obj/item/tcgcard/update_icon_state()
|
|
if(flipped)
|
|
icon_state = "cardback"
|
|
return ..()
|
|
|
|
var/datum/card/template = extract_datum()
|
|
if(!template)
|
|
return
|
|
icon_state = template.icon_state
|
|
return ..()
|
|
|
|
/obj/item/tcgcard/attackby(obj/item/item, mob/living/user, params)
|
|
if(istype(item, /obj/item/tcgcard))
|
|
var/obj/item/tcgcard/second_card = item
|
|
var/obj/item/tcgcard_deck/new_deck = new /obj/item/tcgcard_deck(drop_location())
|
|
new_deck.flipped = flipped
|
|
user.transferItemToLoc(second_card, new_deck)//Start a new pile with both cards, in the order of card placement.
|
|
user.transferItemToLoc(src, new_deck)
|
|
new_deck.update_icon_state()
|
|
user.put_in_hands(new_deck)
|
|
if(istype(item, /obj/item/tcgcard_deck))
|
|
var/obj/item/tcgcard_deck/old_deck = item
|
|
if(length(old_deck.contents) >= 30)
|
|
to_chat(user, span_notice("This pile has too many cards for a regular deck!"))
|
|
return
|
|
user.transferItemToLoc(src, old_deck)
|
|
flipped = old_deck.flipped
|
|
old_deck.update_appearance()
|
|
update_appearance()
|
|
return ..()
|
|
|
|
/obj/item/tcgcard/proc/check_menu(mob/living/user)
|
|
if(!istype(user))
|
|
return FALSE
|
|
if(user.incapacitated || !user.Adjacent(src))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/item/tcgcard/proc/tap_card(mob/user)
|
|
var/matrix/ntransform = matrix(transform)
|
|
if(tapped)
|
|
ntransform.TurnTo(TAPPED_ANGLE , UNTAPPED_ANGLE)
|
|
else
|
|
ntransform.TurnTo(UNTAPPED_ANGLE , TAPPED_ANGLE)
|
|
tapped = !tapped
|
|
animate(src, transform = ntransform, time = 2, easing = (EASE_IN|EASE_OUT))
|
|
|
|
/obj/item/tcgcard/proc/flip_card(mob/user)
|
|
to_chat(user, span_notice("You turn the card over."))
|
|
if(!flipped)
|
|
name = "Trading Card"
|
|
desc = "It's the back of a trading card... no peeking!"
|
|
icon_state = "cardback"
|
|
else
|
|
var/datum/card/template = extract_datum()
|
|
name = template.name
|
|
desc = "<i>[template.desc]</i>"
|
|
icon_state = template.icon_state
|
|
flipped = !flipped
|
|
|
|
/**
|
|
* A stack item that's not actually a stack because ORDER MATTERS with a deck of cards!
|
|
* The "top" card of the deck will always be the bottom card in the stack for our purposes.
|
|
*/
|
|
/obj/item/tcgcard_deck
|
|
name = "Trading Card Pile"
|
|
desc = "A stack of TCG cards."
|
|
icon = 'icons/obj/toys/tcgmisc.dmi'
|
|
icon_state = "deck_up"
|
|
base_icon_state = "deck"
|
|
obj_flags = UNIQUE_RENAME
|
|
var/flipped = FALSE
|
|
var/static/radial_draw = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_draw")
|
|
var/static/radial_shuffle = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_shuffle")
|
|
var/static/radial_pickup = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_pickup")
|
|
|
|
/obj/item/tcgcard_deck/Initialize(mapload)
|
|
. = ..()
|
|
create_storage(storage_type = /datum/storage/tcg)
|
|
RegisterSignal(atom_storage, COMSIG_STORAGE_REMOVED_ITEM, PROC_REF(on_item_removed))
|
|
|
|
/obj/item/tcgcard_deck/update_icon_state()
|
|
if(!flipped)
|
|
icon_state = "[base_icon_state]_up"
|
|
return ..()
|
|
|
|
switch(contents.len)
|
|
if(1 to 10)
|
|
icon_state = "[base_icon_state]_tcg_low"
|
|
if(11 to 20)
|
|
icon_state = "[base_icon_state]_tcg_half"
|
|
if(21 to INFINITY)
|
|
icon_state = "[base_icon_state]_tcg_full"
|
|
else
|
|
icon_state = "[base_icon_state]_tcg"
|
|
return ..()
|
|
|
|
/obj/item/tcgcard_deck/examine(mob/user)
|
|
. = ..()
|
|
. += span_notice("\The [src] has [contents.len] cards inside.")
|
|
|
|
/obj/item/tcgcard_deck/attack_hand(mob/user, list/modifiers)
|
|
var/list/choices = list(
|
|
"Draw" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_draw"),
|
|
"Shuffle" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_shuffle"),
|
|
"Pickup" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_pickup"),
|
|
"Flip" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_flip"),
|
|
)
|
|
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
|
|
if(!check_menu(user))
|
|
return
|
|
switch(choice)
|
|
if("Draw")
|
|
draw_card(user)
|
|
if("Shuffle")
|
|
shuffle_deck(user)
|
|
if("Pickup")
|
|
user.put_in_hands(src)
|
|
if("Flip")
|
|
flip_deck()
|
|
if(null)
|
|
return
|
|
|
|
/obj/item/tcgcard_deck/Destroy()
|
|
for(var/card in 1 to contents.len)
|
|
var/obj/item/tcgcard/stored_card = contents[card]
|
|
stored_card.forceMove(drop_location())
|
|
. = ..()
|
|
|
|
/obj/item/tcgcard_deck/proc/check_menu(mob/living/user)
|
|
if(!istype(user))
|
|
return FALSE
|
|
if(user.incapacitated || !user.Adjacent(src))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/item/tcgcard_deck/attackby(obj/item/item, mob/living/user, params)
|
|
. = ..()
|
|
if(istype(item, /obj/item/tcgcard))
|
|
if(contents.len >= 30)
|
|
to_chat(user, span_notice("This pile has too many cards for a regular deck!"))
|
|
return FALSE
|
|
var/obj/item/tcgcard/new_card = item
|
|
new_card.flipped = flipped
|
|
new_card.forceMove(src)
|
|
|
|
|
|
/obj/item/tcgcard_deck/attack_self(mob/living/carbon/user)
|
|
shuffle_deck(user)
|
|
return ..()
|
|
|
|
/**
|
|
* The user draws a single card. The deck is then handled based on how many cards are left.
|
|
*/
|
|
/obj/item/tcgcard_deck/proc/draw_card(mob/user)
|
|
if(!contents.len)
|
|
CRASH("A TCG deck was created with no cards inside of it.")
|
|
var/obj/item/tcgcard/drawn_card = contents[contents.len]
|
|
user.put_in_hands(drawn_card)
|
|
drawn_card.flipped = flipped //If it's a face down deck, it'll be drawn face down, if it's a face up pile you'll draw it face up.
|
|
drawn_card.update_icon_state()
|
|
user.visible_message(span_notice("[user] draws a card from \the [src]!"), \
|
|
span_notice("You draw a card from \the [src]!"))
|
|
if(contents.len <= 1)
|
|
var/obj/item/tcgcard/final_card = contents[1]
|
|
user.transferItemToLoc(final_card, drop_location())
|
|
qdel(src)
|
|
|
|
|
|
/**
|
|
* The user shuffles the order of the deck, then closes any visability into the deck's storage to prevent cheesing.
|
|
* *User: The person doing the shuffling, used in visable message and closing UI.
|
|
* *Visible: Will anyone need to hear the visable message about the shuffling?
|
|
*/
|
|
/obj/item/tcgcard_deck/proc/shuffle_deck(mob/user, visable = TRUE)
|
|
if(!contents)
|
|
return
|
|
contents = shuffle(contents)
|
|
if(user.active_storage)
|
|
user.active_storage.hide_contents(user)
|
|
if(visable)
|
|
user.visible_message(span_notice("[user] shuffles \the [src]!"), \
|
|
span_notice("You shuffle \the [src]!"))
|
|
|
|
|
|
/**
|
|
* The user flips the deck, turning it into a face up/down pile, and reverses the order of the cards from top to bottom.
|
|
*/
|
|
/obj/item/tcgcard_deck/proc/flip_deck()
|
|
flipped = !flipped
|
|
var/list/temp_deck = contents.Copy()
|
|
contents = reverse_range(temp_deck)
|
|
//Now flip the cards to their opposite positions.
|
|
for (var/obj/item/tcgcard/nu_card as anything in contents)
|
|
nu_card.flipped = flipped
|
|
nu_card.update_icon_state()
|
|
update_icon_state()
|
|
|
|
/**
|
|
* Signal handler for COMSIG_STORAGE_REMOVED_ITEM. Qdels src if contents are empty, flips the removed card if needed.
|
|
*/
|
|
/obj/item/tcgcard_deck/proc/on_item_removed(datum/storage/storage_datum, obj/item/thing, atom/remove_to_loc, silent = FALSE)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!istype(thing, /obj/item/tcgcard))
|
|
return
|
|
var/obj/item/tcgcard/card = thing
|
|
card.flipped = flipped
|
|
card.update_appearance(UPDATE_ICON_STATE)
|
|
|
|
if(length(contents) == 0)
|
|
qdel(src)
|
|
|
|
/obj/item/cardpack
|
|
name = "Trading Card Pack: Coder"
|
|
desc = "Contains six complete fuckups by the coders. Report this on GitHub please!"
|
|
icon = 'icons/obj/toys/tcgmisc.dmi'
|
|
icon_state = "error"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
custom_price = PAYCHECK_CREW * 0.75 //Price reduced from * 2 to * 0.75, this is planned as a temporary measure until card persistence is added.
|
|
///The card series to look in
|
|
var/series = "MEME"
|
|
///Chance of the pack having a coin in it out of 10
|
|
var/contains_coin = -1
|
|
///The amount of cards to draw from the rarity table
|
|
var/card_count = 5
|
|
///The rarity table, the set must contain at least one of each
|
|
var/list/rarity_table = list(
|
|
"common" = 900,
|
|
"uncommon" = 300,
|
|
"rare" = 100,
|
|
"epic" = 30,
|
|
"legendary" = 5,
|
|
"misprint" = 1)
|
|
///The amount of cards to draw from the guaranteed rarity table
|
|
var/guaranteed_count = 1
|
|
///The guaranteed rarity table, acts about the same as the rarity table. it can have as many or as few raritys as you'd like
|
|
var/list/guar_rarity = list(
|
|
"legendary" = 1,
|
|
"epic" = 9,
|
|
"rare" = 30,
|
|
"uncommon" = 60)
|
|
var/drop_all_cards = FALSE
|
|
|
|
/obj/item/cardpack/series_one
|
|
name = "Trading Card Pack: Series 1"
|
|
desc = "Contains six cards of varying rarity from the 2560 Core Set. Collect them all!"
|
|
icon_state = "cardpack_series1"
|
|
series = "coreset2020"
|
|
contains_coin = 10
|
|
|
|
/obj/item/cardpack/resin
|
|
name = "Trading Card Pack: Resin Frontier Booster Pack"
|
|
desc = "Contains six cards of varying rarity from the Resin Frontier set. Collect them all!"
|
|
icon_state = "cardpack_resin"
|
|
series = "resinfront"
|
|
contains_coin = 0
|
|
rarity_table = list(
|
|
"common" = 900,
|
|
"uncommon" = 300,
|
|
"rare" = 100,
|
|
"epic" = 30,
|
|
"legendary" = 5)
|
|
|
|
/obj/item/cardpack/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/item_scaling, 0.4, 1)
|
|
rarity_table = SStrading_card_game.get_rarity_table(type, rarity_table)
|
|
guar_rarity = SStrading_card_game.get_guarenteed_rarity_table(type, guar_rarity)
|
|
|
|
/obj/item/cardpack/attack_self(mob/user)
|
|
. = ..()
|
|
var/list/cards
|
|
if(drop_all_cards)
|
|
cards = SStrading_card_game.cached_cards[series]["ALL"]
|
|
else
|
|
cards = buildCardListWithRarity(card_count, guaranteed_count)
|
|
|
|
for(var/template in cards)
|
|
//Makes a new card based of the series of the pack.
|
|
new /obj/item/tcgcard(get_turf(user), series, template)
|
|
to_chat(user, span_notice("Wow! Check out these cards!"))
|
|
new /obj/effect/decal/cleanable/wrapping(get_turf(user))
|
|
playsound(loc, 'sound/items/poster/poster_ripped.ogg', 20, TRUE)
|
|
if(prob(contains_coin))
|
|
to_chat(user, span_notice("...and it came with a flipper, too!"))
|
|
new /obj/item/coin/thunderdome(get_turf(user))
|
|
qdel(src)
|
|
|
|
/obj/item/coin/thunderdome
|
|
name = "\improper TGC Flipper"
|
|
desc = "A TGC flipper, for deciding who gets to go first. Also conveniently acts as a counter, for various purposes."
|
|
icon = 'icons/obj/toys/tcgmisc.dmi'
|
|
icon_state = "coin_nanotrasen"
|
|
custom_materials = list(/datum/material/plastic = SMALL_MATERIAL_AMOUNT*5)
|
|
material_flags = NONE
|
|
sideslist = list("nanotrasen", "syndicate")
|
|
override_material_worth = TRUE
|
|
|
|
/obj/item/storage/card_binder
|
|
name = "card binder"
|
|
desc = "The perfect way to keep your collection of cards safe and valuable."
|
|
icon = 'icons/obj/toys/tcgmisc.dmi'
|
|
icon_state = "binder"
|
|
inhand_icon_state = "album"
|
|
lefthand_file = 'icons/mob/inhands/items/books_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/items/books_righthand.dmi'
|
|
resistance_flags = FLAMMABLE //burn your enemies' collections, for only you can Collect Them All!
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
|
|
|
/obj/item/storage/card_binder/Initialize(mapload)
|
|
. = ..()
|
|
atom_storage.set_holdable(/obj/item/tcgcard)
|
|
atom_storage.max_total_storage = 120
|
|
atom_storage.max_slots = 60
|
|
|
|
///Returns a list of cards ids of card_cnt weighted by rarity from the pack's tables that have matching series, with gnt_cnt of the guaranteed table.
|
|
/obj/item/cardpack/proc/buildCardListWithRarity(card_cnt, rarity_cnt)
|
|
var/list/toReturn = list()
|
|
//You can always get at least one of some rarity
|
|
toReturn += returnCardsByRarity(rarity_cnt, guar_rarity)
|
|
toReturn += returnCardsByRarity(card_cnt, rarity_table)
|
|
return toReturn
|
|
|
|
///Returns a list of card datums of the length cardCount that match a random rarity weighted by rarity_table[]
|
|
/obj/item/cardpack/proc/returnCardsByRarity(cardCount, list/rarity_table)
|
|
var/list/toReturn = list()
|
|
for(var/card in 1 to cardCount)
|
|
var/rarity = 0
|
|
//Some number between 1 and the sum of all values in the list
|
|
var/weight = 0
|
|
for(var/chance in rarity_table)
|
|
weight += rarity_table[chance]
|
|
var/random = rand(weight)
|
|
for(var/bracket in rarity_table)
|
|
//Steals blatantly from pick_weight(), sorry buddy I need the index
|
|
random -= rarity_table[bracket]
|
|
if(random <= 0)
|
|
rarity = bracket
|
|
break
|
|
//What we're doing here is using the cached the results of the rarity we find.
|
|
//This allows us to only have to run this once per rarity, ever.
|
|
//Unless you reload the cards of course, in which case we have to do this again.
|
|
var/list/cards = SStrading_card_game.cached_cards[series][rarity]
|
|
if(cards.len)
|
|
toReturn += pick(cards)
|
|
else
|
|
//If we still don't find anything yell into the void. Lazy coders.
|
|
log_runtime("The index [rarity] of rarity_table does not exist in the global cache")
|
|
return toReturn
|
|
|
|
//All of these values should be overridden by either a template or a card itself
|
|
/datum/card
|
|
///Unique ID, for use in lookups and (eventually) for persistence. MAKE SURE THIS IS UNIQUE FOR EACH CARD IN AS SERIES, OR THE ENTIRE SYSTEM WILL BREAK, AND I WILL BE VERY DISAPPOINTED.
|
|
var/id = "coder"
|
|
var/name = "Coder"
|
|
var/desc = "Wow, a mint condition coder card! Better tell the GitHub all about this!"
|
|
///This handles any extra rules for the card, i.e. extra attributes, special effects, etc. If you've played any other card game, you know how this works.
|
|
var/rules = "There are no rules here. There is no escape. No Recall or Intervention can work in this place."
|
|
var/icon = DEFAULT_TCG_DMI
|
|
var/icon_state = "template"
|
|
///What it costs to summon this card to the battlefield.
|
|
var/summoncost = -1
|
|
///How hard this card hits (by default)
|
|
var/power = -1
|
|
///How hard this card can get hit (by default)
|
|
var/resolve = -1
|
|
///Someone please come up with a ruleset so I can comment this
|
|
var/faction = "socks"
|
|
///Used to define the behaviour the card uses during the game.
|
|
var/cardtype ="C43a7u43?"
|
|
///An extra descriptor for the card. Combined with the cardtype for a larger card descriptor, i.e. Creature- Xenomorph, Spell- Instant, that sort of thing. For creatures, this has no effect, for spells, this is important.
|
|
var/cardsubtype = "Weeb"
|
|
///Defines the series that the card originates from, this is *very* important for spawning the cards via packs.
|
|
var/series = "hunter2"
|
|
///The rarity of this card, determines how much (or little) it shows up in packs. Rarities are common, uncommon, rare, epic, legendary and misprint.
|
|
var/rarity = "uber rare to the extreme"
|
|
|
|
///Icon file that summons are pulled from
|
|
var/summon_icon_file = "icons/obj/toys/tcgmisc.dmi"
|
|
///Icon state for summons to use
|
|
var/summon_icon_state = "template"
|
|
|
|
/datum/card/New(list/data = list(), list/templates = list())
|
|
applyTemplates(data, templates)
|
|
apply(data)
|
|
applyKeywords(data | templates)
|
|
|
|
///For each var that the card datum and the json entry share, we set the datum var to the json entry
|
|
/datum/card/proc/apply(list/data)
|
|
for(var/name in (data & vars))
|
|
vars[name] = data[name]
|
|
|
|
///Applies a json file to a card datum
|
|
/datum/card/proc/applyTemplates(list/data, list/templates = list())
|
|
apply(templates["default"])
|
|
apply(templates[data["template"]])
|
|
|
|
///Searches for keywords in the card's variables, marked by wrapping them in {$}
|
|
///Adds on hovor logic to them, using the passed in list
|
|
///We use the changed_vars list just to make the var searching faster
|
|
/datum/card/proc/applyKeywords(list/changed_vars)
|
|
for(var/name in (changed_vars & vars))
|
|
var/value = vars[name]
|
|
if(!istext(value))
|
|
continue
|
|
vars[name] = SStrading_card_game.resolve_keywords(value)
|
|
|
|
#undef TAPPED_ANGLE
|
|
#undef UNTAPPED_ANGLE
|