This commit is contained in:
Fordoxia
2024-04-26 16:23:32 +01:00
85 changed files with 1969 additions and 823 deletions

5
.github/CODEOWNERS vendored
View File

@@ -26,3 +26,8 @@ _build_dependencies.sh @AffectedArc07
dreamchecker.exe @AffectedArc07
rust_g.dll @AffectedArc07
librust_g.so @AffectedArc07
### S34NW
# TGUI stuff
/tgui/bin @S34NW

View File

@@ -157,7 +157,7 @@ if(thing == TRUE)
return "bleh"
var/other_thing = pick(TRUE, FALSE)
if(other_thing == FALSE)
return "meh"
return "meh"
// Good
var/thing = pick(TRUE, FALSE)
@@ -165,7 +165,7 @@ if(thing)
return "bleh"
var/other_thing = pick(TRUE, FALSE)
if(!other_thing)
return "meh"
return "meh"
```
### Use `pick(x, y, z)`, not `pick(list(x, y, z))`
@@ -452,6 +452,32 @@ Look for code examples on how to properly use it.
addtimer(CALLBACK(target, PROC_REF(dothing), arg1, arg2, arg3), 5 SECONDS)
```
### Signals
Signals are a slightly more advanced topic, but are often useful for attaching external behavior to objects that should be triggered when a specific event occurs.
When defining procs that should be called by signals, you must include `SIGNAL_HANDLER` after the proc header. This ensures that no sleeping code can be called from within a signal handler, as that can cause problems with the signal system.
Since callbacks can be connected to many signals with `RegisterSignal`, it can be difficult to pin down the source that a callback is invoked from. Any new `SIGNAL_HANDLER` should be followed by a comment listing the signals that the proc is expected to be invoked for. If there are multiple signals to be handled, separate them with a `+`.
```dm
/atom/movable/proc/when_moved(atom/movable/A)
SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED
do_something()
/datum/component/foo/proc/on_enter(datum/source, atom/enterer)
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED + COMSIG_ATOM_INITIALIZED_ON
do_something_else()
```
If your proc does have something that needs to sleep (such as a `do_after()`), do not simply omit the `SIGNAL_HANDLER`. Instead, call the sleeping code with `INVOKE_ASYNC` from within the signal handling function.
```dm
/atom/movable/proc/when_moved(atom/movable/A)
SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED
INVOKE_ASYNC(src, PROC_REF(thing_that_sleeps), arg1)
```
### Operators
#### Spacing of operators

View File

@@ -2,4 +2,4 @@
#Add a choice for what type of brain borgs want to have
ALTER TABLE `characters`
ADD COLUMN `cyborg_brain_type` VARCHAR(11) NOT NULL DEFAULT 'MMI' AFTER `height`;
ADD COLUMN `cyborg_brain_type` ENUM('MMI', 'Robobrain', 'Positronic') NOT NULL DEFAULT 'MMI' AFTER `height`;

View File

@@ -126,6 +126,11 @@
/obj/structure/bed,
/turf/simulated/floor/mineral/titanium/purple,
/area/ruin/space/powered)
"Q" = (
/obj/structure/table/wood,
/obj/item/blank_tarot_card,
/turf/simulated/floor/mineral/titanium/purple,
/area/ruin/space/powered)
(1,1,1) = {"
a
@@ -277,7 +282,7 @@ b
j
r
w
n
Q
j
b
a

View File

@@ -551,7 +551,6 @@
info = "Nothing of interest to report.";
name = "november report"
},
/obj/item/pen,
/obj/item/tape,
/obj/item/radio/intercom{
freerange = 1;
@@ -559,7 +558,7 @@
name = "intercom"
},
/obj/item/paper_bin,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel/dark,
/area/ruin/space/syndicate_listening_station)

View File

@@ -523,7 +523,7 @@
/obj/item/paper_bin{
pixel_x = -6
},
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/mineral/plastitanium,
/area/ruin/space/mech_transport)
"MA" = (

View File

@@ -5200,6 +5200,7 @@
},
/obj/item/coin/antagtoken/syndicate,
/obj/structure/table,
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/plating/asteroid/ancient,
/area/ruin/space/moonbase19)
"rk" = (

View File

@@ -98,11 +98,11 @@
pixel_x = 4
},
/obj/item/paper/syndicate_druglab,
/obj/item/pen,
/obj/item/flashlight/lamp/green/off{
pixel_y = 12;
pixel_x = -6
},
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/carpet/black,
/area/ruin/space/syndicate_druglab)
"qa" = (

View File

@@ -2985,7 +2985,7 @@
dir = 8
},
/obj/item/hand_labeler,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/plasteel{
dir = 9;
icon_state = "darkgreen"
@@ -3423,7 +3423,7 @@
"th" = (
/obj/structure/table,
/obj/item/paper_bin,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/obj/structure/extinguisher_cabinet{
name = "north bump";
pixel_y = 30
@@ -3760,7 +3760,7 @@
/area/ruin/unpowered/syndicate_space_base/service)
"vd" = (
/obj/structure/table,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/obj/item/paper_bin,
/obj/item/stamp/syndicate,
/obj/machinery/light_switch{
@@ -8462,7 +8462,7 @@
dir = 8
},
/obj/item/hand_labeler,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/plasteel{
dir = 10;
icon_state = "darkgreen"

View File

@@ -498,6 +498,7 @@
/obj/machinery/light/small{
dir = 4
},
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/engine,
/area/ruin/space/unpowered)
"tX" = (

View File

@@ -665,7 +665,7 @@
"bV" = (
/obj/structure/table,
/obj/item/folder/syndicate/yellow,
/obj/item/pen,
/obj/item/pen/multi/syndicate,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},

View File

@@ -167,6 +167,7 @@
/area/ruin/space/unpowered)
"aF" = (
/obj/structure/table/wood,
/obj/item/blank_tarot_card,
/turf/simulated/floor/wood{
icon_state = "wood-broken6"
},

View File

@@ -10,10 +10,6 @@
/// Every proc you pass to RegisterSignal must have this.
#define SIGNAL_HANDLER SHOULD_NOT_SLEEP(TRUE)
/// Signifies that this proc is used to handle signals, but also sleeps.
/// Do not use this for new work.
#define SIGNAL_HANDLER_DOES_SLEEP
/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments
#define AddElement(arguments...) _AddElement(list(##arguments))
/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments

View File

@@ -1061,3 +1061,6 @@
/// Used by admin-tooling to remove radiation
#define COMSIG_ADMIN_DECONTAMINATE "admin_decontaminate"
/// Sent when bodies transfer between shades/shards and constructs
#define COMSIG_SHADE_TO_CONSTRUCT_TRANSFER "shade_to_construct_transfer"

View File

@@ -17,7 +17,7 @@
#define PREFTOGGLE_CHAT_DEAD (1<<1)
#define PREFTOGGLE_CHAT_GHOSTEARS (1<<2)
#define PREFTOGGLE_CHAT_GHOSTSIGHT (1<<3)
#define PREFTOGGLE_CHAT_PRAYER (1<<4)
#define PREFTOGGLE_CHAT_PRAYER (1<<4) // Defunct
#define PREFTOGGLE_CHAT_RADIO (1<<5)
// #define PREFTOGGLE_AZERTY (1<<6) // obsolete
#define PREFTOGGLE_CHAT_DEBUGLOGS (1<<7)
@@ -81,6 +81,21 @@
#error toggles_2 bitflag over 16777215. Please make an issue report and postpone the feature you are working on.
#endif
// This is a list index. Required to start at 1 instead of 0 so it's properly placed in the list
#define PREFTOGGLE_CATEGORY_GENERAL 1
#define PREFTOGGLE_CATEGORY_LIVING 2
#define PREFTOGGLE_CATEGORY_GHOST 3
#define PREFTOGGLE_CATEGORY_ADMIN 4
// Preftoggle type defines
/// Special toggles, stuff that just overrides set_toggles entirely
#define PREFTOGGLE_SPECIAL 0
/// Interacts with the sound bitflag
#define PREFTOGGLE_SOUND 1
/// Interacts with the toggles bitflag
#define PREFTOGGLE_TOGGLE1 2
/// Interacts with the toggles2 bitflag
#define PREFTOGGLE_TOGGLE2 3
// Admin attack logs filter system, see /proc/add_attack_logs and /proc/msg_admin_attack
@@ -133,6 +148,7 @@
#define TAB_ANTAG 2
#define TAB_GEAR 3
#define TAB_KEYS 4
#define TAB_TOGGLES 5
// Colourblind modes
#define COLOURBLIND_MODE_NONE "None"

View File

@@ -18,6 +18,8 @@
#define STATUS_EFFECT_SHADOW_MEND /datum/status_effect/shadow_mend //Quick, powerful heal that deals damage afterwards. Heals 15 brute/burn every second for 3 seconds.
#define STATUS_EFFECT_VOID_PRICE /datum/status_effect/void_price //The price of healing yourself with void energy. Deals 3 brute damage every 3 seconds for 30 seconds.
#define STATUS_EFFECT_SHADOW_MEND_DEVIL /datum/status_effect/shadow_mend/devil //Tarot version, hurts others over self
#define STATUS_EFFECT_HIPPOCRATIC_OATH /datum/status_effect/hippocraticOath //Gives you an aura of healing as well as regrowing the Rod of Asclepius if lost
#define STATUS_EFFECT_REGENERATIVE_CORE /datum/status_effect/regenerative_core
@@ -37,6 +39,8 @@
#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
#define STATUS_EFFECT_BLOODDRUNK_CHARIOT /datum/status_effect/blooddrunk/chariot //adds pacifism
#define STATUS_EFFECT_DASH /datum/status_effect/dash // Grants the ability to dash, expiring after a few secodns
/// Rapid burn/brute/oxy/blood healing from the cling ability
@@ -62,6 +66,12 @@
#define STATUS_EFFECT_BEARSERKER_RAGE /datum/status_effect/bearserker_rage
#define STATUS_EFFECT_XRAY /datum/status_effect/xray // Xray vision for 2 minutes
#define STATUS_EFFECT_BADASS /datum/status_effect/badass // Badass trait for 2 minutes.
#define STATUS_EFFECT_REVERSED_SUN /datum/status_effect/reversed_sun // Weaker eternal darkness, nightvision, but nearsight
/////////////
// DEBUFFS //
/////////////
@@ -114,6 +124,8 @@
#define STATUS_EFFECT_PEPPERSPRAYED /datum/status_effect/pepper_spray
#define STATUS_EFFECT_REVERSED_HIGH_PRIESTESS /datum/status_effect/reversed_high_priestess //Bubblegum will chase the person hit by the effect, grabbing people at random. This can and WILL include the caster.
//#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse
//#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured
//#define CURSE_SPAWNING 2 //spawns creatures that attack the target only

View File

@@ -139,6 +139,11 @@
if(initial(D.name))
GLOB.keybindings += new path()
for(var/path in subtypesof(/datum/preference_toggle))
var/datum/preference_toggle/pref_toggle = path
if(initial(pref_toggle.name))
GLOB.preference_toggles += new path()
for(var/path in subtypesof(/datum/objective))
var/datum/objective/O = path
if(isnull(initial(O.name)))

View File

@@ -0,0 +1,8 @@
GLOBAL_LIST_EMPTY(preference_toggles)
GLOBAL_LIST_INIT(preference_toggle_groups, list(
"General Preferences" = PREFTOGGLE_CATEGORY_GENERAL,
"In-Round Preferences" = PREFTOGGLE_CATEGORY_LIVING,
"Ghost Preferences" = PREFTOGGLE_CATEGORY_GHOST,
"Admin Preferences" = PREFTOGGLE_CATEGORY_ADMIN,
))

View File

@@ -483,16 +483,3 @@
H.r_hand.screen_loc = null
if(H.l_hand)
H.l_hand.screen_loc = null
/mob/living/carbon/human/verb/toggle_hotkey_verbs()
set category = "OOC"
set name = "Toggle Hotkey Buttons"
set desc = "This disables or enables the user interface buttons which can be used with hotkeys."
if(hud_used.hotkey_ui_hidden)
client.screen += hud_used.hotkeybuttons
hud_used.hotkey_ui_hidden = FALSE
else
client.screen -= hud_used.hotkeybuttons
hud_used.hotkey_ui_hidden = TRUE

View File

@@ -10,6 +10,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/datum/radial_menu/parent
/atom/movable/screen/radial/Destroy()
parent.current_user.screen -= src
parent = null
return ..()
@@ -245,7 +246,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
QDEL_LIST_CONTENTS(elements)
QDEL_NULL(close_button)
anchor = null
. = ..()
return ..()
/*
Presents radial menu to user anchored to anchor (or user if the anchor is currently in users screen)

View File

@@ -18,7 +18,7 @@
var/allow_antag_hud = TRUE
/// Forbid players from rejoining if they use AntagHUD?
var/restrict_antag_hud_rejoin = TRUE
/// Enable respanws by default?
/// Enable respawns by default?
var/respawn_enabled = FALSE
/// Enable CID randomiser buster?
var/enabled_cid_randomiser_buster = FALSE
@@ -93,8 +93,8 @@
CONFIG_LOAD_BOOL(guest_ban, data["guest_ban"])
CONFIG_LOAD_BOOL(allow_antag_hud, data["allow_antag_hud"])
CONFIG_LOAD_BOOL(restrict_antag_hud_rejoin, data["restrict_antag_hud_rejoin"])
CONFIG_LOAD_BOOL(respawn_enabled, data["respawn_enabled"])
CONFIG_LOAD_BOOL(enabled_cid_randomiser_buster, data["enable_cid_randomiser_buster"])
CONFIG_LOAD_BOOL(respawn_enabled, data["respawn_enabled"])
CONFIG_LOAD_BOOL(forbid_singulo_possession, data["prevent_admin_singlo_possession"])
CONFIG_LOAD_BOOL(popup_admin_pm, data["popup_admin_pm"])
CONFIG_LOAD_BOOL(allow_holidays, data["allow_holidays"])

View File

@@ -97,7 +97,7 @@ SUBSYSTEM_DEF(changelog)
/client/verb/changes()
set name = "Changelog"
set desc = "View the changelog."
set category = "OOC"
set category = null
// Just invoke the actual CL thing
SSchangelog.OpenChangelog(src)

View File

@@ -699,7 +699,7 @@
// Make a holder for the charge text
var/image/count_down_holder = image('icons/effects/effects.dmi', icon_state = "nothing")
count_down_holder.plane = FLOAT_PLANE + 1.1
var/text = S.cooldown_handler.statpanel_info()
var/text = S.cooldown_handler.cooldown_info()
count_down_holder.maptext = "<div style=\"font-size:6pt;color:[recharge_text_color];font:'Small Fonts';text-align:center;\" valign=\"bottom\">[text]</div>"
button.add_overlay(count_down_holder)

View File

@@ -0,0 +1,76 @@
/**
* A component for tracking and manipulating bodies held inside constructs/shades
* Will drop the body/brain when the parent dies or is deleted.
*/
/datum/component/construct_held_body
dupe_mode = COMPONENT_DUPE_ALLOWED
/// A reference to either a mob, or a brain organ that is held inside our parent. Will drop when parent dies/is deleted
var/atom/movable/held_body
/datum/component/construct_held_body/Initialize(atom/movable/new_body)
. = ..()
add_body(new_body)
/datum/component/construct_held_body/Destroy(force, silent)
if(held_body)
stack_trace("/datum/component/construct_held_body had a held body still despite being destroyed. Body is [held_body] ([held_body.type])")
held_body = null
return ..()
/datum/component/construct_held_body/PostTransfer()
held_body.forceMove(parent) // forcemove them to the new parent
/datum/component/construct_held_body/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOB_DEATH, PROC_REF(drop_body))
RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(drop_body))
RegisterSignal(parent, COMSIG_SHADE_TO_CONSTRUCT_TRANSFER, PROC_REF(transfer_held_body))
/datum/component/construct_held_body/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_MOB_DEATH)
UnregisterSignal(parent, COMSIG_PARENT_QDELETING)
UnregisterSignal(parent, COMSIG_SHADE_TO_CONSTRUCT_TRANSFER)
/datum/component/construct_held_body/proc/add_body(atom/movable/new_body)
held_body = new_body
RegisterSignal(new_body, COMSIG_PARENT_QDELETING, PROC_REF(_null_held_body))
new_body.forceMove(parent)
/datum/component/construct_held_body/proc/_null_held_body()
SIGNAL_HANDLER // COMSIG_PARENT_QDELETING
UnregisterSignal(held_body, COMSIG_PARENT_QDELETING)
held_body = null
/datum/component/construct_held_body/proc/transfer_held_body(mob/living/current_parent, mob/living/new_body_holder)
SIGNAL_HANDLER // COMSIG_SHADE_TO_CONSTRUCT_TRANSFER
new_body_holder.TakeComponent(src)
/datum/component/construct_held_body/proc/drop_body()
SIGNAL_HANDLER // COMSIG_MOB_DEATH + COMSIG_PARENT_QDELETING
INVOKE_ASYNC(src, PROC_REF(_drop_body))
/datum/component/construct_held_body/proc/_drop_body() // call me lazy ig
if(!held_body) // Null check for empty bodies
return
var/mob/living/parent_mob = parent
held_body.forceMove(get_turf(parent))
SSticker.mode?.cult_team?.add_cult_immunity(held_body)
var/mob/living/held_mob = held_body
if(ismob(held_body)) // Check if the held_body is a mob
held_mob.key = parent_mob.key
held_mob.cancel_camera()
else if(istype(held_body, /obj/item/organ/internal/brain)) // Check if the held_body is a brain
var/obj/item/organ/internal/brain/brain = held_body
if(brain.brainmob) // Check if the brain has a brainmob
brain.brainmob.key = parent_mob.key // Set the key to the brainmob
held_mob = brain.brainmob
if(!istype(held_mob) || QDELETED(held_mob))
CRASH("/datum/component/construct_held_body/proc/_drop_body attempted to drop a body despite having no body, or a qdeleted body")
parent_mob.mind.transfer_to(held_mob) // Transfer the mind to the original mob
// goodbye construct antag datums!
held_mob.mind.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
held_mob.mind.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE)
held_body = null
qdel(src) // our job here is done

View File

@@ -537,7 +537,10 @@
/client/proc/view_var_Topic(href, href_list, hsrc)
//This should all be moved over to datum/admins/Topic() or something ~Carn
if(!check_rights(R_ADMIN|R_MOD, FALSE) && !((href_list["datumrefresh"] || href_list["Vars"] || href_list["VarsList"]) && check_rights(R_VIEWRUNTIMES, FALSE)))
if(!check_rights(R_ADMIN|R_MOD, FALSE) \
&& !((href_list["datumrefresh"] || href_list["Vars"] || href_list["VarsList"]) && check_rights(R_VIEWRUNTIMES, FALSE)) \
&& !((href_list["proc_call"]) && check_rights(R_PROCCALL, FALSE)) \
)
return // clients with R_VIEWRUNTIMES can still refresh the window/view references/view lists. they cannot edit anything else however.
if(view_var_Topic_list(href, href_list, hsrc)) // done because you can't use UIDs with lists and I don't want to snowflake into the below check to supress warnings

