diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index f4dcd49664160..3725c549df4e5 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -133,3 +133,7 @@ #define COMSIG_ATOM_PRE_CLEAN "atom_pre_clean" ///cancel clean #define COMSIG_ATOM_CANCEL_CLEAN (1<<0) + +/// From /obj/effect/particle_effect/sparks/proc/sparks_touched(datum/source, atom/movable/singed) +#define COMSIG_ATOM_TOUCHED_SPARKS "atom_touched_sparks" +#define COMSIG_ATOM_TOUCHED_HAZARDOUS_SPARKS "atom_touched_hazardous_sparks" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 5237132e4b10e..06f81e742adfe 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -331,6 +331,9 @@ GLOBAL_LIST_INIT(skin_tone_names, list( /proc/deadchat_broadcast(message, source=null, mob/follow_target=null, turf/turf_target=null, speaker_key=null, message_type=DEADCHAT_REGULAR, admin_only=FALSE) message = span_deadsay("[source][span_linkify(message)]") + if(admin_only) + message += span_deadsay(" (This is viewable to admins only).") + for(var/mob/M in GLOB.player_list) var/chat_toggles = TOGGLES_DEFAULT_CHAT var/toggles = TOGGLES_DEFAULT @@ -341,10 +344,8 @@ GLOBAL_LIST_INIT(skin_tone_names, list( toggles = prefs.toggles ignoring = prefs.ignoring if(admin_only) - if (!M.client?.holder) - return - else - message += span_deadsay(" (This is viewable to admins only).") + if(!M.client?.holder) + continue var/override = FALSE if(M.client?.holder && (chat_toggles & CHAT_DEAD)) override = TRUE diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index e1a60112c901f..ef882a5f96f28 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -76,7 +76,7 @@ ///lowers bloody_shoes[index] by adjust_by /datum/component/bloodysoles/proc/adjust_bloody_shoes(index, adjust_by) bloody_shoes[index] = max(bloody_shoes[index] - adjust_by, 0) - on_changed_bloody_shoes() + on_changed_bloody_shoes(index) /datum/component/bloodysoles/proc/set_bloody_shoes(index, new_value) bloody_shoes[index] = new_value diff --git a/code/datums/components/combustible_flooder.dm b/code/datums/components/combustible_flooder.dm index 5b5c7b61219b4..a4260a9641a9f 100644 --- a/code/datums/components/combustible_flooder.dm +++ b/code/datums/components/combustible_flooder.dm @@ -13,6 +13,7 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(attackby_react)) RegisterSignal(parent, COMSIG_ATOM_FIRE_ACT, PROC_REF(flame_react)) + RegisterSignal(parent, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(sparks_react)) RegisterSignal(parent, COMSIG_ATOM_BULLET_ACT, PROC_REF(projectile_react)) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(welder_react)) if(isturf(parent)) @@ -62,6 +63,13 @@ if(exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) flood(null, exposed_temperature) +/// sparks_touched reaction. +/datum/component/combustible_flooder/proc/sparks_react(datum/source, obj/effect/particle_effect/sparks/sparks) + SIGNAL_HANDLER + + if(sparks) // this shouldn't ever be false but existence is mysterious + flood(null, FIRE_MINIMUM_TEMPERATURE_TO_SPREAD) + /// Hotspot reaction. /datum/component/combustible_flooder/proc/hotspots_react(datum/source, air, exposed_temperature) SIGNAL_HANDLER diff --git a/code/datums/elements/food/processable.dm b/code/datums/elements/food/processable.dm index 625dba6149495..9ca96b3821b21 100644 --- a/code/datums/elements/food/processable.dm +++ b/code/datums/elements/food/processable.dm @@ -46,7 +46,7 @@ var/found_location = found_item.loc var/found_turf = isturf(found_location) var/found_table = locate(/obj/structure/table) in found_location - var/found_tray = locate(/obj/item/storage/bag/tray) in found_location + var/found_tray = locate(/obj/item/storage/bag/tray) in found_location || locate(/obj/item/plate/oven_tray) in found_location if(!found_turf && !istype(found_location, /obj/item/storage/bag/tray) || found_turf && !(found_table || found_tray)) to_chat(user, span_notice("You cannot make [initial(result_atom_type.name)] here! You need a table or at least a tray.")) return diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index 7c426e921e00c..fc952b8a9e23c 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -52,6 +52,11 @@ if (!isnull(should_strip_proc_path) && !call(source, should_strip_proc_path)(user)) return + if (isliving(source)) + var/mob/living/mob = source + if (mob.can_be_held && (user.grab_state == GRAB_AGGRESSIVE) && (user.pulling == source)) + return + var/datum/strip_menu/strip_menu = LAZYACCESS(strip_menus, source) if (isnull(strip_menu)) diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index dd625ab919aca..46c31c4578d1d 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -136,6 +136,18 @@ /// Type of mob light emitter we use when on fire var/moblight_type = /obj/effect/dummy/lighting_obj/moblight/fire +/datum/status_effect/fire_handler/fire_stacks/proc/owner_touched_sparks() + SIGNAL_HANDLER + + ignite() + +/datum/status_effect/fire_handler/fire_stacks/on_creation(mob/living/new_owner, new_stacks, forced = FALSE) + . = ..() + RegisterSignal(owner, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(owner_touched_sparks)) + +/datum/status_effect/fire_handler/fire_stacks/on_remove() + UnregisterSignal(owner, COMSIG_ATOM_TOUCHED_SPARKS) + /datum/status_effect/fire_handler/fire_stacks/tick(seconds_between_ticks) if(stacks <= 0) qdel(src) diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 7b6632e3cab01..21804def7e361 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -333,33 +333,33 @@ GLOBAL_LIST_INIT(dye_registry, list( default_unfasten_wrench(user, tool) return ITEM_INTERACT_SUCCESS -/obj/machinery/washing_machine/attackby(obj/item/W, mob/living/user, params) - if(default_deconstruction_screwdriver(user, null, null, W)) - update_appearance() - return - - else if(!user.combat_mode) - if (!state_open) - to_chat(user, span_warning("Open the door first!")) - return TRUE - - if(bloody_mess) - to_chat(user, span_warning("[src] must be cleaned up first!")) - return TRUE - - if(contents.len >= max_wash_capacity) - to_chat(user, span_warning("The washing machine is full!")) - return TRUE - - if(!user.transferItemToLoc(W, src)) - to_chat(user, span_warning("\The [W] is stuck to your hand, you cannot put it in the washing machine!")) - return TRUE - if(W.dye_color) - color_source = W +/obj/machinery/washing_machine/screwdriver_act(mob/living/user, obj/item/tool) + if (!state_open) + default_deconstruction_screwdriver(user, null, null, tool) update_appearance() + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + +/obj/machinery/washing_machine/item_interaction(mob/living/user, obj/item/item, list/modifiers) + if(user.combat_mode) + return NONE + if (!state_open) + to_chat(user, span_warning("Open the door first!")) + return ITEM_INTERACT_BLOCKING + if(bloody_mess) + to_chat(user, span_warning("[src] must be cleaned up first!")) + return ITEM_INTERACT_BLOCKING + if(contents.len >= max_wash_capacity) + to_chat(user, span_warning("The washing machine is full!")) + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(item, src)) + to_chat(user, span_warning("\The [item] is stuck to your hand, you cannot put it in the washing machine!")) + return ITEM_INTERACT_BLOCKING + if(item.dye_color) + color_source = item + update_appearance() + return ITEM_INTERACT_SUCCESS - else - return ..() /obj/machinery/washing_machine/attack_hand(mob/living/user, list/modifiers) . = ..() diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index b99c8000c58a4..fcc4afa14944d 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -458,6 +458,7 @@ COMSIG_TURF_MOVABLE_THROW_LANDED = PROC_REF(ignition_trigger), ) AddElement(/datum/element/connect_loc, ignition_trigger_connections) + RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(ignition_trigger)) for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf if(pool == src) continue @@ -532,6 +533,8 @@ var/mob/living/enflamed_liver = enflammable_atom if(enflamed_liver.on_fire) ignite() + else if(istype(enflammable_atom, /obj/effect/particle_effect/sparks)) + ignite() /obj/effect/decal/cleanable/fuel_pool/hivis diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index c715cc1d7457d..d7acb25fde459 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -57,6 +57,7 @@ */ /obj/effect/particle_effect/sparks/proc/affect_location(turf/location, just_initialized = FALSE) location.hotspot_expose(1000,100) + SEND_SIGNAL(location, COMSIG_ATOM_TOUCHED_SPARKS, src) // for plasma floors; other floor types only have to worry about the mysterious HAZARDOUS sparks if(just_initialized) for(var/atom/movable/singed in location) sparks_touched(src, singed) @@ -67,43 +68,27 @@ * This is invoked by the signals sent by every atom when they're crossed or crossing something. It * signifies that something has been touched by sparks, and should be affected by possible pyrotechnic affects.. * datum/source - Can either be the spark itself or an object that just walked into it -* mob/living/singed_mob - The mob that was touched by the spark +* mob/living/singed - What was touched by the spark */ -/obj/effect/particle_effect/sparks/proc/sparks_touched(datum/source, atom/movable/singed) +/obj/effect/particle_effect/sparks/proc/sparks_touched(datum/source, atom/singed) SIGNAL_HANDLER + SEND_SIGNAL(singed, COMSIG_ATOM_TOUCHED_SPARKS, src) if(isobj(singed)) - var/obj/singed_obj = singed - if(singed_obj.reagents) - var/datum/reagents/reagents = singed_obj.reagents // heat up things that contain reagents before we check to see if they burn + if(singed.reagents) + var/datum/reagents/reagents = singed.reagents // heat up things that contain reagents before we check to see if they burn reagents?.expose_temperature(1000) // we set this at 1000 because that's the max reagent temp for a chem heater, higher temps require more than sparks - if(singed_obj.custom_materials && (GET_MATERIAL_REF(/datum/material/plasma) in singed_obj.custom_materials)) - singed_obj.fire_act(FIRE_MINIMUM_TEMPERATURE_TO_SPREAD,100) - return // if it's made of plasma we just start burning no matter what, even furniture (see right below) - if(isstructure(singed_obj) || ismachinery(singed_obj)) // don't ignite furniture even if it's flammable, leave that to actual fires - return - if(singed_obj.resistance_flags & FLAMMABLE && !(singed_obj.resistance_flags & ON_FIRE)) //only fire_act flammable objects instead of burning EVERYTHING - if(isitem(singed_obj)) - var/obj/item/singed_item = singed_obj - var/ignite_chance = 120 // base chance applies to anything under WEIGHT_CLASS_NORMAL, so burn everything flammable that's small/tiny - if(singed_item.w_class > WEIGHT_CLASS_SMALL) - var/ignite_chance_penalty = (singed_item.w_class * 2 + round(singed_item.w_class * 0.5)) * 10 // size penalties to ignite chance: normal = 70, bulky = 100, - ignite_chance -= ignite_chance_penalty // the bigger the item, the less likely it is to ignite - if(prob(ignite_chance)) - singed_item.fire_act(FIRE_MINIMUM_TEMPERATURE_TO_SPREAD,100) - return - else - singed_obj.fire_act(FIRE_MINIMUM_TEMPERATURE_TO_SPREAD,100) - return - if(isliving(singed)) - var/mob/living/singed_living = singed - if(singed_living.fire_stacks) - singed_living.ignite_mob(FALSE) //ignite the mob, silent = FALSE (You're set on fire!) return + if(ishuman(singed)) + var/mob/living/carbon/human/singed_human = singed + for(var/obj/item/anything in singed_human.get_visible_items()) + sparks_touched(src, anything) /datum/effect_system/spark_spread effect_type = /obj/effect/particle_effect/sparks + + /datum/effect_system/spark_spread/quantum effect_type = /obj/effect/particle_effect/sparks/quantum diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index be5d0b8ec2b1c..7c0ebfda5f4a8 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -189,6 +189,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM light() AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH), slot_flags) //90% to knock off when wearing a mask AddElement(/datum/element/update_icon_updates_onmob) + RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(sparks_touched)) icon_state = icon_off inhand_icon_state = inhand_icon_off @@ -306,6 +307,14 @@ CIGARETTE PACKETS ARE IN FANCY.DM icon_state = icon_off inhand_icon_state = inhand_icon_off + +/obj/item/clothing/mask/cigarette/proc/sparks_touched(datum/source, obj/effect/particle_effect) + SIGNAL_HANDLER + + if(lit) + return + light() + /// Lights the cigarette with given flavor text. /obj/item/clothing/mask/cigarette/proc/light(flavor_text = null) if(lit) diff --git a/code/game/objects/items/dna_probe.dm b/code/game/objects/items/dna_probe.dm index f299a9254f80e..ee6a32766522f 100644 --- a/code/game/objects/items/dna_probe.dm +++ b/code/game/objects/items/dna_probe.dm @@ -31,19 +31,46 @@ var/datum/weakref/dna_vault_ref /obj/item/dna_probe/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - if(istype(interacting_with, /obj/machinery/dna_vault) && !dna_vault_ref?.resolve()) - try_linking_vault(interacting_with, user) - else - scan_dna(interacting_with, user) + if(istype(interacting_with, /obj/machinery/dna_vault)) + if(dna_vault_ref?.resolve()) + // Weirdly we can upload to any existing DNA vault so long as we're linked to any other existing DNA vault. + return try_upload_dna(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + else + return try_linking_vault(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + + scan_dna(interacting_with, user) return ITEM_INTERACT_BLOCKING -/obj/item/dna_probe/proc/try_linking_vault(atom/target, mob/user) +/obj/item/dna_probe/proc/try_linking_vault(obj/machinery/dna_vault/target, mob/user) var/obj/machinery/dna_vault/our_vault = dna_vault_ref?.resolve() if(!our_vault) dna_vault_ref = WEAKREF(target)//linking the dna vault with the probe balloon_alert(user, "vault linked") playsound(src, 'sound/machines/terminal_success.ogg', 50) - return + return TRUE + return FALSE + +/obj/item/dna_probe/proc/try_upload_dna(obj/machinery/dna_vault/target, mob/user) + var/uploaded = 0 + var/plant_dna_length = length(stored_dna_plants) + var/human_dna_length = length(stored_dna_human) + var/animal_dna_length = length(stored_dna_animal) + if(plant_dna_length) + uploaded += plant_dna_length + target.plant_dna += stored_dna_plants + stored_dna_plants.Cut() + if(human_dna_length) + uploaded += human_dna_length + target.human_dna += stored_dna_human + stored_dna_human.Cut() + if(animal_dna_length) + uploaded += animal_dna_length + target.animal_dna += stored_dna_animal + stored_dna_animal.Cut() + target.check_goal() + playsound(target, 'sound/misc/compiler-stage1.ogg', 50) + to_chat(user, span_notice("[uploaded] new datapoints uploaded.")) + return uploaded /obj/item/dna_probe/proc/scan_dna(atom/target, mob/user) var/obj/machinery/dna_vault/our_vault = dna_vault_ref?.resolve() diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index 89efdd35b97ac..74472995b688e 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -22,6 +22,62 @@ user.visible_message(span_notice("[user] shows you: [icon2html(src, viewers(user))] [name]."), span_notice("You show [src].")) add_fingerprint(user) +/obj/item/card/emag/emag_act(mob/user, obj/item/card/emag/emag_card) + if(isnull(user) || !istype(emag_card)) + return FALSE + var/emag_count = 0 + for(var/obj/item/card/emag/emag in get_all_contents() + emag_card.get_all_contents()) // This is including itself + emag_count++ + if(emag_count > 6) // 1 uplink's worth is the limit + to_chat(user, span_warning("Nope, lesson learned. No more.")) + return FALSE + if(emag_card.loc != loc) // Both have to be in your hand (or TK shenanigans) + return FALSE + if(!user.transferItemToLoc(emag_card, src, silent = FALSE)) + return FALSE + + user.visible_message( + span_notice("[user] holds [emag_card] to [src], getting the two cards stuck together!"), + span_notice("As you hold [emag_card] to [src], [emag_card.p_their()] magnets attract to one another, \ + and [emag_card.p_they()] become stuck together!"), + visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE, + ) + playsound(src, 'sound/effects/bang.ogg', 33, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + addtimer(CALLBACK(src, PROC_REF(contemplation_period), user), 2 SECONDS, TIMER_DELETE_ME) + emag_card.vis_flags |= VIS_INHERIT_ID|VIS_INHERIT_PLANE + vis_contents += emag_card + name = initial(name) + desc = initial(desc) + var/list/all_emags = get_all_contents_type(/obj/item/card/emag) - src + for(var/i in 1 to length(all_emags)) + var/obj/item/card/emag/other_emag = all_emags[i] + other_emag.pixel_x = pixel_x + (4 * i) + other_emag.pixel_y = pixel_y + (4 * i) + other_emag.layer = layer - (0.01 * i) + name += "-[initial(other_emag.name)]" + desc += " There seems to be another card stuck to it...pretty soundly." + return TRUE + +/obj/item/card/emag/proc/contemplation_period(mob/user) + if(QDELETED(user)) + return + if(QDELETED(src)) + to_chat(user, span_notice("Oh, well.")) + else + to_chat(user, span_warning("Well, shit. Those are never coming apart now.")) + +/obj/item/card/emag/Exited(atom/movable/gone, direction) + . = ..() + if(istype(gone, /obj/item/card/emag)) + // This is here so if(when) admins fish it out of contents it doesn't become glitchy + gone.layer = initial(gone.layer) + gone.vis_flags = initial(gone.vis_flags) + vis_contents -= gone + name = initial(name) + desc = initial(desc) + gone.name = initial(name) + gone.desc = initial(desc) + /obj/item/card/emag/bluespace name = "bluespace cryptographic sequencer" desc = "It's a blue card with a magnetic strip attached to some circuitry. It appears to have some sort of transmitter attached to it." @@ -34,11 +90,14 @@ icon_state = "hack_o_lantern" /obj/item/card/emagfake - desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"Donk Co.\" logo stamped on the back." - name = "cryptographic sequencer" - icon_state = "emag" + name = /obj/item/card/emag::name + desc = /obj/item/card/emag::desc + " Closer inspection shows that this card is a poorly made replica, with a \"Donk Co.\" logo stamped on the back." + icon = /obj/item/card/emag::icon + icon_state = /obj/item/card/emag::icon_state + worn_icon_state = /obj/item/card/emag::worn_icon_state slot_flags = ITEM_SLOT_ID - worn_icon_state = "emag" + /// Whether we are exploding + var/exploding = FALSE /obj/item/card/emagfake/attack_self(mob/user) //for assistants with balls of plasteel if(Adjacent(user)) @@ -46,9 +105,34 @@ add_fingerprint(user) /obj/item/card/emagfake/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE) + if(exploding) + playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE, frequency = 2) + else if(obj_flags & EMAGGED) + log_bomber(user, "triggered", src, "(rigged/emagged)") + visible_message(span_boldwarning("[src] begins to heat up!")) + playsound(src, 'sound/items/bikehorn.ogg', 100, TRUE, frequency = 0.25) + addtimer(CALLBACK(src, PROC_REF(blow_up)), 1 SECONDS, TIMER_DELETE_ME) + exploding = TRUE + else + playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE) return ITEM_INTERACT_SKIP_TO_ATTACK // So it does the attack animation. +/obj/item/card/emagfake/proc/blow_up() + visible_message(span_boldwarning("[src] explodes!")) + explosion(src, light_impact_range = 1, explosion_cause = src) + qdel(src) + +/obj/item/card/emagfake/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + playsound(src, SFX_SPARKS, 50, TRUE, SILENCED_SOUND_EXTRARANGE) + desc = /obj/item/card/emag::desc + obj_flags |= EMAGGED + if(user) + balloon_alert(user, "rigged to blow") + log_bomber(user, "rigged to blow", src, "(emagging)") + return TRUE + /obj/item/card/emag/Initialize(mapload) . = ..() type_blacklist = list(typesof(/obj/machinery/door/airlock) + typesof(/obj/machinery/door/window/) + typesof(/obj/machinery/door/firedoor) - typesof(/obj/machinery/door/airlock/tram)) //list of all typepaths that require a specialized emag to hack. diff --git a/code/game/objects/items/maintenance_loot.dm b/code/game/objects/items/maintenance_loot.dm index f6d7fd1c3290d..e667aca6007d9 100644 --- a/code/game/objects/items/maintenance_loot.dm +++ b/code/game/objects/items/maintenance_loot.dm @@ -43,3 +43,4 @@ . = ..() var/initial_percent = rand(20, 80) / 100 charge = initial_percent * maxcharge + ADD_TRAIT(src, TRAIT_FISHING_BAIT, INNATE_TRAIT) diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm index 9c9c0b1b73a85..9a29ccbd9ef97 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -275,6 +275,7 @@ icon_state = "borghypo_s" tgui_theme = "syndicate" default_reagent_types = HACKED_MEDICAL_REAGENTS + expanded_reagent_types = null /// Peacekeeper hypospray /obj/item/reagent_containers/borghypo/peace diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index fe15dab29588e..b4d35efdda12a 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -36,7 +36,7 @@ var/igniting = FALSE /// The gases this tank contains. Don't modify this directly, use return_air() to get it instead var/datum/gas_mixture/air_contents = null - /// The volume of this tank. Among other things gas tank explosions (including TTVs) scale off of this. Be sure to account for that if you change this or you will break ~~toxins~~ordinance. + /// The volume of this tank. Among other things gas tank explosions (including TTVs) scale off of this. Be sure to account for that if you change this or you will break ~~toxins~~ ordinance. var/volume = TANK_STANDARD_VOLUME /// Whether the tank is currently leaking. var/leaking = FALSE @@ -83,11 +83,13 @@ /// Called by carbons after they connect the tank to their breathing apparatus. /obj/item/tank/proc/after_internals_opened(mob/living/carbon/carbon_target) breathing_mob = carbon_target + playsound(loc, 'sound/items/internals_on.ogg', 15, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) RegisterSignal(carbon_target, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) /// Called by carbons after they disconnect the tank from their breathing apparatus. /obj/item/tank/proc/after_internals_closed(mob/living/carbon/carbon_target) breathing_mob = null + playsound(loc, 'sound/items/internals_off.ogg', 15, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) UnregisterSignal(carbon_target, COMSIG_MOB_GET_STATUS_TAB_ITEMS) /obj/item/tank/proc/get_status_tab_item(mob/living/source, list/items) diff --git a/code/modules/escape_menu/home_page.dm b/code/modules/escape_menu/home_page.dm index a05aaf351e0df..5b1f76056777e 100644 --- a/code/modules/escape_menu/home_page.dm +++ b/code/modules/escape_menu/home_page.dm @@ -15,9 +15,20 @@ null, /* hud_owner = */ null, src, - "Settings", + "Character", /* offset = */ 2, - CALLBACK(src, PROC_REF(home_open_settings)), + CALLBACK(src, PROC_REF(home_open_charater_settings)), + ) + ) + + page_holder.give_screen_object( + new /atom/movable/screen/escape_menu/home_button( + null, + /* hud_owner = */ null, + src, + "Settings", + /* offset = */ 3, + CALLBACK(src, PROC_REF(home_open_game_settings)), ) ) @@ -27,7 +38,7 @@ /* hud_owner = */ src, src, "Admin Help", - /* offset = */ 3, + /* offset = */ 4, ) ) @@ -37,7 +48,7 @@ /* hud_owner = */ src, src, "Leave Body", - /* offset = */ 4, + /* offset = */ 5, CALLBACK(src, PROC_REF(open_leave_body)), ) ) @@ -45,7 +56,15 @@ /datum/escape_menu/proc/home_resume() qdel(src) -/datum/escape_menu/proc/home_open_settings() +/datum/escape_menu/proc/home_open_charater_settings() + client?.prefs.current_window = PREFERENCE_TAB_CHARACTER_PREFERENCES + client?.prefs.update_static_data(client?.mob) + client?.prefs.ui_interact(client?.mob) + qdel(src) + +/datum/escape_menu/proc/home_open_game_settings() + client?.prefs.current_window = PREFERENCE_TAB_GAME_PREFERENCES + client?.prefs.update_static_data(client?.mob) client?.prefs.ui_interact(client?.mob) qdel(src) diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm index 9423c8d8a4db0..27d43ea7dd280 100644 --- a/code/modules/fishing/fish/fish_types.dm +++ b/code/modules/fishing/fish/fish_types.dm @@ -316,6 +316,7 @@ random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS required_temperature_min = MIN_AQUARIUM_TEMP+10 required_temperature_max = MIN_AQUARIUM_TEMP+30 + favorite_bait = list(/obj/item/stock_parts/cell/lead) fish_traits = list( /datum/fish_trait/parthenogenesis, /datum/fish_trait/mixotroph, @@ -333,7 +334,6 @@ fish_traits = list(/datum/fish_trait/necrophage) required_temperature_min = MIN_AQUARIUM_TEMP+15 required_temperature_max = MIN_AQUARIUM_TEMP+35 - fish_ai_type = FISH_AI_ZIPPY favorite_bait = list( list( @@ -651,7 +651,7 @@ average_size = 30 average_weight = 500 random_case_rarity = FISH_RARITY_VERY_RARE - favorite_bait = list(/obj/item/food/bait/doughball) + favorite_bait = list(/obj/item/stock_parts/cell/lead) required_temperature_min = MIN_AQUARIUM_TEMP+18 required_temperature_max = MIN_AQUARIUM_TEMP+26 fish_traits = list( diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 9cc564df6f411..b748a5215b6a6 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -277,6 +277,8 @@ if(istype(bait, /obj/item/food/bait)) var/obj/item/food/bait/real_bait = bait bait_state = real_bait.rod_overlay_icon_state + if(istype(bait, /obj/item/stock_parts/cell/lead)) + bait_state = "battery_overlay" . += bait_state /obj/item/fishing_rod/worn_overlays(mutable_appearance/standing, isinhands, icon_file) diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index 8a6b3258a0ef7..392d716965d6a 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -302,6 +302,10 @@ to_chat(user, span_warning("There is nothing in [weapon] to put in [src]!")) return FALSE + if(!powered()) + to_chat(user, span_warning("\The [src]'s magnetic door won't open without power!")) + return FALSE + if(!user.combat_mode) to_chat(user, span_warning("\The [src] smartly refuses [weapon].")) return FALSE diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm index 4ae6bf19e1d4c..add7eecaf92e0 100644 --- a/code/modules/food_and_drinks/plate.dm +++ b/code/modules/food_and_drinks/plate.dm @@ -121,6 +121,7 @@ icon = 'icons/obj/service/kitchen.dmi' icon_state = "plate_shard1" base_icon_state = "plate_shard" + hitsound = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_TINY force = 5 throwforce = 5 @@ -131,6 +132,6 @@ /obj/item/plate_shard/Initialize(mapload) . = ..() - AddComponent(/datum/component/caltrop, min_damage = force) + AddComponent(/datum/component/caltrop, min_damage = force, paralyze_duration = 2 SECONDS, soundfile = hitsound) - icon_state = "[base_icon_state][pick(1,variants)]" + icon_state = "[base_icon_state][rand(1, variants)]" diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 44b7db6ee0b11..85fdeed5d887a 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -50,8 +50,9 @@ ///last mind to control this mob, for blood-based cloning var/datum/mind/last_mind = null - ///This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. + ///This is used to determine if the mob failed a breath. If they did fail a breath, they will attempt to breathe each tick, otherwise just once per 4 ticks. var/failed_last_breath = FALSE + /// Used in [carbon/proc/check_breath] and [lungs/proc/check_breath]] var/co2overloadtime = null diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 45ca4487184e3..de6a2692c9b6f 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -282,7 +282,7 @@ update_mob_action_buttons() return TRUE -/// Close the the currently open external (that's EX-ternal) air tank. Returns TREUE if successful. +/// Close the the currently open external (that's EX-ternal) air tank. Returns TRUE if successful. /mob/living/carbon/proc/close_externals() return close_internals(TRUE) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e09d68db5fde8..7fb92c26e6183 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -64,6 +64,7 @@ // Second link in a breath chain, calls [carbon/proc/check_breath()] /mob/living/carbon/proc/breathe(seconds_per_tick, times_fired) var/obj/item/organ/internal/lungs = get_organ_slot(ORGAN_SLOT_LUNGS) + if(SEND_SIGNAL(src, COMSIG_CARBON_ATTEMPT_BREATHE, seconds_per_tick, times_fired) & COMSIG_CARBON_BLOCK_BREATH) return diff --git a/code/modules/spells/spell_types/touch/_touch.dm b/code/modules/spells/spell_types/touch/_touch.dm index 1ed5ce49511dd..d1adc9619be27 100644 --- a/code/modules/spells/spell_types/touch/_touch.dm +++ b/code/modules/spells/spell_types/touch/_touch.dm @@ -191,13 +191,16 @@ return ITEM_INTERACT_SUCCESS /// Checks if the passed victim can be cast on by the caster. -/datum/action/cooldown/spell/touch/proc/can_hit_with_hand(atom/victim, mob/caster) +/datum/action/cooldown/spell/touch/proc/can_hit_with_hand(atom/victim, mob/living/caster) if(!can_cast_on_self && victim == caster) return FALSE if(!is_valid_target(victim)) return FALSE if(!can_cast_spell(feedback = TRUE)) return FALSE + if(!(caster.mobility_flags & MOBILITY_USE)) + caster.balloon_alert(caster, "can't reach out!") + return FALSE return TRUE @@ -222,6 +225,8 @@ log_combat(caster, victim, "cast the touch spell [name] on", hand) spell_feedback(caster) caster.do_attack_animation(victim) + caster.changeNext_move(CLICK_CD_MELEE) + victim.add_fingerprint(caster) remove_hand(caster) /** @@ -240,6 +245,8 @@ log_combat(caster, victim, "cast the touch spell [name] on", hand, "(secondary / alt cast)") spell_feedback(caster) caster.do_attack_animation(victim) + caster.changeNext_move(CLICK_CD_MELEE) + victim.add_fingerprint(caster) remove_hand(caster) // Call normal will call the normal cast proc @@ -346,14 +353,6 @@ if(spell) spell_which_made_us = WEAKREF(spell) -/obj/item/melee/touch_attack/attack(mob/target, mob/living/carbon/user) - if(!iscarbon(user)) //Look ma, no hands - return TRUE - if(!(user.mobility_flags & MOBILITY_USE)) - user.balloon_alert(user, "can't reach out!") - return TRUE - return ..() - /** * When the hand component of a touch spell is qdel'd, (the hand is dropped or otherwise lost), * the cooldown on the spell that made it is automatically refunded. diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index ba53c8b8c41d6..6c2661bbe2237 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -115,32 +115,6 @@ qdel(filler) return ..() -/obj/machinery/dna_vault/attackby(obj/item/our_item, mob/user, params) - if(istype(our_item, /obj/item/dna_probe)) - var/obj/item/dna_probe/our_probe = our_item - var/uploaded = 0 - var/plant_dna_length = length(our_probe.stored_dna_plants) - var/human_dna_length = length(our_probe.stored_dna_human) - var/animal_dna_length = length(our_probe.stored_dna_animal) - if(plant_dna_length) - uploaded += plant_dna_length - plant_dna += our_probe.stored_dna_plants - our_probe.stored_dna_plants.Cut() - if(human_dna_length) - uploaded += human_dna_length - human_dna += our_probe.stored_dna_human - our_probe.stored_dna_human.Cut() - if(animal_dna_length) - uploaded += animal_dna_length - animal_dna += our_probe.stored_dna_animal - our_probe.stored_dna_animal.Cut() - check_goal() - playsound(src, 'sound/misc/compiler-stage1.ogg', 50) - to_chat(user, span_notice("[uploaded] new datapoints uploaded.")) - return - - return ..() - /obj/machinery/dna_vault/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 25db3cdabfb10..b3427db9291ba 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -540,6 +540,10 @@ // Breath in nitrium. It's helpful, but has nasty side effects /obj/item/organ/internal/lungs/proc/too_much_nitrium(mob/living/carbon/breather, datum/gas_mixture/breath, nitrium_pp, old_nitrium_pp) breathe_gas_volume(breath, /datum/gas/nitrium) + + if(prob(20)) + breather.emote("burp") + // Random chance to inflict side effects increases with pressure. if((prob(nitrium_pp) && (nitrium_pp > 15))) // Nitrium side-effect. diff --git a/html/changelogs/AutoChangeLog-pr-84070.yml b/html/changelogs/AutoChangeLog-pr-84070.yml new file mode 100644 index 0000000000000..0f52be52df6b4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84070.yml @@ -0,0 +1,4 @@ +author: "LucyGrind" +delete-after: True +changes: + - bugfix: "crayons interact with washing machine once again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84125.yml b/html/changelogs/AutoChangeLog-pr-84125.yml deleted file mode 100644 index 2109a86d39ef0..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-84125.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "jlsnow301" -delete-after: True -changes: - - bugfix: "Bitrunning made more illegal: Increased the rate at which antags spawn." - - bugfix: "\"Temporary\" bitrunning antagonists and spawners are made actually temporary. You will return to your original body after death, just like CTF." - - rscadd: "Added more examine text for ghosts to bitrunning equipment." - - balance: "Server cooldown reduced by 1 minute at base level." - - rscadd: "As an observer, you can now switch views between station and virtual domain by clicking the hololadder and netpod respectively." - - rscdel: "Removed the starfront saloon BR map." - - bugfix: "Syndicate assault map: Added pistols, reduced exploits." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84132.yml b/html/changelogs/AutoChangeLog-pr-84132.yml deleted file mode 100644 index 5f7a33c4c3210..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-84132.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Donglesplonge" -delete-after: True -changes: - - balance: "most livestock crates, with some exception, have been made cheaper to facilitate healthier mental states in the crew, go build a farm!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84175.yml b/html/changelogs/AutoChangeLog-pr-84175.yml new file mode 100644 index 0000000000000..8a5aadd5d189a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84175.yml @@ -0,0 +1,4 @@ +author: "GoblinBackwards" +delete-after: True +changes: + - rscadd: "Breathing nitrium now has a chance to make you burp." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84176.yml b/html/changelogs/AutoChangeLog-pr-84176.yml new file mode 100644 index 0000000000000..646d9e0f796f8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84176.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - rscadd: "Adds an effect for emagging a fake emag" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84178.yml b/html/changelogs/AutoChangeLog-pr-84178.yml new file mode 100644 index 0000000000000..6c733f8e7b635 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84178.yml @@ -0,0 +1,4 @@ +author: "LT3" +delete-after: True +changes: + - bugfix: "Smartfridge will now correctly respond 'no power' instead of 'forbidden item' when it doesn't have power" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84182.yml b/html/changelogs/AutoChangeLog-pr-84182.yml new file mode 100644 index 0000000000000..d1a9c48888d7d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84182.yml @@ -0,0 +1,6 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Touch Spells now apply click CD again" + - bugfix: "Touch Spells now apply fingerprints again" + - bugfix: "Touch Spells now check if your hands are blocked again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84183.yml b/html/changelogs/AutoChangeLog-pr-84183.yml new file mode 100644 index 0000000000000..7157e07f3274f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84183.yml @@ -0,0 +1,4 @@ +author: "DATA, with sounds by Beebblie" +delete-after: True +changes: + - sound: "Added sounds for turning on and off internals." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84193.yml b/html/changelogs/AutoChangeLog-pr-84193.yml new file mode 100644 index 0000000000000..973f83442ebb4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84193.yml @@ -0,0 +1,4 @@ +author: "Bisar" +delete-after: True +changes: + - balance: "Sparks have been heavily adjusted; they only affect items made of plasma, pools of welding fuel, flammable people, cigarettes, and items that contain reagents... for now. Their long-standing behavior of igniting flammable gas has been untouched." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84212.yml b/html/changelogs/AutoChangeLog-pr-84212.yml new file mode 100644 index 0000000000000..6487a3d5f8930 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84212.yml @@ -0,0 +1,4 @@ +author: "Rhials" +delete-after: True +changes: + - bugfix: "Admin-only deadchat broadcasts don't append a second \"this message is for admins only\" string for every admin online." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84213.yml b/html/changelogs/AutoChangeLog-pr-84213.yml new file mode 100644 index 0000000000000..cd7df37946b71 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84213.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - rscadd: "The game settings menu can now actually be accessed through the escape menu." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84216.yml b/html/changelogs/AutoChangeLog-pr-84216.yml new file mode 100644 index 0000000000000..ea8d9d1294f2e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84216.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Bloody footprints now go until you run out of blood on your feet instead if only a single tile" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84219.yml b/html/changelogs/AutoChangeLog-pr-84219.yml new file mode 100644 index 0000000000000..f21db76dfdb94 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84219.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - rscadd: "Adds an effect for emagging an emag" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84221.yml b/html/changelogs/AutoChangeLog-pr-84221.yml new file mode 100644 index 0000000000000..fdad8684400c5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84221.yml @@ -0,0 +1,4 @@ +author: "Paxilmaniac" +delete-after: True +changes: + - rscadd: "Electric eels now prefer used car batteries for bait." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84224.yml b/html/changelogs/AutoChangeLog-pr-84224.yml new file mode 100644 index 0000000000000..ab53e5b1013a5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84224.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - qol: "Oven trays now count as valid trays to cut food on." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84227.yml b/html/changelogs/AutoChangeLog-pr-84227.yml new file mode 100644 index 0000000000000..341482fef14e2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84227.yml @@ -0,0 +1,5 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Fixed plate shards not randomizing icon correctly" + - qol: "Gives plate sharts a more fitting hitsound / caltrop sound, gives them a set caltrop stun duration (instead of default)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84236.yml b/html/changelogs/AutoChangeLog-pr-84236.yml new file mode 100644 index 0000000000000..f45e9aae81aa7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84236.yml @@ -0,0 +1,4 @@ +author: "Kocma-san" +delete-after: True +changes: + - bugfix: "you can hold Ian in your arms" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84243.yml b/html/changelogs/AutoChangeLog-pr-84243.yml new file mode 100644 index 0000000000000..59c4dc8544400 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84243.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Fix DNA vault probes" \ No newline at end of file diff --git a/html/changelogs/archive/2024-06.yml b/html/changelogs/archive/2024-06.yml index 2b62716374ae9..87b304d39cdab 100644 --- a/html/changelogs/archive/2024-06.yml +++ b/html/changelogs/archive/2024-06.yml @@ -994,3 +994,17 @@ pool. mc-oofert: - bugfix: borg factory gives you your preference borg name +2024-06-23: + Donglesplonge: + - balance: most livestock crates, with some exception, have been made cheaper to + facilitate healthier mental states in the crew, go build a farm! + jlsnow301: + - bugfix: 'Bitrunning made more illegal: Increased the rate at which antags spawn.' + - bugfix: '"Temporary" bitrunning antagonists and spawners are made actually temporary. + You will return to your original body after death, just like CTF.' + - rscadd: Added more examine text for ghosts to bitrunning equipment. + - balance: Server cooldown reduced by 1 minute at base level. + - rscadd: As an observer, you can now switch views between station and virtual domain + by clicking the hololadder and netpod respectively. + - rscdel: Removed the starfront saloon BR map. + - bugfix: 'Syndicate assault map: Added pistols, reduced exploits.' diff --git a/icons/obj/fishing.dmi b/icons/obj/fishing.dmi index 92d7da8238ad3..92d1cf9a12231 100644 Binary files a/icons/obj/fishing.dmi and b/icons/obj/fishing.dmi differ diff --git a/sound/items/internals_off.ogg b/sound/items/internals_off.ogg new file mode 100644 index 0000000000000..7336ec41d6144 Binary files /dev/null and b/sound/items/internals_off.ogg differ diff --git a/sound/items/internals_on.ogg b/sound/items/internals_on.ogg new file mode 100644 index 0000000000000..2a08a916d2f0b Binary files /dev/null and b/sound/items/internals_on.ogg differ