diff --git a/baystation12.dme b/baystation12.dme
index c56eb52e88b..2bc32743c89 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -948,6 +948,7 @@
#include "code\modules\mob\dead\observer\logout.dm"
#include "code\modules\mob\dead\observer\observer.dm"
#include "code\modules\mob\dead\observer\say.dm"
+#include "code\modules\mob\dead\observer\spells.dm"
#include "code\modules\mob\living\damage_procs.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_defense.dm"
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 825585b829a..b80ca1e4bed 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -19,6 +19,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var"
var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used
+ var/ghost = 0 // Skip life check.
var/clothes_req = 1 //see if it requires clothes
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
@@ -63,31 +64,28 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
user << "[name] has no charges left."
return 0
- if(user.stat && !stat_allowed)
- user << "Not when you're incapacitated."
- return 0
-
- if(ishuman(user))
-
- var/mob/living/carbon/human/H = user
-
- if(istype(H.wear_mask, /obj/item/clothing/mask/muzzle))
- user << "You can't get the words out!"
+ if(!ghost)
+ if(usr.stat && !stat_allowed)
+ usr << "Not when you're incapacitated."
return 0
- if(clothes_req) //clothes check
- if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard))
- H << "I don't feel strong enough without my robe."
+ if(ishuman(usr) || ismonkey(usr))
+ if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle))
+ usr << "Mmmf mrrfff!"
return 0
- if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
- H << "I don't feel strong enough without my sandals."
- return 0
- if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard))
- H << "I don't feel strong enough without my hat."
- return 0
- else
- if(clothes_req)
- user << "This spell can only be casted by humans!"
+ var/obj/effect/proc_holder/spell/noclothes/spell = locate() in user.spell_list
+ if(clothes_req && !(spell && istype(spell)))//clothes check
+ if(!istype(usr, /mob/living/carbon/human))
+ usr << "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans."
+ return 0
+ if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/rig/wizard))
+ usr << "I don't feel strong enough without my robe."
+ return 0
+ if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal))
+ usr << "I don't feel strong enough without my sandals."
+ return 0
+ if(!istype(usr:head, /obj/item/clothing/head/wizard) && !istype(usr:head, /obj/item/clothing/head/helmet/space/rig/wizard))
+ usr << "I don't feel strong enough without my hat."
return 0
if(!skipcharge)
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index f02a6fc33a7..a2789cecd8e 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -28,6 +28,10 @@
amt_weakened = 5
amt_dam_fire = 10
+/obj/effect/proc_holder/spell/noclothes
+ name = "No Clothes"
+ desc = "This is a placeholder for knowing if you dont need clothes for any spell"
+
/obj/effect/proc_holder/spell/targeted/genetic/mutate
name = "Mutate"
desc = "This spell causes you to turn into a hulk and gain laser vision for a short while."
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 5f90a827826..37f8d485e9d 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -38,6 +38,9 @@
dat += "Memorize which spell:
"
dat += "The number after the spell name is the cooldown time.
"
+ dat += "Remove Clothes Requirement"
+ dat += "Warning: this takes away 2 spell choices.
"
+
dat += "Magic Missile (15)
"
dat += "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.
"
@@ -187,6 +190,11 @@
*/
if(!already_knows)
switch(href_list["spell_choice"])
+ if("noclothes")
+ feedback_add_details("wizard_spell_learned","NC")
+ H.spell_list += new /obj/effect/proc_holder/spell/noclothes
+ temp = "This teaches you how to use your spells without your magical garb, truely you are the wizardest."
+ uses--
if("magicmissile")
feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(H)
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index c62f1a236aa..746f5a06996 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -36,6 +36,8 @@
var/friendc = 0 // track if Friend Computer mode
+ var/spookymode=0 // Ghosts.
+
maptext_height = 26
maptext_width = 32
@@ -49,11 +51,14 @@
// timed process
-
process()
if(stat & NOPOWER)
remove_display()
return
+ if(spookymode)
+ spookymode = 0
+ remove_display()
+ return
update()
emp_act(severity)
@@ -206,6 +211,8 @@
anchored = 1
density = 0
+ var/spookymode=0 // Ghosts
+
var/mode = 0 // 0 = Blank
// 1 = AI emoticon
// 2 = Blue screen of death
@@ -219,6 +226,10 @@
if(stat & NOPOWER)
overlays.Cut()
return
+ if(spookymode)
+ spookymode = 0
+ overlays.Cut()
+ return
update()
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 892efd82fb2..493c909d672 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -30,6 +30,9 @@
see_in_dark = 100
verbs += /mob/dead/observer/proc/dead_tele
+ // Our new boo spell.
+ spell_list += new /obj/effect/proc_holder/spell/aoe_turf/boo(src)
+
can_reenter_corpse = flags & GHOST_CAN_REENTER
started_as_observer = flags & GHOST_IS_OBSERVER
@@ -432,18 +435,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
A.loc = T
else
A << "This mob is not located in the game world."
-/*
+
+
+/* Now a spell. See spells.dm
/mob/dead/observer/verb/boo()
set category = "Ghost"
set name = "Boo!"
set desc= "Scare your crew members because of boredom!"
if(bootime > world.time) return
+ bootime = world.time + 600
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
if(L)
L.flicker()
- bootime = world.time + 600
- return
//Maybe in the future we can add more spooky code here!
return
*/
@@ -456,6 +460,58 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set hidden = 1
src << "\red You are dead! You have no mind to store memory!"
+/mob/dead/observer/verb/analyze_air()
+ set name = "Analyze Air"
+ set category = "Ghost"
+
+ if(!istype(usr, /mob/dead/observer)) return
+
+ // Shamelessly copied from the Gas Analyzers
+ if (!( istype(usr.loc, /turf) ))
+ return
+
+ var/datum/gas_mixture/environment = usr.loc.return_air()
+
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles()
+
+ src << "\blue Results:"
+ if(abs(pressure - ONE_ATMOSPHERE) < 10)
+ src << "\blue Pressure: [round(pressure,0.1)] kPa"
+ else
+ src << "\red Pressure: [round(pressure,0.1)] kPa"
+ if(total_moles)
+ var/o2_concentration = environment.oxygen/total_moles
+ var/n2_concentration = environment.nitrogen/total_moles
+ var/co2_concentration = environment.carbon_dioxide/total_moles
+ var/plasma_concentration = environment.toxins/total_moles
+
+ var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration)
+ if(abs(n2_concentration - N2STANDARD) < 20)
+ src << "\blue Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)"
+ else
+ src << "\red Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)"
+
+ if(abs(o2_concentration - O2STANDARD) < 2)
+ src << "\blue Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)"
+ else
+ src << "\red Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)"
+
+ if(co2_concentration > 0.01)
+ src << "\red CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)"
+ else
+ src << "\blue CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)"
+
+ if(plasma_concentration > 0.01)
+ src << "\red Plasma: [round(plasma_concentration*100)]% ([round(environment.toxins,0.01)] moles)"
+
+ if(unknown_concentration > 0.01)
+ src << "\red Unknown: [round(unknown_concentration*100)]% ([round(unknown_concentration*total_moles,0.01)] moles)"
+
+ src << "\blue Temperature: [round(environment.temperature-T0C,0.1)]°C"
+ src << "\blue Heat Capacity: [round(environment.heat_capacity(),0.1)]"
+
+
/mob/dead/observer/verb/toggle_darkness()
set name = "Toggle Darkness"
set category = "Ghost"
@@ -504,4 +560,4 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
sleep(15)
following = null
..()
-//END TELEPORT HREF CODE
\ No newline at end of file
+//END TELEPORT HREF CODE
diff --git a/code/modules/mob/dead/observer/spells.dm b/code/modules/mob/dead/observer/spells.dm
new file mode 100644
index 00000000000..ef51c787e5a
--- /dev/null
+++ b/code/modules/mob/dead/observer/spells.dm
@@ -0,0 +1,51 @@
+
+
+var/global/list/boo_phrases=list(
+ "You feel a chill run down your spine.",
+ "You think you see a figure in your peripheral vision.",
+ "What was that?",
+ "The hairs stand up on the back of your neck.",
+ "You are filled with a great sadness.",
+ "Something doesn't feel right...",
+ "You feel a presence in the room.",
+ "It feels like someone's standing behind you.",
+)
+
+/obj/effect/proc_holder/spell/aoe_turf/boo
+ name = "Boo!"
+ desc = "Fuck with the living."
+
+ ghost = 1
+
+ school = "transmutation"
+ charge_max = 600
+ clothes_req = 0
+ invocation = ""
+ invocation_type = "none"
+ range = 1 // Or maybe 3?
+
+/obj/effect/proc_holder/spell/aoe_turf/boo/cast(list/targets)
+ for(var/turf/T in targets)
+ for(var/atom/A in T.contents)
+
+ // Bug humans
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(H && H.client)
+ H << "[pick(boo_phrases)]"
+
+ // Flicker unblessed lights in range
+ if(istype(A,/obj/machinery/light))
+ var/obj/machinery/light/L = A
+ if(L)
+ L.flicker()
+
+ // OH GOD BLUE APC (single animation cycle)
+ if(istype(A, /obj/machinery/power/apc))
+ A:spookify()
+
+ if(istype(A, /obj/machinery/status_display))
+ A:spookymode=1
+
+ if(istype(A, /obj/machinery/ai_status_display))
+ A:spookymode=1
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 33573573aee..6f77bf407a8 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -24,6 +24,7 @@
anchored = 1
use_power = 0
req_access = list(access_engine_equip)
+ var/spooky=0
var/area/area
var/areastring = null
var/obj/item/weapon/cell/cell
@@ -165,7 +166,7 @@
icon_state = "[basestate]-nocover"
else if (stat & BROKEN)
icon_state = "apc-b"
- else if(emagged || malfai)
+ else if(emagged || malfai || spooky)
icon_state = "apcemag"
else if(wiresexposed)
icon_state = "apcewires"
@@ -187,8 +188,15 @@
update_icon()
updating_icon = 0
-//attack with an item - open/close cover, insert cell, or (un)lock interface
+/obj/machinery/power/apc/proc/spookify()
+ if(spooky) return // Fuck you we're already spooky
+ spooky=1
+ update_icon()
+ spawn(10)
+ spooky=0
+ update_icon()
+//attack with an item - open/close cover, insert cell, or (un)lock interface
/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
@@ -836,7 +844,6 @@
if(!area.requires_power)
return
-
/*
if (equipment > 1) // off=0, off auto=1, on=2, on auto=3
use_power(src.equip_consumption, EQUIP)
@@ -985,7 +992,6 @@
area.poweralert(0, src)
// update icon & area power if anything changed
-
if(last_lt != lighting || last_eq != equipment || last_en != environ)
queue_icon_update()
update()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 7f1a2d90ef0..a62d1d4c3f0 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -448,7 +448,6 @@
flickering = 0
// ai attack - make lights flicker, because why not
-
/obj/machinery/light/attack_ai(mob/user)
src.flicker(1)
return