View File

@@ -65,8 +65,6 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
/datum/spell
var/name = "Spell" // Only rename this if the spell you're making is not abstract
var/desc = "A wizard spell"
var/panel = "Spells"//What panel the proc holder needs to go on.
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
///recharge time in deciseconds
var/base_cooldown = 10 SECONDS

View File

@@ -49,7 +49,7 @@
..()
charge_time = world.time
/datum/spell_cooldown/charges/statpanel_info()
/datum/spell_cooldown/charges/cooldown_info()
var/charge_string = charge_duration != 0 ? round(min(1, (charge_duration - (charge_time - world.time)) / charge_duration), 0.01) * 100 : 100 // need this for possible 0 charge duration
var/recharge_string = recharge_duration != 0 ? round(min(1, (recharge_duration - (recharge_time - world.time)) / recharge_duration), 0.01) * 100 : 100
return "[charge_string != 100 ? "[charge_string]%\n" : ""][recharge_string != 100 ? "[recharge_string]%\n" : ""][current_charges]/[max_charges]"

View File

@@ -64,5 +64,5 @@
/datum/spell_cooldown/proc/revert_cast()
recharge_time = world.time
/datum/spell_cooldown/proc/statpanel_info()
/datum/spell_cooldown/proc/cooldown_info()
return "[round(get_availability_percentage(), 0.01) * 100]%"

View File

@@ -8,7 +8,6 @@
overlay = null
action_icon_state = "bloodcrawl"
action_background_icon_state = "bg_demon"
panel = "Demon"
var/allowed_type = /obj/effect/decal/cleanable
var/phased = FALSE

View File

@@ -2,7 +2,6 @@
name = "Invisible Wall"
desc = "The mime's performance transmutates into physical reality."
school = "mime"
panel = "Mime"
summon_type = list(/obj/structure/forcefield/mime)
invocation_type = "emote"
invocation_emote_self = "<span class='notice'>You form a wall in front of yourself.</span>"
@@ -32,7 +31,6 @@
name = "Speech"
desc = "Make or break a vow of silence."
school = "mime"
panel = "Mime"
clothes_req = FALSE
base_cooldown = 5 MINUTES
human_req = TRUE
@@ -66,7 +64,6 @@
name = "Invisible Greater Wall"
desc = "Form an invisible three tile wide blockade."
school = "mime"
panel = "Mime"
wall_type = /obj/effect/forcefield/mime/advanced
invocation_type = "emote"
invocation_emote_self = "<span class='notice'>You form a blockade in front of yourself.</span>"
@@ -91,7 +88,6 @@
name = "Finger Gun"
desc = "Shoot lethal, silencing bullets out of your fingers! 3 bullets available per cast. Use your fingers to holster them manually."
school = "mime"
panel = "Mime"
clothes_req = FALSE
base_cooldown = 30 SECONDS
human_req = TRUE

View File

@@ -62,6 +62,11 @@
id = "shadow_mend"
duration = 3 SECONDS
alert_type = /atom/movable/screen/alert/status_effect/shadow_mend
/// If this is true, the status effect will try to apply the debuff to others, rather than the user
var/devil = FALSE
/datum/status_effect/shadow_mend/devil
devil = TRUE
/atom/movable/screen/alert/status_effect/shadow_mend
name = "Shadow Mend"
@@ -78,10 +83,25 @@
owner.adjustFireLoss(-15)
/datum/status_effect/shadow_mend/on_remove()
owner.visible_message("<span class='warning'>The violet light around [owner] glows black!</span>", "<span class='warning'>The tendrils around you cinch tightly and reap their toll...</span>")
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, 1)
owner.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
if(!devil)
owner.visible_message("<span class='warning'>The violet light around [owner] glows black!</span>", "<span class='warning'>The tendrils around you cinch tightly and reap their toll...</span>")
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, TRUE)
owner.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
return
var/found_someone = FALSE
for(var/mob/living/L in oview(9, owner))
found_someone = TRUE
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, TRUE)
L.Beam(owner, "grabber_beam", time = 1 SECONDS, maxdistance = 9)
L.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
if(found_someone)
owner.visible_message("<span class='warning'>The violet light around [owner] glows black... and shoots off to those around [owner.p_them()]!</span>", "<span class='warning'>The tendrils around you cinch tightly... but then unwravel and fly at others!</span>")
else
owner.visible_message("<span class='warning'>The violet light around [owner] glows black!</span>", "<span class='warning'>The tendrils around you cinch tightly and reap their toll...</span>")
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, TRUE)
owner.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
/datum/status_effect/void_price
id = "void_price"
@@ -110,6 +130,13 @@
tick_interval = 0
alert_type = /atom/movable/screen/alert/status_effect/blooddrunk
var/blooddrunk_damage_mod_remove = 4 // Damage is multiplied by this at the end of the status effect. Modify this one, it changes the _add
/// If this is the chariot subtype, which grants pacifism while the effect is active.
var/chariot = FALSE
/datum/status_effect/blooddrunk/chariot
duration = 10 SECONDS
chariot = TRUE
blooddrunk_damage_mod_remove = 6
/atom/movable/screen/alert/status_effect/blooddrunk
name = "Blood-Drunk"
@@ -120,6 +147,8 @@
. = ..()
if(.)
ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, "blooddrunk")
if(chariot)
ADD_TRAIT(owner, TRAIT_PACIFISM, "blooddrunk")
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
var/blooddrunk_damage_mod_add = 1 / blooddrunk_damage_mod_remove // Damage is multiplied by this at the start of the status effect. Don't modify this one directly.
@@ -144,6 +173,7 @@
H.physiology.stamina_mod *= blooddrunk_damage_mod_remove
add_attack_logs(owner, owner, "lost blood-drunk stun immunity", ATKLOG_ALL)
REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, "blooddrunk")
REMOVE_TRAIT(owner, TRAIT_PACIFISM, "blooddrunk")
if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"])
owner.remove_stun_absorption("blooddrunk")
@@ -183,7 +213,7 @@
H.physiology.stamina_mod *= 0.5
H.physiology.stun_mod *= 0.5
var/datum/antagonist/vampire/V = owner.mind.has_antag_datum(/datum/antagonist/vampire)
if(V.get_ability(/datum/vampire_passive/blood_swell_upgrade))
if(V?.get_ability(/datum/vampire_passive/blood_swell_upgrade))
bonus_damage_applied = TRUE
H.physiology.melee_bonus += 10
H.dna.species.punchstunthreshold += 8 //higher chance to stun but not 100%
@@ -776,3 +806,70 @@
var/mob/living/carbon/human/H = owner
H.physiology.stamina_mod /= 0.75
add_attack_logs(owner, owner, "lost bearserker rage resistances", ATKLOG_ALL)
/datum/status_effect/xray
id = "xray"
alert_type = null
status_type = STATUS_EFFECT_REFRESH
duration = 2 MINUTES
tick_interval = 0
/datum/status_effect/xray/on_apply()
. = ..()
ADD_TRAIT(owner, TRAIT_XRAY_VISION, "XRAY_BUFF")
ADD_TRAIT(owner, TRAIT_NIGHT_VISION, "XRAY_BUFF")
owner.update_sight()
/datum/status_effect/xray/on_remove()
. = ..()
REMOVE_TRAIT(owner, TRAIT_XRAY_VISION, "XRAY_BUFF")
REMOVE_TRAIT(owner, TRAIT_NIGHT_VISION, "XRAY_BUFF")
owner.update_sight()
/datum/status_effect/badass
id = "badass"
alert_type = null
status_type = STATUS_EFFECT_REFRESH
duration = 2 MINUTES
tick_interval = 0
/datum/status_effect/badass/on_apply()
. = ..()
ADD_TRAIT(owner, TRAIT_BADASS, "BADDASS_BUFF")
/datum/status_effect/badass/on_remove()
. = ..()
REMOVE_TRAIT(owner, TRAIT_BADASS, "BADDASS_BUFF")
/datum/status_effect/reversed_sun
id = "reversed_sun"
alert_type = null
status_type = STATUS_EFFECT_REFRESH
duration = 1 MINUTES
tick_interval = 0.2 SECONDS
/datum/status_effect/reversed_sun/on_apply()
. = ..()
owner.become_nearsighted("REVERSED_SUN")
ADD_TRAIT(owner, TRAIT_NIGHT_VISION, "REVERSED_SUN")
owner.update_sight()
owner.set_light(7, -5, "#ddd6cf")
/datum/status_effect/reversed_sun/on_remove()
. = ..()
owner.remove_light()
owner.cure_nearsighted("REVERSED_SUN")
REMOVE_TRAIT(owner, TRAIT_NIGHT_VISION, "REVERSED_SUN")
owner.update_sight()
/datum/status_effect/reversed_sun/tick()
for(var/atom/movable/AM in oview(8, owner))
if(isliving(AM))
var/mob/living/L = AM
if(L.affects_vampire(owner))
L.adjust_bodytemperature(-1.5 * TEMPERATURE_DAMAGE_COEFFICIENT)
continue
if(istype(AM, /obj/item/projectile))
var/obj/item/projectile/P = AM
if(P.flag == ENERGY || P.flag == LASER)
P.damage *= 0.85

View File

@@ -1322,3 +1322,29 @@
desc = "Real winners quit before they reach the ultimate prize."
#undef DEFAULT_MAX_CURSE_COUNT
/datum/status_effect/reversed_high_priestess
id = "reversed_high_priestess"
duration = 1 MINUTES
status_type = STATUS_EFFECT_REFRESH
tick_interval = 6 SECONDS
alert_type = /atom/movable/screen/alert/status_effect/bubblegum_curse
/datum/status_effect/reversed_high_priestess/tick()
. = ..()
new /obj/effect/bubblegum_warning(get_turf(owner))
/obj/effect/bubblegum_warning
name = "bloody rift"
desc = "You feel like even being *near* this is a bad idea"
icon = 'icons/obj/biomass.dmi'
icon_state = "rift"
color = "red"
/obj/effect/bubblegum_warning/Initialize()
. = ..()
addtimer(CALLBACK(src, PROC_REF(slap_someone)), 2.5 SECONDS) //A chance to run away
/obj/effect/bubblegum_warning/proc/slap_someone()
new /obj/effect/abstract/bubblegum_rend_helper(get_turf(src), null, 10)
qdel(src)

View File

@@ -4,6 +4,7 @@
tick_interval = -1
alert_type = /atom/movable/screen/alert/status_effect/magic_disguise
status_type = STATUS_EFFECT_REPLACE
var/mob/living/disguise_mob
var/datum/icon_snapshot/disguise
/atom/movable/screen/alert/status_effect/magic_disguise
@@ -12,27 +13,26 @@
icon = 'icons/mob/actions/actions.dmi'
icon_state = "chameleon_outfit"
/datum/status_effect/magic_disguise/on_creation(mob/living/new_owner, mob/living/disguise_mob)
/datum/status_effect/magic_disguise/on_creation(mob/living/new_owner, mob/living/_disguise_mob)
. = ..()
if(!ishuman(new_owner))
return FALSE
if(!disguise_mob)
disguise_mob = select_disguise()
if(disguise_mob && ishuman(disguise_mob))
create_disguise(disguise_mob)
if(disguise)
apply_disguise(new_owner)
return TRUE
else
to_chat(owner, "<span class='warning'>Your spell fails to find a disguise!</span>")
return FALSE
disguise_mob = _disguise_mob
/datum/status_effect/magic_disguise/on_apply()
. = ..()
if(!ishuman(owner))
return FALSE
if(!disguise_mob)
disguise_mob = select_disguise()
if(ishuman(disguise_mob))
create_disguise(disguise_mob)
if(disguise)
apply_disguise(owner)
else
to_chat(owner, "<span class='warning'>Your spell fails to find a disguise!</span>")
return FALSE
RegisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(remove_disguise))
return TRUE
/datum/status_effect/magic_disguise/on_remove()
owner.regenerate_icons()
@@ -74,6 +74,7 @@
H.overlays = disguise.overlays
H.update_inv_r_hand()
H.update_inv_l_hand()
SEND_SIGNAL(H, COMSIG_CARBON_REGENERATE_ICONS)
to_chat(H, "<span class='notice'>You disguise yourself as [disguise.name].</span>")
/datum/status_effect/magic_disguise/proc/remove_disguise()

View File

@@ -305,6 +305,17 @@
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
job = list("Head of Personnel", "Quartermaster", "Cargo Technician", "Librarian", "Coroner", "Psychiatrist", "Virologist")
// Tarot card generator, librarian and Chaplain.
/datum/uplink_item/jobspecific/tarot_generator
name = "Enchanted tarot card deck"
desc = "A magic tarot card deck \"borrowed\" from a Wizard federation storage unit. \
Capable of producing magic tarot cards of the 22 major arcana, and their reversed versions. Each card has a different effect. \
Throw the card at someone to use it on them, or use it in hand to apply it to yourself. Unlimited uses, 25 second cooldown, can have up to 3 cards in the world."
reference = "tarot"
item = /obj/item/tarot_generator
cost = 55 //This can do a lot of stuff, but is quite random. As such, higher price.
job = list("Chaplain", "Librarian")
//--------------------------//
// Species Restricted Gear //

View File

@@ -490,7 +490,6 @@
/datum/spell/immolate
name = "Incendiary Mitochondria"
desc = "The subject becomes able to convert excess cellular energy into thermal energy."
panel = "Abilities"
base_cooldown = 600

View File

@@ -277,7 +277,6 @@
/datum/spell/cryokinesis
name = "Cryokinesis"
desc = "Drops the bodytemperature of another person."
panel = "Abilities"
base_cooldown = 1200
@@ -348,7 +347,6 @@
/datum/spell/eat
name = "Eat"
desc = "Eat just about anything!"
panel = "Abilities"
base_cooldown = 300
@@ -471,8 +469,6 @@
/datum/spell/leap
name = "Jump"
desc = "Leap great distances!"
panel = "Abilities"
base_cooldown = 60
clothes_req = FALSE
@@ -564,7 +560,6 @@
/datum/spell/polymorph
name = "Polymorph"
desc = "Mimic the appearance of others!"
panel = "Abilities"
base_cooldown = 1800
clothes_req = FALSE
@@ -726,7 +721,6 @@
/datum/spell/morph
name = "Morph"
desc = "Mimic the appearance of your choice!"
panel = "Abilities"
base_cooldown = 1800
clothes_req = FALSE

View File

@@ -318,7 +318,7 @@ GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
selection_title = "Archives"
creation_message = "<span class='cultitalic'>You invoke the dark magic of the tomes creating a %ITEM%!</span>"
choosable_items = list("Shuttle Curse" = /obj/item/shuttle_curse, "Zealot's Blindfold" = /obj/item/clothing/glasses/hud/health/night/cultblind,
"Veil Shifter" = /obj/item/cult_shift, "Reality sunderer" = /obj/item/portal_amulet) //Add void torch to veil shifter spawn
"Veil Shifter" = /obj/item/cult_shift, "Reality sunderer" = /obj/item/portal_amulet, "Blank Tarot Card" = /obj/item/blank_tarot_card)
/obj/structure/cult/functional/archives/Initialize(mapload)
. = ..()

View File

