Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Citadel-Station-13-master

This commit is contained in:
dzahlus
2021-02-18 04:26:43 +01:00
124 changed files with 3887 additions and 279 deletions
@@ -139,6 +139,7 @@
dir = 4;
name = "shrine of the liberator"
},
/obj/item/tcg_card/special/golem,
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
"v" = (
@@ -14,6 +14,10 @@
},
/turf/open/floor/plating/beach/sand,
/area/icemoon/surface/outdoors)
"l" = (
/obj/item/tcg_card/special/morph,
/turf/open/floor/plating/beach/sand,
/area/icemoon/surface/outdoors)
"I" = (
/turf/closed/indestructible/fakeglass,
/area/icemoon/surface/outdoors)
@@ -72,7 +76,7 @@ L
c
c
c
U
l
U
a
b
@@ -20,6 +20,10 @@
},
/turf/open/floor/mineral/diamond,
/area/icemoon/surface/outdoors)
"f" = (
/obj/item/tcg_card/special/xenomaid,
/turf/open/floor/mineral/diamond,
/area/icemoon/surface/outdoors)
(1,1,1) = {"
a
@@ -65,7 +69,7 @@ a
a
a
b
c
f
c
c
b
@@ -49,6 +49,7 @@
/area/ruin/unpowered)
"k" = (
/obj/structure/closet/crate/freezer,
/obj/item/tcg_card/special/demonic_miner,
/turf/open/floor/wood,
/area/ruin/unpowered)
"l" = (
@@ -31,6 +31,10 @@
"N" = (
/turf/open/indestructible/necropolis/ice,
/area/icemoon/underground/explored)
"S" = (
/obj/item/tcg_card/special/wendigo,
/turf/open/indestructible/necropolis/ice,
/area/icemoon/underground/explored)
"U" = (
/obj/item/paper/crumpled/bloody{
info = "for your own sake, do not enter"
@@ -451,7 +455,7 @@ a
N
N
N
N
S
N
N
N
@@ -862,6 +862,7 @@
/obj/structure/disposalpipe/segment{
dir = 10
},
/obj/item/tcg_card/special/honk,
/turf/open/floor/plating,
/area/ruin/powered/clownplanet)
"bF" = (
@@ -155,6 +155,12 @@
/obj/item/stack/tile/brass/fifty,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors/unexplored)
"Y" = (
/obj/item/tcg_card/special/ratvar,
/turf/open/floor/clockwork{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/lavaland/surface/outdoors/unexplored)
(1,1,1) = {"
a
@@ -484,7 +490,7 @@ h
h
h
h
h
Y
h
l
l
@@ -709,7 +715,7 @@ b
l
l
b
h
Y
h
t
b
@@ -26,6 +26,10 @@
},
/turf/open/indestructible/hierophant/two,
/area/ruin/unpowered/hierophant)
"s" = (
/obj/item/tcg_card/special/hierophant,
/turf/open/indestructible/hierophant,
/area/ruin/unpowered/hierophant)
(1,1,1) = {"
a
@@ -494,7 +498,7 @@ b
b
b
c
b
s
a
a
b
@@ -11,6 +11,13 @@
"d" = (
/turf/closed/wall/mineral/abductor,
/area/ruin/unpowered)
"h" = (
/obj/structure/closet/abductor,
/obj/item/tcg_card/special/abductor,
/turf/open/floor/plating/abductor{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"j" = (
/obj/machinery/abductor/experiment{
team_number = 100
@@ -188,7 +195,7 @@ a
a
c
d
q
h
t
q
d
@@ -567,6 +567,7 @@
"bm" = (
/obj/structure/closet/wardrobe/science_white,
/obj/structure/disposalpipe/segment,
/obj/item/tcg_card/special/space_carp,
/turf/open/floor/plasteel{
icon_state = "dark"
},
@@ -16,8 +16,8 @@
/area/template_noop)
"ae" = (
/obj/structure/fluff/broken_flooring{
icon_state = "plating";
dir = 4
dir = 4;
icon_state = "plating"
},
/turf/template_noop,
/area/template_noop)
@@ -66,8 +66,8 @@
"an" = (
/obj/structure/lattice,
/obj/structure/fluff/broken_flooring{
icon_state = "plating";
dir = 4
dir = 4;
icon_state = "plating"
},
/turf/template_noop,
/area/template_noop)
@@ -78,8 +78,8 @@
"ap" = (
/obj/structure/lattice,
/obj/structure/fluff/broken_flooring{
icon_state = "pile";
dir = 8
dir = 8;
icon_state = "pile"
},
/turf/template_noop,
/area/template_noop)
@@ -133,8 +133,8 @@
/area/template_noop)
"aE" = (
/obj/structure/fluff/broken_flooring{
icon_state = "pile";
dir = 4
dir = 4;
icon_state = "pile"
},
/turf/template_noop,
/area/template_noop)
@@ -1054,6 +1054,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/structure/closet/crate/secure/weapon,
/obj/item/gun/ballistic/automatic/pistol/APS,
/obj/item/tcg_card/special/spess_pirate,
/turf/open/floor/plasteel/airless/dark,
/area/shuttle/caravan/freighter2)
"js" = (
@@ -91,6 +91,10 @@
},
/turf/open/floor/plating/asteroid/airless,
/area/ruin/space/has_grav)
"Y" = (
/obj/item/tcg_card/special/gondola,
/turf/open/floor/plating/asteroid/airless,
/area/ruin/space/has_grav)
(1,1,1) = {"
a
@@ -339,7 +343,7 @@ b
c
c
c
c
Y
o
c
r
@@ -19,6 +19,7 @@
/area/ruin/space/has_grav/powered/mechtransport)
"g" = (
/obj/structure/closet/crate/secure/loot,
/obj/item/tcg_card/special/phazon,
/turf/open/floor/mineral/titanium/blue,
/area/ruin/space/has_grav/powered/mechtransport)
"h" = (
+1
View File
@@ -24,3 +24,4 @@
#define LANGUAGE_STONER "stoner"
#define LANGUAGE_VASSAL "vassal"
#define LANGUAGE_VOICECHANGE "voicechange"
#define LANGUAGE_MULTILINGUAL "multilingual"
+5 -5
View File
@@ -69,8 +69,8 @@
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
//silicon_priviledges flags
#define PRIVILEDGES_SILICON (1<<0)
#define PRIVILEDGES_PAI (1<<1)
#define PRIVILEDGES_BOT (1<<2)
#define PRIVILEDGES_DRONE (1<<3)
//silicon_privileges flags
#define PRIVILEGES_SILICON (1<<0)
#define PRIVILEGES_PAI (1<<1)
#define PRIVILEGES_BOT (1<<2)
#define PRIVILEGES_DRONE (1<<3)
+2 -2
View File
@@ -204,7 +204,7 @@
///Compile all the overlays for an atom from the cache lists
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
do {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
if(LAZYLEN(rm)){\
@@ -216,7 +216,7 @@
ad.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
} while(FALSE)
/**
+29 -1
View File
@@ -66,7 +66,7 @@
} while(FALSE)
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
switch(total)
if (0)
@@ -87,6 +87,34 @@
return "[output][and_text][input[index]]"
/**
* English_list but associative supporting. Higher overhead.
*/
/proc/english_list_assoc(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
switch(total)
if (0)
return "[nothing_text]"
if (1)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
return "[input[1]][assoc]"
if (2)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
var/assoc2 = input[input[2]] == null? "" : " = [input[input[2]]]"
return "[input[1]][assoc][and_text][input[2]][assoc2]"
else
var/output = ""
var/index = 1
var/assoc
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
assoc = input[input[index]] == null? "" : " = [input[input[index]]]"
output += "[input[index]][assoc][comma_text]"
++index
assoc = input[input[index]] == null? "" : " = [input[input[index]]]"
return "[output][and_text][input[index]]"
//Returns list element or null. Should prevent "index out of bounds" error.
/proc/listgetindex(list/L, index)
if(LAZYLEN(L))
+2 -2
View File
@@ -231,10 +231,10 @@
src_object = window.locked_by.src_object
// Insert src_object info
if(src_object)
entry += "\nUsing: [src_object.type] [REF(src_object)]"
entry += "Using: [src_object.type] [REF(src_object)]"
// Insert message
if(message)
entry += "\n[message]"
entry += "[message]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
+46 -21
View File
@@ -118,27 +118,7 @@
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//CITADEL CHANGES - sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//END OF CITADEL CHANGES
//same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
assert_move_intent_ui(owner, TRUE)
// clickdelay
clickdelay = new
@@ -393,6 +373,51 @@
update_locked_slots()
/datum/hud/human/proc/assert_move_intent_ui(mob/living/carbon/human/owner = mymob, on_new = FALSE)
var/obj/screen/using
// delete old ones
var/list/obj/screen/victims = list()
victims += locate(/obj/screen/mov_intent) in static_inventory
victims += locate(/obj/screen/sprintbutton) in static_inventory
victims += locate(/obj/screen/sprint_buffer) in static_inventory
if(victims)
static_inventory -= victims
if(mymob?.client)
mymob.client.screen -= victims
QDEL_LIST(victims)
// make new ones
// walk/run
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.screen_loc = ui_movi
using.hud = src
using.update_icon()
static_inventory += using
if(!on_new)
owner?.client?.screen += using
if(!CONFIG_GET(flag/sprint_enabled))
return
// sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
if(!on_new)
owner?.client?.screen += using
// same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
if(!on_new)
owner?.client?.screen += using
/datum/hud/human/update_locked_slots()
if(!mymob)
return
+5 -1
View File
@@ -351,6 +351,10 @@
icon = 'icons/mob/screen_midnight.dmi'
icon_state = "running"
/obj/screen/mov_intent/Initialize(mapload)
. = ..()
update_icon()
/obj/screen/mov_intent/Click()
toggle(usr)
@@ -359,7 +363,7 @@
if(MOVE_INTENT_WALK)
icon_state = "walking"
if(MOVE_INTENT_RUN)
icon_state = "running"
icon_state = CONFIG_GET(flag/sprint_enabled)? "running" : "running_nosprint"
/obj/screen/mov_intent/proc/toggle(mob/user)
if(isobserver(user))
@@ -290,6 +290,17 @@
var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk)
M.sync()
/datum/config_entry/flag/sprint_enabled
config_entry_value = TRUE
/datum/config_entry/flag/sprint_enabled/ValidateAndSet(str_val)
. = ..()
for(var/datum/hud/human/H)
H.assert_move_intent_ui()
if(!config_entry_value) // disabled
for(var/mob/living/L in world)
L.disable_intentional_sprint_mode()
/datum/config_entry/number/movedelay/sprint_speed_increase
config_entry_value = 1
@@ -26,50 +26,6 @@
/datum/config_entry/flag/hub // if the game appears on the hub or not
/datum/config_entry/flag/log_ooc // log OOC channel
/datum/config_entry/flag/log_access // log login/logout
/datum/config_entry/flag/log_say // log client say
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
/datum/config_entry/flag/log_law // log lawchanges
/datum/config_entry/flag/log_game // log game events
/datum/config_entry/flag/log_virus // log virology data
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_craft // log crafting
/datum/config_entry/flag/log_whisper // log client whisper
/datum/config_entry/flag/log_attack // log attack messages
/datum/config_entry/flag/log_emote // log emotes
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/datum/config_entry/flag/log_pda // log pda messages
/datum/config_entry/flag/log_telecomms // log telecomms messages
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
/datum/config_entry/flag/allow_vote_restart // allow votes to restart
@@ -472,10 +428,6 @@
/datum/config_entry/string/default_view_square
config_entry_value = "15x15"
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/datum/config_entry/number/max_bunker_days
config_entry_value = 7
min_val = 1
@@ -0,0 +1,70 @@
/datum/config_entry/flag/log_ooc // log OOC channel
config_entry_value = TRUE
/datum/config_entry/flag/log_access // log login/logout
config_entry_value = TRUE
/datum/config_entry/flag/log_say // log client say
config_entry_value = TRUE
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
config_entry_value = TRUE
/datum/config_entry/flag/log_law // log lawchanges
config_entry_value = TRUE
/datum/config_entry/flag/log_game // log game events
config_entry_value = TRUE
/datum/config_entry/flag/log_virus // log virology data
config_entry_value = TRUE
/datum/config_entry/flag/log_vote // log voting
config_entry_value = TRUE
/datum/config_entry/flag/log_craft // log crafting
config_entry_value = TRUE
/datum/config_entry/flag/log_whisper // log client whisper
config_entry_value = TRUE
/datum/config_entry/flag/log_attack // log attack messages
config_entry_value = TRUE
/datum/config_entry/flag/log_emote // log emotes
config_entry_value = TRUE
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
config_entry_value = TRUE
/datum/config_entry/flag/log_pda // log pda messages
config_entry_value = TRUE
/datum/config_entry/flag/log_telecomms // log telecomms messages
config_entry_value = TRUE
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
config_entry_value = TRUE
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
config_entry_value = TRUE
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
config_entry_value = TRUE
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
config_entry_value = TRUE
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/// forces log_href for tgui
/datum/config_entry/flag/emergency_tgui_logging
config_entry_value = FALSE
+22
View File
@@ -490,6 +490,28 @@ SUBSYSTEM_DEF(job)
job.after_spawn(H, M, joined_late) // note: this happens before the mob has a key! M will always have a client, H might not.
equip_loadout(N, H, TRUE)//CIT CHANGE - makes players spawn with in-backpack loadout items properly. A little hacky but it works
if(ishuman(H) && H.client && N)
if(H.client && H.client.prefs && length(H.client.prefs.tcg_cards))
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
if(!H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
qdel(binder)
else
for(var/card_type in H.client.prefs.tcg_cards)
var/obj/item/tcg_card/card = new(get_turf(H), card_type, H.client.prefs.tcg_cards[card_type])
card.forceMove(binder)
binder.cards.Add(card)
binder.check_for_exodia()
else
if(H && N.client.prefs && length(N.client.prefs.tcg_cards))
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
if(!H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
qdel(binder)
else
for(var/card_type in N.client.prefs.tcg_cards)
var/obj/item/tcg_card/card = new(get_turf(H), card_type, H.client.prefs.tcg_cards[card_type])
card.forceMove(binder)
binder.cards.Add(card)
return H
/*
/datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank)
@@ -88,6 +88,7 @@ SUBSYSTEM_DEF(persistence)
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
SavePaintings()
SaveScars()
SaveTCGCards()
/**
* Loads persistent data relevant to the current map: Objects, etc.
@@ -349,3 +350,25 @@ SUBSYSTEM_DEF(persistence)
if(!ending_human.client)
return
ending_human.client.prefs.save_character()
/datum/controller/subsystem/persistence/proc/SaveTCGCards()
for(var/i in GLOB.joined_player_list)
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.tcg_cards)
continue
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
if(!original_human || original_human.stat == DEAD || !(original_human == ending_human))
continue
var/obj/item/tcgcard_binder/binder = locate() in ending_human
if(!binder || !length(binder.cards))
continue
var/list/card_types = list()
for(var/obj/item/tcg_card/card in binder.cards)
//if(!card.illegal) //Uncomment if you want to block syndie cards from saving
card_types[card.datum_type] = card.illegal
ending_human.client.prefs.tcg_cards = card_types
ending_human.client.prefs.save_character(TRUE)
+4 -3
View File
@@ -26,15 +26,16 @@ GLOBAL_LIST_EMPTY(GPS_list)
if(. == COMPONENT_INCOMPATIBLE || !isitem(parent))
return COMPONENT_INCOMPATIBLE
var/atom/A = parent
A.add_overlay("working")
if(starton)
A.add_overlay("working")
else
tracking = FALSE
A.name = "[initial(A.name)] ([gpstag])"
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
if(!emp_proof)
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_AltClick)
if(!starton)
tracking = FALSE
///Called on COMSIG_ITEM_ATTACK_SELF
/datum/component/gps/item/proc/interact(datum/source, mob/user)
@@ -0,0 +1,49 @@
/**
*A storage component to be used on card piles, for use as hands/decks/discard piles. Don't use on something that's not a card pile!
*/
/datum/component/storage/concrete/tcg
display_numerical_stacking = FALSE
max_w_class = WEIGHT_CLASS_TINY
max_items = 30
max_combined_w_class = WEIGHT_CLASS_TINY * 30
///The deck that the card pile is using for FAIR PLAY.
/datum/component/storage/concrete/tcg/can_be_inserted(obj/item/I, stop_messages, mob/M)
. = ..()
return istype(I, /obj/item/tcg_card)
/datum/component/storage/concrete/tcg/PostTransfer()
. = ..()
handle_empty_deck()
/datum/component/storage/concrete/tcg/remove_from_storage(atom/movable/AM, atom/new_location)
. = ..()
handle_empty_deck()
/datum/component/storage/concrete/tcg/ui_show(mob/M)
. = ..()
M.visible_message("<span class='notice'>[M] starts to look through the contents of \the [parent]!</span>", \
"<span class='notice'>You begin looking into the contents of \the [parent]!</span>")
/datum/component/storage/concrete/tcg/close(mob/M)
. = ..()
var/list/card_contents = contents()
var/obj/temp_parent = parent
temp_parent.visible_message("<span class='notice'>\the [parent] is shuffled after looking through it.</span>")
card_contents = shuffle(card_contents)
/datum/component/storage/concrete/tcg/mass_remove_from_storage(atom/target, list/things, datum/progressbar/progress, trigger_on_found)
. = ..()
if(!things.len)
qdel(parent)
/datum/component/storage/concrete/tcg/proc/handle_empty_deck()
var/list/contents = contents()
//You can't have a deck of one card!
if(contents.len == 1)
var/obj/item/tcgcard_deck/deck = parent
var/obj/item/tcg_card/card = contents[1]
remove_from_storage(card, card.drop_location())
card.flipped = deck.flipped
card.update_icon_state()
qdel(parent)
+3 -3
View File
@@ -228,10 +228,10 @@
gain_text = "You've learned an extra language!"
lose_text = "You've forgotten your extra language."
/datum/quirk/multilingual/add()
/datum/quirk/multilingual/post_add()
var/mob/living/carbon/human/H = quirk_holder
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MIND)
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
/datum/quirk/multilingual/remove()
var/mob/living/carbon/human/H = quirk_holder
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MIND)
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
+2
View File
@@ -264,6 +264,8 @@ What a mess.*/
active1 = null
if(!( GLOB.data_core.security.Find(active2) ))
active2 = null
if(!authenticated && href_list["choice"] != "Log In") // logging in is the only action you can do if not logged in
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
switch(href_list["choice"])
+21 -15
View File
@@ -10,35 +10,41 @@
/obj/item/armorkit/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
// yeah have fun making subtypes and modifying the afterattack if you want to make variants
// idiot
// - hatter
var/used = FALSE
if(isobj(target) && istype(target, /obj/item/clothing/under))
var/obj/item/clothing/under/C = target
if(C.armor.melee < 10)
C.armor.melee = 10
if(C.damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [C] first.</span>")
return
if(C.attached_accessory)
to_chat(user,"<span class='warning'>Kind of hard to sew around [C.attached_accessory].</span>")
return
if(C.armor.getRating("melee") < 10)
C.armor = C.armor.setRating("melee" = 10)
used = TRUE
if(C.armor.laser < 10)
C.armor.laser = 10
if(C.armor.getRating("laser") < 10)
C.armor = C.armor.setRating("laser" = 10)
used = TRUE
if(C.armor.fire < 40)
C.armor.fire = 40
if(C.armor.getRating("fire") < 40)
C.armor = C.armor.setRating("fire" = 40)
used = TRUE
if(C.armor.acid < 10)
C.armor.acid = 10
if(C.armor.getRating("acid") < 10)
C.armor = C.armor.setRating("acid" = 10)
used = TRUE
if(C.armor.bomb < 5)
C.armor.bomb = 5
if(C.armor.getRating("bomb") < 5)
C.armor = C.armor.setRating("bomb" = 5)
used = TRUE
if(used)
user.visible_message("<span class = 'notice'>[user] uses [src] on [C], reinforcing it and tossing the empty case away afterwards.</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it a little more protective! You toss the empty casing away afterwards.</span>")
C.name = "durathread [C.name]" // this disappears if it gets repaired, which is annoying
user.visible_message("<span class = 'notice'>[user] reinforces [C] with [src].</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it as protective as a durathread jumpsuit.</span>")
C.name = "durathread [C.name]"
C.upgrade_prefix = "durathread" // god i hope this works
qdel(src)
return
else
to_chat(user, "<span class = 'notice'>You stare at [src] and [C], coming to the conclusion that you probably don't need to reinforce it any further.")
to_chat(user, "<span class = 'notice'>You don't need to reinforce [C] any further.")
return
else
return
+2 -1
View File
@@ -8,11 +8,12 @@
slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME
var/gpstag = "COM0"
var/emp_proof = FALSE
var/starton = TRUE
/obj/item/gps/Initialize()
. = ..()
AddComponent(/datum/component/gps/item, gpstag, starton)
AddComponent(/datum/component/gps/item, gpstag, emp_proof, starton)
/obj/item/gps/science
icon_state = "gps-s"
+8 -1
View File
@@ -245,6 +245,9 @@
slowdown = 7
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
/obj/item/restraints/legcuffs/proc/on_removed()
return
/obj/item/restraints/legcuffs/beartrap
name = "bear trap"
throw_speed = 1
@@ -376,4 +379,8 @@
icon_state = "ebola"
hitsound = 'sound/weapons/taserhit.ogg'
w_class = WEIGHT_CLASS_SMALL
breakouttime = 60
breakouttime = 25
/obj/item/restraints/legcuffs/bola/energy/on_removed()
do_sparks(1, TRUE, src)
qdel(src)
@@ -466,6 +466,7 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5), \
new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \
new/datum/stack_recipe("folder", /obj/item/folder), \
new/datum/stack_recipe("cardboard card", /obj/item/cardboard_card, 1), \
// holy fuck why are there so many boxes
new/datum/stack_recipe_list("fancy boxes", list ( \
new /datum/stack_recipe("donut box", /obj/item/storage/fancy/donut_box), \
@@ -526,3 +526,8 @@
new /obj/item/book/granter/martial/carp(src)
new /obj/item/clothing/suit/hooded/carp_costume(src)
new /obj/item/staff/bostaff(src)
/obj/item/storage/box/syndie_kit/sleepytime/cardpack/PopulateContents()
. = ..()
new /obj/item/cardpack/syndicate(src)
new /obj/item/cardpack/syndicate(src)
@@ -149,8 +149,6 @@
if(prob(50))
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
add_objective(new/datum/objective/destroy, TRUE)
else if(prob(30))
add_objective(new/datum/objective/maroon, TRUE)
else
add_objective(new/datum/objective/assassinate, TRUE)
else
@@ -441,19 +441,20 @@
else
kill_objective.find_target()
objectives += kill_objective
else
/*else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
if(team_mode)
maroon_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
else
maroon_objective.find_target()
objectives += maroon_objective
objectives += maroon_objective*/
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
identity_theft.target = maroon_objective.target
identity_theft.target = kill_objective.target
identity_theft.update_explanation_text()
objectives += identity_theft
escape_objective_possible = FALSE
@@ -8,7 +8,7 @@
descname = "Powers Nearby Structures"
name = "Sigil of Transmission"
desc = "Places a sigil that can drain and will store energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
invocations = list("Divinity...", "...power our creations.")
channel_time = 70
power_cost = 200
whispered = TRUE
@@ -28,7 +28,7 @@
descname = "Powered Structure, Delay Emergency Shuttles"
name = "Prolonging Prism"
desc = "Creates a mechanized prism which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost."
invocations = list("May this prism...", "...grant us time to enact his will!")
invocations = list("May this prism...", "...grant us time to enact his will.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/prolonging_prism
@@ -60,7 +60,7 @@
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
invocations = list("May this transmitter...", "...break the will of all who oppose us.")
channel_time = 80
power_cost = 750
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
@@ -83,7 +83,7 @@
descname = "Powered Structure, Teleportation Hub"
name = "Clockwork Obelisk"
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
invocations = list("May this obelisk...", "...take us to all places.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
@@ -163,7 +163,7 @@
descname = "Well-Rounded Combat Construct"
name = "Clockwork Marauder"
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal!")
channel_time = 80
power_cost = 8000
creator_message = "<span class='brass'>Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor.</span>"
@@ -7,7 +7,7 @@
descname = "Generates Power From Starlight"
name = "Stargazer"
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
invocations = list("Capture their inferior light for us!")
invocations = list("Capture their inferior light for us.")
channel_time = 50
power_cost = 200
object_path = /obj/structure/destructible/clockwork/stargazer
@@ -16,6 +16,7 @@
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
whispered = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
quickbind = TRUE
@@ -34,7 +35,7 @@
descname = "Power Generation"
name = "Integration Cog"
desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
invocations = list("Take that which sustains them!")
invocations = list("Take that which sustains them.")
channel_time = 10
power_cost = 10
whispered = TRUE
@@ -55,7 +56,7 @@
descname = "Trap, Stunning"
name = "Sigil of Transgression"
desc = "Wards a tile with a sigil, which will briefly stun the next non-Servant to cross it and apply Belligerent to them."
invocations = list("Divinity, smite...", "...those who trespass here!")
invocations = list("Divinity, smite...", "...those who trespass here.")
channel_time = 50
power_cost = 50
whispered = TRUE
@@ -75,7 +76,7 @@
descname = "Trap, Conversion"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
invocations = list("Divinity, enlighten...", "...those who trespass here.")
channel_time = 60
power_cost = 125
whispered = TRUE
@@ -95,7 +96,7 @@
descname = "Short-Range Single-Target Stun"
name = "Kindle"
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
invocations = list("Divinity, show them your light.")
whispered = TRUE
channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy
power_cost = 125
@@ -118,7 +119,7 @@
descname = "Handcuffs"
name = "Hateful Manacles"
desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
invocations = list("Shackle the heretic!", "Break them in body and spirit!")
invocations = list("Shackle the heretic!", "Break them in body and spirit.")
channel_time = 15
power_cost = 25
whispered = TRUE
@@ -269,7 +270,7 @@
descname = "New Clockwork Slab"
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
invocations = list("Metal, become greater.")
channel_time = 10
power_cost = 25
whispered = TRUE
@@ -290,7 +291,7 @@
descname = "Limited Xray Vision Glasses"
name = "Wraith Spectacles"
desc = "Fabricates a pair of glasses which grant true sight but cause gradual vision loss."
invocations = list("Show the truth of this world to me!")
invocations = list("Show the truth of this world to me.")
channel_time = 10
power_cost = 50
whispered = TRUE
@@ -310,7 +311,7 @@
name = "Spatial Gateway"
desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
invocations = list("Spatial Gateway...", "...activate!")
invocations = list("Spatial Gateway...", "...activate.")
channel_time = 30
power_cost = 400
whispered = TRUE
@@ -29,7 +29,7 @@
descname = "Structure, Turret"
name = "Ocular Warden"
desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
invocations = list("Guardians of Engine...", "...judge those who would harm us!")
invocations = list("Guardians of Engine...", "...judge those who would harm us.")
channel_time = 100
power_cost = 250
object_path = /obj/structure/destructible/clockwork/ocular_warden
@@ -105,7 +105,7 @@
descname = "Delayed Area Knockdown Glasses"
name = "Judicial Visor"
desc = "Creates a visor that can smite an area, applying Belligerent and briefly stunning. The smote area will explode after 3 seconds."
invocations = list("Grant me the flames of Engine!")
invocations = list("Grant me the flames of Engine.")
channel_time = 10
power_cost = 400
whispered = TRUE
@@ -124,7 +124,7 @@
descname = "Shield with empowerable bashes"
name = "Nezbere's shield"
desc = "Creates a shield which generates charge from blocking damage, using it to empower its bashes tremendously. It is repaired with brass, and while very durable, extremely weak to lasers and, even more so, to energy weaponry."
invocations = list("Shield me...", "... from the coming dark!")
invocations = list("Shield me...", "... from the coming dark.")
channel_time = 20
power_cost = 600 //Shouldn't be too spammable but not too hard to get either
whispered = TRUE
@@ -143,7 +143,7 @@
descname = "Summonable Armor and Weapons"
name = "Clockwork Armaments"
desc = "Allows the invoker to summon clockwork armor and a Ratvarian spear at will. The spear's attacks will generate Vitality, used for healing."
invocations = list("Grant me armaments...", "...from the forge of Armorer!")
invocations = list("Grant me armaments...", "...from the forge of Armorer.")
channel_time = 20
power_cost = 250
whispered = TRUE
@@ -15,13 +15,16 @@
var/ignore_holy_water = FALSE
/datum/antagonist/clockcult/silent
name = "Silent Clock Cultist"
silent = TRUE
show_in_antagpanel = FALSE //internal
/datum/antagonist/clockcult/neutered
name = "Neutered Clock Cultist"
neutered = TRUE
/datum/antagonist/clockcult/neutered/traitor
name = "Traitor Clock Cultist"
ignore_eligibility_check = TRUE
ignore_holy_water = TRUE
show_in_roundend = FALSE
@@ -185,7 +188,7 @@
/datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin)
add_servant_of_ratvar(new_owner.current, TRUE)
add_servant_of_ratvar(new_owner.current, TRUE, override_type = type)
message_admins("[key_name_admin(admin)] has made [new_owner.current] into a servant of Ratvar.")
log_admin("[key_name(admin)] has made [new_owner.current] into a servant of Ratvar.")
+2
View File
@@ -19,9 +19,11 @@
var/ignore_holy_water = FALSE
/datum/antagonist/cult/neutered
name = "Neutered Cultist"
neutered = TRUE
/datum/antagonist/cult/neutered/traitor
name = "Traitor Cultist"
ignore_eligibility_checks = TRUE
ignore_holy_water = TRUE
show_in_roundend = FALSE
@@ -8,11 +8,9 @@
/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/permakill_prob = 20
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
permakill_prob = max(0,mode.threat_level-50)
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
@@ -20,11 +18,6 @@
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(permakill_prob))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
@@ -41,11 +41,6 @@
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
@@ -17,11 +17,6 @@
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else
var/list/weights = list()
weights["sabo"] = length(subtypesof(/datum/sabotage_objective))
@@ -304,7 +304,7 @@
"danger_level" = cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure)
))
if(!locked || hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE))
if(!locked || hasSiliconAccessInArea(user, PRIVILEGES_SILICON|PRIVILEGES_DRONE))
data["vents"] = list()
for(var/id_tag in A.air_vent_names)
var/long_name = A.air_vent_names[id_tag]
@@ -385,13 +385,13 @@
if(..() || buildstage != 2)
return
var/silicon_access = hasSiliconAccessInArea(usr)
var/bot_priviledges = silicon_access || (usr.silicon_privileges & PRIVILEDGES_DRONE)
if((locked && !bot_priviledges) || (silicon_access && aidisabled))
var/bot_privileges = silicon_access || (usr.silicon_privileges & PRIVILEGES_DRONE)
if((locked && !bot_privileges) || (silicon_access && aidisabled))
return
var/device_id = params["id_tag"]
switch(action)
if("lock")
if(bot_priviledges && !wires.is_cut(WIRE_IDSCAN))
if(bot_privileges && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
. = TRUE
if("power", "toggle_filter", "widenet", "scrubbing")
+21 -2
View File
@@ -318,7 +318,7 @@
/obj/item/clothing/under/suit/white, // white is a weird color for a groom but some people are weird
/obj/item/clothing/under/suit/polychromic,
/obj/item/clothing/under/suit/polychromic, // in case you can't be satisfied with the most fitting choices, of course.
/obj/item/clothing/under/dress/wedding,
/obj/item/clothing/under/dress/wedding,
/obj/item/clothing/under/dress/wedding, // this is what you actually bought the crate for. You can't get these anywhere else.
/obj/item/clothing/under/dress/wedding/orange,
/obj/item/clothing/under/dress/wedding/orange,
@@ -333,4 +333,23 @@
/obj/item/storage/fancy/ringbox/silver,
/obj/item/storage/fancy/ringbox/silver) //diamond rings cost the same price as this crate via cargo so we're not giving you two for free. Wedding rings are traditionally less valuable anyway.
crate_name = "wedding crate"
/datum/supply_pack/costumes_toys/randomised/tcg
name = "Big-Ass Booster Pack Pack"
desc = "A bumper load of NT TCG Booster Packs of varying series. Collect them all!"
cost = 3000
contains = list()
crate_name = "booster pack pack"
/datum/supply_pack/costumes_toys/randomised/tcg/generate()
. = ..()
var/cardpacktype
var/list/cardtypes = subtypesof(/obj/item/cardpack)
for(var/cardtype in cardtypes)
var/obj/item/cardpack/pack = new cardtype(.)
if(pack.illegal)
cardtypes.Remove(cardtype)
qdel(pack)
for(var/i in 1 to 10)
cardpacktype = pick(cardtypes)
new cardpacktype(.)
+9 -7
View File
@@ -76,9 +76,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
return
//Logs all hrefs, except chat pings
if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2))
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
// Tgui Topic middleware
if(tgui_Topic(href_list))
if(CONFIG_GET(flag/emergency_tgui_logging))
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
return
//Logs all hrefs
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
//byond bug ID:2256651
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
@@ -105,10 +111,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
handle_statpanel_click(href_list)
return
// Tgui Topic middleware
if(tgui_Topic(href_list))
return
// Admin PM
if(href_list["priv_msg"])
cmd_admin_pm(href_list["priv_msg"],null)
+2
View File
@@ -220,6 +220,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/hide_ckey = FALSE //pref for hiding if your ckey shows round-end or not
var/list/tcg_cards = list()
/datum/preferences/New(client/C)
parent = C
+14 -1
View File
@@ -271,7 +271,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
loadout_data["SAVE_[i]"] = list()
for(var/some_gear_item in saved_loadout_paths)
if(!ispath(text2path(some_gear_item)))
message_admins("Failed to copy item [some_gear_item] to new loadout system when migrating from version [current_version] to 40, issue: item is not a path")
log_game("Failed to copy item [some_gear_item] to new loadout system when migrating from version [current_version] to 40, issue: item is not a path")
continue
var/datum/gear/gear_item = text2path(some_gear_item)
if(!(initial(gear_item.loadout_flags) & LOADOUT_CAN_COLOR_POLYCHROMIC))
@@ -658,6 +658,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
modified_limbs = safe_json_decode(limbmodstr)
else
modified_limbs = list()
var/tcgcardstr
S["tcg_cards"] >> tcgcardstr
if(length(tcgcardstr))
tcg_cards = safe_json_decode(tcgcardstr)
else
tcg_cards = list()
S["chosen_limb_id"] >> chosen_limb_id
S["hide_ckey"] >> hide_ckey //saved per-character
@@ -1095,6 +1103,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else
S["loadout"] << safe_json_encode(list())
if(length(tcg_cards))
S["tcg_cards"] << safe_json_encode(tcg_cards)
else
S["tcg_cards"] << safe_json_encode(list())
cit_character_pref_save(S)
return 1
+5
View File
@@ -31,6 +31,9 @@
// What items can be consumed to repair this clothing (must by an /obj/item/stack)
var/repairable_by = /obj/item/stack/sheet/cloth
// has this item been upgraded by an upgrade kit (see: durathread armor kits)
var/upgrade_prefix
//Var modification - PLEASE be careful with this I know who you are and where you live
var/list/user_vars_to_edit //VARNAME = VARVALUE eg: "name" = "butts"
var/list/user_vars_remembered //Auto built by the above + dropped() + equipped()
@@ -120,6 +123,8 @@
update_clothes_damaged_state(CLOTHING_PRISTINE)
obj_integrity = max_integrity
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
if(upgrade_prefix)
name = upgrade_prefix + " " + initial(name)
body_parts_covered = initial(body_parts_covered)
slot_flags = initial(slot_flags)
damage_by_parts = null
@@ -220,8 +220,8 @@
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 2.25 SECONDS
parry_failed_stagger_duration = 2.25 SECONDS
parry_cooldown = 0
parry_failed_clickcd_duration = 0
parry_cooldown = 3 SECONDS
parry_failed_clickcd_duration = 0.5 SECONDS
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
+11
View File
@@ -51,6 +51,17 @@
desc = "Very gay shoes."
icon_state = "rain_bow"
/obj/item/clothing/shoes/sneakers/poly/polychromic
name = "polychromic shoes"
desc = "Every color."
icon_state = "poly"
item_state = "poly"
var/list/poly_colors = list("#FFFFFF", "#1D1D1D")
/obj/item/clothing/shoes/sneakers/poly/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 2)
/obj/item/clothing/shoes/sneakers/orange
name = "orange shoes"
icon_state = "orange"
+12 -1
View File
@@ -102,7 +102,18 @@
/obj/item/clothing/neck/cloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/neck/cancloak/polychromic
name = "canvas cloak"
desc = "A rugged cloak made of canvas."
icon_state = "cancloak"
item_state = "cancloak"
var/list/poly_colors = list("#585858", "#373737", "#BEBEBE")
/obj/item/clothing/neck/cancloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/neck/cloak/alt
name = "cloak"
desc = "A ragged up white cloak. It reminds you of a place not far from here."
@@ -1030,6 +1030,16 @@
alternate_worn_layer = UNDER_HEAD_LAYER
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/toggle/wbreakpoly
name = "polychromic windbreaker"
desc = "Perfect for windy days."
icon_state = "wbreakpoly"
item_state = "wbreakpoly"
/obj/item/clothing/suit/toggle/wbreakpoly/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#464F65", "#916035", "#474747"), 3)
/obj/item/clothing/suit/flakjack
name = "flak jacket"
desc = "A dilapidated jacket made of a supposedly bullet-proof material (Hint: It isn't.). Smells faintly of napalm."
+3
View File
@@ -32,6 +32,9 @@
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
if(damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [src] first.</span>")
return 0
var/obj/item/stack/cable_coil/C = I
I.use_tool(src, user, 0, 1)
has_sensor = HAS_SENSORS
@@ -54,7 +54,7 @@
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
playsound(H, "desceration", 50, TRUE)
if(!H.is_mouth_covered())
reagents.trans_to(H, 15, log = TRUE) //Cream pie combat
reagents.trans_to(H, 15, log = "creampie hit") //Cream pie combat
if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
H.creamed = TRUE
@@ -79,7 +79,7 @@ God bless America.
to_chat(user, "<span class='warning'>There's nothing to dissolve [I] in!</span>")
return
user.visible_message("<span class='notice'>[user] drops [I] into [src].</span>", "<span class='notice'>You dissolve [I] in [src].</span>")
I.reagents.trans_to(src, I.reagents.total_volume)
I.reagents.trans_to(src, I.reagents.total_volume, log = "pill into deep fryer")
qdel(I)
return
if(istype(I,/obj/item/clothing/head/mob_holder))
+18 -2
View File
@@ -115,13 +115,20 @@
return FALSE
var/valid = FALSE
var/list/checked = program_cache.Copy()
if(obj_flags & EMAGGED)
checked |= emag_programs
for(var/prog in checked)
var/list/P = prog
if(P["type"] == program_to_load)
valid = TRUE
break
if(obj_flags & EMAGGED) //split up into separate for loops instead of together so we can adminlog it
checked = emag_programs.Copy()
for(var/prog in checked)
var/list/P = prog
if(P["type"] == program_to_load)
valid = TRUE
log_game("[key_name(usr)] has loaded the restricted holodeck program [program_to_load]")
message_admins("[ADMIN_LOOKUPFLW(usr)] has loaded the restricted holodeck program [program_to_load]")
break
if(!valid)
return FALSE
@@ -134,6 +141,14 @@
nerf(obj_flags & EMAGGED)
obj_flags ^= EMAGGED
say("Safeties restored. Restarting...")
if(obj_flags & EMAGGED)
to_chat(usr,"<span class='warning'>You vastly increase projector power and override the safety and security protocols.</span>")
log_game("[key_name(usr)] has disabled safeties on the holodeck computer")
message_admins("[ADMIN_LOOKUPFLW(usr)] has disabled safeties on the holodeck computer")
else
to_chat(usr,"<span class='notice'>You restore the safeties to the holodeck.</span>")
log_game("[key_name(usr)] has reenabled safeties on the holodeck computer")
message_admins("[ADMIN_LOOKUPFLW(usr)] has reenabled safeties on the holodeck computer")
/obj/machinery/computer/holodeck/process()
if(damaged && prob(10))
@@ -179,6 +194,7 @@
to_chat(user, "<span class='warning'>You vastly increase projector power and override the safety and security protocols.</span>")
say("Warning. Automatic shutoff and derezzing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.")
log_game("[key_name(user)] emagged the Holodeck Control Console")
message_admins("[ADMIN_LOOKUPFLW(user)] emagged the Holodeck Control Console.")
nerf(!(obj_flags & EMAGGED))
/obj/machinery/computer/holodeck/emp_act(severity)
+2 -1
View File
@@ -527,12 +527,13 @@
else if(istype(O, /obj/item/seeds) && !istype(O, /obj/item/seeds/sample))
if(!myseed)
if(istype(O, /obj/item/seeds/kudzu))
investigate_log("had Kudzu planted in it by [key_name(user)] at [AREACOORD(src)]","kudzu")
investigate_log("had Kudzu planted in it by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_BOTANY)
if(!user.transferItemToLoc(O, src))
return
to_chat(user, "<span class='notice'>You plant [O].</span>")
dead = FALSE
myseed = O
investigate_log("planting: [user] planted [O] with traits [english_list(myseed)] and reagents [english_list_assoc(myseed.reagents_add)] and potency [myseed.potency]", INVESTIGATE_BOTANY)
TRAY_NAME_UPDATE
age = 1
plant_health = myseed.endurance
+2
View File
@@ -188,6 +188,8 @@
///The Number of products produced by the plant, typically the yield.
var/product_count = getYield()
parent.investigate_log("manual harvest by [key_name(user)] of [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list_assoc(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY)
while(t_amount < product_count)
var/obj/item/reagent_containers/food/snacks/grown/t_prod
if(instability >= 30 && (seed_flags & MUTATE_EARLY) && LAZYLEN(mutatelist) && prob(instability/3))
+50 -2
View File
@@ -128,10 +128,58 @@
if(dbflags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE) //they have not completed age gate
var/age_verification = age_gate()
if(age_verification != 1)
client.add_system_note("Automated-Age-Gate", "Failed automatic age gate process")
client.add_system_note("Automated-Age-Gate", "Failed automatic age gate process.")
//ban them and kick them
AddBan(client.ckey, client.computer_id, "SYSTEM BAN - Inputted date during join verification was under 18 years of age. Contact administration on discord for verification.", "SYSTEM", FALSE, null, client.address)
//parameters used by sql line, easier to read:
var/bantype_str = "ADMIN_PERMABAN"
var/reason = "SYSTEM BAN - Inputted date during join verification was under 18 years of age. Contact administration on discord for verification."
var/duration = -1
var/sql_ckey = sanitizeSQL(client.ckey)
var/computerid = client.computer_id
if(!computerid)
computerid = "0"
var/sql_computerid = sanitizeSQL(computerid)
var/ip = client.address
if(!ip)
ip = "0.0.0.0"
var/sql_ip = sanitizeSQL(ip)
//parameter not used as there's no job but i want to fill out all parameters for the insert line
var/sql_job
// these are typically the banning admin's, but it's the system so we leave them null, but they're still here for the sake of a full set of values
var/sql_a_ckey
var/sql_a_computerid
var/sql_a_ip
// record all admins and non-admins online at the time
var/who
for(var/client/C in GLOB.clients)
if(!who)
who = "[C]"
else
who += ", [C]"
var/adminwho
for(var/client/C in GLOB.admins)
if(!adminwho)
adminwho = "[C]"
else
adminwho += ", [C]"
var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]', '[bantype_str]', '[reason]', '[sql_job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[sql_ckey]', '[sql_computerid]', INET_ATON('[sql_ip]'), '[sql_a_ckey]', '[sql_a_computerid]', INET_ATON('[sql_a_ip]'), '[who]', '[adminwho]')"
var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql)
qdel(query_add_ban)
// announce this
message_admins("[html_encode(client.ckey)] has been banned for failing the automatic age gate.")
send2irc("[html_encode(client.ckey)] has been banned for failing the automatic age gate.")
// removing the client disconnects them
qdel(client)
return FALSE
else
//they claim to be of age, so allow them to continue and update their flags
@@ -11,6 +11,8 @@
maxHealth = 25
health = 25
can_ventcrawl = TRUE
var/amount_grown = 0
var/max_grown = 100
var/time_of_birth
+3
View File
@@ -434,6 +434,9 @@
legcuffed.forceMove(drop_location())
legcuffed = null
I.dropped(src)
if(istype(I, /obj/item/restraints/legcuffs))
var/obj/item/restraints/legcuffs/lgcf = I
lgcf.on_removed()
update_inv_legcuffed()
return
else
@@ -95,9 +95,10 @@
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = 3
parry_cooldown = 30
parry_failed_stagger_duration = 0
parry_failed_clickcd_duration = 0.4
parry_cooldown = 3 SECONDS
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 0.4 SECONDS
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
@@ -135,16 +136,16 @@
parry_imperfect_falloff_percent = 20
parry_efficiency_perfect = 100
parry_efficiency_perfect_override = list(
ATTACK_TYPE_PROJECTILE_TEXT = 60,
TEXT_ATTACK_TYPE_PROJECTILE = 60,
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 0
parry_cooldown = 0
parry_failed_clickcd_duration = 0.8
parry_failed_cooldown_duration = 3 SECONDS
parry_failed_stagger_duration = 2 SECONDS
parry_cooldown = 3 SECONDS
parry_failed_clickcd_duration = 0.8 SECONDS
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
@@ -1425,8 +1425,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
var/punchwoundbonus = user.dna.species.punchwoundbonus
var/puncherstam = user.getStaminaLoss()
var/puncherbrute = user.getBruteLoss()
var/punchedstam = target.getStaminaLoss()
var/punchedbrute = target.getBruteLoss()
@@ -1434,7 +1432,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.2
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.8
damage *= 0.65
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.8
//END OF CITADEL CHANGES
@@ -1446,19 +1444,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!affecting) //Maybe the bodypart is missing? Or things just went wrong..
affecting = target.get_bodypart(BODY_ZONE_CHEST) //target chest instead, as failsafe. Or hugbox? You decide.
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)
miss_chance = 0
else
if(user.dna.species.punchdamagelow)
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
miss_chance = 0
else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists, being good at Punching People, also never miss
miss_chance = 0
else
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
if(!damage || !affecting)//future-proofing for species that have 0 damage/weird cases where no zone is targeted
playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1)
target.visible_message("<span class='danger'>[user]'s [atk_verb] misses [target]!</span>", \
"<span class='danger'>You avoid [user]'s [atk_verb]!</span>", "<span class='hear'>You hear a swoosh!</span>", null, COMBAT_MESSAGE_RANGE, null, \
+4
View File
@@ -26,6 +26,8 @@
update_sprint_icon()
/mob/living/proc/enable_sprint_mode(update_icon = TRUE)
if(!CONFIG_GET(flag/sprint_enabled))
return
if(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
return
ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_ACTIVE)
@@ -61,6 +63,8 @@
update_sprint_icon()
/mob/living/proc/user_toggle_intentional_sprint_mode()
if(!CONFIG_GET(flag/sprint_enabled))
return
var/old = (combat_flags & COMBAT_FLAG_SPRINT_TOGGLED)
if(old)
if(combat_flags & COMBAT_FLAG_SPRINT_FORCED)
+1 -1
View File
@@ -11,7 +11,7 @@
maxHealth = 500
layer = BELOW_MOB_LAYER
var/obj/item/instrument/piano_synth/internal_instrument
silicon_privileges = PRIVILEDGES_PAI
silicon_privileges = PRIVILEGES_PAI
var/network = "ss13"
var/obj/machinery/camera/current = null
@@ -1,4 +1,7 @@
/mob/living/silicon/robot/default_toggle_sprint(shutdown = FALSE)
if(!CONFIG_GET(flag/sprint_enabled))
disable_intentional_sprint_mode()
return
var/current = (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
if(current || shutdown || !cell || (cell.charge < 25) || !cansprint)
disable_intentional_sprint_mode()
+1 -1
View File
@@ -1,6 +1,6 @@
/mob/living/silicon
gender = NEUTER
silicon_privileges = PRIVILEDGES_SILICON
silicon_privileges = PRIVILEGES_SILICON
verb_say = "states"
verb_ask = "queries"
verb_exclaim = "declares"
@@ -15,7 +15,7 @@
maxbodytemp = INFINITY
minbodytemp = 0
blood_volume = 0
silicon_privileges = PRIVILEDGES_BOT
silicon_privileges = PRIVILEGES_BOT
sentience_type = SENTIENCE_ARTIFICIAL
status_flags = NONE //no default canpush
verb_say = "states"
@@ -340,6 +340,7 @@
target = null
playsound(src, 'sound/effects/whistlereset.ogg', 50, TRUE)
return
if(isspaceturf(target_turf))
//Must be a hull breach or in line mode to continue.
if(!is_hull_breach(target_turf) && !targetdirection)
@@ -355,9 +356,9 @@
sleep(50)
if(mode == BOT_REPAIRING && src.loc == target_turf)
if(autotile) //Build the floor and include a tile.
target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
else //Build a hull plating without a floor tile.
target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else //Build a hull plating without a floor tile.
target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
else
var/turf/open/floor/F = target_turf
@@ -371,7 +372,7 @@
if(mode == BOT_REPAIRING && F && src.loc == F)
F.broken = 0
F.burnt = 0
F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
F.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
anchored = TRUE
@@ -433,4 +434,4 @@
if(robot.mode == BOT_REPAIRING)
return TRUE
return FALSE
@@ -40,7 +40,7 @@
bubble_icon = "machine"
initial_language_holder = /datum/language_holder/drone
mob_size = MOB_SIZE_SMALL
silicon_privileges = PRIVILEDGES_DRONE
silicon_privileges = PRIVILEGES_DRONE
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
+3 -3
View File
@@ -408,7 +408,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return
return TRUE
/atom/proc/hasSiliconAccessInArea(mob/user, flags = PRIVILEDGES_SILICON)
/atom/proc/hasSiliconAccessInArea(mob/user, flags = PRIVILEGES_SILICON)
return user.silicon_privileges & (flags) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas))
/mob/proc/toggleSiliconAccessArea(area/area)
@@ -496,7 +496,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
colored_message = "<font color=[color]>[message]</font>"
else
colored_message = "<font color='[color]'>[message]</font>"
//This makes readability a bit better for admins.
switch(message_type)
if(LOG_WHISPER)
@@ -507,7 +507,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
colored_message = "(ASAY) [colored_message]"
if(LOG_EMOTE)
colored_message = "(EMOTE) [colored_message]"
var/list/timestamped_message = list("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(src)] [loc_name(src)] (Event #[LAZYLEN(logging[smessage_type])])" = colored_message)
logging[smessage_type] += timestamped_message
+1 -1
View File
@@ -146,7 +146,7 @@
return
reagents.clear_reagents()
// This also reacts them. No nitroglycerin deathpools, sorry gamers :(
W.reagents.trans_to(reagents, max_beaker_transfer)
W.reagents.trans_to(reagents, max_beaker_transfer, log = "pool fill from reagent container")
user.visible_message("<span class='notice'>[src] makes a slurping noise.</span>", "<span class='notice'>All of the contents of [W] are quickly suctioned out by the machine!</span")
updateUsrDialog()
var/list/reagent_names = list()
+4 -4
View File
@@ -903,7 +903,7 @@
if(H && !H.stealthmode && H.toggled)
abilitiesavail = TRUE
var/list/data = list(
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE),
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user, PRIVILEGES_SILICON|PRIVILEGES_DRONE),
"failTime" = failure_timer,
"isOperating" = operating,
"externalPower" = main_status,
@@ -994,7 +994,7 @@
return TRUE
if (user == hijacker || (area.hasSiliconAccessInArea(user) && !aidisabled))
return TRUE
if(user.silicon_privileges & PRIVILEDGES_SILICON)
if(user.silicon_privileges & PRIVILEGES_SILICON)
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
if (src.aidisabled || malfhack && istype(malfai) && ((istype(AI) && (malfai!=AI && malfai != AI.parent)) || (istype(robot) && (robot in malfai.connected_robots))))
@@ -1023,7 +1023,7 @@
if(action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button
hijack(usr)
return
if(locked && !area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) && !failure_timer && action != "toggle_nightshift" && (!integration_cog || !(is_servant_of_ratvar(usr))))
if(locked && !area.hasSiliconAccessInArea(usr, PRIVILEGES_SILICON|PRIVILEGES_DRONE) && !failure_timer && action != "toggle_nightshift" && (!integration_cog || !(is_servant_of_ratvar(usr))))
return
switch(action)
if("lock")
@@ -1064,7 +1064,7 @@
update()
. = TRUE
if("overload")
if(area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE)) //usr.has_unlimited_silicon_privilege)
if(area.hasSiliconAccessInArea(usr, PRIVILEGES_SILICON|PRIVILEGES_DRONE)) //usr.has_unlimited_silicon_privilege)
overload_lighting()
. = TRUE
if("hack")
@@ -2663,3 +2663,32 @@
M.SetSleeping(0, 0)
..()
//Nerdy card reagents
/datum/reagent/card_powder
var/rarity = "Stoopid"
/datum/reagent/card_powder/blue
name = "Blue Card Powder"
rarity = "Rare"
color = "#00B7EF" // blue
/datum/reagent/card_powder/purple
name = "Purple Card Powder"
rarity = "Epic"
color = "#DA00FF" // purple
/datum/reagent/card_powder/yellow
name = "Yellow Crayon Powder"
rarity = "Legendary"
color = "#FFF200" // yellow
/datum/reagent/card_powder/green
name = "Green Crayon Powder"
rarity = "Common"
color = "#A8E61D" // green
/datum/reagent/card_powder/black
name = "Black Crayon Powder"
rarity = "Exodia"
color = "#1C1C1C" // not quite black
@@ -881,3 +881,29 @@
results = list(/datum/reagent/carbon = 1)
required_reagents = list(/datum/reagent/cellulose = 1)
required_temp = 512
//Nerdy card shit
/datum/chemical_reaction/card_powder/blue
name = "Blue Card Powder"
id = /datum/reagent/card_powder/blue
results = list(/datum/reagent/card_powder/blue = 1)
required_reagents = list(/datum/reagent/card_powder/green = 12)
/datum/chemical_reaction/card_powder/purple
name = "Purple Card Powder"
id = /datum/reagent/card_powder/purple
results = list(/datum/reagent/card_powder/purple = 1)
required_reagents = list(/datum/reagent/card_powder/blue = 12)
/datum/chemical_reaction/card_powder/yellow
name = "Yellow Card Powder"
id = /datum/reagent/card_powder/yellow
results = list(/datum/reagent/card_powder/yellow = 1)
required_reagents = list(/datum/reagent/card_powder/purple = 12)
/datum/chemical_reaction/card_powder/black
name = "Black Card Powder"
id = /datum/reagent/card_powder/black
results = list(/datum/reagent/card_powder/black = 1)
required_reagents = list(/datum/reagent/card_powder/yellow = 12)
@@ -48,7 +48,7 @@
safe_thing.create_reagents(100, NONE, NO_REAGENTS_VALUE)
reagents.reaction(safe_thing, TOUCH, fraction)
trans = reagents.trans_to(safe_thing, amount_per_transfer_from_this)
trans = reagents.trans_to(safe_thing, amount_per_transfer_from_this, log = "failed squirt")
target.visible_message("<span class='danger'>[user] tries to squirt something into [target]'s eyes, but fails!</span>", \
"<span class='userdanger'>[user] tries to squirt something into [target]'s eyes, but fails!</span>")
@@ -67,7 +67,7 @@
var/mob/M = target
log_combat(user, M, "squirted", reagents.log_list())
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
trans = src.reagents.trans_to(target, amount_per_transfer_from_this, log = "dropper drop")
to_chat(user, "<span class='notice'>You transfer [trans] unit\s of the solution.</span>")
update_icon()
@@ -81,7 +81,7 @@
to_chat(user, "<span class='warning'>[target] is empty!</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, log = "dropper fill")
to_chat(user, "<span class='notice'>You fill [src] with [trans] unit\s of the solution.</span>")
@@ -41,7 +41,7 @@
if(M.reagents)
var/trans = 0
if(!infinite)
trans = reagents.trans_to(M, amount_per_transfer_from_this, log = TRUE)
trans = reagents.trans_to(M, amount_per_transfer_from_this, log = "hypospray injection")
else
trans = reagents.copy_to(M, amount_per_transfer_from_this)
@@ -427,7 +427,7 @@
var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
vial.reagents.reaction(L, method, fraction)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this, log = TRUE)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this, log = "hypospray fill")
var/long_sound = vial.amount_per_transfer_from_this >= 15
playsound(loc, long_sound ? 'sound/items/hypospray_long.ogg' : pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
to_chat(user, "<span class='notice'>You [fp_verb] [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.</span>")
@@ -39,7 +39,7 @@
C.visible_message("<span class='danger'>[user] is trying to smother \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] is trying to smother you with \the [src]!</span>", "<span class='italics'>You hear some struggling and muffled cries of surprise.</span>")
if(do_after(user, 20, target = C))
reagents.reaction(C, INGEST)
reagents.trans_to(C, 5, log = TRUE)
reagents.trans_to(C, 5, log = "rag smother")
C.visible_message("<span class='danger'>[user] has smothered \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] has smothered you with \the [src]!</span>", "<span class='italics'>You hear some struggling and a heavy breath taken.</span>")
log_combat(user, C, "smothered", log_object)
else
@@ -107,7 +107,7 @@
reagents.clear_reagents()
else
msg += "'s liquids into \the [target]"
reagents.trans_to(target, reagents.total_volume, log = TRUE)
reagents.trans_to(target, reagents.total_volume, log = "rag squeeze dry")
to_chat(user, "<span class='notice'>[msg].</span>")
return TRUE
+1 -1
View File
@@ -36,6 +36,6 @@
log_combat(owner, null, "swallowed an implanted pill", target)
if(target.reagents.total_volume)
target.reagents.reaction(owner, INGEST)
target.reagents.trans_to(owner, target.reagents.total_volume, log = TRUE)
target.reagents.trans_to(owner, target.reagents.total_volume, log = "dental pill swallow")
qdel(target)
return 1
+714
View File
@@ -0,0 +1,714 @@
#define TAPPED_ANGLE 90
#define UNTAPPED_ANGLE 0
#define COMMON_SERIES list(/datum/tcg_card/pack_1, /datum/tcg_card/exodia) //So star cards don't drop
/datum/tcg_card
var/name = "Stupid Coder"
var/desc = "A coder that fucked up this card. Report if you see this."
var/rules = "Tap this card. It will ahelp itself"
var/icon_state = "cardback"
var/pack = 'icons/obj/tcg/pack_1.dmi'
var/mana_cost = 0
var/attack = 0
var/health = 0
var/faction = "Coderbus"
var/rarity = "Stoopid"
var/card_type = "Unit"
var/obj/item/tcg_card/card
/*Uncomment if you want to make the game automatic
/datum/tcg_card/proc/Use(datum/tcg_card/affected_card, mob/living/user)
if(card_type == "Equipment")
affected_card.health += health
affected_card.attack += attack
to_chat(user, "<span class ='notice'>You use [card] on [affected_card.card], upgrading it's stats.</span>")
user.emote("uses [card] on [affected_card.card], upgrading it's stats.") //To get that visible emote. Useful if you want nice gameplay
else if (card_type == "Unit")
affected_card.health -= attack
health -= affected_card.attack
var/flavortext = "."
if(affected_card.health <= 0)
flavortext = ", killing [affected_card.card]!"
if(health <= 0)
flavortext = ", killing both [affected_card.card] and [card]!"
else
flavortext = ", killing [card] in the process!"
to_chat(user, "<span class ='notice'>You attack [affected_card.card] with [card][flavortext]</span>")
user.emote("attacks [affected_card.card] with [card][flavortext]")
*/
/datum/tcg_card/proc/UseSelf(mob/living/user)
return
/datum/tcg_card/proc/Tap(mob/living/user) //Actually runtimes on tap! Tapping is basically disabling a card for a turn in exchange for special effects
if(type == /datum/tcg_card)
log_runtime("[user] managed to get a blank TCG card.")
/datum/tcg_card/proc/Untap(mob/living/user)
return
/datum/tcg_card/proc/Reset(mob/living/user)
to_chat(user, "<span class ='notice'>You reset [card]'s stats to original.</span>")
mana_cost = initial(mana_cost)
rules = initial(rules)
health = initial(health)
attack = initial(attack)
faction = initial(faction)
/obj/item/tcg_card
name = "TCG card"
desc = "A flipped TCG-branded card."
icon_state = "cardback"
icon = 'icons/obj/tcg/pack_1.dmi'
var/datum_type = /datum/tcg_card
var/datum/tcg_card/card_datum
w_class = WEIGHT_CLASS_TINY
var/flipped = FALSE
var/tapped = FALSE
var/special = FALSE
var/illegal = FALSE
/obj/item/tcg_card/special
special = TRUE
/obj/item/tcg_card/examine(mob/user)
. = ..()
sleep(2) //So it prints this shit after the examine
if(flipped)
return
to_chat(user, "<span class='notice'>This card has following stats:</span>")
to_chat(user, "<span class='notice'>Mana cost: [card_datum.mana_cost]</span>")
to_chat(user, "<span class='notice'>Health: [card_datum.health]</span>")
to_chat(user, "<span class='notice'>Attack: [card_datum.attack]</span>")
to_chat(user, "<span class='notice'>Faction: [card_datum.faction]</span>")
to_chat(user, "<span class='notice'>Rarity: [card_datum.rarity]</span>")
to_chat(user, "<span class='notice'>Card Type: [card_datum.card_type]</span>")
to_chat(user, "<span class='notice'>It's effect is: [card_datum.rules]</span>")
if(illegal)
to_chat(user, "<span class='warning'>It's a low-quality copy of a real card. TCG Gaming Community won't probably accept it.</span>") //Doesn't do crap, just for lulz
/obj/item/tcg_card/openTip(location, control, params, user) //Overriding for nice UI
if(flipped)
return ..()
var/desc_content = "[desc] <br> \
<span class='notice'>This card has following stats:</span> <br> \
<span class='notice'>Mana cost: [card_datum.mana_cost]</span> <br> \
<span class='notice'>Health: [card_datum.health]</span> <br> \
<span class='notice'>Attack: [card_datum.attack]</span> <br> \
<span class='notice'>Faction: [card_datum.faction]</span> <br> \
<span class='notice'>Rarity: [card_datum.rarity]</span> <br> \
<span class='notice'>Card Type: [card_datum.card_type]</span> <br> \
<span class='notice'>It's effect is: [card_datum.rules]</span>"
openToolTip(user,src,params,title = name,content = desc_content,theme = "")
/obj/item/tcg_card/New(loc, new_datum, illegal_card = FALSE)
. = ..()
if(!special)
datum_type = new_datum
card_datum = new datum_type
icon = card_datum.pack
icon_state = card_datum.icon_state
name = card_datum.name
desc = card_datum.desc
illegal = illegal_card
switch(card_datum.rarity)
if("Common")
grind_results = list(/datum/reagent/card_powder/green = 1)
if("Rare")
grind_results = list(/datum/reagent/card_powder/blue = 1)
if("Epic")
grind_results = list(/datum/reagent/card_powder/purple = 1)
if("Legendary")
grind_results = list(/datum/reagent/card_powder/yellow = 1)
if("Exodia")
grind_results = list(/datum/reagent/card_powder/black = 1)
/obj/item/tcg_card/attack_hand(mob/user)
var/list/possible_actions = list(
"Pick Up" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pickup"),
"Tap" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_tap"),
"Flip" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_flip")
)
var/result = show_radial_menu(user, src, possible_actions, require_near = TRUE, tooltips = TRUE)
switch(result)
if("Pick Up")
. = ..()
if("Flip")
flipped = !flipped
if(flipped)
icon_state = "cardback"
name = "TCG card"
desc = "A flipped TCG-branded card."
else
name = card_datum.name
desc = card_datum.desc
icon_state = card_datum.icon_state
if("Tap")
var/matrix/ntransform = matrix(transform)
if(tapped)
ntransform.TurnTo(TAPPED_ANGLE , UNTAPPED_ANGLE)
else
ntransform.TurnTo(UNTAPPED_ANGLE , TAPPED_ANGLE)
tapped = !tapped
animate(src, transform = ntransform, time = 2, easing = (EASE_IN|EASE_OUT))
if(tapped)
card_datum.Tap(user)
else
card_datum.Untap(user)
/obj/item/tcg_card/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/tcg_card))
var/obj/item/tcg_card/second_card = I
if(loc == user && second_card.loc == user)
var/obj/item/tcgcard_hand/hand = new(get_turf(user))
src.forceMove(hand)
second_card.forceMove(hand)
hand.cards.Add(src)
hand.cards.Add(second_card)
user.put_in_hands(hand)
hand.update_icon()
return ..()
var/obj/item/tcgcard_deck/new_deck = new /obj/item/tcgcard_deck(drop_location())
new_deck.flipped = flipped
user.transferItemToLoc(second_card, new_deck)//Start a new pile with both cards, in the order of card placement.
user.transferItemToLoc(src, new_deck)
new_deck.update_icon_state()
user.put_in_hands(new_deck)
new_deck.update_icon()
if(istype(I, /obj/item/tcgcard_deck))
var/obj/item/tcgcard_deck/old_deck = I
if(length(old_deck.contents) >= 30)
to_chat(user, "<span class='notice'>This pile has too many cards for a regular deck!</span>")
return
user.transferItemToLoc(src, old_deck)
flipped = old_deck.flipped
old_deck.update_icon()
update_icon()
return ..()
/obj/item/tcg_card/attack_self(mob/user)
var/list/possible_actions = list(
"Reset to Default" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_reset"),
"Change stats" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_change_stats")
)
var/result = show_radial_menu(user, src, possible_actions, require_near = TRUE, tooltips = TRUE)
switch(result)
if("Reset to Default")
card_datum.Reset(user)
user.visible_message("<span class='notice'>[user] resets [src]'s stats.</span>")
if("Change stats")
possible_actions = list(
"Health" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_health"),
"Attack" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_attack"),
"Mana" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mana")
)
result = show_radial_menu(user, src, possible_actions, require_near = TRUE, tooltips = TRUE)
switch(result)
if("Health")
card_datum.health = input(user, "What do you want health to be?", "Changing [src]'s health") as num|null
if("Attack")
card_datum.attack = input(user, "What do you want attack to be?", "Changing [src]'s attack") as num|null
if("Mana")
card_datum.mana_cost = input(user, "What do you want mana cost to be?", "Changing [src]'s mana cost") as num|null
user.visible_message("<span class='notice'>[user] changes [src]'s [result].</span>")
/obj/item/tcg_card/equipped(mob/user, slot, initial)
. = ..()
transform = matrix()
/obj/item/tcg_card/dropped(mob/user, silent)
. = ..()
transform = matrix(0.5,0,0,0,0.5,0)
/obj/item/cardpack
name = "Trading Card Pack: Coder"
desc = "Contains six complete fuckups by the coders. Report this on github please!"
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "cardpack"
w_class = WEIGHT_CLASS_TINY
///The card series to look in
var/list/series = list(/datum/tcg_card/pack_1, /datum/tcg_card/exodia)
///Chance of the pack having a coin in it out of 10
var/contains_coin = -1
///The amount of cards to draw from the rarity table
var/card_count = 5
///The rarity table, the set must contain at least one of each
var/list/rarity_table = list(
"Common" = 900,
"Rare" = 300,
"Epic" = 50,
"Legendary" = 3,
"Exodia" = 1) //Basically 0.1%, it doesn't have guar. rarity
///The amount of cards to draw from the guarenteed rarity table
var/guaranteed_count = 1
///The guaranteed rarity table, acts about the same as the rarity table. it can have as many or as few raritys as you'd like
var/list/guar_rarity = list(
"Legendary" = 1,
"Epic" = 9,
"Rare" = 30)
var/illegal = FALSE //Can cargo get it?
custom_price = PRICE_EXPENSIVE
/obj/item/cardpack/series_one
name = "Trading Card Pack: 2560 Core Set"
desc = "Contains six cards of varying rarity from the 2560 Core Set. Collect them all!"
icon_state = "cardpack"
series = list(/datum/tcg_card/pack_1, /datum/tcg_card/exodia)
contains_coin = 10
/obj/item/cardpack/syndicate //More cards. Perfect stuff for gaming gang
name = "Trading Card Pack: Nuclear Danger"
desc = "Contains twelve cards of varying rarity from 2560 Core Set and 2560 Nuclear Danger. This pack was stamped by Waffle Co."
icon_state = "cardpack_syndicate"
series = list(/datum/tcg_card/pack_1, /datum/tcg_card/pack_nuclear)
contains_coin = 100
card_count = 9
guaranteed_count = 3
guar_rarity = list( //Better chances
"Legendary" = 5,
"Epic" = 10,
"Rare" = 30)
/obj/item/cardpack/equipped(mob/user, slot, initial)
. = ..()
transform = matrix()
/obj/item/cardpack/dropped(mob/user, silent)
. = ..()
transform = matrix(0.5,0,0,0,0.5,0)
/obj/item/cardpack/attack_self(mob/user)
. = ..()
var/list/cards = buildCardListWithRarity(card_count, guaranteed_count)
var/obj/item/tcgcard_hand/hand = new(get_turf(user))
for(var/template in cards)
var/obj/item/tcg_card/card = new(hand, template, illegal)
hand.cards.Add(card)
user.put_in_hands(hand)
hand.update_icon()
to_chat(user, "<span_class='notice'>Wow! Check out these cards!</span>")
playsound(loc, 'sound/items/poster_ripped.ogg', 20, TRUE)
if(prob(contains_coin))
to_chat(user, "<span_class='notice'>...and it came with a flipper, too!</span>")
new /obj/item/coin/thunderdome(get_turf(user))
new /obj/item/tcg_rules(get_turf(user))
qdel(src)
/obj/item/cardpack/proc/buildCardListWithRarity(card_cnt, rarity_cnt)
var/list/return_cards = list()
var/list/cards = list()
for(var/card_type in series)
for(var/card in subtypesof(card_type))
var/datum/tcg_card/new_card = new card()
if(new_card.name == "Stupid Coder")
continue
cards.Add(card)
qdel(new_card)
var/list/possible_cards = list()
var/list/rarity_cards = list("Exodia" = list(), "Legendary" = list(), "Epic" = list(), "Rare" = list(), "Common" = list())
for(var/card in cards)
var/datum/tcg_card/new_card = new card()
if(new_card.name == "Stupid Coder")
continue
possible_cards[card] = rarity_table[new_card.rarity]
var/list/rarity_card_type = rarity_cards[new_card.rarity]
if(!rarity_card_type)
rarity_card_type = list()
rarity_card_type.Add(card)
rarity_cards[new_card.rarity] = rarity_card_type //FUCK CI
qdel(new_card)
for(var/card_counter = 1 to card_count)
var/cardtype = pickweight(possible_cards)
return_cards.Add(cardtype)
for(var/card_counter = 1 to guaranteed_count)
var/card_list = pickweight(guar_rarity)
return_cards.Add(pick(rarity_cards[card_list]))
return return_cards
/obj/item/coin/thunderdome
name = "Thunderdome Flipper"
desc = "A Thunderdome TCG flipper, for deciding who gets to go first. Also conveniently acts as a counter, for various purposes."
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "coin_nanotrasen"
custom_materials = list(/datum/material/plastic = 400)
material_flags = NONE
sideslist = list("nanotrasen", "syndicate")
/obj/item/coin/thunderdome/Initialize()
. = ..()
transform = matrix(0.5,0,0,0,0.5,0)
/obj/item/coin/thunderdome/equipped(mob/user, slot, initial)
. = ..()
transform = matrix()
/obj/item/coin/thunderdome/dropped(mob/user, silent)
. = ..()
transform = matrix(0.5,0,0,0,0.5,0)
/obj/item/tcgcard_deck
name = "Trading Card Pile"
desc = "A stack of TCG cards."
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "deck_up"
var/flipped = FALSE
var/static/radial_draw = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_draw")
var/static/radial_shuffle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_shuffle")
var/static/radial_pickup = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pickup")
/obj/item/tcgcard_deck/Initialize()
. = ..()
LoadComponent(/datum/component/storage/concrete/tcg)
/obj/item/tcgcard_deck/update_icon_state()
. = ..()
if(flipped)
switch(contents.len)
if(1 to 10)
icon_state = "deck_tcg_low"
if(11 to 20)
icon_state = "deck_tcg_half"
if(21 to INFINITY)
icon_state = "deck_tcg_full"
else
icon_state = "deck_up"
/obj/item/tcgcard_deck/examine(mob/user)
. = ..()
. += "<span class='notice'>\The [src] has [contents.len] cards inside.</span>"
/obj/item/tcgcard_deck/attack_hand(mob/user)
var/list/choices = list(
"Draw" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_draw"),
"Shuffle" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_shuffle"),
"Pickup" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pickup"),
"Flip" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_flip"),
)
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
if(!check_menu(user))
return
switch(choice)
if("Draw")
draw_card(user)
if("Shuffle")
shuffle_deck(user)
if("Pickup")
user.put_in_hands(src)
if("Flip")
flip_deck()
/obj/item/tcgcard_deck/Destroy()
for(var/card in 1 to contents.len)
var/obj/item/tcg_card/stored_card = contents[card]
stored_card.forceMove(drop_location())
. = ..()
/obj/item/tcgcard_deck/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/tcgcard_deck/attackby(obj/item/I, mob/living/user, params)
. = ..()
if(istype(I, /obj/item/tcg_card))
if(contents.len > 30)
to_chat(user, "<span class='notice'>This pile has too many cards for a regular deck!</span>")
return FALSE
var/obj/item/tcg_card/new_card = I
new_card.flipped = flipped
new_card.forceMove(src)
/obj/item/tcgcard_deck/attack_self(mob/living/carbon/user)
shuffle_deck(user)
return ..()
/obj/item/tcgcard_deck/proc/draw_card(mob/user)
if(!contents.len)
CRASH("A TCG deck was created with no cards inside of it.")
var/obj/item/tcg_card/drawn_card = contents[contents.len]
user.put_in_hands(drawn_card)
drawn_card.flipped = flipped //If it's a face down deck, it'll be drawn face down, if it's a face up pile you'll draw it face up.
drawn_card.update_icon_state()
user.visible_message("<span class='notice'>[user] draws a card from \the [src]!</span>", \
"<span class='notice'>You draw a card from \the [src]!</span>")
if(contents.len <= 1)
var/obj/item/tcg_card/final_card = contents[1]
user.transferItemToLoc(final_card, drop_location())
qdel(src)
/obj/item/tcgcard_deck/proc/shuffle_deck(mob/user, visable = TRUE)
if(!contents)
return
contents = shuffle(contents)
if(user.active_storage)
user.active_storage.close(user)
if(visable)
user.visible_message("<span class='notice'>[user] shuffles \the [src]!</span>", \
"<span class='notice'>You shuffle \the [src]!</span>")
/obj/item/tcgcard_deck/proc/flip_deck()
flipped = !flipped
var/list/temp_deck = contents.Copy()
contents = reverseRange(temp_deck)
//Now flip the cards to their opposite positions.
for(var/a in 1 to contents.len)
var/obj/item/tcg_card/nu_card = contents[a]
nu_card.flipped = flipped
nu_card.update_icon_state()
update_icon_state()
/obj/item/tcgcard_hand
name = "Trading Card Hand"
desc = "A hand full of TCG cards."
icon = 'icons/effects/effects.dmi'
icon_state = "nothing"
w_class = WEIGHT_CLASS_TINY
var/list/cards = list()
/obj/item/tcgcard_hand/update_icon()
. = ..()
cut_overlays()
var/angular = length(cards) / 2 * -30 + 15
for(var/obj/item/tcg_card/card in cards)
var/image/I = image(icon = card.icon, icon_state = card.icon_state)
var/matrix/ntransform = matrix(I.transform)
ntransform.TurnTo(angular, 0)
ntransform.Translate(sin(angular) * -15, cos(angular) * 15)
I.transform = ntransform
angular += 30
overlays += I
/obj/item/tcgcard_hand/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/tcg_card))
var/obj/item/tcg_card/card = I
if(loc == user && card.loc == user)
card.forceMove(src)
cards.Add(card)
update_icon()
. = ..()
/obj/item/tcgcard_hand/attack_hand(mob/living/carbon/user)
if(loc == user)
var/list/choices = list()
for(var/obj/item/tcg_card/card in cards)
choices[card] = image(icon = card.icon, icon_state = card.icon_state)
var/obj/item/tcg_card/choice = show_radial_menu(user, src, choices, require_near = TRUE, tooltips = TRUE)
if(choice)
choice.forceMove(get_turf(src))
user.put_in_hands(choice)
cards.Remove(choice)
update_icon()
if(length(cards) == 0)
qdel(src)
return
. = ..()
/obj/item/tcgcard_binder
name = "Trading Card Binder"
desc = "A TCG-branded card binder, specifically for your infinite collection of TCG cards!"
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "binder"
var/list/cards = list()
var/mode = 0 //If 1, will show all the cards even if you don't have em
/obj/item/tcgcard_binder/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/tcg_card))
var/obj/item/tcg_card/card = I
card.forceMove(src)
cards.Add(card)
. = ..()
/obj/item/tcgcard_binder/attack_self(mob/living/carbon/user)
mode = !mode
to_chat(user, "<span class='notice'>[src] now shows you [mode ? "all the different cards" : "the cards you already have"].")
/obj/item/tcgcard_binder/attack_hand(mob/living/carbon/user)
if(loc == user)
var/list/choices = list()
if(mode)
var/card_types = list()
for(var/obj/item/tcg_card/card in cards)
card_types[card.datum_type] = card
for(var/card_type in subtypesof(/datum/tcg_card))
if(card_type in card_types)
var/obj/item/tcg_card/card = card_types[card_type]
choices[card] = image(icon = card.icon, icon_state = card.icon_state)
continue
var/datum/tcg_card/card_dat = new card_type
if(card_dat.name == "Stupid Coder")
continue
var/image/I = image(icon = card_dat.pack, icon_state = card_dat.icon_state)
I.color = "#999999"
choices[card_dat.name] = I
qdel(card_dat)
else
for(var/obj/item/tcg_card/card in cards)
choices[card] = image(icon = card.icon, icon_state = card.icon_state)
var/obj/item/tcg_card/choice = show_radial_menu(user, src, choices, require_near = TRUE, tooltips = TRUE)
if(choice && (choice in cards))
choice.forceMove(get_turf(src))
user.put_in_hands(choice)
cards.Remove(choice)
if(choice)
return
. = ..()
/obj/item/tcgcard_binder/proc/check_for_exodia()
var/list/card_types = list()
for(var/obj/item/tcg_card/card in cards)
card_types.Add(card.datum_type)
for(var/card_type in subtypesof(/datum/tcg_card))
var/datum/tcg_card/card_dat = new card_type
if(card_dat.name == "Eldritch Horror" && (card_type in card_types)) //We already have Exodia saved
qdel(card_dat)
return
if(card_dat.name == "Stupid Coder" || card_dat.name == "Eldritch Horror") //It would be stupid if we require exodia or system cards to get exodia
continue
qdel(card_dat)
if(!(card_type in card_types))
return
var/obj/item/tcg_card/card = new(get_turf(src), /datum/tcg_card/exodia/exodia)
card.forceMove(src)
cards.Add(card)
/obj/item/tcgcard_binder/full/Initialize() //For admemes.
. = ..()
for(var/cardtype in subtypesof(/datum/tcg_card))
var/obj/item/tcg_card/card = new(get_turf(src), cardtype)
if(card.card_datum.name == "Stupid Coder")
qdel(card)
continue
card.forceMove(src)
cards.Add(card)
/obj/item/tcg_rules
name = "TCG Rulebook"
desc = "A small rulebook containing a starter guide for TCG."
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "deck_low"
w_class = WEIGHT_CLASS_TINY
/obj/item/tcg_rules/examine(mob/user)
. = ..()
. += "<span class='notice'>*---------* \n\
<span class='boldnotice'>Welcome to the Exciting world of Tactical Card Game!</span> <span clas='smallnotice'>Sponsored by Nanotrasen Edu-tainment Devision.</span> \n \
<span class='boldnotice'>Core Rules:</span> \n \
Tactical Card Game (Also known as TCG) is a traditional trading card game. It's played between two players, each with a deck or collection of cards. \n \
Each player's deck contains up to 30 cards. Each player's hand can hold a maximum of 7 cards. At the end of your turn, if you have more than 7 cards, you must choose cards to discard to your discard pile until you have 7 cards. \n \
To begin a match, both players must flip a coin to decide who goes first. The winner of the coin toss then decides if they go first or second. Before the match begins each player draws 5 cards each with the ability to mulligan cards from their hand facedown once (Basically, you get a first pass where you can replace cards in your hands back into your deck, shuffle your deck, then draw until you're back to 5). \n \
Each player begins with 1 Max Mana to start with, which serves as the cost to playing cards. \n \
In order to play the TCG, a deck is required. As stated above, decks must contain up to 30 cards. \n \
Additionally, to save cards you need to have a card binder on yourself to store the cards. When the shift ends, your cards will be automatically saved by integrated scanners in your card binder. \n \
Finally, a stock of Thunderdome Flippers to use for coin tosses and counter effects is recommended- these can be obtained occasionally from cardpacks, but any coin will do. \n \
Win condition is simple - kill your opponent's hero by depleting all of their 20 lifeshards. \n \
<span class='boldnotice'>Gameplay Phases:</span> \n \
A single turn of the game goes as follows, and the order of card effects is very similar to other card games. Within a single turn, the following phases are gone through, in order, unless otherwise altered by a card effect. Turn Phases are the Draw Phase, Effect Phase 1, Play Phase, Combat Phase, Effect Phase 2, and the End Phase. \n \
During the draw phase, the player whose turn it is untaps all their cards, then draws a single card. They gain 1 Max Mana, and their Mana is refilled. Cards with missing health due to defending, attacking, or damage effects return to max health at the end of the draw phase. \n \
During the First Effect Phase, this is when effects that take place at the start of your turn would occur. If an opponent's effect takes place at the start of your turn, their effects will always take place first, then yours, unless otherwise stated by a card effect. If an opponent's effect would cause you to lose the game, and your effects would prevent that condition from happening afterwards, you would lose the game. As a general roll, when it's your turn, your opponent's effects take place FIRST, then yours. \n \
During the Play Phase, this is when you can play, summon, or activate your own cards. Card Effects that don't state when they're activated MUST be activated during the Play Phase. Your opponent can also activate their own card effects in response to one of your actions during your play phase, if able. Any card played during the play phase can activate its effect as soon as it's played. More details within the Card Breakdown section. \n \
During the Battle Phase, a Unit Card is able to battle other Unit Cards, or attack their opponent once per turn. Neither player can attack on their first turn, and all cards that enter the field can attack as soon as they can, unless it is that player's first turn, or they are prevented by a card effect. More details within the Card Combat section. \n \
During the End Phase, end of turn effects will occur. If the active player has more than 7 cards in their hand by this point, this is when they must discard cards. All of the player's cards who used an effect at any point in the turn are refreshed, and able to use their effect again going into the opponent's turn. By the end of their turn, if the player has more than 7 cards, they must discard cards from their hand until 7 remain. \n \
After all 5 phases have passed, the players turn officially ends, and the opponent begins their turn, starting anew from the draw phase. \n \
Card effects are typically limited to the turn that that card is played. For example, a card effect that provides a card +1/+1 attack/health would only last until the end of the turn, unless otherwise stated, OR if the card is an Equipment Card. More on those below. \n \
<span class='boldnotice'>Card Breakdown:</span> \n \
Within the game, there are 3 kinds of cards (So far), Unit, Equipment and Spell cards. \n \
Unit Cards. All Unit Cards have 4 core values to keep in mind, Attack, Health, Faction, and Summoning Cost. Attack serves as a card's offensive value in combat. Health serves as a card's defensive value in combat, and doubles as a card's health. Factions are groupings of cards that can often share effects and traits together. Summoning Cost is how much mana a card needs in order to be summoned. \n \
Equipment Cards. All Equipment Cards similarly to Unit Cards have Attack, Health, and Summon Cost values, but for equipment, these values are added to the attached card's values. Equipment can only be attached (Equip) to units, and they last until the unit dies, or otherwise leaves the field, following it's equipt card. If returned to the hand, send to the discard pile, or otherwise leaves the field, it is detatched from the equipt card. When a Equipment Card increases a card's attack or health, those effects stay on the equip card until the equipment is unequip or removed from the parent card. \n \
If a card would have it's health decreased by having it's equip card removed, it's handled by having it's maximum health decreased, not it's current health. For example, lets say you had a card with 1/1 attack/health, and give it an equipment giving it +1/+2, then that card enters combat, dropping it down to 2/1. If by an opponent's card effect it lost that +1/+2 equipment now, it's stats would be 1/1 once again. If an equip card explicitly lowers a card's stats, it is possible for a card to be killed as a result, but drops in attack will always bottom out at 0 attack at any given time. \n \
Spell Cards. Spell Cards don't have attack or health values, instead, they activate their effects as soon as they are summoned and leave the field afterwards(if not stated otherwise). \n \
<span class='boldnotice'>Card Subtypes:</span> \n \
Card effects: \n \
Asimov - Unit cannot attack units with Human subtype \n \
Changeling - Unit posesses all the subtypes at the same time \n \
Greytide - On summon, unit gains amount of power equal to amount of other units with Greytide for 1 turn \n \
Holy - Unit can't be targeted by spells \n \
Taunt - All opposing unit attacks must be directed towards the unit with Taunt. \n \
First Strike - This unit attacks first. If attacked unit is dead, unit doesn't recieve damage from it. \n \
Deadeye - This unit can always hit opponents, regardless of effects or immunities. \n \
Squad Tactics - When this unit attacks an opponent's unit and defeats it in combat, the owner of the defeated card takes 1 lifeshard of damage from combat. \n \
Immunity - The unit cannot be affected by card effects or combat of its immunity type. This includes both friendly and opposing effects. \n \
Fury - The unit must attack at every possibility. \n \
Blocker - The unit cannot declare attacks, but can defend. \n \
Hivemind - The unit enters combat with a hivemind token on it. The first time this card would take damage, remove that token instead. This does not apply to instant removal effects, only points of damage. \n \
Clockwork - The unit can copy a single keyword on another unit on the field, until they lose the clockwork keyword or leave the field. \n \
<span class='boldnotice'>Card Combat:</span> \n \
Card combat is determined as follows. On your turn, any non-tapped unit card with a positive attack power is capable of declaring an attack. Upon declaring an attack, you must state if you're attacking your opponent directly, or if you're going to attack a specific opponent's unit. Unless otherwise stated, cards can only attack or defend one time per turn. \n \
An attack against a unit healths as follows: Both units will do their power as damage to the opponent's unit's health. Damage is typically dealt at the same time, and if both units would kill each other through combat, both are destroyed at the same time. If One or both units would not be destroyed by combat, they would have their health reduced by the difference of their health minus their opponent's power, until the start of your next turn. If the attacker or defender has a keyword or effect that prevents them from attacking their opponent (Like silicon, immunity), then they are not able to attack, but may still defend against the opponent's attack. Once combat has healthd, all remaining participants become tapped. \n \
A direct attack healths as follows: The attacking unit declares an attack against the opponent's lifeshards. Your opponent may then declare a defender if one is available, who will then turn the combat into an attack against a unit for the purposes of combat that turn. If the attack is not blocked, and the direct attack connects, then your opponent loses a number of lifeshards equal to the attacking units power. </span>"
/obj/item/cardboard_card
name = "cardboard card cutout"
desc = "A small piece of cardboard shaped as a TCG card."
icon = 'icons/obj/tcg/misc.dmi'
icon_state = "template"
/datum/reagent/card_powder/reaction_obj(obj/O, reac_volume)
if(istype(O, /obj/item/cardboard_card))
var/list/possible_cards = list()
for(var/card_series in COMMON_SERIES)
for(var/card_type in subtypesof(card_series))
var/datum/tcg_card/card = new card_type
if(card.rarity == rarity)
possible_cards.Add(card_type)
qdel(card)
if(length(possible_cards))
new /obj/item/tcg_card(get_turf(O), pick(possible_cards), TRUE)
qdel(O)
. = ..()
#undef COMMON_SERIES
#undef TAPPED_ANGLE
#undef UNTAPPED_ANGLE
File diff suppressed because it is too large Load Diff
+483
View File
@@ -0,0 +1,483 @@
/datum/tcg_card/pack_nuclear
pack = 'icons/obj/tcg/pack_nuclear.dmi'
/datum/tcg_card/pack_nuclear/cayenne
name = "Cayenne"
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
rules = "Only playable when there are other Syndicate units on the field."
icon_state = "cayenne"
mana_cost = 4
attack = 4
health = 3
faction = "Syndicate"
rarity = "Rare"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/esword
name = "Energy Sword"
desc = "Hard-light sword that doesn't leave burns. Don't ask questions."
rules = ""
icon_state = "esword"
mana_cost = 3
attack = 2
health = 0
faction = "Syndicate"
rarity = "Common"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/stechkin
name = "Stechkin Pistol"
desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors."
rules = "When equipping this card, flip it so opponent won't see it. Flip the card after the first attack."
icon_state = "stechkin"
mana_cost = 2
attack = 2
health = 0
faction = "Syndicate"
rarity = "Common"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/c20r
name = "C-20R SMG"
desc = "A bullpup two-round burst .45 SMG, designated 'C-20r'. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp."
rules = "After attack, flip a coin. If heads, leave the weapon. If tails, unequip this card."
icon_state = "c20r"
mana_cost = 4
attack = 4
health = 0
faction = "Syndicate"
rarity = "Rare"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/l6saw
name = "L6 Saw LMG"
desc = "A heavily modified 1.95x129mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
rules = "After equipped unit dies, this card goes to the bottom of draw deck"
icon_state = "l6saw"
mana_cost = 8
attack = 6
health = 0
faction = "Syndicate"
rarity = "Epic"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/bulldog
name = "Bulldog Shotgun"
desc = "A semi-auto, mag-fed shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines."
rules = "After attack, deal 1 damage to enemy units next to the attacked one."
icon_state = "bulldog"
mana_cost = 3
attack = 3
health = 0
faction = "Syndicate"
rarity = "Rare"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/nuke_op_leader
name = "Nuclear Team Commander"
desc = "All commanders of elite nuclear teams are equipped with high-tier gear and weaponery. And, sometimes, gaming cards."
rules = "Squad Tactics. Give all Syndicate units on your side +1/0."
icon_state = "nuke_op_leader"
mana_cost = 5
attack = 3
health = 4
faction = "Syndicate"
rarity = "Epic"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/nuke_op
name = "Nuclear Team Commander"
desc = "An unequipped nuclear operative, ready to buy some gear and go full ham!"
rules = "Squad Tactics. On summon: Search your deck for Syndicate equipment. Equip it on this unit. Shuffle it afterwards."
icon_state = "nuke_op"
mana_cost = 3
attack = 2
health = 3
faction = "Syndicate"
rarity = "Common"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/dark_gygax
name = "Dark Gygax"
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
rules = "Squad Tactics."
icon_state = "dark_gygax"
mana_cost = 6
attack = 8
health = 4
faction = "Syndicate"
rarity = "Epic"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/mauler
name = "Mauler"
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model. A perfect killing machine equipped with best weaponery in the world."
rules = "Squad Tactics. Deadeye."
icon_state = "mauler"
mana_cost = 8
attack = 8
health = 8
faction = "Syndicate"
rarity = "Legendary"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/saboteur
name = "Syndicate Saboteur Cyborg"
desc = "A streamlined engineering cyborg, equipped with covert modules. Allows to sabotage all the systems you want without being suspicious."
rules = "Block the first spell your opponent plays against your hero."
icon_state = "saboteur"
mana_cost = 3
attack = 1
health = 3
faction = "Syndicate"
rarity = "Rare"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/medic
name = "Syndicate Medical Cyborg"
desc = "A combat medical cyborg. Has limited offensive potential, but makes more than up for it with its support capabilities."
rules = "Each turn you can give one of your units 0/+1."
icon_state = "medic"
mana_cost = 4
attack = 1
health = 2
faction = "Syndicate"
rarity = "Rare"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/combat
name = "Syndicate Assault Cyborg"
desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
rules = "Squad Tactics. Fury."
icon_state = "combat"
mana_cost = 5
attack = 4
health = 4
faction = "Syndicate"
rarity = "Epic"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/emag
name = "Cryptographic Sequencer"
desc = "It's a card with a magnetic strip attached to some circuitry."
rules = "Convert an enemy silicon unit to your side."
icon_state = "emag"
mana_cost = 4
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/bomb
name = "Syndicate Bomb"
desc = "A large and menacing device. Can be bolted down with a wrench."
rules = "Deal 6 damage to all units on the field after 2 turns."
icon_state = "bomb"
mana_cost = 6
faction = "Syndicate"
rarity = "Rare"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/honkbomb
name = "H.O.N.K. Bomb"
desc = "A bomb filled to the brim with bananium and dehydrated clowns!"
rules = "Search your deck for up to 3 Clowns. Play them for free. Shuffle the deck afterwards."
icon_state = "honkbomb"
mana_cost = 8
faction = "Syndicate"
rarity = "Epic"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/assault_pod
name = "Assault Pod"
desc = "Raining Steel. Nothing personnel, just disky."
rules = "Summon up to 3 units from your hand with 4 mana discount each."
icon_state = "assault_pod"
mana_cost = 8
faction = "Syndicate"
rarity = "Epic"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/c4
name = "C4"
desc = "A bunch of plastic explosives wired together."
rules = "Deal 2 damage to an enemy unit."
icon_state = "c4"
mana_cost = 1
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/emp
name = "EMP Grenade"
desc = "A modern-looking grenade which creates a powerful EMP upon activation. Do not eat."
rules = "Deal 2 damage to an enemy silicon unit."
icon_state = "emp"
mana_cost = 0
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/zombie
name = "Romerol Zombie"
desc = "A horrible abomination, resembling a dead human. Has green skin and red claws. Wait, is it blood dripping from them?"
rules = "After killing an enemy unit, search your deck for a Zombie and summon it for free."
icon_state = "zombie"
mana_cost = 8
attack = 4
health = 3
faction = "Syndicate"
rarity = "Epic"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/north_star
name = "North Star Armbands"
desc = "The armbands of a deadly martial artist. Makes you pretty keen to put an end to evil in an extremely violent manner."
rules = "Equipped unit can attack twice per turn."
icon_state = "north_star"
mana_cost = 4
faction = "Syndicate"
rarity = "Rare"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/fastdetonation
name = "Big-Ass Red Button"
desc = "A menacing red button. What could it do?"
rules = "Activate all spells that require several turns to occur."
icon_state = "fastdetonation"
mana_cost = 2
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/rpg
name = "PML-9 Rocket Launcher"
desc = "A reusable rocket propelled grenade launcher. The words \"NT this way\" and an arrow have been written near the barrel."
rules = "When equipped unit attacks enemy units, flip a coin. If heads, destroy the unit. If tails, deal 1/2 damage instead of the full blow."
icon_state = "rpg"
mana_cost = 8
attack = 6
faction = "Syndicate"
rarity = "Legendary"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/darkhonk
name = "Dark H.O.N.K. Mech"
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. This one was painted black for maximum HONKing!"
rules = "Taunt. Squad Tactics. Blocker."
icon_state = "darkhonk"
mana_cost = 8
attack = 6
health = 8
faction = "Syndicate"
rarity = "Epic"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/shielded_hardsuit
name = "Shielded Blood-red Hardsuit"
desc = "An advanced version of Gorlex Maradeurs' hardsuit with built-in energy shielding."
rules = "Give equipped unit First Strike."
icon_state = "shielded_hardsuit"
mana_cost = 4
attack = 0
health = 4
faction = "Syndicate"
rarity = "Epic"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/nuclear_disk
name = "Nuclear Authentication Disk"
desc = "Better keep this safe."
rules = "Give equipped unit Taunt. After the equipped unit dies, re-equip this card to the killer."
icon_state = "nuclear_disk"
mana_cost = 0
attack = 1
health = 1
faction = "Syndicate"
rarity = "Epic"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/buzzkill
name = "Buzzkill grenade"
desc = "A whole swarm of angry bees filled with deadly toxins. Nasty!"
rules = "Hivemind."
icon_state = "buzzkill"
mana_cost = 4
attack = 1
health = 5
faction = "Syndicate"
rarity = "Rare"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/syndicate_minibomb
name = "Syndicate Minibomb"
desc = "A syndicate manufactured explosive used to sow destruction and chaos."
rules = "Deal 3 damage to an enemy unit and units adjacent to it."
icon_state = "syndicate_minibomb"
mana_cost = 3
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/viscerator
name = "Viscerator"
desc = "A small yet deadly machine, designed to rip it's targets apart."
rules = "Gain +1/+1 for every other viscerator on field."
icon_state = "viscerator"
mana_cost = 2
attack = 3
health = 1
faction = "Syndicate"
rarity = "Common"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/cqc
name = "CQC Manual"
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
rules = "Give equipped unit Deadeye and First Strike."
icon_state = "cqc"
mana_cost = 4
attack = 4
health = 3
faction = "Syndicate"
rarity = "Epic"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/holoparasite
name = "Holoparasite"
desc = "A mysterious being that stands by its charge, ever vigilant."
rules = "On summon: \"Link\" this unit to another unit. Whenever this unit takes damage, instead, transfer all damage to the linked unit."
icon_state = "holoparasite"
mana_cost = 6
attack = 8
health = 0
faction = "Syndicate"
rarity = "Legendary"
card_type = "Unit"
/datum/tcg_card/pack_nuclear/rapier
name = "Rapier"
desc = "An elegant plastitanium rapier with a diamond tip and coated in a specialized knockout poison."
rules = ""
icon_state = "rapier"
mana_cost = 2
attack = 3
health = 0
faction = "Syndicate"
rarity = "Rare"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/sniper
name = "Sniper Rifle"
desc = "A long ranged weapon that does significant damage. No, you can't quickscope."
rules = "Give equipped unit Deadeye."
icon_state = "sniper"
mana_cost = 6
attack = 5
health = 0
faction = "Syndicate"
rarity = "Epic"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/honksword
name = "Bananium Sword"
desc = "An elegant weapon, for a more \"civilized\" age."
rules = "Equipped unit does not deal damage. Instead, it taps the attacked card without activating it's effects."
icon_state = "honksword"
mana_cost = 3
attack = 0
health = 0
faction = "Syndicate"
rarity = "Common"
card_type = "Equipment"
/datum/tcg_card/pack_nuclear/mustache
name = "Mustache Grenade"
desc = "A handsomely-attired teargas grenade."
rules = "Unequip all enemy units. Unequipped equipment cards must be discarded."
icon_state = "mustache"
mana_cost = 5
faction = "Syndicate"
rarity = "Common"
card_type = "Spell"
/datum/tcg_card/pack_nuclear/taeclowndo
name = "Tae-Clown-Do"
desc = "A pair of clown shoes, infused with bananium. Rumors say that these can teach their wearer the art of Tae-Clown-Do."
rules = "Flip a coin. If heads, your enemy skips a turn. If tails, you skip a turn instead."
icon_state = "taeclowndo"
mana_cost = 3
faction = "Syndicate"
rarity = "Epic"
card_type = "Spell"
+304
View File
@@ -0,0 +1,304 @@
/datum/tcg_card/pack_star
pack = 'icons/obj/tcg/pack_star.dmi'
/datum/tcg_card/pack_star/golem
name = "Adamantine Golem"
desc = "An adamantine golem, immune to magic and being able to coordinate other golems, has a great power in combat."
rules = "Holy. Taunt."
icon_state = "golem"
mana_cost = 4
attack = 4
health = 5
faction = "Unique"
rarity = "Rare"
card_type = "Unit"
/obj/item/tcg_card/special/golem
datum_type = /datum/tcg_card/pack_star/golem
/datum/tcg_card/pack_star/xenomaid
name = "Lusty Xenomorph Maid"
desc = "Just a lusty xenomorph maid, nothing to see here."
rules = "Blocker. Each turn, gain -1/-1."
icon_state = "xenomaid"
mana_cost = 3
attack = 6
health = 6
faction = "Unique"
rarity = "Epic"
card_type = "Unit"
/obj/item/tcg_card/special/xenomaid
datum_type = /datum/tcg_card/pack_star/xenomaid
/datum/tcg_card/pack_star/morph
name = "Morph"
desc = "A revolting, pulsating pile of flesh that can mimic everything it sees."
rules = "On summon: Copy stats of an opponent's card."
icon_state = "morph"
mana_cost = 4
attack = 0
health = 1
faction = "Unique"
rarity = "Common"
card_type = "Unit"
/obj/item/tcg_card/special/morph
datum_type = /datum/tcg_card/pack_star/morph
/datum/tcg_card/pack_star/demonic_miner
name = "Demonic Miner"
desc = "An soul of extremely geared miner, driven crazy or possessed by the demonic forces here, either way a terrifying enemy."
rules = "Each turn: Deal 1 damage to all the creatures on the field."
icon_state = "demonic_miner"
mana_cost = 7
attack = 4
health = 5
faction = "Unique"
rarity = "Rare"
card_type = "Unit"
/obj/item/tcg_card/special/demonic_miner
datum_type = /datum/tcg_card/pack_star/demonic_miner
/datum/tcg_card/pack_star/wendigo
name = "Wendigo"
desc = "A mythological man-eating legendary creature, you probably aren't going to survive this."
rules = ""
icon_state = "wendigo"
mana_cost = 6
attack = 5
health = 3
faction = "Unique"
rarity = "Common"
card_type = "Unit"
/obj/item/tcg_card/special/wendigo
datum_type = /datum/tcg_card/pack_star/wendigo
/datum/tcg_card/pack_star/honk
name = "H.O.N.K. Mech"
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!"
rules = "Taunt."
icon_state = "honk"
mana_cost = 8
attack = 6
health = 8
faction = "Unique"
rarity = "Epic"
card_type = "Unit"
/obj/item/tcg_card/special/honk
datum_type = /datum/tcg_card/pack_star/honk
/datum/tcg_card/pack_star/ratvar
name = "Clockwork Slab"
desc = "A link between clockwork servants and the Celestial Derelict. It contains information, recites scripture, and is Servant's most vital tool."
rules = "Equipped unit gains Clockwork and can't attack units with Holy."
icon_state = "ratvar"
mana_cost = 2
attack = 3
health = 0
faction = "Unique"
rarity = "Common"
card_type = "Equipment"
/obj/item/tcg_card/special/ratvar
datum_type = /datum/tcg_card/pack_star/ratvar
/datum/tcg_card/pack_star/hierophant
name = "Hierophant Club"
desc = "The strange technology of this large club allows various nigh-magical feats. It used to beat you, but now you can set the beat."
rules = "Give equipped unit First Strike."
icon_state = "hierophant"
mana_cost = 4
attack = 2
health = 0
faction = "Unique"
rarity = "Rare"
card_type = "Equipment"
/obj/item/tcg_card/special/hierophant
datum_type = /datum/tcg_card/pack_star/hierophant
/datum/tcg_card/pack_star/abductor
name = "Alien Gland"
desc = "A nausea-inducing hunk of twisting flesh and metal. These things are often found after people were abducted by grey-skinned aliens."
rules = "Each turn: Flip a coin. If heads, unit gain +1/+1. If tails, unit gains -2/-1."
icon_state = "abductor"
mana_cost = 2
attack = 0
health = 0
faction = "Unique"
rarity = "Common"
card_type = "Equipment"
/obj/item/tcg_card/special/abductor
datum_type = /datum/tcg_card/pack_star/abductor
/datum/tcg_card/pack_star/space_carp
name = "Space Carp"
desc = "A failed weaponery experiment, looking like a ferocious, fang-bearing creature that resembles a fish."
rules = ""
icon_state = "space_carp"
mana_cost = 1
attack = 2
health = 1
faction = "Unique"
rarity = "Common"
card_type = "Unit"
/obj/item/tcg_card/special/space_carp
datum_type = /datum/tcg_card/pack_star/space_carp
/datum/tcg_card/pack_star/spess_pirate
name = "Space Pirate"
desc = "Space Pirate does whatever he wants because he is free. Sadly, Space Rum insn't free."
rules = "On summon: Draw 2 cards. If there are no spells, discard them."
icon_state = "spess_pirate"
mana_cost = 4
attack = 3
health = 2
faction = "Unique"
rarity = "Rare"
card_type = "Unit"
/obj/item/tcg_card/special/spess_pirate
datum_type = /datum/tcg_card/pack_star/spess_pirate
/datum/tcg_card/pack_star/gondola
name = "Gondola"
desc = "Gondola is the silent walker. Having no hands he embodies the Taoist principle of wu-wei (non-action) while his smiling facial expression shows his utter and complete acceptance of the world as it is. Its hide is extremely valuable."
rules = "Taunt. Holy."
icon_state = "gondola"
mana_cost = 6
attack = 0
health = 6
faction = "Unique"
rarity = "Epic"
card_type = "Unit"
/obj/item/tcg_card/special/gondola
datum_type = /datum/tcg_card/pack_star/gondola
/datum/tcg_card/pack_star/phazon
name = "Phazon"
desc = "The pinnacle of scientific research and pride of Nanotrasen, Phazon uses cutting edge bluespace technology and expensive materials."
rules = "Whenever this unit takes damage, flip a coin. If heads, take no damage. If tails, take double damage."
icon_state = "phazon"
mana_cost = 8
attack = 5
health = 7
faction = "Unique"
rarity = "Rare"
card_type = "Unit"
/obj/item/tcg_card/special/phazon
datum_type = /datum/tcg_card/pack_star/phazon
//Ultimate Exodia cards. I really, really doubt that someone will ever find them.
/datum/tcg_card/exodia
pack = 'icons/obj/tcg/pack_star.dmi'
/datum/tcg_card/exodia/exodia_singulo
name = "Singularity"
desc = "A monstrous gravitational singularity, pitch black(but not quiet) and very menacings."
rules = "This card doesn't leave field. At the end of each turn: Remove all the cards(except other Exodia cards) from the field."
icon_state = "exodia_singularity"
mana_cost = 8
faction = "Exodia"
rarity = "Exodia"
card_type = "Spell"
/datum/tcg_card/exodia/exodia_tesla
name = "Energy Orb"
desc = "An orb made out of hypercharged plasma. An ultimate bug zapper."
rules = "This card doesn't leave field. Every turn all units take 4 damage."
icon_state = "exodia_tesla"
mana_cost = 8
faction = "Exodia"
rarity = "Exodia"
card_type = "Spell"
/datum/tcg_card/exodia/exodia_narie
name = "Nar-Sie"
desc = "An avatar of the Nar-Sie, one of the Eldritch Gods."
rules = "This card doesn't leave field. Every turn all units take 1 damage and you restore 1 lifeshard."
icon_state = "exodia_narsie"
mana_cost = 8
faction = "Exodia"
rarity = "Exodia"
card_type = "Spell"
/datum/tcg_card/exodia/exodia_ratvar
name = "Ratvar"
desc = "Ratvar, the god of cogs and clockwork mechanisms, was trapped by Nar-Sie a long ago."
rules = "This card doesn't leave field. Every turn enemy hero recieves 2 lifeshard damage."
icon_state = "exodia_ratvar"
mana_cost = 8
faction = "Exodia"
rarity = "Exodia"
card_type = "Spell"
/datum/tcg_card/exodia/exodia
name = "Eldritch Horror"
desc = "The Eldritch Horror is a long forgotten demon that was the beginning of everything. Afterwards, his creations revolted and left him abadoned in endless void."
rules = "This card doesn't leave field. If all other 4 Exodia cards are on the field(Singularity, Energy Orb, Nar-Sie and Ratvar), the game is won."
icon_state = "exodia_eldritch"
mana_cost = 8
faction = "Exodia"
rarity = "Unique" //No drop lads
card_type = "Spell"
/obj/item/tcg_card/special/exodia_singulo
datum_type = /datum/tcg_card/exodia/exodia_singulo
/obj/item/tcg_card/special/exodia_tesla
datum_type = /datum/tcg_card/exodia/exodia_tesla
/obj/item/tcg_card/special/exodia_narie
datum_type = /datum/tcg_card/exodia/exodia_narie
/obj/item/tcg_card/special/exodia_ratvar
datum_type = /datum/tcg_card/exodia/exodia_ratvar
/obj/item/tcg_card/special/exodia
datum_type = /datum/tcg_card/exodia/exodia
@@ -78,3 +78,16 @@
limited_stock = 1
cant_discount = TRUE
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/badass/gaming_cardpack
name = "TCG Card Operatives Bundle"
desc = "A bundle full of goodies required to work as a TCG Card Operative. A warm pajama, a mug of cocoa, a plushie and a two packs full of rare 2560 Core Set cards!"
item = /obj/item/storage/box/syndie_kit/sleepytime/cardpack
cost = 20
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/badass/cardpack
name = "TCG Nuclear Cardpack"
desc = "A cardpack filled with top-tier TCG cards."
item = /obj/item/cardpack/syndicate
cost = 4
+4 -1
View File
@@ -21,6 +21,7 @@
/obj/item/clothing/suit/jacket/puffer/vest = 4,
/obj/item/clothing/suit/jacket/puffer = 4,
/obj/item/clothing/suit/hooded/cloak/david = 4,
/obj/item/clothing/neck/cancloak = 4,
/obj/item/clothing/suit/bomber = 5,
/obj/item/clothing/under/suit/turtle/teal = 3,
/obj/item/clothing/under/suit/turtle/grey = 3,
@@ -212,7 +213,9 @@
/obj/item/clothing/neck/necklace/dope = 5,
/obj/item/clothing/suit/jacket/letterman_nanotrasen = 5,
/obj/item/clothing/under/misc/corporateuniform = 5,
/obj/item/clothing/suit/hooded/wintercoat/polychromic = 5)
/obj/item/clothing/suit/hooded/wintercoat/polychromic = 5,
/obj/item/clothing/suit/toggle/wbreakpoly/polychromic = 5,
/obj/item/clothing/shoes/sneakers/poly/polychromic = 10)
refill_canister = /obj/item/vending_refill/clothing
default_price = PRICE_CHEAP
extra_price = PRICE_BELOW_NORMAL
+3 -1
View File
@@ -7,7 +7,9 @@
/obj/item/storage/dice = 10,
/obj/item/toy/cards/deck/cas = 3,
/obj/item/toy/cards/deck/cas/black = 3,
/obj/item/toy/cards/deck/unum = 3)
/obj/item/toy/cards/deck/unum = 3,
/obj/item/cardpack/series_one = 10,
/obj/item/tcgcard_binder = 5)
contraband = list(/obj/item/dice/fudge = 9)
premium = list(/obj/item/melee/skateboard/pro = 3,
/obj/item/melee/skateboard/hoverboard = 1)
+155 -19
View File
@@ -66,40 +66,116 @@
</ul>
<h2 class="date">11 February 2021</h2>
<h3 class="author">Adelphon updated:</h3>
<h2 class="date">18 February 2021</h2>
<h3 class="author">BlueWildrose updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Charismatic Suit</li>
<li class="rscadd">Urban Jacket</li>
<li class="admin">Admins now receive messages regarding certain holodeck actions.</li>
</ul>
<h3 class="author">DeltaFire15 updated:</h3>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Added nanogel to the robodrobe.</li>
<li class="bugfix">Free Golem Ship GPSes now start as disabled. Like they were supposed to.</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<h3 class="author">LetterN updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Config to keep unreadied players from mode voting</li>
<li class="tweak">No more liver damage when you opt out of "hornychems"</li>
</ul>
<h3 class="author">SmArtKar updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added a new TCG card game</li>
</ul>
<h3 class="author">dzahlus updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes grenadelaunch.ogg being used where it shouldn't and makes mech weapons use correct sound</li>
<li class="rscdel">Removed maroon objective due to toxic gameplay behaviour</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<h3 class="author">shellspeed1 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">10 > 30 second for Warp Implant cooldown</li>
<li class="rscdel">Comments out power sink objective.</li>
<li class="bugfix">floor bots place plating before tiles now.</li>
<li class="bugfix">gets rid of another tile duplication issue.</li>
</ul>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="spellcheck">priviledge --> privilege</li>
</ul>
<h2 class="date">16 February 2021</h2>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="config">sprint removal entry added, UI will revert to old UI while this is active.</li>
</ul>
<h2 class="date">15 February 2021</h2>
<h3 class="author">Adelphon updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">polychromatic shoes</li>
<li class="rscadd">polychromatic windbreaker</li>
<li class="rscadd">polychromatic canvas cloak</li>
<li class="bugfix">digitigrade charismatic suit texture</li>
</ul>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Kneecapped pugilist parries somewhat.</li>
<li class="balance">Slightly nerfed default unarmed parries.</li>
<li class="balance">Slightly nerfed traitor armwrap parries.</li>
<li class="bugfix">Pugilist parries now cannot perfectly defend against projectiles, as they were supposed to.</li>
<li class="bugfix">Some parrying numbers that one would think were in seconds didn't have the SECONDS. I added those.</li>
<li class="balance">Clock cultists now yell alot less when invoking scripture.</li>
</ul>
<h3 class="author">dzahlus updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added new emote</li>
<li class="soundadd">added a new emote sound</li>
</ul>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="balance">people on the ground hit less hard in unarmed combat. rng miss remove from punches.</li>
<li class="bugfix">chat highlighting no longer drops half your entered words.</li>
</ul>
<h2 class="date">14 February 2021</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="admin">The antag panel now correctly shows the names of cultist / clockcult datum subtypes.</li>
<li class="bugfix">Adding clock cultists via the admin panel now works correctly.</li>
<li class="bugfix">Xeno larvae should now be able to ventcrawl again.</li>
</ul>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Repairing sensors on jumpsuits now requires a fully-intact jumpsuit. Find some cloth.</li>
<li class="tweak">Durathread armor kits now require you to have a fully-repaired jumpsuit, first, with no attachments.</li>
<li class="bugfix">Durathread armor kits now no longer weave the entirety of the jumpsuit armor universe into having armor.</li>
</ul>
<h3 class="author">TyrianTyrell updated:</h3>
<ul class="changes bgimages16">
<li class="code_imp">added a define for multilingual granted languages, and changed the multilingual trait to use it.</li>
</ul>
<h2 class="date">13 February 2021</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Energy bolas now take 2.5 seconds to remove and dissipate on removal.</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">persistent blood should stop being invisible and alt clicking it shouldn't return the entire spritesheet</li>
<li class="admin">pickpocketing is now logged using log_combat</li>
</ul>
<h3 class="author">zeroisthebiggay updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">the aesthetic sterile mask no longer hides faces so you can cosplay egirls and keep flavortexts</li>
<li class="admin">migration error to version 39+ of savefiles is now logged instead of messaging all online admins in the chat</li>
</ul>
<h2 class="date">09 February 2021</h2>
<h3 class="author">Chiirno updated:</h3>
<h2 class="date">12 February 2021</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="balance">The ATVs on SnowCabin.dmm have been replaced with snowmobiles.</li>
</ul>
<h3 class="author">MrJWhit updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Random deltastation fixes.</li>
<li class="tweak">Gives boxstation vault door actual vault door access</li>
</ul>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Voice of God - sleep removed, stun staggers instead, knockdown is faster but does not do stamina damage, vomit is faster but doesn't stun</li>
</ul>
<h2 class="date">11 February 2021</h2>
<h3 class="author">Adelphon updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds clown waddle to clown shoes. Enhanced Clown Waddle Dampeners can be engaged in-hand with ctrl+click, _but why would you?_</li>
</ul>
@@ -116,6 +192,66 @@
<li class="balance">sentient viruses can now infect synths and ipcs</li>
</ul>
<h2 class="date">07 February 2021</h2>
<h3 class="author">Thalpy updated:</h3>
<ul class="changes bgimages16">
<li class="refactor">Dispenser: Adds the ability to store a small amount of reagents in the machine itself for dispensing. Reacting recipies cannot be stored. Size of storage increases with bin size.</li>
<li class="refactor">Dispenser: Allows reagents to be color coded by pH</li>
<li class="refactor">Dispenser: Each reagent displays it's pH on hover</li>
<li class="refactor">Dispenser: Allows the user to toggle between buttons and a radial dial</li>
<li class="refactor">Dispenser: When the dispencer is upgraded it can dispense 5/3/2/1 volumes based on rating refactor: Dispenser: as it was before. This does not break recorded recipes.</li>
<li class="tweak">Adds a round function to some numbers so they're not huge</li>
<li class="tweak">The Chem master can now get purity for all reagents when analysed</li>
<li class="bugfix">Synthissue fixes</li>
<li class="tweak">buffers now have a strong and weak variant. Weak can be dispensed, and strong can be created. Strong buffers are 6x more effective.</li>
<li class="bugfix">Some buffer pH edge calculation fixes</li>
</ul>
<h3 class="author">TyrianTyrell updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">added a signed language, that can't be used over the radio but can be used if you're mute. also added the multilingual trait.</li>
<li class="imageadd">hopefully added an icon for the signed language.</li>
<li class="code_imp">changed how some traits function slightly.</li>
<li class="bugfix">persistent blood should stop being invisible and alt clicking it shouldn't return the entire spritesheet</li>
<li class="admin">pickpocketing is now logged using log_combat</li>
</ul>
<h3 class="author">dzahlus updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">tweaked a few sounds</li>
<li class="soundadd">added a new weapon sounds</li>
<li class="sounddel">removed old weapon sounds</li>
<li class="code_imp">changed some sound related code</li>
</ul>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">syndicate ablative armwraps have been added.</li>
</ul>
<h2 class="date">05 February 2021</h2>
<h3 class="author">SmArtKar updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">The orbit menu now has an Auto-Observe button! No more sifting through the lame observe menu to snoop in people's backpacks! Also, orbit menu now refreshes.</li>
<li class="bugfix">KAs are no longer getting broken when fired by a circuit</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Force and damage > 15 from 18/25</li>
<li class="balance">Knockdown put down to 5 from 30</li>
<li class="balance">Armor pen down to 10 from 100.</li>
<li class="balance">Makes cell chargers, charge faster.</li>
</ul>
<h3 class="author">raspy-on-osu updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">alien royals can no longer ventcrawl</li>
</ul>
<h3 class="author">shellspeed1 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">There actually needs to be people for zombies to happen now.</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">dwarf facial hair is no longer randomised</li>
</ul>
<h2 class="date">07 February 2021</h2>
<h3 class="author">Thalpy updated:</h3>
<ul class="changes bgimages16">
+64 -1
View File
@@ -26243,7 +26243,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
Ghommie:
- bugfix: You can now actually gain wiring experience from using cable coils.
- bugfix: Opening the View Skill Panel shouldn't trigger messages about insufficient
admin priviledges anymore.
admin privileges anymore.
Yakumo Chen, kappa-sama:
- rscdel: Removes improvised handguns
- rscdel: removed handsaws, improvised gun barrels (you can use atmos pipes again)
@@ -28454,3 +28454,66 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
silicons:
- balance: Voice of God - sleep removed, stun staggers instead, knockdown is faster
but does not do stamina damage, vomit is faster but doesn't stun
2021-02-13:
Hatterhat:
- balance: Energy bolas now take 2.5 seconds to remove and dissipate on removal.
timothyteakettle:
- admin: migration error to version 39+ of savefiles is now logged instead of messaging
all online admins in the chat
2021-02-14:
DeltaFire15:
- admin: The antag panel now correctly shows the names of cultist / clockcult datum
subtypes.
- bugfix: Adding clock cultists via the admin panel now works correctly.
- bugfix: Xeno larvae should now be able to ventcrawl again.
Hatterhat:
- tweak: Repairing sensors on jumpsuits now requires a fully-intact jumpsuit. Find
some cloth.
- tweak: Durathread armor kits now require you to have a fully-repaired jumpsuit,
first, with no attachments.
- bugfix: Durathread armor kits now no longer weave the entirety of the jumpsuit
armor universe into having armor.
TyrianTyrell:
- code_imp: added a define for multilingual granted languages, and changed the multilingual
trait to use it.
2021-02-15:
Adelphon:
- rscadd: polychromatic shoes
- rscadd: polychromatic windbreaker
- rscadd: polychromatic canvas cloak
- bugfix: digitigrade charismatic suit texture
DeltaFire15:
- balance: Kneecapped pugilist parries somewhat.
- balance: Slightly nerfed default unarmed parries.
- balance: Slightly nerfed traitor armwrap parries.
- bugfix: Pugilist parries now cannot perfectly defend against projectiles, as they
were supposed to.
- bugfix: Some parrying numbers that one would think were in seconds didn't have
the SECONDS. I added those.
- balance: Clock cultists now yell alot less when invoking scripture.
dzahlus:
- rscadd: Added new emote
- soundadd: added a new emote sound
silicons:
- balance: people on the ground hit less hard in unarmed combat. rng miss remove
from punches.
- bugfix: chat highlighting no longer drops half your entered words.
2021-02-16:
silicons:
- config: sprint removal entry added, UI will revert to old UI while this is active.
2021-02-18:
BlueWildrose:
- admin: Admins now receive messages regarding certain holodeck actions.
Hatterhat:
- bugfix: Free Golem Ship GPSes now start as disabled. Like they were supposed to.
LetterN:
- tweak: No more liver damage when you opt out of "hornychems"
SmArtKar:
- rscadd: Added a new TCG card game
dzahlus:
- rscdel: Removed maroon objective due to toxic gameplay behaviour
shellspeed1:
- bugfix: floor bots place plating before tiles now.
- bugfix: gets rid of another tile duplication issue.
silicons:
- spellcheck: priviledge --> privilege
Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 KiB

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Some files were not shown because too many files have changed in this diff Show More