Card Shark DLC - GIMMIE MY MONEY OR I BREAK YOUR KNEECAPS (#64200)

Co-authored-by: Seth Scherer <supernovaa41@gmx.com>
Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
This commit is contained in:
Tim
2022-05-02 16:56:30 -07:00
committed by GitHub
co-authored by Seth Scherer Kylerace
parent 115f4284b6
commit 22aa3566ab
37 changed files with 1112 additions and 792 deletions
+20 -20
View File
@@ -1396,22 +1396,6 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/shuttle/abandoned/medbay)
"cU" = (
/obj/effect/turf_decal/bot_white,
/obj/effect/decal/cleanable/dirt/dust,
/obj/structure/table,
/obj/item/stack/sheet/iron/fifty,
/obj/item/storage/toolbox/electrical{
pixel_x = -3;
pixel_y = 8
},
/obj/item/stock_parts/cell/high{
pixel_x = 3;
pixel_y = -1
},
/obj/effect/decal/cleanable/cobweb,
/turf/open/floor/iron/dark,
/area/shuttle/abandoned/medbay)
"cV" = (
/obj/effect/turf_decal/bot_white,
/obj/effect/decal/cleanable/dirt/dust,
@@ -1952,6 +1936,22 @@
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/shuttle/abandoned/cargo)
"Ch" = (
/obj/effect/turf_decal/bot_white,
/obj/effect/decal/cleanable/dirt/dust,
/obj/structure/table,
/obj/item/stack/sheet/iron/fifty,
/obj/item/storage/toolbox/electrical{
pixel_x = -3;
pixel_y = 8
},
/obj/item/stock_parts/cell/high{
pixel_x = 3;
pixel_y = -1
},
/obj/effect/decal/cleanable/cobweb,
/turf/open/floor/iron/dark,
/area/shuttle/abandoned/medbay)
"DZ" = (
/obj/effect/turf_decal/delivery/white,
/obj/effect/decal/cleanable/dirt/dust,
@@ -1966,7 +1966,7 @@
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/shuttle/abandoned/cargo)
"FO" = (
"IO" = (
/obj/effect/decal/cleanable/dirt/dust,
/obj/structure/table,
/obj/item/toy/cards/deck{
@@ -1974,7 +1974,7 @@
pixel_y = 12
},
/obj/item/toy/cards/cardhand{
init_cards = list("2 of Diamonds","3 of Clubs");
cards = list("2 of Diamonds","3 of Clubs");
pixel_x = -5
},
/obj/item/reagent_containers/food/drinks/bottle/beer{
@@ -2366,7 +2366,7 @@ aa
aa
aa
vm
cU
Ch
dn
vm
dS
@@ -2450,7 +2450,7 @@ cy
"}
(20,1,1) = {"
af
FO
IO
aH
bb
bu
+23 -13
View File
@@ -53,30 +53,30 @@
///this memory can be memorized by unconscious people.
#define MEMORY_SKIP_UNCONSCIOUS (1<<8)
//These defines are for what notable event happened. they correspond to the json lists related to the memory
///a memory of completing a surgery.
// These defines are for what notable event happened. they correspond to the json lists related to the memory
/// A memory of completing a surgery.
#define MEMORY_SUCCESSFUL_SURGERY "surgery"
///a memory of priming a bomb
/// A memory of priming a bomb
#define MEMORY_BOMB_PRIMED "bomb"
///a memory of pulling off either a high five or a high ten
/// A memory of pulling off either a high five or a high ten
#define MEMORY_HIGH_FIVE "highfive"
///a memory of getting borged
/// A memory of getting borged
#define MEMORY_BORGED "borged"
///a memory of dying! includes time of death
/// A memory of dying! includes time of death
#define MEMORY_DEATH "death"
///a memory of being creampied! Mentions where
/// A memory of being creampied! Mentions where
#define MEMORY_CREAMPIED "creampied"
///a memory of being slipped! Mentions on what
/// A memory of being slipped! Mentions on what
#define MEMORY_SLIPPED "slipped"
///A memory of letting my spaghetti spill, how embarrasing!
/// A memory of letting my spaghetti spill, how embarrasing!
#define MEMORY_SPAGHETTI_SPILL "spaghetti_spilled"
///A memory of getting a kiss blown. Provides the kisser and kissee.
/// A memory of getting a kiss blown. Provides the kisser and kissee.
#define MEMORY_KISS "kiss"
///A memory of a really good meal
/// A memory of a really good meal
#define MEMORY_MEAL "meal"
///A memory of a really good drink
/// A memory of a really good drink
#define MEMORY_DRINK "drink"
///A memory of being lit
/// A memory of being lit
#define MEMORY_FIRE "fire"
/// A memory of limb loss
#define MEMORY_DISMEMBERED "dismembered"
@@ -98,6 +98,11 @@
#define MEMORY_SUPERMATTER_DUSTED "supermatter_dusted"
/// Nuke ops nuke code memory
#define MEMORY_NUKECODE "nuke_code"
/// A memory of having to play 52 card pickup
#define MEMORY_PLAYING_52_PICKUP "playing_52_pickup"
/// A memory of playing cards with others
#define MEMORY_PLAYING_CARDS "playing_cards"
/**
* These are also memories, but they're examples of what I kinda don't want to be memories. They're stuff that I had to port
@@ -152,5 +157,10 @@
#define DETAIL_MEDAL_TYPE "MEDAL_TYPE"
#define DETAIL_MEDAL_REASON "MEDAL_REASON"
#define DETAIL_NUKE_CODE "NUKE_CODE"
// for cardgames
#define DETAIL_PLAYERS "PLAYERS"
#define DETAIL_CARDGAME "CARDGAME"
#define DETAIL_DEALER "DEALER"
#define DETAIL_HELD_CARD_ITEM "HELD_CARD_ITEM" // could either be a singlecard, cardhand, or a deck
@@ -354,6 +354,7 @@ GLOBAL_LIST_INIT(oddity_loot, list(//oddity: strange or crazy items
/obj/item/instrument/trombone/spectral = 1,
/obj/item/instrument/trumpet/spectral = 1,
) = 1,
/obj/item/toy/cards/deck/tarot/haunted = 1,
))
//Maintenance loot spawner pools
+1 -3
View File
@@ -309,11 +309,8 @@ GLOBAL_LIST_INIT(phobia_objs, list(
/obj/item/clothing/suit/hooded/cultrobes,
/obj/item/clothing/suit/wizrobe,
/obj/item/clothing/under/rank/civilian/chaplain,
/obj/item/clothing/under/rank/civilian/chaplain,
/obj/item/cult_bastard,
/obj/item/gun/magic/staff,
/obj/item/gun/magic/staff,
/obj/item/gun/magic/wand,
/obj/item/gun/magic/wand,
/obj/item/melee/cultblade,
/obj/item/necromantic_stone,
@@ -333,6 +330,7 @@ GLOBAL_LIST_INIT(phobia_objs, list(
/obj/narsie,
/obj/structure/destructible/cult,
/obj/structure/spirit_board,
/obj/item/toy/cards/deck/tarot,
)),
"aliens" = typecacheof(list(
@@ -370,3 +370,8 @@
description = "If I'm not good at video games, can I truly call myself a gamer?"
mood_change = -10
timeout = 10 MINUTES
/datum/mood_event/lost_52_card_pickup
description = "This is really embarrassing! I'm ashamed to pick up all these cards off the floor..."
mood_change = -3
timeout = 3 MINUTES
@@ -272,3 +272,24 @@
mood_change = 10
timeout = 5 MINUTES
/datum/mood_event/won_52_card_pickup
description = "HA! That loser will be picking cards up for a long time!"
mood_change = 3
timeout = 3 MINUTES
/datum/mood_event/playing_cards
description = "I'm enjoying playing cards with other people!"
mood_change = 2
timeout = 3 MINUTES
/datum/mood_event/playing_cards/add_effects(param)
var/card_players = 1
for(var/mob/living/carbon/player in viewers(COMBAT_MESSAGE_RANGE, owner))
var/player_has_cards = player.is_holding(/obj/item/toy/singlecard) || player.is_holding_item_of_type(/obj/item/toy/cards)
if(player_has_cards)
card_players++
if(card_players > 5)
break
mood_change *= card_players
return ..()
@@ -208,12 +208,10 @@
name = "deck spawner"
icon_state = "deck"
loot = list(
/obj/item/toy/cards/deck = 10,
/obj/item/toy/cards/deck/kotahi = 3,
/obj/item/toy/cards/deck/wizoff = 3,
/obj/item/toy/cards/deck/tarot = 2,
/obj/item/toy/cards/deck/cas = 1,
/obj/item/toy/cards/deck/cas/black = 1,
/obj/item/toy/cards/deck = 5,
/obj/item/toy/cards/deck/kotahi = 2,
/obj/item/toy/cards/deck/wizoff = 2,
/obj/item/toy/cards/deck/tarot = 1,
)
/obj/effect/spawner/random/entertainment/toy_figure
+1 -479
View File
@@ -10,7 +10,6 @@
* AI core prizes
* Toy codex gigas
* Skeleton toys
* Cards
* Toy nuke
* Fake meteor
* Foam armblade
@@ -27,14 +26,12 @@
* Fake Pierced Reality
* Intento
*/
/obj/item/toy
throwforce = 0
throw_speed = 3
throw_range = 7
force = 0
/*
* Balloons
*/
@@ -45,7 +42,6 @@
icon_state = "waterballoon-e"
inhand_icon_state = "balloon-empty"
/obj/item/toy/waterballoon/Initialize(mapload)
. = ..()
create_reagents(10)
@@ -152,7 +148,6 @@
else
return ..()
/obj/item/toy/balloon/proc/pop_balloon(monkey_pop = FALSE)
playsound(src, 'sound/effects/cartoon_pop.ogg', 50, vary = TRUE)
if(monkey_pop) // Monkeys make money from popping bloons
@@ -191,14 +186,12 @@
SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "badass_antag", /datum/mood_event/badass_antag)
. = ..()
/obj/item/toy/balloon/syndicate/Destroy()
if(ismob(loc))
var/mob/M = loc
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "badass_antag", /datum/mood_event/badass_antag)
. = ..()
/obj/item/toy/balloon/arrest
name = "arreyst balloon"
desc = "A half inflated balloon about a boyband named Arreyst that was popular about ten years ago, famous for making fun of red jumpsuits as unfashionable."
@@ -303,8 +296,6 @@
user.death(FALSE)
user.ghostize(FALSE)
/*
* Toy gun: Why isn't this an /obj/item/gun?
*/
@@ -412,7 +403,6 @@
clumsy_check = FALSE)
RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, .proc/on_transform)
/*
* Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
*
@@ -473,7 +463,6 @@
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
/obj/item/toy/windup_toolbox
name = "windup toolbox"
desc = "A replica toolbox that rumbles when you turn the key."
@@ -580,7 +569,6 @@
/*
* Snap pops
*/
/obj/item/toy/snappop
name = "snap pop"
desc = "Wow!"
@@ -733,462 +721,9 @@
phomeme = "griffin"
w_class = WEIGHT_CLASS_SMALL
/*
|| A Deck of Cards for playing various games of chance ||
*/
/obj/item/toy/cards
resistance_flags = FLAMMABLE
max_integrity = 50
///The parent deck of the cards
var/datum/weakref/parentdeck
///Artistic style of the deck
var/deckstyle = "nanotrasen"
var/card_hitsound = null
var/card_force = 0
var/card_throwforce = 0
var/card_throw_speed = 3
var/card_throw_range = 7
var/list/card_attack_verb_continuous = list("attacks")
var/list/card_attack_verb_simple = list("attack")
/obj/item/toy/cards/Initialize(mapload)
. = ..()
if(card_attack_verb_continuous)
card_attack_verb_continuous = string_list(card_attack_verb_continuous)
if(card_attack_verb_simple)
card_attack_verb_simple = string_list(card_attack_verb_simple)
/obj/item/toy/cards/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] is slitting [user.p_their()] wrists with \the [src]! It looks like [user.p_they()] [user.p_have()] a crummy hand!"))
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
return BRUTELOSS
/**
* ## apply_card_vars
*
* Applies variables for supporting multiple types of card deck
*/
/obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj)
if(!istype(sourceobj))
return
/**
* ## add_card
*
* Adds a card to the deck (or hand of cards).
*
* Arguments:
* * mob/user - The user adding the card.
* * list/cards - The list of cards the user is adding to.
* * obj/item/toy/cards/card_to_add - The card (or hand of cards) that will be added back into the deck
*/
/obj/item/toy/cards/proc/add_card(mob/user, list/cards, obj/item/toy/cards/card_to_add)
///Are we adding a hand of cards to the deck?
var/from_cardhand = FALSE
///Are we adding to a hand of cards?
var/to_cardhand = FALSE
if (istype(card_to_add, /obj/item/toy/cards/cardhand))
from_cardhand = TRUE
if (istype(src, /obj/item/toy/cards/cardhand))
to_cardhand = TRUE
if ((card_to_add.parentdeck != src.parentdeck) && (card_to_add.parentdeck != WEAKREF(src)))
to_chat(user, span_warning("You can't mix cards from other decks!"))
return
if (!user.temporarilyRemoveItemFromInventory(card_to_add))
to_chat(user, span_warning("The [from_cardhand ? "hand of cards" : "card"] is stuck to your hand, you can't add it to [to_cardhand ? "your hand" : "the deck"]!"))
return
if (from_cardhand)
var/obj/item/toy/cards/cardhand/cards_to_add = card_to_add
for (var/obj/item/toy/cards/singlecard/card in cards_to_add.cards)
card.loc = src
cards += card
else
var/obj/item/toy/cards/singlecard/card = card_to_add
card.loc = src
cards += card
user.visible_message(span_notice("[user] adds [from_cardhand ? "the hand of cards" : "a card"] to [to_cardhand ? "[user.p_their()] hand" : "the bottom of the deck"]."), span_notice("You add the [from_cardhand ? "hand of cards" : "card"] to [to_cardhand ? "your hand" : "the bottom of the deck"]."))
update_appearance()
/**
* ## draw_card
*
* Draws a card from the deck (or hand of cards).
*
* Arguments:
* * mob/user - The user drawing from the deck.
* * list/cards - The list of cards the user is drawing from.
* * obj/item/toy/cards/singlecard/forced_card (optional) - Used to force the card drawn from the deck
*/
/obj/item/toy/cards/proc/draw_card(mob/user, list/cards, obj/item/toy/cards/singlecard/forced_card = null)
if(isliving(user))
var/mob/living/living_user = user
if(!(living_user.mobility_flags & MOBILITY_PICKUP))
return
if(cards.len == 0)
to_chat(user, span_warning("There are no more cards to draw!"))
return
///Are we drawing from a hand of cards?
var/from_cardhand = FALSE
if (istype(src, /obj/item/toy/cards/cardhand))
from_cardhand = TRUE
var/obj/item/toy/cards/singlecard/card_to_draw
if (forced_card)
card_to_draw = forced_card
else
card_to_draw = cards[1]
cards -= card_to_draw
card_to_draw.pickup(user)
user.put_in_hands(card_to_draw)
user.visible_message(span_notice("[user] draws a card from [from_cardhand ? "[user.p_their()] hand" : "the deck"]."), span_notice("You draw a card from [from_cardhand ? "your hand" : "the deck"]."))
update_appearance()
return card_to_draw
/obj/item/toy/cards/deck
name = "deck of cards"
desc = "A deck of space-grade playing cards."
icon = 'icons/obj/toy.dmi'
deckstyle = "nanotrasen"
icon_state = "deck_nanotrasen_full"
worn_icon_state = "card"
w_class = WEIGHT_CLASS_SMALL
///Deck shuffling cooldown.
COOLDOWN_DECLARE(shuffle_cooldown)
///Tracks holodeck cards, since they shouldn't be infinite
var/obj/machinery/computer/holodeck/holo = null
///Cards in this deck
var/list/cards = list()
/obj/item/toy/cards/deck/Initialize(mapload)
. = ..()
AddElement(/datum/element/drag_pickup)
populate_deck()
/**
* ## generate_card
*
* Generates a new playing card, and assigns all of the necessary variables.
*
* Arguments:
* * name - The name of the playing card.
*/
/obj/item/toy/cards/deck/proc/generate_card(name)
var/obj/item/toy/cards/singlecard/card_to_add = new/obj/item/toy/cards/singlecard()
if(holo)
holo.spawned += card_to_add
card_to_add.cardname = name
card_to_add.parentdeck = WEAKREF(src)
card_to_add.apply_card_vars(card_to_add, src)
return card_to_add
/**
* ## populate_deck
*
* Generates all the cards within the deck.
*/
/obj/item/toy/cards/deck/proc/populate_deck()
icon_state = "deck_[deckstyle]_full"
for(var/suit in list("Hearts", "Spades", "Clubs", "Diamonds"))
cards += generate_card("Ace of [suit]")
for(var/i in 2 to 10)
cards += generate_card("[i] of [suit]")
for(var/person in list("Jack", "Queen", "King"))
cards += generate_card("[person] of [suit]")
/obj/item/toy/cards/deck/attack_hand(mob/living/user, list/modifiers)
if (!user.combat_mode)
draw_card(user, cards)
else
return ..()
/obj/item/toy/cards/deck/update_icon_state()
switch(cards.len)
if(27 to INFINITY)
icon_state = "deck_[deckstyle]_full"
if(11 to 27)
icon_state = "deck_[deckstyle]_half"
if(1 to 11)
icon_state = "deck_[deckstyle]_low"
else
icon_state = "deck_[deckstyle]_empty"
return ..()
#define DECK_SHUFFLE_COOLDOWN 5 SECONDS
/obj/item/toy/cards/deck/attack_self(mob/user)
if(!COOLDOWN_FINISHED(src, shuffle_cooldown))
return
COOLDOWN_START(src, shuffle_cooldown, DECK_SHUFFLE_COOLDOWN)
cards = shuffle(cards)
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
user.visible_message(span_notice("[user] shuffles the deck."), span_notice("You shuffle the deck."))
#undef DECK_SHUFFLE_COOLDOWN
/obj/item/toy/cards/deck/attackby(obj/item/item, mob/living/user, params)
if(istype(item, /obj/item/toy/cards/singlecard) || istype(item, /obj/item/toy/cards/cardhand))
add_card(user, cards, item)
else
return ..()
/obj/item/toy/cards/cardhand
name = "hand of cards"
desc = "A number of cards not in a deck, customarily held in ones hand."
icon = 'icons/obj/toy.dmi'
icon_state = "none"
worn_icon_state = "card"
w_class = WEIGHT_CLASS_TINY
///Cards in this hand of cards.
var/list/cards = list()
///List of cards to add into the hand on initialization (used for mapping mostly)
var/list/init_cards = list()
/obj/item/toy/cards/cardhand/Initialize()
. = ..()
if (init_cards.len > 0)
for (var/card in init_cards)
var/obj/item/toy/cards/singlecard/new_card = new /obj/item/toy/cards/singlecard(src)
new_card.cardname = card
new_card.Flip()
cards += new_card
update_sprite()
/obj/item/toy/cards/cardhand/add_card(mob/user, list/cards, obj/item/toy/cards/card_to_add)
. = ..()
interact(user)
update_sprite()
/obj/item/toy/cards/cardhand/attack_self(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/human_user = user
if(!(human_user.mobility_flags & MOBILITY_USE))
return
if(user.stat || !ishuman(user))
return
interact(user)
var/list/handradial = list()
for(var/obj/item/toy/cards/singlecard/card in cards)
handradial[card] = image(icon = src.icon, icon_state = "sc_[card.name]_[deckstyle]")
var/obj/item/toy/cards/singlecard/choice = show_radial_menu(usr, src, handradial, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
draw_card(user, cards, choice)
interact(user)
if(length(cards) == 1)
var/obj/item/toy/cards/singlecard/last_card = draw_card(user, cards)
qdel(src)
last_card.pickup(user)
user.put_in_hands(last_card)
to_chat(user, span_notice("You also take [last_card.cardname] and hold it."))
else
update_sprite()
/obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/card, mob/living/user, params)
if(istype(card))
if (!card.flipped)
card.Flip() // flip so that the card appears properly in the hand
add_card(user, cards, card)
else
return ..()
/obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj)
..()
newobj.deckstyle = sourceobj.deckstyle
update_sprite()
newobj.card_hitsound = sourceobj.card_hitsound
newobj.card_force = sourceobj.card_force
newobj.card_throwforce = sourceobj.card_throwforce
newobj.card_throw_speed = sourceobj.card_throw_speed
newobj.card_throw_range = sourceobj.card_throw_range
newobj.card_attack_verb_continuous = sourceobj.card_attack_verb_continuous //null or unique list made by string_list()
newobj.card_attack_verb_simple = sourceobj.card_attack_verb_simple //null or unique list made by string_list()
newobj.resistance_flags = sourceobj.resistance_flags
/**
* ## check_menu
*
* Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user - The mob interacting with a menu
*/
/obj/item/toy/cards/cardhand/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
return TRUE
/**
* ## update_sprite
*
* This proc updates the sprite for when you create a hand of cards
*/
/obj/item/toy/cards/cardhand/proc/update_sprite()
cut_overlays()
var/overlay_cards = cards.len
var/k = overlay_cards == 2 ? 1 : overlay_cards - 2
for(var/i = k; i <= overlay_cards; i++)
var/obj/item/toy/cards/singlecard/card = cards[i]
var/card_overlay = image(icon = src.icon, icon_state = "sc_[card.cardname]_[deckstyle]", pixel_x = (1 - i + k) * 3, pixel_y = (1 - i + k) * 3)
add_overlay(card_overlay)
/obj/item/toy/cards/singlecard
name = "card"
desc = "A playing card used to play card games like poker."
icon = 'icons/obj/toy.dmi'
icon_state = "singlecard_down_nanotrasen"
worn_icon_state = "card"
w_class = WEIGHT_CLASS_TINY
pixel_x = -5
///The name of the card
var/cardname = null
///is the card facedown (F), or faceup (T)?
var/flipped = FALSE
/obj/item/toy/cards/singlecard/examine(mob/user)
. = ..()
if(ishuman(user))
var/mob/living/carbon/human/cardUser = user
if(cardUser.is_holding(src))
cardUser.visible_message(span_notice("[cardUser] checks [cardUser.p_their()] card."), span_notice("The card reads: [cardname]."))
else
. += span_warning("You need to have the card in your hand to check it!")
/**
* ## Flip
*
* flips the card over
*/
/obj/item/toy/cards/singlecard/verb/Flip()
set name = "Flip Card"
set category = "Object"
set src in range(1)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(!flipped)
src.flipped = TRUE
if (cardname)
src.icon_state = "sc_[cardname]_[deckstyle]"
src.name = src.cardname
else
src.icon_state = "sc_Ace of Spades_[deckstyle]"
src.name = "What Card"
src.pixel_x = 5
else if(flipped)
src.flipped = FALSE
src.icon_state = "singlecard_down_[deckstyle]"
src.name = "card"
src.pixel_x = -5
/**
* ## do_cardhand
*
* Creates, or adds to an existing hand of cards
*
* Arguments:
* * mob/living/user - the user
* * list/cards - the list of cards being added together (/obj/item/toy/cards/singlecard)
* * obj/item/toy/cards/cardhand/given_hand (optional) - the cardhand to add said cards into
*/
/obj/item/toy/cards/singlecard/proc/do_cardhand(mob/living/user, list/cards, obj/item/toy/cards/cardhand/given_hand = null)
if (given_hand && (given_hand?.parentdeck != parentdeck))
to_chat(user, span_warning("You can't mix cards from other decks!"))
return
for (var/obj/item/toy/cards/singlecard/card in cards)
if (card.parentdeck != parentdeck)
to_chat(user, span_warning("You can't mix cards from other decks!"))
return
var/obj/item/toy/cards/cardhand/new_cardhand = given_hand
var/preexisting = TRUE // does the cardhand already exist, or are we making a new one
if (!new_cardhand)
preexisting = FALSE
new_cardhand = new /obj/item/toy/cards/cardhand(user.loc)
for (var/obj/item/toy/cards/singlecard/card in cards)
user.dropItemToGround(card) // drop them all so the loc will properly update
if (!card.flipped)
card.Flip() // flip so the card shows up in the cardhand properly
new_cardhand.cards += card
if (preexisting)
new_cardhand.interact(user)
new_cardhand.update_sprite()
user.visible_message(span_notice("[user] adds a card to [user.p_their()] hand."), span_notice("You add the [cardname] to your hand."))
else
new_cardhand.parentdeck = parentdeck
new_cardhand.apply_card_vars(new_cardhand, src)
to_chat(user, span_notice("You combine the cards into a hand."))
new_cardhand.pickup(user)
user.put_in_active_hand(new_cardhand)
for (var/obj/item/toy/cards/singlecard/card in cards)
card.loc = new_cardhand // move the cards into the cardhand
/obj/item/toy/cards/singlecard/attackby(obj/item/item, mob/living/user, params)
if(istype(item, /obj/item/toy/cards/singlecard/))
do_cardhand(user, list(src, item))
if(istype(item, /obj/item/toy/cards/cardhand/))
do_cardhand(user, list(src), item)
else
return ..()
/obj/item/toy/cards/singlecard/attack_self(mob/living/carbon/human/user)
if(!ishuman(user) || !(user.mobility_flags & MOBILITY_USE))
return
Flip()
/obj/item/toy/cards/singlecard/apply_card_vars(obj/item/toy/cards/singlecard/newobj,obj/item/toy/cards/sourceobj)
..()
newobj.deckstyle = sourceobj.deckstyle
newobj.icon_state = "singlecard_down_[deckstyle]" // Without this the card is invisible until flipped. It's an ugly hack, but it works.
newobj.card_hitsound = sourceobj.card_hitsound
newobj.hitsound = newobj.card_hitsound
newobj.card_force = sourceobj.card_force
newobj.force = newobj.card_force
newobj.card_throwforce = sourceobj.card_throwforce
newobj.throwforce = newobj.card_throwforce
newobj.card_throw_speed = sourceobj.card_throw_speed
newobj.throw_speed = newobj.card_throw_speed
newobj.card_throw_range = sourceobj.card_throw_range
newobj.throw_range = newobj.card_throw_range
newobj.attack_verb_continuous = newobj.card_attack_verb_continuous = sourceobj.card_attack_verb_continuous //null or unique list made by string_list()
newobj.attack_verb_simple = newobj.card_attack_verb_simple = sourceobj.card_attack_verb_simple //null or unique list made by string_list()
/*
|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. ||
*/
/obj/item/toy/cards/deck/syndicate
name = "suspicious looking deck of cards"
desc = "A deck of space-grade playing cards. They seem unusually rigid."
icon_state = "deck_syndicate_full"
deckstyle = "syndicate"
card_hitsound = 'sound/weapons/bladeslice.ogg'
card_force = 5
card_throwforce = 10
card_throw_speed = 3
card_throw_range = 7
card_attack_verb_continuous = list("attacks", "slices", "dices", "slashes", "cuts")
card_attack_verb_simple = list("attack", "slice", "dice", "slash", "cut")
resistance_flags = NONE
/*
* Fake nuke
*/
/obj/item/toy/nuke
name = "\improper Nuclear Fission Explosive toy"
desc = "A plastic model of a Nuclear Fission Explosive."
@@ -1222,16 +757,15 @@
to_chat(user, span_alert("Nothing happens, and '</span>[round(timeleft/10)]<span class='alert'>' appears on the small display."))
sleep(5)
/obj/item/toy/nuke/emag_act(mob/user)
if (obj_flags & EMAGGED)
return
to_chat(user, span_warning("You short-circuit \the [src]."))
obj_flags |= EMAGGED
/*
* Fake meteor
*/
/obj/item/toy/minimeteor
name = "\improper Mini-Meteor"
desc = "Relive the excitement of a meteor shower! SweetMeat-eor Co. is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor."
@@ -1286,7 +820,6 @@
/*
* Snowballs
*/
/obj/item/toy/snowball
name = "snowball"
desc = "A compact ball of snow. Good for throwing at people."
@@ -1322,7 +855,6 @@
/*
* Clockwork Watch
*/
/obj/item/toy/clockwork_watch
name = "steampunk watch"
desc = "A stylish steampunk watch made out of thousands of tiny cogwheels."
@@ -1348,7 +880,6 @@
/*
* Toy Dagger
*/
/obj/item/toy/toy_dagger
name = "toy dagger"
desc = "A cheap plastic replica of a dagger. Produced by THE ARM Toys, Inc."
@@ -1362,7 +893,6 @@
/*
* Xenomorph action figure
*/
/obj/item/toy/toy_xeno
icon = 'icons/obj/toy.dmi'
icon_state = "toy_xeno"
@@ -1387,7 +917,6 @@
return
// TOY MOUSEYS :3 :3 :3
/obj/item/toy/cattoy
name = "toy mouse"
desc = "A colorful toy mouse!"
@@ -1401,7 +930,6 @@
/*
* Action Figures
*/
/obj/item/toy/figure
name = "\improper Non-Specific Action Figure action figure"
icon = 'icons/obj/toy.dmi'
@@ -1624,7 +1152,6 @@
icon_state = "warden"
toysay = "Seventeen minutes for coughing at an officer!"
/obj/item/toy/dummy
name = "ventriloquist dummy"
desc = "It's a dummy, dummy."
@@ -1697,11 +1224,9 @@
cooldown = (world.time + 10)
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/effects/blobattack.ogg', 50, FALSE), 0.5 SECONDS)
/*
* Eldritch Toys
*/
/obj/item/toy/eldritch_book
name = "Codex Cicatrix"
desc = "A toy book that closely resembles the Codex Cicatrix. Covered in fake polyester human flesh and has a huge goggly eye attached to the cover. The runes are gibberish and cannot be used to summon demons... Hopefully?"
@@ -1724,7 +1249,6 @@
/*
* Fake tear
*/
/obj/item/toy/reality_pierce
name = "Pierced reality"
desc = "Hah. You thought it was the real deal!"
@@ -1795,7 +1319,6 @@ GLOBAL_LIST_EMPTY(intento_players)
#define TIME_PER_DEMO_STEP 0.6 SECONDS
#define TIME_TO_RESET_ICON 0.5 SECONDS
/obj/item/toy/intento
name = "\improper Intento"
desc = "Fundamentally useless for all intentsive purposes."
@@ -1877,7 +1400,6 @@ GLOBAL_LIST_EMPTY(intento_players)
state = STATE_STARTING
COOLDOWN_START(src, next_process, TIME_TO_BEGIN)
/obj/item/toy/intento/process()
if(next_icon_reset && next_icon_reset <= world.time)
icon_state = initial(icon_state)
+30 -2
View File
@@ -60,6 +60,7 @@
)
AddElement(/datum/element/contextual_screentip_tools, tool_behaviors)
register_context()
/obj/structure/table/examine(mob/user)
. = ..()
@@ -114,11 +115,9 @@
user.stop_pulling()
return ..()
/obj/structure/table/attack_tk(mob/user)
return
/obj/structure/table/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
if(.)
@@ -215,6 +214,14 @@
return
// If the tray IS empty, continue on (tray will be placed on the table like other items)
if(istype(I, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = I
if(dealer_deck.wielded) // deal a card facedown on the table
var/obj/item/toy/singlecard/card = dealer_deck.draw(user)
if(card)
attackby(card, user, params)
return
if(istype(I, /obj/item/riding_offhand))
var/obj/item/riding_offhand/riding_item = I
var/mob/living/carried_mob = riding_item.rider
@@ -252,6 +259,27 @@
else
return ..()
/obj/structure/table/attackby_secondary(obj/item/weapon, mob/user, params)
if(istype(weapon, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = weapon
if(dealer_deck.wielded) // deal a card faceup on the table
var/obj/item/toy/singlecard/card = dealer_deck.draw(user)
if(card)
card.Flip()
attackby(card, user, params)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
..()
return SECONDARY_ATTACK_CONTINUE_CHAIN
/obj/structure/table/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(istype(held_item, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = held_item
if(dealer_deck.wielded)
context[SCREENTIP_CONTEXT_LMB] = "Deal card"
context[SCREENTIP_CONTEXT_RMB] = "Deal card faceup"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/obj/structure/table/proc/AfterPutItemOnTable(obj/item/I, mob/living/user)
return
+143
View File
@@ -0,0 +1,143 @@
/obj/item/toy/cards/cardhand
name = "hand of cards"
desc = "A number of cards not in a deck, customarily held in ones hand."
icon = 'icons/obj/playing_cards.dmi'
icon_state = "none"
w_class = WEIGHT_CLASS_TINY
worn_icon_state = "card"
/obj/item/toy/cards/cardhand/Initialize(mapload, list/cards_to_combine)
. = ..()
if(!LAZYLEN(cards_to_combine) && (mapload && !LAZYLEN(cards)))
CRASH("[src] is being made into a cardhand without a list of cards to combine")
if(mapload && LAZYLEN(cards)) // these cards have not been initialized
for(var/card_name in cards)
var/obj/item/toy/singlecard/new_card = new (loc, card_name)
new_card.update_appearance()
cards_to_combine += new_card
cards = list() // reset our cards to an empty list
for(var/obj/item/toy/singlecard/new_card in cards_to_combine)
new_card.forceMove(src)
cards += new_card
register_context()
update_appearance()
/obj/item/toy/cards/cardhand/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] is slitting [user.p_their()] wrists with \the [src]! It looks like [user.p_they()] [user.p_have()] a crummy hand!"))
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
return BRUTELOSS
/obj/item/toy/cards/cardhand/examine(mob/user)
. = ..()
for(var/obj/item/toy/singlecard/card in cards)
if(HAS_TRAIT(user, TRAIT_XRAY_VISION))
. += span_notice("You scan the cardhand with your x-ray vision and there is a: [card.cardname]")
var/marked_color = card.getMarkedColor(user)
if(marked_color)
. += span_notice("There is a [marked_color] mark on the corner of a card in the cardhand!")
/obj/item/toy/cards/cardhand/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(istype(held_item, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = held_item
if(dealer_deck.wielded)
context[SCREENTIP_CONTEXT_LMB] = "Deal card"
context[SCREENTIP_CONTEXT_RMB] = "Deal card faceup"
return CONTEXTUAL_SCREENTIP_SET
context[SCREENTIP_CONTEXT_LMB] = "Recycle cards"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/singlecard))
context[SCREENTIP_CONTEXT_LMB] = "Combine cards"
context[SCREENTIP_CONTEXT_RMB] = "Combine cards faceup"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/obj/item/toy/cards/cardhand/attack_self(mob/living/user)
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK))
return
var/list/handradial = list()
for(var/obj/item/toy/singlecard/card in cards)
handradial[card] = image(icon = src.icon, icon_state = card.icon_state)
var/obj/item/toy/singlecard/choice = show_radial_menu(usr, src, handradial, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
var/obj/item/toy/singlecard/selected_card = draw(user, choice)
selected_card.pickup(user)
user.put_in_hands(selected_card)
if(cards.len == 1)
user.temporarilyRemoveItemFromInventory(src, TRUE)
var/obj/item/toy/singlecard/last_card = draw(user)
last_card.pickup(user)
user.put_in_hands(last_card)
qdel(src) // cardhand is empty now so delete it
/obj/item/toy/cards/cardhand/proc/check_menu(mob/living/user)
return isliving(user) && !user.incapacitated()
/obj/item/toy/cards/cardhand/attackby(obj/item/weapon, mob/living/user, params, flip_card = FALSE)
var/obj/item/toy/singlecard/card
if(istype(weapon, /obj/item/toy/singlecard))
card = weapon
if(istype(weapon, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = weapon
if(!dealer_deck.wielded) // recycle cardhand into deck (if unwielded)
dealer_deck.insert(src)
user.balloon_alert_to_viewers("puts card in deck")
return
card = dealer_deck.draw(user)
if(card)
if(flip_card)
card.Flip()
insert(card)
return
return ..()
/obj/item/toy/cards/cardhand/attackby_secondary(obj/item/weapon, mob/user, params)
attackby(weapon, user, params, flip_card = TRUE)
return SECONDARY_ATTACK_CONTINUE_CHAIN
#define CARDS_MAX_DISPLAY_LIMIT 5 // the amount of cards that are displayed in a hand
#define CARDS_PIXEL_X_OFFSET -5 // start out displaying the 1st card -5 pixels left
#define CARDS_ANGLE_OFFSET -45 // start out displaying the 1st card -45 degrees counter clockwise
/obj/item/toy/cards/cardhand/update_overlays()
. = ..()
cut_overlays()
if(cards.len <= 1)
icon_state = null // we want an error icon to appear if this doesn't get qdel
return
var/starting_card_pos = max(1, cards.len - CARDS_MAX_DISPLAY_LIMIT) // only display the top cards in the cardhand
var/cards_to_display = min(CARDS_MAX_DISPLAY_LIMIT, cards.len)
// 90 degrees from the 1st card to the last, so split the divider by total cards displayed
var/angle_divider = round(90/(cards_to_display - 1))
// 10 pixels from the 1st card to the last, so split the divider by total cards displayed
var/pixel_divider = round(10/(cards_to_display - 1))
// starting from the 1st card to last, we want to slowly increase the angle and pixel_x offset
// to spread the cards out using our dividers
for(var/i in 0 to cards_to_display - 1)
var/obj/item/toy/singlecard/card = cards[starting_card_pos + i]
var/image/card_overlay = image(icon, icon_state = card.icon_state, pixel_x = CARDS_PIXEL_X_OFFSET + (i * pixel_divider))
var/rotation_angle = CARDS_ANGLE_OFFSET + (i * angle_divider)
var/matrix/M = matrix()
M.Turn(rotation_angle)
card_overlay.transform = M
add_overlay(card_overlay)
#undef CARDS_MAX_DISPLAY_LIMIT
#undef CARDS_PIXEL_X_OFFSET
#undef CARDS_ANGLE_OFFSET
+114
View File
@@ -0,0 +1,114 @@
/*
** The base card class that is used by decks and cardhands
*/
/obj/item/toy/cards
resistance_flags = FLAMMABLE
max_integrity = 50
/// Do all the cards drop to the floor when thrown at a person
var/can_play_52_card_pickup = TRUE
/// List of cards for a hand or deck
var/list/cards = list()
/obj/item/toy/cards/Destroy()
if(LAZYLEN(cards))
QDEL_LIST(cards)
return ..()
/// This is how we play 52 card pickup
/obj/item/toy/cards/throw_impact(mob/living/target, datum/thrownthing/throwingdatum)
. = ..()
if(. || !istype(target)) // was it caught or is the target not a living mob
return .
if(!throwingdatum?.thrower) // if a mob didn't throw it (need two people to play 52 pickup)
return
var/has_no_cards = !LAZYLEN(cards)
if(has_no_cards)
return
for(var/obj/item/toy/singlecard/card in cards)
cards -= card
card.forceMove(target.drop_location())
if(prob(50))
card.Flip()
card.pixel_x = rand(-16, 16)
card.pixel_y = rand(-16, 16)
var/matrix/Matrix = matrix()
var/angle = pick(0, 90, 180, 270)
Matrix.Turn(angle)
card.transform = Matrix
card.update_appearance()
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
if(istype(src, /obj/item/toy/cards/cardhand))
qdel(src)
return
update_appearance()
/**
* This is used to insert a list of cards into a deck or cardhand
*
* All cards that are inserted have their angle and pixel offsets reset to zero however their
* flip state does not change unless it's being inserted into a deck which is always facedown
* (see the deck/insert proc)
*
* Arguments:
* * card_item - Either a singlecard or cardhand that gets inserted into the src
*/
/obj/item/toy/cards/proc/insert(obj/item/toy/card_item)
var/cards_to_add = list()
var/obj/item/toy/cards/cardhand/recycled_cardhand
if(istype(card_item, /obj/item/toy/singlecard))
cards_to_add += card_item
if(istype(card_item, /obj/item/toy/cards/cardhand))
recycled_cardhand = card_item
for(var/obj/item/toy/singlecard/card in recycled_cardhand.cards)
cards_to_add += card
recycled_cardhand.cards -= card
card.moveToNullspace()
qdel(recycled_cardhand)
for(var/obj/item/toy/singlecard/card in cards_to_add)
card.forceMove(src)
// reset the position and angle
card.pixel_x = 0
card.pixel_y = 0
var/matrix/M = matrix()
M.Turn(0)
card.transform = M
card.update_appearance()
cards += card
cards_to_add -= card
update_appearance()
/**
* Draws a card from the deck or hand of cards.
*
* Draws the top card unless a card arg is supplied then it picks that specific card
* and returns it (the card arg is used by the radial menu for cardhands to select
* specific cards out of the cardhand)
* Arguments:
* * mob/living/user - The user drawing the card.
* * obj/item/toy/singlecard/card (optional) - The card drawn from the hand
**/
/obj/item/toy/cards/proc/draw(mob/living/user, obj/item/toy/singlecard/card)
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK))
return
var/has_no_cards = !LAZYLEN(cards)
if(has_no_cards)
to_chat(user, span_warning("There are no more cards to draw!"))
return
card = card || cards[1] //draw the card on top
cards -= card
update_appearance()
playsound(src, 'sound/items/cardflip.ogg', 50, TRUE)
return card
+21
View File
@@ -0,0 +1,21 @@
/obj/item/toy/cards/deck/blank
name = "custom deck of cards"
desc = "A deck of playing cards that can be customized with writing."
cardgame_desc = "custom card game"
icon_state = "deck_white_full"
deckstyle = "white"
has_unique_card_icons = FALSE
is_standard_deck = FALSE
decksize = 25
can_play_52_card_pickup = FALSE
/obj/item/toy/cards/deck/blank/black
icon_state = "deck_black_full"
deckstyle = "black"
/obj/item/toy/cards/deck/blank/Initialize(mapload)
. = ..()
for(var/i in 1 to decksize)
var/obj/item/toy/singlecard/blank_card = new (src, "blank card", src)
blank_card.blank = TRUE
cards += blank_card
+38
View File
@@ -0,0 +1,38 @@
// CARDS AGAINST SPESS
// This is a parody of Cards Against Humanity (https://en.wikipedia.org/wiki/Cards_Against_Humanity)
// which is licensed under CC BY-NC-SA 2.0, the full text of which can be found at the following URL:
// https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode
// Original code by Zuhayr, Polaris Station, ported with modifications
/obj/item/toy/cards/deck/cas
name = "\improper CAS deck (white)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the white deck."
cardgame_desc = "Cards Against Spess game"
icon_state = "deck_white_full"
deckstyle = "white"
has_unique_card_icons = FALSE
is_standard_deck = FALSE
decksize = 150
can_play_52_card_pickup = FALSE
/obj/item/toy/cards/deck/cas/black
name = "\improper CAS deck (black)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the black deck."
icon_state = "deck_black_full"
deckstyle = "black"
decksize = 50
GLOBAL_LIST_INIT(card_decks, list(
black = world.file2list("strings/cas_black.txt"),
white = world.file2list("strings/cas_white.txt")
))
/obj/item/toy/cards/deck/cas/Initialize(mapload)
. = ..()
var/list/cards_against_space = GLOB.card_decks[deckstyle]
var/list/possible_cards = cards_against_space.Copy()
var/list/random_cards = list()
for(var/i in 1 to decksize)
random_cards += pick_n_take(possible_cards)
for(var/card in random_cards)
cards += new /obj/item/toy/singlecard(src, card, src)
+246
View File
@@ -0,0 +1,246 @@
#define DECK_SHUFFLE_TIME (5 SECONDS)
#define DECK_SYNDIE_SHUFFLE_TIME (3 SECONDS)
/obj/item/toy/cards/deck
name = "deck of cards"
desc = "A deck of space-grade playing cards."
icon = 'icons/obj/playing_cards.dmi'
icon_state = "deck_nanotrasen_full"
w_class = WEIGHT_CLASS_SMALL
worn_icon_state = "card"
hitsound = null
attack_verb_continuous = list("attacks")
attack_verb_simple = list("attack")
/// The amount of time it takes to shuffle
var/shuffle_time = DECK_SHUFFLE_TIME
/// Deck shuffling cooldown.
COOLDOWN_DECLARE(shuffle_cooldown)
/// If the deck is the standard 52 playing card deck (used for poker and blackjack)
var/is_standard_deck = TRUE
/// The amount of cards to spawn in the deck (optional)
var/decksize = INFINITY
/// The description of the cardgame that is played with this deck (used for memories)
var/cardgame_desc = "card game"
/// Wielding status for holding with two hands
var/wielded = FALSE
/// The holodeck computer used to spawn a holographic deck (see /obj/item/toy/cards/deck/syndicate/holographic)
var/obj/machinery/computer/holodeck/holodeck
/// If the cards in the deck have different card faces icons (blank and CAS decks do not)
var/has_unique_card_icons = TRUE
/// The art style of deck used (determines both deck and card icons used)
var/deckstyle = "nanotrasen"
/obj/item/toy/cards/deck/Initialize(mapload)
. = ..()
AddElement(/datum/element/drag_pickup)
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
AddComponent(/datum/component/two_handed, attacksound='sound/items/cardflip.ogg')
register_context()
if(!is_standard_deck)
return
// generate a normal playing card deck
cards += new /obj/item/toy/singlecard(src, "Joker Clown", src)
cards += new /obj/item/toy/singlecard(src, "Joker Mime", src)
for(var/suit in list("Hearts", "Spades", "Clubs", "Diamonds"))
cards += new /obj/item/toy/singlecard(src, "Ace of [suit]", src)
for(var/i in 2 to 10)
cards += new /obj/item/toy/singlecard(src, "[i] of [suit]", src)
for(var/person in list("Jack", "Queen", "King"))
cards += new /obj/item/toy/singlecard(src, "[person] of [suit]", src)
/// triggered on wield of two handed item
/obj/item/toy/cards/deck/proc/on_wield(obj/item/source, mob/user)
SIGNAL_HANDLER
wielded = TRUE
/// triggered on unwield of two handed item
/obj/item/toy/cards/deck/proc/on_unwield(obj/item/source, mob/user)
SIGNAL_HANDLER
wielded = FALSE
/obj/item/toy/cards/deck/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] is slitting [user.p_their()] wrists with \the [src]! It looks like their luck ran out!"))
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
return BRUTELOSS
/obj/item/toy/cards/deck/examine(mob/user)
. = ..()
if(cards.len > 0)
var/obj/item/toy/singlecard/card = cards[1]
if(HAS_TRAIT(user, TRAIT_XRAY_VISION))
. += span_notice("You scan the deck with your x-ray vision and the top card reads: [card.cardname].")
var/marked_color = card.getMarkedColor(user)
if(marked_color)
. += span_notice("The top card of the deck has a [marked_color] mark on the corner!")
. += span_notice("Click and drag the deck to yourself to pickup.") // This should be a context screentip
/obj/item/toy/cards/deck/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(src == held_item)
var/obj/item/toy/cards/deck/dealer_deck = held_item
context[SCREENTIP_CONTEXT_LMB] = dealer_deck.wielded ? "Recycle mode" : "Dealer mode"
context[SCREENTIP_CONTEXT_ALT_LMB] = "Shuffle"
return CONTEXTUAL_SCREENTIP_SET
if(isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "Draw card"
context[SCREENTIP_CONTEXT_RMB] = "Draw card faceup"
// add drag & drop screentip here in the future
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/singlecard))
context[SCREENTIP_CONTEXT_LMB] = "Recycle card"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/cards/cardhand))
context[SCREENTIP_CONTEXT_LMB] = "Recycle cards"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/**
* Shuffles the cards in the deck
*
* Arguments:
* * user - The person shuffling the cards.
*/
/obj/item/toy/cards/deck/proc/shuffle_cards(mob/living/user)
if(!COOLDOWN_FINISHED(src, shuffle_cooldown))
return
COOLDOWN_START(src, shuffle_cooldown, shuffle_time)
cards = shuffle(cards)
playsound(src, 'sound/items/cardshuffle.ogg', 50, TRUE)
user.balloon_alert_to_viewers("shuffles the deck")
addtimer(CALLBACK(src, .proc/CardgameEvent, user), 60 SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE)
/// This checks if nearby mobs are playing a cardgame and triggers a mood and memory
/obj/item/toy/cards/deck/proc/CardgameEvent(mob/living/dealer)
var/card_players = list()
for(var/mob/living/carbon/person in viewers(loc, COMBAT_MESSAGE_RANGE))
var/obj/item/toy/held_card_item = person.is_holding_item_of_type(/obj/item/toy/singlecard) || person.is_holding_item_of_type(/obj/item/toy/cards/deck) || person.is_holding_item_of_type(/obj/item/toy/cards/cardhand)
if(held_card_item)
card_players[person] = held_card_item
if(length(card_players) >= 2) // need at least 2 people to play a cardgame, duh!
for(var/mob/living/carbon/player in card_players)
var/other_players = english_list(card_players - player)
var/obj/item/toy/held_card_item = card_players[player]
SEND_SIGNAL(player, COMSIG_ADD_MOOD_EVENT, "playing_cards", /datum/mood_event/playing_cards)
player.mind?.add_memory(
MEMORY_PLAYING_CARDS,
list(
DETAIL_PROTAGONIST = player,
DETAIL_PLAYERS = other_players,
DETAIL_CARDGAME = cardgame_desc,
DETAIL_DEALER = dealer,
DETAIL_HELD_CARD_ITEM = held_card_item,
),
story_value = STORY_VALUE_OKAY,
memory_flags = MEMORY_CHECK_BLINDNESS
)
/obj/item/toy/cards/deck/attack_hand(mob/living/user, list/modifiers, flip_card = FALSE)
if(!ishuman(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK, !iscyborg(user)))
return
var/obj/item/toy/singlecard/card = draw(user)
if(!card)
return
if(flip_card)
card.Flip()
card.pickup(user)
user.put_in_hands(card)
user.balloon_alert_to_viewers("draws a card")
/obj/item/toy/cards/deck/attack_hand_secondary(mob/living/user, list/modifiers)
attack_hand(user, modifiers, flip_card = TRUE)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/item/toy/cards/deck/AltClick(mob/living/user)
if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK, !iscyborg(user)))
if(wielded)
shuffle_cards(user)
else
to_chat(user, span_notice("You must hold the [src] with both hands to shuffle."))
return ..()
/obj/item/toy/cards/deck/update_icon_state()
switch(cards.len)
if(27 to INFINITY)
icon_state = "deck_[deckstyle]_full"
if(11 to 27)
icon_state = "deck_[deckstyle]_half"
if(1 to 11)
icon_state = "deck_[deckstyle]_low"
else
icon_state = "deck_[deckstyle]_empty"
return ..()
/obj/item/toy/cards/deck/insert(obj/item/toy/card_item)
// any card inserted into the deck is always facedown
if(istype(card_item, /obj/item/toy/singlecard))
var/obj/item/toy/singlecard/card = card_item
card.Flip(CARD_FACEDOWN)
if(istype(card_item, /obj/item/toy/cards/cardhand))
var/obj/item/toy/cards/cardhand/cardhand = card_item
for(var/obj/item/toy/singlecard/card in cardhand.cards)
card.Flip(CARD_FACEDOWN)
. = ..()
/obj/item/toy/cards/deck/attackby(obj/item/item, mob/living/user, params)
if(istype(item, /obj/item/toy/singlecard) || istype(item, /obj/item/toy/cards/cardhand))
insert(item)
var/card_grammar = istype(item, /obj/item/toy/singlecard) ? "card" : "cards"
user.balloon_alert_to_viewers("puts [card_grammar] in deck")
return
return ..()
/// This is how we play 52 card pickup
/obj/item/toy/cards/deck/throw_impact(mob/living/target, datum/thrownthing/throwingdatum)
. = ..()
if(. || !istype(target)) // was it caught or is the target not a living mob
return .
if(!throwingdatum?.thrower) // if a mob didn't throw it (need two people to play 52 pickup)
return
var/mob/living/thrower = throwingdatum.thrower
target.visible_message(span_warning("[target] is forced to play 52 card pickup!"), span_warning("You are forced to play 52 card pickup."))
SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "lost_52_card_pickup", /datum/mood_event/lost_52_card_pickup)
SEND_SIGNAL(thrower, COMSIG_ADD_MOOD_EVENT, "won_52_card_pickup", /datum/mood_event/won_52_card_pickup)
add_memory_in_range(
target,
7,
MEMORY_PLAYING_52_PICKUP,
list(DETAIL_PROTAGONIST = thrower, DETAIL_DEUTERAGONIST = target, DETAIL_WHAT_BY = src),
story_value = STORY_VALUE_OKAY,
memory_flags = MEMORY_CHECK_BLINDNESS
)
/*
|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. ||
*/
/obj/item/toy/cards/deck/syndicate
name = "suspicious looking deck of cards"
desc = "A deck of space-grade playing cards. They seem unusually rigid."
cardgame_desc = "suspicious card game"
icon_state = "deck_syndicate_full"
deckstyle = "syndicate"
hitsound = 'sound/weapons/bladeslice.ogg'
force = 5
throwforce = 10
attack_verb_continuous = list("attacks", "slices", "dices", "slashes", "cuts")
attack_verb_simple = list("attack", "slice", "dice", "slash", "cut")
resistance_flags = NONE
shuffle_time = DECK_SYNDIE_SHUFFLE_TIME
#undef DECK_SHUFFLE_TIME
#undef DECK_SYNDIE_SHUFFLE_TIME
+21
View File
@@ -0,0 +1,21 @@
/obj/item/toy/cards/deck/kotahi
name = "\improper KOTAHI deck"
desc = "A deck of kotahi cards. House rules to argue over not included."
cardgame_desc = "KOTAHI game"
icon_state = "deck_kotahi_full"
deckstyle = "kotahi"
is_standard_deck = FALSE
/obj/item/toy/cards/deck/kotahi/Initialize(mapload)
. = ..()
for(var/colour in list("Red","Yellow","Green","Blue"))
cards += new /obj/item/toy/singlecard(src, "[colour] 0", src) //kotahi decks have only one colour of each 0, weird huh?
for(var/k in 0 to 1) //two of each colour of number
cards += new /obj/item/toy/singlecard(src, "[colour] skip", src)
cards += new /obj/item/toy/singlecard(src, "[colour] reverse", src)
cards += new /obj/item/toy/singlecard(src, "[colour] draw 2", src)
for(var/i in 1 to 9)
cards += new /obj/item/toy/singlecard(src, "[colour] [i]", src)
for(var/k in 0 to 3) //4 wilds and draw 4s
cards += new /obj/item/toy/singlecard(src, "Wildcard", src)
cards += new /obj/item/toy/singlecard(src, "Draw 4", src)
+59
View File
@@ -0,0 +1,59 @@
#define TAROT_GHOST_TIMER (666 SECONDS) // this translates into 11 mins and 6 seconds
//These cards certainly won't tell the future, but you can play some nice games with them.
/obj/item/toy/cards/deck/tarot
name = "tarot game deck"
desc = "A full 78 card game deck of tarot cards. Complete with 4 suites of 14 cards, and a full suite of trump cards."
cardgame_desc = "tarot card reading"
icon_state = "deck_tarot_full"
deckstyle = "tarot"
is_standard_deck = FALSE
/obj/item/toy/cards/deck/tarot/Initialize(mapload)
. = ..()
for(var/suit in list("Hearts", "Pikes", "Clovers", "Tiles"))
for(var/i in 1 to 10)
cards += new /obj/item/toy/singlecard(src, "[i] of [suit]", src)
for(var/person in list("Valet", "Chevalier", "Dame", "Roi"))
cards += new /obj/item/toy/singlecard(src, "[person] of [suit]", src)
for(var/trump in list("The Magician", "The High Priestess", "The Empress", "The Emperor", "The Hierophant", "The Lover", "The Chariot", "Justice", "The Hermit", "The Wheel of Fortune", "Strength", "The Hanged Man", "Death", "Temperance", "The Devil", "The Tower", "The Star", "The Moon", "The Sun", "Judgement", "The World", "The Fool"))
cards += new /obj/item/toy/singlecard(src, trump, src)
/obj/item/toy/cards/deck/tarot/draw(mob/user)
. = ..()
if(prob(50))
var/obj/item/toy/singlecard/card = .
var/matrix/M = matrix()
M.Turn(180)
card.transform = M
/obj/item/toy/cards/deck/tarot/haunted
name = "haunted tarot game deck"
desc = "A spooky looking tarot deck. You can sense a supernatural presence linked to the cards..."
/// ghost notification cooldown
COOLDOWN_DECLARE(ghost_alert_cooldown)
/obj/item/toy/cards/deck/tarot/haunted/on_wield(obj/item/source, mob/living/carbon/user)
. = ..()
ADD_TRAIT(user, TRAIT_SIXTHSENSE, MAGIC_TRAIT)
to_chat(user, span_notice("The veil to the underworld is opened. You can sense the dead souls calling out..."))
if(!COOLDOWN_FINISHED(src, ghost_alert_cooldown))
return
COOLDOWN_START(src, ghost_alert_cooldown, TAROT_GHOST_TIMER)
notify_ghosts(
"Someone has begun playing with a [src.name] in [get_area(src)]!",
source = src,
header = "Haunted Tarot Deck",
ghost_sound = 'sound/effects/ghost2.ogg',
notify_volume = 75,
action = NOTIFY_ORBIT,
)
/obj/item/toy/cards/deck/tarot/haunted/on_unwield(obj/item/source, mob/living/carbon/user)
. = ..()
REMOVE_TRAIT(user, TRAIT_SIXTHSENSE, MAGIC_TRAIT)
to_chat(user, span_notice("The veil to the underworld closes shut. You feel your senses returning to normal."))
#undef TAROT_GHOST_TIMER
+34
View File
@@ -0,0 +1,34 @@
//It's Wiz-Off, the wizard themed card game! It's modular too, in case you might want to make it Syndie, Sec and Clown themed or something stupid like that.
/obj/item/toy/cards/deck/wizoff
name = "\improper Wiz-Off deck"
desc = "A Wiz-Off deck. Fight an arcane battle for the fate of the universe: Draw 5! Play 5! Best of 5! A rules card is attached."
cardgame_desc = "Wiz-Off game"
icon_state = "deck_wizoff_full"
deckstyle = "wizoff"
is_standard_deck = FALSE
/obj/item/toy/cards/deck/wizoff/Initialize(mapload)
. = ..()
var/card_list = strings("wizoff.json", "wizard")
cards += new /obj/item/toy/singlecard/wizoff_ruleset(src) // ruleset should be the top card
for(var/card in card_list)
cards += new /obj/item/toy/singlecard(src, card, src)
/obj/item/toy/singlecard/wizoff_ruleset
desc = "A ruleset for the playing card game Wiz-Off."
cardname = "Wizoff Ruleset"
deckstyle = "black"
has_unique_card_icons = FALSE
icon_state = "singlecard_down_black"
/obj/item/toy/singlecard/wizoff_ruleset/examine(mob/living/carbon/human/user)
. = ..()
. += span_notice("Remember the rules of Wiz-Off!")
. += span_info("Each player draws 5 cards.")
. += span_info("There are five rounds. Each round, a player selects a card to play, and the winner is selected based on the following rules:")
. += span_info("Defensive beats Offensive!")
. += span_info("Offensive beats Utility!")
. += span_info("Utility beats Defensive!")
. += span_info("If both players play the same type of spell, the higher number wins!")
. += span_info("The player who wins the most of the 5 rounds wins the game!")
. += span_notice("Now get ready to battle for the fate of the universe: Wiz-Off!")
+242
View File
@@ -0,0 +1,242 @@
#define CARD_FACEDOWN 0
#define CARD_FACEUP 1
/obj/item/toy/singlecard
name = "card"
desc = "A playing card used to play card games like poker."
icon = 'icons/obj/playing_cards.dmi'
icon_state = "sc_Ace of Spades_nanotrasen"
w_class = WEIGHT_CLASS_TINY
worn_icon_state = "card"
pixel_x = -5
resistance_flags = FLAMMABLE
max_integrity = 50
force = 0
throwforce = 0
throw_speed = 3
throw_range = 7
attack_verb_continuous = list("attacks")
attack_verb_simple = list("attack")
/// Artistic style of the deck
var/deckstyle = "nanotrasen"
/// If the cards in the deck have different icon states (blank and CAS decks do not)
var/has_unique_card_icons = TRUE
/// The name of the card
var/cardname = "Ace of Spades"
/// Is the card flipped facedown (FALSE) or flipped faceup (TRUE)
var/flipped = FALSE
/// The card is blank and can be written on with a pen.
var/blank = FALSE
/// The color used to mark a card for cheating (by pens or crayons)
var/marked_color
/obj/item/toy/singlecard/Initialize(mapload, cardname, obj/item/toy/cards/deck/parent_deck)
. = ..()
src.cardname = cardname || src.cardname
if(istype(parent_deck))
deckstyle = parent_deck.deckstyle
has_unique_card_icons = parent_deck.has_unique_card_icons
icon_state = "singlecard_down_[parent_deck.deckstyle]"
hitsound = parent_deck.hitsound
force = parent_deck.force
throwforce = parent_deck.throwforce
throw_speed = parent_deck.throw_speed
throw_range = parent_deck.throw_range
attack_verb_continuous = parent_deck.attack_verb_continuous
attack_verb_simple = parent_deck.attack_verb_simple
if(parent_deck.holodeck)
flags_1 |= HOLOGRAM_1
parent_deck.holodeck.spawned += src
register_context()
/obj/item/toy/singlecard/examine(mob/living/carbon/human/user)
. = ..()
if(!ishuman(user))
return
if(user.is_holding(src))
user.visible_message(span_notice("[user] checks [user.p_their()] card."), span_notice("The card reads: [cardname]."))
if(blank)
. += span_notice("The card is blank. Write on it with a pen.")
else if(HAS_TRAIT(user, TRAIT_XRAY_VISION))
. += span_notice("You scan the card with your x-ray vision and it reads: [cardname].")
else
. += span_warning("You need to have the card in your hand to check it!")
var/marked_color = getMarkedColor(user)
if(marked_color)
. += span_notice("The card has a [marked_color] mark on the corner!")
/obj/item/toy/singlecard/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(isnull(held_item) || src == held_item)
context[SCREENTIP_CONTEXT_ALT_LMB] = "Rotate counter-clockwise" // add a ALT_RMB screentip to rotate clockwise
context[SCREENTIP_CONTEXT_RMB] = "Flip card"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = held_item
if(dealer_deck.wielded)
context[SCREENTIP_CONTEXT_LMB] = "Deal card"
context[SCREENTIP_CONTEXT_RMB] = "Deal card faceup"
return CONTEXTUAL_SCREENTIP_SET
context[SCREENTIP_CONTEXT_LMB] = "Recycle card"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/singlecard))
context[SCREENTIP_CONTEXT_LMB] = "Combine cards"
context[SCREENTIP_CONTEXT_RMB] = "Combine cards faceup"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/cards/cardhand))
context[SCREENTIP_CONTEXT_LMB] = "Combine cards"
return CONTEXTUAL_SCREENTIP_SET
if(istype(held_item, /obj/item/toy/crayon) || istype(held_item, /obj/item/pen))
context[SCREENTIP_CONTEXT_LMB] = blank ? "Write on card" : "Mark card"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/obj/item/toy/singlecard/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] is slitting [user.p_their()] wrists with \the [src]! It looks like [user.p_they()] [user.p_have()] an unlucky card!"))
playsound(src, 'sound/weapons/bladeslice.ogg', 50, TRUE)
return BRUTELOSS
/**
* Flips the card over
*
* * Arguments:
* * orientation (optional) - Sets flipped state to CARD_FACEDOWN or CARD_FACEUP if given orientation (otherwise just invert the flipped state)
*/
/obj/item/toy/singlecard/proc/Flip(orientation)
if(!isnull(orientation))
flipped = orientation
else
flipped = !flipped
name = flipped ? cardname : "card"
update_appearance()
/**
* Returns a color if a card is marked and the user can see it
*
* * Arguments:
* * user - We need to check if the user see the marked card
*/
/obj/item/toy/singlecard/proc/getMarkedColor(mob/living/carbon/user)
if(!istype(user))
return
var/is_marked_with_visible_color = (marked_color && marked_color != "invisible")
if(is_marked_with_visible_color || (marked_color == "invisible" && HAS_TRAIT(user, TRAIT_REAGENT_SCANNER)))
return marked_color
/obj/item/toy/singlecard/update_icon_state()
if(!flipped)
icon_state = "singlecard_down_[deckstyle]"
else if(has_unique_card_icons) // each card in a deck has a different icon
icon_state = "sc_[cardname]_[deckstyle]"
else // all cards are the same icon state (blank or scribble)
icon_state = blank ? "sc_blank_[deckstyle]" : "sc_scribble_[deckstyle]"
return ..()
/obj/item/toy/singlecard/update_name()
name = flipped ? cardname : "card"
return ..()
/obj/item/toy/singlecard/attackby(obj/item/item, mob/living/user, params, flip_card=FALSE)
var/obj/item/toy/singlecard/card
if(istype(item, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/dealer_deck = item
if(!dealer_deck.wielded) // recycle card into deck (if unwielded)
dealer_deck.insert(src)
user.balloon_alert_to_viewers("puts card in deck")
return
card = dealer_deck.draw(user)
if(istype(item, /obj/item/toy/singlecard))
card = item
if(card) // card + card = combine into cardhand
if(flip_card)
card.Flip()
if(istype(item, /obj/item/toy/cards/deck))
// only decks cause a balloon alert
user.balloon_alert_to_viewers("deals a card")
var/obj/item/toy/cards/cardhand/new_cardhand = new (drop_location(), list(src, card))
new_cardhand.pixel_x = pixel_x
new_cardhand.pixel_y = pixel_y
if(!isturf(loc)) // make a cardhand in our active hand
user.temporarilyRemoveItemFromInventory(src, TRUE)
new_cardhand.pickup(user)
user.put_in_active_hand(new_cardhand)
return
if(istype(item, /obj/item/toy/cards/cardhand)) // insert into cardhand
var/obj/item/toy/cards/cardhand/target_cardhand = item
target_cardhand.insert(src)
return
var/can_item_write
var/marked_cheating_color
if(istype(item, /obj/item/pen))
var/obj/item/pen/pen = item
can_item_write = TRUE
marked_cheating_color = (pen.colour == "white" && "invisible") || pen.colour
if(istype(item, /obj/item/toy/crayon))
var/obj/item/toy/crayon/crayon = item
can_item_write = TRUE
marked_cheating_color = (crayon.crayon_color == "mime" && "invisible") || crayon.crayon_color
if(can_item_write && !blank) // You cheated not only the game, but yourself
marked_color = marked_cheating_color
to_chat(user, span_notice("You put a [marked_color] mark in the corner of [src] with the [item]. Cheat to win!"))
return
if(can_item_write)
if(!user.is_literate())
to_chat(user, span_notice("You scribble illegibly on [src]!"))
return
var/cardtext = stripped_input(user, "What do you wish to write on the card?", "Card Writing", "", 50)
if(!cardtext || !user.canUseTopic(src, BE_CLOSE))
return
cardname = cardtext
blank = FALSE
update_appearance()
return
return ..()
/obj/item/toy/singlecard/attackby_secondary(obj/item/item, mob/living/user, modifiers)
attackby(item, user, modifiers, flip_card=TRUE)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/item/toy/singlecard/attack_hand_secondary(mob/living/carbon/human/user, modifiers)
attack_self(user)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/item/toy/singlecard/attack_self_secondary(mob/living/carbon/human/user, modifiers)
attack_self(user)
/obj/item/toy/singlecard/attack_self(mob/living/carbon/human/user)
if(!ishuman(user) || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK, !iscyborg(user)))
return
Flip()
if(isturf(src.loc)) // only display tihs message when flipping in a visible spot like on a table
user.balloon_alert_to_viewers("flips a card")
/obj/item/toy/singlecard/AltClick(mob/living/carbon/human/user)
if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, NO_TK, !iscyborg(user)))
transform = turn(transform, 90)
// use the simple_rotation component to make this turn with Alt+RMB & Alt+LMB at some point in the future - TimT
return ..()
+15
View File
@@ -448,6 +448,16 @@
desc = "A pair of xray goggles manufactured by the Syndicate."
vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS
/obj/item/clothing/glasses/thermal/xray/equipped(mob/living/carbon/human/user, slot)
. = ..()
if(slot != ITEM_SLOT_EYES || !istype(user))
return
ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
/obj/item/clothing/glasses/thermal/xray/dropped(mob/living/carbon/human/user)
. = ..()
REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete
name = "chameleon thermals"
desc = "A pair of thermal optic goggles with an onboard chameleon generator."
@@ -551,11 +561,14 @@
H.add_hud_to(user)
ADD_TRAIT(user, TRAIT_MEDICAL_HUD, GLASSES_TRAIT)
ADD_TRAIT(user, TRAIT_SECURITY_HUD, GLASSES_TRAIT)
if(xray)
ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
/obj/item/clothing/glasses/debug/dropped(mob/user)
. = ..()
REMOVE_TRAIT(user, TRAIT_MEDICAL_HUD, GLASSES_TRAIT)
REMOVE_TRAIT(user, TRAIT_SECURITY_HUD, GLASSES_TRAIT)
REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/H = GLOB.huds[hud]
@@ -566,8 +579,10 @@
if(ishuman(user))
if(xray)
vision_flags -= SEE_MOBS|SEE_OBJS
REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
else
vision_flags += SEE_MOBS|SEE_OBJS
ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
xray = !xray
var/mob/living/carbon/human/H = user
H.update_sight()
+2 -2
View File
@@ -55,8 +55,8 @@
/obj/item/valentine
name = "valentine"
desc = "A Valentine's card! Wonder what it says..."
icon = 'icons/obj/toy.dmi'
icon_state = "sc_Ace of Hearts_syndicate" // shut up
icon = 'icons/obj/playing_cards.dmi'
icon_state = "sc_Ace of Hearts_syndicate" // shut up // bye felicia
var/message = "A generic message of love or whatever."
resistance_flags = FLAMMABLE
w_class = WEIGHT_CLASS_TINY
-157
View File
@@ -1,157 +0,0 @@
// CARDS AGAINST SPESS
// This is a parody of Cards Against Humanity (https://en.wikipedia.org/wiki/Cards_Against_Humanity)
// which is licensed under CC BY-NC-SA 2.0, the full text of which can be found at the following URL:
// https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode
// Original code by Zuhayr, Polaris Station, ported with modifications
/datum/playingcard
var/name = "playing card"
var/card_icon = "card_back"
var/suit
var/number
/obj/item/toy/cards/deck/cas
name = "\improper CAS deck (white)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the white deck."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_caswhite_full"
deckstyle = "caswhite"
var/card_face = "cas_white"
var/blanks = 25
var/decksize = 150
var/card_text_file = "strings/cas_white.txt"
var/list/allcards = list()
/obj/item/toy/cards/deck/cas/black
name = "\improper CAS deck (black)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the black deck."
icon_state = "deck_casblack_full"
deckstyle = "casblack"
card_face = "cas_black"
blanks = 0
decksize = 50
card_text_file = "strings/cas_black.txt"
/obj/item/toy/cards/deck/cas/populate_deck()
var/static/list/cards_against_space = list("cas_white" = world.file2list("strings/cas_white.txt"),"cas_black" = world.file2list("strings/cas_black.txt"))
allcards = cards_against_space[card_face]
var/list/possiblecards = allcards.Copy()
if(possiblecards.len < decksize) // sanity check
decksize = (possiblecards.len - 1)
var/list/randomcards = list()
for(var/x in 1 to decksize)
randomcards += pick_n_take(possiblecards)
for(var/x in 1 to randomcards.len)
var/cardtext = randomcards[x]
var/datum/playingcard/P
P = new()
P.name = "[cardtext]"
P.card_icon = "[src.card_face]"
cards += P
if(!blanks)
return
for(var/x in 1 to blanks)
var/datum/playingcard/P
P = new()
P.name = "Blank Card"
P.card_icon = "cas_white"
cards += P
shuffle_inplace(cards) // distribute blank cards throughout deck
/obj/item/toy/cards/deck/cas/draw_card(mob/user)
if(isliving(user))
var/mob/living/L = user
if(!(L.mobility_flags & MOBILITY_PICKUP))
return
if(cards.len == 0)
to_chat(user, span_warning("There are no more cards to draw!"))
return
var/obj/item/toy/cards/singlecard/cas/H = new/obj/item/toy/cards/singlecard/cas(user.loc)
var/datum/playingcard/choice = cards[1]
if (choice.name == "Blank Card")
H.blank = 1
H.name = choice.name
H.buffertext = choice.name
H.icon_state = choice.card_icon
H.card_face = choice.card_icon
H.parentdeck = WEAKREF(src)
src.cards -= choice
H.pickup(user)
user.put_in_hands(H)
user.visible_message(span_notice("[user] draws a card from the deck."), span_notice("You draw a card from the deck."))
update_appearance()
/obj/item/toy/cards/deck/cas/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/cards/singlecard/cas))
var/obj/item/toy/cards/singlecard/cas/SC = I
if(!user.temporarilyRemoveItemFromInventory(SC))
to_chat(user, span_warning("The card is stuck to your hand, you can't add it to the deck!"))
return
var/datum/playingcard/RC // replace null datum for the re-added card
RC = new()
RC.name = "[SC.name]"
RC.card_icon = SC.card_face
cards += RC
user.visible_message(span_notice("[user] adds a card to the bottom of the deck."),span_notice("You add the card to the bottom of the deck."))
qdel(SC)
update_appearance()
/obj/item/toy/cards/deck/cas/update_icon_state()
if(cards.len < 26)
icon_state = "deck_[deckstyle]_low"
return ..()
/obj/item/toy/cards/singlecard/cas
name = "CAS card"
desc = "A CAS card."
icon_state = "cas_white"
flipped = 0
var/card_face = "cas_white"
var/blank = 0
var/buffertext = "A funny bit of text."
/obj/item/toy/cards/singlecard/cas/examine(mob/user)
. = ..()
if (flipped)
. += span_notice("The card is face down.")
else if (blank)
. += span_notice("The card is blank. Write on it with a pen.")
else
. += span_notice("The card reads: [name]")
. += span_notice("Alt-click to flip it.")
/obj/item/toy/cards/singlecard/cas/Flip()
set name = "Flip Card"
set category = "Object"
set src in range(1)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(!flipped)
name = "CAS card"
else if(flipped)
name = buffertext
flipped = !flipped
update_appearance()
/obj/item/toy/cards/singlecard/cas/AltClick(mob/living/user)
if(!ishuman(user) || !user.canUseTopic(src, BE_CLOSE))
return
Flip()
/obj/item/toy/cards/singlecard/cas/update_icon_state()
icon_state = "[card_face][flipped ? "_flipped" : null]"
return ..()
/obj/item/toy/cards/singlecard/cas/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/pen))
if(!user.is_literate())
to_chat(user, span_notice("You scribble illegibly on [src]!"))
return
if(!blank)
to_chat(user, span_warning("You cannot write on that card!"))
return
var/cardtext = stripped_input(user, "What do you wish to write on the card?", "Card Writing", "", 50)
if(!cardtext || !user.canUseTopic(src, BE_CLOSE))
return
name = cardtext
buffertext = cardtext
blank = 0
-20
View File
@@ -1,20 +0,0 @@
/obj/item/toy/cards/deck/kotahi
name = "\improper KOTAHI deck"
desc = "A deck of kotahi cards. House rules to argue over not included."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_kotahi_full"
deckstyle = "kotahi"
//Populate the deck.
/obj/item/toy/cards/deck/kotahi/populate_deck()
for(var/colour in list("Red","Yellow","Green","Blue"))
cards += generate_card("[colour] 0") //kotahi decks have only one colour of each 0, weird huh?
for(var/k in 0 to 1) //two of each colour of number
cards += generate_card("[colour] skip")
cards += generate_card("[colour] reverse")
cards += generate_card("[colour] draw 2")
for(var/i in 1 to 9)
cards += generate_card("[colour] [i]")
for(var/k in 0 to 3) //4 wilds and draw 4s
cards += generate_card("Wildcard")
cards += generate_card("Draw 4")
-25
View File
@@ -1,25 +0,0 @@
//These cards certainly won't tell the future, but you can play some nice games with them.
/obj/item/toy/cards/deck/tarot
name = "tarot game deck"
desc = "A full 78 card game deck of tarot cards. Complete with 4 suites of 14 cards, and a full suite of trump cards."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_tarot_full"
deckstyle = "tarot"
/obj/item/toy/cards/deck/tarot/populate_deck()
for(var/suit in list("Hearts", "Pikes", "Clovers", "Tiles"))
for(var/i in 1 to 10)
cards += generate_card("[i] of [suit]")
for(var/person in list("Valet", "Chevalier", "Dame", "Roi"))
cards += generate_card("[person] of [suit]")
for(var/trump in list("The Magician", "The High Priestess", "The Empress", "The Emperor", "The Hierophant", "The Lover", "The Chariot", "Justice", "The Hermit", "The Wheel of Fortune", "Strength", "The Hanged Man", "Death", "Temperance", "The Devil", "The Tower", "The Star", "The Moon", "The Sun", "Judgement", "The World", "The Fool"))
cards += generate_card("[trump]")
/obj/item/toy/cards/deck/tarot/draw_card(mob/user, list/cards, obj/item/toy/cards/singlecard/forced_card = null)
. = ..()
var/obj/item/toy/cards/singlecard/C = .
var/matrix/M = matrix()
M.Turn(180)
if(prob(50))
C.transform = M
return
-26
View File
@@ -1,26 +0,0 @@
//It's Wiz-Off, the wizard themed card game! It's modular too, in case you might want to make it Syndie, Sec and Clown themed or something stupid like that.
/obj/item/toy/cards/deck/wizoff
name = "\improper Wiz-Off deck"
desc = "A Wiz-Off deck. Fight an arcane battle for the fate of the universe: Draw 5! Play 5! Best of 5! A rules card is attached."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_wizoff_full"
deckstyle = "wizoff"
var/theme = "wizard"
/obj/item/toy/cards/deck/wizoff/populate_deck()
var/card_list = strings("wizoff.json", theme)
for(var/card in card_list)
cards += generate_card("[card]")
/obj/item/toy/cards/deck/wizoff/examine_more(mob/user)
. = ..()
. += span_notice("Remember the rules of Wiz-Off!")
. += "\t[span_info("Each player draws 5 cards.")]"
. += "\t[span_info("There are five rounds. Each round, a player selects a card to play, and the winner is selected based on the following rules:")]"
. += "\t[span_info("Defensive beats Offensive!")]"
. += "\t[span_info("Offensive beats Utility!")]"
. += "\t[span_info("Utility beats Defensive!")]"
. += "\t[span_info("If both players play the same type of spell, the higher number wins!")]"
. += "\t[span_info("The player who wins the most of the 5 rounds wins the game!")]"
. += "\t[span_notice("Now get ready to battle for the fate of the universe: Wiz-Off!")]"
return .
+5 -32
View File
@@ -23,43 +23,16 @@
/obj/effect/holodeck_effect/proc/safety(active)
return
// Generates a holodeck-tracked card deck
/obj/effect/holodeck_effect/cards
icon = 'icons/obj/toy.dmi'
icon_state = "deck_nanotrasen_full"
var/obj/item/toy/cards/deck/deck
icon = 'icons/obj/playing_cards.dmi'
icon_state = "deck_syndicate_full"
/obj/effect/holodeck_effect/cards/activate(obj/machinery/computer/holodeck/HC)
deck = new(loc)
safety(!(HC.obj_flags & EMAGGED))
deck.holo = HC
RegisterSignal(deck, COMSIG_PARENT_QDELETING, .proc/handle_card_delete)
/obj/effect/holodeck_effect/cards/activate(obj/machinery/computer/holodeck/holodeck)
var/obj/item/toy/cards/deck/syndicate/holographic/deck = new(loc, holodeck)
deck.flags_1 |= HOLOGRAM_1
return deck
/obj/effect/holodeck_effect/cards/proc/handle_card_delete(datum/source)
SIGNAL_HANDLER
deck = null
/obj/effect/holodeck_effect/cards/safety(active)
if(!deck)
return
if(active)
deck.card_hitsound = null
deck.card_force = 0
deck.card_throwforce = 0
deck.card_throw_speed = 3
deck.card_throw_range = 7
deck.card_attack_verb_continuous = string_list(list("attacks"))
else
deck.card_hitsound = 'sound/weapons/bladeslice.ogg'
deck.card_force = 5
deck.card_throwforce = 10
deck.card_throw_speed = 3
deck.card_throw_range = 7
deck.card_attack_verb_continuous = string_list(list("attacks", "slices", "dices", "slashes", "cuts"))
/obj/effect/holodeck_effect/sparks/activate(obj/machinery/computer/holodeck/HC)
var/turf/T = get_turf(src)
if(T)
+18
View File
@@ -32,6 +32,24 @@
/obj/item/melee/energy/sword/holographic/red
sword_color_icon = "red"
/obj/item/toy/cards/deck/syndicate/holographic
desc = "A deck of holographic playing cards."
/obj/item/toy/cards/deck/syndicate/holographic/Initialize(mapload, obj/machinery/computer/holodeck/holodeck)
src.holodeck = holodeck
RegisterSignal(src, COMSIG_PARENT_QDELETING, .proc/handle_card_delete)
. = ..()
/obj/item/toy/cards/deck/syndicate/holographic/proc/handle_card_delete(datum/source)
SIGNAL_HANDLER
//if any REAL cards have been inserted into the deck they are moved outside before destroying it
for(var/obj/item/toy/singlecard/card in cards)
if(card.flags_1 & HOLOGRAM_1)
continue
cards -= card
card.forceMove(drop_location())
//BASKETBALL OBJECTS
/obj/item/toy/beach_ball/holoball
@@ -508,7 +508,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/guardiancreator
name = "enchanted deck of tarot cards"
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power."
icon = 'icons/obj/toy.dmi'
icon = 'icons/obj/playing_cards.dmi'
icon_state = "deck_tarot_full"
var/used = FALSE
var/theme = "magic"
+8
View File
@@ -193,6 +193,14 @@
see_in_dark = NIGHTVISION_FOV_RANGE
sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS
/obj/item/organ/eyes/robotic/xray/Insert(mob/living/carbon/eye_owner, special = FALSE)
. = ..()
ADD_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT)
/obj/item/organ/eyes/robotic/xray/Remove(mob/living/carbon/eye_owner, special = FALSE)
REMOVE_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT)
return ..()
/obj/item/organ/eyes/robotic/thermals
name = "thermal eyes"
desc = "These cybernetic eye implants will give you thermal vision. Vertical slit pupil included."
@@ -86,6 +86,8 @@
ignore += typesof(/obj/effect/skyfall_landingzone)
//Expects a mob to holderize, we have nothing to give
ignore += typesof(/obj/item/clothing/head/mob_holder)
//Needs cards passed into the initilazation args
ignore += typesof(/obj/item/toy/cards/cardhand)
var/list/cached_contents = spawn_at.contents.Copy()
var/baseturf_count = length(spawn_at.baseturfs)
+2
View File
@@ -8,6 +8,8 @@
/obj/item/storage/crayons = 2,
/obj/item/toy/cards/deck = 5,
/obj/item/storage/dice = 10,
/obj/item/toy/cards/deck/blank = 3,
/obj/item/toy/cards/deck/blank/black = 3,
/obj/item/toy/cards/deck/cas = 3,
/obj/item/toy/cards/deck/cas/black = 3,
/obj/item/toy/cards/deck/kotahi = 3,
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.
-1
View File
@@ -340,7 +340,6 @@ Cursed duffle bags.
Fetish content.
The shotgun.
Lavaland bestiality.
░░░░░▄▄▄▄▀▀▀▀▀▀▀▀▄▄▄▄▄▄░░░░░░░ ░░░░░█░░░░▒▒▒▒▒▒▒▒▒▒▒▒░░▀▀▄░░░░ ░░░░█░░░▒▒▒▒▒▒░░░░░░░░▒▒▒░░█░░░ ░░░█░░░░░░▄██▀▄▄░░░░░▄▄▄░░░░█░░ ░▄▀▒▄▄▄▒░█▀▀▀▀▄▄█░░░██▄▄█░░░░█░ █░▒█▒▄░▀▄▄▄▀░░░░░░░░█░░░▒▒▒▒▒░█ █░▒█░█▀▄▄░░░░░█▀░░░░▀▄░░▄▀▀▀▄▒█ ░█░▀▄░█▄░█▀▄▄░▀░▀▀░▄▄▀░░░░█░░█░ ░░█░░░▀▄▀█▄▄░█▀▀▀▄▄▄▄▀▀█▀██░█░░ ░░░█░░░░██░░▀█▄▄▄█▄▄█▄████░█░░░ ░░░░█░░░░▀▀▄░█░░░█░█▀██████░█░░ ░░░░░▀▄░░░░░▀▀▄▄▄█▄█▄█▄█▄▀░░█░░ ░░░░░░░▀▄▄░▒▒▒▒░░░░░░░░░░▒░░░█░ ░░░░░░░░░░▀▀▄▄░▒▒▒▒▒▒▒▒▒▒░░░░█░ ░░░░░░░░░░░░░░▀▄▄▄▄▄░░░░░░░░█░░
Vore.
CAT WITH NO UNDIES
Surgical implantation of cat body parts.
+25 -1
View File
@@ -195,7 +195,7 @@
"The borging of %PROTAGONIST."
],
"borged_starts":[
"%PROTAGONIST havign their brain put into a robot",
"%PROTAGONIST having their brain put into a robot",
"%PROTAGONIST getting turned into a bucket of bolts"
],
"borged_moods":[
@@ -418,5 +418,29 @@
"nuke_code_starts":[
"The number %NUKE_CODE written on a sticky note with the words \"FOR SYNDICATE EYES ONLY\" scrawled next to it.",
"A piece of paper with the number %NUKE_CODE being handed to %PROTAGONIST from a figure in a blood-red hardsuit."
],
"playing_cards_names":[
"The %CARDGAME of %PROTAGONIST with %PLAYERS."
],
"playing_cards_starts":[
"%PLAYERS are waiting for %PROTAGONIST to start the %CARDGAME",
"The %CARDGAME has been setup by %DEALER",
"%DEALER starts shuffling the deck for the %CARDGAME"
],
"playing_cards_moods":[
"%PROTAGONIST %MOOD as they hold the %HELD_CARD_ITEM for the %CARDGAME.",
"%PROTAGONIST %MOOD as they pickup the %HELD_CARD_ITEM.",
"%PROTAGONIST %MOOD as they put down the %HELD_CARD_ITEM."
],
"playing_52_pickup_names":[
"%PROTAGONIST tricking %DEUTERAGONIST into playing 52 pickup with %WHAT_BY."
],
"playing_52_pickup_starts":[
"%PROTAGONIST tosses the %WHAT_BY at %DEUTERAGONIST spilling cards all over the floor",
"A %WHAT_BY thrown by %PROTAGONIST splatters across %DEUTERAGONIST face"
],
"playing_52_pickup_moods":[
"%PROTAGONIST %MOOD as they taunt %DEUTERAGONIST.",
"%DEUTERAGONIST %MOOD as they shamefully pickup the cards."
]
}
+1
View File
@@ -251,3 +251,4 @@ Laying down will help slow down bloodloss. Death will halt it entirely.
♪ Hey, have you ever tried appending the % character before your messages when speaking in-game? ♫
@You can use the |, + and _ characters to emphasize parts of what you say in-game (e.g. say"my _ass_ |is| +heavy+." will be outputted as "my <u>ass</u> <i>is</i> <b>heavy</b>."). You can also escape these emphasizers by appending backslashes before them (e.g. say"1\+2\+3" will come out as "1+2+3" and not "1\<b>2\</b>3").
If you knock into somebody while doing a wicked grind on a skateboard, they will be floored for double the time. Radical!
You can cheat games by baking dice in microwaves to make them loaded. Cards can be seen with x-ray vision or be marked with either a pen or crayon to gain an edge.
+9 -4
View File
@@ -2395,6 +2395,15 @@
#include "code\modules\capture_the_flag\ctf_panel.dm"
#include "code\modules\capture_the_flag\medieval_sim\medisim_classes.dm"
#include "code\modules\capture_the_flag\medieval_sim\medisim_game.dm"
#include "code\modules\cards\cardhand.dm"
#include "code\modules\cards\cards.dm"
#include "code\modules\cards\singlecard.dm"
#include "code\modules\cards\deck\blank.dm"
#include "code\modules\cards\deck\cas.dm"
#include "code\modules\cards\deck\deck.dm"
#include "code\modules\cards\deck\kotahi.dm"
#include "code\modules\cards\deck\tarot.dm"
#include "code\modules\cards\deck\wizoff.dm"
#include "code\modules\cargo\bounty.dm"
#include "code\modules\cargo\centcom_podlauncher.dm"
#include "code\modules\cargo\coupon.dm"
@@ -2824,10 +2833,6 @@
#include "code\modules\food_and_drinks\restaurant\custom_order.dm"
#include "code\modules\food_and_drinks\restaurant\generic_venues.dm"
#include "code\modules\food_and_drinks\restaurant\customers\_customer.dm"
#include "code\modules\games\cas.dm"
#include "code\modules\games\kotahi.dm"
#include "code\modules\games\tarot.dm"
#include "code\modules\games\wizoff.dm"
#include "code\modules\holiday\easter.dm"
#include "code\modules\holiday\foreign_calendar.dm"
#include "code\modules\holiday\holidays.dm"