@@ -464,14 +464,15 @@
user.playsound_local(user, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [target]!</span>")
target.audible_message("<span class='danger'>You hear a loud electrical buzzing sound coming from [target]!</span>")
playsound(target, 'sound/goonstation/misc/fuse.ogg', 50, FALSE, use_reverb = FALSE)
addtimer(CALLBACK(src, PROC_REF(detonate_machine), target), 5 SECONDS) //kaboom!
to_chat(user, "<span class='warning'>Overloading machine circuitry...</span>")
return TRUE
/datum/spell/ai_spell/ranged/overload_machine/proc/detonate_machine(obj/machinery/M)
if(M && !QDELETED(M))
explosion(get_turf(M), 0, 3, 5, 0)
explosion(get_turf(M), 0, 2, 3, 0)
if(M) //to check if the explosion killed it before we try to delete it
qdel(M)

View File

@@ -71,6 +71,7 @@
M.overlays = disguise.overlays
M.update_inv_r_hand()
M.update_inv_l_hand()
SEND_SIGNAL(M, COMSIG_CARBON_REGENERATE_ICONS)
/obj/item/clothing/suit/armor/abductor/vest/proc/DeactivateStealth()
if(!stealth_active)

View File

@@ -216,6 +216,35 @@
occupant = null
update_icon(UPDATE_ICON_STATE)
/obj/machinery/abductor/experiment/relaymove()
if(!occupant)
return
to_chat(occupant, "<span class='warning'>You start trying to break free!</span>")
if(!do_after(occupant, 20 SECONDS, FALSE, src))
return
var/list/possible_results = list(
CALLBACK(src, PROC_REF(electrocute_abductee)) = 1,
CALLBACK(src, PROC_REF(sedate_abductee)) = 1,
CALLBACK(src, PROC_REF(eject_abductee)) = 2
)
var/datum/callback/result = pickweight(possible_results)
result.Invoke()
/obj/machinery/abductor/experiment/proc/electrocute_abductee()
if(!occupant)
return
to_chat(occupant, "<span class='warning'>Something is electrifying you!</span>")
sleep(1 SECONDS)
occupant.electrocute_act(10, src)
do_sparks(5, TRUE, src)
/obj/machinery/abductor/experiment/proc/sedate_abductee()
if(!occupant)
return
to_chat(occupant, "<span class='warning'>Something is stabbing you in the back!</span>")
occupant.apply_damage(5, BRUTE, BODY_ZONE_CHEST)
occupant.reagents.add_reagent("ether", 5)
/obj/machinery/abductor/experiment/force_eject_occupant(mob/target)
eject_abductee()

View File

@@ -187,8 +187,6 @@
action_background_icon_state = "shadow_demon_bg"
action_icon_state = "shadow_grapple"
panel = "Demon"
sound = null
invocation_type = "none"
invocation = null

View File

@@ -111,7 +111,6 @@
overlay = null
action_icon_state = "bloodcrawl"
action_background_icon_state = "bg_cult"
panel = "Demon"
/datum/spell/sense_victims/create_new_targeting()
return new /datum/spell_targeting/alive_mob_list

View File

@@ -9,7 +9,6 @@
#define PD_UPGRADE_MAX_CHARGE "Capacity"
/datum/spell/pulse_demon
panel = "Pulse Demon"
school = "pulse demon"
clothes_req = FALSE
action_background_icon_state = "bg_pulsedemon"

View File

@@ -110,7 +110,6 @@
//Toggle night vision: lets the revenant toggle its night vision
/datum/spell/night_vision/revenant
base_cooldown = 0
panel = "Revenant Abilities"
message = "<span class='revennotice'>You toggle your night vision.</span>"
action_icon_state = "r_nightvision"
action_background_icon_state = "bg_revenant"
@@ -119,7 +118,6 @@
/datum/spell/revenant_transmit
name = "Transmit"
desc = "Telepathically transmits a message to the target."
panel = "Revenant Abilities"
base_cooldown = 0
clothes_req = FALSE
action_icon_state = "r_transmit"
@@ -145,7 +143,6 @@
name = "Spell"
clothes_req = FALSE
action_background_icon_state = "bg_revenant"
panel = "Revenant Abilities (Locked)"
/// How long it reveals the revenant in deciseconds
var/reveal = 8 SECONDS
/// How long it stuns the revenant in deciseconds
@@ -192,7 +189,6 @@
return FALSE
name = "[initial(name)] ([cast_amount]E)"
to_chat(user, "<span class='revennotice'>You have unlocked [initial(name)]!</span>")
panel = "Revenant Abilities"
locked = FALSE
cooldown_handler.revert_cast()
return FALSE

View File

@@ -0,0 +1,885 @@
/obj/item/tarot_generator
name = "Enchanted tarot card deck"
desc = "This tarot card box has quite the array of runes and artwork on it."
icon = 'icons/obj/playing_cards.dmi'
icon_state = "tarot_box"
w_class = WEIGHT_CLASS_SMALL
/// What is the maximum number of cards the tarot generator can have in the world at a time?
var/maximum_cards = 3
/// List of cards we have created, to check against maximum, and so we can purge them from the pack.
var/list/our_card_list = list()
///How long the cooldown is each time we draw a card before we can draw another?
var/our_card_cooldown_time = 25 SECONDS
COOLDOWN_DECLARE(card_cooldown)
/obj/item/tarot_generator/wizard
maximum_cards = 5
our_card_cooldown_time = 12 SECONDS // A minute for a full hand of 5 cards
/obj/item/tarot_generator/attack_self(mob/user)
if(!COOLDOWN_FINISHED(src, card_cooldown))
to_chat(user, "<span class='warning'>[src]'s magic is still recovering from the last card, wait [round(COOLDOWN_TIMELEFT(src, card_cooldown) / 10)] more second\s!</span>")
return
if(length(our_card_list) >= maximum_cards)
to_chat(user, "<span class='warning'>[src]'s magic can only support up to [maximum_cards] in the world at once, use or destroy some!</span>")
return
var/obj/item/magic_tarot_card/MTC = new /obj/item/magic_tarot_card(get_turf(src), src)
our_card_list += MTC
user.put_in_hands(MTC)
to_chat(user, "<span class='hierophant'>You draw [MTC.name]... [MTC.card_desc]</span>") //No period on purpose.
COOLDOWN_START(src, card_cooldown, our_card_cooldown_time)
/obj/item/tarot_generator/examine(mob/user)
. = ..()
. += "<span class='hierophant'>Alt-Shift-Click to destroy all cards it has produced.</span>"
. += "<span class='hierophant'>It has [length(our_card_list)] card\s in the world right now.</span>"
if(!COOLDOWN_FINISHED(src, card_cooldown))
. += "<span class='hierophant'>You may draw another card again in [round(COOLDOWN_TIMELEFT(src, card_cooldown) / 10)] second\s.</span>"
/obj/item/tarot_generator/AltShiftClick(mob/user)
for(var/obj/item/magic_tarot_card/MTC in our_card_list)
MTC.dust()
to_chat(user, "<span class='hierophant'>You dispell the cards [src] had created.</span>")
// Booster packs filled with 3, 5, or 7 playing cards! Used by the wizard space ruin, or rarely in lavaland tendril chests.
/obj/item/tarot_card_pack
name = "\improper Enchanted Arcana Pack"
desc = "A pack of 3 Enchanted tarot cards. Collect them all!"
icon = 'icons/obj/playing_cards.dmi'
icon_state = "pack"
///How many cards in a pack. 3 in base, 5 in jumbo, 7 in mega
var/cards = 3
/obj/item/tarot_card_pack/attack_self(mob/user)
user.visible_message("<span class='notice'>[user] tears open [src].</span>", \
"<span class='hierophant'>You tear open [src]!</span>")
playsound(loc, 'sound/items/poster_ripped.ogg', 50, TRUE)
for(var/i in 1 to cards)
new /obj/item/magic_tarot_card(get_turf(src))
qdel(src)
/obj/item/tarot_card_pack/jumbo
name = "\improper Jumbo Arcana Pack"
desc = "A Jumbo card pack from your friend Jimbo!"
icon_state = "jumbopack"
cards = 5
/obj/item/tarot_card_pack/mega
name = "\improper MEGA Arcana Pack"
desc = "Sadly, you won't find a Joker for an angel room, or a Soul card in here either."
icon_state = "megapack"
cards = 7
// Blank tarot cards. Made by the cult, however also good for space ruins potentially, where one feels a card pack would be too much?
/obj/item/blank_tarot_card
name = "blank tarot card"
desc = "A blank tarot card."
icon = 'icons/obj/playing_cards.dmi'
icon_state = "tarot_blank"
w_class = WEIGHT_CLASS_TINY
throw_speed = 3
throw_range = 10
throwforce = 0
force = 0
resistance_flags = FLAMMABLE
/// If a person can choose what the card produces. No cost if they can choose.
var/let_people_choose = FALSE
/obj/item/blank_tarot_card/examine(mob/user)
. = ..()
if(!let_people_choose)
. += "<span class='hierophant'>With a bit of Ink, a work of art could be created. Will you provide your Ink?</span>"
else
. += "<span class='hierophant'>We have the Ink... Could you provide your Vision instead?</span>"
/obj/item/blank_tarot_card/attack_self(mob/user)
if(!ishuman(user))
return
if(!let_people_choose)
var/mob/living/carbon/human/H = user
if(H.dna && (NO_BLOOD in H.dna.species.species_traits))
to_chat(user, "<span class='cult'>No blood to provide?...</span><span class='hierophant'> Then no Ink for the art...</span>")
return
if(H.blood_volume <= 100) //Shouldn't happen, they should be dead, but failsafe. Not bleeding as then they could recover the blood with blood rites
return
H.blood_volume -= 100
H.drop_item()
var/obj/item/magic_tarot_card/MTC = new /obj/item/magic_tarot_card(get_turf(src))
user.put_in_hands(MTC)
to_chat(user, "<span class='cult'>Your blood flows into [src]...</span><span class='hierophant'> And your Ink makes a work of art! [MTC.name]... [MTC.card_desc]</span>") //No period on purpose.
qdel(src)
return
var/tarot_type
var/tarot_name
var/list/card_by_name = list()
for(var/T in subtypesof(/datum/tarot) - /datum/tarot/reversed)
var/datum/tarot/temp = T
card_by_name[temp.name] = T
tarot_name = tgui_input_list(user, "Choose the Work of Art to create.", "Art Creation", card_by_name)
tarot_type = card_by_name[tarot_name]
if(tarot_type)
user.drop_item()
var/obj/item/magic_tarot_card/MTC = new /obj/item/magic_tarot_card(get_turf(src), null, tarot_type)
user.put_in_hands(MTC)
to_chat(user, "</span><span class='hierophant'>You put your Vision into [src], and your Vision makes a work of Art! [MTC.name]... [MTC.card_desc]</span>") //No period on purpose.
qdel(src)
/obj/item/blank_tarot_card/choose //For admins mainly, to spawn a specific tarot card. Not recommended for ruins.
let_people_choose = TRUE
/obj/item/magic_tarot_card
name = "XXII - The Unknown"
desc = "A beautiful tarot card. However, it feels like... more?"
icon = 'icons/obj/playing_cards.dmi'
icon_state = "tarot_the_unknown"
w_class = WEIGHT_CLASS_TINY
throw_speed = 3
throw_range = 10
throwforce = 0
force = 0
resistance_flags = FLAMMABLE
/// The deck that created us. Notifies it we have been deleted on use.
var/obj/item/tarot_generator/creator_deck
/// Our magic tarot card datum that lets the tarot card do stuff on use, or hitting someone
var/datum/tarot/our_tarot
/// Our fancy description given to use by the tarot datum.
var/card_desc = "Untold answers... wait what? This is a bug, report this as an issue on github!"
///Is the card face down? Shows the card back, hides the examine / name.
var/face_down = FALSE
/obj/item/magic_tarot_card/Initialize(mapload, obj/item/tarot_generator/source, datum/tarot/chosen_tarot)
. = ..()
if(source)
creator_deck = source
if(chosen_tarot)
our_tarot = new chosen_tarot
if(!istype(our_tarot))
var/tarotpath = pick(subtypesof(/datum/tarot) - /datum/tarot/reversed)
our_tarot = new tarotpath
name = our_tarot.name
card_desc = our_tarot.desc
icon_state = "tarot_[our_tarot.card_icon]"
/obj/item/magic_tarot_card/Destroy()
if(creator_deck)
creator_deck.our_card_list -= src
return ..()
/obj/item/magic_tarot_card/examine(mob/user)
. = ..()
if(!face_down)
. += "<span class='hierophant'>[card_desc]</span>"
. += "<span class='hierophant'>Alt-Shift-Click to flip the card over.</span>"
/obj/item/magic_tarot_card/attack_self(mob/user)
if(our_tarot)
INVOKE_ASYNC(our_tarot, TYPE_PROC_REF(/datum/tarot, activate), user)
poof()
/obj/item/magic_tarot_card/throw_at(atom/target, range, speed, mob/thrower, spin, diagonals_first, datum/callback/callback, force, dodgeable)
if(face_down)
flip()
. = ..()
/obj/item/magic_tarot_card/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
if(isliving(hit_atom) && our_tarot)
INVOKE_ASYNC(our_tarot, TYPE_PROC_REF(/datum/tarot, activate), hit_atom)
poof()
/obj/item/magic_tarot_card/AltShiftClick(mob/user)
flip()
/obj/item/magic_tarot_card/proc/flip()
if(!face_down)
icon_state = "cardback[our_tarot.reversed ? "?" : ""]"
name = "Enchanted tarot card"
face_down = TRUE
else
name = our_tarot.name
icon_state = "tarot_[our_tarot.card_icon]"
face_down = FALSE
/obj/item/magic_tarot_card/proc/poof()
new /obj/effect/temp_visual/revenant(get_turf(src))
qdel(src)
/obj/item/magic_tarot_card/proc/dust()
visible_message("<span class='danger'>[src] disintegrates into dust!</span>")
new /obj/effect/temp_visual/revenant(get_turf(src))
qdel(src)
/datum/tarot
/// Name used for the card
var/name = "XXII - The Unknown."
/// Desc used for the card description of the card
var/desc = "Untold answers... wait what? This is a bug, report this as an issue on github!"
/// What icon is used for the card?
var/card_icon = "the_unknown"
/// Are we reversed? Used for the card back.
var/reversed = FALSE
/datum/tarot/proc/activate(mob/living/target)
stack_trace("A bugged tarot card was spawned and used. Please make an issue report! Type was [src.type]")
/datum/tarot/reversed
name = "XXII - The Unknown?"
desc = "Untold answers... wait what? This is a bug, report this as an issue on github! This one was a reversed arcana!"
card_icon = "the_unknown?"
reversed = TRUE
/datum/tarot/the_fool
name = "0 - The Fool"
desc = "Where journey begins."
card_icon = "the_fool"
/datum/tarot/the_fool/activate(mob/living/target)
target.forceMove(pick(GLOB.latejoin))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
/datum/tarot/the_magician
name = "I - The Magician"
desc = "May you never miss your goal."
card_icon = "the_magician"
/datum/tarot/the_magician/activate(mob/living/target)
target.apply_status_effect(STATUS_EFFECT_BADASS)
to_chat(target, "<span class='notice'>You feel badass.</span>")
/datum/tarot/the_high_priestess
name = "II - The High Priestess"
desc = "Mother is watching you."
card_icon = "the_high_priestess"
/datum/tarot/the_high_priestess/activate(mob/living/target)
new /obj/effect/abstract/bubblegum_rend_helper(get_turf(target), target, 20)
/obj/effect/abstract/bubblegum_rend_helper
name = "bubblegum_rend_helper"
/obj/effect/abstract/bubblegum_rend_helper/Initialize(mapload, mob/living/owner, damage)
. = ..()
INVOKE_ASYNC(src, PROC_REF(rend), owner, damage)
/obj/effect/abstract/bubblegum_rend_helper/proc/rend(mob/living/owner, damage)
if(!owner)
for(var/mob/living/L in shuffle(view(9, src)))
owner = L
break
owner.Immobilize(3 SECONDS)
for(var/i in 1 to 3)
var/turf/first_turf = get_turf(owner)
new /obj/effect/decal/cleanable/blood/bubblegum(first_turf)
if(prob(50))
new /obj/effect/temp_visual/bubblegum_hands/rightsmack(first_turf)
else
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(first_turf)
sleep(6)
var/turf/second_turf = get_turf(owner)
to_chat(owner, "<span class='userdanger'>Something huge rends you!</span>")
playsound(second_turf, 'sound/misc/demon_attack1.ogg', 100, TRUE, -1)
owner.adjustBruteLoss(damage)
qdel(src)
/datum/tarot/the_empress
name = "III - The Empress"
desc = "May your rage bring power."
card_icon = "the_empress"
/datum/tarot/the_empress/activate(mob/living/target)
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.reagents.add_reagent("mephedrone", 4.5)
H.reagents.add_reagent("mitocholide", 12)
/datum/tarot/the_emperor
name = "IV - The Emperor"
desc = "Challenge me!"
card_icon = "the_emperor"
/datum/tarot/the_emperor/activate(mob/living/target)
var/list/L = list()
for(var/turf/T in get_area_turfs(/area/station/command/bridge))
if(is_blocked_turf(T))
continue
L.Add(T)
if(!length(L))
to_chat(target, "<span class='warning'>Huh. No bridge? Well, that sucks.</span>")
return
target.forceMove(pick(L))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
/datum/tarot/the_hierophant
name = "V - The Hierophant"
desc = "Two prayers for the lost."
card_icon = "the_hierophant"
/datum/tarot/the_hierophant/activate(mob/living/target)
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
if(!H.wear_suit)
return
H.wear_suit.setup_hierophant_shielding()
H.update_appearance(UPDATE_ICON)
/datum/tarot/the_lovers
name = "VI - The Lovers"
desc = "May you prosper and be in good health."
card_icon = "the_lovers"
/datum/tarot/the_lovers/activate(mob/living/target)
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.adjustBruteLoss(-40, robotic = TRUE)
H.adjustFireLoss(-40, robotic = TRUE)
H.blood_volume = min(H.blood_volume + 100, BLOOD_VOLUME_NORMAL)
else
target.adjustBruteLoss(-40)
target.adjustFireLoss(-40)
target.adjustOxyLoss(-40)
target.adjustToxLoss(-40)
/datum/tarot/the_chariot
name = "VII - The Chariot"
desc = "May nothing stand before you."
card_icon = "the_chariot"
/datum/tarot/the_chariot/activate(mob/living/target)
target.apply_status_effect(STATUS_EFFECT_BLOOD_RUSH)
target.apply_status_effect(STATUS_EFFECT_BLOODDRUNK_CHARIOT)
/datum/tarot/justice
name = "VIII - Justice"
desc = "May your future become balanced."
card_icon = "justice"
/datum/tarot/justice/activate(mob/living/target)
var/turf/target_turf = get_turf(target)
new /obj/item/storage/firstaid/regular(target_turf)
new /obj/item/grenade/chem_grenade/waterpotassium(target_turf)
new /obj/item/card/emag/magic_key(target_turf)
new /obj/item/stack/spacecash/c100(target_turf)
/datum/tarot/the_hermit
name = "IX - The Hermit"
desc = "May you see what life has to offer."
card_icon = "the_hermit"
/datum/tarot/the_hermit/activate(mob/living/target)
var/list/viable_vendors = list()
for(var/obj/machinery/economy/vending/candidate in GLOB.machines)
if(!is_station_level(candidate.z))
continue
viable_vendors += candidate
if(!length(viable_vendors))
to_chat(target, "<span class='warning'>No vending machines? Well, with luck cargo will have something to offer. If you go there yourself.</span>")
return
target.forceMove(get_turf(pick(viable_vendors)))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
/datum/tarot/wheel_of_fortune
name = "X - Wheel of Fortune"
desc = "Spin the wheel of destiny."
card_icon = "wheel_of_fortune"
/datum/tarot/wheel_of_fortune/activate(mob/living/target)
var/list/static/bad_vendors = list(
/obj/machinery/economy/vending/liberationstation,
/obj/machinery/economy/vending/toyliberationstation,
/obj/machinery/economy/vending/wallmed
)
var/turf/target_turf = get_turf(target)
var/vendorpath = pick(subtypesof(/obj/machinery/economy/vending) - bad_vendors)
new vendorpath(target_turf)
/datum/tarot/strength
name = "XI - Strength"
desc = "May your power bring rage."
card_icon = "strength"
/datum/tarot/strength/activate(mob/living/target)
target.apply_status_effect(STATUS_EFFECT_VAMPIRE_GLADIATOR)
target.apply_status_effect(STATUS_EFFECT_BLOOD_SWELL)
/datum/tarot/the_hanged_man
name = "XII - The Hanged Man"
desc = "May you find enlightenment."
card_icon = "the_hanged_man"
/datum/tarot/the_hanged_man/activate(mob/living/target)
if(target.flying)
return
target.flying = TRUE
addtimer(VARSET_CALLBACK(target, flying, FALSE), 60 SECONDS)
/datum/tarot/death
name = "XIII - Death"
desc = "Lay waste to all that oppose you."
card_icon = "death"
/datum/tarot/death/activate(mob/living/target)
for(var/mob/living/L in oview(9, target))
L.adjustBruteLoss(20)
L.adjustFireLoss(20)
/datum/tarot/temperance
name = "XIV - Temperance"
desc = "May you be pure in heart."
card_icon = "temperance"
/datum/tarot/temperance/activate(mob/living/target)
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
var/obj/item/organ/internal/body_egg/egg = H.get_int_organ(/obj/item/organ/internal/body_egg)
if(egg)
egg.remove(H)
H.vomit()
egg.forceMove(get_turf(H))
H.reagents.add_reagent("mutadone", 1)
for(var/obj/item/organ/internal/I in H.internal_organs)
I.heal_internal_damage(60)
H.apply_status_effect(STATUS_EFFECT_PANACEA)
for(var/thing in H.viruses)
var/datum/disease/D = thing
if(D.severity == NONTHREAT)
continue
D.cure()
/datum/tarot/the_devil
name = "XV - The Devil"
desc = "Revel in the power of darkness."
card_icon = "the_devil"
/datum/tarot/the_devil/activate(mob/living/target)
target.apply_status_effect(STATUS_EFFECT_SHADOW_MEND_DEVIL)
/datum/tarot/the_tower
name = "XVI - The Tower"
desc = "Destruction brings creation."
card_icon = "the_tower"
/datum/tarot/the_tower/activate(mob/living/target)
var/obj/item/grenade/clusterbuster/ied/bakoom = new(get_turf(target))
bakoom.prime()
/// I'm sorry matt, this is very funny.
/datum/tarot/the_stars
name = "XVII - The Stars"
desc = "May you find what you desire."
card_icon = "the_stars"
/datum/tarot/the_stars/activate(mob/living/target)
var/list/L = list()
for(var/turf/T in get_area_turfs(/area/station/security/evidence))
if(is_blocked_turf(T))
continue
L.Add(T)
if(!length(L))
to_chat(target, "<span class='warning'>Huh. No evidence? Well, that means they can't charge you with a crime, right?</span>")
return
target.forceMove(pick(L))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
for(var/obj/structure/closet/C in shuffle(view(9, target)))
if(istype(C, /obj/structure/closet/secure_closet))
var/obj/structure/closet/secure_closet/SC = C
SC.locked = FALSE
C.open()
break //Only open one locker
/datum/tarot/the_moon
name = "XVIII - The Moon"
desc = "May you find all you have lost."
card_icon = "the_moon"
/datum/tarot/the_moon/activate(mob/living/target)
var/list/funny_ruin_list = list()
var/turf/target_turf = get_turf(target)
for(var/I in GLOB.ruin_landmarks)
var/obj/effect/landmark/ruin/ruin_landmark = I
if(ruin_landmark.z == target_turf.z)
funny_ruin_list += ruin_landmark
if(length(funny_ruin_list))
var/turf/T = get_turf(pick(funny_ruin_list))
target.forceMove(T)
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
T.ChangeTurf(/turf/simulated/floor/plating) //we give them plating so they are not trapped in a wall, and a pickaxe to avoid being trapped in a wall
new /obj/item/pickaxe/emergency(T)
target.update_parallax_contents()
return
//We did not find a ruin on the same level. Well. I hope you have a space suit, but we'll go space ruins as they are mostly sorta kinda safer.
for(var/I in GLOB.ruin_landmarks)
var/obj/effect/landmark/ruin/ruin_landmark = I
if(!is_mining_level(ruin_landmark.z))
funny_ruin_list += ruin_landmark
if(!length(funny_ruin_list))
to_chat(target, "<span class='warning'>Huh. No space ruins? Well, this card is RUINED!</span>")
var/turf/T = get_turf(pick(funny_ruin_list))
target.forceMove(T)
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
T.ChangeTurf(/turf/simulated/floor/plating) //we give them plating so they are not trapped in a wall, and a pickaxe to avoid being trapped in a wall
new /obj/item/pickaxe/emergency(T)
target.update_parallax_contents()
return
/datum/tarot/the_sun
name = "XIX - The Sun"
desc = "May the light heal and enlighten you."
card_icon = "the_sun"
/datum/tarot/the_sun/activate(mob/living/target)
target.revive()
/datum/tarot/judgement
name = "XX - Judgement"
desc = "Judge lest ye be judged."
card_icon = "judgement"
/datum/tarot/judgement/activate(mob/living/target)
notify_ghosts("[target] has used a judgment card. Judge them. Or not, up to you.", enter_link = "<a href=byond://?src=[UID()];follow=1>(Click to judge)</a>", source = target, action = NOTIFY_FOLLOW)
/datum/tarot/the_world
name = "XXI - The World"
desc = "Open your eyes and see."
card_icon = "the_world"
/datum/tarot/the_world/activate(mob/living/target)
var/datum/effect_system/smoke_spread/bad/smoke = new()
smoke.set_up(10, FALSE, target)
smoke.start()
target.apply_status_effect(STATUS_EFFECT_XRAY)
////////////////////////////////
////////REVERSED ARCANA/////////
////////////////////////////////
/datum/tarot/reversed/the_fool
name = "0 - The Fool?"
desc = "Let go and move on."
card_icon = "the_fool?"
/datum/tarot/reversed/the_fool/activate(mob/living/target)
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
for(var/obj/item/I in H)
if(istype(/obj/item/bio_chip, I))
continue
H.unEquip(I)
/datum/tarot/reversed/the_magician
name = "I - The Magician?"
desc = "May no harm come to you."
card_icon = "the_magician?"
/datum/tarot/reversed/the_magician/activate(mob/living/target)
var/list/thrown_atoms = list()
var/sparkle_path = /obj/effect/temp_visual/gravpush
for(var/turf/T in range(5, target)) //Done this way so things don't get thrown all around hilariously.
for(var/atom/movable/AM in T)
thrown_atoms += AM
for(var/atom/movable/AM as anything in thrown_atoms)
if(AM == target || AM.anchored || (ismob(AM) && !isliving(AM)))
continue
var/throw_target = get_edge_target_turf(target, get_dir(target, get_step_away(AM, target)))
var/dist_from_user = get_dist(target, AM)
if(dist_from_user == 0)
if(isliving(AM))
var/mob/living/M = AM
M.Weaken(6 SECONDS)
M.adjustBruteLoss(10)
to_chat(M, "<span class='userdanger'>You're slammed into the floor by [name]!</span>")
add_attack_logs(target, M, "[M] was thrown by [target]'s [name]", ATKLOG_ALMOSTALL)
else
new sparkle_path(get_turf(AM), get_dir(target, AM))
if(isliving(AM))
var/mob/living/M = AM
to_chat(M, "<span class='userdanger'>You're thrown back by [name]!</span>")
add_attack_logs(target, M, "[M] was thrown by [target]'s [name]", ATKLOG_ALMOSTALL)
INVOKE_ASYNC(AM, TYPE_PROC_REF(/atom/movable, throw_at), throw_target, ((clamp((3 - (clamp(dist_from_user - 2, 0, dist_from_user))), 3, 3))), 1) //So stuff gets tossed around at the same time.
/datum/tarot/reversed/the_high_priestess
name = "II - The High Priestess?"
desc = "Run."
card_icon = "the_high_priestess?"
/datum/tarot/reversed/the_high_priestess/activate(mob/living/target)
target.visible_message("<span class='colossus'><b>WHO DARES TO TRY TO USE MY POWER IN A CARD?</b></span>")
target.apply_status_effect(STATUS_EFFECT_REVERSED_HIGH_PRIESTESS)
/datum/tarot/reversed/the_empress
name = "III - The Empress?"
desc = "May your love bring protection."
card_icon = "the_empress?"
/datum/tarot/reversed/the_empress/activate(mob/living/target)
for(var/mob/living/L in oview(9, target))
L.apply_status_effect(STATUS_EFFECT_PACIFIED)
/datum/tarot/reversed/the_emperor
name = "IV - The Emperor?"
desc = "May you find a worthy opponent."
card_icon = "the_emperor?"
/datum/tarot/reversed/the_emperor/activate(mob/living/target)
var/list/L = list()
var/list/heads = SSticker.mode.get_all_heads()
for(var/datum/mind/head in heads)
if(ishuman(head.current))
L.Add(head.current)
if(!length(L))
to_chat(target, "<span class='warning'>Huh. No command members? I hope you didn't kill them all already...</span>")
return
target.forceMove(get_turf(pick(L)))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")
/datum/tarot/reversed/the_hierophant
name = "V - The Hierophant?"
desc = "Two prayers for the forgotten."
card_icon = "the_hierophant?"
/datum/tarot/reversed/the_hierophant/activate(mob/living/target)
var/active_chasers = 0
for(var/mob/living/M in shuffle(orange(7, target)))
if(M.stat == DEAD) //Let us not have dead mobs be used to make a disco inferno.
continue
if(active_chasers >= 2)
return
var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(target), target, M, 1, FALSE)
C.moving = 2
C.standard_moving_before_recalc = 2
C.moving_dir = text2dir(pick("NORTH", "SOUTH", "EAST", "WEST"))
active_chasers++
/datum/tarot/reversed/the_lovers
name = "VI - The Lovers?"
desc = "May your heart shatter to pieces."
card_icon = "the_lovers?"
/datum/tarot/reversed/the_lovers/activate(mob/living/target)
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
H.apply_damage(20, BRUTE, BODY_ZONE_CHEST)
H.bleed(120)
var/obj/item/organ/external/chest = H.get_organ(BODY_ZONE_CHEST)
chest.fracture()
var/datum/organ/heart/datum_heart = H.get_int_organ_datum(ORGAN_DATUM_HEART)
var/obj/item/organ/internal/our_heart = datum_heart.linked_organ
our_heart.receive_damage(20, TRUE)
/datum/tarot/reversed/the_chariot
name = "VII - The Chariot?"
desc = "May nothing walk past you."
card_icon = "the_chariot?"
/datum/tarot/reversed/the_chariot/activate(mob/living/target)
target.Stun(4 SECONDS)
new /obj/structure/closet/statue/indestructible(get_turf(target), target)
/datum/tarot/reversed/justice
name = "VIII - Justice?"
desc = "May your sins come back to torment you."
card_icon = "justice?"
/datum/tarot/reversed/justice/activate(mob/living/target)
var/list/static/ignored_supply_pack_types = list(
/datum/supply_packs/abstract,
/datum/supply_packs/abstract/shuttle
)
var/chosen = pick(SSeconomy.supply_packs - ignored_supply_pack_types)
var/datum/supply_packs/the_pack = new chosen()
var/spawn_location = get_turf(target)
var/obj/structure/closet/crate/crate = the_pack.create_package(spawn_location)
crate.name = "magic [crate.name]"
qdel(the_pack)
/datum/tarot/reversed/the_hermit
name = "IX - The Hermit?"
desc = "May you see the value of all things in life."
card_icon = "the_hermit?"
/datum/tarot/reversed/the_hermit/activate(mob/living/target) //Someone can improve this in the future (hopefully comment will not be here in 10 years.)
for(var/obj/item/I in view(7, target))
if(istype(I, /obj/item/gun))
new /obj/item/stack/spacecash/c200(get_turf(I))
qdel(I)
continue
if(istype(I, /obj/item/grenade))
new /obj/item/stack/spacecash/c50(get_turf(I))
qdel(I)
if(istype(I, /obj/item/clothing/suit/armor))
new /obj/item/stack/spacecash/c100(get_turf(I))
qdel(I)
if(istype(I, /obj/item/melee/baton))
new /obj/item/stack/spacecash/c100(get_turf(I))
qdel(I)
/datum/tarot/reversed/wheel_of_fortune
name = "X - Wheel of Fortune?"
desc = "Throw the dice of fate."
card_icon = "wheel_of_fortune?"
/datum/tarot/reversed/wheel_of_fortune/activate(mob/living/target)
var/obj/item/dice/d20/fate/one_use/gonna_roll_a_one = new /obj/item/dice/d20/fate/one_use(get_turf(target))
gonna_roll_a_one.diceroll(target)
/datum/tarot/reversed/strength
name = "XI - Strength?"
desc = "May you break their resolve."
card_icon = "strength?"
/datum/tarot/reversed/strength/activate(mob/living/target)
for(var/mob/living/M in oview(9, target))
M.Hallucinate(2 MINUTES)
new /obj/effect/hallucination/delusion(get_turf(M), M)
M.adjustBrainLoss(30)
/datum/tarot/reversed/the_hanged_man
name = "XII - The Hanged Man?"
desc = "May your greed know no bounds."
card_icon = "the_hanged_man?"
/datum/tarot/reversed/the_hanged_man/activate(mob/living/target)
var/obj/structure/cursed_slot_machine/pull_the_lever_kronk = new /obj/structure/cursed_slot_machine(get_turf(target))
if(ishuman(target))
var/mob/living/carbon/human/WRONG_LEVER = target
pull_the_lever_kronk.attack_hand(WRONG_LEVER)
/datum/tarot/reversed/death
name = "XIII - Death?"
desc = "May life spring forth from the fallen."
card_icon = "death?"
/datum/tarot/reversed/death/activate(mob/living/target)
new /obj/structure/constructshell(get_turf(target))
new /obj/item/soulstone/anybody(get_turf(target))
/datum/tarot/reversed/temperance
name = "XIV - Temperance?"
desc = "May your hunger be satiated."
card_icon = "temperance?"
/datum/tarot/reversed/temperance/activate(mob/living/target)
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
for(var/i in 1 to 5)
var/datum/reagents/R = new /datum/reagents(10)
R.add_reagent(get_unrestricted_random_reagent_id(), 10)
R.reaction(H, REAGENT_INGEST)
R.trans_to(H, 10)
target.visible_message("<span class='warning'>[target] consumes 5 pills rapidly!</span>")
/datum/tarot/reversed/the_devil
name = "XV - The Devil?"
desc = "Bask in the light of your mercy."
card_icon = "the_devil?"
/datum/tarot/reversed/the_devil/activate(mob/living/target)
var/obj/item/grenade/clusterbuster/i_hate_nians = new(get_turf(target))
i_hate_nians.prime()
/datum/tarot/reversed/the_tower
name = "XVI - The Tower?"
desc = "Creation brings destruction."
card_icon = "the_tower?"
/datum/tarot/reversed/the_tower/activate(mob/living/target)
for(var/turf/T in RANGE_TURFS(9, target))
if(locate(/mob/living) in T)
continue
if(istype(T, /turf/simulated/wall/indestructible))
continue
if(prob(66))
continue
T.ChangeTurf(/turf/simulated/mineral/random/labormineral)
/datum/tarot/reversed/the_stars
name = "XVII - The Stars?"
desc = "May your loss bring fortune."
card_icon = "the_stars?"
/datum/tarot/reversed/the_stars/activate(mob/living/target) //Heavy clone damage hit, but gain 2 cards. Not teathered to the card producer. Could lead to card stacking, but would require the sun to fix easily
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
H.adjustCloneLoss(50)
for(var/obj/item/organ/external/E in shuffle(H.bodyparts))
switch(rand(1,3))
if(1)
E.fracture()
if(2)
E.cause_internal_bleeding()
if(3)
E.cause_burn_wound()
break // I forgot the break the first time. Very funny.
H.drop_l_hand()
H.drop_r_hand()
var/obj/item/magic_tarot_card/MTC = new /obj/item/magic_tarot_card(get_turf(src))
var/obj/item/magic_tarot_card/MPC = new /obj/item/magic_tarot_card(get_turf(src))
H.put_in_hands(MTC)
H.put_in_hands(MPC)
/datum/tarot/reversed/the_moon
name = "XVIII - The Moon?"
desc = "May you remember lost memories."
card_icon = "the_moon?"
/datum/tarot/reversed/the_moon/activate(mob/living/target)
for(var/mob/living/L in view(5, target)) //Shorter range as this kinda can give away antagonists, though that is also funny.
target.mind.show_memory(L, 0) //Safe code? Bank accounts? PDA codes? It's yours my friend, as long as you have enough tarots
/datum/tarot/reversed/the_sun
name = "XIX - The Sun?"
desc = "May the darkness swallow all around you."
card_icon = "the_sun?"
/datum/tarot/reversed/the_sun/activate(mob/living/target)
target.apply_status_effect(STATUS_EFFECT_REVERSED_SUN)
/datum/tarot/reversed/judgement
name = "XX - Judgement?"
desc = "May you redeem those found wanting" //Who wants more, but ghosts for something interesting
card_icon = "judgement?"
/datum/tarot/reversed/judgement/activate(mob/living/target)
var/datum/event_container/EC = SSevents.event_containers[EVENT_LEVEL_MODERATE]
var/decrease = 5 MINUTES
EC.next_event_time -= decrease
log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by 5 minutes by use of a [src].")
/datum/tarot/reversed/the_world
name = "XXI - The World?"
desc = "Step into the abyss."
card_icon = "the_world?"
/datum/tarot/reversed/the_world/activate(mob/living/target)
var/list/L = list()
for(var/turf/T in get_area_turfs(/area/mine/outpost)) //Lavaland is the abyss, but also too hot to send people too. Mining base should be fair!
if(is_blocked_turf(T))
continue
L.Add(T)
if(!length(L))
to_chat(target, "<span class='warning'>Hmm. No base? A miner issue.</span>")
return
target.forceMove(pick(L))
to_chat(target, "<span class='userdanger'>You are abruptly pulled through space!</span>")

