//Originally stolen from paradise. Credits to tigercat2000. //Modified a lot by Kokojo and Tortellini Tony for hippiestation. //Heavily refactored by tgstation /obj/machinery/pool icon = 'icons/obj/machines/pool.dmi' anchored = TRUE /obj/machinery/pool/controller name = "\improper Pool Controller" desc = "An advanced substance generation and fluid tank management system that can refill the contents of a pool to a completely different substance in minutes." icon_state = "poolc_3" density = TRUE use_power = TRUE idle_power_usage = 75 var/list/linkedturfs //List contains all of the linked pool turfs to this controller, assignment happens on initialize var/list/mobs_in_pool = list()//List contains all the mobs currently in the pool. var/temperature = POOL_NORMAL //1-5 Frigid Cool Normal Warm Scalding var/srange = 6 //The range of the search for pool turfs, change this for bigger or smaller pools. var/list/linkedmist = list() //Used to keep track of created mist var/misted = FALSE //Used to check for mist. var/cur_reagent = "water" var/drainable = FALSE var/drained = FALSE var/bloody = 0 var/obj/machinery/pool/drain/linked_drain = null var/obj/machinery/pool/filter/linked_filter = null var/interact_delay = 0 //cooldown on messing with settings var/reagent_delay = 0 //cooldown on reagent ticking var/shocked = FALSE//Shocks morons, like an airlock. var/tempunlocked = FALSE var/old_rcolor /obj/machinery/pool/controller/Initialize() . = ..() START_PROCESSING(SSprocessing, src) create_reagents(100) wires = new /datum/wires/poolcontroller(src) scan_things() /obj/machinery/pool/controller/proc/scan_things() for(var/turf/open/pool/W in range(srange,src)) LAZYADD(linkedturfs, W) W.controller = src for(var/obj/machinery/pool/drain/pooldrain in range(srange,src)) linked_drain = pooldrain linked_drain.pool_controller = src for(var/obj/machinery/pool/filter/F in range(srange, src)) linked_filter = F linked_filter.pool_controller = src /obj/machinery/pool/controller/Destroy() STOP_PROCESSING(SSprocessing, src) linked_drain = null linked_filter = null linkedturfs.Cut() mobs_in_pool.Cut() return ..() /obj/machinery/pool/controller/emag_act(user as mob) //Emag_act, this is called when it is hit with a cryptographic sequencer. if(!(obj_flags & EMAGGED)) //If it is not already emagged, emag it. to_chat(user, "You disable the [src]'s safety features.") do_sparks(5, TRUE, src) obj_flags |= EMAGGED tempunlocked = TRUE drainable = TRUE log_game("[key_name(user)] emagged [src]") message_admins("[key_name_admin(user)] emagged [src]") else to_chat(user, "The interface on [src] is already too damaged to short it again.") return /obj/machinery/pool/controller/attackby(obj/item/W, mob/user) if(shocked && !(stat & NOPOWER)) shock(user,50) if(stat & (BROKEN)) return if(istype(W,/obj/item/reagent_containers)) if(W.reagents.total_volume >= 100) //check if there's enough reagent for(var/datum/reagent/R in W.reagents.reagent_list) if(R.name in GLOB.blacklisted_pool_reagents) to_chat(user, "\The [src] cannot accept [R.name].") reagents.clear_reagents() return if(R.reagent_state == SOLID) to_chat(user, "The pool cannot accept reagents in solid form!.") reagents.clear_reagents() return reagents.clear_reagents() W.reagents.copy_to(reagents, 100) W.reagents.clear_reagents() user.visible_message("\The [src] makes a slurping noise.", "All of the contents of \the [W] are quickly suctioned out by the machine!\The [src] beeps unpleasantly as it rejects the beaker. It must not have enough in it.") return else if(panel_open && is_wire_tool(W)) wires.interact(user) else return ..() /obj/machinery/pool/controller/screwdriver_act(mob/living/user, obj/item/W) . = ..() if(.) return TRUE cut_overlays() panel_open = !panel_open to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") W.play_tool_sound(src) if(panel_open) add_overlay("wires") return TRUE //procs /obj/machinery/pool/controller/proc/shock(mob/user, prb) if(stat & (BROKEN|NOPOWER)) // unpowered, no shock return FALSE if(!prob(prb)) return FALSE var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(5, 1, src) s.start() if(electrocute_mob(user, get_area(src), src, 0.7)) return TRUE else return FALSE /obj/machinery/pool/controller/proc/poolreagent() if(reagents.reagent_list.len > 0) for(var/turf/open/pool/W in linkedturfs) for(var/mob/living/carbon/human/swimee in W) for(var/datum/reagent/R in reagents.reagent_list) if(R.reagent_state == SOLID) R.reagent_state = LIQUID swimee.reagents.add_reagent(R.name, 0.5) //osmosis reagents.reaction(swimee, VAPOR, 0.03) //3 percent for(var/obj/objects in W) if(W.reagents) W.reagents.reaction(objects, VAPOR, 1) reagent_delay = world.time + POOL_REAGENT_TICK_INTERVAL changecolor() /obj/machinery/pool/controller/process() updateUsrDialog() if(stat & (NOPOWER|BROKEN)) return if (!drained) updatePool() if(reagent_delay <= world.time) poolreagent() /obj/machinery/pool/controller/proc/updatePool() if(!drained) for(var/mob/living/M in mobs_in_pool) switch(temperature) //Apply different effects based on what the temperature is set to. if(POOL_SCALDING) //Scalding M.adjust_bodytemperature(50,0,500) if(POOL_WARM) //Warm M.adjust_bodytemperature(20,0,360) //Heats up mobs till the termometer shows up if(POOL_NORMAL) //Normal temp does nothing, because it's just room temperature water. if(POOL_COOL) M.adjust_bodytemperature(-20,250) //Cools mobs till the termometer shows up if(POOL_FRIGID) //Freezing M.adjust_bodytemperature(-60) //cool mob at -35k per cycle, less would not affect the mob enough. if(M.bodytemperature <= 50 && !M.stat) M.apply_status_effect(/datum/status_effect/freon) if(ishuman(M)) var/mob/living/carbon/human/drownee = M if(!drownee || drownee.stat == DEAD) return if(drownee.lying && !drownee.internal) if(drownee.stat != CONSCIOUS) drownee.adjustOxyLoss(9) else drownee.adjustOxyLoss(4) if(prob(35)) to_chat(drownee, "You're drowning!") /* not sure what to do about this part for(var/obj/effect/decal/cleanable/decal in W) CHECK_TICK animate(decal, alpha = 10, time = 20) QDEL_IN(decal, 25) if(istype(decal,/obj/effect/decal/cleanable/blood) || istype(decal, /obj/effect/decal/cleanable/trail_holder)) bloody = TRUE */ changecolor() /obj/machinery/pool/controller/proc/changecolor() if(drained) return var/rcolor if(reagents.reagent_list.len) rcolor = mix_color_from_reagents(reagents.reagent_list) if(rcolor == old_rcolor) return // small performance upgrade hopefully? old_rcolor = rcolor for(var/X in linkedturfs) var/turf/open/pool/color1 = X if(bloody) if(rcolor) color1.watereffect.color = BlendRGB(rgb(150, 20, 20), rcolor, 0.5) color1.watertop.color = color1.watereffect.color else color1.watereffect.color = rgb(150, 20, 20) color1.watertop.color = color1.watereffect.color else if(!bloody && rcolor) color1.watereffect.color = rcolor color1.watertop.color = color1.watereffect.color else color1.watereffect.color = null color1.watertop.color = null /obj/machinery/pool/controller/proc/miston() //Spawn /obj/effect/mist (from the shower) on all linked pool tiles for(var/X in linkedturfs) var/turf/open/pool/W = X if(W.filled) var/M = new /obj/effect/mist(W) if(misted) return linkedmist += M misted = TRUE //var just to keep track of when the mist on proc has been called. /obj/machinery/pool/controller/proc/mistoff() //Delete all /obj/effect/mist from all linked pool tiles. for(var/M in linkedmist) qdel(M) misted = FALSE //no mist left, turn off the tracking var /obj/machinery/pool/controller/proc/handle_temp() interact_delay = world.time + 10 mistoff() icon_state = "poolc_[temperature]" if(temperature == POOL_SCALDING) miston() update_icon() /obj/machinery/pool/controller/proc/CanUpTemp(mob/user) if(temperature == POOL_WARM && (tempunlocked || issilicon(user) || IsAdminGhost(user)) || temperature < POOL_WARM) return TRUE return FALSE /obj/machinery/pool/controller/proc/CanDownTemp(mob/user) if(temperature == POOL_COOL && (tempunlocked || issilicon(user) || IsAdminGhost(user)) || temperature > POOL_COOL) return TRUE return FALSE /obj/machinery/pool/controller/Topic(href, href_list) if(..()) return if(interact_delay > world.time) return if(href_list["IncreaseTemp"]) if(CanUpTemp(usr)) temperature++ handle_temp() if(href_list["DecreaseTemp"]) if(CanDownTemp(usr)) temperature-- handle_temp() if(href_list["Activate Drain"]) if((drainable || issilicon(usr) || IsAdminGhost(usr)) && !linked_drain.active) mistoff() interact_delay = world.time + 60 linked_drain.active = TRUE linked_drain.timer = 15 if(!linked_drain.status) new /obj/effect/whirlpool(linked_drain.loc) temperature = POOL_NORMAL else new /obj/effect/waterspout(linked_drain.loc) temperature = POOL_NORMAL handle_temp() bloody = FALSE updateUsrDialog() /obj/machinery/pool/controller/proc/temp2text() switch(temperature) if(POOL_FRIGID) return "Frigid" if(POOL_COOL) return "Cool" if(POOL_NORMAL) return "Normal" if(POOL_WARM) return "Warm" if(POOL_SCALDING) return "Scalding" else return "Outside of possible range." /obj/machinery/pool/controller/ui_interact(mob/user) . = ..() if(.) return if(shocked && !(stat & NOPOWER)) shock(user,50) if(panel_open && !isAI(user)) return wires.interact(user) if(stat & (NOPOWER|BROKEN)) return var/datum/browser/popup = new(user, "Pool Controller", name, 300, 450) var/dat = "" if(interact_delay > world.time) dat += "[(interact_delay - world.time)] seconds left until [src] can operate again.
" dat += text({"

Temperature

Current temperature: [temp2text()]
[CanUpTemp(user) ? "Increase Temperature
" : "Increase Temperature
"] [CanDownTemp(user) ? "Decrease Temperature
" : "Decrease Temperature
"]

Drain

Drain status: [(issilicon(user) || IsAdminGhost(user) || drainable) ? "Enabled" : "Disabled"]
Pool status: "}) if(!drained) dat += "Full
" else dat += "Drained
" if((issilicon(user) || IsAdminGhost(user) || drainable) && !linked_drain.active) dat += "[drained ? "Fill" : "Drain"] Pool
" popup.set_content(dat) popup.open() /obj/machinery/pool/controller/proc/reset(wire) switch(wire) if(WIRE_SHOCK) if(!wires.is_cut(wire)) shocked = FALSE