diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm index cea0efc3ab7..3eccad7e913 100644 --- a/code/ZAS/FEA_gas_mixture.dm +++ b/code/ZAS/FEA_gas_mixture.dm @@ -965,6 +965,7 @@ What are the archived variables for? //Outputs: 1 if can rebuild, 0 if not. if(!sample) return 0 + if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) return 0 @@ -972,52 +973,61 @@ What are the archived variables for? ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) return 0 if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ - ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (carbon_dioxide > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) return 0 if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) return 0 + if(total_moles() > MINIMUM_AIR_TO_SUSPEND) if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) //world << "temp fail [temperature] & [sample.temperature]" return 0 - + var/check_moles if(sample.trace_gases.len) for(var/datum/gas/trace_gas in sample.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) - return 0 - else - return 0 + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + check_moles = corresponding.moles + else + check_moles = 0 + + if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((check_moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (check_moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) + return 0 if(trace_gases.len) for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) - return 0 - else - return 0 + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + check_moles = corresponding.moles + else + check_moles = 0 + + if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles))) + return 0 + return 1 -/datum/gas_mixture/proc/compare_unsim(turf/list/samples) - //Purpose: Compares a list of unsimulated tiles to self to see if within acceptable ranges that group processing may be enabled - //Called by: ZAS sleeping detection. - //Inputs: List of unsimulated turfs to compare to - //Outputs: 1 if within an acceptable range to sleep, 0 otherwise. - var/datum/gas_mixture/after_share = new - after_share.copy_from(src) +/datum/gas_mixture/proc/add(datum/gas_mixture/right_side) + oxygen += right_side.oxygen + carbon_dioxide += right_side.carbon_dioxide + nitrogen += right_side.nitrogen + toxins += right_side.toxins - ShareSpace(after_share, samples) + if(trace_gases.len || right_side.trace_gases.len) + for(var/datum/gas/trace_gas in right_side.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + corresponding.moles += trace_gas.moles - return src.compare(after_share) + update_values() + return 1 /datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side) //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle @@ -1025,18 +1035,42 @@ What are the archived variables for? //Inputs: Gas mix to remove //Outputs: 1 - oxygen -= right_side.oxygen - carbon_dioxide -= right_side.carbon_dioxide - nitrogen -= right_side.nitrogen - toxins -= right_side.toxins + oxygen = max(oxygen - right_side.oxygen) + carbon_dioxide = max(carbon_dioxide - right_side.carbon_dioxide) + nitrogen = max(nitrogen - right_side.nitrogen) + toxins = max(toxins - right_side.toxins) - if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) + if(trace_gases.len || right_side.trace_gases.len) for(var/datum/gas/trace_gas in right_side.trace_gases) var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding + if(corresponding) + corresponding.moles = max(0, corresponding.moles - trace_gas.moles) - corresponding.moles -= trace_gas.moles update_values() - return 1 \ No newline at end of file + return 1 + +/datum/gas_mixture/proc/multiply(factor) + oxygen *= factor + carbon_dioxide *= factor + nitrogen *= factor + toxins *= factor + + if(trace_gases && trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles *= factor + + update_values() + return 1 + +/datum/gas_mixture/proc/divide(factor) + oxygen /= factor + carbon_dioxide /= factor + nitrogen /= factor + toxins /= factor + + if(trace_gases && trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles /= factor + + update_values() + return 1 diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index b58cdd1903a..2a5c5818a49 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -10,6 +10,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs var/list/contents //All the tiles that are contained in this zone. var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out. + var/datum/gas_mixture/air_unsim //Overall average of the air in connected unsimualted tiles. + var/unsim_air_needs_update = 0 //Set to 1 on geometry changes, marks air_unsim as needing update. + var/list/connections //connection objects which refer to connections with other zones, e.g. through a door. var/list/direct_connections //connections which directly connect two zones. @@ -126,6 +129,8 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs unsimulated_tiles += T contents -= T + unsim_air_needs_update = 1 + /zone/proc/RemoveTurf(turf/T) //Same, but in reverse. if(istype(T, /turf/simulated)) @@ -146,6 +151,45 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs if(!unsimulated_tiles.len) unsimulated_tiles = null + unsim_air_needs_update = 1 + +//Updates the air_unsim var +/zone/proc/UpdateUnsimAvg() + if(!unsim_air_needs_update) + return + + unsim_air_needs_update = 0 + + if(!air_unsim) + air_unsim = new /datum/gas_mixture + + air_unsim.oxygen = 0 + air_unsim.nitrogen = 0 + air_unsim.carbon_dioxide = 0 + air_unsim.toxins = 0 + air_unsim.temperature = 0 + + var/correction_ratio = max(1, max(max(1, air.group_multiplier) + 3, 1) + unsimulated_tiles.len) / unsimulated_tiles.len + + for(var/turf/T in unsimulated_tiles) + if(!istype(T, /turf/simulated)) + air_unsim.oxygen += T.oxygen + air_unsim.carbon_dioxide += T.carbon_dioxide + air_unsim.nitrogen += T.nitrogen + air_unsim.toxins += T.toxins + air_unsim.temperature += T.temperature/unsimulated_tiles.len + + //These values require adjustment in order to properly represent a room of the specified size. + air_unsim.oxygen *= correction_ratio + air_unsim.carbon_dioxide *= correction_ratio + air_unsim.nitrogen *= correction_ratio + air_unsim.toxins *= correction_ratio + + air_unsim.group_multiplier = unsimulated_tiles.len + + air_unsim.update_values() + return + ////////////// //PROCESSING// ////////////// @@ -180,20 +224,23 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: ShareSpace()" + if(unsim_air_needs_update) + unsim_air_needs_update = 0 + UpdateUnsimAvg() + if(unsimulated_tiles) if(locate(/turf/simulated) in unsimulated_tiles) for(var/turf/simulated/T in unsimulated_tiles) unsimulated_tiles -= T if(unsimulated_tiles.len) - var/old_pressure = air.return_pressure() - var/moved_air = ShareSpace(air,unsimulated_tiles) + var/moved_air = ShareSpace(air, air_unsim) + + if(!air.compare(air_unsim)) + interactions_with_unsim++ if(moved_air > vsc.airflow_lightest_pressure) AirflowSpace(src) - - if(old_pressure && (moved_air / old_pressure) > MINIMUM_AIR_RATIO_TO_SUSPEND) //Check if we've moved enough air to be considered awake. - interactions_with_unsim++ else unsimulated_tiles = null @@ -310,11 +357,11 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs Z.interactions_with_neighbors++ interactions_with_neighbors++ - if(!interactions_with_neighbors && !interactions_with_unsim) - SetStatus(ZONE_SLEEPING) + if(!interactions_with_neighbors && !interactions_with_unsim) + SetStatus(ZONE_SLEEPING) - interactions_with_neighbors = 0 - interactions_with_unsim = 0 + interactions_with_neighbors = 0 + interactions_with_unsim = 0 progress = "all components completed successfully, the problem is not here" @@ -327,6 +374,11 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs else if(status == ZONE_ACTIVE && new_status == ZONE_SLEEPING) air_master.active_zones.Remove(src) status = ZONE_SLEEPING + + if(unsimulated_tiles && unsimulated_tiles.len) + UpdateUnsimAvg() + air.copy_from(air_unsim) + if(!archived_air) archived_air = new archived_air.copy_from(air) @@ -342,12 +394,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs var/difference = 0 if(unsimulated_tiles && unsimulated_tiles.len) - if(air.compare_unsim(unsimulated_tiles)) + UpdateUnsimAvg() + if(!air.compare(air_unsim)) difference = 1 if(!difference) for(var/zone/Z in connected_zones) //Check adjacent zones for air difference. - if(air.compare(Z.air)) + if(!air.compare(Z.air)) difference = 1 break @@ -362,11 +415,20 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs return air.merge(giver) else + if(unsimulated_tiles && unsimulated_tiles.len) + UpdateUnsimAvg() + var/datum/gas_mixture/compare_air = new + compare_air.copy_from(giver) + compare_air.add(air_unsim) + compare_air.divide(air.group_multiplier) + + if(air_unsim.compare(compare_air)) + return 0 + var/result = air.merge(giver) if(!archived_air.compare(air)) SetStatus(ZONE_ACTIVE) - return result @@ -443,6 +505,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) if(H) var/G_avg = (G.moles*size + H.moles*share_size) / (size+share_size) G.moles = (G.moles - G_avg) * (1-ratio) + G_avg + H.moles = (H.moles - G_avg) * (1-ratio) + G_avg else H = new G.type @@ -451,6 +514,15 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) G.moles = (G.moles - G_avg) * (1-ratio) + G_avg H.moles = (H.moles - G_avg) * (1-ratio) + G_avg + for(var/datum/gas/G in B.trace_gases) + var/datum/gas/H = locate(G.type) in A.trace_gases + if(H) + H = new G.type + A.trace_gases += H + var/G_avg = (G.moles*size) / (size+share_size) + G.moles = (G.moles - G_avg) * (1-ratio) + G_avg + H.moles = (H.moles - G_avg) * (1-ratio) + G_avg + A.update_values() B.update_values() @@ -459,7 +531,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) //A modified version of ShareRatio for spacing gas at the same rate as if it were going into a large airless room. - if(!unsimulated_tiles || !unsimulated_tiles.len) + if(!unsimulated_tiles) return 0 var @@ -472,6 +544,22 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) size = max(1,A.group_multiplier) + var/tileslen + var/share_size + + if(istype(unsimulated_tiles, /datum/gas_mixture)) + var/datum/gas_mixture/avg_unsim = unsimulated_tiles + unsim_oxygen = avg_unsim.oxygen + unsim_co2 = avg_unsim.carbon_dioxide + unsim_nitrogen = avg_unsim.nitrogen + unsim_plasma = avg_unsim.toxins + unsim_temperature = avg_unsim.temperature + share_size = max(1, max(size + 3, 1) + avg_unsim.group_multiplier) + tileslen = avg_unsim.group_multiplier + + else if(istype(unsimulated_tiles, /list)) + if(!unsimulated_tiles.len) + return 0 // We use the same size for the potentially single space tile // as we use for the entire room. Why is this? // Short answer: We do not want larger rooms to depressurize more @@ -479,20 +567,25 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) // oh-shit effect when large rooms get breached, but still having small // rooms remain pressurized for long enough to make escape possible. share_size = max(1, max(size + 3, 1) + unsimulated_tiles.len) - correction_ratio = share_size / unsimulated_tiles.len + var/correction_ratio = share_size / unsimulated_tiles.len - for(var/turf/T in unsimulated_tiles) - unsim_oxygen += T.oxygen - unsim_co2 += T.carbon_dioxide - unsim_nitrogen += T.nitrogen - unsim_plasma += T.toxins - unsim_temperature += T.temperature/unsimulated_tiles.len + for(var/turf/T in unsimulated_tiles) + unsim_oxygen += T.oxygen + unsim_co2 += T.carbon_dioxide + unsim_nitrogen += T.nitrogen + unsim_plasma += T.toxins + unsim_temperature += T.temperature/unsimulated_tiles.len + + //These values require adjustment in order to properly represent a room of the specified size. + unsim_oxygen *= correction_ratio + unsim_co2 *= correction_ratio + unsim_nitrogen *= correction_ratio + unsim_plasma *= correction_ratio + tileslen = unsimulated_tiles.len + + else //invalid input type + return 0 - //These values require adjustment in order to properly represent a room of the specified size. - unsim_oxygen *= correction_ratio - unsim_co2 *= correction_ratio - unsim_nitrogen *= correction_ratio - unsim_plasma *= correction_ratio unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen, unsim_co2, unsim_nitrogen, unsim_plasma) var @@ -517,8 +610,8 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) if((full_heat_capacity + unsim_heat_capacity) > 0) temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity) - if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick. - ratio = sharing_lookup_table[unsimulated_tiles.len] + if(sharing_lookup_table.len >= tileslen) //6 or more interconnecting tiles will max at 42% of air moved per tick. + ratio = sharing_lookup_table[tileslen] A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg ) A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg ) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 93d87635dad..fc7202bd179 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -72,16 +72,16 @@ for(var/chemical in connected.available_chemicals) dat += "[connected.available_chemicals[chemical]]: [occupant.reagents.get_reagent_amount(chemical)] units
" dat += "
Refresh meter readings each second
" - if(src.connected.beaker) - if(src.connected.filtering) - dat += "
Stop Dialysis
" - dat += text("Output Beaker has [] units of free space remaining