View File

@@ -79,7 +79,9 @@ GLOBAL_LIST_INIT(summoned_magic, list(
/obj/item/scrying,
/obj/item/clothing/suit/space/hardsuit/wizard,
/obj/item/immortality_talisman,
/obj/item/melee/ghost_sword))
/obj/item/melee/ghost_sword,
/obj/item/tarot_card_pack,
/obj/item/tarot_card_pack/jumbo))
GLOBAL_LIST_INIT(summoned_special_magic, list(
/obj/item/gun/magic/staff/animate,
@@ -87,7 +89,8 @@ GLOBAL_LIST_INIT(summoned_special_magic, list(
/obj/item/contract,
/obj/item/gun/magic/staff/chaos,
/obj/item/necromantic_stone,
/obj/item/blood_contract))
/obj/item/blood_contract,
/obj/item/tarot_generator))
//everything above except for single use spellbooks, because they are counted separately (and are for basic bitches anyways)
GLOBAL_LIST_INIT(summoned_magic_objectives, list(
@@ -100,7 +103,8 @@ GLOBAL_LIST_INIT(summoned_magic_objectives, list(
/obj/item/necromantic_stone,
/obj/item/scrying,
/obj/item/spellbook,
/obj/item/storage/belt/wands/full))
/obj/item/storage/belt/wands/full,
/obj/item/tarot_generator))
// If true, it's the probability of triggering "survivor" antag.
GLOBAL_VAR_INIT(summon_guns_triggered, FALSE)

View File

