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()