diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ad29125d95..899ef16306 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -221,9 +221,10 @@ else // A variation of get_hear inlined here to take advantage of the compiler's fastpath for obj/mob in view var/lum = T.luminosity T.luminosity = 6 // This is the maximum luminosity - for(var/mob/M in view(R, T)) + var/list/cachedview = view(R, T) + for(var/mob/M in cachedview) processing_list += M - for(var/obj/O in view(R, T)) + for(var/obj/O in cachedview) processing_list += O T.luminosity = lum diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 03c60be91c..7284b3c738 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -81,6 +81,12 @@ to_chat(usr, "The drip beeps: Warning, incompatible creature!") return + var/mob/living/L + if(isliving(target)) + L = target + if(!L.can_inject(usr, 1)) + return + if(Adjacent(target) && usr.Adjacent(target)) if(beaker) usr.visible_message("[usr] attaches [src] to [target].", "You attach [src] to [target].") diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index bb3a4442b3..4f17f5d762 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -816,10 +816,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
" dat += "
[gear_tab]
" dat += "
" - dat += "Name" - dat += "Cost" - dat += "Restrictions" - dat += "Description" + dat += "Name" + dat += "Cost" + dat += "Restrictions" + dat += "Description" for(var/j in GLOB.loadout_items[gear_tab]) var/datum/gear/gear = GLOB.loadout_items[gear_tab][j] var/donoritem diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index f47361e794..8bd7065c1f 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -27,14 +27,19 @@ if("mam_snouts" in pref_species.default_features) if(H.dna.features["mam_snouts"] != "None") muzzle_var = ALT_STYLE + else + muzzle_var = NORMAL_STYLE else if("snout" in pref_species.default_features) if(H.dna.features["snout"] != "None") muzzle_var = ALT_STYLE + else + muzzle_var = NORMAL_STYLE else muzzle_var = NORMAL_STYLE - H.update_inv_head() + + H.update_inv_head() /obj/item/clothing/head/worn_overlays(isinhands = FALSE) . = list() diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index ea4c9e16b7..8f10184f86 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -30,10 +30,15 @@ if("mam_snouts" in pref_species.default_features) if(H.dna.features["mam_snouts"] != "None") muzzle_var = ALT_STYLE + else + muzzle_var = NORMAL_STYLE else if("snout" in pref_species.default_features) if(H.dna.features["snout"] != "None") muzzle_var = ALT_STYLE + else + muzzle_var = NORMAL_STYLE + else muzzle_var = NORMAL_STYLE diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index 86ede7f255..75833fc086 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -13,16 +13,49 @@ var/list/vents = list() var/randomProbability = 1 var/reagentsAmount = 100 - var/list/saferChems = list("water","carbon","flour","cleaner","nutriment","condensedcapsaicin","mushroomhallucinogen","lube","pink_glitter","cryptobiolin", - "plantbgone","blood","charcoal","space_drugs","morphine","holywater","ethanol","hot_coco","sacid","mindbreaker","rotatium","bluespace", - "pax","laughter","concentrated_barbers_aid","colorful_reagent","dizzysolution","tiresolution","sodiumchloride","beer","hair_dye","sugar","white_glitter","growthserum") + var/list/saferChems = list( + "water", + "carbon", + "flour", + "cleaner", + "nutriment", + "condensedcapsaicin", + "mushroomhallucinogen", + "lube", + "pink_glitter", + "cryptobiolin", + "plantbgone", + "blood", + "charcoal", + "space_drugs", + "morphine", + "holywater", + "ethanol", + "hot_coco", + "sacid", + "mindbreaker", + "rotatium", + "bluespace", + "pax", + "laughter", + "concentrated_barbers_aid", + "colorful_reagent", + "dizzysolution", + "tiresolution", + "sodiumchloride", + "beer", + "hair_dye", + "sugar", + "white_glitter", + "growthserum" + ) //needs to be chemid unit checked at some point /datum/round_event/vent_clog/announce() priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert") /datum/round_event/vent_clog/setup() - endWhen = rand(25, 100) + endWhen = rand(120, 180) for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in GLOB.machines) var/turf/T = get_turf(temp_vent) if(T && is_station_level(T.z) && !temp_vent.welded) @@ -30,25 +63,34 @@ if(!vents.len) return kill() -/datum/round_event/vent_clog/start() - for(var/obj/machinery/atmospherics/components/unary/vent in vents) - if(vent && vent.loc) - var/datum/reagents/R = new/datum/reagents(1000) - R.my_atom = vent - if (prob(randomProbability)) - R.add_reagent(get_random_reagent_id(), reagentsAmount) - else - R.add_reagent(pick(saferChems), reagentsAmount) +/datum/round_event/vent_clog/tick() - var/datum/effect_system/foam_spread/foam = new - foam.set_up(200, get_turf(vent), R) - foam.start() + if(!vents.len) + return kill() - var/cockroaches = prob(33) ? 3 : 0 - while(cockroaches) - new /mob/living/simple_animal/cockroach(get_turf(vent)) - cockroaches-- - CHECK_TICK + CHECK_TICK + + var/obj/machinery/atmospherics/components/unary/vent = pick(vents) + vents -= vent + + if(!vent) + return + + var/turf/T = get_turf(vent) + if(!T) + return + + var/datum/reagents/R = new/datum/reagents(1000) + R.my_atom = vent + if (prob(randomProbability)) + R.add_reagent(get_random_reagent_id(), reagentsAmount) + else + R.add_reagent(pick(saferChems), reagentsAmount) + + var/datum/effect_system/smoke_spread/chem/C = new + C.set_up(R,16,T,TRUE) + C.start() + playsound(T, 'sound/effects/smoke.ogg', 50, 1, -3) /datum/round_event_control/vent_clog/threatening name = "Clogged Vents: Threatening" diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 6e8b0cb777..a7c58e8669 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -1309,4 +1309,35 @@ set_pin_data(IC_OUTPUT, 2, regurgitated_contents) push_data() + activate_pin(2) + +//Degens +/obj/item/integrated_circuit/input/bonermeter + name = "bonermeter" + desc = "Detects the target's arousal and various statistics about the target's arousal levels. Invasive!" + icon_state = "medscan" + complexity = 4 + inputs = list("target" = IC_PINTYPE_REF) + outputs = list( + "current arousal" = IC_PINTYPE_NUMBER, + "minimum arousal" = IC_PINTYPE_NUMBER, + "maximum arousal" = IC_PINTYPE_NUMBER, + "can be aroused" = IC_PINTYPE_BOOLEAN + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 40 + +/obj/item/integrated_circuit/input/bonermeter/do_work() + + var/mob/living/L = get_pin_data_as_type(IC_INPUT, 1, /mob/living) + + if(!istype(L) || !L.Adjacent(get_turf(src)) ) //Invalid input + return + + set_pin_data(IC_OUTPUT, 1, L.getArousalLoss()) + set_pin_data(IC_OUTPUT, 2, L.min_arousal) + set_pin_data(IC_OUTPUT, 3, L.max_arousal) + set_pin_data(IC_OUTPUT, 4, L.canbearoused) + push_data() activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index f63d58b707..c187f49473 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -144,7 +144,7 @@ w_class = WEIGHT_CLASS_SMALL complexity = 10 cooldown_per_use = 1 - ext_cooldown = 1 + ext_cooldown = 2 inputs = list("direction" = IC_PINTYPE_DIR) outputs = list("obstacle" = IC_PINTYPE_REF) activators = list("step towards dir" = IC_PINTYPE_PULSE_IN,"on step"=IC_PINTYPE_PULSE_OUT,"blocked"=IC_PINTYPE_PULSE_OUT) diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index b9bd4627c4..1959fb55c7 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -125,7 +125,7 @@ name = "man-machine interface tank" desc = "This circuit is just a jar filled with an artificial liquid mimicking the cerebrospinal fluid." extended_desc = "This jar can hold 1 man-machine interface and let it take control of some basic functions of the assembly." - complexity = 29 + complexity = 60 inputs = list("laws" = IC_PINTYPE_LIST) outputs = list( "man-machine interface" = IC_PINTYPE_REF, @@ -254,7 +254,7 @@ name = "pAI connector circuit" desc = "This circuit lets you fit in a personal artificial intelligence to give it some form of control over the bot." extended_desc = "You can wire various functions to it." - complexity = 29 + complexity = 60 inputs = list("laws" = IC_PINTYPE_LIST) outputs = list( "personal artificial intelligence" = IC_PINTYPE_REF, diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 4d631691d0..c2abc2f2c5 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -963,7 +963,7 @@ prereq_ids = list("biotech","engineering") boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor, - /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor) + /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) export_price = 20000 hidden = TRUE diff --git a/html/changelogs/AutoChangeLog-pr-8182.yml b/html/changelogs/AutoChangeLog-pr-8182.yml new file mode 100644 index 0000000000..8247409f1b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8182.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - code_imp: "get_hearers_in_view() now actually caches the results of view() instead of calling view() twice" diff --git a/html/changelogs/AutoChangeLog-pr-8252.yml b/html/changelogs/AutoChangeLog-pr-8252.yml new file mode 100644 index 0000000000..c86d0b5aa0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8252.yml @@ -0,0 +1,6 @@ +author: "BurgerBB" +delete-after: True +changes: + - rscadd: "Adds the bonermeter; a device that measures arousal based statistics." + - refactor: "Added a new input to the electrostimulator that controls the strength of the shock. It accepts negative inputs which reduce arousal. Added a new output to the electrostimulator that displays the amount of arousal gained." + - balance: "Rebalanced the electro-stimulator to be less spammy by giving it a 2.5 second enforced cooldown per circuit contraption. Increased the complexity of electro stimulator from 10 to 15." diff --git a/html/changelogs/AutoChangeLog-pr-8255.yml b/html/changelogs/AutoChangeLog-pr-8255.yml new file mode 100644 index 0000000000..1b2e81f5bd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8255.yml @@ -0,0 +1,4 @@ +author: "BurgerB" +delete-after: True +changes: + - tweak: "Tweaked the UI of the loadout to be less cluttered due to an issue with formatting." diff --git a/html/changelogs/AutoChangeLog-pr-8258.yml b/html/changelogs/AutoChangeLog-pr-8258.yml new file mode 100644 index 0000000000..2d1f75603f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8258.yml @@ -0,0 +1,4 @@ +author: "BurgerBB" +delete-after: True +changes: + - refactor: "Reworked the Vent Clog event to spray smoke instead of foam, also made it shoot smoke over time instead through each vent instead of all at once." diff --git a/html/changelogs/AutoChangeLog-pr-8259.yml b/html/changelogs/AutoChangeLog-pr-8259.yml new file mode 100644 index 0000000000..54a1dd6a4b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8259.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - balance: "Locomotion circuits are now restricted to jogging speed" + - balance: "MMI circuits and pAI circuits both now have 60 complexity, up from their original 29." diff --git a/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm b/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm index 79d229c757..246205f7b6 100644 --- a/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -1,33 +1,54 @@ /obj/item/integrated_circuit/manipulation/electric_stimulator name = "electronic stimulation module" - desc = "Used to induce sexual stimulation with electricity." + desc = "Used to induce sexual stimulation in a target via electricity." icon_state = "power_relay" - extended_desc = "The circuit accepts a reference to a person and upon activation, attempts to stimulate them to orgasm." - complexity = 10 - size = 3 - inputs = list("target" = IC_PINTYPE_REF) - outputs = list() - activators = list("fire" = IC_PINTYPE_PULSE_IN) + extended_desc = "The circuit accepts a reference to a person, as well as a number representing the strength of the shock, and upon activation, attempts to stimulate them to orgasm. The number ranges from -35 to 35, with negative numbers reducing arousal and positive numbers increasing it by that amount." + complexity = 15 + size = 2 + inputs = list("target" = IC_PINTYPE_REF, "strength" = IC_PINTYPE_NUMBER) + outputs = list("arousal gain"=IC_PINTYPE_NUMBER) + activators = list("fire" = IC_PINTYPE_PULSE_IN, "on success" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT, "on orgasm" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 500 cooldown_per_use = 50 + ext_cooldown = 25 /obj/item/integrated_circuit/manipulation/electric_stimulator/do_work() ..() + set_pin_data(IC_OUTPUT, 1, 0) var/mob/living/M = get_pin_data_as_type(IC_INPUT, 1, /mob/living) if(!check_target(M)) return - if(ismob(M) && M.canbearoused) - if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna()) - var/mob/living/carbon/human/H = M - var/orgasm_message = pick("A sharp pulse of electricity pushes you to orgasm!", "You feel a jolt of electricity force you into orgasm!") - H.visible_message("\The [assembly] electrodes shock [H]!", "[orgasm_message]") - playsound(src, "sound/effects/light_flicker.ogg", 30, 1) - H.mob_climax(forced_climax=TRUE) + + var/arousal_gain = CLAMP(get_pin_data(IC_INPUT, 2),-35,35) + set_pin_data(IC_OUTPUT, 1, arousal_gain) + + if(ismob(M) && M.canbearoused && arousal_gain != 0) + var/orgasm = FALSE + if(arousal_gain > 0) + if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna()) + var/mob/living/carbon/human/H = M + var/orgasm_message = pick("A sharp pulse of electricity pushes you to orgasm!", "You feel a jolt of electricity force you into orgasm!") + H.visible_message("\The [assembly] electrodes shock [H]!", "[orgasm_message]") + playsound(src, "sound/effects/light_flicker.ogg", 30, 1) + H.mob_climax(forced_climax=TRUE) + orgasm = TRUE + else + M.adjustArousalLoss(arousal_gain) + var/stimulate_message = pick("You feel a sharp warming tingle of electricity through your body!", "A burst of arousing electricity flows through your body!") + M.visible_message("\The [assembly] electrodes shock [M]!", "[stimulate_message]") + else - M.adjustArousalLoss(35) - var/stimulate_message = pick("You feel a sharp warming tingle of electricity through your body!", "A burst of arousing electricity flows through your body!") + var/stimulate_message = pick("You feel a dull prickle of electricity through your body!", "A burst of dull electricity flows through your body!") M.visible_message("\The [assembly] electrodes shock [M]!", "[stimulate_message]") - playsound(src, "sound/effects/light_flicker.ogg", 30, 1) + M.adjustArousalLoss(arousal_gain) + + playsound(src, "sound/effects/light_flicker.ogg", 30, 1) + push_data() + activate_pin(2) + if(orgasm) activate_pin(4) + else visible_message("\The [assembly] electrodes fail to shock [M]!") + push_data() + activate_pin(3) diff --git a/modular_citadel/code/modules/mentor/mentorpm.dm b/modular_citadel/code/modules/mentor/mentorpm.dm index 4184a4abef..34ace6f002 100644 --- a/modular_citadel/code/modules/mentor/mentorpm.dm +++ b/modular_citadel/code/modules/mentor/mentorpm.dm @@ -70,16 +70,16 @@ else //recipient is an mentor but sender is not to_chat(C, "Reply PM from-[key_name_mentor(src, C, 1, 0, show_char)]: [msg]") - to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, 0)]: [msg]") + to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, 0)]: [msg]") else if(is_mentor()) //sender is an mentor but recipient is not. to_chat(C, "Mentor PM from-[key_name_mentor(src, C, 1, 0, 0)]: [msg]") - to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, show_char)]: [msg]") + to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, show_char)]: [msg]") //we don't use message_Mentors here because the sender/receiver might get it too var/show_char_sender = !is_mentor() && CONFIG_GET(flag/mentors_mobname_only) var/show_char_recip = !C.is_mentor() && CONFIG_GET(flag/mentors_mobname_only) for(var/client/X in GLOB.mentors | GLOB.admins) if(X.key!=key && X.key!=C.key) //check client/X is an Mentor and isn't the sender or recipient - to_chat(X, "Mentor PM: [key_name_mentor(src, X, 0, 0, show_char_sender)]->[key_name_mentor(C, X, 0, 0, show_char_recip)]: [msg]") //inform X \ No newline at end of file + to_chat(X, "Mentor PM: [key_name_mentor(src, X, 0, 0, show_char_sender)]->[key_name_mentor(C, X, 0, 0, show_char_recip)]: [msg]") //inform X diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm index 017a9dd52d..df41a79592 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm @@ -55,7 +55,7 @@ /obj/item/projectile/bullet/nlmags //non-lethal boolets icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' icon_state = "magjectile-nl" - damage = 0 + damage = 2 knockdown = 0 stamina = 25 armour_penetration = -10 @@ -210,7 +210,7 @@ /obj/item/projectile/bullet/nlmagrifle //non-lethal boolets icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' icon_state = "magjectile-large-nl" - damage = 0 + damage = 2 knockdown = 0 stamina = 25 armour_penetration = -10 diff --git a/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm b/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm index e931f37520..22085d520c 100644 --- a/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm +++ b/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm @@ -232,10 +232,11 @@ M.forceMove(drop_location()) // Move the belly contents into the same location as belly's owner. items_preserved -= M - for(var/mob/H in get_hearers_in_view(2, get_turf(owner))) - if(H.client && (H.client.prefs.cit_toggles & EATING_NOISES)) - var/sound/releasement = GLOB.release_sounds[release_sound] - playsound(get_turf(owner),releasement,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED) + if(!silent) + for(var/mob/H in get_hearers_in_view(2, get_turf(owner))) + if(H.client && (H.client.prefs.cit_toggles & EATING_NOISES)) + var/sound/releasement = GLOB.release_sounds[release_sound] + playsound(get_turf(owner),releasement,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED) if(istype(M,/mob/living)) var/mob/living/ML = M diff --git a/modular_citadel/code/modules/vore/eating/living_vr.dm b/modular_citadel/code/modules/vore/eating/living_vr.dm index b1d2a46ff2..a8a77895c8 100644 --- a/modular_citadel/code/modules/vore/eating/living_vr.dm +++ b/modular_citadel/code/modules/vore/eating/living_vr.dm @@ -289,8 +289,7 @@ if(!confirm == "Okay" || loc != B) return //Actual escaping - forceMove(get_turf(src)) //Just move me up to the turf, let's not cascade through bellies, there's been a problem, let's just leave. - src.cure_blind("belly_[REF(src)]") + B.release_specific_contents(src,TRUE) //we might as well take advantage of that specific belly's handling. Else we stay blinded forever. src.stop_sound_channel(CHANNEL_PREYLOOP) SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey) for(var/mob/living/simple_animal/SA in range(10)) diff --git a/modular_citadel/icons/mob/muzzled_helmet.dmi b/modular_citadel/icons/mob/muzzled_helmet.dmi index 3c0a229d58..36313cce66 100644 Binary files a/modular_citadel/icons/mob/muzzled_helmet.dmi and b/modular_citadel/icons/mob/muzzled_helmet.dmi differ