@@ -11,8 +11,8 @@
slot_flags = SLOT_FLAG_BELT
origin_tech = "bluespace=4;materials=5"
/// The body/brain of the player inside this construct, transferred over from the soulstone.
var/atom/movable/held_body
/// Should we show rays? Triggered by a held body
var/animate_rays = FALSE
/// Does this soulstone ask the victim whether they want to be turned into a shade
var/optional = FALSE
/// Can this soul stone be used by anyone, or only cultists/wizards?
@@ -26,13 +26,6 @@
var/opt_in = FALSE
var/purified = FALSE
/obj/item/soulstone/proc/add_held_body(atom/movable/body)
held_body = body
RegisterSignal(body, COMSIG_PARENT_QDELETING, PROC_REF(remove_held_body))
/obj/item/soulstone/proc/remove_held_body()
SIGNAL_HANDLER
held_body = null
/obj/item/soulstone/proc/can_use(mob/living/user)
if(IS_CULTIST(user) && purified && !iswizard(user))
@@ -78,13 +71,12 @@
/obj/item/soulstone/Destroy() //Stops the shade from being qdel'd immediately and their ghost being sent back to the arrival shuttle.
for(var/mob/living/simple_animal/shade/A in src)
A.death()
remove_held_body()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/soulstone/process()
. = ..()
if(held_body)
if(animate_rays)
var/new_filter = isnull(get_filter("ray"))
if(!purified)
ray_filter_helper(1, 40,"#c926ae", 6, 20)
@@ -242,20 +234,19 @@
to_chat(user, "<span class='notice'>The shard feels too tough to shatter, you are not holy enough to free its captive!</span>")
return
if(!do_after_once(user, 10 SECONDS, FALSE, src) || !held_body)
if(!do_after_once(user, 10 SECONDS, FALSE, src))
return
user.visible_message("[user] shatters the soulstone apart! Releasing [held_body] from their prison!", "You shatter the soulstone holding [held_body], binding them free!", "You hear something shatter with a ghastly crack.")
if(ismob(held_body))
var/mob/M = held_body
M.key = S.key
else if(istype(held_body, /obj/item/organ/internal/brain))
var/obj/item/organ/internal/brain/B = held_body
B.brainmob.key = S.key
S.cancel_camera()
held_body.forceMove(get_turf(src))
SSticker.mode?.cult_team?.add_cult_immunity(held_body)
remove_held_body()
if(!S)
return
var/datum/component/construct_held_body/body_holder = S.GetComponent(/datum/component/construct_held_body)
var/atom/movable/dropped_body = body_holder.held_body
body_holder.drop_body()
if(!dropped_body)
return
user.visible_message("[user] shatters the soulstone apart! Releasing [dropped_body] from their prison!", "You shatter the soulstone holding [dropped_body], binding them free!", "You hear something shatter with a ghastly crack.")
new /obj/effect/temp_visual/cult/sparks(get_turf(src))
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
qdel(src)
@@ -276,6 +267,7 @@
was_used()
remove_filter("ray")
STOP_PROCESSING(SSobj, src)
animate_rays = FALSE
///////////////////////////Transferring to constructs/////////////////////////////////////////////////////
/obj/structure/constructshell
@@ -320,9 +312,8 @@
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
T.Paralyse(40 SECONDS)
if(!get_cult_ghost(T, user, TRUE))
add_held_body(T)
T.forceMove(src) //If we can't get a ghost, shard the body anyways.
START_PROCESSING(SSobj, src)
// no luck, dont shard them.
to_chat(user, "<span class='userdanger'>No soul responds to the soul stone.</span>")
if("VICTIM")
var/mob/living/carbon/human/T = target
@@ -361,6 +352,7 @@
name = "soulstone : [T.name]"
to_chat(T, "<span class='notice'>Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form</span>")
to_chat(user, "<span class='notice'>Capture successful!</span> [T.name]'s has been recaptured and stored within the soul stone.")
animate_rays = TRUE
START_PROCESSING(SSobj, src)
if("CONSTRUCT")
@@ -413,9 +405,8 @@
to_chat(src, "<span class='userdanger'>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</span>")
else
to_chat(src, "<span class='userdanger'>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</span>")
SS.held_body.forceMove(src)
add_held_body(SS.held_body)
SS.remove_held_body()
SEND_SIGNAL(shade, COMSIG_SHADE_TO_CONSTRUCT_TRANSFER, src)
cancel_camera()
qdel(shell)
qdel(shade)
@@ -465,13 +456,13 @@
if(!isrobot(M))
for(var/obj/item/I in M)
M.unEquip(I)
var/target_body = M
if(isbrain(M))
var/obj/item/organ/internal/brain/brain_obj = M.loc
add_held_body(brain_obj)
brain_obj.forceMove(src)
else
add_held_body(M)
M.forceMove(src)
target_body = M.loc // get the brain organ instead of the brain mob
S.AddComponent(/datum/component/construct_held_body, target_body)
animate_rays = TRUE
/obj/item/soulstone/proc/get_shade_type()
if(purified)

View File

@@ -483,6 +483,15 @@
cost = 1
category = "Artefacts"
/datum/spellbook_entry/item/tarot_generator
name = "Enchanted tarot card deck"
desc = "An magic tarot card deck, enchanted with special Ink. \
Capable of producing magic tarot cards of the 22 major arcana, both normal and reversed. Each card has a different effect. \
Throw the card at someone to use it on them, or use it in hand to apply it to yourself. Unlimited uses, 12 second cooldown, can have up to 5 cards in the world."
item_path = /obj/item/tarot_generator/wizard
cost = 2
category = "Artefacts"
//Weapons and Armors
/datum/spellbook_entry/item/battlemage
name = "Battlemage Armor"

View File

@@ -32,18 +32,6 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
ROLE_ABDUCTOR = 20,
))
// Client Verbs
/client/verb/cmd_check_own_playtime()
set category = "Special Verbs"
set name = "Check my playtime"
if(!GLOB.configuration.jobs.enable_exp_tracking)
to_chat(src, "<span class='warning'>Playtime tracking is not enabled.</span>")
return
to_chat(src, "<span class='notice'>Your [EXP_TYPE_CREW] playtime is [get_exp_type(EXP_TYPE_CREW)].</span>")
// Admin Verbs
/client/proc/cmd_mentor_check_player_exp() //Allows admins to determine who the newer players are.

View File

@@ -9,6 +9,13 @@
name = "blood sparks"
icon_state = "bloodsparkles"
/obj/effect/temp_visual/cult/sparks/hierophant
icon = 'icons/effects/effects.dmi'
randomdir = TRUE
duration = 12
name = "purple sparks"
icon_state = "hierophant_blast"
/obj/effect/temp_visual/dir_setting/cult/phase
name = "phase glow"
duration = 12

View File

@@ -514,7 +514,7 @@ GLOBAL_LIST_INIT(cult_recipes, list (
new /datum/stack_recipe/cult("runed girder (used to make cult walls)", /obj/structure/girder/cult, 1, time = 1 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
new /datum/stack_recipe/cult("pylon (heals nearby cultists)", /obj/structure/cult/functional/pylon, 4, time = 4 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
new /datum/stack_recipe/cult("forge (crafts shielded robes, flagellant's robes, and mirror shields)", /obj/structure/cult/functional/forge, 3, time = 4 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
new /datum/stack_recipe/cult("archives (crafts zealot's blindfolds, shuttle curse orbs, veil shifters, and reality sunderers)", /obj/structure/cult/functional/archives, 3, time = 4 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
new /datum/stack_recipe/cult("archives (crafts zealot's blindfolds, shuttle curse orbs, veil shifters, reality sunderers, and blank tarot cards)", /obj/structure/cult/functional/archives, 3, time = 4 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
new /datum/stack_recipe/cult("altar (crafts eldritch whetstones, construct shells, and flasks of unholy water)", /obj/structure/cult/functional/altar, 3, time = 4 SECONDS, one_per_turf = TRUE, on_floor = TRUE, cult_structure = TRUE),
))

View File

@@ -47,6 +47,21 @@
return
A.emag_act(user)
/obj/item/card/emag/magic_key
name = "magic key"
desc = "It's a magic key, that will open one door!"
icon_state = "magic_key"
origin_tech = "magnets=2"
/obj/item/card/emag/magic_key/afterattack(atom/target, mob/user, proximity)
if(!istype(target, /obj/machinery/door))
return
var/obj/machinery/door/D = target
D.locked = FALSE
update_icon()
. = ..()
qdel(src)
/obj/item/card/cmag
desc = "It's a card coated in a slurry of electromagnetic bananium."
name = "jestographic sequencer"

View File

@@ -227,6 +227,11 @@
desc = "For when you need to knock out EVERYONE."
payload = /obj/item/grenade/gas/knockout
/obj/item/grenade/clusterbuster/ied
name = "\improper IED Cluster Grenade"
desc = "For when you need to do something between everything and nothing."
payload = /obj/item/grenade/iedcasing
////////////Clusterbuster of Clusterbusters////////////
//As a note: be extrodinarily careful about make the payload clusterbusters as it can quickly destroy the MC/Server

View File

@@ -720,7 +720,8 @@
/obj/item/warp_cube/red = 1,
/obj/item/reagent_containers/drinks/everfull = 2,
/obj/item/clothing/suit/space/hardsuit/wizard = 2,
/obj/item/immortality_talisman = 1 ) //spells recharge when invincible
/obj/item/immortality_talisman = 1, //spells recharge when invincible
/obj/item/tarot_generator/wizard = 2)
var/obj/item/pickeda = pick(list_a)
value += list_a[pickeda]
new pickeda(src)

View File

@@ -117,3 +117,17 @@
user.dust()
dump_contents()
visible_message("<span class='warning'>[src] shatters!</span>")
/obj/structure/closet/statue/indestructible
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
timer = 240 SECONDS_TO_LIFE_CYCLES
/obj/structure/closet/statue/indestructible/ex_act(severity)
return //No delimbing them
/obj/structure/closet/statue/indestructible/shatter(mob/user)
return //No. Failsafe.
/obj/structure/closet/statue/indestructible/singularity_act()
return //I mean maybe but no.

View File

@@ -106,61 +106,6 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(GLOB.configuration.general.auto_disable_ooc && GLOB.ooc_enabled != on)
toggle_ooc()
/client/proc/set_ooc(newColor as color)
set name = "Set Player OOC Colour"
set desc = "Modifies the default player OOC color."
set category = "Server"
if(!check_rights(R_SERVER)) return
GLOB.normal_ooc_colour = newColor
message_admins("[key_name_admin(usr)] has set the default player OOC color to [newColor]")
log_admin("[key_name(usr)] has set the default player OOC color to [newColor]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Player OOC")
/client/proc/reset_ooc()
set name = "Reset Player OOC Color"
set desc = "Returns the default player OOC color to default."
set category = "Server"
if(!check_rights(R_SERVER)) return
GLOB.normal_ooc_colour = DEFAULT_PLAYER_OOC_COLOUR
message_admins("[key_name_admin(usr)] has reset the default player OOC color")
log_admin("[key_name(usr)] has reset the default player OOC color")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Reset Player OOC")
/client/proc/colorooc()
set name = "Set Your OOC Color"
set desc = "Allows you to pick a custom OOC color."
set category = "Preferences"
if(!check_rights(R_ADMIN)) return
var/new_ooccolor = input(src, "Please select your OOC color.", "OOC color", prefs.ooccolor) as color|null
if(new_ooccolor)
prefs.ooccolor = new_ooccolor
prefs.save_preferences(src)
to_chat(usr, "Your OOC color has been set to [new_ooccolor].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Own OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/resetcolorooc()
set name = "Reset Your OOC Color"
set desc = "Returns your OOC color to default."
set category = "Preferences"
if(!check_rights(R_ADMIN)) return
prefs.ooccolor = initial(prefs.ooccolor)
prefs.save_preferences(src)
to_chat(usr, "Your OOC color has been reset.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Reset Own OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/looc(msg = "" as text)
set name = "LOOC"
set desc = "Local OOC, seen only by those in view."

View File

@@ -2,8 +2,6 @@
GLOBAL_LIST_INIT(admin_verbs_default, list(
/client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/
/client/proc/hide_verbs, /*hides all our adminverbs*/
/client/proc/toggleadminhelpsound,
/client/proc/togglementorhelpsound,
/client/proc/cmd_mentor_check_new_players,
/client/proc/cmd_mentor_check_player_exp /* shows players by playtime */
))
@@ -13,8 +11,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
/datum/admins/proc/announce, /*priority announce something to all clients.*/
/client/proc/colorooc, /*allows us to set a custom colour for everything we say in ooc*/
/client/proc/resetcolorooc, /*allows us to set a reset our ooc color*/
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
/client/proc/toggle_view_range, /*changes how far we can see*/
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
@@ -35,8 +31,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
/client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */
/client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
/client/proc/toggleprayers, /*toggles prayers on/off*/
/client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
/datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
/datum/admins/proc/togglelooc, /*toggles looc on/off for everyone*/
@@ -49,9 +43,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
/client/proc/cmd_mentor_say,
/datum/admins/proc/show_player_notes,
/client/proc/free_slot, /*frees slot for chosen job*/
/client/proc/toggleattacklogs,
/client/proc/toggleadminlogs,
/client/proc/toggledebuglogs,
/client/proc/update_mob_sprite,
/client/proc/man_up,
/client/proc/global_man_up,
@@ -140,8 +131,6 @@ GLOBAL_LIST_INIT(admin_verbs_server, list(
/client/proc/view_asays,
/client/proc/toggle_antagHUD_use,
/client/proc/toggle_antagHUD_restrictions,
/client/proc/set_ooc,
/client/proc/reset_ooc,
/client/proc/set_next_map,
/client/proc/manage_queue,
/client/proc/add_queue_server_bypass
@@ -155,7 +144,6 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/cmd_debug_del_sing,
/client/proc/restart_controller,
/client/proc/enable_debug_verbs,
/client/proc/toggledebuglogs,
/client/proc/cmd_display_del_log,
/client/proc/cmd_display_del_log_simple,
/client/proc/check_bomb_impacts,
@@ -181,8 +169,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/debug_timers,
/client/proc/force_verb_bypass,
/client/proc/show_gc_queues,
/client/proc/debug_global_variables,
/client/proc/toggle_mctabs
/client/proc/debug_global_variables
))
GLOBAL_LIST_INIT(admin_verbs_possess, list(
/proc/possess,
@@ -215,7 +202,6 @@ GLOBAL_LIST_INIT(admin_verbs_mentor, list(
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/
/client/proc/openMentorTicketUI,
/client/proc/toggleMentorTicketLogs,
/client/proc/cmd_mentor_say /* mentor say*/
// cmd_mentor_say is added/removed by the toggle_mentor_chat verb
))
@@ -226,9 +212,7 @@ GLOBAL_LIST_INIT(admin_verbs_proccall, list(
))
GLOBAL_LIST_INIT(admin_verbs_ticket, list(
/client/proc/openAdminTicketUI,
/client/proc/toggleticketlogs,
/client/proc/openMentorTicketUI,
/client/proc/toggleMentorTicketLogs,
/client/proc/resolveAllAdminTickets,
/client/proc/resolveAllMentorTickets
))
@@ -246,15 +230,13 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
/client/proc/view_runtimes,
/client/proc/cmd_display_del_log,
/client/proc/cmd_display_del_log_simple,
/client/proc/toggledebuglogs,
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
/client/proc/ss_breakdown,
/client/proc/show_gc_queues,
/client/proc/debug_global_variables,
/client/proc/visualise_active_turfs,
/client/proc/debug_timers,
/client/proc/timer_log,
/client/proc/toggle_mctabs
/client/proc/timer_log
))
/client/proc/add_admin_verbs()
@@ -880,91 +862,6 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
log_admin("[key_name(usr)] has freed a job slot for [job].")
message_admins("[key_name_admin(usr)] has freed a job slot for [job].")
/client/proc/toggleattacklogs()
set name = "Attack Log Messages"
set category = "Preferences.Toggle"
if(!check_rights(R_ADMIN))
return
if(prefs.atklog == ATKLOG_ALL)
prefs.atklog = ATKLOG_ALMOSTALL
to_chat(usr, "Your attack logs preference is now: show ALMOST ALL attack logs (notable exceptions: NPCs attacking other NPCs, vampire bites, equipping/stripping, people pushing each other over)")
else if(prefs.atklog == ATKLOG_ALMOSTALL)
prefs.atklog = ATKLOG_MOST
to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides player v. NPC combat, and certain areas like lavaland syndie base and thunderdome)")
else if(prefs.atklog == ATKLOG_MOST)
prefs.atklog = ATKLOG_FEW
to_chat(usr, "Your attack logs preference is now: show FEW attack logs (only the most important stuff: attacks on SSDs, use of explosives, messing with the engine, gibbing, AI wiping, forcefeeding, acid sprays, and organ extraction)")
else if(prefs.atklog == ATKLOG_FEW)
prefs.atklog = ATKLOG_NONE
to_chat(usr, "Your attack logs preference is now: show NO attack logs")
else if(prefs.atklog == ATKLOG_NONE)
prefs.atklog = ATKLOG_ALL
to_chat(usr, "Your attack logs preference is now: show ALL attack logs")
else
prefs.atklog = ATKLOG_ALL
to_chat(usr, "Your attack logs preference is now: show ALL attack logs (your preference was set to an invalid value, it has been reset)")
prefs.save_preferences(src)
/client/proc/toggleadminlogs()
set name = "Admin Log Messages"
set category = "Preferences.Toggle"
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= PREFTOGGLE_CHAT_NO_ADMINLOGS
prefs.save_preferences(src)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_ADMINLOGS)
to_chat(usr, "You now won't get admin log messages.")
else
to_chat(usr, "You now will get admin log messages.")
/client/proc/toggleMentorTicketLogs()
set name = "Mentor Ticket Messages"
set category = "Preferences.Toggle"
if(!check_rights(R_MENTOR|R_ADMIN))
return
prefs.toggles ^= PREFTOGGLE_CHAT_NO_MENTORTICKETLOGS
prefs.save_preferences(src)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_MENTORTICKETLOGS)
to_chat(usr, "You now won't get mentor ticket messages.")
else
to_chat(usr, "You now will get mentor ticket messages.")
/client/proc/toggleticketlogs()
set name = "Admin Ticket Messgaes"
set category = "Preferences.Toggle"
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= PREFTOGGLE_CHAT_NO_TICKETLOGS
prefs.save_preferences(src)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)
to_chat(usr, "You now won't get admin ticket messages.")
else
to_chat(usr, "You now will get admin ticket messages.")
/client/proc/toggledebuglogs()
set name = "Debug Log Messages"
set category = "Preferences.Toggle"
if(!check_rights(R_VIEWRUNTIMES | R_DEBUG))
return
prefs.toggles ^= PREFTOGGLE_CHAT_DEBUGLOGS
prefs.save_preferences(src)
if(prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS)
to_chat(usr, "You now will get debug log messages")
else
to_chat(usr, "You now won't get debug log messages")
/client/proc/man_up(mob/T as mob in GLOB.player_list)
set name = "\[Admin\] Man Up"
set desc = "Tells mob to man up and deal with it."

View File

@@ -28,12 +28,14 @@
set category = "OOC"
set name = "Custom Event Info"
var/list/custom_event_information = list()
if(!GLOB.custom_event_msg || GLOB.custom_event_msg == "")
to_chat(src, "There currently is no known custom event taking place.")
to_chat(src, "Keep in mind: it is possible that an admin has not properly set this.")
custom_event_information += "There currently is no known custom event taking place."
custom_event_information += "Keep in mind: it is possible that an admin has not properly set this."
to_chat(src, chat_box_regular(custom_event_information.Join("<br>")))
return
to_chat(src, "<h1 class='alert'>Custom Event</h1>")
to_chat(src, "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>")
to_chat(src, "<span class='alert'>[html_encode(GLOB.custom_event_msg)]</span>")
to_chat(src, "<br>")
custom_event_information += "<h1 class='alert'>Custom Event</h1>"
custom_event_information += "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>"
custom_event_information += "<span class='alert'>[html_encode(GLOB.custom_event_msg)]</span>"
to_chat(src, chat_box_regular(custom_event_information.Join("<br>")))

View File

@@ -117,7 +117,6 @@
action_icon_state = "demonic_grasp"
panel = "Vampire"
school = "vampire"
action_background_icon_state = "bg_vampire"
sound = null
@@ -259,6 +258,7 @@
user.apply_status_effect(STATUS_EFFECT_VAMPIRE_GLADIATOR)
spell_active = TRUE
timer = addtimer(CALLBACK(src, PROC_REF(dispel), user, TRUE), 30 SECONDS, TIMER_STOPPABLE)
INVOKE_ASYNC(src, PROC_REF(arena_trap), get_turf(target)) //Gets another arena trap queued up for when this one runs out.
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(dispel))
arena_checks(get_turf(target), user)
@@ -266,7 +266,6 @@
if(!spell_active || QDELETED(src))
return
INVOKE_ASYNC(src, PROC_REF(fighters_check), user) //Checks to see if our fighters died.
INVOKE_ASYNC(src, PROC_REF(arena_trap), target_turf) //Gets another arena trap queued up for when this one runs out.
addtimer(CALLBACK(src, PROC_REF(arena_checks), target_turf, user), 5 SECONDS)
/datum/spell/vampire/arena/proc/arena_trap(turf/target_turf)