", src.connected.beaker.reagents.maximum_volume - src.connected.beaker.reagents.total_volume) - else - dat += "
Start Dialysis
" - dat += text("Output Beaker has [] units of free space remaining

", src.connected.beaker.reagents.maximum_volume - src.connected.beaker.reagents.total_volume) - else - dat += "
No Dialysis Output Beaker is present.

" - + if(src.connected.beaker) + if(src.connected.filtering) + dat += "
Stop Dialysis
" + dat += text("Output Beaker has [] units of free space remaining

", src.connected.beaker.reagents.maximum_volume - src.connected.beaker.reagents.total_volume) + else + dat += "
Start Dialysis
" + dat += text("Output Beaker has [] units of free space remaining

", src.connected.beaker.reagents.maximum_volume - src.connected.beaker.reagents.total_volume) + else + dat += "
No Dialysis Output Beaker is present.

" + for(var/chemical in connected.available_chemicals) dat += "Inject [connected.available_chemicals[chemical]]: " for(var/amount in connected.amounts) @@ -110,9 +110,9 @@ usr << "\red \b This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!" if (href_list["refresh"]) src.updateUsrDialog() - if (href_list["togglefilter"]) - src.connected.toggle_filter() - src.updateUsrDialog() + if (href_list["togglefilter"]) + src.connected.toggle_filter() + src.updateUsrDialog() src.add_fingerprint(usr) return @@ -143,15 +143,15 @@ density = 1 anchored = 1 var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" - var/mob/living/carbon/human/occupant = null + var/mob/living/carbon/human/occupant = null var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") var/amounts = list(5, 10) - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/filtering = 0 + var/obj/item/weapon/reagent_containers/glass/beaker = null + var/filtering = 0 New() ..() - beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large() + beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large() spawn( 5 ) if(orient == "RIGHT") icon_state = "sleeper_0-r" @@ -164,14 +164,14 @@ process() - if(filtering > 0) - if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - src.occupant.vessel.trans_to(beaker, 1) - for(var/datum/reagent/x in src.occupant.reagents.reagent_list) -// world << "FILTERING CHEMS" - src.occupant.reagents.trans_to(beaker, 3) - src.occupant.vessel.trans_to(beaker, 1) + if(filtering > 0) + if(beaker) + if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) + src.occupant.vessel.trans_to(beaker, 1) + for(var/datum/reagent/x in src.occupant.reagents.reagent_list) + if(x.volume > 20) + src.occupant.reagents.trans_id_to(beaker, x.id, 2) + src.occupant.vessel.trans_to(beaker, 1) src.updateDialog() return @@ -184,59 +184,59 @@ del(src) return - attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) - if(istype(G, /obj/item/weapon/reagent_containers/glass)) - if(!beaker) - beaker = G - user.drop_item() - G.loc = src - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") - return - else - user << "\red The sleeper has a beaker already." + attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) + if(istype(G, /obj/item/weapon/reagent_containers/glass)) + if(!beaker) + beaker = G + user.drop_item() + G.loc = src + user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + return + else + user << "\red The sleeper has a beaker already." return - else if(istype(G, /obj/item/weapon/grab)) - if(!ismob(G:affecting)) - return + else if(istype(G, /obj/item/weapon/grab)) + if(!ismob(G:affecting)) + return if(src.occupant) user << "\blue The sleeper is already occupied!" return - for(var/mob/living/carbon/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - usr << "[G:affecting.name] will not fit into the sleeper because they have a slime latched onto their head." - return - - visible_message("[user] starts putting [G:affecting:name] into the sleeper.", 3) - - if(do_after(user, 20)) - if(src.occupant) - user << "\blue The sleeper is already occupied!" - return - if(!G || !G:affecting) return - var/mob/M = G:affecting - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.loc = src - src.occupant = M - src.icon_state = "sleeper_1" - if(orient == "RIGHT") - icon_state = "sleeper_1-r" - - M << "\blue You feel cool air surround you. You go numb as your senses turn inward." - - src.add_fingerprint(user) - del(G) + for(var/mob/living/carbon/slime/M in range(1,G:affecting)) + if(M.Victim == G:affecting) + usr << "[G:affecting.name] will not fit into the sleeper because they have a slime latched onto their head." + return + + visible_message("[user] starts putting [G:affecting:name] into the sleeper.", 3) + + if(do_after(user, 20)) + if(src.occupant) + user << "\blue The sleeper is already occupied!" + return + if(!G || !G:affecting) return + var/mob/M = G:affecting + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + src.occupant = M + src.icon_state = "sleeper_1" + if(orient == "RIGHT") + icon_state = "sleeper_1-r" + + M << "\blue You feel cool air surround you. You go numb as your senses turn inward." + + src.add_fingerprint(user) + del(G) return return ex_act(severity) - if(filtering) - toggle_filter() + if(filtering) + toggle_filter() switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) @@ -260,8 +260,8 @@ return return emp_act(severity) - if(filtering) - toggle_filter() + if(filtering) + toggle_filter() if(stat & (BROKEN|NOPOWER)) ..(severity) return @@ -286,15 +286,15 @@ if (M:reagents.get_reagent_amount("inaprovaline") < 5) M:reagents.add_reagent("inaprovaline", 5) return - proc/toggle_filter() - if(filtering) - filtering = 0 - else - filtering = 1 + proc/toggle_filter() + if(filtering) + filtering = 0 + else + filtering = 1 proc/go_out() - if(filtering) - toggle_filter() + if(filtering) + toggle_filter() if(!src.occupant) return if(src.occupant.client) @@ -337,10 +337,10 @@ user << text("[]\t -Burn Severity %: []", (src.occupant.getFireLoss() < 60 ? "\blue " : "\red "), src.occupant.getFireLoss()) user << "\blue Expected time till occupant can safely awake: (note: If health is below 20% these times are inaccurate)" user << text("\blue \t [] second\s (if around 1 or 2 the sleeper is keeping them asleep.)", src.occupant.paralysis / 5) - if(src.beaker) - user << text("\blue \t Dialysis Output Beaker has [] of free space remaining.", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) - else - user << "\blue No Dialysis Output Beaker loaded." + if(src.beaker) + user << text("\blue \t Dialysis Output Beaker has [] of free space remaining.", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) + else + user << "\blue No Dialysis Output Beaker loaded." else user << "\blue There is no one inside!" return @@ -359,19 +359,19 @@ add_fingerprint(usr) return - verb/remove_beaker() - set name = "Remove Beaker" - set category = "Object" - set src in oview(1) - if(usr.stat != 0) - return - if(beaker) - filtering = 0 - beaker.loc = usr.loc - beaker = null - add_fingerprint(usr) - return - + verb/remove_beaker() + set name = "Remove Beaker" + set category = "Object" + set src in oview(1) + if(usr.stat != 0) + return + if(beaker) + filtering = 0 + beaker.loc = usr.loc + beaker = null + add_fingerprint(usr) + return + verb/move_inside() set name = "Enter Sleeper" set category = "Object" @@ -402,10 +402,10 @@ if(orient == "RIGHT") icon_state = "sleeper_1-r" - usr << "\blue You feel cool air surround you. You go numb as your senses turn inward." - + usr << "\blue You feel cool air surround you. You go numb as your senses turn inward." + for(var/obj/O in src) del(O) src.add_fingerprint(usr) return - return + return diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1b21ecac955..05d0ccea8d6 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -200,4 +200,10 @@ name = "Engineering Cameras" desc = "Used to monitor fires and breaches." icon_state = "engineeringcameras" - network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms") + network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms") + +/obj/machinery/computer/security/nuclear + name = "Mission Monitor" + desc = "Used to access the built-in cameras in helmets." + icon_state = "syndicam" + network = list("NUKE") \ No newline at end of file diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 58ed13b9d9d..f95a2b5d934 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -48,29 +48,30 @@ /obj/structure/table/update_icon() - if(flipped) - var/type = 0 - var/tabledirs = 0 - for(var/direction in list(turn(dir,90), turn(dir,-90)) ) - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) - if (T && T.flipped) - type++ - tabledirs |= direction - var/base = "table" - if (istype(src, /obj/structure/table/woodentable)) - base = "wood" - if (istype(src, /obj/structure/table/reinforced)) - base = "rtable" - - icon_state = "[base]flip[type]" - if (type==1) - if (tabledirs & turn(dir,90)) - icon_state = icon_state+"-" - if (tabledirs & turn(dir,-90)) - icon_state = icon_state+"+" - return 1 - spawn(2) //So it properly updates when deleting + + if(flipped) + var/type = 0 + var/tabledirs = 0 + for(var/direction in list(turn(dir,90), turn(dir,-90)) ) + var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) + if (T && T.flipped && T.dir == src.dir) + type++ + tabledirs |= direction + var/base = "table" + if (istype(src, /obj/structure/table/woodentable)) + base = "wood" + if (istype(src, /obj/structure/table/reinforced)) + base = "rtable" + + icon_state = "[base]flip[type]" + if (type==1) + if (tabledirs & turn(dir,90)) + icon_state = icon_state+"-" + if (tabledirs & turn(dir,-90)) + icon_state = icon_state+"+" + return 1 + var/dir_sum = 0 for(var/direction in list(1,2,4,8,5,6,9,10)) var/skip_sum = 0 @@ -393,20 +394,19 @@ return /obj/structure/table/proc/straight_table_check(var/direction) - var/turf/left = get_step(src,turn(direction,90)) - var/turf/right = get_step(src,turn(direction,-90)) - var/turf/next = get_step(src,direction) - if(locate(/obj/structure/table,left) || locate(/obj/structure/table,right)) - return 0 - var/obj/structure/table/T = locate(/obj/structure/table, next) + var/obj/structure/table/T + for(var/angle in list(-90,90)) + T = locate() in get_step(src.loc,turn(direction,angle)) + if(T && !T.flipped) + return 0 + T = locate() in get_step(src.loc,direction) + if (!T || T.flipped) + return 1 if (istype(T,/obj/structure/table/reinforced/)) var/obj/structure/table/reinforced/R = T if (R.status == 2) return 0 - if (!T) - return 1 - else - return T.straight_table_check(direction) + return T.straight_table_check(direction) /obj/structure/table/verb/do_flip() set name = "Flip table" @@ -423,21 +423,35 @@ usr.visible_message("[usr] flips \the [src]!") return +/obj/structure/table/proc/unflipping_check(var/direction) + for(var/mob/M in oview(src,0)) + return 0 + + var/list/L = list() + if(direction) + L.Add(direction) + else + L.Add(turn(src.dir,-90)) + L.Add(turn(src.dir,90)) + for(var/new_dir in L) + var/obj/structure/table/T = locate() in get_step(src.loc,new_dir) + if(T) + if(T.flipped && T.dir == src.dir && !T.unflipping_check(new_dir)) + return 0 + return 1 + /obj/structure/table/proc/do_put() set name = "Put table back" set desc = "Puts flipped table back" set category = "Object" set src in oview(1) - if (!unflip()) + if (!unflipping_check()) usr << "It won't budge." return - + unflip() /obj/structure/table/proc/flip(var/direction) - if (flipped) - return 0 - if( !straight_table_check(turn(direction,90)) || !straight_table_check(turn(direction,-90)) ) return 0 @@ -456,8 +470,8 @@ flipped = 1 flags |= ON_BORDER for(var/D in list(turn(direction, 90), turn(direction, -90))) - if(locate(/obj/structure/table,get_step(src,D))) - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,D)) + var/obj/structure/table/T = locate() in get_step(src,D) + if(T && !T.flipped) T.flip(direction) update_icon() update_adjacent() @@ -465,16 +479,6 @@ return 1 /obj/structure/table/proc/unflip() - if (!flipped) - return 0 - - var/can_flip = 1 - for (var/mob/A in oview(src,0))//src.loc) - if (istype(A)) - can_flip = 0 - if (!can_flip) - return 0 - verbs -=/obj/structure/table/proc/do_put verbs +=/obj/structure/table/verb/do_flip @@ -482,8 +486,8 @@ flipped = 0 flags &= ~ON_BORDER for(var/D in list(turn(dir, 90), turn(dir, -90))) - if(locate(/obj/structure/table,get_step(src,D))) - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,D)) + var/obj/structure/table/T = locate() in get_step(src.loc,D) + if(T && T.flipped && T.dir == src.dir) T.unflip() update_icon() update_adjacent() @@ -646,4 +650,4 @@ del(src) /obj/structure/rack/attack_tk() // no telehulk sorry - return + return \ No newline at end of file diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm index 7359a026b46..f1e6204d223 100644 --- a/code/modules/admin/verbs/vox_raiders.dm +++ b/code/modules/admin/verbs/vox_raiders.dm @@ -66,7 +66,7 @@ var/global/vox_tick = 1 C.registered_user = src var/obj/item/weapon/storage/wallet/W = new(src) W.handle_item_insertion(C) - spawn_money(rand(100,300)*5,W) + spawn_money(rand(50,150)*10,W) equip_to_slot_or_del(W, slot_wear_id) var/obj/item/weapon/implant/cortical/I = new(src) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index aed3517d03a..be7a028f2aa 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -35,7 +35,6 @@ icon_state = "night" item_state = "glasses" origin_tech = "magnets=2" - vision_flags = SEE_TURFS darkness_view = 3 /obj/item/clothing/glasses/eyepatch diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b63e7b8f107..361074fdd82 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1251,12 +1251,6 @@ mob/living/carbon/human/yank_out_object() species = all_species[new_species] - see_in_dark = species.darksight - if(see_in_dark > 2) - see_invisible = SEE_INVISIBLE_LEVEL_ONE - else - see_invisible = SEE_INVISIBLE_LIVING - spawn(0) update_icons() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 60a9d1c9f2a..19d00be7004 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1180,6 +1180,8 @@ if(healths) healths.icon_state = "health7" //DEAD healthmeter else sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = species.darksight + see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING if(dna) switch(dna.mutantrace) if("slime") @@ -1224,40 +1226,27 @@ if(!druggy) see_invisible = SEE_INVISIBLE_LIVING if(glasses) - if(istype(glasses, /obj/item/clothing/glasses/meson)) - sight |= SEE_TURFS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/night)) - see_in_dark = 5 - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/thermal)) - sight |= SEE_MOBS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - else if(istype(glasses, /obj/item/clothing/glasses/material)) - sight |= SEE_OBJS - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM + var/obj/item/clothing/glasses/G = glasses + if(istype(G)) + see_in_dark += G.darkness_view + if(G.vision_flags) + sight |= G.vision_flags + if(!druggy) + see_invisible = SEE_INVISIBLE_MINIMUM /* HUD shit goes here, as long as it doesn't modify sight flags */ // The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl - else if(istype(glasses, /obj/item/clothing/glasses/sunglasses)) - see_in_dark = 1 - if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud)) - var/obj/item/clothing/glasses/sunglasses/sechud/O = glasses - if(O.hud) O.hud.process_hud(src) - if(!druggy) see_invisible = SEE_INVISIBLE_LIVING - + if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud)) + var/obj/item/clothing/glasses/sunglasses/sechud/O = glasses + if(O.hud) O.hud.process_hud(src) + if(!druggy) see_invisible = SEE_INVISIBLE_LIVING else if(istype(glasses, /obj/item/clothing/glasses/hud)) var/obj/item/clothing/glasses/hud/O = glasses O.process_hud(src) if(!druggy) see_invisible = SEE_INVISIBLE_LIVING - else - see_invisible = SEE_INVISIBLE_LIVING + else if(!seer) see_invisible = SEE_INVISIBLE_LIVING diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 8f162524556..2121ce13aa7 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -3084,7 +3084,7 @@ datum var/datum/organ/internal/heart/L = H.internal_organs["heart"] if (istype(L)) L.take_damage(100, 0) - + holder.remove_reagent(src.id, FOOD_METABOLISM) ethanol/deadrum name = "Deadrum" diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index 00d5d6b2bad..3e969e6dce1 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -5959,7 +5959,7 @@ "ckE" = (/obj/structure/table,/obj/item/clothing/ears/earmuffs{pixel_x = -5; pixel_y = 6},/obj/item/clothing/ears/earmuffs{pixel_x = -5; pixel_y = 6},/obj/item/clothing/glasses/welding,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/item/clothing/ears/earmuffs{pixel_x = -5; pixel_y = 6},/obj/item/clothing/glasses/welding,/obj/item/clothing/glasses/welding,/turf/simulated/floor,/area/engine/engineering) "ckF" = (/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/machinery/light{dir = 1},/turf/simulated/floor,/area/engine/engineering) "ckG" = (/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/item/device/radio/intercom{broadcasting = 0; name = "Station Intercom (General)"; pixel_y = 20},/obj/structure/table,/obj/item/device/modkit/tajaran,/turf/simulated/floor,/area/engine/engineering) -"ckH" = (/obj/machinery/computer/security{desc = ""; icon_state = "syndicam"; name = "Mission Monitor"; network = list("NUKE")},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/syndicate_station/start) +"ckH" = (/obj/machinery/computer/security/nuclear,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/syndicate_station/start) "ckI" = (/obj/structure/table,/obj/machinery/cell_charger,/turf/simulated/floor,/area/engine/engineering) "ckJ" = (/obj/structure/closet/crate{name = "solar pack crate"},/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/solar_assembly,/obj/item/weapon/circuitboard/solar_control,/obj/item/weapon/tracker_electronics,/obj/item/weapon/paper/solar,/obj/machinery/light{dir = 1},/obj/machinery/power/apc{cell_type = 15000; dir = 1; name = "Engineering APC"; pixel_x = 0; pixel_y = 25},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor,/area/engine/engineering) "ckK" = (/obj/machinery/alarm{pixel_x = 0; pixel_y = 24},/obj/machinery/computer/atmos_alert,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor,/area/engine/engineering)