diff --git a/code/modules/games/cardemon.dm b/code/modules/games/cardemon.dm index 23e8d6e251..a99e656add 100644 --- a/code/modules/games/cardemon.dm +++ b/code/modules/games/cardemon.dm @@ -2,6 +2,7 @@ name = "cardemon booster pack" desc = "Finally! A children's card game in space!" icon_state = "card_pack_cardemon" + parentdeck = "cardemon" /obj/item/weapon/pack/cardemon/New() ..() @@ -28,4 +29,4 @@ P.name = "[rarity] [P.name]" P.card_icon += "_[rarity]" P.back_icon = "card_back_cardemon" - cards += P \ No newline at end of file + cards += P diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index 0eba340761..68aef108ec 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -7,6 +7,7 @@ w_class = ITEMSIZE_SMALL icon = 'icons/obj/playing_cards.dmi' var/list/cards = list() + var/cooldown = 0 // to prevent spam shuffle /obj/item/weapon/deck/holder name = "card box" @@ -43,7 +44,7 @@ P.back_icon = "card_back" cards += P - for(var/i = 0,i<2,i++) + for(var/i = 0, i<2, i++) P = new() P.name = "joker" P.card_icon = "joker" @@ -52,13 +53,20 @@ /obj/item/weapon/deck/attackby(obj/O as obj, mob/user as mob) if(istype(O,/obj/item/weapon/hand)) var/obj/item/weapon/hand/H = O - for(var/datum/playingcard/P in H.cards) - cards += P - qdel(O) - user << "You place your cards on the bottom of \the [src]." - return + if(H.parentdeck == src) + for(var/datum/playingcard/P in H.cards) + cards += P + qdel(H) + to_chat(user,"You place your cards on the bottom of \the [src].") + return + else + to_chat(user,"You can't mix cards from other decks!") + return ..() +/obj/item/weapon/deck/attack_hand(mob/user as mob) + draw_card() + /obj/item/weapon/deck/verb/draw_card() set category = "Object" @@ -66,18 +74,26 @@ set desc = "Draw a card from a deck." set src in view(1) + var/mob/living/carbon/user = usr + if(usr.stat || !Adjacent(usr)) return + if(user.hands_are_full()) // Safety check lest the card disappear into oblivion + to_chat(user,"Your hands are full!") + return + if(!istype(usr,/mob/living/carbon)) return - var/mob/living/carbon/user = usr - if(!cards.len) - usr << "There are no cards in the deck." + to_chat(user,"There are no cards in the deck.") return var/obj/item/weapon/hand/H = user.get_type_in_hands(/obj/item/weapon/hand) + if(H && !(H.parentdeck == src)) + to_chat(user,"You can't mix cards from different decks!") + return + if(!H) H = new(get_turf(src)) user.put_in_hands(H) @@ -87,9 +103,10 @@ var/datum/playingcard/P = cards[1] H.cards += P cards -= P + H.parentdeck = src H.update_icon() - user.visible_message("\The [user] draws a card.") - user << "It's the [P]." + user.visible_message("\The [user] draws a card.") + to_chat(user,"It's the [P].") /obj/item/weapon/deck/verb/deal_card() @@ -101,7 +118,7 @@ if(usr.stat || !Adjacent(usr)) return if(!cards.len) - usr << "There are no cards in the deck." + to_chat(usr,"There are no cards in the deck.") return var/list/players = list() @@ -113,26 +130,56 @@ var/mob/living/M = input("Who do you wish to deal a card?") as null|anything in players if(!usr || !src || !M) return - deal_at(usr, M) + deal_at(usr, M, 1) -/obj/item/weapon/deck/proc/deal_at(mob/user, mob/target) +/obj/item/weapon/deck/verb/deal_card_multi() + + set category = "Object" + set name = "Deal Multiple Cards" + set desc = "Deal multiple cards from a deck." + set src in view(1) + + if(usr.stat || !Adjacent(usr)) return + + if(!cards.len) + to_chat(usr,"There are no cards in the deck.") + return + + var/list/players = list() + for(var/mob/living/player in viewers(3)) + if(!player.stat) + players += player + //players -= usr + var/maxcards = max(min(cards.len,10),1) + var/dcard = input("How many card(s) do you wish to deal? You may deal up to [maxcards] cards.") as num + if(dcard > maxcards) + return + var/mob/living/M = input("Who do you wish to deal [dcard] card(s)?") as null|anything in players + if(!usr || !src || !M) return + + deal_at(usr, M, dcard) + +/obj/item/weapon/deck/proc/deal_at(mob/user, mob/target, dcard) // Take in the no. of card to be dealt var/obj/item/weapon/hand/H = new(get_step(user, user.dir)) - - H.cards += cards[1] - cards -= cards[1] - H.concealed = 1 - H.update_icon() + var/i + for(i = 0, i < dcard, i++) + H.cards += cards[1] + cards -= cards[1] + H.parentdeck = src + H.concealed = 1 + H.update_icon() if(user==target) - user.visible_message("\The [user] deals a card to \himself.") + user.visible_message("\The [user] deals [dcard] card(s) to \himself.") else - user.visible_message("\The [user] deals a card to \the [target].") + user.visible_message("\The [user] deals [dcard] card(s) to \the [target].") H.throw_at(get_step(target,target.dir),10,1,H) + /obj/item/weapon/hand/attackby(obj/O as obj, mob/user as mob) if(cards.len == 1 && istype(O, /obj/item/weapon/pen)) var/datum/playingcard/P = cards[1] if(P.name != "Blank Card") - user << "You cannot write on that card." + to_chat(user,"You cannot write on that card.") return var/cardtext = sanitize(input(user, "What do you wish to write on the card?", "Card Editing") as text|null, MAX_PAPER_MESSAGE_LEN) if(!cardtext) @@ -143,36 +190,81 @@ update_icon() else if(istype(O,/obj/item/weapon/hand)) var/obj/item/weapon/hand/H = O - for(var/datum/playingcard/P in cards) - H.cards += P - H.concealed = src.concealed - user.drop_from_inventory(src) - qdel(src) - H.update_icon() - return + if(H.parentdeck == src.parentdeck) // Prevent cardmixing + for(var/datum/playingcard/P in cards) + H.cards += P + H.concealed = src.concealed + user.drop_from_inventory(src) + qdel(src) + H.update_icon() + return + else + to_chat(user,"You cannot mix cards from other decks!") + return + ..() -/obj/item/weapon/deck/attack_self(var/mob/user as mob) +/obj/item/weapon/deck/attack_self() + shuffle() - var/list/newcards = list() - while(cards.len) - var/datum/playingcard/P = pick(cards) - newcards += P - cards -= P - cards = newcards - user.visible_message("\The [user] shuffles [src].") -/obj/item/weapon/deck/MouseDrop(atom/over) - if(!usr || !over) return - if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows +/obj/item/weapon/deck/verb/verb_shuffle() + set category = "Object" + set name = "Shuffle" + set desc = "Shuffle the cards in the deck." + set src in view(1) + shuffle() - if(!ishuman(over) || !(over in viewers(3))) return - - if(!cards.len) - usr << "There are no cards in the deck." +/obj/item/weapon/deck/proc/shuffle() + var/mob/living/user = usr + if (cooldown < world.time - 10) // 15 ticks cooldown + var/list/newcards = list() + while(cards.len) + var/datum/playingcard/P = pick(cards) + newcards += P + cards -= P + cards = newcards + user.visible_message("\The [user] shuffles [src].") + playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) + cooldown = world.time + else return - deal_at(usr, over) + +/obj/item/weapon/deck/MouseDrop(mob/user as mob) // Code from Paper bin, so you can still pick up the deck + if((user == usr && (!( usr.restrained() ) && (!( usr.stat ) && (usr.contents.Find(src) || in_range(src, usr)))))) + if(!istype(usr, /mob/living/simple_animal)) + if( !usr.get_active_hand() ) //if active hand is empty + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] + + if (H.hand) + temp = H.organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + to_chat(user,"You try to move your [temp.name], but cannot!") + return + + to_chat(user,"You pick up [src].") + user.put_in_hands(src) + + return + +/obj/item/weapon/deck/verb_pickup(mob/user as mob) // Snowflaked so pick up verb work as intended + if((user == usr && (!( usr.restrained() ) && (!( usr.stat ) && (usr.contents.Find(src) || in_range(src, usr)))))) + if(!istype(usr, /mob/living/simple_animal)) + if( !usr.get_active_hand() ) //if active hand is empty + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] + + if (H.hand) + temp = H.organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + to_chat(user,"You try to move your [temp.name], but cannot!") + return + + to_chat(user,"You pick up [src].") + user.put_in_hands(src) + return /obj/item/weapon/pack/ name = "Card Pack" @@ -182,13 +274,15 @@ icon = 'icons/obj/playing_cards.dmi' w_class = ITEMSIZE_TINY var/list/cards = list() + var/parentdeck = null // This variable is added here so that card pack dependent card can be mixed together by defining a "parentdeck" for them /obj/item/weapon/pack/attack_self(var/mob/user as mob) - user.visible_message("[user] rips open \the [src]!") + user.visible_message("[user] rips open \the [src]!") var/obj/item/weapon/hand/H = new() H.cards += cards + H.parentdeck = src.parentdeck cards.Cut(); user.drop_item() qdel(src) @@ -205,31 +299,39 @@ var/concealed = 0 var/list/cards = list() + var/parentdeck = null /obj/item/weapon/hand/verb/discard() set category = "Object" set name = "Discard" - set desc = "Place a card from your hand in front of you." + set desc = "Place (a) card(s) from your hand in front of you." - var/list/to_discard = list() - for(var/datum/playingcard/P in cards) - to_discard[P.name] = P - var/discarding = input("Which card do you wish to put down?") as null|anything in to_discard + var/i + var/maxcards = min(cards.len,5) // Maximum of 5 cards at once + var/discards = input("How many cards do you want to discard? You may discard up to [maxcards] card(s)") as num + if(discards > maxcards) + return + for (i = 0;i < discards;i++) + var/list/to_discard = list() + for(var/datum/playingcard/P in cards) + to_discard[P.name] = P + var/discarding = input("Which card do you wish to put down?") as null|anything in to_discard - if(!discarding || !to_discard[discarding] || !usr || !src) return + if(!discarding || !to_discard[discarding] || !usr || !src) return - var/datum/playingcard/card = to_discard[discarding] - to_discard.Cut() + var/datum/playingcard/card = to_discard[discarding] + to_discard.Cut() - var/obj/item/weapon/hand/H = new(src.loc) - H.cards += card - cards -= card - H.concealed = 0 - H.update_icon() - src.update_icon() - usr.visible_message("\The [usr] plays \the [discarding].") - H.loc = get_step(usr,usr.dir) + var/obj/item/weapon/hand/H = new(src.loc) + H.cards += card + cards -= card + H.concealed = 0 + H.parentdeck = src.parentdeck + H.update_icon() + src.update_icon() + usr.visible_message("\The [usr] plays \the [discarding].") + H.loc = get_step(usr,usr.dir) if(!cards.len) qdel(src) @@ -237,14 +339,51 @@ /obj/item/weapon/hand/attack_self(var/mob/user as mob) concealed = !concealed update_icon() - user.visible_message("\The [user] [concealed ? "conceals" : "reveals"] their hand.") + user.visible_message("\The [user] [concealed ? "conceals" : "reveals"] their hand.") /obj/item/weapon/hand/examine(mob/user) ..(user) - if((!concealed || src.loc == user) && cards.len) - user << "It contains: " + if((!concealed) && cards.len) + to_chat(user,"It contains: ") for(var/datum/playingcard/P in cards) - user << "\The [P.name]." + to_chat(user,"\The [P.name].") + +/obj/item/weapon/hand/verb/Removecard() + + set category = "Object" + set name = "Remove card" + set desc = "Remove a card from the hand." + set src in view(1) + + var/mob/living/carbon/user = usr + + if(user.stat || !Adjacent(user)) return + + if(user.hands_are_full()) // Safety check lest the card disappear into oblivion + to_chat(usr,"Your hands are full!") + return + + var/pickablecards = list() + for(var/datum/playingcard/P in cards) + pickablecards[P.name] += P + var/pickedcard = input("Which card do you want to remove from the hand?") as null|anything in pickablecards + + if(!pickedcard || !pickablecards[pickedcard] || !usr || !src) return + + var/datum/playingcard/card = pickablecards[pickedcard] + + var/obj/item/weapon/hand/H = new(get_turf(src)) + user.put_in_hands(H) + H.cards += card + cards -= card + H.parentdeck = src.parentdeck + H.concealed = src.concealed + H.update_icon() + src.update_icon() + + if(!cards.len) + qdel(src) + return /obj/item/weapon/hand/update_icon(var/direction = 0) @@ -308,4 +447,4 @@ update_icon() /obj/item/weapon/hand/pickup(mob/user as mob) - src.update_icon() \ No newline at end of file + src.update_icon() diff --git a/code/modules/games/spaceball_cards.dm b/code/modules/games/spaceball_cards.dm index 57a28fa1a2..146317a720 100644 --- a/code/modules/games/spaceball_cards.dm +++ b/code/modules/games/spaceball_cards.dm @@ -2,6 +2,7 @@ name = "spaceball booster pack" desc = "Officially licensed to take your money." icon_state = "card_pack_spaceball" + parentdeck = "spaceball" /obj/item/weapon/pack/spaceball/New() ..() diff --git a/code/modules/games/tarot.dm b/code/modules/games/tarot.dm index f5727a0c43..cae71540cb 100644 --- a/code/modules/games/tarot.dm +++ b/code/modules/games/tarot.dm @@ -24,14 +24,20 @@ P.back_icon = "card_back_tarot" cards += P -/obj/item/weapon/deck/tarot/attack_self(var/mob/user as mob) - var/list/newcards = list() - while(cards.len) - var/datum/playingcard/P = pick(cards) - P.name = replacetext(P.name," reversed","") - if(prob(50)) - P.name += " reversed" - newcards += P - cards -= P - cards = newcards - user.visible_message("\The [user] shuffles [src].") \ No newline at end of file +/obj/item/weapon/deck/tarot/shuffle() + var/mob/living/user = usr + if (cooldown < world.time - 10) + var/list/newcards = list() + while(cards.len) + var/datum/playingcard/P = pick(cards) + P.name = replacetext(P.name," reversed","") + if(prob(50)) + P.name += " reversed" + newcards += P + cards -= P + cards = newcards + playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) + user.visible_message("\The [user] shuffles [src].") + cooldown = world.time + else + return diff --git a/sound/items/cardshuffle.ogg b/sound/items/cardshuffle.ogg new file mode 100644 index 0000000000..1fe763af5b Binary files /dev/null and b/sound/items/cardshuffle.ogg differ