View File

@@ -250,7 +250,6 @@
gain_desc = "You have gained the ability to shift into a pool of blood, allowing you to evade pursuers with great mobility."
jaunt_duration = 3 SECONDS
clothes_req = FALSE
panel = "Vampire"
school = "vampire"
action_background_icon_state = "bg_vampire"
action_icon_state = "blood_pool"

View File

@@ -13,7 +13,6 @@
return TRUE
/datum/spell/vampire
panel = "Vampire"
school = "vampire"
action_background_icon_state = "bg_vampire"
human_req = TRUE

View File

@@ -18,8 +18,12 @@
/obj/item/guardiancreator = 1, // jackpot.
/obj/item/spellbook/oneuse/knock = 1, // tresspassing charges incoming
/obj/item/gun/magic/wand/resurrection = 1, // medbay's best friend
/obj/item/tarot_generator = 1, // A little bit of everything, all of the time.
/obj/item/spellbook/oneuse/charge = 20, // and now for less useful stuff to dilute the good loot chances
/obj/item/spellbook/oneuse/summonitem = 20,
/obj/item/spellbook/oneuse/forcewall = 10,
/obj/item/book/granter/spell/summon_cheese = 20 // hungry wizard stuff
/obj/item/tarot_card_pack = 10,
/obj/item/tarot_card_pack/jumbo = 6,
/obj/item/tarot_card_pack/mega = 4,
/obj/item/book/granter/spell/summon_cheese = 15 // hungry wizard stuff
)

View File

@@ -1265,6 +1265,10 @@
init_keybindings(keybindings_overrides)
save_preferences(user) //Ideally we want to save people's keybinds when they enter them
if("preference_toggles")
if(href_list["toggle"])
var/datum/preference_toggle/toggle = locateUID(href_list["toggle"])
toggle.set_toggles(user.client)
ShowChoices(user)
return 1
return TRUE

View File

@@ -167,6 +167,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "<a href='byond://?_src_=prefs;preference=tab;tab=[TAB_ANTAG]' [current_tab == TAB_ANTAG ? "class='linkOn'" : ""]>Antagonists</a>"
dat += "<a href='byond://?_src_=prefs;preference=tab;tab=[TAB_GEAR]' [current_tab == TAB_GEAR ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='byond://?_src_=prefs;preference=tab;tab=[TAB_KEYS]' [current_tab == TAB_KEYS ? "class='linkOn'" : ""]>Key Bindings</a>"
dat += "<a href='byond://?_src_=prefs;preference=tab;tab=[TAB_TOGGLES]' [current_tab == TAB_TOGGLES ? "class='linkOn'" : ""]>General Preferences</a>"
dat += "</center>"
dat += "<hr>"
@@ -476,6 +477,12 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
else
var/is_special = (i in src.be_special)
dat += "<b>Be [capitalize(i)]:</b><a class=[is_special ? "green" : "red"] href='byond://?_src_=prefs;preference=be_special;role=[i]'><b>[(is_special) ? "Yes" : "No"]</b></a><br>"
dat += "<h2>Total Playtime:</h2>"
if(!GLOB.configuration.jobs.enable_exp_tracking)
dat += "<span class='warning'>Playtime tracking is not enabled.</span>"
else
dat += "<b>Your [EXP_TYPE_CREW] playtime is [user.client.get_exp_type(EXP_TYPE_CREW)]</b><br>"
dat += "</td></tr></table>"
if(TAB_GEAR)
@@ -587,6 +594,42 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "</table>"
if(TAB_TOGGLES)
dat += "<div align='center'><b>Preference Toggles:&nbsp;</b>"
dat += "<table align='center' width='100%'>"
// Lookup lists to make our life easier
var/static/list/pref_toggles_by_category
if(!pref_toggles_by_category)
pref_toggles_by_category = list()
for(var/datum/preference_toggle/toggle as anything in GLOB.preference_toggles)
pref_toggles_by_category["[toggle.preftoggle_category]"] += list(toggle)
for(var/category in GLOB.preference_toggle_groups)
dat += "<tr><td colspan=4><hr></td></tr>"
dat += "<tr><td colspan=3><h2>[category]</h2></td></tr>"
for(var/datum/preference_toggle/toggle as anything in pref_toggles_by_category["[GLOB.preference_toggle_groups[category]]"])
dat += "<tr>"
dat += "<td style='width: 25%'>[toggle.name]</td>"
dat += "<td style='width: 45%'>[toggle.description]</td>"
if(toggle.preftoggle_category == PREFTOGGLE_CATEGORY_ADMIN)
if(!check_rights(toggle.rights_required, 0, (user)))
dat += "<td style='width: 20%'><b>Admin Restricted.</b></td>"
dat += "</tr>"
continue
switch(toggle.preftoggle_toggle)
if(PREFTOGGLE_SPECIAL)
dat += "<td style='width: 20%'><a href='byond://?_src_=prefs;preference=preference_toggles;toggle=[toggle.UID()];'>Adjust</a></td>"
if(PREFTOGGLE_TOGGLE1)
dat += "<td style='width: 20%'><a href='byond://?_src_=prefs;preference=preference_toggles;toggle=[toggle.UID()];'>[(toggles & toggle.preftoggle_bitflag) ? "<span class='good'>Enabled</span>" : "<span class='bad'>Disabled</span>"]</a></td>"
if(PREFTOGGLE_TOGGLE2)
dat += "<td style='width: 20%'><a href='byond://?_src_=prefs;preference=preference_toggles;toggle=[toggle.UID()];'>[(toggles2 & toggle.preftoggle_bitflag) ? "<span class='good'>Enabled</span>" : "<span class='bad'>Disabled</span>"]</a></td>"
if(PREFTOGGLE_SOUND)
dat += "<td style='width: 20%'><a href='byond://?_src_=prefs;preference=preference_toggles;toggle=[toggle.UID()];'>[(sound & toggle.preftoggle_bitflag) ? "<span class='good'>Enabled</span>" : "<span class='bad'>Disabled</span>"]</a></td>"
dat += "</tr>"
dat += "<tr><td colspan=4><br></td></tr>"
dat += "<hr><center>"
if(!IsGuestKey(user.key))

View File

