diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 71c55554a3..1f598436a7 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -260,3 +260,22 @@ Pipelines + Other Objects -> Pipe network if(user.buckled) user.buckled.unbuckle_mob(user, TRUE) user.throw_at(get_edge_target_turf(user, get_dir(src, user) || pick(GLOB.cardinal)), pressures / 250, pressures / 1250) + +/// Blows out a pipe, deconstructing it, breaking the floor and releasing all mobs crawling inside it +/obj/machinery/atmospherics/proc/blowout(mob/user) + // Deconstruct turf + var/turf/our_turf = loc + if(!our_turf.is_plating() && istype(our_turf,/turf/simulated/floor)) //intact floor, pop the tile + var/turf/simulated/floor/our_floor = our_turf + our_floor.make_plating(TRUE) + // Deconstruct pipe + var/datum/gas_mixture/int_air = return_air() + var/datum/gas_mixture/env_air = our_turf.return_air() + var/internal_pressure = int_air.return_pressure()-env_air.return_pressure() + deconstruct() + // Release pressure + playsound(our_turf, 'sound/effects/bang.ogg', 70, 0, 0) + playsound(our_turf, 'sound/effects/clang2.ogg', 70, 0, 0) + if(internal_pressure > 2*ONE_ATMOSPHERE) + unsafe_pressure_release(user, internal_pressure) + playsound(our_turf, 'sound/machines/hiss.ogg', 50, 0, 0) diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm index e6c28e4428..16c88e04aa 100644 --- a/code/ATMOSPHERICS/components/unary/unary_base.dm +++ b/code/ATMOSPHERICS/components/unary/unary_base.dm @@ -11,7 +11,7 @@ var/datum/pipe_network/network - var/welded = 0 //defining this here for ventcrawl stuff + var/welded = FALSE //defining this here for ventcrawl stuff /obj/machinery/atmospherics/unary/Initialize(mapload) . = ..() diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 23a48b8a51..286576890e 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -68,7 +68,9 @@ if(!istype(T)) return - if(!powered()) + if(welded) + scrubber_icon += "weld" + else if(!powered()) scrubber_icon += "off" else scrubber_icon += "[use_power ? "[scrubbing ? "on" : "in"]" : "off"]" @@ -269,6 +271,27 @@ update_icon() /obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/W as obj, var/mob/user as mob) + if(W.has_tool_quality(TOOL_WELDER)) + var/obj/item/weldingtool/WT = W + if (WT.remove_fuel(0,user)) + to_chat(user, span_notice("Now welding the vent.")) + + if(do_after(user, 20 * WT.toolspeed)) + if(!src || !WT.isOn()) return + playsound(src, WT.usesound, 50, 1) + if(!welded) + user.visible_message(span_notice("\The [user] welds the vent shut."), span_notice("You weld the vent shut."), "You hear welding.") + welded = TRUE + update_icon() + else + user.visible_message(span_notice("[user] unwelds the vent."), span_notice("You unweld the vent."), "You hear welding.") + welded = FALSE + update_icon() + else + to_chat(user, span_notice("The welding tool needs to be on to start this task.")) + else + to_chat(user, span_warning("You need more welding fuel to complete this task.")) + return 1 if (!W.has_tool_quality(TOOL_WRENCH)) return ..() if (!(stat & NOPOWER) && use_power) @@ -278,6 +301,9 @@ if (node && node.level==1 && isturf(T) && !T.is_plating()) to_chat(user, span_warning("You must remove the plating first.")) return 1 + if(welded) + to_chat(user, span_warning("You cannot unwrench \the [src], it is welded down firmly.")) + return 1 if(!can_unwrench()) to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) @@ -297,3 +323,5 @@ . += "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W" else . += "You are too far away to read the gauge." + if(welded) + . += "It is welded shut." diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index a965c3b470..9de4f014a2 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -822,6 +822,24 @@ ///called when you clear a mood event from anywhere in the code. #define COMSIG_CLEAR_MOOD_EVENT "clear_mood" +//Ventcrawling + +///called when a ventcrawling mob checks if it can begin ventcrawling : (obj/machinery/atmospherics/unary/vent_entered) +#define COMSIG_MOB_VENTCRAWL_CHECK "ventcrawl_check" +///called when a ventcrawling mob checks if it can enter a vent : (mob/entering_mob) +#define COMSIG_VENT_CRAWLER_CHECK "ventcrawl_check" + #define VENT_CRAWL_BLOCK_ENTRY (1<<0) + +///called when a ventcrawling mob enters a vent : (obj/machinery/atmospherics/unary/vent_entered) +#define COMSIG_MOB_VENTCRAWL_START "ventcrawl_start" +///called when a ventcrawling mob leaves a vent : (obj/machinery/atmospherics/unary/vent_exited) +#define COMSIG_MOB_VENTCRAWL_END "ventcrawl_end" + +///called when a ventcrawling mob enters a vent : (mob/entering_mob) +#define COMSIG_VENT_CRAWLER_ENTERED "ventcrawl_entered_vent" +///called when a ventcrawling mob leaves a vent : (mob/exiting_mob) +#define COMSIG_VENT_CRAWLER_EXITED "ventcrawl_exit_vent" + //NTnet ///called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) diff --git a/code/datums/ghost_spawn_options.dm b/code/datums/ghost_spawn_options.dm index 3f1724aa57..31832e8f20 100644 --- a/code/datums/ghost_spawn_options.dm +++ b/code/datums/ghost_spawn_options.dm @@ -55,6 +55,8 @@ host.ckey = user.ckey host.add_ventcrawl(vent_found) to_chat(host, span_info("You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.")) + SEND_SIGNAL(host,COMSIG_MOB_VENTCRAWL_START,vent_found) + SEND_SIGNAL(vent_found,COMSIG_VENT_CRAWLER_ENTERED,host) /datum/tgui_module/ghost_spawn_menu/proc/become_drone(mob/observer/dead/user, fabricator) if(SSticker.current_state < GAME_STATE_PLAYING) diff --git a/code/modules/mob/living/simple_mob/life.dm b/code/modules/mob/living/simple_mob/life.dm index 259fefc308..cd5a070de0 100644 --- a/code/modules/mob/living/simple_mob/life.dm +++ b/code/modules/mob/living/simple_mob/life.dm @@ -11,7 +11,6 @@ handle_weakened() handle_paralysed() handle_supernatural() - handle_atmos() handle_special() @@ -102,73 +101,62 @@ /mob/living/simple_mob/proc/handle_special() return - // Handle interacting with and taking damage from atmos -// TODO - Refactor this to use handle_environment() like a good /mob/living -/mob/living/simple_mob/proc/handle_atmos() - var/atmos_unsuitable = 0 +/mob/living/simple_mob/handle_environment(datum/gas_mixture/environment) if(in_stasis) return 1 // return early to skip atmos checks if(is_incorporeal()) return 1 - var/atom/A = src.loc + if( abs(environment.temperature - bodytemperature) > temperature_range ) + bodytemperature += ((environment.temperature - bodytemperature) / 5) - if(istype(A,/turf)) - var/turf/T = A + var/atmos_unsuitable = 0 + if(min_oxy && environment.gas[GAS_O2] < min_oxy) + atmos_unsuitable = 1 + throw_alert("oxy", /atom/movable/screen/alert/not_enough_oxy) + else if(max_oxy && environment.gas[GAS_O2] > max_oxy) + atmos_unsuitable = 1 + throw_alert("oxy", /atom/movable/screen/alert/too_much_oxy) + else + clear_alert("oxy") - var/datum/gas_mixture/Environment = T.return_air() + if(min_tox && environment.gas[GAS_PHORON] < min_tox) + atmos_unsuitable = 2 + throw_alert("tox_in_air", /atom/movable/screen/alert/not_enough_tox) + else if(max_tox && environment.gas[GAS_PHORON] > max_tox) + atmos_unsuitable = 2 + throw_alert("tox_in_air", /atom/movable/screen/alert/tox_in_air) + else + clear_alert("tox_in_air") - if(Environment) + if(min_n2 && environment.gas[GAS_N2] < min_n2) + atmos_unsuitable = 1 + throw_alert("n2o", /atom/movable/screen/alert/not_enough_nitro) + else if(max_n2 && environment.gas[GAS_N2] > max_n2) + atmos_unsuitable = 1 + throw_alert("n2o", /atom/movable/screen/alert/too_much_nitro) + else + clear_alert("n2o") - if( abs(Environment.temperature - bodytemperature) > temperature_range ) //VOREStation Edit: heating adjustments - bodytemperature += ((Environment.temperature - bodytemperature) / 5) + if(min_co2 && environment.gas[GAS_CO2] < min_co2) + atmos_unsuitable = 1 + throw_alert("co2", /atom/movable/screen/alert/not_enough_co2) + else if(max_co2 && environment.gas[GAS_CO2] > max_co2) + atmos_unsuitable = 1 + throw_alert("co2", /atom/movable/screen/alert/too_much_co2) + else + clear_alert("co2") - if(min_oxy && Environment.gas[GAS_O2] < min_oxy) - atmos_unsuitable = 1 - throw_alert("oxy", /atom/movable/screen/alert/not_enough_oxy) - else if(max_oxy && Environment.gas[GAS_O2] > max_oxy) - atmos_unsuitable = 1 - throw_alert("oxy", /atom/movable/screen/alert/too_much_oxy) - else - clear_alert("oxy") - - if(min_tox && Environment.gas[GAS_PHORON] < min_tox) - atmos_unsuitable = 2 - throw_alert("tox_in_air", /atom/movable/screen/alert/not_enough_tox) - else if(max_tox && Environment.gas[GAS_PHORON] > max_tox) - atmos_unsuitable = 2 - throw_alert("tox_in_air", /atom/movable/screen/alert/tox_in_air) - else - clear_alert("tox_in_air") - - if(min_n2 && Environment.gas[GAS_N2] < min_n2) - atmos_unsuitable = 1 - throw_alert("n2o", /atom/movable/screen/alert/not_enough_nitro) - else if(max_n2 && Environment.gas[GAS_N2] > max_n2) - atmos_unsuitable = 1 - throw_alert("n2o", /atom/movable/screen/alert/too_much_nitro) - else - clear_alert("n2o") - - if(min_co2 && Environment.gas[GAS_CO2] < min_co2) - atmos_unsuitable = 1 - throw_alert("co2", /atom/movable/screen/alert/not_enough_co2) - else if(max_co2 && Environment.gas[GAS_CO2] > max_co2) - atmos_unsuitable = 1 - throw_alert("co2", /atom/movable/screen/alert/too_much_co2) - else - clear_alert("co2") - - if(min_ch4 && Environment.gas[GAS_CH4] < min_ch4) - atmos_unsuitable = 2 - throw_alert("methane_in_air", /atom/movable/screen/alert/not_enough_methane) - else if(max_tox && Environment.gas[GAS_CH4] > max_ch4) - atmos_unsuitable = 2 - throw_alert("methane_in_air", /atom/movable/screen/alert/methane_in_air) - else - clear_alert("methane_in_air") + if(min_ch4 && environment.gas[GAS_CH4] < min_ch4) + atmos_unsuitable = 2 + throw_alert("methane_in_air", /atom/movable/screen/alert/not_enough_methane) + else if(max_tox && environment.gas[GAS_CH4] > max_ch4) + atmos_unsuitable = 2 + throw_alert("methane_in_air", /atom/movable/screen/alert/methane_in_air) + else + clear_alert("methane_in_air") //Atmos effect if(bodytemperature < minbodytemp) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm index e4dac2f548..112126086a 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon.dm @@ -71,14 +71,12 @@ /mob/living/simple_mob/vore/demon/UnarmedAttack() if(shifted_out) return FALSE - . = ..() /mob/living/simple_mob/vore/demon/can_fall() if(shifted_out) return FALSE - - return ..() + . = ..() /mob/living/simple_mob/vore/demon/zMove(direction) if(shifted_out) @@ -86,26 +84,23 @@ if(destination) forceMove(destination) return TRUE - - return ..() + . = ..() /mob/living/simple_mob/vore/demon/Life() . = ..() if(shifted_out) density = FALSE -/mob/living/simple_mob/vore/demon/handle_atmos() +/mob/living/simple_mob/vore/demon/handle_environment(datum/gas_mixture/environment) // TODO - Refactor demons to use is_incorporeal() if(shifted_out) return - else - return .=..() + . = ..() /mob/living/simple_mob/vore/demon/update_canmove() if(is_shifting) canmove = FALSE return canmove - else - return ..() + . = ..() /mob/living/simple_mob/vore/demon/apply_melee_effects(var/atom/A) if(isliving(A)) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demonAI.dm b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demonAI.dm index c399d88a3f..3b3b67e4cb 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demonAI.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demonAI.dm @@ -74,14 +74,12 @@ /mob/living/simple_mob/vore/demonAI/UnarmedAttack() if(shifted_out) return FALSE - . = ..() /mob/living/simple_mob/vore/demonAI/can_fall() if(shifted_out) return FALSE - - return ..() + . = ..() /mob/living/simple_mob/vore/demonAI/zMove(direction) if(shifted_out) @@ -89,19 +87,17 @@ if(destination) forceMove(destination) return TRUE - - return ..() + . = ..() /mob/living/simple_mob/vore/demonAI/Life() . = ..() if(shifted_out) density = FALSE -/mob/living/simple_mob/vore/demonAI/handle_atmos() +/mob/living/simple_mob/vore/demonAI/handle_environment(datum/gas_mixture/environment) // TODO - Refactor demons to use is_incorporeal() if(shifted_out) return - else - return .=..() + . = ..() /mob/living/simple_mob/vore/demonAI/update_canmove() if(is_shifting) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm index 3d8b172244..44f8de9db3 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm @@ -347,11 +347,6 @@ return TRUE return FALSE -/mob/living/simple_mob/shadekin/handle_atmos() - if(comp.in_phase) - return - else - return .=..() /* //VOREStation AI Removal //Friendly ones wander towards people, maybe shy-ly if they are set to shy /mob/living/simple_mob/shadekin/handle_wander_movement() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index e13fede983..d84be90d5d 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -263,5 +263,6 @@ VAR_PROTECTED/list/resistances var/custom_footstep = FOOTSTEP_MOB_SHOE + var/vent_crawl_time = 4.5 SECONDS // Time to animate entering a vent VAR_PRIVATE/is_motion_tracking = FALSE // Prevent multiple unsubs and resubs, also used to check if the vis layer is enabled, use has_motiontracking() to get externally. VAR_PRIVATE/wants_to_see_motion_echos = TRUE diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index f9dd5444e7..bef1b7f4af 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -21,8 +21,8 @@ var/list/ventcrawl_machinery = list( /mob/living/var/list/icon/pipes_shown = list() /mob/living/var/last_played_vent -/mob/living/var/is_ventcrawling = 0 -/mob/living/var/prepping_to_ventcrawl = 0 +/mob/living/var/is_ventcrawling = FALSE +/mob/living/var/prepping_to_ventcrawl = FALSE /mob/var/next_play_vent = 0 /mob/living/proc/can_ventcrawl() @@ -180,8 +180,12 @@ var/list/ventcrawl_machinery = list( break if(vent_found) - if(vent_found.network && (vent_found.network.normal_members.len || vent_found.network.line_members.len)) + if(SEND_SIGNAL(src,COMSIG_MOB_VENTCRAWL_CHECK,vent_found) & VENT_CRAWL_BLOCK_ENTRY) + return + if(SEND_SIGNAL(vent_found,COMSIG_VENT_CRAWLER_CHECK,src) & VENT_CRAWL_BLOCK_ENTRY) + return + if(vent_found.network && (vent_found.network.normal_members.len || vent_found.network.line_members.len)) to_chat(src, "You begin climbing into the ventilation system...") if(vent_found.air_contents && !issilicon(src)) @@ -202,15 +206,20 @@ var/list/ventcrawl_machinery = list( to_chat(src, span_warning("You feel a strong drag pulling you into the vent.")) if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) to_chat(src, span_warning("You feel a strong current pushing you away from the vent.")) - if(HAZARD_HIGH_PRESSURE to INFINITY) + if(HAZARD_HIGH_PRESSURE to (HAZARD_HIGH_PRESSURE*2)) to_chat(src, span_danger("You feel a roaring wind pushing you away from the vent!")) + if((HAZARD_HIGH_PRESSURE*2) to INFINITY) // A little too crazy to enter + to_chat(src, span_danger("You're pushed away by the extreme pressure in the vent!")) + return - fade_towards(vent_found,45) - prepping_to_ventcrawl = 1 - spawn(50) - prepping_to_ventcrawl = 0 - if(!do_after(src, 45, target = src)) + // Handle animation delay + fade_towards(vent_found, vent_crawl_time) + prepping_to_ventcrawl = TRUE + if(!do_after(src, vent_crawl_time, target = src)) + prepping_to_ventcrawl = FALSE return + prepping_to_ventcrawl = FALSE + if(!can_ventcrawl()) return @@ -218,7 +227,8 @@ var/list/ventcrawl_machinery = list( forceMove(vent_found) add_ventcrawl(vent_found) - + SEND_SIGNAL(src,COMSIG_MOB_VENTCRAWL_START,vent_found) + SEND_SIGNAL(vent_found,COMSIG_VENT_CRAWLER_ENTERED,src) else to_chat(src, "This vent is not connected to anything.") @@ -226,7 +236,7 @@ var/list/ventcrawl_machinery = list( to_chat(src, "You must be standing on or beside an air vent to enter it.") /mob/living/proc/add_ventcrawl(obj/machinery/atmospherics/starting_machine) - is_ventcrawling = 1 + is_ventcrawling = TRUE //candrop = 0 var/datum/pipe_network/network = starting_machine.return_network(starting_machine) if(!network) @@ -242,7 +252,7 @@ var/list/ventcrawl_machinery = list( client.screen += GLOB.global_hud.centermarker /mob/living/proc/remove_ventcrawl() - is_ventcrawling = 0 + is_ventcrawling = FALSE //candrop = 1 if(client) for(var/image/current_image in pipes_shown) diff --git a/code/modules/ventcrawl/ventcrawl_atmospherics.dm b/code/modules/ventcrawl/ventcrawl_atmospherics.dm index 710f296d88..8b5c11c386 100644 --- a/code/modules/ventcrawl/ventcrawl_atmospherics.dm +++ b/code/modules/ventcrawl/ventcrawl_atmospherics.dm @@ -4,6 +4,8 @@ for(var/mob/living/M in src) //ventcrawling is serious business M.remove_ventcrawl() M.forceMove(get_turf(src)) + SEND_SIGNAL(M,COMSIG_MOB_VENTCRAWL_END,src) + SEND_SIGNAL(src,COMSIG_VENT_CRAWLER_EXITED,M) if(pipe_image) for(var/mob/living/M in GLOB.player_list) if(M.client) @@ -43,6 +45,7 @@ if(world.time > user.next_play_vent) user.next_play_vent = world.time+30 var/turf/T = get_turf(src) + SSmotiontracker.ping(T,40) // Teshari rattler playsound(T, 'sound/machines/ventcrawl.ogg', 50, 1, -3) var/message = pick( prob(90);"* clunk *", @@ -56,6 +59,8 @@ if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery) && src.can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent user.remove_ventcrawl() user.forceMove(src.loc) + SEND_SIGNAL(user,COMSIG_MOB_VENTCRAWL_END,src) + SEND_SIGNAL(src,COMSIG_VENT_CRAWLER_EXITED,user) user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.") user.canmove = 0 spawn(1) diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 0f2aa5d3b3..648e356048 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -883,6 +883,11 @@ if (!(M in contents)) return 0 // They weren't in this belly anyway + // Ventcrawlings will explode their vent to avoid exploits + if(istype(owner.loc,/obj/machinery/atmospherics)) + var/obj/machinery/atmospherics/our_pipe = owner.loc + our_pipe.blowout(owner) + if(istype(M, /mob/living/simple_mob/vore/morph/dominated_prey)) var/mob/living/simple_mob/vore/morph/dominated_prey/p = M p.undo_prey_takeover(FALSE)