diff --git a/code/game/mecha/components/_component.dm b/code/game/mecha/components/_component.dm index 3d770e0dce0..4058500dd2a 100644 --- a/code/game/mecha/components/_component.dm +++ b/code/game/mecha/components/_component.dm @@ -138,12 +138,26 @@ var/obj/item/stack/nanopaste/NP = W if(integrity < max_integrity) + to_chat(user, "You start to repair damage to \the [src].") while(integrity < max_integrity && NP) - if(do_after(user, 1 SECOND, src) && NP.use(1)) - adjust_integrity(10) + if(do_after(user, 1 SECOND, src)) + NP.use(1) + adjust_integrity(NP.mech_repair) + + if(integrity >= max_integrity) + to_chat(user, "You finish repairing \the [src].") + break + + else if(NP.amount == 0) + to_chat(user, "Insufficient nanopaste to complete repairs!") + break + return + else + to_chat(user, "\The [src] doesn't require repairs.") + return ..() // Various procs to handle different calls by Exosuits. IE, movement actions, damage actions, etc. diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index f5821b18d19..1dd50dc0bfe 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1567,15 +1567,27 @@ for(var/slot in internal_components) var/obj/item/mecha_parts/component/C = internal_components[slot] - if(C) + if(!C) + to_chat(user, "There are no components installed!") + return - if(C.integrity < C.max_integrity) - while(C.integrity < C.max_integrity && NP && do_after(user, 1 SECOND, src)) - if(NP.use(1)) - C.adjust_integrity(10) + if(C.integrity >= C.max_integrity) + to_chat(user, "\The [C] does not require repairs.") - to_chat(user, "You repair damage to \the [C].") + else if(C.integrity < C.max_integrity) + to_chat(user, "You start to repair damage to \the [C].") + while(C.integrity < C.max_integrity && NP) + if(do_after(user, 1 SECOND, src)) + NP.use(1) + C.adjust_integrity(NP.mech_repair) + if(C.integrity >= C.max_integrity) + to_chat(user, "You finish repairing \the [C].") + break + + else if(NP.amount == 0) + to_chat(user, "Insufficient nanopaste to complete repairs!") + break return else diff --git a/code/game/objects/items/stacks/nanopaste_vr.dm b/code/game/objects/items/stacks/nanopaste_vr.dm index cd39b61fef4..d0bd4e80034 100644 --- a/code/game/objects/items/stacks/nanopaste_vr.dm +++ b/code/game/objects/items/stacks/nanopaste_vr.dm @@ -2,6 +2,7 @@ var/restoration_external = 5 var/restoration_internal = 20 var/repair_external = FALSE + var/mech_repair = 10 /obj/item/stack/nanopaste/advanced name = "advanced nanopaste" @@ -10,4 +11,5 @@ icon = 'icons/obj/stacks_vr.dmi' icon_state = "adv_nanopaste" restoration_external = 10 - repair_external = TRUE \ No newline at end of file + repair_external = TRUE + mech_repair = 20 \ No newline at end of file diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index cbfac3ae02e..9f25d74a027 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -17,7 +17,7 @@ center_of_mass = null var/list/datum/stack_recipe/recipes var/singular_name - VAR_PROTECTED/amount = 1 + var/amount = 1 var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount var/stacktype //determines whether different stack types can merge var/build_type = null //used when directly applied to a turf diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm index 7afc90d082e..c700e2ba93b 100644 --- a/code/modules/client/preference_setup/global/01_ui.dm +++ b/code/modules/client/preference_setup/global/01_ui.dm @@ -14,6 +14,7 @@ S["tgui_fancy"] >> pref.tgui_fancy S["tgui_lock"] >> pref.tgui_lock S["tgui_input_mode"] >> pref.tgui_input_mode + S["tgui_input_lock"] >> pref.tgui_input_lock S["tgui_large_buttons"] >> pref.tgui_large_buttons S["tgui_swapped_buttons"] >> pref.tgui_swapped_buttons @@ -29,6 +30,7 @@ S["tgui_fancy"] << pref.tgui_fancy S["tgui_lock"] << pref.tgui_lock S["tgui_input_mode"] << pref.tgui_input_mode + S["tgui_input_lock"] << pref.tgui_input_lock S["tgui_large_buttons"] << pref.tgui_large_buttons S["tgui_swapped_buttons"] << pref.tgui_swapped_buttons @@ -44,6 +46,7 @@ pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy)) pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock)) pref.tgui_input_mode = sanitize_integer(pref.tgui_input_mode, 0, 1, initial(pref.tgui_input_mode)) + pref.tgui_input_lock = sanitize_integer(pref.tgui_input_lock, 0, 1, initial(pref.tgui_input_lock)) pref.tgui_large_buttons = sanitize_integer(pref.tgui_large_buttons, 0, 1, initial(pref.tgui_large_buttons)) pref.tgui_swapped_buttons = sanitize_integer(pref.tgui_swapped_buttons, 0, 1, initial(pref.tgui_swapped_buttons)) @@ -56,9 +59,10 @@ . += "Client FPS: [pref.client_fps]
" . += "Random Ambience Frequency: [pref.ambience_freq]
" . += "Ambience Chance: [pref.ambience_chance]
" - . += "tgui Window Mode: [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
" - . += "tgui Window Placement: [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
" + . += "TGUI Window Mode: [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
" + . += "TGUI Window Placement: [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
" . += "TGUI Input Framework: [(pref.tgui_input_mode) ? "Enabled" : "Disabled (default)"]
" + . += "TGUI Input Lock: [(pref.tgui_input_lock) ? "Enabled" : "Disabled (default)"]
" . += "TGUI Large Buttons: [(pref.tgui_large_buttons) ? "Enabled (default)" : "Disabled"]
" . += "TGUI Swapped Buttons: [(pref.tgui_swapped_buttons) ? "Enabled" : "Disabled (default)"]
" if(can_select_ooc_color(user)) @@ -107,14 +111,14 @@ if(pref.client) pref.client.fps = fps_new return TOPIC_REFRESH - + else if(href_list["select_ambience_freq"]) var/ambience_new = tgui_input_number(user, "Input how often you wish to hear ambience repeated! (1-60 MINUTES, 0 for disabled)", "Global Preference", pref.ambience_freq, 60, 0) if(isnull(ambience_new) || !CanUseTopic(user)) return TOPIC_NOACTION if(ambience_new < 0 || ambience_new > 60) return TOPIC_NOACTION pref.ambience_freq = ambience_new return TOPIC_REFRESH - + else if(href_list["select_ambience_chance"]) var/ambience_chance_new = tgui_input_number(user, "Input the chance you'd like to hear ambience played to you (On area change, or by random ambience). 35 means a 35% chance to play ambience. This is a range from 0-100. 0 disables ambience playing entirely. This is also affected by Ambience Frequency.", "Global Preference", pref.ambience_freq, 100, 0) if(isnull(ambience_chance_new) || !CanUseTopic(user)) return TOPIC_NOACTION @@ -125,7 +129,7 @@ else if(href_list["tgui_fancy"]) pref.tgui_fancy = !pref.tgui_fancy return TOPIC_REFRESH - + else if(href_list["tgui_lock"]) pref.tgui_lock = !pref.tgui_lock return TOPIC_REFRESH @@ -134,6 +138,10 @@ pref.tgui_input_mode = !pref.tgui_input_mode return TOPIC_REFRESH + else if(href_list["tgui_input_lock"]) + pref.tgui_input_lock = !pref.tgui_input_lock + return TOPIC_REFRESH + else if(href_list["tgui_large_buttons"]) pref.tgui_large_buttons = !pref.tgui_large_buttons return TOPIC_REFRESH diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c5e3200a2bf..db1e8fda212 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -29,6 +29,7 @@ var/list/preferences_datums = list() var/tgui_fancy = TRUE var/tgui_lock = FALSE var/tgui_input_mode = FALSE // All the Input Boxes (Text,Number,List,Alert) + var/tgui_input_lock = FALSE var/tgui_large_buttons = TRUE var/tgui_swapped_buttons = FALSE diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index c3bdad4e4ea..bbf0809bc4b 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -98,6 +98,7 @@ name = "shipping cap" desc = "It's a ballcap bearing the colors of Major Bill's Shipping." icon_state = "mbillsoft" + item_state_slots = list(slot_r_hand_str = "redsoft", slot_l_hand_str = "redsoft") catalogue_data = list(/datum/category_item/catalogue/information/organization/major_bills) /obj/item/clothing/head/soft/med diff --git a/code/modules/mob/living/carbon/human/species/species_vr.dm b/code/modules/mob/living/carbon/human/species/species_vr.dm index 7b3b1f5cce8..49962ef351c 100644 --- a/code/modules/mob/living/carbon/human/species/species_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_vr.dm @@ -20,6 +20,7 @@ var/selects_bodytype = SELECTS_BODYTYPE_FALSE // Allows the species to choose from body types like custom species can, affecting suit fitting and etcetera as you would expect. var/bloodsucker = FALSE // Allows safely getting nutrition from blood. + var/bloodsucker_controlmode = "always loud" //Allows selecting between bloodsucker control modes. Always Loud corresponds to original implementation. var/is_weaver = FALSE var/silk_production = FALSE diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm index ddaf32787c6..94e0d2f47cd 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm @@ -389,8 +389,6 @@ set desc = "Bites prey and drains them of a significant portion of blood, feeding you in the process. You may only do this once per minute." set category = "Abilities" - if(last_special > world.time) - return if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) to_chat(src, "You cannot bite anyone in your current state!") @@ -400,9 +398,27 @@ for(var/mob/living/carbon/human/M in view(1,src)) if(!istype(M,/mob/living/silicon) && Adjacent(M)) choices += M - choices -= src - var/mob/living/carbon/human/B = tgui_input_list(src, "Who do you wish to bite?", "Suck Blood", choices) + + var/mob/living/carbon/human/B = tgui_input_list(src, "Who do you wish to bite? Select yourself to bring up configuration for privacy and bleeding. \ + Beware! Configuration resets on new round!", "Suck Blood", choices) + + if(B == src) //We are using this to minimize the amount of pop-ups or buttons. + var/control_options = list("always loud", "pop-up", "intents", "always subtle") + src.species.bloodsucker_controlmode = tgui_input_list(src,"Choose your preferred control of blood sucking. \ + You can only cause bleeding wounds with pop up and intents modes. Choosing intents prints controls to chat.", "Configure Bloodsuck", control_options, "always loud") + if(src.species.bloodsucker_controlmode == "intents") //We are printing to chat for better readability + to_chat(src, SPAN_NOTICE("You've chosen to use intents for blood draining. \n \ + HELP - Loud, No Bleeding \n \ + DISARM - Subtle, Causes bleeding \n \ + GRAB - Subtle, No Bleeding \n \ + HARM - Loud, Causes Bleeding")) + return + + if(last_special > world.time) + to_chat(src, "You cannot suck blood so quickly in a row!") + return + if(!B || !src || src.stat) return @@ -418,12 +434,64 @@ return last_special = world.time + 600 - src.visible_message("[src] moves their head next to [B]'s neck, seemingly looking for something!") + + var/control_pref = src.species.bloodsucker_controlmode + var/noise = TRUE + var/bleed = FALSE + + switch(control_pref) + if("always subtle") + noise = FALSE + if("pop-up") + if(tgui_alert(src, "Do you want to be subtle?", "Privacy", list("Yes", "No")) == "Yes") + noise = FALSE + if(tgui_alert(src, "Do you want your target to keep bleeding?", "Continue Bleeding", list("Yes", "No")) == "Yes" ) + bleed = TRUE + if("intents") + /* + Logic is, with "Help", we are taking our time but it's pretty obvious.. + With "disarm", we rush the act, letting it keep bleeding + "HURT" is self-evidently loud and bleedy + "Grab" is subtle because we keep our prey tight and close. + */ + switch(src.a_intent) + //if(I_HELP) uses default values. Added as a comment for clarity + if(I_DISARM) + noise = FALSE + bleed = TRUE + if(I_GRAB) + noise = FALSE + if(I_HURT) + bleed =TRUE + + + + + if(noise) + src.visible_message("[src] moves their head next to [B]'s neck, seemingly looking for something!") + else + src.visible_message("[src] moves their head next to [B]'s neck, seemingly looking for something!", range = 1) + + if(bleed) //Due to possibility of missing/misclick and missing the bleeding cues, we are warning the scene members of BLEEDING being on + to_chat(src, SPAN_WARNING("This is going to cause [B] to keep bleeding!")) + to_chat(B, SPAN_DANGER("You are going to keep bleeding from this bite!")) if(do_after(src, 300, B)) //Thrirty seconds. if(!Adjacent(B)) return - src.visible_message("[src] suddenly extends their fangs and plunges them down into [B]'s neck!") - B.apply_damage(5, BRUTE, BP_HEAD) //You're getting fangs pushed into your neck. What do you expect???? + if(noise) + src.visible_message("[src] suddenly extends their fangs and plunges them down into [B]'s neck!") + else + src.visible_message("[src] suddenly extends their fangs and plunges them down into [B]'s neck!", range = 1) + if(bleed) + B.apply_damage(10, BRUTE, BP_HEAD, blocked = 0, soaked = 0, sharp = TRUE, edge = FALSE) + var/obj/item/organ/external/E = B.get_organ(BP_HEAD) + if(!(E.status & ORGAN_BLEEDING)) + E.status |= ORGAN_BLEEDING //If 10 points of piercing didn't make the organ bleed, we are making it bleed. + + + else + B.apply_damage(5, BRUTE, BP_HEAD) //You're getting fangs pushed into your neck. What do you expect???? + B.drip(80) //Remove enough blood to make them a bit woozy, but not take oxyloss. adjust_nutrition(400) sleep(50) @@ -1386,4 +1454,4 @@ name = "tongue ball" hitsound = 'sound/vore/sunesound/pred/schlorp.ogg' hitsound_wall = 'sound/vore/sunesound/pred/schlorp.ogg' - zaptype = /obj/item/projectile/beam/appendage \ No newline at end of file + zaptype = /obj/item/projectile/beam/appendage diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm index f115fdde63c..614f9e142ec 100644 --- a/code/modules/tgui_input/text.dm +++ b/code/modules/tgui_input/text.dm @@ -39,6 +39,11 @@ return input(user, message, title, default) as message|null else return input(user, message, title, default) as text|null + + //Client has TGUI input lock on; override whatever prevent_enter was specified beforehand + if(user.client.prefs.tgui_input_lock) + prevent_enter = TRUE + var/datum/tgui_input_text/text_input = new(user, message, title, default, max_length, multiline, encode, timeout, prevent_enter) text_input.tgui_interact(user) text_input.wait() diff --git a/config/alienwhitelist.txt b/config/alienwhitelist.txt index 3f2c5964db5..440e35dbf25 100644 --- a/config/alienwhitelist.txt +++ b/config/alienwhitelist.txt @@ -111,6 +111,9 @@ pastelprincedan - Protean pearlprophet - Protean pemdesos - Protean phoenixx0 - Vox +pontifexminimus - Black-Eyed Shadekin +pontifexminimus - Protean +pontifexminimus - Xenochimera qrocakes - Black-Eyed Shadekin radiantaurora - Protean residentcody - Black-Eyed Shadekin diff --git a/icons/inventory/head/mob.dmi b/icons/inventory/head/mob.dmi index 856681fa942..9ba1cea1ff2 100644 Binary files a/icons/inventory/head/mob.dmi and b/icons/inventory/head/mob.dmi differ diff --git a/icons/inventory/head/mob_vr_vulpkanin.dmi b/icons/inventory/head/mob_vr_vulpkanin.dmi index 7da329c30a7..d82fece7caf 100644 Binary files a/icons/inventory/head/mob_vr_vulpkanin.dmi and b/icons/inventory/head/mob_vr_vulpkanin.dmi differ diff --git a/maps/groundbase/gb-centcomm.dmm b/maps/groundbase/gb-centcomm.dmm index 1d31b107c56..e078f40080d 100644 --- a/maps/groundbase/gb-centcomm.dmm +++ b/maps/groundbase/gb-centcomm.dmm @@ -4405,12 +4405,6 @@ /obj/item/weapon/book/manual/security_space_law, /turf/simulated/floor/tiled, /area/centcom/security) -"pf" = ( -/obj/structure/bed/chair/shuttle{ - dir = 4 - }, -/turf/simulated/shuttle/floor, -/area/shuttle/escape) "pg" = ( /obj/structure/table/standard, /turf/simulated/floor/carpet, @@ -21031,9 +21025,9 @@ SA tQ tQ Ll -pf -pf -pf +Sc +Sc +Sc jh Sc Sc diff --git a/maps/groundbase/gb-z2.dmm b/maps/groundbase/gb-z2.dmm index 55007f41dba..fd74501e4d0 100644 --- a/maps/groundbase/gb-z2.dmm +++ b/maps/groundbase/gb-z2.dmm @@ -2774,8 +2774,8 @@ }, /obj/machinery/button/remote/blast_door{ dir = 4; - pixel_x = -25; - id = "chem_room" + id = "chem_room"; + pixel_x = -25 }, /turf/simulated/floor/tiled/white, /area/groundbase/medical/Chemistry) @@ -5088,14 +5088,8 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/machinery/requests_console{ - department = "Cargo Bay"; - departmentType = 2; - dir = 8; - pixel_x = 28 - }, -/turf/simulated/floor/wood, -/area/groundbase/cargo/qm) +/turf/simulated/floor/tiled, +/area/groundbase/cargo/storage) "ou" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -7271,7 +7265,13 @@ /turf/simulated/floor/wood, /area/groundbase/civilian/library) "uA" = ( -/obj/structure/closet/secure_closet/cargotech, +/obj/structure/table/standard, +/obj/item/clothing/under/pizzaguy, +/obj/item/clothing/under/pizzaguy, +/obj/item/clothing/under/pizzaguy, +/obj/item/clothing/head/pizzaguy, +/obj/item/clothing/head/pizzaguy, +/obj/item/clothing/head/pizzaguy, /turf/simulated/floor/tiled, /area/groundbase/cargo/storage) "uC" = ( @@ -7777,9 +7777,9 @@ /obj/structure/window/reinforced/full, /obj/machinery/door/firedoor, /obj/machinery/door/blast/regular{ + dir = 4; id = "chem_room"; - name = "Chemistry Shutters"; - dir = 4 + name = "Chemistry Shutters" }, /turf/simulated/floor, /area/groundbase/medical/Chemistry)