@@ -1,361 +1,528 @@
//toggles
/client/verb/toggle_ghost_ears()
set name = "GhostEars"
set category = "Preferences.Show/Hide"
set desc = "Toggle Between seeing all mob speech, and only speech of nearby mobs"
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTEARS
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
prefs.save_preferences(src)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle GhostEars") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_sight()
set name = "GhostSight"
set category = "Preferences.Show/Hide"
set desc = "Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTSIGHT
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
prefs.save_preferences(src)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle GhostSight") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_radio()
set name = "GhostRadio"
set category = "Preferences.Show/Hide"
set desc = "Toggle between hearing all radio chatter, or only from nearby speakers"
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].")
prefs.save_preferences(src)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle GhostRadio")
/client/proc/toggle_hear_radio()
set name = "RadioChatter"
set category = "Preferences.Show/Hide"
set desc = "Toggle seeing radiochatter from radios and speakers"
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= PREFTOGGLE_CHAT_RADIO
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles & PREFTOGGLE_CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle RadioChatter") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ai_voice_annoucements()
set name = "AI Voice Announcements"
set category = "Preferences.Hear/Silence"
set desc = "Toggle hearing AI annoucements in voice form or in text form"
prefs.sound ^= SOUND_AI_VOICE
prefs.save_preferences(src)
to_chat(usr, "[(prefs.sound & SOUND_AI_VOICE) ? "You will now hear AI announcements." : "AI annoucements will now be converted to text."] ")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle AI Voice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleadminhelpsound()
set name = "Admin Bwoinks"
set category = "Preferences.Hear/Silence"
set desc = "Toggle hearing a notification when admin PMs are received"
if(!check_rights(R_ADMIN))
return
prefs.sound ^= SOUND_ADMINHELP
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.sound & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Admin Bwoinks") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/togglementorhelpsound()
set name = "Mentorhelp Bwoinks"
set category = "Preferences.Hear/Silence"
set desc = "Toggle hearing a notification when mentorhelps are received"
if(!check_rights(R_ADMIN|R_MENTOR))
return
prefs.sound ^= SOUND_MENTORHELP
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.sound & SOUND_MENTORHELP) ? "now" : "no longer"] hear a sound when mentorhelps arrive.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Mentor Bwoinks") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/deadchat() // Deadchat toggle is usable by anyone.
set name = "Deadchat"
set category = "Preferences.Show/Hide"
set desc ="Toggles seeing deadchat"
prefs.toggles ^= PREFTOGGLE_CHAT_DEAD
prefs.save_preferences(src)
if(src.holder)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
else
to_chat(src, "As a ghost, you will [(prefs.toggles & PREFTOGGLE_CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Deadchat") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleprayers()
set name = "Prayers"
set category = "Preferences.Show/Hide"
set desc = "Toggles seeing prayers"
prefs.toggles ^= PREFTOGGLE_CHAT_PRAYER
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Prayers") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggleprayernotify()
set name = "Prayer Notification Sound"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing when prayers are made"
prefs.sound ^= SOUND_PRAYERNOTIFY
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.sound & SOUND_PRAYERNOTIFY) ? "now" : "no longer"] hear when prayers are made.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Prayer Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglescoreboard()
set name = "End Round Scoreboard"
set category = "Preferences.Show/Hide"
set desc = "Toggles displaying end of round scoreboard"
prefs.toggles ^= PREFTOGGLE_DISABLE_SCOREBOARD
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_DISABLE_SCOREBOARD) ? "no longer" : "now"] see the end of round scoreboard.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Scoreboard") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggletitlemusic()
set name = "LobbyMusic"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing the GameLobby music"
prefs.sound ^= SOUND_LOBBY
prefs.save_preferences(src)
if(prefs.sound & SOUND_LOBBY)
to_chat(src, "You will now hear music in the game lobby.")
if(isnewplayer(usr))
usr.client.playtitlemusic()
else
to_chat(src, "You will no longer hear music in the game lobby.")
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Lobby Music") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglemidis()
set name = "Midis"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing sounds uploaded by admins"
prefs.sound ^= SOUND_MIDI
prefs.save_preferences(src)
if(prefs.sound & SOUND_MIDI)
to_chat(src, "You will now hear any sounds uploaded by admins.")
else
usr.stop_sound_channel(CHANNEL_ADMIN)
to_chat(src, "You will no longer hear sounds uploaded by admins; any currently playing midis have been disabled.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle MIDIs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/listen_ooc()
set name = "OOC (Out of Character)"
set category = "Preferences.Show/Hide"
set desc = "Toggles seeing OutOfCharacter chat"
prefs.toggles ^= PREFTOGGLE_CHAT_OOC
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/listen_looc()
set name = "LOOC (Local Out of Character)"
set category = "Preferences.Show/Hide"
set desc = "Toggles seeing Local OutOfCharacter chat"
prefs.toggles ^= PREFTOGGLE_CHAT_LOOC
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle LOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful
set name = "Ambience"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing ambient sound effects"
prefs.sound ^= SOUND_AMBIENCE
prefs.save_preferences(src)
if(prefs.sound & SOUND_AMBIENCE)
to_chat(src, "You will now hear ambient sounds.")
else
to_chat(src, "You will no longer hear ambient sounds.")
usr.stop_sound_channel(CHANNEL_AMBIENCE)
update_ambience_pref()
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Ambience") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/Toggle_Parallax_Dark() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful
set name = "Parallax in darkness"
set category = "Preferences.Show/Hide"
set desc = "If enabled, drawing parallax if you see in dark instead of black tiles."
prefs.toggles2 ^= PREFTOGGLE_2_PARALLAX_IN_DARKNESS
prefs.save_preferences(src)
if(prefs.toggles2 & PREFTOGGLE_2_PARALLAX_IN_DARKNESS)
to_chat(src, "You will now see parallax in dark with nightvisions.")
else
to_chat(src, "You will no longer see parallax in dark with nightvisions.")
usr.hud_used?.update_parallax_pref()
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Parallax Darkness") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/Toggle_Buzz() //No more headaches because headphones bump up shipambience.ogg to insanity levels.
set name = "White Noise"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing ambient white noise"
prefs.sound ^= SOUND_BUZZ
prefs.save_preferences(src)
if(prefs.sound & SOUND_BUZZ)
to_chat(src, "You will now hear ambient white noise.")
else
to_chat(src, "You will no longer hear ambient white noise.")
usr.stop_sound_channel(CHANNEL_BUZZ)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Whitenoise") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/Toggle_Heartbeat() //to toggle off heartbeat sounds, in case they get too annoying
set name = "Heartbeat"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing heart beating sound effects"
prefs.sound ^= SOUND_HEARTBEAT
prefs.save_preferences(src)
if(prefs.sound & SOUND_HEARTBEAT)
to_chat(src, "You will now hear heartbeat sounds.")
else
to_chat(src, "You will no longer hear heartbeat sounds.")
usr.stop_sound_channel(CHANNEL_HEARTBEAT)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Hearbeat") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
// This needs a toggle because you people are awful and spammed terrible music
/client/verb/toggle_instruments()
set name = "Instruments"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing musical instruments like the violin and piano"
prefs.sound ^= SOUND_INSTRUMENTS
prefs.save_preferences(src)
if(prefs.sound & SOUND_INSTRUMENTS)
to_chat(src, "You will now hear people playing musical instruments.")
else
to_chat(src, "You will no longer hear musical instruments.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Instruments") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_input()
set name = "TGUI Input"
set category = "Preferences.Toggle"
set desc = "Switches inputs between the TGUI and the standard one"
prefs.toggles2 ^= PREFTOGGLE_2_DISABLE_TGUI_INPUT
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_DISABLE_TGUI_INPUT) ? "no longer" : "now"] use TGUI Inputs.")
/client/verb/Toggle_disco() //to toggle off the disco machine locally, in case it gets too annoying
set name = "Dance Machine"
set category = "Preferences.Hear/Silence"
set desc = "Toggles hearing and dancing to the radiant dance machine"
prefs.sound ^= SOUND_DISCO
prefs.save_preferences(src)
if(prefs.sound & SOUND_DISCO)
to_chat(src, "You will now hear and dance to the radiant dance machine.")
else
to_chat(src, "You will no longer hear or dance to the radiant dance machine.")
usr.stop_sound_channel(CHANNEL_JUKEBOX)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Dance Machine") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/setup_character()
set name = "Game Preferences"
set category = "Preferences"
set desc = "Allows you to access the Setup Character screen. Changes to your character won't take effect until next round, but other changes will."
set category = "Special Verbs"
prefs.current_tab = 1
prefs.ShowChoices(usr)
/client/verb/toggle_ghost_pda()
set name = "GhostPDA"
set category = "Preferences.Show/Hide"
set desc = "Toggle seeing PDA messages as an observer."
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTPDA
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTPDA) ? "see all PDA messages" : "no longer see PDA messages"].")
prefs.save_preferences(src)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Ghost PDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
// Preference toggles
/datum/preference_toggle
/// Name of the preference toggle. Don't set this if you don't want it to appear in game
var/name
/// Bitflag this datum will set to
var/preftoggle_bitflag
/// Category of the toggle
var/preftoggle_category
/// What toggles to set this to?
var/preftoggle_toggle
/// Description of what the pref setting does
var/description
/// Message to display when this toggle is enabled
var/enable_message
/// Message to display when this toggle is disabled
var/disable_message
/// Message for the blackbox, legacy verbs so we can't just use the name
var/blackbox_message
/// Rights required to be able to use this pref option
var/rights_required
/datum/preference_toggle/proc/set_toggles(client/user)
var/datum/preferences/our_prefs = user.prefs
switch(preftoggle_toggle)
if(PREFTOGGLE_SPECIAL)
CRASH("[src] did not have it's set_toggles overriden even though it was a special toggle, please use the special_toggle path!")
if(PREFTOGGLE_TOGGLE1)
our_prefs.toggles ^= preftoggle_bitflag
to_chat(user, "<span class='notice'>[(our_prefs.toggles & preftoggle_bitflag) ? enable_message : disable_message]</span>")
if(PREFTOGGLE_TOGGLE2)
our_prefs.toggles2 ^= preftoggle_bitflag
to_chat(user, "<span class='notice'>[(our_prefs.toggles2 & preftoggle_bitflag) ? enable_message : disable_message]</span>")
if(PREFTOGGLE_SOUND)
our_prefs.sound ^= preftoggle_bitflag
to_chat(user, "<span class='notice'>[(our_prefs.sound & preftoggle_bitflag) ? enable_message : disable_message]</span>")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, blackbox_message)
our_prefs.save_preferences(user)
/datum/preference_toggle/toggle_ghost_ears
name = "Toggle Hearing All Speech as a Ghost"
description = "Toggle Between seeing all mob speech, and only speech of nearby mobs"
preftoggle_bitflag = PREFTOGGLE_CHAT_GHOSTEARS
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GHOST
enable_message = "As a ghost, you will now only see speech from nearby mobs."
disable_message = "As a ghost, you will now see all speech in the world."
blackbox_message = "Toggle GhostEars"
/datum/preference_toggle/toggle_ghost_sight
name = "Toggle Ghost Emote Viewing"
description = "Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
preftoggle_bitflag = PREFTOGGLE_CHAT_GHOSTSIGHT
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GHOST
enable_message = "As a ghost, you will now only see speech from nearby mobs."
disable_message = "As a ghost, you will now see all emotes in the world."
blackbox_message = "Toggle GhostSight"
/datum/preference_toggle/toggle_ghost_radio
name = "Toggle Ghost Radio"
description = "Toggle between hearing all radio chatter, or only from nearby speakers"
preftoggle_bitflag = PREFTOGGLE_CHAT_GHOSTRADIO
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GHOST
enable_message = "As a ghost, you will now only hear from nearby speakers."
disable_message = "As a ghost, you will now hear all radio chat in the world."
blackbox_message = "Toggle GhostRadio"
/datum/preference_toggle/toggle_admin_radio
name = "Admin Radio"
description = "Toggle seeing radiochatter from radios and speakers"
preftoggle_bitflag = PREFTOGGLE_CHAT_RADIO
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
enable_message = "You will no longer see radio chatter from radios or speakers."
disable_message = "You will now see radio chatter from radios or speakers."
blackbox_message = "Toggle RadioChatter"
/datum/preference_toggle/toggle_ai_voice_annoucements
name = "AI Voice Announcements"
description = "Toggle hearing AI annoucements in voice form or in text form"
preftoggle_bitflag = SOUND_AI_VOICE
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear AI announcements."
disable_message = "You will now hear AI announcements."
blackbox_message = "Toggle AI Voice"
/datum/preference_toggle/toggle_admin_pm_sound
name = "Admin PM sound"
description = "Toggle hearing a notification when admin PMs are received"
preftoggle_bitflag = SOUND_ADMINHELP
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
enable_message = "You will now hear a sound when adminhelp is sent."
disable_message = "You will no longer hear a sound when adminhelp is sent."
blackbox_message = "Toggle Admin Bwoinks"
/datum/preference_toggle/toggle_mentor_pm_sound
name = "Mentor PM sound"
description = "Toggle hearing a notification when mentor PMs are received"
preftoggle_bitflag = SOUND_MENTORHELP
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_MENTOR
enable_message = "You will now hear a sound when mentorhelp is sent."
disable_message = "You will no longer hear a sound when mentorhelp is sent."
blackbox_message = "Toggle Mentor Bwoinks"
/datum/preference_toggle/toggle_deadchat_visibility
name = "Toggle Deadchat visibility"
description = "Toggles Dchat's visibility"
preftoggle_bitflag = PREFTOGGLE_CHAT_DEAD
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see deadchat."
disable_message = "You will no longer see deadchat."
blackbox_message = "Toggle Deadchat"
/datum/preference_toggle/end_of_round_scoreboard
name = "Toggle the End of Round Scoreboard"
description = "Prevents you from seeing the end of round scoreboard"
preftoggle_bitflag = PREFTOGGLE_DISABLE_SCOREBOARD
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see the end of round scoreboard."
disable_message = "You will no longer see see the end of round scoreboard."
blackbox_message = "Toggle Scoreboard"
/datum/preference_toggle/title_music
name = "Toggle Lobby Music"
description = "Toggles hearing the GameLobby music"
preftoggle_bitflag = SOUND_LOBBY
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear music in the game lobby."
disable_message = "You will no longer hear music in the game lobby."
blackbox_message = "Toggle Lobby Music"
/datum/preference_toggle/title_music/set_toggles(client/user)
. = ..()
if(user.prefs.sound & SOUND_LOBBY)
if(isnewplayer(usr))
user.playtitlemusic()
else
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
/datum/preference_toggle/toggle_admin_midis
name = "Toggle Admin Midis"
description = "Toggles hearing sounds uploaded by admins"
preftoggle_bitflag = SOUND_MIDI
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear any sounds uploaded by admins."
disable_message = "You will no longer hear sounds uploaded by admins; any currently playing midis have been disabled."
blackbox_message = "Toggle MIDIs"
/datum/preference_toggle/toggle_admin_midis/set_toggles(client/user)
. = ..()
if(user.prefs.sound & ~SOUND_LOBBY)
usr.stop_sound_channel(CHANNEL_ADMIN)
/datum/preference_toggle/toggle_ooc
name = "Toggle OOC chat"
description = "Toggles seeing OutOfCharacter chat"
preftoggle_bitflag = PREFTOGGLE_CHAT_OOC
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see the OOC channel."
disable_message = "You will no longer see the OOC channel."
blackbox_message = "Toggle OOC"
/datum/preference_toggle/toggle_looc
name = "Toggle LOOC chat"
description = "Toggles seeing Local OutOfCharacter chat"
preftoggle_bitflag = PREFTOGGLE_CHAT_LOOC
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see the LOOC channel."
disable_message = "You will no longer see the LOOC channel."
blackbox_message = "Toggle LOOC"
/datum/preference_toggle/toggle_ambience
name = "Toggle Ambient sounds"
description = "Toggles hearing ambient sound effects"
preftoggle_bitflag = SOUND_AMBIENCE
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You now hear ambient sounds."
disable_message = "Ambience is now silenced."
blackbox_message = "Toggle Ambience"
/datum/preference_toggle/toggle_ambience/set_toggles(client/user)
. = ..()
if(user.prefs.sound & ~SOUND_AMBIENCE)
usr.stop_sound_channel(CHANNEL_AMBIENCE)
user.update_ambience_pref()
/datum/preference_toggle/toggle_parallax_in_darkness
name = "Toggle Parallax in darkness"
description = "Toggles seeing space tiles instead of blank tiles"
preftoggle_bitflag = PREFTOGGLE_2_PARALLAX_IN_DARKNESS
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see parallax in dark with nightvision."
disable_message = "You will no longer see parallax in dark with nightvision."
blackbox_message = "Toggle Parallax Darkness"
/datum/preference_toggle/toggle_parallax_in_darkness/set_toggles(client/user)
. = ..()
usr.hud_used?.update_parallax_pref()
/datum/preference_toggle/toggle_white_noise
name = "Toggle White Noise"
description = "Toggles hearing White Noise"
preftoggle_bitflag = SOUND_BUZZ
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear ambient white noise."
disable_message = "You will no longer hear ambient white noise."
blackbox_message = "Toggle Whitenoise"
/datum/preference_toggle/toggle_white_noise/set_toggles(client/user)
. = ..()
if(user.prefs.sound & ~SOUND_BUZZ)
usr.stop_sound_channel(CHANNEL_BUZZ)
/datum/preference_toggle/toggle_heartbeat_noise
name = "Toggle Heartbeat noise"
description = "Toggles hearing heartbeat sounds"
preftoggle_bitflag = SOUND_HEARTBEAT
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear heartbeat sounds."
disable_message = "You will no longer hear heartbeat sounds."
blackbox_message = "Toggle Hearbeat"
/datum/preference_toggle/toggle_heartbeat_noise/set_toggles(client/user)
. = ..()
if(user.prefs.sound & ~SOUND_HEARTBEAT)
usr.stop_sound_channel(CHANNEL_HEARTBEAT)
/datum/preference_toggle/toggle_instruments
name = "Toggle Instruments"
description = "Toggles hearing musical instruments like the violin and piano"
preftoggle_bitflag = SOUND_INSTRUMENTS
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear people playing musical instruments."
disable_message = "You will no longer hear musical instruments."
blackbox_message = "Toggle Instruments"
/datum/preference_toggle/toggle_disco
name = "Toggle Disco Machine Music"
description = "Toggles hearing musical instruments like the violin and piano"
preftoggle_bitflag = SOUND_DISCO
preftoggle_toggle = PREFTOGGLE_SOUND
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now hear and dance to the radiant dance machine."
disable_message = "You will no longer hear or dance to the radiant dance machine."
blackbox_message = "Toggle Dance Machine"
/datum/preference_toggle/toggle_disco/set_toggles(client/user)
. = ..()
if(user.prefs.sound & ~SOUND_DISCO)
usr.stop_sound_channel(CHANNEL_JUKEBOX)
/datum/preference_toggle/toggle_ghost_pda
name = "Toggle Ghost PDA messages"
description = "Toggle seeing PDA messages as an observer"
preftoggle_bitflag = PREFTOGGLE_CHAT_GHOSTPDA
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_GHOST
enable_message = "As a ghost, you will now see all PDA messages."
disable_message = "As a ghost, you will no longer see PDA messages."
blackbox_message = "Toggle Ghost PDA"
/client/verb/silence_current_midi()
set name = "Silence Current Midi"
set category = "Preferences"
set category = "Special Verbs"
set desc = "Silence the current admin midi playing"
usr.stop_sound_channel(CHANNEL_ADMIN)
to_chat(src, "The current admin midi has been silenced")
/datum/preference_toggle/toggle_runechat
name = "Toggle Runechat"
description = "Toggle seeing Runechat messages"
preftoggle_bitflag = PREFTOGGLE_2_RUNECHAT
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now see runechat."
disable_message = "You will no longer see runechat."
blackbox_message = "Toggle Runechat"
/client/verb/toggle_runechat()
set name = "Runechat"
set category = "Preferences.Toggle"
set desc = "Toggle runechat messages"
prefs.toggles2 ^= PREFTOGGLE_2_RUNECHAT
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_RUNECHAT) ? "now see" : "no longer see"] floating chat messages.")
/datum/preference_toggle/toggle_runechat
name = "Toggle Ghost Death Notifications"
description = "Toggle a notification when a player dies"
preftoggle_bitflag = PREFTOGGLE_2_DEATHMESSAGE
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GHOST
enable_message = "You will now see a notification in deadchat when a player dies."
disable_message = "You will no longer see a notification in deadchat when a player dies."
blackbox_message = "Toggle Death Notifications"
/client/verb/toggle_death_messages()
set name = "Death Notifications"
set category = "Preferences.Toggle"
set desc = "Toggle player death notifications"
prefs.toggles2 ^= PREFTOGGLE_2_DEATHMESSAGE
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_DEATHMESSAGE) ? "now" : "no longer"] see a notification in deadchat when a player dies.")
/datum/preference_toggle/toggle_reverb
name = "Toggle Reverb"
description = "Toggles Reverb on specific sounds"
preftoggle_bitflag = PREFTOGGLE_2_REVERB_DISABLE
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now get reverb on some in game sounds."
disable_message = "You will no longer get reverb on some in game sounds."
blackbox_message = "Toggle reverb"
/client/verb/toggle_reverb()
set name = "Reverb"
set category = "Preferences.Toggle"
set desc = "Toggle ingame reverb effects"
prefs.toggles2 ^= PREFTOGGLE_2_REVERB_DISABLE
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_REVERB_DISABLE) ? "no longer" : "now"] get reverb on ingame sounds.")
/datum/preference_toggle/toggle_white_runechat
name = "Toggle Runechat Colour Forcing"
description = "Forces your runechat color to white"
preftoggle_bitflag = PREFTOGGLE_2_FORCE_WHITE_RUNECHAT
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "Your runechat messages are forced to be white."
disable_message = "Your runechat messages are no longer forced to be white."
blackbox_message = "Toggle runechat color"
/client/verb/toggle_forced_white_runechat()
set name = "Runechat Colour Forcing"
set category = "Preferences.Toggle"
set desc = "Toggles forcing your runechat colour to white"
prefs.toggles2 ^= PREFTOGGLE_2_FORCE_WHITE_RUNECHAT
prefs.save_preferences(src)
to_chat(src, "Your runechats will [(prefs.toggles2 & PREFTOGGLE_2_FORCE_WHITE_RUNECHAT) ? "now" : "no longer"] be forced to be white.")
/datum/preference_toggle/toggle_simple_stat_panel
name = "Toggle item outlines"
description = "Toggles seeing item outlines on hover"
preftoggle_bitflag = PREFTOGGLE_2_SEE_ITEM_OUTLINES
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_LIVING
enable_message = "You no longer see item outlines when hovering over an item with your mouse."
disable_message = "You now see item outlines when hovering over an item with your mouse."
blackbox_message = "Toggle item outlines"
/client/verb/toggle_item_outlines()
set name = "Item Outlines"
set category = "Preferences.Toggle"
set desc = "Toggles seeing item outlines on hover."
prefs.toggles2 ^= PREFTOGGLE_2_SEE_ITEM_OUTLINES
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles2 & PREFTOGGLE_2_SEE_ITEM_OUTLINES) ? "now" : "no longer"] see item outlines on hover.")
/datum/preference_toggle/toggle_item_tooltips
name = "Toggle item tooltips"
description = "Toggles textboxes with the item descriptions after hovering on them in your inventory"
preftoggle_bitflag = PREFTOGGLE_2_HIDE_ITEM_TOOLTIPS
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_LIVING
enable_message = "You no longer see item tooltips."
disable_message = "You now see item tooltips."
blackbox_message = "Toggle item tooltips"
/client/verb/toggle_item_tooltips()
set name = "Hover-over Item Tooltips"
set category = "Preferences.Toggle"
set desc = "Toggles textboxes with the item descriptions after hovering on them in your inventory."
prefs.toggles2 ^= PREFTOGGLE_2_HIDE_ITEM_TOOLTIPS
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_HIDE_ITEM_TOOLTIPS) ? "no longer" : "now"] see item tooltips when you hover over items on your HUD.")
/datum/preference_toggle/toggle_anonmode
name = "Toggle Anonymous Mode"
description = "Toggles showing your key in various parts of the game (deadchat, end round, etc)"
preftoggle_bitflag = PREFTOGGLE_2_ANON
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "Your key will no longer be shown in certain events (end round reports, deadchat, etc)."
disable_message = "Your key will now will be shown in certain events (end round reports, deadchat, etc)."
blackbox_message = "Toggle Anon mode"
/mob/verb/toggle_anonmode()
set name = "Anonymous Mode"
set category = "Preferences.Toggle"
set desc = "Toggles showing your key in various parts of the game (deadchat, end round, etc)."
client.prefs.toggles2 ^= PREFTOGGLE_2_ANON
to_chat(src, "Your key will [(client.prefs.toggles2 & PREFTOGGLE_2_ANON) ? "no longer" : "now"] be shown in certain events (end round reports, deadchat, etc).</span>")
client.prefs.save_preferences(src)
/datum/preference_toggle/toggle_disco_dance
name = "Toggle Disco Machine Dancing"
description = "Toggles automatic dancing from the radiant dance machine"
preftoggle_bitflag = PREFTOGGLE_2_DANCE_DISCO
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_LIVING
enable_message = "You will now dance to the radiant dance machine."
disable_message = "You will no longer dance to the radiant dance machine."
blackbox_message = "Toggle disco machine dancing"
/client/verb/toggle_dance()
set name = "Disco Machine Dancing"
set category = "Preferences.Toggle"
set desc = "Toggles automatic dancing from the radiant dance machine"
prefs.toggles2 ^= PREFTOGGLE_2_DANCE_DISCO
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles2 & PREFTOGGLE_2_DANCE_DISCO) ? "now" : "no longer"] dance to the radiant dance machine.")
/datum/preference_toggle/toggle_typing_indicator
name = "Toggle Typing Indicator"
description = "Hides the typing indicator"
preftoggle_bitflag = PREFTOGGLE_SHOW_TYPING
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_LIVING
enable_message = "You will no longer display a typing indicator."
disable_message = "You will now display a typing indicator."
blackbox_message = "Toggle Typing Indicator (Speech)"
/client/verb/manage_adminsound_mutes()
set name = "Manage Admin Sound Mutes"
set category = "Preferences"
set desc = "Manage admins that you wont hear played audio from"
/datum/preference_toggle/toggle_typing_indicator/set_toggles(client/user)
. = ..()
if(user.prefs.toggles & PREFTOGGLE_SHOW_TYPING)
if(istype(usr))
usr.set_typing_indicator(FALSE)
usr.set_thinking_indicator(FALSE)
if(!length(prefs.admin_sound_ckey_ignore))
/datum/preference_toggle/toggle_tgui_input_lists
name = "Toggle TGUI Input"
description = "Switches input lists between the TGUI and the standard one"
preftoggle_bitflag = PREFTOGGLE_2_DISABLE_TGUI_INPUT
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
enable_message = "You will now use TGUI Input."
disable_message = "You will no longer use TGUI Input."
blackbox_message = "Toggle TGUI Input"
/datum/preference_toggle/toggle_admin_logs
name = "Toggle Admin Log Messages"
description = "Disables admin log messages"
preftoggle_bitflag = PREFTOGGLE_CHAT_NO_ADMINLOGS
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
enable_message = "Admin logs disabled."
disable_message = "Admin logs re-enabled."
blackbox_message = "Admin logs toggled"
/datum/preference_toggle/toggle_mhelp_notification
name = "Toggle Mentor Ticket Messages"
description = "Disables mentor ticket notifications"
preftoggle_bitflag = PREFTOGGLE_CHAT_NO_MENTORTICKETLOGS
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_MENTOR | R_ADMIN
enable_message = "You now won't get mentor ticket messages."
disable_message = "You now will get mentor ticket messages."
blackbox_message = "Mentor ticket notification toggled"
/datum/preference_toggle/toggle_ahelp_notification
name = "Toggle Admin Ticket Messages"
description = "Disables admin ticket notifications"
preftoggle_bitflag = PREFTOGGLE_CHAT_NO_TICKETLOGS
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
enable_message = "You now won't get admin ticket messages."
disable_message = "You now will get admin ticket messages."
blackbox_message = "Admin ticket notification toggled"
/datum/preference_toggle/toggle_debug_logs
name = "Toggle Debug Log Messages"
description = "Disables debug notifications (Runtimes, ghost role notifications, weird checks that weren't removed)"
preftoggle_bitflag = PREFTOGGLE_CHAT_DEBUGLOGS
preftoggle_toggle = PREFTOGGLE_TOGGLE1
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_VIEWRUNTIMES | R_DEBUG
enable_message = "You now won't get debug logs."
disable_message = "You now will get debug logs."
blackbox_message = "Debug logs toggled"
/datum/preference_toggle/toggle_mctabs
name = "Toggle MC tab"
description = "Toggles MC tab visibility"
preftoggle_bitflag = PREFTOGGLE_2_MC_TAB
preftoggle_toggle = PREFTOGGLE_TOGGLE2
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_VIEWRUNTIMES | R_DEBUG
enable_message = "You'll now see subsystem information in the verb panel."
disable_message = "You'll no longer see subsystem information in the verb panel."
blackbox_message = "MC tabs toggled"
/datum/preference_toggle/special_toggle
preftoggle_toggle = PREFTOGGLE_SPECIAL
/datum/preference_toggle/special_toggle/set_toggles(client/user)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, blackbox_message)
user.prefs.save_preferences(user)
/datum/preference_toggle/special_toggle/toggle_adminsound_mutes
name = "Manage Admin Sound Mutes"
description = "Manage admins that you wont hear played audio from"
preftoggle_category = PREFTOGGLE_CATEGORY_GENERAL
blackbox_message = "MC tabs toggled"
/datum/preference_toggle/special_toggle/toggle_adminsound_mutes/set_toggles(client/user)
if(!length(user.prefs.admin_sound_ckey_ignore))
to_chat(usr, "You have no admins with muted sounds.")
return
var/choice = input(usr, "Select an admin to unmute sounds from.", "Pick an admin") as null|anything in prefs.admin_sound_ckey_ignore
var/choice = input(usr, "Select an admin to unmute sounds from.", "Pick an admin") as null|anything in user.prefs.admin_sound_ckey_ignore
if(!choice)
return
prefs.admin_sound_ckey_ignore -= choice
user.prefs.admin_sound_ckey_ignore -= choice
to_chat(usr, "You will now hear sounds from <code>[choice]</code> again.")
prefs.save_preferences(src)
return ..()
/client/proc/toggle_mctabs()
set name = "MC Tab"
set category = "Preferences.Show/Hide"
set desc = "Shows or hides the MC tab."
prefs.toggles2 ^= PREFTOGGLE_2_MC_TAB
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_MC_TAB) ? "now" : "no longer"] see the MC tab on the top right.")
/datum/preference_toggle/special_toggle/set_ooc_color
name = "Set Your OOC Color"
description = "Pick a custom OOC color"
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
blackbox_message = "Set Own OOC"
/datum/preference_toggle/special_toggle/set_ooc_color/set_toggles(client/user)
var/new_ooccolor = input(usr, "Please select your OOC color.", "OOC color", user.prefs.ooccolor) as color|null
if(new_ooccolor)
user.prefs.ooccolor = new_ooccolor
to_chat(usr, "Your OOC color has been set to [new_ooccolor].")
else
user.prefs.ooccolor = initial(user.prefs.ooccolor)
to_chat(usr, "Your OOC color has been reset.")
return ..()
/datum/preference_toggle/special_toggle/set_attack_logs
name = "Change Attack Log settings"
description = "Changes what attack logs you see, ranges from all attacklogs to no attacklogs"
preftoggle_category = PREFTOGGLE_CATEGORY_ADMIN
rights_required = R_ADMIN
blackbox_message = "changed attack log settings"
/datum/preference_toggle/special_toggle/set_attack_logs/set_toggles(client/user)
var/static/list/attack_log_settings = list("All attack logs" = ATKLOG_ALL, "Almost all attack logs" = ATKLOG_ALMOSTALL, "Most attack logs" = ATKLOG_MOST, "Few attack logs" = ATKLOG_FEW, "No attack logs" = ATKLOG_NONE)
var/input = input(usr, "Please select your Attack Log settings.") as null|anything in attack_log_settings
if(!input)
return
var/attack_log_type = attack_log_settings[input]
switch(attack_log_type)
if(ATKLOG_ALL)
user.prefs.atklog = ATKLOG_ALL
to_chat(usr, "Your attack logs preference is now: show ALL attack logs")
if(ATKLOG_ALMOSTALL)
user.prefs.atklog = ATKLOG_ALMOSTALL
to_chat(usr, "Your attack logs preference is now: show ALMOST ALL attack logs (notable exceptions: NPCs attacking other NPCs, vampire bites, equipping/stripping, people pushing each other over)")
if(ATKLOG_MOST)
user.prefs.atklog = ATKLOG_MOST
to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides player v. NPC combat, and certain areas like lavaland syndie base and thunderdome)")
if(ATKLOG_FEW)
user.prefs.atklog = ATKLOG_FEW
to_chat(usr, "Your attack logs preference is now: show FEW attack logs (only the most important stuff: attacks on SSDs, use of explosives, messing with the engine, gibbing, AI wiping, forcefeeding, acid sprays, and organ extraction)")
if(ATKLOG_NONE)
user.prefs.atklog = ATKLOG_NONE
to_chat(usr, "Your attack logs preference is now: show NO attack logs")
return ..()

