diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 4eae2cd194..c34c219882 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -74,4 +74,3 @@
else
// Like how did we get here?
return FALSE
-
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index 95f72d15b3..e75752adcc 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -11,6 +11,7 @@
/datum/round_event/ghost_role/blob
announceWhen = -1
role_name = "blob overmind"
+ fakeable = TRUE
/datum/round_event/ghost_role/blob/announce(fake)
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index b75140e3c7..c17140a2d2 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -23,3 +23,5 @@
new /mob/living/simple_animal/hostile/carp(C.loc)
else
new /mob/living/simple_animal/hostile/carp/megacarp(C.loc)
+
+
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index a41b4bfdde..f2e3104ab8 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -13,7 +13,7 @@
var/max_severity = 3
-/datum/round_event/disease_outbreak/announce()
+/datum/round_event/disease_outbreak/announce(fake)
priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak7.ogg')
/datum/round_event/disease_outbreak/setup()
diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm
index 978f62d85a..47eb2d4ea8 100644
--- a/code/modules/events/dust.dm
+++ b/code/modules/events/dust.dm
@@ -28,4 +28,4 @@
fakeable = FALSE
/datum/round_event/sandstorm/tick()
- spawn_meteors(10, GLOB.meteorsC)
+ spawn_meteors(10, GLOB.meteorsC)
\ No newline at end of file
diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm
index f5e9513b2e..e50d89a3a3 100644
--- a/code/modules/events/ghost_role.dm
+++ b/code/modules/events/ghost_role.dm
@@ -7,6 +7,7 @@
var/minimum_required = 1
var/role_name = "debug rat with cancer" // Q U A L I T Y M E M E S
var/list/spawned_mobs = list()
+ fakeable = FALSE
/datum/round_event/ghost_role/start()
try_spawning()
diff --git a/code/modules/events/holiday/friday13th.dm b/code/modules/events/holiday/friday13th.dm
index b1db15a896..ba2c9ea78f 100644
--- a/code/modules/events/holiday/friday13th.dm
+++ b/code/modules/events/holiday/friday13th.dm
@@ -15,4 +15,4 @@
/datum/round_event/fridaythethirteen/announce(fake)
for(var/mob/living/L in player_list)
- to_chat(L, "You are feeling unlucky today.")
+ to_chat(L, "You are feeling unlucky today.")
\ No newline at end of file
diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm
index 88fe218a22..5bad888f17 100644
--- a/code/modules/events/mass_hallucination.dm
+++ b/code/modules/events/mass_hallucination.dm
@@ -10,4 +10,4 @@
/datum/round_event/mass_hallucination/start()
for(var/mob/living/carbon/C in GLOB.alive_mob_list)
- C.hallucination += rand(20, 50)
+ C.hallucination += rand(20, 50)
\ No newline at end of file
diff --git a/code/modules/events/operative.dm b/code/modules/events/operative.dm
index 894ad7e995..e0e3b98776 100644
--- a/code/modules/events/operative.dm
+++ b/code/modules/events/operative.dm
@@ -26,12 +26,10 @@
var/datum/preferences/A = new
A.copy_to(operative)
operative.dna.update_dna_identity()
-
var/datum/mind/Mind = new /datum/mind(selected.key)
Mind.assigned_role = "Lone Operative"
Mind.special_role = "Lone Operative"
Mind.active = 1
-
Mind.transfer_to(operative)
Mind.add_antag_datum(/datum/antagonist/nukeop/lone)
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index ebcade74a3..96f5a3917d 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -56,4 +56,4 @@
temp.prison_open()
else if(istype(O, /obj/machinery/door_timer))
var/obj/machinery/door_timer/temp = O
- temp.timer_end(forced = TRUE)
+ temp.timer_end(forced = TRUE)
\ No newline at end of file
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index 7b66ac553f..d186d2cf88 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -16,5 +16,4 @@
//sound not longer matches the text, but an audible warning is probably good
/datum/round_event/radiation_storm/start()
- SSweather.run_weather("radiation storm",ZLEVEL_STATION_PRIMARY)
- make_maint_all_access()
+ SSweather.run_weather("radiation storm",ZLEVEL_STATION_PRIMARY)
\ No newline at end of file
diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm
index b9815bf7cf..50ed1211c4 100644
--- a/code/modules/events/sentience.dm
+++ b/code/modules/events/sentience.dm
@@ -9,6 +9,7 @@
role_name = "random animal"
var/animals = 1
var/one = "one"
+ fakeable = TRUE
/datum/round_event/ghost_role/sentience/announce(fake)
var/sentience_report = ""
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index ca5de88d58..55984df033 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -135,7 +135,7 @@
new /obj/structure/spider/stickyweb(T)
if(ANTIDOTE_NEEDED)
- var/obj/item/reagent_containers/glass/bottle/virus_type = pick(/obj/item/reagent_containers/glass/bottle/beesease, /obj/item/reagent_containers/glass/bottle/brainrot, /obj/item/reagent_containers/glass/bottle/fluspanish)
+ var/obj/effect/mob_spawn/human/corpse/assistant/infected_assistant = pick(/obj/effect/mob_spawn/human/corpse/assistant/beesease_infection, /obj/effect/mob_spawn/human/corpse/assistant/brainrot_infection, /obj/effect/mob_spawn/human/corpse/assistant/spanishflu_infection)
var/turf/T
for(var/i=0, i<10, i++)
if(prob(15))
@@ -145,7 +145,7 @@
else if(prob(25))
shuttle_spawns.Add(/obj/item/shard)
T = pick_n_take(empty_shuttle_turfs)
- new virus_type(T)
+ new infected_assistant(T)
shuttle_spawns.Add(/obj/structure/closet/crate)
shuttle_spawns.Add(/obj/item/reagent_containers/glass/bottle/pierrot_throat)
shuttle_spawns.Add(/obj/item/reagent_containers/glass/bottle/magnitis)
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 34d3f8a870..a3c625e396 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -35,4 +35,3 @@
spawn_atom_to_turf(spawn_type, vent, 1, FALSE)
vents -= vent
spawncount--
-
diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm
index 46bb254703..a9ae27993d 100644
--- a/code/modules/events/spontaneous_appendicitis.dm
+++ b/code/modules/events/spontaneous_appendicitis.dm
@@ -26,4 +26,4 @@
var/datum/disease/D = new /datum/disease/appendicitis
H.ForceContractDisease(D)
- break
+ break
\ No newline at end of file
diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm
index ec55b35b02..5e91160575 100644
--- a/code/modules/events/vent_clog.dm
+++ b/code/modules/events/vent_clog.dm
@@ -47,4 +47,3 @@
while(cockroaches)
new /mob/living/simple_animal/cockroach(get_turf(vent))
cockroaches--
-
diff --git a/code/modules/events/weightless.dm b/code/modules/events/weightless.dm
index 425ed7ef9f..bb5b3fd15a 100644
--- a/code/modules/events/weightless.dm
+++ b/code/modules/events/weightless.dm
@@ -28,3 +28,5 @@
if(announceWhen >= 0)
command_alert("Artificial gravity arrays are now functioning within normal parameters. Please report any irregularities to your respective head of staff.")
+
+
diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm
index 779fe7fa09..bfbad559e1 100644
--- a/code/modules/flufftext/Dreaming.dm
+++ b/code/modules/flufftext/Dreaming.dm
@@ -1,5 +1,5 @@
-/mob/living/carbon/proc/dream()
- set waitfor = 0
+/mob/living/carbon/proc/dream()
+ set waitfor = 0
var/list/dreams = GLOB.dream_strings.Copy()
for(var/obj/item/bedsheet/sheet in loc)
dreams += sheet.dream_messages
@@ -9,12 +9,12 @@
dreaming++
for(var/i in 1 to dream_images.len)
addtimer(CALLBACK(src, .proc/experience_dream, dream_images[i]), ((i - 1) * rand(30,60)))
- return 1
-
-/mob/living/carbon/proc/handle_dreams()
- if(prob(5) && !dreaming)
- dream()
-
+ return 1
+
+/mob/living/carbon/proc/handle_dreams()
+ if(prob(5) && !dreaming)
+ dream()
+
/mob/living/carbon/proc/experience_dream(dream_image)
dreaming--
if(stat != UNCONSCIOUS || InCritical())
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index e55b7ed183..886d9b4837 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -736,6 +736,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
/datum/hallucination/whispers/New(mob/living/carbon/T, forced = TRUE)
..()
+ var/target_name = target.first_name()
var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\
"[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\
"[pick_list_replacements(HAL_LINES_FILE, "getout")]",\
@@ -769,8 +770,10 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
person = H
people += H
if(person) //Basic talk
+ var/chosen = pick(speak_messages)
+ chosen = replacetext(chosen, "%TARGETNAME%", target_name)
var/image/speech_overlay = image('icons/mob/talk.dmi', person, "default0", layer = ABOVE_MOB_LAYER)
- var/message = target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans(),face_name = TRUE)
+ var/message = target.compose_message(person,understood_language,chosen,null,person.get_spans(),face_name = TRUE)
feedback_details += "Type: Talk, Source: [person.real_name], Message: [message]"
to_chat(target, message)
if(target.client)
@@ -778,11 +781,13 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
sleep(30)
target.client.images.Remove(speech_overlay)
else // Radio talk
+ var/chosen = pick(radio_messages)
+ chosen = replacetext(chosen, "%TARGETNAME%", target_name)
var/list/humans = list()
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
humans += H
person = pick(humans)
- var/message = target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans(),face_name = TRUE)
+ var/message = target.compose_message(person,understood_language,chosen,"[FREQ_COMMON]",person.get_spans(),face_name = TRUE)
feedback_details += "Type: Radio, Source: [person.real_name], Message: [message]"
to_chat(target, message)
qdel(src)
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 005dda29ca..81ebc3d67c 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -232,8 +232,8 @@
icon_state = "absinthebottle"
list_reagents = list("absinthe" = 100)
-/obj/item/reagent_containers/food/drinks/bottle/absinthe/New()
- ..()
+/obj/item/reagent_containers/food/drinks/bottle/absinthe/Initialize()
+ . = ..()
redact()
/obj/item/reagent_containers/food/drinks/bottle/absinthe/proc/redact()
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index 765f118c5e..5e05e85a28 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -9,13 +9,12 @@
var/foodtype = NONE
var/last_check_time
-/obj/item/weapon/reagent_containers/food/Initialize(mapload)
- ..()
+/obj/item/reagent_containers/food/Initialize(mapload)
+ . = ..()
if(!mapload)
- pixel_x = rand(-5, 5) //Randomizes postion slightly.
+ pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
-
/obj/item/reagent_containers/food/proc/checkLiked(var/fraction, mob/M)
if(last_check_time + 50 < world.time)
if(ishuman(M))
diff --git a/code/modules/food_and_drinks/food/customizables.dm b/code/modules/food_and_drinks/food/customizables.dm
index f3460edcaa..7d83788f9d 100644
--- a/code/modules/food_and_drinks/food/customizables.dm
+++ b/code/modules/food_and_drinks/food/customizables.dm
@@ -276,8 +276,8 @@
icon = 'icons/obj/food/soupsalad.dmi'
icon_state = "wishsoup"
-/obj/item/reagent_containers/food/snacks/customizable/soup/New()
- ..()
+/obj/item/reagent_containers/food/snacks/customizable/soup/Initialize()
+ . = ..()
eatverb = pick("slurp","sip","suck","inhale","drink")
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 08b09124d5..b0e2067be0 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -316,10 +316,10 @@
// name = "Xenoburger" //Name that displays in the UI.
// desc = "Smells caustic. Tastes like heresy." //Duh
// icon_state = "xburger" //Refers to an icon in food.dmi
-///obj/item/reagent_containers/food/snacks/xenoburger/New() //Don't mess with this.
-// ..() //Same here.
+///obj/item/reagent_containers/food/snacks/xenoburger/Initialize() //Don't mess with this. | nO I WILL MESS WITH THIS
+// . = ..() //Same here.
// reagents.add_reagent("xenomicrobes", 10) //This is what is in the food item. you may copy/paste
-// reagents.add_reagent("nutriment", 2) // this line of code for all the contents.
+// reagents.add_reagent("nutriment", 2) //this line of code for all the contents.
// bitesize = 3 //This is the amount each bite consumes.
//All foods are distributed among various categories. Use common sense.
diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm
index c7681fe807..9691eee144 100644
--- a/code/modules/food_and_drinks/food/snacks_other.dm
+++ b/code/modules/food_and_drinks/food/snacks_other.dm
@@ -67,8 +67,8 @@
tastes = list("popcorn" = 3, "butter" = 1)
foodtype = JUNKFOOD
-/obj/item/reagent_containers/food/snacks/popcorn/New()
- ..()
+/obj/item/reagent_containers/food/snacks/popcorn/Initialize()
+ . = ..()
eatverb = pick("bite","crunch","nibble","gnaw","gobble","chomp")
/obj/item/reagent_containers/food/snacks/loadedbakedpotato
@@ -448,8 +448,8 @@
tastes = list("candy" = 1)
foodtype = JUNKFOOD | SUGAR
-/obj/item/reagent_containers/food/snacks/lollipop/New()
- ..()
+/obj/item/reagent_containers/food/snacks/lollipop/Initialize()
+ . = ..()
head = mutable_appearance('icons/obj/lollipop.dmi', "lollipop_head")
change_head_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
@@ -467,8 +467,8 @@
/obj/item/reagent_containers/food/snacks/lollipop/cyborg
var/spamchecking = TRUE
-/obj/item/reagent_containers/food/snacks/lollipop/cyborg/New()
- ..()
+/obj/item/reagent_containers/food/snacks/lollipop/cyborg/Initialize()
+ . = ..()
addtimer(CALLBACK(src, .proc/spamcheck), 1200)
/obj/item/reagent_containers/food/snacks/lollipop/cyborg/equipped(mob/living/user, slot)
@@ -488,15 +488,15 @@
tastes = list("candy")
foodtype = JUNKFOOD
-/obj/item/reagent_containers/food/snacks/gumball/New()
- ..()
+/obj/item/reagent_containers/food/snacks/gumball/Initialize()
+ . = ..()
color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
/obj/item/reagent_containers/food/snacks/gumball/cyborg
var/spamchecking = TRUE
-/obj/item/reagent_containers/food/snacks/gumball/cyborg/New()
- ..()
+/obj/item/reagent_containers/food/snacks/gumball/cyborg/Initialize()
+ . = ..()
addtimer(CALLBACK(src, .proc/spamcheck), 1200)
/obj/item/reagent_containers/food/snacks/gumball/cyborg/equipped(mob/living/user, slot)
diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm
index 284784484f..b7df203e30 100644
--- a/code/modules/food_and_drinks/food/snacks_pastry.dm
+++ b/code/modules/food_and_drinks/food/snacks_pastry.dm
@@ -350,3 +350,113 @@
filling_color = "#F2CE91"
tastes = list("pastry" = 1, "sweetness" = 1)
foodtype = GRAIN
+
+#define PANCAKE_MAX_STACK 10
+
+/obj/item/reagent_containers/food/snacks/pancakes
+ name = "pancake"
+ desc = "A fluffy pancake. The softer, superior relative of the waffle."
+ icon_state = "pancakes_1"
+ item_state = "pancakes"
+ bonus_reagents = list("vitamin" = 1)
+ list_reagents = list("nutriment" = 4, "vitamin" = 1)
+ filling_color = "#D2691E"
+ tastes = list("pancakes" = 1)
+ foodtype = GRAIN | SUGAR
+
+/obj/item/reagent_containers/food/snacks/pancakes/blueberry
+ name = "blueberry pancake"
+ desc = "A fluffy and delicious blueberry pancake."
+ icon_state = "bbpancakes_1"
+ item_state = "bbpancakes"
+ bonus_reagents = list("vitamin" = 2)
+ list_reagents = list("nutriment" = 6, "vitamin" = 3)
+ tastes = list("pancakes" = 1, "blueberries" = 1)
+
+/obj/item/reagent_containers/food/snacks/pancakes/chocolatechip
+ name = "chocolate chip pancake"
+ desc = "A fluffy and delicious chocolate chip pancake."
+ icon_state = "ccpancakes_1"
+ item_state = "ccpancakes"
+ bonus_reagents = list("vitamin" = 2)
+ list_reagents = list("nutriment" = 6, "vitamin" = 3)
+ tastes = list("pancakes" = 1, "chocolate" = 1)
+
+/obj/item/reagent_containers/food/snacks/pancakes/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/reagent_containers/food/snacks/pancakes/update_icon()
+ if(contents.len)
+ name = "stack of pancakes"
+ else
+ name = initial(name)
+ if(contents.len < our_overlays.len)
+ cut_overlay(our_overlays[our_overlays.len])
+
+/obj/item/reagent_containers/food/snacks/pancakes/examine(mob/user)
+ var/ingredients_listed = ""
+ var/pancakeCount = contents.len
+ switch(pancakeCount)
+ if(0)
+ desc = initial(desc)
+ if(1 to 2)
+ desc = "A stack of fluffy pancakes."
+ if(3 to 6)
+ desc = "A fat stack of fluffy pancakes!"
+ if(7 to 9)
+ desc = "A grand tower of fluffy, delicious pancakes!"
+ if(PANCAKE_MAX_STACK to INFINITY)
+ desc = "A massive towering spire of fluffy, delicious pancakes. It looks like it could tumble over!"
+ var/originalBites = bitecount
+ if (pancakeCount)
+ var/obj/item/reagent_containers/food/snacks/S = contents[pancakeCount]
+ bitecount = S.bitecount
+ ..()
+ if (pancakeCount)
+ for(var/obj/item/reagent_containers/food/snacks/pancakes/ING in contents)
+ ingredients_listed += "[ING.name], "
+ to_chat(user, "It contains [contents.len?"[ingredients_listed]":"no ingredient, "]on top of a [initial(name)].")
+ bitecount = originalBites
+
+/obj/item/reagent_containers/food/snacks/pancakes/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/reagent_containers/food/snacks/pancakes/))
+ var/obj/item/reagent_containers/food/snacks/pancakes/P = I
+ if((contents.len >= PANCAKE_MAX_STACK) || ((P.contents.len + contents.len) > PANCAKE_MAX_STACK) || (reagents.total_volume >= volume))
+ to_chat(user, "You can't add that many pancakes to [src]!")
+ else
+ if(!user.transferItemToLoc(I, src))
+ return
+ to_chat(user, "You add the [I] to the [name].")
+ P.name = initial(P.name)
+ contents += P
+ update_overlays(P)
+ if (P.contents.len)
+ for(var/V in P.contents)
+ P = V
+ P.name = initial(P.name)
+ contents += P
+ update_overlays(P)
+ P = I
+ clearlist(P.contents)
+ return
+ else if(contents.len)
+ var/obj/O = contents[contents.len]
+ return O.attackby(I, user, params)
+ ..()
+
+/obj/item/reagent_containers/food/snacks/pancakes/update_overlays(obj/item/reagent_containers/food/snacks/P)
+ var/mutable_appearance/pancake = mutable_appearance(icon, "[P.item_state]_[rand(1,3)]")
+ pancake.pixel_x = rand(-1,1)
+ pancake.pixel_y = 3 * contents.len - 1
+ add_overlay(pancake)
+ update_icon()
+
+/obj/item/reagent_containers/food/snacks/pancakes/attack(mob/M, mob/user, def_zone, stacked = TRUE)
+ if(user.a_intent == INTENT_HARM || !contents.len || !stacked)
+ return ..()
+ var/obj/item/O = contents[contents.len]
+ . = O.attack(M, user, def_zone, FALSE)
+ update_icon()
+
+#undef PANCAKE_MAX_STACK
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm
index 977bd60da1..4ce942aadf 100644
--- a/code/modules/food_and_drinks/food/snacks_pie.dm
+++ b/code/modules/food_and_drinks/food/snacks_pie.dm
@@ -27,6 +27,7 @@
list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2)
tastes = list("pie" = 1)
foodtype = GRAIN | DAIRY | SUGAR
+ var/stunning = TRUE
/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom)
. = ..()
@@ -46,15 +47,18 @@
creamoverlay.icon_state = "creampie_lizard"
else
creamoverlay.icon_state = "creampie_human"
- H.Knockdown(20) //splat!
+ if(stunning)
+ H.Knockdown(20) //splat!
H.adjust_blurriness(1)
H.visible_message("[H] is creamed by [src]!", "You've been creamed by [src]!")
playsound(H, "desceration", 50, TRUE)
- if (!H.creamed) // one layer at a time
+ if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
H.creamed = TRUE
qdel(src)
+/obj/item/reagent_containers/food/snacks/pie/cream/nostun
+ stunning = FALSE
/obj/item/reagent_containers/food/snacks/pie/berryclafoutis
name = "berry clafoutis"
@@ -112,13 +116,13 @@
foodtype = GRAIN | VEGETABLES
-/obj/item/reagent_containers/food/snacks/pie/plump_pie/New()
+/obj/item/reagent_containers/food/snacks/pie/plump_pie/Initialize()
+ . = ..()
var/fey = prob(10)
if(fey)
name = "exceptional plump pie"
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!"
bonus_reagents = list("nutriment" = 1, "omnizine" = 5, "vitamin" = 4)
- ..()
if(fey)
reagents.add_reagent("omnizine", 5)
diff --git a/code/modules/food_and_drinks/food/snacks_salad.dm b/code/modules/food_and_drinks/food/snacks_salad.dm
index 4cb44093a7..65ff4d2eb9 100644
--- a/code/modules/food_and_drinks/food/snacks_salad.dm
+++ b/code/modules/food_and_drinks/food/snacks_salad.dm
@@ -9,9 +9,9 @@
tastes = list("leaves" = 1)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/salad/New()
- ..()
- eatverb = pick("crunch","devour","nibble","gnaw","gobble","chomp")
+/obj/item/reagent_containers/food/snacks/salad/Initialize()
+ . = ..()
+ eatverb = pick("crunch","devour","nibble","gnaw","gobble","chomp") //who the fuck gnaws and devours on a salad
/obj/item/reagent_containers/food/snacks/salad/aesirsalad
name = "\improper Aesir salad"
diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm
index 422e35b849..3e3fc9440a 100644
--- a/code/modules/food_and_drinks/food/snacks_soup.dm
+++ b/code/modules/food_and_drinks/food/snacks_soup.dm
@@ -8,8 +8,8 @@
tastes = list("tasteless soup" = 1)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/soup/New()
- ..()
+/obj/item/reagent_containers/food/snacks/soup/Initialize()
+ . = ..()
eatverb = pick("slurp","sip","suck","inhale","drink")
/obj/item/reagent_containers/food/snacks/soup/wish
@@ -19,12 +19,12 @@
list_reagents = list("water" = 10)
tastes = list("wishes" = 1)
-/obj/item/reagent_containers/food/snacks/soup/wish/New()
+/obj/item/reagent_containers/food/snacks/soup/wish/Initialize()
+ . = ..()
var/wish_true = prob(25)
if(wish_true)
desc = "A wish come true!"
bonus_reagents = list("nutriment" = 9, "vitamin" = 1)
- ..()
if(wish_true)
reagents.add_reagent("nutriment", 9)
reagents.add_reagent("vitamin", 1)
@@ -99,10 +99,10 @@
list_reagents = list("nutriment" = 6)
tastes = list("chaos" = 1)
-/obj/item/reagent_containers/food/snacks/soup/mystery/New()
+/obj/item/reagent_containers/food/snacks/soup/mystery/Initialize()
+ . = ..()
extra_reagent = pick("capsaicin", "frostoil", "omnizine", "banana", "blood", "slimejelly", "toxin", "banana", "carbon", "oculine")
bonus_reagents = list("[extra_reagent]" = 5, "nutriment" = 6)
- ..()
reagents.add_reagent("[extra_reagent]", 5)
/obj/item/reagent_containers/food/snacks/soup/hotchili
@@ -173,8 +173,8 @@
bonus_reagents = list("nutriment" = 1, "vitamin" = 5)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/soup/beet/New()
- ..()
+/obj/item/reagent_containers/food/snacks/soup/beet/Initialize()
+ . = ..()
name = pick("borsch","bortsch","borstch","borsh","borshch","borscht")
tastes = list(name = 1)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
index 372c085adb..99a3de90e1 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
@@ -1,4 +1,3 @@
-
/obj/machinery/gibber
name = "gibber"
desc = "The name isn't descriptive enough?"
@@ -12,10 +11,10 @@
circuit = /obj/item/circuitboard/machine/gibber
var/operating = FALSE //Is it on?
- var/dirty = 0 // Does it need cleaning?
+ var/dirty = FALSE // Does it need cleaning?
var/gibtime = 40 // Time from starting until meat appears
var/meat_produced = 0
- var/ignore_clothing = 0
+ var/ignore_clothing = FALSE
/obj/machinery/gibber/Initialize()
@@ -30,7 +29,7 @@
gib_time -= 5 * M.rating
gibtime = gib_time
if(M.rating >= 2)
- ignore_clothing = 1
+ ignore_clothing = TRUE
/obj/machinery/gibber/update_icon()
cut_overlays()
@@ -61,6 +60,10 @@
to_chat(user, "It's locked and running.")
return
+ if(!anchored)
+ to_chat(user, "[src] cannot be used unless bolted to the ground.")
+ return
+
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
var/mob/living/L = user.pulling
if(!iscarbon(L))
@@ -70,12 +73,17 @@
if(C.buckled ||C.has_buckled_mobs())
to_chat(user, "[C] is attached to something!")
return
- if(C.abiotic(1) && !ignore_clothing)
- to_chat(user, "Subject may not have abiotic items on.")
- return
+
+ if(!ignore_clothing)
+ for(var/obj/item/I in C.held_items + C.get_equipped_items())
+ if(!(I.flags_1 & NODROP_1))
+ to_chat(user, "Subject may not have abiotic items on.")
+ return
user.visible_message("[user] starts to put [C] into the gibber!")
- src.add_fingerprint(user)
+
+ add_fingerprint(user)
+
if(do_after(user, gibtime, target = src))
if(C && user.pulling == C && !C.buckled && !C.has_buckled_mobs() && !occupant)
user.visible_message("[user] stuffs [C] into the gibber!")
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index 6ef8e5e4e9..b1c1a8495c 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -28,9 +28,10 @@
var/const/BOMB_TIMER_MIN = 1
var/const/BOMB_TIMER_MAX = 10
-/obj/item/pizzabox/New()
+/obj/item/pizzabox/Initialize()
+ . = ..()
update_icon()
- ..()
+
/obj/item/pizzabox/Destroy()
unprocess()
@@ -257,29 +258,31 @@
wires = null
update_icon()
-/obj/item/pizzabox/bomb/New()
+/obj/item/pizzabox/bomb/Initialize()
+ . = ..()
var/randompizza = pick(subtypesof(/obj/item/reagent_containers/food/snacks/pizza))
pizza = new randompizza(src)
bomb = new(src)
wires = new /datum/wires/explosive/pizza(src)
- ..()
-/obj/item/pizzabox/margherita/New()
+/obj/item/pizzabox/margherita/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/margherita(src)
boxtag = "Margherita Deluxe"
- ..()
-/obj/item/pizzabox/vegetable/New()
+
+/obj/item/pizzabox/vegetable/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/vegetable(src)
boxtag = "Gourmet Vegatable"
- ..()
-/obj/item/pizzabox/mushroom/New()
+
+/obj/item/pizzabox/mushroom/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/mushroom(src)
boxtag = "Mushroom Special"
- ..()
-/obj/item/pizzabox/meat/New()
+/obj/item/pizzabox/meat/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/meat(src)
boxtag = "Meatlover's Supreme"
- ..()
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index 041a58c467..a75510ae9a 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -50,7 +50,7 @@
result = /obj/item/reagent_containers/food/snacks/donut/jelly/slimejelly
subcategory = CAT_PASTRY
-////////////////////////////////////////////////WAFFLES////////////////////////////////////////////////
+////////////////////////////////////////////////WAFFLES AND PANCAKES////////////////////////////////////////////////
/datum/crafting_recipe/food/waffles
time = 15
@@ -90,6 +90,33 @@
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
subcategory = CAT_PASTRY
+/datum/crafting_recipe/food/pancakes
+ name = "Pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes
+ subcategory = CAT_PASTRY
+
+/datum/crafting_recipe/food/bbpancakes
+ name = "Blueberry pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/reagent_containers/food/snacks/grown/berries = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes/blueberry
+ subcategory = CAT_PASTRY
+
+/datum/crafting_recipe/food/ccpancakes
+ name = "Chocolate chip pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/reagent_containers/food/snacks/chocolatebar = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes/chocolatechip
+ subcategory = CAT_PASTRY
+
+
////////////////////////////////////////////////DONKPOCCKETS////////////////////////////////////////////////
/datum/crafting_recipe/food/donkpocket
diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm
index bceaf6d7dd..e7bf3ea9d7 100644
--- a/code/modules/games/cards.dm
+++ b/code/modules/games/cards.dm
@@ -16,7 +16,7 @@
var/list/cards = list()
-/obj/item/deck/New()
+/obj/item/deck/Initialize()
. = ..()
var/cardcolor
diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm
index 0832f372c8..10b1fcd80d 100644
--- a/code/modules/goonchat/browserOutput.dm
+++ b/code/modules/goonchat/browserOutput.dm
@@ -179,6 +179,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
//Global chat procs
+
/proc/to_chat(target, message)
if(!target)
return
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index c72f26a4e7..4ea8c85b16 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -313,7 +313,6 @@ h1.alert, h2.alert {color: #000000;}
.green {color: #03ff39;}
.shadowling {color: #3b2769;}
.cult {color: #960000;}
-.cultitalic {color: #960000; font-style: italic;}
.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
.narsie {color: #960000; font-weight: bold; font-size: 120px;}
.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
@@ -322,7 +321,6 @@ h1.alert, h2.alert {color: #000000;}
.hierophant_warning {color: #660099; font-style: italic;}
.purple {color: #5e2d79;}
.holoparasite {color: #35333a;}
-.holoparasitebold {color: #35333a; font-weight: bold;}
.revennotice {color: #1d2953;}
.revenboldnotice {color: #1d2953; font-weight: bold;}
@@ -331,10 +329,10 @@ h1.alert, h2.alert {color: #000000;}
.revenwarning {color: #760fbb; font-style: italic;}
.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
.umbra {color: #5000A0;}
-.umbra_bold {color: #5000A0; font-weight: bold;}
-.umbra_italics {color: #5000A0; font-style: italic;}
.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px;}
+.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
+
+.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
.brass {color: #BE8700;}
.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
@@ -343,7 +341,6 @@ h1.alert, h2.alert {color: #000000;}
.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
.alloy {color: #42474D;}
.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.large_alloy {color: #42474D; font-size: 24px;}
.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_small {color: #42474D;}
@@ -366,7 +363,6 @@ h1.alert, h2.alert {color: #000000;}
.alien {color: #543354;}
.noticealien {color: #00c000;}
.alertalien {color: #00c000; font-weight: bold;}
-.borer {color: #543354; font-style: italic;}
.changeling {color: #800080; font-style: italic;}
.spider {color: #4d004d;}
@@ -381,11 +377,13 @@ h1.alert, h2.alert {color: #000000;}
.small {font-size: 8px;}
.big {font-size: 24px;}
.reallybig {font-size: 32px;}
+.extremelybig {font-size: 40px;}
.greentext {color: #00FF00; font-size: 24px;}
.redtext {color: #FF0000; font-size: 24px;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
+.icon {height: 1em; width: auto;}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 16px;}
@@ -397,8 +395,8 @@ h1.alert, h2.alert {color: #000000;}
.swarmer {color: #2C75FF;}
.resonate {color: #298F85;}
-.love {color: #FF69Bf;}
-.lovebold {color: #FF69Bf; font-weight: bold;}
+.monkeyhive {color: #774704;}
+.monkeylead {color: #774704; font-size: 2;}
.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
.connectionClosed.restored {background: green;}
diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm
index 66d92df569..9c1fd87cac 100644
--- a/code/modules/holiday/easter.dm
+++ b/code/modules/holiday/easter.dm
@@ -109,8 +109,8 @@
/obj/item/reagent_containers/food/snacks/egg/loaded
containsPrize = TRUE
-/obj/item/reagent_containers/food/snacks/egg/loaded/New()
- ..()
+/obj/item/reagent_containers/food/snacks/egg/loaded/Initialize()
+ . = ..()
var/eggcolor = pick("blue","green","mime","orange","purple","rainbow","red","yellow")
icon_state = "egg-[eggcolor]"
item_color = "[eggcolor]"
diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm
index 2b24f02a44..f4734d9506 100644
--- a/code/modules/holiday/holidays.dm
+++ b/code/modules/holiday/holidays.dm
@@ -9,6 +9,8 @@
var/begin_weekday = FALSE //If set to a weekday, then this will trigger the holiday on the above week
var/always_celebrate = FALSE // for christmas neverending, or testing.
+ var/obj/item/drone_hat //If this is defined, drones without a default hat will spawn with this one during the holiday; check drones_as_items.dm to see this used
+
// This proc gets run before the game starts when the holiday is activated. Do festive shit here.
/datum/holiday/proc/celebrate()
return
@@ -172,11 +174,13 @@
name = "Labor Day"
begin_day = 1
begin_month = MAY
+ drone_hat = /obj/item/clothing/head/hardhat
/datum/holiday/firefighter
name = "Firefighter's Day"
begin_day = 4
begin_month = MAY
+ drone_hat = /obj/item/clothing/head/hardhat/red
/datum/holiday/firefighter/getStationPrefix()
return pick("Burning","Blazing","Plasma","Fire")
@@ -190,6 +194,7 @@
name = "Doctor's Day"
begin_day = 1
begin_month = JULY
+ drone_hat = /obj/item/clothing/head/nursehat
/datum/holiday/UFO
name = "UFO Day"
@@ -221,6 +226,7 @@
name = "Talk-Like-a-Pirate Day"
begin_day = 19
begin_month = SEPTEMBER
+ drone_hat = /obj/item/clothing/head/pirate
/datum/holiday/pirate/greet()
return "Ye be talkin' like a pirate today or else ye'r walkin' tha plank, matey!"
@@ -321,6 +327,7 @@
begin_week = 4
begin_month = NOVEMBER
begin_weekday = THURSDAY
+ drone_hat = /obj/item/clothing/head/that //This is the closest we can get to a pilgrim's hat
/datum/holiday/thanksgiving/canada
name = "Thanksgiving in Canada"
@@ -384,12 +391,14 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
name = "Mayan Doomsday Anniversary"
begin_day = 21
begin_month = DECEMBER
+ drone_hat = /obj/item/clothing/mask/rat/tribal
/datum/holiday/xmas
name = CHRISTMAS
begin_day = 22
begin_month = DECEMBER
end_day = 27
+ drone_hat = /obj/item/clothing/head/santa
/datum/holiday/xmas/greet()
return "Have a merry Christmas!"
@@ -410,6 +419,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
begin_day = 1
begin_month = DECEMBER
end_day = 31
+ drone_hat = /obj/item/clothing/head/santa
/datum/holiday/festive_season/greet()
return "Have a nice festive season!"
@@ -432,6 +442,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
/datum/holiday/easter
name = EASTER
+ drone_hat = /obj/item/clothing/head/rabbitears
var/const/days_early = 1 //to make editing the holiday easier
var/const/days_extra = 1
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index 6a8a720366..1dcab21e16 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -25,13 +25,13 @@
armour_penetration = 50
var/active = 0
-/obj/item/holo/esword/green/New()
- ..()
+/obj/item/holo/esword/green/Initialize()
+ . = ..()
item_color = "green"
-/obj/item/holo/esword/red/New()
- ..()
+/obj/item/holo/esword/red/Initialize()
+ . = ..()
item_color = "red"
/obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
@@ -42,9 +42,9 @@
/obj/item/holo/esword/attack(target as mob, mob/user as mob)
..()
-/obj/item/holo/esword/New()
+/obj/item/holo/esword/Initialize()
+ . = ..()
item_color = pick("red","blue","green","purple")
- ..()
/obj/item/holo/esword/attack_self(mob/living/user as mob)
active = !active
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index d4269013f7..cf12ccb3ce 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -37,8 +37,8 @@
var/bee_resources = 0
-/obj/structure/beebox/New()
- ..()
+/obj/structure/beebox/Initialize()
+ . = ..()
START_PROCESSING(SSobj, src)
@@ -55,8 +55,8 @@
var/random_reagent = FALSE
-/obj/structure/beebox/premade/New()
- ..()
+/obj/structure/beebox/premade/Initialize()
+ . = ..()
icon_state = "beebox"
var/datum/reagent/R = null
@@ -152,6 +152,7 @@
else
to_chat(user, "There's no room for any more frames in the apiary!")
return
+
if(istype(I, /obj/item/wrench))
if(default_unfasten_wrench(user, I, time = 20))
return
diff --git a/code/modules/hydroponics/beekeeping/honeycomb.dm b/code/modules/hydroponics/beekeeping/honeycomb.dm
index 8b9d641eac..e7faff0209 100644
--- a/code/modules/hydroponics/beekeeping/honeycomb.dm
+++ b/code/modules/hydroponics/beekeeping/honeycomb.dm
@@ -13,8 +13,8 @@
grind_results = list()
var/honey_color = ""
-/obj/item/reagent_containers/honeycomb/New()
- ..()
+/obj/item/reagent_containers/honeycomb/Initialize()
+ . = ..()
pixel_x = rand(8,-8)
pixel_y = rand(8,-8)
update_icon()
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index bb349b7d19..fa1e25a6d4 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -422,8 +422,8 @@
var/read_only = 0 //Well, it's still a floppy disk
unique_rename = 1
-/obj/item/disk/plantgene/New()
- ..()
+/obj/item/disk/plantgene/Initialize()
+ . = ..()
add_overlay("datadisk_gene")
src.pixel_x = rand(-5, 5)
src.pixel_y = rand(-5, 5)
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index 15456c1e34..dadf077c8a 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -146,7 +146,7 @@
/obj/item/reagent_containers/food/snacks/grown/on_grind()
var/nutriment = reagents.get_reagent_amount("nutriment")
- if(grind_results.len)
+ if(grind_results&&grind_results.len)
for(var/i in 1 to grind_results.len)
grind_results[grind_results[i]] = nutriment
reagents.del_reagent("nutriment")
@@ -154,7 +154,7 @@
/obj/item/reagent_containers/food/snacks/grown/on_juice()
var/nutriment = reagents.get_reagent_amount("nutriment")
- if(juice_results.len)
+ if(juice_results&&juice_results.len)
for(var/i in 1 to juice_results.len)
juice_results[juice_results[i]] = nutriment
reagents.del_reagent("nutriment")
diff --git a/code/modules/hydroponics/grown/random.dm b/code/modules/hydroponics/grown/random.dm
index 8f25eff215..04b3ff29fa 100644
--- a/code/modules/hydroponics/grown/random.dm
+++ b/code/modules/hydroponics/grown/random.dm
@@ -12,9 +12,9 @@
icon_harvest = "xpod-harvest"
growthstages = 4
-/obj/item/seeds/random/New()
+/obj/item/seeds/random/Initialize()
+ . = ..()
randomize_stats()
- ..()
if(prob(60))
add_random_reagents(1, 3)
if(prob(50))
diff --git a/code/modules/hydroponics/sample.dm b/code/modules/hydroponics/sample.dm
index 52c2e1052f..fff4c646ac 100644
--- a/code/modules/hydroponics/sample.dm
+++ b/code/modules/hydroponics/sample.dm
@@ -5,8 +5,8 @@
yield = -1
var/sample_color = "#FFFFFF"
-/obj/item/seeds/sample/New()
- ..()
+/obj/item/seeds/sample/Initialize()
+ . = ..()
if(sample_color)
var/mutable_appearance/filling = mutable_appearance(icon, "sample-filling")
filling.color = sample_color
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 56f80c548d..d956055c41 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -35,8 +35,8 @@
var/weed_rate = 1 //If the chance below passes, then this many weeds sprout during growth
var/weed_chance = 5 //Percentage chance per tray update to grow weeds
-/obj/item/seeds/New(loc, nogenes = 0)
- ..()
+/obj/item/seeds/Initialize(loc, nogenes = 0)
+ . = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm
index 805cf787f7..637c3bfcee 100644
--- a/code/modules/integrated_electronics/core/assemblies.dm
+++ b/code/modules/integrated_electronics/core/assemblies.dm
@@ -20,6 +20,8 @@
var/charge_tick = FALSE
var/charge_delay = 4
var/use_cyborg_cell = TRUE
+ max_integrity = 50
+ armor = list(melee = 50, bullet = 70, laser = 70, energy = 100, bomb = 10, bio = 100, rad = 100, fire = 0, acid = 0)
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
@@ -30,8 +32,6 @@
START_PROCESSING(SScircuit, src)
materials[MAT_METAL] = round((max_complexity + max_components) / 4) * SScircuit.cost_multiplier
-
-
/obj/item/device/electronic_assembly/Destroy()
STOP_PROCESSING(SScircuit, src)
return ..()
@@ -273,22 +273,9 @@
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
- for(var/obj/item/integrated_circuit/input/sensor/S in assembly_components)
- if(!proximity)
- if(istype(S,/obj/item/integrated_circuit/input/sensor/ranged)||(!user))
- if(user.client)
- if(!(target in view(user.client)))
- continue
- else
- if(!(target in view(user)))
- continue
- else
- continue
- S.set_pin_data(IC_OUTPUT, 1, WEAKREF(target))
- S.check_then_do_work()
- S.scan(target)
-
- visible_message(" [user] waves [src] around [target].")
+ for(var/obj/item/integrated_circuit/input/S in assembly_components)
+ if(S.sense(target,user,proximity))
+ visible_message(" [user] waves [src] around [target].")
/obj/item/device/electronic_assembly/screwdriver_act(mob/living/user, obj/item/S)
@@ -326,8 +313,11 @@
interact(user)
return TRUE
else
+ for(var/obj/item/integrated_circuit/input/S in assembly_components)
+ S.attackby_react(I,user,user.a_intent)
return ..()
+
/obj/item/device/electronic_assembly/attack_self(mob/user)
if(!check_interactivity(user))
return
@@ -391,7 +381,6 @@
/obj/item/device/electronic_assembly/proc/get_object()
return src
-
// Returns the location to be used for dropping items.
// Same as the regular drop_location(), but with checks being run on acting_object if necessary.
/obj/item/integrated_circuit/drop_location()
@@ -406,6 +395,7 @@
/obj/item/device/electronic_assembly/default //The /default electronic_assemblys are to allow the introduction of the new naming scheme without breaking old saves.
name = "type-a electronic assembly"
+
/obj/item/device/electronic_assembly/calc
name = "type-b electronic assembly"
icon_state = "setup_small_calc"
@@ -507,4 +497,4 @@
/obj/item/device/electronic_assembly/drone/arms
name = "type-b electronic drone"
icon_state = "setup_drone_arms"
- desc = "It's a case, for building mobile electronics with. This one is armed and dangerous."
\ No newline at end of file
+ desc = "It's a case, for building mobile electronics with. This one is armed and dangerous."
diff --git a/code/modules/integrated_electronics/core/debugger.dm b/code/modules/integrated_electronics/core/debugger.dm
index ac6f5c1a1e..666fcf00d6 100644
--- a/code/modules/integrated_electronics/core/debugger.dm
+++ b/code/modules/integrated_electronics/core/debugger.dm
@@ -56,7 +56,7 @@
data_to_show = A.name
to_chat(user, "You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].")
else if(io.io_type == PULSE_CHANNEL)
- io.holder.check_then_do_work(ignore_power = TRUE)
+ io.holder.check_then_do_work(io.ord,ignore_power = TRUE)
to_chat(user, "You pulse \the [io.holder]'s [io].")
io.holder.interact(user) // This is to update the UI.
diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm
index e84823f201..773c4f0684 100644
--- a/code/modules/integrated_electronics/core/helpers.dm
+++ b/code/modules/integrated_electronics/core/helpers.dm
@@ -15,9 +15,9 @@
io_type_override = io_list_copy[io_entry]
if(io_type_override)
- io_list.Add(new io_type_override(src, io_entry, default_data, pin_type))
+ io_list.Add(new io_type_override(src, io_entry, default_data, pin_type,i))
else
- io_list.Add(new io_type(src, io_entry, default_data, pin_type))
+ io_list.Add(new io_type(src, io_entry, default_data, pin_type,i))
/obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data)
diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm
index 069ca4245c..0c1a2fdad5 100644
--- a/code/modules/integrated_electronics/core/integrated_circuit.dm
+++ b/code/modules/integrated_electronics/core/integrated_circuit.dm
@@ -58,6 +58,12 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
+/obj/item/integrated_circuit/proc/attackby_react(var/atom/movable/A,mob/user)
+ return
+
+/obj/item/integrated_circuit/proc/sense(var/atom/movable/A,mob/user,prox)
+ return
+
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
@@ -291,17 +297,18 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE // Battery has enough.
return FALSE // Not enough power.
-/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE)
+/obj/item/integrated_circuit/proc/check_then_do_work(ord,var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
- return
+ return FALSE
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
- return
+ return FALSE
next_use = world.time + cooldown_per_use
- do_work()
+ do_work(ord)
+ return TRUE
-/obj/item/integrated_circuit/proc/do_work()
+/obj/item/integrated_circuit/proc/do_work(ord)
return
/obj/item/integrated_circuit/proc/disconnect_all()
@@ -369,4 +376,3 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE
return FALSE
-
diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm
index bff96b713c..528281c3b7 100644
--- a/code/modules/integrated_electronics/core/pins.dm
+++ b/code/modules/integrated_electronics/core/pins.dm
@@ -25,14 +25,16 @@ D [1]/ ||
var/list/linked = list()
var/io_type = DATA_CHANNEL
var/pin_type // IC_INPUT, IC_OUTPUT, IC_ACTIVATOR - used in saving assembly wiring
+ var/ord
-
-/datum/integrated_io/New(loc, _name, _data, _pin_type)
+/datum/integrated_io/New(loc, _name, _data, _pin_type,_ord)
name = _name
if(_data)
data = _data
if(_pin_type)
pin_type = _pin_type
+ if(_ord)
+ ord = _ord
holder = loc
@@ -148,7 +150,7 @@ D [1]/ ||
/datum/integrated_io/activate/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
- io.holder.check_then_do_work()
+ io.holder.check_then_do_work(io.ord)
/datum/integrated_io/proc/pull_data()
for(var/k in 1 to linked.len)
@@ -207,7 +209,7 @@ D [1]/ ||
write_data_to_pin(new_data)
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
- holder.check_then_do_work(ignore_power = TRUE)
+ holder.check_then_do_work(ord,ignore_power = TRUE)
to_chat(user, "You pulse \the [holder]'s [src] pin.")
/datum/integrated_io/activate
diff --git a/code/modules/integrated_electronics/core/special_pins/index_pin.dm b/code/modules/integrated_electronics/core/special_pins/index_pin.dm
index 51b12a0f3a..06267eec61 100644
--- a/code/modules/integrated_electronics/core/special_pins/index_pin.dm
+++ b/code/modules/integrated_electronics/core/special_pins/index_pin.dm
@@ -1,4 +1,4 @@
-// These pins can only contain integer numbers between 1 and IC_MAX_LIST_LENGTH. Null is not allowed.
+// These pins can only contain integer numbers between 0 and IC_MAX_LIST_LENGTH. Null is allowed.
/datum/integrated_io/index
name = "index pin"
data = 1
@@ -11,10 +11,10 @@
/datum/integrated_io/index/write_data_to_pin(new_data)
if(isnull(new_data))
- new_data = 1
+ new_data = 0
if(isnum(new_data))
- data = CLAMP(round(new_data), 1, IC_MAX_LIST_LENGTH)
+ data = CLAMP(round(new_data), 0, IC_MAX_LIST_LENGTH)
holder.on_data_written()
/datum/integrated_io/index/display_pin_type()
diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm
index 7dec779f83..e491a34a69 100644
--- a/code/modules/integrated_electronics/subtypes/arithmetic.dm
+++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm
@@ -30,10 +30,9 @@
/obj/item/integrated_circuit/arithmetic/addition/do_work()
var/result = 0
for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- I.pull_data()
- if(isnum(I.data))
- result = result + I.data
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I))
+ result += I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -56,13 +55,10 @@
return
var/result = A.data
- for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- if(I == A)
- continue
- I.pull_data()
- if(isnum(I.data))
- result = result - I.data
+ for(var/k in 2 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I))
+ result -= I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -85,13 +81,10 @@
if(!isnum(A.data))
return
var/result = A.data
- for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- if(I == A)
- continue
- I.pull_data()
- if(isnum(I.data))
- result = result * I.data
+ for(var/k in 2 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I))
+ result *= I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -114,13 +107,12 @@
return
var/result = A.data
- for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- if(I == A)
- continue
- I.pull_data()
- if(isnum(I.data) && I.data != 0) //No runtimes here.
- result = result / I.data
+
+ for(var/k in 2 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I) && (I != 0))
+ result /= I
+
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -228,12 +220,11 @@
/obj/item/integrated_circuit/arithmetic/average/do_work()
var/result = 0
var/inputs_used = 0
- for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- I.pull_data()
- if(isnum(I.data))
+ for(var/k in 2 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I))
inputs_used++
- result = result + I.data
+ result += I
if(inputs_used)
result = result / inputs_used
@@ -288,11 +279,10 @@
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
var/result = 0
- for(var/k in 1 to inputs.len)
- var/datum/integrated_io/I = inputs[k]
- I.pull_data()
- if(isnum(I.data))
- result = sqrt(I.data)
+ for(var/k in 2 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(isnum(I))
+ result += sqrt(I)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm
index d622ea8ca9..cd9306d0da 100644
--- a/code/modules/integrated_electronics/subtypes/converters.dm
+++ b/code/modules/integrated_electronics/subtypes/converters.dm
@@ -160,10 +160,10 @@
/obj/item/integrated_circuit/converter/concatenator/do_work()
var/result = null
- for(var/datum/integrated_io/I in inputs)
- I.pull_data()
- if(!isnull(I.data))
- result = result + I.data
+ for(var/k in 1 to inputs.len)
+ var/I = get_pin_data(IC_INPUT, k)
+ if(!isnull(I))
+ result = result + I
set_pin_data(IC_OUTPUT, 1, result)
push_data()
diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index a47dc53447..a85009d851 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -128,7 +128,7 @@
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
- if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
+ if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
@@ -143,6 +143,49 @@
push_data()
activate_pin(2)
+/obj/item/integrated_circuit/input/slime_scanner
+ name = "slime_scanner"
+ desc = "A very small version of the xenobio analyser. This allows the machine to know every needed properties of slime."
+ icon_state = "medscan_adv"
+ complexity = 12
+ inputs = list("\[ target")
+ outputs = list(
+ "colour" = IC_PINTYPE_STRING,
+ "adult" = IC_PINTYPE_BOOLEAN,
+ "nutrition" = IC_PINTYPE_NUMBER,
+ "charge" = IC_PINTYPE_NUMBER,
+ "health" = IC_PINTYPE_NUMBER,
+ "possible mutation" = IC_PINTYPE_LIST,
+ "genetic destability"= IC_PINTYPE_NUMBER,
+ "slime core amount" = IC_PINTYPE_NUMBER,
+ "Growth progress" = IC_PINTYPE_NUMBER,
+ )
+ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ power_draw_per_use = 80
+
+/obj/item/integrated_circuit/input/slime_scanner/do_work()
+ var/mob/living/simple_animal/slime/T = get_pin_data_as_type(IC_INPUT, 1, /mob/living/simple_animal/slime)
+ if(!isslime(T)) //Invalid input
+ return
+ if(T in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
+
+ set_pin_data(IC_OUTPUT, 1, T.colour)
+ set_pin_data(IC_OUTPUT, 2, T.is_adult)
+ set_pin_data(IC_OUTPUT, 3, T.nutrition/T.get_max_nutrition())
+ set_pin_data(IC_OUTPUT, 4, T.powerlevel)
+ set_pin_data(IC_OUTPUT, 5, round(T.health/T.maxHealth,0.01)*100)
+ set_pin_data(IC_OUTPUT, 6, uniqueList(T.slime_mutation))
+ set_pin_data(IC_OUTPUT, 7, T.mutation_chance)
+ set_pin_data(IC_OUTPUT, 8, T.cores)
+ set_pin_data(IC_OUTPUT, 9, T.amount_grown/SLIME_EVOLUTION_THRESHOLD)
+
+
+ push_data()
+ activate_pin(2)
+
+
+
/obj/item/integrated_circuit/input/plant_scanner
name = "integrated plant analyzer"
desc = "A very small version of the plant analyser. This allows the machine to know all valuable params of plants in trays. \
@@ -180,7 +223,7 @@
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
- if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
+ if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
set_pin_data(IC_OUTPUT, 1, H.myseed.plantname)
set_pin_data(IC_OUTPUT, 2, H.age)
@@ -228,7 +271,7 @@
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
- if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
+ if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
for(var/datum/plant_gene/reagent/G in H.myseed.genes)
greagents.Add(G.get_name())
@@ -478,8 +521,8 @@
power_draw_idle = 5
power_draw_per_use = 40
- var/frequency = 1457
- var/code = 30
+ var/frequency = FREQ_SIGNALER
+ var/code = DEFAULT_SIGNALER_CODE
var/datum/radio_frequency/radio_connection
/obj/item/integrated_circuit/input/signaler/Initialize()
@@ -509,24 +552,16 @@
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.source = src
- signal.encryption = code
- signal.data["message"] = "ACTIVATE"
+ var/datum/signal/signal = new(list("code" = code))
radio_connection.post_signal(src, signal)
-
activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
return
- if(!SSradio)
- sleep(20)
- if(!SSradio)
- return
SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_CHAT)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
var/new_code = get_pin_data(IC_INPUT, 2)
@@ -536,7 +571,7 @@
code = new_code
if(!signal)
return 0
- if(signal.encryption != code)
+ if(signal.data["code"] != code)
return 0
if(signal.source == src) // Don't trigger ourselves.
return 0
@@ -671,12 +706,15 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
-/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
+/obj/item/integrated_circuit/input/sensor/sense(var/atom/A,mob/user,prox)
+ if(!prox)
+ return FALSE
+ if(!check_then_do_work())
+ return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/storage))
return FALSE
-
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
push_data()
activate_pin(1)
@@ -694,6 +732,52 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
+/obj/item/integrated_circuit/input/sensor/ranged/sense(var/atom/A,mob/user)
+ if(!user)
+ return FALSE
+ if(user.client)
+ if(!(A in view(user.client)))
+ return FALSE
+ else
+ if(!(A in view(user)))
+ return FALSE
+ if(!check_then_do_work())
+ return FALSE
+ var/ignore_bags = get_pin_data(IC_INPUT, 1)
+ if(ignore_bags)
+ if(istype(A, /obj/item/storage))
+ return FALSE
+ set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
+ push_data()
+ activate_pin(1)
+ return TRUE
+
+/obj/item/integrated_circuit/input/objscaner
+ name = "scaner"
+ desc = "Scans and obtains a reference for any objects you use on assembly."
+ extended_desc = "If 'put down' pin is set to true, assembly will take scanned object from your hands to it's location.\
+ useful for interaction with grabber. Scaner works only with help intent."
+ icon_state = "recorder"
+ complexity = 4
+ inputs = list("put down" = IC_PINTYPE_BOOLEAN)
+ outputs = list("scanned" = IC_PINTYPE_REF)
+ activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+ power_draw_per_use = 20
+
+/obj/item/integrated_circuit/input/objscaner/attackby_react(var/atom/A,var/mob/user,intent)
+ if(intent!=INTENT_HELP)
+ return FALSE
+ if(!check_then_do_work())
+ return FALSE
+ var/pu = get_pin_data(IC_INPUT, 1)
+ if(pu)
+ user.transferItemToLoc(A,drop_location())
+ set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
+ push_data()
+ activate_pin(1)
+ return TRUE
+
/obj/item/integrated_circuit/input/internalbm
name = "internal battery monitor"
desc = "This monitors the charge level of an internal battery."
@@ -760,3 +844,38 @@
activate_pin(2)
push_data()
return
+
+/obj/item/integrated_circuit/input/ntnetsc
+ name = "NTnet scaner"
+ desc = "This can return NTnet id of component insi given object, if there is any."
+ icon_state = "signalsc"
+ w_class = WEIGHT_CLASS_TINY
+ complexity = 2
+ inputs = list("target" = IC_PINTYPE_REF)
+ outputs = list(
+ "id" = IC_PINTYPE_STRING
+ )
+ activators = list("read" = IC_PINTYPE_PULSE_IN, "found" = IC_PINTYPE_PULSE_OUT,"not found" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+ power_draw_per_use = 1
+
+/obj/item/integrated_circuit/input/ntnetsc/do_work()
+
+ var/atom/AM = get_pin_data_as_type(IC_INPUT, 1, /atom)
+ var/list/processing_list = list(AM)
+ var/datum/component/ntnet_interface/net = null
+ set_pin_data(IC_OUTPUT, 1, null)
+ while(processing_list.len && !net)
+ var/atom/A = processing_list[1]
+ processing_list.Cut(1, 2)
+ //Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
+ //This is also why we don't need to check against assembled as we go along
+ processing_list += A.contents
+ net = A.GetComponent(/datum/component/ntnet_interface)
+ if(net)
+ set_pin_data(IC_OUTPUT, 1, net.hardware_id)
+ activate_pin(2)
+ else
+ activate_pin(3)
+ push_data()
+ return
diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm
index 627301ef10..f8e858ef94 100644
--- a/code/modules/integrated_electronics/subtypes/logic.dm
+++ b/code/modules/integrated_electronics/subtypes/logic.dm
@@ -2,7 +2,7 @@
name = "logic gate"
desc = "This tiny chip will decide for you!"
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
- complexity = 3
+ complexity = 1
outputs = list("result")
activators = list("compare" = IC_PINTYPE_PULSE_IN)
category_text = "Logic"
diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm
index f32f414fbb..5099547197 100644
--- a/code/modules/integrated_electronics/subtypes/manipulation.dm
+++ b/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -155,9 +155,11 @@
if(isnum(wanted_dir.data))
if(step(assembly, wanted_dir.data))
activate_pin(2)
+ return
else
activate_pin(3)
return FALSE
+ return FALSE
/obj/item/integrated_circuit/manipulation/grenade
name = "grenade primer"
@@ -247,9 +249,14 @@
/obj/item/integrated_circuit/manipulation/plant_module/do_work()
..()
var/turf/T = get_turf(src)
- var/obj/machinery/hydroponics/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/hydroponics)
- if(!istype(AM)) //Invalid input
+ var/obj/OM = get_pin_data_as_type(IC_INPUT, 1, /obj)
+ if(istype(OM,/obj/structure/spacevine) && get_pin_data(IC_INPUT, 2) == 2)
+ qdel(OM)
+ activate_pin(2)
return
+ var/obj/machinery/hydroponics/AM = OM
+ if(!istype(AM)) //Invalid input
+ return FALSE
var/mob/living/M = get_turf(AM)
if(!M.Adjacent(T))
return //Can't reach
@@ -276,6 +283,7 @@
qdel(AM.myseed)
AM.myseed = null
AM.weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
+ AM.dead = 0
AM.update_icon()
else
activate_pin(2)
@@ -284,7 +292,7 @@
/obj/item/integrated_circuit/manipulation/grabber
name = "grabber"
- desc = "A circuit with it's own inventory for small/medium items, used to grab and store things."
+ desc = "A circuit with it's own inventory for tiny/small items, used to grab and store things."
icon_state = "grabber"
extended_desc = "The circuit accepts a reference to thing to be grabbed. It can store up to 10 things. Modes: 1 for grab. 0 for eject the first thing. -1 for eject all."
w_class = WEIGHT_CLASS_SMALL
@@ -307,7 +315,7 @@
var/mode = get_pin_data(IC_INPUT, 2)
if(mode == 1)
- if(check_target(AM, exclude_contents = TRUE))
+ if(check_target(AM))
if((contents.len < max_items) && (!max_w_class || AM.w_class <= max_w_class))
AM.forceMove(src)
if(mode == 0)
diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm
index 33f92c3646..9f74797e35 100644
--- a/code/modules/integrated_electronics/subtypes/reagents.dm
+++ b/code/modules/integrated_electronics/subtypes/reagents.dm
@@ -9,6 +9,11 @@
. = ..()
if(volume)
create_reagents(volume)
+ push_vol()
+
+/obj/item/integrated_circuit/reagent/proc/push_vol()
+ set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
+ push_data()
/obj/item/integrated_circuit/reagent/smoke
name = "smoke generator"
@@ -29,7 +34,8 @@
)
activators = list(
"create smoke" = IC_PINTYPE_PULSE_IN,
- "on smoked" = IC_PINTYPE_PULSE_OUT
+ "on smoked" = IC_PINTYPE_PULSE_OUT,
+ "push ref" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 20
@@ -40,24 +46,27 @@
//reset warning only if we have reagents now
if(changetype == ADD_REAGENT)
notified = FALSE
- set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
- push_data()
+ push_vol()
-/obj/item/integrated_circuit/reagent/smoke/do_work()
- if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS))
- return
- var/location = get_turf(src)
- var/datum/effect_system/smoke_spread/chem/S = new
- S.attach(location)
- playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
- if(S)
- S.set_up(reagents, smoke_radius, location, notified)
- if(!notified)
- notified = TRUE
- S.start()
-
- reagents.clear_reagents()
- activate_pin(2)
+/obj/item/integrated_circuit/reagent/smoke/do_work(ord)
+ switch(ord)
+ if(1)
+ if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS))
+ return
+ var/location = get_turf(src)
+ var/datum/effect_system/smoke_spread/chem/S = new
+ S.attach(location)
+ playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
+ if(S)
+ S.set_up(reagents, smoke_radius, location, notified)
+ if(!notified)
+ notified = TRUE
+ S.start()
+ reagents.clear_reagents()
+ activate_pin(2)
+ if(3)
+ set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
+ push_data()
/obj/item/integrated_circuit/reagent/injector
name = "integrated hypo-injector"
@@ -85,7 +94,9 @@
activators = list(
"inject" = IC_PINTYPE_PULSE_IN,
"on injected" = IC_PINTYPE_PULSE_OUT,
- "on fail" = IC_PINTYPE_PULSE_OUT
+ "on fail" = IC_PINTYPE_PULSE_OUT,
+ "push ref" = IC_PINTYPE_PULSE_IN
+
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
@@ -93,15 +104,8 @@
var/transfer_amount = 10
var/busy = FALSE
-/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
- set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
- push_data()
- ..()
-
-
/obj/item/integrated_circuit/reagent/injector/on_reagent_change(changetype)
- set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
- push_data()
+ push_vol()
/obj/item/integrated_circuit/reagent/injector/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 2)
@@ -127,7 +131,15 @@
temp_reagents.clear_reagents()
qdel(temp_reagents)
-/obj/item/integrated_circuit/reagent/injector/do_work()
+/obj/item/integrated_circuit/reagent/injector/do_work(ord)
+ switch(ord)
+ if(1)
+ inject()
+ if(4)
+ set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
+ push_data()
+
+/obj/item/integrated_circuit/reagent/injector/proc/inject()
set waitfor = FALSE // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/acting_object = get_object()
@@ -281,17 +293,16 @@
"volume used" = IC_PINTYPE_NUMBER,
"self reference" = IC_PINTYPE_REF
)
- activators = list()
+ activators = list("push ref" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
-/obj/item/integrated_circuit/reagent/storage/interact(mob/user)
+
+/obj/item/integrated_circuit/reagent/storage/do_work()
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
- ..()
/obj/item/integrated_circuit/reagent/storage/on_reagent_change(changetype)
- set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
- push_data()
+ push_vol()
/obj/item/integrated_circuit/reagent/storage/cryo
name = "cryo reagent storage"
@@ -306,6 +317,7 @@
. = ..()
reagents.set_reacting(FALSE)
+
/obj/item/integrated_circuit/reagent/storage/big
name = "big reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 180u."
@@ -317,6 +329,99 @@
complexity = 16
spawn_flags = IC_SPAWN_RESEARCH
+/obj/item/integrated_circuit/reagent/storage/grinder
+ name = "reagent grinder"
+ desc = "This is reagent grinder.It accepts ref to something and refines it into reagents. Can store up to 100u."
+ icon_state = "blender"
+ extended_desc = ""
+ inputs = list(
+ "target" = IC_PINTYPE_REF,
+ )
+ outputs = list(
+ "volume used" = IC_PINTYPE_NUMBER,
+ "self reference" = IC_PINTYPE_REF
+ )
+ activators = list(
+ "grind" = IC_PINTYPE_PULSE_IN,
+ "on grind" = IC_PINTYPE_PULSE_OUT,
+ "on fail" = IC_PINTYPE_PULSE_OUT,
+ "push ref" = IC_PINTYPE_PULSE_IN
+ )
+ volume = 100
+ power_draw_per_use = 150
+ complexity = 16
+ spawn_flags = IC_SPAWN_RESEARCH
+
+
+/obj/item/integrated_circuit/reagent/storage/grinder/do_work(ord)
+ switch(ord)
+ if(1)
+ grind()
+ if(4)
+ set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
+ push_data()
+
+/obj/item/integrated_circuit/reagent/storage/grinder/proc/grind()
+ if(reagents.total_volume >= reagents.maximum_volume)
+ activate_pin(3)
+ return FALSE
+ var/obj/item/I = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
+ if(istype(I)&&(I.grind_results)&&check_target(I)&&(I.on_grind(src) != -1))
+ reagents.add_reagent_list(I.grind_results)
+ if(I.reagents)
+ I.reagents.trans_to(src, I.reagents.total_volume)
+ qdel(I)
+ activate_pin(2)
+ return TRUE
+ activate_pin(3)
+ return FALSE
+
+obj/item/integrated_circuit/reagent/storage/juicer
+ name = "reagent juicer"
+ desc = "This is reagent juicer.It accepts ref to something and refines it into reagents. Can store up to 100u."
+ icon_state = "blender"
+ extended_desc = ""
+ inputs = list(
+ "target" = IC_PINTYPE_REF,
+ )
+ outputs = list(
+ "volume used" = IC_PINTYPE_NUMBER,
+ "self reference" = IC_PINTYPE_REF
+ )
+ activators = list(
+ "juice" = IC_PINTYPE_PULSE_IN,
+ "on juice" = IC_PINTYPE_PULSE_OUT,
+ "on fail" = IC_PINTYPE_PULSE_OUT,
+ "push ref" = IC_PINTYPE_PULSE_IN
+ )
+ volume = 100
+ power_draw_per_use = 150
+ complexity = 16
+ spawn_flags = IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/reagent/storage/juicer/do_work(ord)
+ switch(ord)
+ if(1)
+ juice()
+ if(4)
+ set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
+ push_data()
+
+/obj/item/integrated_circuit/reagent/storage/juicer/proc/juice()
+ if(reagents.total_volume >= reagents.maximum_volume)
+ activate_pin(3)
+ return FALSE
+ var/obj/item/I = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
+ if(istype(I)&&check_target(I)&&(I.juice_results)&&(I.on_juice() != -1))
+ reagents.add_reagent_list(I.juice_results)
+ qdel(I)
+ activate_pin(2)
+ return TRUE
+ activate_pin(3)
+ return FALSE
+
+
+
/obj/item/integrated_circuit/reagent/storage/scan
name = "reagent scanner"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. On pulse this beaker will send list of contained reagents."
@@ -330,17 +435,22 @@
"list of reagents" = IC_PINTYPE_LIST
)
activators = list(
- "scan" = IC_PINTYPE_PULSE_IN
+ "scan" = IC_PINTYPE_PULSE_IN,
+ "push ref" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_RESEARCH
-/obj/item/integrated_circuit/reagent/storage/scan/do_work()
- var/cont[0]
- for(var/datum/reagent/RE in reagents.reagent_list)
- cont += RE.id
- set_pin_data(IC_OUTPUT, 3, cont)
- push_data()
-
+/obj/item/integrated_circuit/reagent/storage/scan/do_work(ord)
+ switch(ord)
+ if(1)
+ var/cont[0]
+ for(var/datum/reagent/RE in reagents.reagent_list)
+ cont += RE.id
+ set_pin_data(IC_OUTPUT, 3, cont)
+ push_data()
+ if(2)
+ set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
+ push_data()
/obj/item/integrated_circuit/reagent/filter
name = "reagent filter"
@@ -394,7 +504,8 @@
if(!source.reagents || !target.reagents)
return
- if(!source.is_drainable() || !target.is_refillable())
+ // FALSE in those procs makes mobs invalid targets.
+ if(!source.is_drawable(FALSE) || !target.is_injectable(FALSE))
return
if(target.reagents.maximum_volume - target.reagents.total_volume <= 0)
@@ -410,3 +521,45 @@
activate_pin(2)
push_data()
+/obj/item/integrated_circuit/reagent/storage/heater
+ name = "chemical heater"
+ desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. Will heat or freeze reagents \
+ to target temperature, when turned on."
+ icon_state = "heater"
+ container_type = OPENCONTAINER
+ complexity = 8
+ inputs = list(
+ "target temperature" = IC_PINTYPE_NUMBER,
+ "on" = IC_PINTYPE_BOOLEAN
+ )
+ inputs_default = list("1" = 300)
+ outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"temperature" = IC_PINTYPE_NUMBER)
+ spawn_flags = IC_SPAWN_RESEARCH
+ var/heater_coefficient = 0.1
+
+/obj/item/integrated_circuit/reagent/storage/heater/on_data_written()
+ if(get_pin_data(IC_INPUT, 2))
+ power_draw_idle = 30
+ else
+ power_draw_idle = 0
+
+/obj/item/integrated_circuit/reagent/storage/heater/Initialize()
+ .=..()
+ START_PROCESSING(SScircuit, src)
+
+/obj/item/integrated_circuit/reagent/storage/heater/Destroy()
+ STOP_PROCESSING(SScircuit, src)
+ return ..()
+
+/obj/item/integrated_circuit/reagent/storage/heater/process()
+ if(power_draw_idle)
+ var/target_temperature = get_pin_data(IC_INPUT, 1)
+ if(reagents.chem_temp > target_temperature)
+ reagents.chem_temp += min(-1, (target_temperature - reagents.chem_temp) * heater_coefficient)
+ if(reagents.chem_temp < target_temperature)
+ reagents.chem_temp += max(1, (target_temperature - reagents.chem_temp) * heater_coefficient)
+
+ reagents.chem_temp = round(reagents.chem_temp)
+ reagents.handle_reactions()
+ set_pin_data(IC_OUTPUT, 3, reagents.chem_temp)
+ push_data()
diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm
index ec59c3cab1..37a38677b0 100644
--- a/code/modules/integrated_electronics/subtypes/smart.dm
+++ b/code/modules/integrated_electronics/subtypes/smart.dm
@@ -27,6 +27,6 @@
push_data()
return // Can't see the target.
- set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_turf(A)))
+ set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_step_towards2(get_turf(src),A)))
push_data()
activate_pin(2)
diff --git a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm
index 220fa2e9ac..83a2af9b4c 100644
--- a/code/modules/jobs/job_exp.dm
+++ b/code/modules/jobs/job_exp.dm
@@ -263,4 +263,4 @@ GLOBAL_PROTECT(exp_to_update)
prefs.db_flags = text2num(flags_read.item[1])
else if(isnull(prefs.db_flags))
prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry.
- return TRUE
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index 03498f1e7b..38418e9916 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -1,77 +1,77 @@
-/*
-Captain
-*/
-/datum/job/captain
- title = "Captain"
- flag = CAPTAIN
+/*
+Captain
+*/
+/datum/job/captain
+ title = "Captain"
+ flag = CAPTAIN
department_head = list("CentCom")
- department_flag = ENGSEC
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "Nanotrasen officials and Space law"
- selection_color = "#ccccff"
- req_admin_notify = 1
- minimal_player_age = 14
+ department_flag = ENGSEC
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "Nanotrasen officials and Space law"
+ selection_color = "#ccccff"
+ req_admin_notify = 1
+ minimal_player_age = 14
exp_requirements = 180
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/captain
-
- access = list() //See get_access()
- minimal_access = list() //See get_access()
-
-/datum/job/captain/get_access()
- return get_all_accesses()
-
-/datum/job/captain/announce(mob/living/carbon/human/H)
- ..()
- SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/minor_announce, "Captain [H.real_name] on deck!"))
-
-/datum/outfit/job/captain
- name = "Captain"
- jobtype = /datum/job/captain
-
- id = /obj/item/card/id/gold
- belt = /obj/item/device/pda/captain
- glasses = /obj/item/clothing/glasses/sunglasses
- ears = /obj/item/device/radio/headset/heads/captain/alt
- gloves = /obj/item/clothing/gloves/color/captain
- uniform = /obj/item/clothing/under/rank/captain
- suit = /obj/item/clothing/suit/armor/vest/capcarapace
- shoes = /obj/item/clothing/shoes/sneakers/brown
- head = /obj/item/clothing/head/caphat
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1)
-
- backpack = /obj/item/storage/backpack/captain
- satchel = /obj/item/storage/backpack/satchel/cap
- duffelbag = /obj/item/storage/backpack/duffelbag/captain
-
- implants = list(/obj/item/implant/mindshield)
- accessory = /obj/item/clothing/accessory/medal/gold/captain
-
-/*
-Head of Personnel
-*/
-/datum/job/hop
- title = "Head of Personnel"
- flag = HOP
- department_head = list("Captain")
- department_flag = CIVILIAN
- head_announce = list("Supply", "Service")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ddddff"
- req_admin_notify = 1
- minimal_player_age = 10
+
+ outfit = /datum/outfit/job/captain
+
+ access = list() //See get_access()
+ minimal_access = list() //See get_access()
+
+/datum/job/captain/get_access()
+ return get_all_accesses()
+
+/datum/job/captain/announce(mob/living/carbon/human/H)
+ ..()
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/minor_announce, "Captain [H.real_name] on deck!"))
+
+/datum/outfit/job/captain
+ name = "Captain"
+ jobtype = /datum/job/captain
+
+ id = /obj/item/card/id/gold
+ belt = /obj/item/device/pda/captain
+ glasses = /obj/item/clothing/glasses/sunglasses
+ ears = /obj/item/device/radio/headset/heads/captain/alt
+ gloves = /obj/item/clothing/gloves/color/captain
+ uniform = /obj/item/clothing/under/rank/captain
+ suit = /obj/item/clothing/suit/armor/vest/capcarapace
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/caphat
+ backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1)
+
+ backpack = /obj/item/storage/backpack/captain
+ satchel = /obj/item/storage/backpack/satchel/cap
+ duffelbag = /obj/item/storage/backpack/duffelbag/captain
+
+ implants = list(/obj/item/implant/mindshield)
+ accessory = /obj/item/clothing/accessory/medal/gold/captain
+
+/*
+Head of Personnel
+*/
+/datum/job/hop
+ title = "Head of Personnel"
+ flag = HOP
+ department_head = list("Captain")
+ department_flag = CIVILIAN
+ head_announce = list("Supply", "Service")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ddddff"
+ req_admin_notify = 1
+ minimal_player_age = 10
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SUPPLY
-
- outfit = /datum/outfit/job/hop
-
+
+ outfit = /datum/outfit/job/hop
+
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
@@ -84,17 +84,17 @@ Head of Personnel
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_LAWYER,
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
-
-
-/datum/outfit/job/hop
- name = "Head of Personnel"
- jobtype = /datum/job/hop
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/hop
- ears = /obj/item/device/radio/headset/heads/hop
- uniform = /obj/item/clothing/under/rank/head_of_personnel
- shoes = /obj/item/clothing/shoes/sneakers/brown
- head = /obj/item/clothing/head/hopcap
- backpack_contents = list(/obj/item/storage/box/ids=1,\
- /obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced = 1)
+
+
+/datum/outfit/job/hop
+ name = "Head of Personnel"
+ jobtype = /datum/job/hop
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/hop
+ ears = /obj/item/device/radio/headset/heads/hop
+ uniform = /obj/item/clothing/under/rank/head_of_personnel
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/hopcap
+ backpack_contents = list(/obj/item/storage/box/ids=1,\
+ /obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced = 1)
diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm
index 2e18807541..6720c28710 100644
--- a/code/modules/jobs/job_types/job.dm
+++ b/code/modules/jobs/job_types/job.dm
@@ -72,14 +72,15 @@
H.dna.species.after_equip_job(src, H, visualsOnly)
+ if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions))
+ if(H.dna.species.id != "human")
+ H.set_species(/datum/species/human)
+ H.rename_self("human", H.client)
+ purrbation_remove(H, silent=TRUE)
+
if(!visualsOnly && announce)
announce(H)
- if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions))
- H.dna.features["tail_human"] = "None"
- H.dna.features["ears"] = "None"
- H.regenerate_icons()
-
/datum/job/proc/get_access()
if(!config) //Needed for robots.
return src.minimal_access.Copy()
diff --git a/code/modules/jobs/job_types/medical.dm b/code/modules/jobs/job_types/medical.dm
index 9a33e1e759..151ed213f8 100644
--- a/code/modules/jobs/job_types/medical.dm
+++ b/code/modules/jobs/job_types/medical.dm
@@ -1,191 +1,191 @@
-/*
-Chief Medical Officer
-*/
-/datum/job/cmo
- title = "Chief Medical Officer"
- flag = CMO_JF
- department_head = list("Captain")
- department_flag = MEDSCI
- head_announce = list("Medical")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ffddf0"
- req_admin_notify = 1
- minimal_player_age = 7
+/*
+Chief Medical Officer
+*/
+/datum/job/cmo
+ title = "Chief Medical Officer"
+ flag = CMO_JF
+ department_head = list("Captain")
+ department_flag = MEDSCI
+ head_announce = list("Medical")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ffddf0"
+ req_admin_notify = 1
+ minimal_player_age = 7
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_MEDICAL
-
- outfit = /datum/outfit/job/cmo
-
+
+ outfit = /datum/outfit/job/cmo
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
-
-/datum/outfit/job/cmo
- name = "Chief Medical Officer"
- jobtype = /datum/job/cmo
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/cmo
+
+/datum/outfit/job/cmo
+ name = "Chief Medical Officer"
+ jobtype = /datum/job/cmo
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/cmo
l_pocket = /obj/item/pinpointer/crew
- ears = /obj/item/device/radio/headset/heads/cmo
- uniform = /obj/item/clothing/under/rank/chief_medical_officer
- shoes = /obj/item/clothing/shoes/sneakers/brown
- suit = /obj/item/clothing/suit/toggle/labcoat/cmo
- l_hand = /obj/item/storage/firstaid/regular
- suit_store = /obj/item/device/flashlight/pen
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1)
-
- backpack = /obj/item/storage/backpack/medic
- satchel = /obj/item/storage/backpack/satchel/med
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Medical Doctor
-*/
-/datum/job/doctor
- title = "Medical Doctor"
- flag = DOCTOR
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 5
- spawn_positions = 3
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
-
- outfit = /datum/outfit/job/doctor
-
+ ears = /obj/item/device/radio/headset/heads/cmo
+ uniform = /obj/item/clothing/under/rank/chief_medical_officer
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat/cmo
+ l_hand = /obj/item/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+ backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1)
+
+ backpack = /obj/item/storage/backpack/medic
+ satchel = /obj/item/storage/backpack/satchel/med
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Medical Doctor
+*/
+/datum/job/doctor
+ title = "Medical Doctor"
+ flag = DOCTOR
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 5
+ spawn_positions = 3
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
+
+ outfit = /datum/outfit/job/doctor
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING)
-
-/datum/outfit/job/doctor
- name = "Medical Doctor"
- jobtype = /datum/job/doctor
-
- belt = /obj/item/device/pda/medical
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/medical
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat
- l_hand = /obj/item/storage/firstaid/regular
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/medic
- satchel = /obj/item/storage/backpack/satchel/med
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Chemist
-*/
-/datum/job/chemist
- title = "Chemist"
- flag = CHEMIST
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/doctor
+ name = "Medical Doctor"
+ jobtype = /datum/job/doctor
+
+ belt = /obj/item/device/pda/medical
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/medical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/medic
+ satchel = /obj/item/storage/backpack/satchel/med
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Chemist
+*/
+/datum/job/chemist
+ title = "Chemist"
+ flag = CHEMIST
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/chemist
-
+
+ outfit = /datum/outfit/job/chemist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/chemist
- name = "Chemist"
- jobtype = /datum/job/chemist
-
- glasses = /obj/item/clothing/glasses/science
- belt = /obj/item/device/pda/chemist
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/chemist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/chemist
- accessory = /obj/item/clothing/accessory/pocketprotector/full
- backpack = /obj/item/storage/backpack/chemistry
- satchel = /obj/item/storage/backpack/satchel/chem
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Geneticist
-*/
-/datum/job/geneticist
- title = "Geneticist"
- flag = GENETICIST
- department_head = list("Chief Medical Officer", "Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "the chief medical officer and research director"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/chemist
+ name = "Chemist"
+ jobtype = /datum/job/chemist
+
+ glasses = /obj/item/clothing/glasses/science
+ belt = /obj/item/device/pda/chemist
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/chemist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/chemist
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
+ backpack = /obj/item/storage/backpack/chemistry
+ satchel = /obj/item/storage/backpack/satchel/chem
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Geneticist
+*/
+/datum/job/geneticist
+ title = "Geneticist"
+ flag = GENETICIST
+ department_head = list("Chief Medical Officer", "Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "the chief medical officer and research director"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/geneticist
-
+
+ outfit = /datum/outfit/job/geneticist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_ROBOTICS, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH)
-
-/datum/outfit/job/geneticist
- name = "Geneticist"
- jobtype = /datum/job/geneticist
-
- belt = /obj/item/device/pda/geneticist
- ears = /obj/item/device/radio/headset/headset_medsci
- uniform = /obj/item/clothing/under/rank/geneticist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/genetics
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/genetics
- satchel = /obj/item/storage/backpack/satchel/gen
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Virologist
-*/
-/datum/job/virologist
- title = "Virologist"
- flag = VIROLOGIST
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/geneticist
+ name = "Geneticist"
+ jobtype = /datum/job/geneticist
+
+ belt = /obj/item/device/pda/geneticist
+ ears = /obj/item/device/radio/headset/headset_medsci
+ uniform = /obj/item/clothing/under/rank/geneticist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/genetics
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/genetics
+ satchel = /obj/item/storage/backpack/satchel/gen
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Virologist
+*/
+/datum/job/virologist
+ title = "Virologist"
+ flag = VIROLOGIST
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/virologist
-
+
+ outfit = /datum/outfit/job/virologist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/virologist
- name = "Virologist"
- jobtype = /datum/job/virologist
-
- belt = /obj/item/device/pda/viro
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/virologist
- mask = /obj/item/clothing/mask/surgical
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/virologist
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/virology
- satchel = /obj/item/storage/backpack/satchel/vir
- duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/datum/outfit/job/virologist
+ name = "Virologist"
+ jobtype = /datum/job/virologist
+
+ belt = /obj/item/device/pda/viro
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/virologist
+ mask = /obj/item/clothing/mask/surgical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/virologist
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/virology
+ satchel = /obj/item/storage/backpack/satchel/vir
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
diff --git a/code/modules/jobs/job_types/science.dm b/code/modules/jobs/job_types/science.dm
index 4eac15d9f1..7fc1dada77 100644
--- a/code/modules/jobs/job_types/science.dm
+++ b/code/modules/jobs/job_types/science.dm
@@ -1,25 +1,25 @@
-/*
-Research Director
-*/
-/datum/job/rd
- title = "Research Director"
- flag = RD_JF
- department_head = list("Captain")
- department_flag = MEDSCI
- head_announce = list("Science")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ffddff"
- req_admin_notify = 1
- minimal_player_age = 7
+/*
+Research Director
+*/
+/datum/job/rd
+ title = "Research Director"
+ flag = RD_JF
+ department_head = list("Captain")
+ department_flag = MEDSCI
+ head_announce = list("Science")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ffddff"
+ req_admin_notify = 1
+ minimal_player_age = 7
exp_type_department = EXP_TYPE_SCIENCE
exp_requirements = 180
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/rd
-
+
+ outfit = /datum/outfit/job/rd
+
access = list(ACCESS_RD, ACCESS_HEADS, ACCESS_TOX, ACCESS_GENETICS, ACCESS_MORGUE,
ACCESS_TOX_STORAGE, ACCESS_TELEPORTER, ACCESS_SEC_DOORS,
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
@@ -30,101 +30,101 @@ Research Director
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM,
ACCESS_TECH_STORAGE, ACCESS_MINISAT, ACCESS_MAINT_TUNNELS, ACCESS_NETWORK)
-
-/datum/outfit/job/rd
- name = "Research Director"
- jobtype = /datum/job/rd
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/rd
- ears = /obj/item/device/radio/headset/heads/rd
- uniform = /obj/item/clothing/under/rank/research_director
- shoes = /obj/item/clothing/shoes/sneakers/brown
- suit = /obj/item/clothing/suit/toggle/labcoat
- l_hand = /obj/item/clipboard
- l_pocket = /obj/item/device/laser_pointer
- accessory = /obj/item/clothing/accessory/pocketprotector/full
+
+/datum/outfit/job/rd
+ name = "Research Director"
+ jobtype = /datum/job/rd
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/rd
+ ears = /obj/item/device/radio/headset/heads/rd
+ uniform = /obj/item/clothing/under/rank/research_director
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/clipboard
+ l_pocket = /obj/item/device/laser_pointer
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced=1)
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
-
-/datum/outfit/job/rd/rig
- name = "Research Director (Hardsuit)"
-
- l_hand = null
- mask = /obj/item/clothing/mask/breath
- suit = /obj/item/clothing/suit/space/hardsuit/rd
- suit_store = /obj/item/tank/internals/oxygen
- internals_slot = slot_s_store
-
-/*
-Scientist
-*/
-/datum/job/scientist
- title = "Scientist"
- flag = SCIENTIST
- department_head = list("Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 5
- spawn_positions = 3
- supervisors = "the research director"
- selection_color = "#ffeeff"
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+
+/datum/outfit/job/rd/rig
+ name = "Research Director (Hardsuit)"
+
+ l_hand = null
+ mask = /obj/item/clothing/mask/breath
+ suit = /obj/item/clothing/suit/space/hardsuit/rd
+ suit_store = /obj/item/tank/internals/oxygen
+ internals_slot = slot_s_store
+
+/*
+Scientist
+*/
+/datum/job/scientist
+ title = "Scientist"
+ flag = SCIENTIST
+ department_head = list("Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 5
+ spawn_positions = 3
+ supervisors = "the research director"
+ selection_color = "#ffeeff"
exp_requirements = 60
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/scientist
-
+
+ outfit = /datum/outfit/job/scientist
+
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS)
minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/scientist
- name = "Scientist"
- jobtype = /datum/job/scientist
-
- belt = /obj/item/device/pda/toxins
- ears = /obj/item/device/radio/headset/headset_sci
- uniform = /obj/item/clothing/under/rank/scientist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/science
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
- accessory = /obj/item/clothing/accessory/pocketprotector/full
-
-/*
-Roboticist
-*/
-/datum/job/roboticist
- title = "Roboticist"
- flag = ROBOTICIST
- department_head = list("Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "research director"
- selection_color = "#ffeeff"
+
+/datum/outfit/job/scientist
+ name = "Scientist"
+ jobtype = /datum/job/scientist
+
+ belt = /obj/item/device/pda/toxins
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/scientist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/science
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
+
+/*
+Roboticist
+*/
+/datum/job/roboticist
+ title = "Roboticist"
+ flag = ROBOTICIST
+ department_head = list("Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "research director"
+ selection_color = "#ffeeff"
exp_requirements = 60
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/roboticist
-
+
+ outfit = /datum/outfit/job/roboticist
+
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS)
minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/roboticist
- name = "Roboticist"
- jobtype = /datum/job/roboticist
-
- belt = /obj/item/storage/belt/utility/full
- l_pocket = /obj/item/device/pda/roboticist
- ears = /obj/item/device/radio/headset/headset_sci
- uniform = /obj/item/clothing/under/rank/roboticist
- suit = /obj/item/clothing/suit/toggle/labcoat
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
-
- pda_slot = slot_l_store
+
+/datum/outfit/job/roboticist
+ name = "Roboticist"
+ jobtype = /datum/job/roboticist
+
+ belt = /obj/item/storage/belt/utility/full
+ l_pocket = /obj/item/device/pda/roboticist
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/roboticist
+ suit = /obj/item/clothing/suit/toggle/labcoat
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+
+ pda_slot = slot_l_store
diff --git a/code/modules/jobs/job_types/security.dm b/code/modules/jobs/job_types/security.dm
index a1b95065c6..442b75c972 100644
--- a/code/modules/jobs/job_types/security.dm
+++ b/code/modules/jobs/job_types/security.dm
@@ -48,7 +48,7 @@ Head of Security
gloves = /obj/item/clothing/gloves/color/black/hos
head = /obj/item/clothing/head/HoS/beret
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
- suit_store = /obj/item/gun/energy/e_gun/cx
+ suit_store = /obj/item/gun/energy/e_gun
r_pocket = /obj/item/device/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
backpack_contents = list(/obj/item/melee/baton/loaded=1)
diff --git a/code/modules/jobs/job_types/silicon.dm b/code/modules/jobs/job_types/silicon.dm
index bc3b31b2bf..4a4893e93d 100644
--- a/code/modules/jobs/job_types/silicon.dm
+++ b/code/modules/jobs/job_types/silicon.dm
@@ -52,4 +52,4 @@ Cyborg
/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M)
if(CONFIG_GET(flag/rename_cyborg)) //name can't be set in robot/New without the client
- R.rename_self("cyborg", M.client)
+ R.rename_self("cyborg", M.client)
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_admin.dm b/code/modules/keybindings/bindings_admin.dm
new file mode 100644
index 0000000000..812bb95784
--- /dev/null
+++ b/code/modules/keybindings/bindings_admin.dm
@@ -0,0 +1,18 @@
+/datum/admins/key_down(_key, client/user)
+ switch(_key)
+ if("F5")
+ user.admin_ghost()
+ return
+ if("F6")
+ player_panel_new()
+ return
+ if("F7")
+ user.togglebuildmodeself()
+ return
+ if("F8")
+ if(user.keys_held["Ctrl"])
+ user.stealth()
+ else
+ user.invisimin()
+ return
+ ..()
diff --git a/code/modules/keybindings/bindings_carbon.dm b/code/modules/keybindings/bindings_carbon.dm
new file mode 100644
index 0000000000..d17f10e963
--- /dev/null
+++ b/code/modules/keybindings/bindings_carbon.dm
@@ -0,0 +1,18 @@
+/mob/living/carbon/key_down(_key, client/user)
+ switch(_key)
+ if("R", "Southwest") // Southwest is End
+ toggle_throw_mode()
+ return
+ if("1")
+ a_intent_change("help")
+ return
+ if("2")
+ a_intent_change("disarm")
+ return
+ if("3")
+ a_intent_change("grab")
+ return
+ if("4")
+ a_intent_change("harm")
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm
new file mode 100644
index 0000000000..6bfaedf39d
--- /dev/null
+++ b/code/modules/keybindings/bindings_client.dm
@@ -0,0 +1,50 @@
+// Clients aren't datums so we have to define these procs indpendently.
+// These verbs are called for all key press and release events
+/client/verb/keyDown(_key as text)
+ set instant = TRUE
+ set hidden = TRUE
+
+ keys_held[_key] = world.time
+ var/movement = GLOB.movement_keys[_key]
+ if(!(next_move_dir_sub & movement))
+ next_move_dir_add |= movement
+
+ // Client-level keybindings are ones anyone should be able to do at any time
+ // Things like taking screenshots, hitting tab, and adminhelps.
+
+ switch(_key)
+ if("F1")
+ if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used?
+ winset(src, null, "command=.options")
+ else
+ adminhelp()
+ if("F2") // Screenshot. Hold shift to choose a name and location to save in
+ winset(src, null, "command=.screenshot [!keys_held["shift"] ? "auto" : ""]")
+ if("F12") // Toggles minimal HUD
+ mob.button_pressed_F12()
+
+ if(holder)
+ holder.key_down(_key, src)
+ if(mob.focus)
+ mob.focus.key_down(_key, src)
+
+/client/verb/keyUp(_key as text)
+ set instant = TRUE
+ set hidden = TRUE
+
+ keys_held -= _key
+ var/movement = GLOB.movement_keys[_key]
+ if(!(next_move_dir_add & movement))
+ next_move_dir_sub |= movement
+
+ if(holder)
+ holder.key_up(_key, src)
+ if(mob.focus)
+ mob.focus.key_up(_key, src)
+
+// Called every game tick
+/client/keyLoop()
+ if(holder)
+ holder.keyLoop(src)
+ if(mob.focus)
+ mob.focus.keyLoop(src)
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_living.dm b/code/modules/keybindings/bindings_living.dm
new file mode 100644
index 0000000000..241bc15b60
--- /dev/null
+++ b/code/modules/keybindings/bindings_living.dm
@@ -0,0 +1,7 @@
+/mob/living/key_down(_key, client/user)
+ switch(_key)
+ if("B")
+ resist()
+ return
+
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_mob.dm b/code/modules/keybindings/bindings_mob.dm
new file mode 100644
index 0000000000..1d35694e5f
--- /dev/null
+++ b/code/modules/keybindings/bindings_mob.dm
@@ -0,0 +1,79 @@
+// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
+// All it takes is one badmin setting their focus to someone else's client to mess things up
+// Or we can have NPC's send actual keypresses and detect that by seeing no client
+
+/mob/key_down(_key, client/user)
+ switch(_key)
+ if("Delete", "H")
+ if(!pulling)
+ to_chat(src, "You are not pulling anything.")
+ else
+ stop_pulling()
+ return
+ if("Insert", "G")
+ a_intent_change(INTENT_HOTKEY_RIGHT)
+ return
+ if("F")
+ a_intent_change(INTENT_HOTKEY_LEFT)
+ return
+ if("X", "Northeast") // Northeast is Page-up
+ swap_hand()
+ return
+ if("Y", "Z", "Southeast") // Southeast is Page-down
+ mode() // attack_self(). No idea who came up with "mode()"
+ return
+ if("Q", "Northwest") // Northwest is Home
+ var/obj/item/I = get_active_held_item()
+ if(!I)
+ to_chat(src, "You have nothing to drop in your hand!")
+ else
+ dropItemToGround(I)
+ return
+ if("Alt")
+ toggle_move_intent()
+ return
+ //Bodypart selections
+ if("Numpad8")
+ user.body_toggle_head()
+ return
+ if("Numpad4")
+ user.body_r_arm()
+ return
+ if("Numpad5")
+ user.body_chest()
+ return
+ if("Numpad6")
+ user.body_l_arm()
+ return
+ if("Numpad1")
+ user.body_r_leg()
+ return
+ if("Numpad2")
+ user.body_groin()
+ return
+ if("Numpad3")
+ user.body_l_leg()
+ return
+
+ if(client.keys_held["Ctrl"])
+ switch(GLOB.movement_keys[_key])
+ if(NORTH)
+ northface()
+ return
+ if(SOUTH)
+ southface()
+ return
+ if(WEST)
+ westface()
+ return
+ if(EAST)
+ eastface()
+ return
+ return ..()
+
+/mob/key_up(_key, client/user)
+ switch(_key)
+ if("Alt")
+ toggle_move_intent()
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_robot.dm b/code/modules/keybindings/bindings_robot.dm
new file mode 100644
index 0000000000..2354f33c9e
--- /dev/null
+++ b/code/modules/keybindings/bindings_robot.dm
@@ -0,0 +1,12 @@
+/mob/living/silicon/robot/key_down(_key, client/user)
+ switch(_key)
+ if("1", "2", "3")
+ toggle_module(text2num(_key))
+ return
+ if("4")
+ a_intent_change(INTENT_HOTKEY_LEFT)
+ return
+ if("Q")
+ uneq_active()
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/focus.dm b/code/modules/keybindings/focus.dm
new file mode 100644
index 0000000000..9d3e44f059
--- /dev/null
+++ b/code/modules/keybindings/focus.dm
@@ -0,0 +1,20 @@
+/datum
+ var/list/focusers //Only initialized when needed. Contains a list of mobs focusing on this.
+
+/mob
+ var/datum/focus //What receives our keyboard inputs. src by default
+
+/mob/proc/set_focus(datum/new_focus)
+ if(focus == new_focus)
+ return
+
+ if(new_focus)
+ if(!new_focus.focusers) //Set up the new focus
+ new_focus.focusers = list()
+ new_focus.focusers += src
+
+ if(focus)
+ focus.focusers -= src //Tell the old focus we're done with it
+
+ focus = new_focus
+ reset_perspective(focus) //Maybe this should be done manually? You figure it out, reader
\ No newline at end of file
diff --git a/code/modules/keybindings/readme.md b/code/modules/keybindings/readme.md
new file mode 100644
index 0000000000..1170804436
--- /dev/null
+++ b/code/modules/keybindings/readme.md
@@ -0,0 +1,40 @@
+# In-code keypress handling system
+
+This whole system is heavily based off of forum_account's keyboard library.
+Thanks to forum_account for saving the day, the library can be found [here](http://www.byond.com/developer/Forum_account/Keyboard)!
+
+.dmf macros have some very serious shortcomings. For example, they do not allow reusing parts
+of one macro in another, so giving cyborgs their own shortcuts to swap active module couldn't
+inherit the movement that all mobs should have anyways. The webclient only supports one macro,
+so having more than one was problematic. Additionally each keybind has to call an actual
+verb, which meant a lot of hidden verbs that just call one other proc. Also our existing
+macro was really bad and tied unrelated behavior into `Northeast()`, `Southeast()`, `Northwest()`,
+and `Southwest()`.
+
+The basic premise of this system is to not screw with .dmf macro setup at all and handle
+pressing those keys in the code instead. We have every key call `client.keyDown()`
+or `client.keyUp()` with the pressed key as an argument. Certain keys get processed
+directly by the client because they should be doable at any time, then we call
+`keyDown()` or `keyUp()` on the client's holder and the client's mob's focus.
+By default `mob.focus` is the mob itself, but you can set it to any datum to give control of a
+client's keypresses to another object. This would be a good way to handle a menu or driving
+a mech. You can also set it to null to disregard input from a certain user.
+
+Movement is handled by having each client call `client.keyLoop()` every game tick.
+As above, this calls holder and `focus.keyLoop()`. `atom/movable/keyLoop()` handles movement
+Try to keep the calculations in this proc light. It runs every tick for every client after all!
+
+You can also tell which keys are being held down now. Each client a list of keys pressed called
+`keys_held`. Each entry is a key as a text string associated with the world.time when it was
+pressed.
+
+No client-set keybindings at this time, but it shouldn't be too hard if someone wants.
+
+Notes about certain keys
+`Tab` has client-sided behavior but acts normally
+`T`, `O`, and `M` move focus to the input when pressed. This fires the keyUp macro right away.
+`\` needs to be escaped in the dmf so any usage is `\\`
+
+You cannot `TICK_CHECK` or check `world.tick_usage` inside of procs called by key down and up
+events. They happen outside of a byond tick and have no meaning there. Key looping
+works correctly since it's part of a subsystem, not direct input.
\ No newline at end of file
diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm
new file mode 100644
index 0000000000..c36db0a1f3
--- /dev/null
+++ b/code/modules/keybindings/setup.dm
@@ -0,0 +1,55 @@
+/client
+ var/list/keys_held = list() // A list of any keys held currently
+ // These next two vars are to apply movement for keypresses and releases made while move delayed.
+ // Because discarding that input makes the game less responsive.
+ var/next_move_dir_add // On next move, add this dir to the move that would otherwise be done
+ var/next_move_dir_sub // On next move, subtract this dir from the move that would otherwise be done
+
+// Set a client's focus to an object and override these procs on that object to let it handle keypresses
+
+/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
+ return
+/datum/proc/key_up(key, client/user) // Called when a key is released
+ return
+/datum/proc/keyLoop(client/user) // Called once every frame
+ return
+
+// Keys used for movement
+GLOBAL_LIST_INIT(movement_keys, list(
+ "W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
+ "North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
+ ))
+
+// removes all the existing macros
+/client/proc/erase_all_macros()
+ var/list/macro_sets = params2list(winget(src, null, "macros"))
+ var/erase_output = ""
+ for(var/i in 1 to macro_sets.len)
+ var/setname = macro_sets[i]
+ var/list/macro_set = params2list(winget(src, "[setname].*", "command")) // The third arg doesnt matter here as we're just removing them all
+ for(var/k in 1 to macro_set.len)
+ var/list/split_name = splittext(macro_set[k], ".")
+ var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command"
+ erase_output = "[erase_output];[macro_name].parent=null"
+ winset(src, null, erase_output)
+
+/client/proc/set_macros()
+ set waitfor = FALSE
+
+ erase_all_macros()
+
+ var/list/macro_sets = SSinput.macro_sets
+ for(var/i in 1 to macro_sets.len)
+ var/setname = macro_sets[i]
+ if(setname != "default")
+ winclone(src, "default", setname)
+ var/list/macro_set = macro_sets[setname]
+ for(var/k in 1 to macro_set.len)
+ var/key = macro_set[k]
+ var/command = macro_set[key]
+ winset(src, "[setname]-[REF(key)]", "parent=[setname];name=[key];command=[command]")
+
+ if(prefs.hotkeys)
+ winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=default")
+ else
+ winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default")
\ No newline at end of file
diff --git a/code/modules/language/aphasia.dm b/code/modules/language/aphasia.dm
index 070a792ecd..91f14f9111 100644
--- a/code/modules/language/aphasia.dm
+++ b/code/modules/language/aphasia.dm
@@ -5,7 +5,7 @@
ask_verb = "mumbles"
whisper_verb = "mutters"
exclaim_verb = "screams incoherently"
- flags_1 = LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
+ flags = LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
key = "i"
syllables = list("m","n","gh","h","l","s","r","a","e","i","o","u")
space_chance = 20
diff --git a/code/modules/language/codespeak.dm b/code/modules/language/codespeak.dm
index e8398c2b9f..2a140f27de 100644
--- a/code/modules/language/codespeak.dm
+++ b/code/modules/language/codespeak.dm
@@ -3,7 +3,7 @@
desc = "Syndicate operatives can use a series of codewords to convey complex information, while sounding like random concepts and drinks to anyone listening in."
key = "t"
default_priority = 0
- flags_1 = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
+ flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
icon_state = "codespeak"
/datum/language/codespeak/scramble(input)
diff --git a/code/modules/language/common.dm b/code/modules/language/common.dm
index 162fbf9226..c00ab328ec 100644
--- a/code/modules/language/common.dm
+++ b/code/modules/language/common.dm
@@ -5,7 +5,7 @@
speech_verb = "says"
whisper_verb = "whispers"
key = "0"
- flags_1 = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_UNDERSTOOD
+ flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_UNDERSTOOD
default_priority = 100
icon_state = "galcom"
diff --git a/code/modules/language/draconic.dm b/code/modules/language/draconic.dm
index a85c1c9747..aaa998c2c0 100644
--- a/code/modules/language/draconic.dm
+++ b/code/modules/language/draconic.dm
@@ -5,7 +5,7 @@
ask_verb = "hisses"
exclaim_verb = "roars"
key = "o"
- flags_1 = TONGUELESS_SPEECH
+ flags = TONGUELESS_SPEECH
space_chance = 40
syllables = list(
"za", "az", "ze", "ez", "zi", "iz", "zo", "oz", "zu", "uz", "zs", "sz",
diff --git a/code/modules/language/drone.dm b/code/modules/language/drone.dm
index 32659e263b..390e0027cf 100644
--- a/code/modules/language/drone.dm
+++ b/code/modules/language/drone.dm
@@ -1,12 +1,12 @@
/datum/language/drone
name = "Drone"
- desc = "A heavily encoded damage control coordination stream, with special flags_1 for hats."
+ desc = "A heavily encoded damage control coordination stream, with special flags for hats."
speech_verb = "chitters"
ask_verb = "chitters inquisitively"
exclaim_verb = "chitters loudly"
spans = list(SPAN_ROBOT)
key = "d"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
syllables = list(".", "|")
// ...|..||.||||.|.||.|.|.|||.|||
space_chance = 0
diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm
index 598fb41e6c..5f2e9963e7 100644
--- a/code/modules/language/language.dm
+++ b/code/modules/language/language.dm
@@ -11,10 +11,10 @@
var/ask_verb = "asks" // Used when sentence ends in a ?
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead.
- var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags_1
+ var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/key // Character used to speak in language
// If key is null, then the language isn't real or learnable.
- var/flags_1 // Various language flags_1.
+ var/flags // Various language flags.
var/list/syllables // Used when scrambling text for a non-speaker.
var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
var/space_chance = 55 // Likelihood of getting a space in the random scramble string
@@ -28,9 +28,9 @@
/datum/language/proc/display_icon(atom/movable/hearer)
var/understands = hearer.has_language(src.type)
- if(flags_1 & LANGUAGE_HIDE_ICON_IF_UNDERSTOOD && understands)
+ if(flags & LANGUAGE_HIDE_ICON_IF_UNDERSTOOD && understands)
return FALSE
- if(flags_1 & LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD && !understands)
+ if(flags & LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD && !understands)
return FALSE
return TRUE
diff --git a/code/modules/language/machine.dm b/code/modules/language/machine.dm
index e5775040a2..4d88bcb416 100644
--- a/code/modules/language/machine.dm
+++ b/code/modules/language/machine.dm
@@ -6,7 +6,7 @@
exclaim_verb = "whistles loudly"
spans = list(SPAN_ROBOT)
key = "6"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz")
space_chance = 10
default_priority = 90
diff --git a/code/modules/language/swarmer.dm b/code/modules/language/swarmer.dm
index ea58775a08..e3b7826706 100644
--- a/code/modules/language/swarmer.dm
+++ b/code/modules/language/swarmer.dm
@@ -6,7 +6,7 @@
exclaim_verb = "tones loudly"
spans = list(SPAN_ROBOT)
key = "s"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
space_chance = 100
sentence_chance = 0
default_priority = 60
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index 9cbd04bf42..b7673a9640 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -144,8 +144,8 @@
/obj/structure/bookcase/manuals/medical
name = "medical manuals bookcase"
-/obj/structure/bookcase/manuals/medical/New()
- ..()
+/obj/structure/bookcase/manuals/medical/Initialize()
+ . = ..()
new /obj/item/book/manual/medical_cloning(src)
update_icon()
@@ -153,8 +153,8 @@
/obj/structure/bookcase/manuals/engineering
name = "engineering manuals bookcase"
-/obj/structure/bookcase/manuals/engineering/New()
- ..()
+/obj/structure/bookcase/manuals/engineering/Initialize()
+ . = ..()
new /obj/item/book/manual/wiki/engineering_construction(src)
new /obj/item/book/manual/engineering_particle_accelerator(src)
new /obj/item/book/manual/wiki/engineering_hacking(src)
@@ -167,8 +167,8 @@
/obj/structure/bookcase/manuals/research_and_development
name = "\improper R&D manuals bookcase"
-/obj/structure/bookcase/manuals/research_and_development/New()
- ..()
+/obj/structure/bookcase/manuals/research_and_development/Initialize()
+ . = ..()
new /obj/item/book/manual/research_and_development(src)
update_icon()
diff --git a/code/modules/library/soapstone.dm b/code/modules/library/soapstone.dm
index cee4665f07..fd75ba4351 100644
--- a/code/modules/library/soapstone.dm
+++ b/code/modules/library/soapstone.dm
@@ -142,7 +142,7 @@
hidden_message = newmessage
creator_name = user.real_name
creator_key = user.ckey
- realdate = world.timeofday
+ realdate = world.realtime
map = SSmapping.config.map_name
update_icon()
]