diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index a39ebf36ba..a3fcb066d6 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -432,6 +432,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
//text files
#define BRAIN_DAMAGE_FILE "traumas.json"
#define ION_FILE "ion_laws.json"
+#define REDPILL_FILE "redpill.json"
#define PIRATE_NAMES_FILE "pirates.json"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 8d8b9f47ae..fa7758be1f 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -98,6 +98,7 @@
#define BRAIN_TRAUMA_MILD /datum/brain_trauma/mild
#define BRAIN_TRAUMA_SEVERE /datum/brain_trauma/severe
#define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special
+#define BRAIN_TRAUMA_MAGIC /datum/brain_trauma/magic
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 435a35c05e..5765f291e9 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -168,12 +168,14 @@
/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
-/datum/config_entry/flag/no_summon_guns //No
+/datum/config_entry/flag/no_summon_guns //No
/datum/config_entry/flag/no_summon_magic //Fun
/datum/config_entry/flag/no_summon_events //Allowed
+/datum/config_entry/flag/no_summon_traumas //!
+
/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes.
/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index abc46cba25..2e4e728191 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -12,7 +12,7 @@ SUBSYSTEM_DEF(events)
var/frequency_upper = 6000 //10 minutes upper bound. Basically an event will happen every 3 to 10 minutes.
var/list/holidays //List of all holidays occuring today or null if no holidays
- var/wizardmode = 0
+ var/wizardmode = FALSE
/datum/controller/subsystem/events/Initialize(time, zlevel)
for(var/type in typesof(/datum/round_event_control))
@@ -91,6 +91,7 @@ SUBSYSTEM_DEF(events)
if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0
E.max_occurrences = 0
else if(. == EVENT_READY)
+ E.random = TRUE
E.runEvent(TRUE)
//allows a client to trigger an event
diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm
index 249907a1b8..ff04ceead9 100644
--- a/code/datums/brain_damage/magic.dm
+++ b/code/datums/brain_damage/magic.dm
@@ -5,6 +5,61 @@
/datum/brain_trauma/magic
resilience = TRAUMA_RESILIENCE_LOBOTOMY
+/datum/brain_trauma/magic/lumiphobia
+ name = "Lumiphobia"
+ desc = "Patient has an inexplicable adverse reaction to light."
+ scan_desc = "light hypersensitivity"
+ gain_text = "You feel a craving for darkness."
+ lose_text = "Light no longer bothers you."
+ var/next_damage_warning = 0
+
+/datum/brain_trauma/magic/lumiphobia/on_life()
+ ..()
+ var/turf/T = owner.loc
+ if(istype(T))
+ var/light_amount = T.get_lumcount()
+ if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying
+ if(world.time > next_damage_warning)
+ to_chat(owner, "The light burns you!")
+ next_damage_warning = world.time + 100 //Avoid spamming
+ owner.take_overall_damage(0,3)
+
+/datum/brain_trauma/magic/poltergeist
+ name = "Poltergeist"
+ desc = "Patient appears to be targeted by a violent invisible entity."
+ scan_desc = "paranormal activity"
+ gain_text = "You feel a hateful presence close to you."
+ lose_text = "You feel the hateful presence fade away."
+
+/datum/brain_trauma/magic/poltergeist/on_life()
+ ..()
+ if(prob(4))
+ var/most_violent = -1 //So it can pick up items with 0 throwforce if there's nothing else
+ var/obj/item/throwing
+ for(var/obj/item/I in view(5, get_turf(owner)))
+ if(I.anchored)
+ continue
+ if(I.throwforce > most_violent)
+ most_violent = I.throwforce
+ throwing = I
+ if(throwing)
+ throwing.throw_at(owner, 8, 2)
+
+/datum/brain_trauma/magic/antimagic
+ name = "Athaumasia"
+ desc = "Patient is completely inert to magical forces."
+ scan_desc = "thaumic blank"
+ gain_text = "You realize that magic cannot be real."
+ lose_text = "You realize that magic might be real."
+
+/datum/brain_trauma/magic/antimagic/on_gain()
+ ADD_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
+ ..()
+
+/datum/brain_trauma/magic/antimagic/on_lose()
+ REMOVE_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
+ ..()
+
/datum/brain_trauma/magic/stalker
name = "Stalking Phantom"
desc = "Patient is stalked by a phantom only they can see."
diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm
index cd8612fd19..3ba00d305b 100644
--- a/code/datums/brain_damage/severe.dm
+++ b/code/datums/brain_damage/severe.dm
@@ -119,8 +119,9 @@
/datum/brain_trauma/severe/paralysis/spinesnapped
random_gain = FALSE
+ clonable = FALSE
paralysis_type = "legs"
- resilience = TRAUMA_RESILIENCE_LOBOTOMY
+ resilience = TRAUMA_RESILIENCE_LOBOTOMY // It shouldn't fix severed spinal cords really, but there is no specific surgery for that yet.
/datum/brain_trauma/severe/narcolepsy
name = "Narcolepsy"
diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm
index 1475cfa356..335ecf889f 100644
--- a/code/datums/mutations/actions.dm
+++ b/code/datums/mutations/actions.dm
@@ -42,6 +42,7 @@
school = "evocation"
charge_max = 600
clothes_req = NONE
+ antimagic_allowed = TRUE
range = 20
base_icon_state = "fireball"
action_icon_state = "fireball0"
@@ -122,6 +123,7 @@
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
school = "evocation"
clothes_req = NONE
+ antimagic_allowed = TRUE
charge_max = 600
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
invocation_type = "shout"
@@ -155,6 +157,7 @@
dropmessage = "You let the electricity from your hand dissipate."
hand_path = /obj/item/melee/touch_attack/shock
charge_max = 400
+ antimagic_allowed = TRUE
clothes_req = NONE
action_icon_state = "zap"
@@ -212,6 +215,7 @@
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
charge_max = 100
clothes_req = NONE
+ antimagic_allowed = TRUE
range = -1
include_user = TRUE
action_icon_state = "nose"
@@ -290,6 +294,7 @@
name = "Drop a limb"
desc = "Concentrate to make a random limb pop right off your body."
clothes_req = NONE
+ antimagic_allowed = TRUE
charge_max = 100
action_icon_state = "autotomy"
@@ -327,6 +332,7 @@
name = "Lay Web"
desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe."
clothes_req = NONE
+ antimagic_allowed = TRUE
charge_max = 4 SECONDS //the same time to lay a web
action_icon = 'icons/mob/actions/actions_genetic.dmi'
action_icon_state = "lay_web"
@@ -368,6 +374,7 @@
name = "Launch spike"
desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it."
clothes_req = NONE
+ antimagic_allowed = TRUE
charge_max = 100
action_icon = 'icons/mob/actions/actions_genetic.dmi'
action_icon_state = "spike"
diff --git a/code/game/gamemodes/clown_ops/bananium_bomb.dm b/code/game/gamemodes/clown_ops/bananium_bomb.dm
index ce864007f0..695fc79169 100644
--- a/code/game/gamemodes/clown_ops/bananium_bomb.dm
+++ b/code/game/gamemodes/clown_ops/bananium_bomb.dm
@@ -51,4 +51,4 @@
H.dna.add_mutation(CLOWNMUT)
H.dna.add_mutation(SMILE)
- H.gain_trauma(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_LOBOTOMY, "clowns") //MWA HA HA
+ H.gain_trauma(/datum/brain_trauma/mild/phobia/clowns, TRAUMA_RESILIENCE_LOBOTOMY) //MWA HA HA
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index cfe9d14663..9afe4808fd 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -134,7 +134,7 @@
return examine(user)
//Start growing a human clone in the pod!
-/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance)
+/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -209,6 +209,12 @@
var/datum/quirk/Q = new V(H)
Q.on_clone(quirks[V])
+ for(var/t in traumas)
+ var/datum/brain_trauma/BT = t
+ var/datum/brain_trauma/cloned_trauma = BT.on_clone()
+ if(cloned_trauma)
+ H.gain_trauma(cloned_trauma, BT.resilience)
+
H.set_cloned_appearance()
H.give_genitals(TRUE)
@@ -271,9 +277,6 @@
var/obj/item/bodypart/BP = I
BP.attach_limb(mob_occupant)
- //Premature clones may have brain damage.
- mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult))
-
use_power(7500) //This might need tweaking.
else if((mob_occupant && mob_occupant.cloneloss <= (100 - heal_level)))
@@ -399,6 +402,8 @@
to_chat(occupant, "There is a bright flash!
You feel like a new being.")
mob_occupant.flash_act()
+ mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, mob_occupant.getCloneLoss())
+
occupant.forceMove(T)
update_icon()
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
@@ -474,10 +479,9 @@
unattached_flesh.Cut()
H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
- //H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE)
- // In addition to being cellularly damaged and having barely any
-
- // brain function, they also have no limbs or internal organs.
+ // In addition to being cellularly damaged, they also have no limbs or internal organs.
+ // Applying brainloss is done when the clone leaves the pod, so application of traumas can happen.
+ // based on the level of damage sustained.
if(!HAS_TRAIT(H, TRAIT_NODISMEMBER))
var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 981a5643a8..7834d6f2a2 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -73,7 +73,7 @@
if(pod.occupant)
continue //how though?
- if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"]))
+ if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
temp = "[R.fields["name"]] => Cloning cycle in progress..."
records -= R
@@ -442,14 +442,17 @@
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
var/datum/bank_account/has_bank_account
+
+ // Do not use unless you know what they are.
+ var/mob/living/carbon/C = mob_occupant
+ var/mob/living/brain/B = mob_occupant
+
if(ishuman(mob_occupant))
- var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
var/obj/item/card/id/I = C.get_idcard()
if(I)
has_bank_account = I.registered_account
if(isbrain(mob_occupant))
- var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!istype(dna))
@@ -497,11 +500,17 @@
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
R.fields["quirks"] = list()
- R.fields["bank_account"] = has_bank_account
for(var/V in mob_occupant.roundstart_quirks)
var/datum/quirk/T = V
R.fields["quirks"][T.type] = T.clone_data()
+ R.fields["traumas"] = list()
+ if(ishuman(mob_occupant))
+ R.fields["traumas"] = C.get_traumas()
+ if(isbrain(mob_occupant))
+ R.fields["traumas"] = B.get_traumas()
+
+ R.fields["bank_account"] = has_bank_account
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
R.fields["mind"] = "[REF(mob_occupant.mind)]"
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index 37b6baaa0b..d7065df0f0 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -370,6 +370,14 @@
for(var/i in 1 to 7)
new /obj/item/reagent_containers/pill/breast_enlargement(src)
+/obj/item/storage/pill_bottle/neurine
+ name = "bottle of neurine pills"
+ desc = "Contains pills to treat non-severe mental traumas."
+
+/obj/item/storage/pill_bottle/neurine/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/neurine(src)
+
/////////////
//Organ Box//
/////////////
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index a9bc64a932..881e668d9b 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -560,6 +560,27 @@
. += "You cast it [times] times.
"
return .
+/datum/spellbook_entry/summon/curse_of_madness
+ name = "Curse of Madness"
+ desc = "Curses the station, warping the minds of everyone inside, causing lasting traumas. Warning: this spell can affect you if not cast from a safe distance."
+ cost = 4
+
+/datum/spellbook_entry/summon/curse_of_madness/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
+ SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
+ active = TRUE
+ var/message = stripped_input(user, "Whisper a secret truth to drive your victims to madness.", "Whispers of Madness")
+ if(!message)
+ return FALSE
+ curse_of_madness(user, message)
+ to_chat(user, "You have cast the curse of insanity!")
+ playsound(user, 'sound/magic/mandswap.ogg', 50, 1)
+ return TRUE
+
+/datum/spellbook_entry/summon/curse_of_madness/IsAvailible()
+ if(!SSticker.mode) // In case spellbook is placed on map
+ return FALSE
+ return (!CONFIG_GET(flag/no_summon_traumas) && ..())
+
/obj/item/spellbook
name = "spell book"
desc = "An unearthly tome that glows with power."
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index 5582947732..723fb93b78 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -238,7 +238,7 @@
item_state = "foilhat"
armor = list("melee" = 0, "bullet" = 0, "laser" = -5,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = -5, "fire" = 0, "acid" = 0)
equip_delay_other = 140
- var/datum/brain_trauma/mild/phobia/paranoia
+ var/datum/brain_trauma/mild/phobia/conspiracies/paranoia
var/warped = FALSE
clothing_flags = IGNORE_HAT_TOSS
@@ -255,7 +255,8 @@
return
if(paranoia)
QDEL_NULL(paranoia)
- paranoia = new("conspiracies")
+ paranoia = new()
+ paranoia.clonable = FALSE
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC)
to_chat(user, "As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. ")
diff --git a/code/modules/events/_event.dm b/code/modules/events/_event.dm
index a8ab470d5d..b88bef1c87 100644
--- a/code/modules/events/_event.dm
+++ b/code/modules/events/_event.dm
@@ -17,9 +17,9 @@
var/holidayID = "" //string which should be in the SSeventss.holidays list if you wish this event to be holiday-specific
//anything with a (non-null) holidayID which does not match holiday, cannot run.
- var/wizardevent = 0
-
- var/alertadmins = 1 //should we let the admins know this event is firing
+ var/wizardevent = FALSE
+ var/random = FALSE //If the event has occured randomly, or if it was forced by an admin or in-game occurance
+ var/alert_observers = TRUE //should we let the ghosts and admins know this event is firing
//should be disabled on events that fire a lot
var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes
@@ -33,7 +33,7 @@
min_players = CEILING(min_players * CONFIG_GET(number/events_min_players_mul), 1)
/datum/round_event_control/wizard
- wizardevent = 1
+ wizardevent = TRUE
var/can_be_midround_wizard = TRUE
// Checks if the event can be spawned. Used by event controller and "false alarm" event.
@@ -67,7 +67,7 @@
return EVENT_CANT_RUN
triggering = TRUE
- if (alertadmins)
+ if (alert_observers)
message_admins("Random Event triggering in 10 seconds: [name] (CANCEL)")
sleep(100)
var/gamemode = SSticker.mode.config_tag
@@ -92,7 +92,7 @@
log_admin_private("[key_name(usr)] cancelled event [name].")
SSblackbox.record_feedback("tally", "event_admin_cancelled", 1, typepath)
-/datum/round_event_control/proc/runEvent(random)
+/datum/round_event_control/proc/runEvent()
var/datum/round_event/E = new typepath()
E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
E.control = src
@@ -101,10 +101,9 @@
testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
if(random)
- if(alertadmins)
- deadchat_broadcast("[name] has just been randomly triggered!") //STOP ASSUMING IT'S BADMINS!
log_game("Random Event triggering: [name] ([typepath])")
-
+ if (alert_observers)
+ deadchat_broadcast("[name] has just been[random ? " randomly" : ""] triggered!") //STOP ASSUMING IT'S BADMINS!
return E
//Special admins setup
@@ -140,6 +139,17 @@
/datum/round_event/proc/start()
return
+/**
+ * Called after something followable has been spawned by an event
+ * Provides ghosts a follow link to an atom if possible
+ * Only called once.
+ */
+/datum/round_event/proc/announce_to_ghosts(atom/atom_of_interest)
+ if(control.alert_observers)
+ if (atom_of_interest)
+ notify_ghosts("[control.name] has an object of interest: [atom_of_interest]!", source=atom_of_interest, action=NOTIFY_ORBIT, header="Something's Interesting!")
+ return
+
//Called when the tick is equal to the announceWhen variable.
//Allows you to announce before starting or vice versa.
//Only called once.
diff --git a/code/modules/events/anomaly.dm b/code/modules/events/anomaly.dm
index d8122eac75..394294db37 100644
--- a/code/modules/events/anomaly.dm
+++ b/code/modules/events/anomaly.dm
@@ -8,7 +8,7 @@
/datum/round_event/anomaly
var/area/impact_area
- var/obj/effect/anomaly/newAnomaly
+ var/obj/effect/anomaly/anomaly_path = /obj/effect/anomaly/flux
announceWhen = 1
@@ -27,7 +27,7 @@
//Subtypes from the above that actually should explode.
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
-
+
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
return safepick(typecache_filter_list(GLOB.sortedAreas,allowed_areas))
@@ -44,6 +44,9 @@
priority_announce("Localized energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
+ var/turf/T = pick(get_area_turfs(impact_area))
+ var/newAnomaly
if(T)
- newAnomaly = new /obj/effect/anomaly/flux(T)
\ No newline at end of file
+ newAnomaly = new anomaly_path(T)
+ if (newAnomaly)
+ announce_to_ghosts(newAnomaly)
diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm
index a6a0effa2b..395b3b88a5 100644
--- a/code/modules/events/anomaly_bluespace.dm
+++ b/code/modules/events/anomaly_bluespace.dm
@@ -1,6 +1,7 @@
/datum/round_event_control/anomaly/anomaly_bluespace
name = "Anomaly: Bluespace"
typepath = /datum/round_event/anomaly/anomaly_bluespace
+
max_occurrences = 1
weight = 5
gamemode_blacklist = list("dynamic")
@@ -8,15 +9,10 @@
/datum/round_event/anomaly/anomaly_bluespace
startWhen = 3
announceWhen = 10
-
+ anomaly_path = /obj/effect/anomaly/bluespace
/datum/round_event/anomaly/anomaly_bluespace/announce(fake)
if(prob(90))
priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
print_command_report("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Unstable bluespace anomaly")
-
-/datum/round_event/anomaly/anomaly_bluespace/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
- if(T)
- newAnomaly = new /obj/effect/anomaly/bluespace(T)
diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm
index f4c78c0ec4..a9a7ed50b9 100644
--- a/code/modules/events/anomaly_flux.dm
+++ b/code/modules/events/anomaly_flux.dm
@@ -10,14 +10,10 @@
/datum/round_event/anomaly/anomaly_flux
startWhen = 10
announceWhen = 3
+ anomaly_path = /obj/effect/anomaly/flux
/datum/round_event/anomaly/anomaly_flux/announce(fake)
if(prob(90))
priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
print_command_report("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].","Localized hyper-energetic flux wave")
-
-/datum/round_event/anomaly/anomaly_flux/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
- if(T)
- newAnomaly = new /obj/effect/anomaly/flux(T)
diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm
index 8500b44597..cabd7face8 100644
--- a/code/modules/events/anomaly_grav.dm
+++ b/code/modules/events/anomaly_grav.dm
@@ -1,6 +1,7 @@
/datum/round_event_control/anomaly/anomaly_grav
name = "Anomaly: Gravitational"
typepath = /datum/round_event/anomaly/anomaly_grav
+
max_occurrences = 5
weight = 20
gamemode_blacklist = list("dynamic")
@@ -9,14 +10,10 @@
/datum/round_event/anomaly/anomaly_grav
startWhen = 3
announceWhen = 20
+ anomaly_path = /obj/effect/anomaly/grav
/datum/round_event/anomaly/anomaly_grav/announce(fake)
if(prob(90))
priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
print_command_report("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Gravitational anomaly")
-
-/datum/round_event/anomaly/anomaly_grav/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
- if(T)
- newAnomaly = new /obj/effect/anomaly/grav(T)
diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm
index 9594727784..8c8fbd6d36 100644
--- a/code/modules/events/anomaly_pyro.dm
+++ b/code/modules/events/anomaly_pyro.dm
@@ -1,6 +1,7 @@
/datum/round_event_control/anomaly/anomaly_pyro
name = "Anomaly: Pyroclastic"
typepath = /datum/round_event/anomaly/anomaly_pyro
+
max_occurrences = 5
weight = 20
gamemode_blacklist = list("dynamic")
@@ -8,14 +9,10 @@
/datum/round_event/anomaly/anomaly_pyro
startWhen = 3
announceWhen = 10
+ anomaly_path = /obj/effect/anomaly/pyro
/datum/round_event/anomaly/anomaly_pyro/announce(fake)
if(prob(90))
priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
print_command_report("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Pyroclastic anomaly")
-
-/datum/round_event/anomaly/anomaly_pyro/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
- if(T)
- newAnomaly = new /obj/effect/anomaly/pyro(T)
diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm
index f6eaea40d5..96d084873d 100644
--- a/code/modules/events/anomaly_vortex.dm
+++ b/code/modules/events/anomaly_vortex.dm
@@ -10,14 +10,10 @@
/datum/round_event/anomaly/anomaly_vortex
startWhen = 10
announceWhen = 3
+ anomaly_path = /obj/effect/anomaly/bhole
/datum/round_event/anomaly/anomaly_vortex/announce(fake)
if(prob(90))
priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
else
print_command_report("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name].","Vortex anomaly")
-
-/datum/round_event/anomaly/anomaly_vortex/start()
- var/turf/T = safepick(get_area_turfs(impact_area))
- if(T)
- newAnomaly = new /obj/effect/anomaly/bhole(T)
diff --git a/code/modules/events/brain_trauma.dm b/code/modules/events/brain_trauma.dm
index 9e8c7e483e..3e8182a827 100644
--- a/code/modules/events/brain_trauma.dm
+++ b/code/modules/events/brain_trauma.dm
@@ -30,4 +30,4 @@
BRAIN_TRAUMA_SPECIAL = 10
))
- H.gain_trauma_type(trauma_type, resistance)
\ No newline at end of file
+ H.gain_trauma_type(trauma_type, resistance)
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index e61af1368d..da5b4c0cb2 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -54,6 +54,7 @@
vendingMachines.Remove(originMachine)
originMachine.shut_up = 0
originMachine.shoot_inventory = 1
+ announce_to_ghosts(originMachine)
/datum/round_event/brand_intelligence/tick()
diff --git a/code/modules/events/camerafailure.dm b/code/modules/events/camerafailure.dm
index e8556e9118..8d7ef3204c 100644
--- a/code/modules/events/camerafailure.dm
+++ b/code/modules/events/camerafailure.dm
@@ -3,7 +3,7 @@
typepath = /datum/round_event/camera_failure
weight = 100
max_occurrences = 20
- alertadmins = 0
+ alert_observers = FALSE
/datum/round_event/camera_failure
fakeable = FALSE
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index e6cb043165..2c553fc8a7 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -10,6 +10,7 @@
/datum/round_event/carp_migration
announceWhen = 3
startWhen = 50
+ var/hasAnnounced = FALSE
/datum/round_event/carp_migration/setup()
startWhen = rand(40, 60)
@@ -22,10 +23,16 @@
/datum/round_event/carp_migration/start()
+ var/mob/living/simple_animal/hostile/carp/fish
for(var/obj/effect/landmark/carpspawn/C in GLOB.landmarks_list)
if(prob(95))
- new /mob/living/simple_animal/hostile/carp(C.loc)
+ fish = new (C.loc)
else
- new /mob/living/simple_animal/hostile/carp/megacarp(C.loc)
-
+ fish = new /mob/living/simple_animal/hostile/carp/megacarp(C.loc)
+ fishannounce(fish) //Prefer to announce the megacarps over the regular fishies
+ fishannounce(fish)
+/datum/round_event/carp_migration/proc/fishannounce(atom/fish)
+ if (!hasAnnounced)
+ announce_to_ghosts(fish) //Only anounce the first fish
+ hasAnnounced = TRUE
diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm
index 802736d5d4..860685c787 100644
--- a/code/modules/events/dust.dm
+++ b/code/modules/events/dust.dm
@@ -4,7 +4,7 @@
weight = 200
max_occurrences = 1000
earliest_start = 0 MINUTES
- alertadmins = 0
+ alert_observers = FALSE
gamemode_blacklist = list("dynamic")
/datum/round_event/space_dust
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 6e6abb1cd4..5e5e318e3c 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -4,7 +4,7 @@
earliest_start = 10 MINUTES
min_players = 5
weight = 40
- alertadmins = 0
+ alert_observers = FALSE
gamemode_blacklist = list("dynamic")
/datum/round_event/electrical_storm
diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm
index e50d89a3a3..ae1d1320a5 100644
--- a/code/modules/events/ghost_role.dm
+++ b/code/modules/events/ghost_role.dm
@@ -37,7 +37,10 @@
signing up.")
else if(status == SUCCESSFUL_SPAWN)
message_admins("[role_name] spawned successfully.")
- if(!spawned_mobs.len)
+ if(spawned_mobs.len)
+ for(var/mob/M in spawned_mobs)
+ announce_to_ghosts(M)
+ else
message_admins("No mobs found in the `spawned_mobs` list, this is \
a bug.")
else
diff --git a/code/modules/events/heart_attack.dm b/code/modules/events/heart_attack.dm
index a47a8b81b4..b3bc571a4a 100644
--- a/code/modules/events/heart_attack.dm
+++ b/code/modules/events/heart_attack.dm
@@ -20,4 +20,4 @@
var/mob/living/carbon/human/winner = pickweight(heart_attack_contestants)
var/datum/disease/D = new /datum/disease/heart_failure()
winner.ForceContractDisease(D, FALSE, TRUE)
- notify_ghosts("[winner] is beginning to have a heart attack!", enter_link="(Click to orbit)", source=winner, action=NOTIFY_ORBIT)
+ announce_to_ghosts(winner)
\ No newline at end of file
diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm
index d4f51e995e..0ace65ffd3 100644
--- a/code/modules/events/immovable_rod.dm
+++ b/code/modules/events/immovable_rod.dm
@@ -35,7 +35,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
var/z = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
var/turf/startT = spaceDebrisStartLoc(startside, z)
var/turf/endT = spaceDebrisFinishLoc(startside, z)
- new /obj/effect/immovablerod(startT, endT, C.special_target)
+ var/atom/rod = new /obj/effect/immovablerod(startT, endT, C.special_target)
+ announce_to_ghosts(rod)
/obj/effect/immovablerod
name = "immovable rod"
@@ -61,10 +62,6 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
z_original = z
destination = end
special_target = aimed_at
- if(notify)
- notify_ghosts("\A [src] is inbound!",
- enter_link="(Click to orbit)",
- source=src, action=NOTIFY_ORBIT)
GLOB.poi_list += src
var/special_target_valid = FALSE
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index b0b12f3944..fd3a189eb3 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -80,8 +80,9 @@
var/mob/M = candidates[1]
spawner.create(M.ckey)
candidates -= M
+ announce_to_ghosts(M)
else
- notify_ghosts("Space pirates are waking up!", source = spawner, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
+ announce_to_ghosts(spawner)
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") //CITADEL EDIT also metabreak here too
diff --git a/code/modules/events/processor_overload.dm b/code/modules/events/processor_overload.dm
index cf6223bf0d..22e475a8ef 100644
--- a/code/modules/events/processor_overload.dm
+++ b/code/modules/events/processor_overload.dm
@@ -30,6 +30,7 @@
/datum/round_event/processor_overload/start()
for(var/obj/machinery/telecomms/processor/P in GLOB.telecomms_list)
if(prob(10))
+ announce_to_ghosts(P)
// Damage the surrounding area to indicate that it popped
explosion(get_turf(P), 0, 0, 2)
// Only a level 1 explosion actually damages the machine
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index 85bcf4959d..c592e06e0e 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -383,7 +383,9 @@
/datum/spacevine_controller/New(turf/location, list/muts, potency, production, datum/round_event/event = null)
vines = list()
growth_queue = list()
- spawn_spacevine_piece(location, null, muts)
+ var/obj/structure/spacevine/SV = spawn_spacevine_piece(location, null, muts)
+ if (event)
+ event.announce_to_ghosts(SV)
START_PROCESSING(SSobj, src)
vine_mutations_list = list()
init_subtypes(/datum/spacevine_mutation/, vine_mutations_list)
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 2cba5fc529..d1c327e0f7 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -35,6 +35,6 @@
var/spawn_type = /obj/structure/spider/spiderling
if(prob(66))
spawn_type = /obj/structure/spider/spiderling/nurse
- spawn_atom_to_turf(spawn_type, vent, 1, FALSE)
+ announce_to_ghosts(spawn_atom_to_turf(spawn_type, vent, 1, FALSE))
vents -= vent
spawncount--
diff --git a/code/modules/events/wizard/madness.dm b/code/modules/events/wizard/madness.dm
new file mode 100644
index 0000000000..ac86236623
--- /dev/null
+++ b/code/modules/events/wizard/madness.dm
@@ -0,0 +1,28 @@
+/datum/round_event_control/wizard/madness
+ name = "Curse of Madness"
+ weight = 1
+ typepath = /datum/round_event/wizard/madness
+ earliest_start = 0 MINUTES
+
+ var/forced_secret
+
+/datum/round_event_control/wizard/madness/admin_setup()
+ if(!check_rights(R_FUN))
+ return
+
+ var/suggested = pick(strings(REDPILL_FILE, "redpill_questions"))
+
+ forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sortList(suggested)) as text|null) || suggested
+
+/datum/round_event/wizard/madness/start()
+ var/datum/round_event_control/wizard/madness/C = control
+
+ var/horrifying_truth
+
+ if(C.forced_secret)
+ horrifying_truth = C.forced_secret
+ C.forced_secret = null
+ else
+ horrifying_truth = pick(strings(REDPILL_FILE, "redpill_questions"))
+
+ curse_of_madness(null, horrifying_truth)
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 36babd9b95..6888a6590f 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -412,6 +412,8 @@
give_guns(humanc)
if(GLOB.summon_magic_triggered)
give_magic(humanc)
+ if(GLOB.curse_of_madness_triggered)
+ give_madness(humanc, GLOB.curse_of_madness_triggered)
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 08d415fc3c..be03827695 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -100,3 +100,9 @@
client.mouse_pointer_icon = M.mouse_pointer
if (client && ranged_ability && ranged_ability.ranged_mousepointer)
client.mouse_pointer_icon = ranged_ability.ranged_mousepointer
+
+/mob/living/brain/proc/get_traumas()
+ . = list()
+ if(istype(loc, /obj/item/organ/brain))
+ var/obj/item/organ/brain/B = loc
+ . = B.traumas
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index b5835aef52..becff250b9 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -265,46 +265,3 @@
if(update)
update_damage_overlays()
update_stamina()
-
-/* TO_REMOVE
-/mob/living/carbon/getOrganLoss(ORGAN_SLOT_BRAIN)
- . = 0
- var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
- if(B)
- . = B.get_brain_damage()
-
-//Some sources of brain damage shouldn't be deadly
-/mob/living/carbon/adjustOrganLoss(ORGAN_SLOT_BRAIN, amount, maximum = BRAIN_DAMAGE_DEATH)
- if(status_flags & GODMODE)
- return FALSE
- var/prev_brainloss = getOrganLoss(ORGAN_SLOT_BRAIN)
- var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
- if(!B)
- return
- B.adjust_brain_damage(amount, maximum)
- if(amount <= 0) //cut this early
- return
- var/brainloss = getOrganLoss(ORGAN_SLOT_BRAIN)
- if(brainloss > BRAIN_DAMAGE_MILD)
- if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_MILD)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2%
- gain_trauma_type(BRAIN_TRAUMA_MILD)
- if(brainloss > BRAIN_DAMAGE_SEVERE)
- if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_SEVERE)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2%
- if(prob(20))
- gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
- else
- gain_trauma_type(BRAIN_TRAUMA_SEVERE)
-
- if(prev_brainloss < BRAIN_DAMAGE_MILD && brainloss >= BRAIN_DAMAGE_MILD)
- to_chat(src, "You feel lightheaded.")
- else if(prev_brainloss < BRAIN_DAMAGE_SEVERE && brainloss >= BRAIN_DAMAGE_SEVERE)
- to_chat(src, "You feel less in control of your thoughts.")
- else if(prev_brainloss < (BRAIN_DAMAGE_DEATH - 20) && brainloss >= (BRAIN_DAMAGE_DEATH - 20))
- to_chat(src, "You can feel your mind flickering on and off...")
-
-/mob/living/carbon/setBrainLoss(amount)
- var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
- if(B)
- var/adjusted_amount = amount - B.get_brain_damage()
- B.adjust_brain_damage(adjusted_amount, null)
-*/
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 28ca97dc2b..0b2588bc6c 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -349,7 +349,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
/mob/proc/reagent_check(datum/reagent/R) // utilized in the species code
return 1
-/proc/notify_ghosts(message, ghost_sound, enter_link, atom/source, mutable_appearance/alert_overlay, action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, ignore_dnr_observers = FALSE) //Easy notification of ghosts.
+/proc/notify_ghosts(message, ghost_sound, enter_link, atom/source, mutable_appearance/alert_overlay, action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, ignore_dnr_observers = FALSE, header) //Easy notification of ghosts.
if(ignore_mapload && SSatoms.initialized != INITIALIZATION_INNEW_REGULAR) //don't notify for objects created during a map load
return
for(var/mob/dead/observer/O in GLOB.player_list)
@@ -366,6 +366,8 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
if(A)
if(O.client.prefs && O.client.prefs.UI_style)
A.icon = ui_style2icon(O.client.prefs.UI_style)
+ if (header)
+ A.name = header
A.desc = message
A.action = action
A.target = source
diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm
index ce87eddc67..0c8a9deaf8 100644
--- a/code/modules/projectiles/guns/magic.dm
+++ b/code/modules/projectiles/guns/magic.dm
@@ -9,7 +9,7 @@
fire_sound = 'sound/weapons/emitter.ogg'
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_HUGE
- var/checks_antimagic = FALSE
+ var/checks_antimagic = TRUE
var/max_charges = 6
var/charges = 0
var/recharge_rate = 4
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index fca04f239e..ec1e7823ed 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -11,8 +11,8 @@
grind_results = list()
var/apply_type = INGEST
var/apply_method = "swallow"
- var/roundstart = 0
- var/self_delay = 0 //pills are instant, this is because patches inheret their aplication from pills
+ var/roundstart = FALSE
+ var/self_delay = FALSE //pills are instant, this is because patches inheret their aplication from pills
var/dissolvable = TRUE
/obj/item/reagent_containers/pill/Initialize()
@@ -83,119 +83,126 @@
desc = "Highly toxic."
icon_state = "pill5"
list_reagents = list(/datum/reagent/toxin = 50)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/cyanide
name = "cyanide pill"
desc = "Don't swallow this."
icon_state = "pill5"
list_reagents = list(/datum/reagent/toxin/cyanide = 50)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/adminordrazine
name = "adminordrazine pill"
desc = "It's magic. We don't have to explain it."
icon_state = "pill16"
list_reagents = list(/datum/reagent/medicine/adminordrazine = 50)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/morphine
name = "morphine pill"
desc = "Commonly used to treat insomnia."
icon_state = "pill8"
list_reagents = list(/datum/reagent/medicine/morphine = 30)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/stimulant
name = "stimulant pill"
desc = "Often taken by overworked employees, athletes, and the inebriated. You'll snap to attention immediately!"
icon_state = "pill19"
list_reagents = list(/datum/reagent/medicine/ephedrine = 10, /datum/reagent/medicine/antihol = 10, /datum/reagent/consumable/coffee = 30)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/salbutamol
name = "salbutamol pill"
desc = "Used to treat oxygen deprivation."
icon_state = "pill16"
list_reagents = list(/datum/reagent/medicine/salbutamol = 30)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/charcoal
name = "charcoal pill"
desc = "Neutralizes many common toxins."
icon_state = "pill17"
list_reagents = list(/datum/reagent/medicine/charcoal = 10)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/epinephrine
name = "epinephrine pill"
desc = "Used to stabilize patients."
icon_state = "pill5"
list_reagents = list(/datum/reagent/medicine/epinephrine = 15)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/mannitol
name = "mannitol pill"
desc = "Used to treat brain damage."
icon_state = "pill17"
list_reagents = list(/datum/reagent/medicine/mannitol = 25)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/mutadone
name = "mutadone pill"
desc = "Used to treat genetic damage."
icon_state = "pill20"
list_reagents = list(/datum/reagent/medicine/mutadone = 25)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/salicyclic
name = "salicylic acid pill"
desc = "Used to dull pain."
icon_state = "pill9"
list_reagents = list(/datum/reagent/medicine/sal_acid = 24)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/oxandrolone
name = "oxandrolone pill"
desc = "Used to stimulate burn healing."
icon_state = "pill11"
list_reagents = list(/datum/reagent/medicine/oxandrolone = 24)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/insulin
name = "insulin pill"
desc = "Handles hyperglycaemic coma."
icon_state = "pill18"
list_reagents = list(/datum/reagent/medicine/insulin = 50)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/psicodine
name = "psicodine pill"
- desc = "Used to treat mental instability and traumas."
+ desc = "Used to treat mental instability and phobias."
list_reagents = list(/datum/reagent/medicine/psicodine = 10)
icon_state = "pill22"
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/antirad
name = "potassium iodide pill"
desc = "Used to treat radition used to counter radiation poisoning."
icon_state = "pill18"
list_reagents = list(/datum/reagent/medicine/potass_iodide = 50)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/antirad_plus
name = "prussian blue pill"
desc = "Used to treat heavy radition poisoning."
icon_state = "prussian_blue"
list_reagents = list(/datum/reagent/medicine/prussian_blue = 25)
- roundstart = 1
+ roundstart = TRUE
/obj/item/reagent_containers/pill/mutarad
name = "radiation treatment deluxe pill"
desc = "Used to treat heavy radition poisoning and genetic defects."
icon_state = "anit_rad_fixgene"
list_reagents = list(/datum/reagent/medicine/prussian_blue = 10, /datum/reagent/medicine/potass_iodide = 10, /datum/reagent/medicine/mutadone = 5)
- roundstart = 1
+ roundstart = TRUE
+
+/obj/item/reagent_containers/pill/neurine
+ name = "neurine pill"
+ desc = "Used to treat non-severe mental traumas."
+ list_reagents = list("neurine" = 10)
+ icon_state = "pill22"
+ roundstart = TRUE
///////////////////////////////////////// this pill is used only in a legion mob drop
/obj/item/reagent_containers/pill/shadowtoxin
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 143fe508b6..21552f7e87 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -120,7 +120,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/list/mobs_blacklist //The opposite of the above.
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting
- var/antimagic_allowed = TRUE // If false, the spell cannot be cast while under the effect of antimagic
+ var/antimagic_allowed = FALSE // If false, the spell cannot be cast while under the effect of antimagic
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
var/invocation_emote_self = null
var/invocation_type = "none" //can be none, whisper, emote and shout
diff --git a/code/modules/spells/spell_types/curse.dm b/code/modules/spells/spell_types/curse.dm
new file mode 100644
index 0000000000..9449e4a5d0
--- /dev/null
+++ b/code/modules/spells/spell_types/curse.dm
@@ -0,0 +1,37 @@
+GLOBAL_VAR_INIT(curse_of_madness_triggered, FALSE)
+
+/proc/curse_of_madness(mob/user, message)
+ if(user) //in this case either someone holding a spellbook or a badmin
+ to_chat(user, "You sent a curse of madness with the message \"[message]\"!")
+ message_admins("[ADMIN_LOOKUPFLW(user)] sent a curse of madness with the message \"[message]\"!")
+ log_game("[key_name(user)] sent a curse of madness with the message \"[message]\"!")
+
+ GLOB.curse_of_madness_triggered = message // So latejoiners are also afflicted.
+
+ deadchat_broadcast("A Curse of Madness has stricken the station, shattering their minds with the awful secret: \"[message]\"")
+
+ for(var/mob/living/carbon/human/H in GLOB.player_list)
+ if(H.stat == DEAD)
+ continue
+ var/turf/T = get_turf(H)
+ if(T && !is_station_level(T.z))
+ continue
+ if(H.anti_magic_check(TRUE, FALSE, TRUE))
+ to_chat(H, "You have a strange feeling for a moment, but then it passes.")
+ continue
+ give_madness(H, message)
+
+/proc/give_madness(mob/living/carbon/human/H, message)
+ H.playsound_local(H,'sound/magic/curse.ogg',40,1)
+ to_chat(H, "[message]")
+ to_chat(H, "Your mind shatters!")
+ switch(rand(1,10))
+ if(1 to 3)
+ H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY)
+ H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY)
+ if(4 to 6)
+ H.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY)
+ if(7 to 8)
+ H.gain_trauma_type(BRAIN_TRAUMA_MAGIC, TRAUMA_RESILIENCE_LOBOTOMY)
+ if(9 to 10)
+ H.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRAUMA_RESILIENCE_LOBOTOMY)
diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm
index 8f39da5031..26a6b57b25 100644
--- a/code/modules/spells/spell_types/mime.dm
+++ b/code/modules/spells/spell_types/mime.dm
@@ -12,6 +12,7 @@
range = 0
cast_sound = null
mobs_whitelist = list(/mob/living/carbon/human)
+ antimagic_allowed = TRUE
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
@@ -40,6 +41,7 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
+ antimagic_allowed = TRUE
/obj/effect/proc_holder/spell/targeted/mime/speak/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind?.miming)
@@ -76,6 +78,7 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
+ antimagic_allowed = TRUE
/obj/effect/proc_holder/spell/targeted/forcewall/mime/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind)
@@ -107,6 +110,7 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
base_icon_state = "mime"
+ antimagic_allowed = TRUE
/obj/effect/proc_holder/spell/aimed/finger_guns/Trigger(mob/user, skip_can_cast = TRUE)
@@ -137,6 +141,7 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
hand_path = /obj/item/melee/touch_attack/mimerope
+ antimagic_allowed = TRUE
/obj/effect/proc_holder/spell/targeted/touch/mimerope/Trigger(mob/user, skip_can_cast = TRUE)
if(user.mind)
diff --git a/code/modules/spells/spell_types/santa.dm b/code/modules/spells/spell_types/santa.dm
index 64ed925455..4f6957433b 100644
--- a/code/modules/spells/spell_types/santa.dm
+++ b/code/modules/spells/spell_types/santa.dm
@@ -13,3 +13,4 @@
summon_type = list("/obj/item/a_gift")
summon_lifespan = 0
summon_amt = 5
+ antimagic_allowed = TRUE
diff --git a/code/modules/spells/spell_types/shadow_walk.dm b/code/modules/spells/spell_types/shadow_walk.dm
index 83996b5bfb..1dd949caa0 100644
--- a/code/modules/spells/spell_types/shadow_walk.dm
+++ b/code/modules/spells/spell_types/shadow_walk.dm
@@ -12,6 +12,7 @@
action_icon = 'icons/mob/actions/actions_minor_antag.dmi'
action_icon_state = "ninja_cloak"
action_background_icon_state = "bg_alien"
+ antimagic_allowed = TRUE
/obj/effect/proc_holder/spell/targeted/shadowwalk/cast(list/targets,mob/living/user = usr)
var/L = user.loc
diff --git a/code/modules/spells/spell_types/taeclowndo.dm b/code/modules/spells/spell_types/taeclowndo.dm
index 5b1e09565b..59826daf07 100644
--- a/code/modules/spells/spell_types/taeclowndo.dm
+++ b/code/modules/spells/spell_types/taeclowndo.dm
@@ -10,6 +10,7 @@
cooldown_min = 30
action_icon = 'icons/obj/food/piecake.dmi'
action_icon_state = "pie"
+ antimagic_allowed = TRUE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -24,6 +25,7 @@
range = 7
selection_type = "view"
projectile_type = null
+ antimagic_allowed = TRUE
active_msg = "You focus, your mind reaching to the clown dimension, ready to make a peel matrialize wherever you want!"
deactive_msg = "You relax, the peel remaining right in the \"thin air\" it would appear out of."
@@ -62,6 +64,7 @@
charge_max = 100
clothes_req = NONE
cooldown_min = 100
+ antimagic_allowed = TRUE
action_icon = 'icons/mecha/mecha_equipment.dmi'
action_icon_state = "mecha_honker"
@@ -76,6 +79,7 @@
charge_max = 450
clothes_req = NONE
cooldown_min = 450
+ antimagic_allowed = TRUE
action_icon = 'icons/obj/food/piecake.dmi'
action_icon_state = "frostypie"
diff --git a/code/modules/spells/spell_types/telepathy.dm b/code/modules/spells/spell_types/telepathy.dm
index 4b4f91eb18..caf9ec79c6 100644
--- a/code/modules/spells/spell_types/telepathy.dm
+++ b/code/modules/spells/spell_types/telepathy.dm
@@ -8,6 +8,7 @@
action_icon = 'icons/mob/actions/actions_revenant.dmi'
action_icon_state = "r_transmit"
action_background_icon_state = "bg_spell"
+ antimagic_allowed = TRUE
var/notice = "notice"
var/boldnotice = "boldnotice"
var/magic_check = FALSE
diff --git a/code/modules/spells/spell_types/voice_of_god.dm b/code/modules/spells/spell_types/voice_of_god.dm
index 495681a818..a920344adc 100644
--- a/code/modules/spells/spell_types/voice_of_god.dm
+++ b/code/modules/spells/spell_types/voice_of_god.dm
@@ -5,6 +5,7 @@
cooldown_min = 0
level_max = 1
clothes_req = NONE
+ antimagic_allowed = TRUE
action_icon = 'icons/mob/actions/actions_items.dmi'
action_icon_state = "voice_of_god"
var/command
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index e9432e2f58..b104c2182a 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -306,6 +306,7 @@
sound = 'sound/magic/tail_swing.ogg'
charge_max = 150
clothes_req = NONE
+ antimagic_allowed = TRUE
range = 2
cooldown_min = 150
invocation_type = "none"
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index b9d60af1b6..21fc3504bc 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -525,7 +525,7 @@ GLOBAL_LIST_EMPTY(vending_products)
if(4) // paralyze this binch
// the new paraplegic gets like 4 lines of losing their legs so skip them
visible_message("[C]'s spinal cord is obliterated with a sickening crunch!", ignored_mobs = list(C))
- C.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic)
+ C.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped)
if(5) // skull squish!
var/obj/item/bodypart/head/O = C.get_bodypart(BODY_ZONE_HEAD)
if(O)
diff --git a/tgstation.dme b/tgstation.dme
index 86a38a2ce8..712e86ce27 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1963,6 +1963,7 @@
#include "code\modules\events\wizard\imposter.dm"
#include "code\modules\events\wizard\invincible.dm"
#include "code\modules\events\wizard\lava.dm"
+#include "code\modules\events\wizard\madness.dm"
#include "code\modules\events\wizard\magicarp.dm"
#include "code\modules\events\wizard\petsplosion.dm"
#include "code\modules\events\wizard\race.dm"
@@ -3203,6 +3204,7 @@
#include "code\modules\spells\spell_types\charge.dm"
#include "code\modules\spells\spell_types\conjure.dm"
#include "code\modules\spells\spell_types\construct_spells.dm"
+#include "code\modules\spells\spell_types\curse.dm"
#include "code\modules\spells\spell_types\devil.dm"
#include "code\modules\spells\spell_types\devil_boons.dm"
#include "code\modules\spells\spell_types\dumbfire.dm"