View File

@@ -88,7 +88,7 @@
/client/verb/volume_mixer()
set name = "Open Volume Mixer"
set category = "Preferences"
set category = null
set hidden = TRUE
var/datum/ui_module/volume_mixer/VM = new()

View File

@@ -4,9 +4,6 @@
* Also includes
*/
/* Defines */
#define CUSTOM_VIEWRANGES list(1, 2, 3, 4, 5, 6, "RESET")
/client/proc/AddViewMod(id, size)
var/datum/viewmod/V = new /datum/viewmod(id, size)
ViewMods[V.id] = V
@@ -69,22 +66,3 @@
/* Client verbs */
/proc/viewNum_to_text(view)
return "[(view * 2) + 1]x[(view * 2) + 1]"
/client/verb/set_view_range()
set name = "Set View Range"
set category = "Preferences"
var/view_range = tgui_input_list(src.mob, "Select a view range", "Set View Range", CUSTOM_VIEWRANGES, "RESET")
if(!view_range)
return
RemoveViewMod("custom")
if(view_range == "RESET")
to_chat(src, "<span class='notice'>View range reset.</span>")
return
to_chat(src, "<span class='notice'>View range set to [viewNum_to_text(view_range)]</span>")
AddViewMod("custom", view_range)
#undef CUSTOM_VIEWRANGES

View File

@@ -611,6 +611,23 @@
/obj/item/clothing/suit/proc/setup_shielding()
return
///Hierophant card shielding. Saves me time.
/obj/item/clothing/suit/proc/setup_hierophant_shielding()
var/datum/component/shielded/shield = GetComponent(/datum/component/shielded)
if(!shield)
AddComponent(/datum/component/shielded, recharge_start_delay = 0 SECONDS, shield_icon = "shield-hierophant", run_hit_callback = CALLBACK(src, PROC_REF(hierophant_shield_damaged)))
return
if(shield.shield_icon == "shield-hierophant") //If the hierophant shield has been used, recharge it. Otherwise, it's a shielded component we don't want to touch
shield.current_charges = 3
/// A proc for callback when the shield breaks, since I am stupid and want custom effects.
/obj/item/clothing/suit/proc/hierophant_shield_damaged(mob/living/wearer, attack_text, new_current_charges)
wearer.visible_message("<span class='danger'>[attack_text] is deflected in a burst of dark-purple sparks!</span>")
new /obj/effect/temp_visual/cult/sparks/hierophant(get_turf(wearer))
playsound(wearer,'sound/magic/blind.ogg', 200, TRUE, -2)
if(new_current_charges == 0)
wearer.visible_message("<span class='danger'>The runed shield around [wearer] suddenly disappears!</span>")
//Proc that opens and closes jackets.
/obj/item/clothing/suit/proc/adjustsuit(mob/user)
if(ignore_suitadjust)

View File

@@ -69,6 +69,18 @@
if(23)
new /obj/item/borg/upgrade/modkit/lifesteal(src)
new /obj/item/bedsheet/cult(src)
if(24)
switch(rand(1, 11))
if(1)
new /obj/item/blank_tarot_card(src)
if(2 to 5)
new /obj/item/tarot_card_pack(src)
if(6 to 8)
new /obj/item/tarot_card_pack/jumbo(src)
if(9, 10)
new /obj/item/tarot_card_pack/mega(src)
if(11)
new /obj/item/tarot_generator(src) // ~1/250? Seems reasonable
//KA modkit design discs
/obj/item/disk/design_disk/modkit_disk

View File

@@ -46,38 +46,12 @@
set_light(2, 3, l_color = GET_CULT_DATA(construct_glow, LIGHT_COLOR_BLOOD_MAGIC))
/mob/living/simple_animal/hostile/construct/Destroy()
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE)
remove_held_body()
return ..()
/mob/living/simple_animal/hostile/construct/death(gibbed)
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE)
if(held_body) // Null check for empty bodies
held_body.forceMove(get_turf(src))
SSticker.mode?.cult_team?.add_cult_immunity(held_body)
if(ismob(held_body)) // Check if the held_body is a mob
held_body.key = key
else if(istype(held_body, /obj/item/organ/internal/brain)) // Check if the held_body is a brain
var/obj/item/organ/internal/brain/brain = held_body
if(brain.brainmob) // Check if the brain has a brainmob
brain.brainmob.key = key // Set the key to the brainmob
brain.brainmob.mind.transfer_to(brain.brainmob) // Transfer the mind to the brainmob
held_body.cancel_camera()
// we also drop our heldbody from the /construct_held_body component, as well as our cult/wiz construct antag datums
new /obj/effect/temp_visual/cult/sparks(get_turf(src))
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
return ..()
/mob/living/simple_animal/hostile/construct/proc/add_held_body(atom/movable/body)
held_body = body
RegisterSignal(body, COMSIG_PARENT_QDELETING, PROC_REF(remove_held_body))
/mob/living/simple_animal/hostile/construct/proc/remove_held_body()
SIGNAL_HANDLER
held_body = null
/mob/living/simple_animal/hostile/construct/examine(mob/user)
. = ..()

View File

@@ -476,6 +476,9 @@ While using this makes the system rely on OnFire, it still gives options for tim
if(isliving(mover))
return FALSE
/obj/effect/temp_visual/elite_tumor_wall/gargantua
duration = 35 SECONDS // A bit longer than the spell lasts, it should be cleaned up by the spell otherwise it might not GC properly
/obj/effect/temp_visual/elite_tumor_wall/gargantua/CanPass(atom/movable/mover, border_dir)
return FALSE

View File

@@ -34,11 +34,6 @@
deathmessage = "lets out a contented sigh as their form unwinds."
var/holy = FALSE
/mob/living/simple_animal/shade/Destroy()
mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE)
return ..()
/mob/living/simple_animal/shade/attackby(obj/item/O, mob/user) //Marker -Agouri
if(istype(O, /obj/item/soulstone))
var/obj/item/soulstone/SS = O

View File

@@ -152,7 +152,6 @@
real_name = name
if(!loc)
stack_trace("Simple animal being instantiated in nullspace")
remove_verb(src, /mob/verb/observe)
if(can_hide)
var/datum/action/innate/hide/hide = new()
hide.Grant(src)

View File

@@ -769,112 +769,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
else
return "<span class='notice'>[copytext_preserve_html(msg, 1, 37)]... <a href='byond://?src=[UID()];flavor_more=1'>More...</a></span>"
// Nobody in their right mind will have this enabled on the production server, uncomment if you want this for some reason
/*
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
if(!GLOB.configuration.general.respawn_enabled)
to_chat(usr, "<span class='warning'>Respawning is disabled.</span>")
return
if(stat != DEAD || !SSticker)
to_chat(usr, "<span class='boldnotice'>You must be dead to use this!</span>")
return
log_game("[key_name(usr)] has respawned.")
to_chat(usr, "<span class='boldnotice'>Make sure to play a different character, and please roleplay correctly!</span>")
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
return
client.screen.Cut()
client.screen += client.void
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
return
var/mob/new_player/M = new /mob/new_player()
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
qdel(M)
return
M.key = key
return
*/
/mob/verb/observe()
set name = "Observe"
set category = "OOC"
var/is_admin = 0
if(client.holder && (client.holder.rights & R_ADMIN))
is_admin = 1
else if(stat != DEAD || isnewplayer(src))
to_chat(usr, "<span class='notice'>You must be observing to use this!</span>")
return
if(is_admin && stat == DEAD)
is_admin = 0
var/list/names = list()
var/list/namecounts = list()
var/list/creatures = list()
for(var/obj/O in GLOB.poi_list)
if(!O.loc)
continue
if(istype(O, /obj/item/disk/nuclear))
var/name = "Nuclear Disk"
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = O
if(istype(O, /obj/singularity))
var/name = "Singularity"
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = O
for(var/mob/M in sortAtom(GLOB.mob_list))
var/name = M.name
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = M
client.perspective = EYE_PERSPECTIVE
var/eye_name = null
var/ok = "[is_admin ? "Admin Observe" : "Observe"]"
eye_name = tgui_input_list(usr, "Please, select a player!", ok, creatures)
if(!eye_name)
return
var/mob/mob_eye = creatures[eye_name]
if(client && mob_eye)
client.eye = mob_eye
/mob/proc/is_dead()
return stat == DEAD
/mob/verb/cancel_camera()
set name = "Cancel Camera View"

View File

@@ -92,19 +92,3 @@ GLOBAL_LIST_EMPTY(thinking_indicator)
set_typing_indicator(FALSE)
if(message)
me_verb(message)
/client/verb/typing_indicator()
set name = "Typing Indicator"
set category = "Preferences.Show/Hide"
set desc = "Toggles showing a typing/thought indicator when you have TGUIsay open."
prefs.toggles ^= PREFTOGGLE_SHOW_TYPING
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_SHOW_TYPING) ? "no longer" : "now"] display a typing/thought indicator when you have TGUIsay open.")
// Clear out any existing typing indicator.
if(prefs.toggles & PREFTOGGLE_SHOW_TYPING)
if(istype(mob))
mob.set_typing_indicator(FALSE)
mob.set_thinking_indicator(FALSE)
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Typing Indicator (Speech)") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -245,6 +245,7 @@
/obj/item/ammo_casing/shotgun/ion
name = "ion shell"
desc = "An advanced 12 gauge shell that fires a spread of ion bolts."
icon_state = "ionshell"
projectile_type = /obj/item/projectile/ion/weak
pellets = 4
variance = 35

View File

@@ -93,7 +93,8 @@
if(!ishuman(target))
return
var/mob/living/carbon/human/H = target
if(H.getStaminaLoss() >= 60)
// initial range - range gives approximate tile distance from user
if(initial(range) - range <= 5 && H.getStaminaLoss() >= 60)
H.KnockDown(8 SECONDS)
/obj/item/projectile/bullet/pellet/assassination

View File

@@ -969,6 +969,17 @@
var/picked_reagent = pick(random_reagents)
return picked_reagent
/// Returns a random reagent ID, with real non blacklisted balance boosting action!
/proc/get_unrestricted_random_reagent_id()
var/static/list/random_reagents
if(!length(random_reagents))
random_reagents = list()
for(var/datum/reagent/thing as anything in subtypesof(/datum/reagent))
var/R = initial(thing.id)
random_reagents += R
var/picked_reagent = pick(random_reagents)
return picked_reagent
/datum/reagents/proc/get_reagent_from_id(id)
var/datum/reagent/result = null
for(var/A in reagent_list)

View File

@@ -55,7 +55,7 @@
equip_item(H, /obj/item/clothing/under/color/random, SLOT_HUD_JUMPSUIT)
if(!H.shoes)
equip_item(H, /obj/item/clothing/shoes/black, SLOT_HUD_SHOES)
equip_item(H, /obj/item/stack/spacecash/c100, SLOT_HUD_LEFT_STORE)
equip_item(H, /obj/item/stack/spacecash/c1000, SLOT_HUD_LEFT_STORE)
var/obj/item/card/id/syndicate/our_id = equip_item(H, /obj/item/card/id/syndicate/ghost_bar, SLOT_HUD_WEAR_ID)
our_id.assignment = assignedrole

View File

@@ -116,7 +116,11 @@
/obj/item/bedsheet/cult = 2,
/obj/item/bedsheet/wiz = 2,
/obj/item/stack/sheet/mineral/tranquillite/fifty = 3,
/obj/item/clothing/gloves/combat = 5
/obj/item/clothing/gloves/combat = 5,
/obj/item/blank_tarot_card = 5,
/obj/item/tarot_card_pack = 5,
/obj/item/tarot_card_pack/jumbo = 3,
/obj/item/tarot_card_pack/mega = 2
)
/obj/effect/spawner/lootdrop/bluespace_tap/organic

View File

@@ -292,7 +292,7 @@
/obj/item/organ/internal/heart/cybernetic/upgraded/proc/shock_heart(mob/living/carbon/human/source, intensity)
SIGNAL_HANDLER_DOES_SLEEP
SIGNAL_HANDLER // COMSIG_LIVING_MINOR_SHOCK + COMSIG_LIVING_ELECTROCUTE_ACT
if(!ishuman(owner))
return
@@ -305,10 +305,11 @@
if(emagged && !(status & ORGAN_DEAD))
if(prob(numHigh))
to_chat(owner, "<span class='warning'>Your [name] spasms violently!</span>")
owner.adjustBruteLoss(numHigh)
// invoke asyncs here because this sleeps
INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob/living/carbon/human, adjustBruteLoss), numHigh)
if(prob(numHigh))
to_chat(owner, "<span class='warning'>Your [name] shocks you painfully!</span>")
owner.adjustFireLoss(numHigh)
INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob/living/carbon/human, adjustFireLoss), numHigh)
if(prob(numMid))
to_chat(owner, "<span class='warning'>Your [name] lurches awkwardly!</span>")
owner.ForceContractDisease(new /datum/disease/critical/heart_failure(0))
@@ -318,14 +319,14 @@
heart_datum.change_beating(FALSE) // Rambunctious Crew - Stop My Fucking Heart
if(prob(numLow))
to_chat(owner, "<span class='danger'>Your [name] shuts down!</span>")
necrotize()
INVOKE_ASYNC(src, PROC_REF(necrotize))
else if(!emagged && !(status & ORGAN_DEAD))
if(prob(numMid))
to_chat(owner, "<span class='warning'>Your [name] spasms violently!</span>")
owner.adjustBruteLoss(numMid)
INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob/living/carbon/human, adjustBruteLoss), numMid)
if(prob(numMid))
to_chat(owner, "<span class='warning'>Your [name] shocks you painfully!</span>")
owner.adjustFireLoss(numMid)
INVOKE_ASYNC(owner, TYPE_PROC_REF(/mob/living/carbon/human, adjustFireLoss), numMid)
if(prob(numLow))
to_chat(owner, "<span class='warning'>Your [name] lurches awkwardly!</span>")
owner.ForceContractDisease(new /datum/disease/critical/heart_failure(0))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

After

Width:  |  Height:  |  Size: 478 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -197,6 +197,7 @@
#include "code\_globalvars\lists\mob_lists.dm"
#include "code\_globalvars\lists\names.dm"
#include "code\_globalvars\lists\objects.dm"
#include "code\_globalvars\lists\preference_toggle_lists.dm"
#include "code\_globalvars\lists\reagents_lists.dm"
#include "code\_globalvars\lists\typecache.dm"
#include "code\_onclick\adjacent.dm"
@@ -399,6 +400,7 @@
#include "code\datums\components\codeword_hearing.dm"
#include "code\datums\components\connect_mob_behalf.dm"
#include "code\datums\components\corpse_description.dm"
#include "code\datums\components\cult_held_body.dm"
#include "code\datums\components\deadchat_control.dm"
#include "code\datums\components\decal.dm"
#include "code\datums\components\defibrillator.dm"
@@ -751,6 +753,7 @@
#include "code\game\gamemodes\vampire\vampire_gamemode.dm"
#include "code\game\gamemodes\wizard\artefact.dm"
#include "code\game\gamemodes\wizard\godhand.dm"
#include "code\game\gamemodes\wizard\magic_tarot.dm"
#include "code\game\gamemodes\wizard\raginmages.dm"
#include "code\game\gamemodes\wizard\rightandwrong.dm"
#include "code\game\gamemodes\wizard\soulstone.dm"