adds the POOL to box station

F in chat for dorms 7.
This commit is contained in:
Detective Google
2020-01-11 23:34:07 -06:00
parent ae46c1f63d
commit d5b227a0ca
31 changed files with 1768 additions and 247 deletions
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
//TODO: move these to their own file
#define POOL_FRIGID 1
#define POOL_COOL 2
#define POOL_NORMAL 3
#define POOL_WARM 4
#define POOL_SCALDING 5
#define POOL_REAGENT_TICK_INTERVAL 5
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list("plasma"))
+4
View File
@@ -461,6 +461,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Recreation Area"
icon_state = "fitness"
/area/crew_quarters/fitness/pool
name = "Pool Area"
icon_state = "pool"
/area/crew_quarters/cafeteria
name = "Cafeteria"
icon_state = "cafeteria"
+2
View File
@@ -184,6 +184,8 @@
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/creep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
if("goose")
soundin = pick('sound/creatures/goose1.ogg', 'sound/creatures/goose2.ogg', 'sound/creatures/goose3.ogg', 'sound/creatures/goose4.ogg')
if("water_wade")
soundin = pick('sound/effects/water_wade1.ogg', 'sound/effects/water_wade2.ogg', 'sound/effects/water_wade3.ogg', 'sound/effects/water_wade4.ogg')
//START OF CIT CHANGES - adds random vore sounds
if ("struggle_sound")
soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg',
@@ -0,0 +1,91 @@
//shameless copies of carps.
/mob/living/simple_animal/hostile/shark
name = "Space Shark"
desc = "The best terror of the seas, next to the kraken."
icon_state = "shark"
icon_living = "shark"
icon = 'icons/mob/sharks.dmi'
icon_dead = "shark_dead"
icon_gib = "carp_gib"
environment_smash = 0
speak_chance = 0
turns_per_move = 3
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
speed = 0
maxHealth = 75
health = 75
harm_intent_damage = 18
melee_damage_lower = 18
melee_damage_upper = 18
attacktext = "maims"
attack_sound = 'sound/weapons/bite.ogg'
gold_core_spawnable = 1
//Space shark aren't affected by cold.
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
faction = list("shark")
/mob/living/simple_animal/hostile/shark/Process_Spacemove(var/movement_dir = 0)
return 1 //No drifting in space for space sharks....either!
/mob/living/simple_animal/hostile/shark/FindTarget()
. = ..()
if(.)
emote("me", 1, "growls at [.]!")
/mob/living/simple_animal/hostile/shark/AttackingTarget()
. =..()
var/mob/living/carbon/L = .
if(istype(L))
if(prob(25))
L.Knockdown(20)
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
/mob/living/simple_animal/hostile/shark/laser
name = "Laser-Shark"
desc = "NOW we've jumped the shark."
icon_state = "lasershark"
icon_living = "lasershark"
icon_dead = "lasershark_dead"
icon_gib = "carp_gib"
ranged = 1
retreat_distance = 3
minimum_distance = 0 //Between shots they can and will close in to nash
projectiletype = /obj/item/projectile/beam/laser/heavylaser
projectilesound = 'sound/weapons/lasercannonfire.ogg'
maxHealth = 50
health = 50
/mob/living/simple_animal/hostile/shark/kawaii
name = "Kawaii Shark"
desc = "Senpai~ Notice me.."
icon_state = "kawaiishark"
icon_living = "kawaiishark"
icon_dead = "kawaiishark_dead"
speak = list("Oh Senpai","Notice me senpai!","Oh my...","Kawaii~")
speak_emote = list("lovingly says","says")
speak_chance = 2
turns_per_move = 3
butcher_results = list(/mob/living/simple_animal/butterfly = 3)
maxHealth = 50
health = 50
maxbodytemp = INFINITY
harm_intent_damage = 0
melee_damage_lower = 0
melee_damage_upper = 0
attacktext = "violently hugs"
vision_range = 0
/mob/living/simple_animal/hostile/shark/kawaii/death()
visible_message("<span class='name'>[src]</span> says : Senpai, you noticed~!")
LoseAggro()
..()
walk(src, 0)
+336
View File
@@ -0,0 +1,336 @@
//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, "<span class='warning'>You disable the [src]'s safety features.</span>")
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, "<span class='warning'>The interface on [src] is already too damaged to short it again.</span>")
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("<span class='notice'>\The [src] makes a slurping noise.</span>", "<span class='notice'>All of the contents of \the [W] are quickly suctioned out by the machine!</span")
updateUsrDialog()
var/reagent_names = ""
for(var/datum/reagent/R in reagents.reagent_list)
reagent_names += "[R.name], "
log_game("[key_name(user)] has changed the [src] chems to [reagent_names]")
message_admins("[key_name_admin(user)] has changed the [src] chems to [reagent_names].")
interact_delay = world.time + 15
else
to_chat(user, "<span class='notice'>\The [src] beeps unpleasantly as it rejects the beaker. It must not have enough in it.</span>")
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, "<span class='danger'>You're drowning!</span>")
/* 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 "<span class='bad'>Frigid</span>"
if(POOL_COOL)
return "<span class='good'>Cool</span>"
if(POOL_NORMAL)
return "<span class='good'>Normal</span>"
if(POOL_WARM)
return "<span class='good'>Warm</span>"
if(POOL_SCALDING)
return "<span class='bad'>Scalding</span>"
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 += "<span class='notice'>[(interact_delay - world.time)] seconds left until [src] can operate again.</span><BR>"
dat += text({"
<h3>Temperature</h3>
<div class='statusDisplay'>
<B>Current temperature:</B> [temp2text()]<BR>
[CanUpTemp(user) ? "<a href='?src=\ref[src];IncreaseTemp=1'>Increase Temperature</a><br>" : "<span class='linkOff'>Increase Temperature</span><br>"]
[CanDownTemp(user) ? "<a href='?src=\ref[src];DecreaseTemp=1'>Decrease Temperature</a><br>" : "<span class='linkOff'>Decrease Temperature</span><br>"]
</div>
<h3>Drain</h3>
<div class='statusDisplay'>
<B>Drain status:</B> [(issilicon(user) || IsAdminGhost(user) || drainable) ? "<span class='bad'>Enabled</span>" : "<span class='good'>Disabled</span>"]
<br><b>Pool status:</b> "})
if(!drained)
dat += "<span class='good'>Full</span><BR>"
else
dat += "<span class='bad'>Drained</span><BR>"
if((issilicon(user) || IsAdminGhost(user) || drainable) && !linked_drain.active)
dat += "<a href='?src=\ref[src];Activate Drain=1'>[drained ? "Fill" : "Drain"] Pool</a><br>"
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
+129
View File
@@ -0,0 +1,129 @@
/obj/machinery/pool/drain
name = "drain"
icon_state = "drain"
desc = "A suction system to remove the contents of the pool, and sometimes small objects. Do not insert fingers."
anchored = TRUE
var/active = FALSE
var/status = FALSE //1 is drained, 0 is full.
var/srange = 6
var/timer = 0
var/cooldown
var/obj/machinery/pool/controller/pool_controller = null
/obj/machinery/pool/drain/Initialize()
START_PROCESSING(SSprocessing, src)
. = ..()
/obj/machinery/pool/drain/Destroy()
pool_controller.linked_drain = null
pool_controller = null
return ..()
/obj/machinery/pool/drain/process()
if(!status) //don't pool/drain an empty pool.
for(var/obj/item/absorbo in orange(1,src))
if(absorbo.w_class == WEIGHT_CLASS_TINY)
step_towards(absorbo, src)
var/dist = get_dist(src, absorbo)
if(dist == 0)
absorbo.forceMove(pool_controller.linked_filter)
if(active)
if(status) //if filling up, get back to normal position
if(timer > 0)
playsound(src, 'sound/effects/fillingwatter.ogg', 100, TRUE)
timer--
for(var/obj/whirlo in orange(1,src))
if(!whirlo.anchored )
step_away(whirlo,src)
for(var/mob/living/carbon/human/whirlm in orange(2,src))
step_away(whirlm,src)
else if(!timer)
for(var/turf/open/pool/undrained in range(5,src))
undrained.filled = TRUE
undrained.update_icon()
for(var/obj/effect/waterspout/undrained3 in range(1,src))
qdel(undrained3)
pool_controller.drained = FALSE
if(pool_controller.bloody < 1000)
pool_controller.bloody /= 2
if(pool_controller.bloody > 1000)
pool_controller.bloody /= 4
pool_controller.changecolor()
status = FALSE
active = FALSE
return
if(!status) //if draining, change everything.
if(timer > 0)
playsound(src, 'sound/effects/pooldrain.ogg', 100, TRUE)
playsound(src, "water_wade", 60, TRUE)
timer--
for(var/obj/whirlo in orange(2,src))
if(!whirlo.anchored )
step_towards(whirlo,src)
for(var/mob/living/carbon/human/whirlm in orange(2,src))
step_towards(whirlm,src)
if(prob(20))
whirlm.Knockdown(40)
for(var/i in list(1,2,4,8,4,2,1)) //swirl!
whirlm.dir = i
sleep(1)
if(whirlm.forceMove(loc))
if(whirlm.health <= -50) //If very damaged, gib.
whirlm.gib()
if(whirlm.stat != CONSCIOUS || whirlm.lying) // If
whirlm.adjustBruteLoss(5)
playsound(src, pick('sound/misc/crack.ogg','sound/misc/crunch.ogg'), 50, TRUE)
to_chat(whirlm, "<span class='danger'>You're caught in the drain!</span>")
continue
else
playsound(src, pick('sound/misc/crack.ogg','sound/misc/crunch.ogg'), 50, TRUE)
whirlm.apply_damage(4, BRUTE, pick("l_leg", "r_leg")) //drain should only target the legs
to_chat(whirlm, "<span class='danger'>Your legs are caught in the drain!</span>")
continue
else if(!timer)
for(var/turf/open/pool/drained in range(5,src))
drained.filled = FALSE
drained.update_icon()
for(var/obj/effect/whirlpool/drained3 in range(1,src))
qdel(drained3)
for(var/obj/machinery/pool/controller/drained4 in range(5,src))
drained4.drained = TRUE
drained4.mistoff()
status = TRUE
active = FALSE
/obj/machinery/pool/filter
name = "Filter"
icon_state = "filter"
desc = "The part of the pool where all the IDs, ATV keys, and pens, and other dangerous things get trapped."
var/obj/machinery/pool/controller/pool_controller = null
/obj/machinery/pool/filter/Destroy()
pool_controller.linked_filter = null
pool_controller = null
return ..()
/obj/machinery/pool/filter/emag_act(user as mob)
if(!(obj_flags & EMAGGED))
to_chat(user, "<span class='warning'>You disable the [src]'s shark filter! Run!</span>")
obj_flags |= EMAGGED
do_sparks(5, TRUE, src)
icon_state = "filter_b"
addtimer(CALLBACK(src, /obj/machinery/pool/filter/proc/spawn_shark), 50)
log_game("[key_name(user)] emagged the pool filter and spawned a shark")
message_admins("[key_name_admin(user)] emagged the pool filter and spawned a shark")
/obj/machinery/pool/filter/proc/spawn_shark()
if(prob(50))
new /mob/living/simple_animal/hostile/shark(loc)
else
if(prob(50))
new /mob/living/simple_animal/hostile/shark/kawaii(loc)
else
new /mob/living/simple_animal/hostile/shark/laser(loc)
/obj/machinery/pool/filter/attack_hand(mob/user)
to_chat(user, "You search the filter.")
for(var/obj/O in contents)
O.forceMove(loc)
+29
View File
@@ -0,0 +1,29 @@
/obj/effect/splash
name = "splash"
desc = "Wataaa!."
icon = 'icons/turf/pool.dmi'
icon_state = "splash"
layer = ABOVE_ALL_MOB_LAYER
/obj/effect/whirlpool
name = "Whirlpool"
icon = 'icons/effects/96x96.dmi'
icon_state = "whirlpool"
layer = 5
anchored = TRUE
mouse_opacity = 0
pixel_x = -32
pixel_y = -32
alpha = 90
/obj/effect/waterspout
name = "Waterspout"
icon = 'icons/effects/96x96.dmi'
icon_state = "waterspout"
color = "#3399AA"
layer = 5
anchored = TRUE
mouse_opacity = 0
pixel_x = -32
pixel_y = -32
alpha = 120
+201
View File
@@ -0,0 +1,201 @@
/turf/open/pool
icon = 'icons/turf/pool.dmi'
name = "poolwater"
desc = "You're safer here than in the deep."
icon_state = "pool_tile"
heat_capacity = INFINITY
var/filled = TRUE
var/next_splash = 1
var/obj/effect/overlay/water/watereffect
var/obj/effect/overlay/water/top/watertop
var/obj/machinery/pool/controller/controller
/turf/open/pool/Initialize()
watereffect = new /obj/effect/overlay/water(src)
watertop = new /obj/effect/overlay/water/top(src)
. = ..()
/turf/open/pool/Destroy()
QDEL_NULL(watereffect)
QDEL_NULL(watertop)
controller = null
return ..()
/turf/open/pool/proc/update_icon_pool()
if(!filled)
name = "drained pool"
desc = "No diving!"
QDEL_NULL(watereffect)
QDEL_NULL(watertop)
else
name = "poolwater"
desc = "You're safer here than in the deep."
watereffect = new /obj/effect/overlay/water(src)
watertop = new /obj/effect/overlay/water/top(src)
/obj/effect/overlay/water
name = "water"
icon = 'icons/turf/pool.dmi'
icon_state = "bottom"
density = 0
mouse_opacity = 0
layer = ABOVE_MOB_LAYER
anchored = TRUE
/obj/effect/overlay/water/top
icon_state = "top"
layer = BELOW_MOB_LAYER
/mob/living
var/swimming = FALSE
//Put people out of the water
/turf/open/floor/MouseDrop_T(mob/living/M, mob/living/user)
if(user.stat || user.lying || !Adjacent(user) || !M.Adjacent(user)|| !iscarbon(M))
if(issilicon(M))
var/turf/T = get_turf(M)
if(istype(T, /turf/open/pool))
M.visible_message("<span class='notice'>[M] begins to float.", \
"<span class='notice'>You start your emergency floaters.</span>")
if(do_mob(user, M, 20))
M.forceMove(src)
to_chat(user, "<span class='notice'>You get out of the pool.</span>")
return ..()
if(!M.swimming) //can't put yourself up if you are not swimming
return ..()
if(user == M)
M.visible_message("<span class='notice'>[user] is getting out the pool", \
"<span class='notice'>You start getting out of the pool.</span>")
if(do_mob(user, M, 20))
M.swimming = FALSE
M.forceMove(src)
to_chat(user, "<span class='notice'>You get out of the pool.</span>")
else
user.visible_message("<span class='notice'>[M] is being pulled to the poolborder by [user].</span>", \
"<span class='notice'>You start getting [M] out of the pool.")
if(do_mob(user, M, 20))
M.swimming = FALSE
M.forceMove(src)
to_chat(user, "<span class='notice'>You get [M] out of the pool.</span>")
return
/turf/open/floor/CanPass(atom/movable/A, turf/T)
if(!has_gravity(src))
return ..()
else if(istype(A, /mob/living) || istype(A, /obj/structure)) //This check ensures that only specific types of objects cannot pass into the water. Items will be able to get tossed out.
if(istype(A, /mob/living/simple_animal) || istype(A, /mob/living/carbon/monkey))
return ..()
if (istype(A, /obj/structure) && istype(A.pulledby, /mob/living/carbon/human))
return ..()
if(istype(get_turf(A), /turf/open/pool) && !istype(T, /turf/open/pool)) //!(locate(/obj/structure/pool/ladder) in get_turf(A).loc)
return FALSE
return ..()
//put people in water, including you
/turf/open/pool/MouseDrop_T(mob/living/M, mob/living/user)
if(!has_gravity(src))
return
if(user.stat || user.lying || !Adjacent(user) || !M.Adjacent(user)|| !iscarbon(M))
return
if(!iscarbon(user)) // no silicons or drones in mechas.
return
if(M.swimming) //can't lower yourself again
return
else
if(user == M)
M.visible_message("<span class='notice'>[user] is descending in the pool", \
"<span class='notice'>You start lowering yourself in the pool.</span>")
if(do_mob(user, M, 20))
M.swimming = TRUE
M.forceMove(src)
to_chat(user, "<span class='notice'>You lower yourself in the pool.</span>")
else
user.visible_message("<span class='notice'>[M] is being put in the pool by [user].</span>", \
"<span class='notice'>You start lowering [M] in the pool.")
if(do_mob(user, M, 20))
M.swimming = TRUE
M.forceMove(src)
to_chat(user, "<span class='notice'>You lower [M] in the pool.</span>")
return
//What happens if you don't drop in it like a good person would, you fool.
/turf/open/pool/Exited(atom/A, turf/NL)
..()
if(!istype(NL, /turf/open/pool) && isliving(A))
var/mob/living/M = A
M.swimming = FALSE
controller.mobs_in_pool.Remove(M)
/turf/open/pool/Entered(atom/A, turf/OL)
..()
if(isliving(A))
var/mob/living/M = A
if(!M.mob_has_gravity())
return
if(!M.swimming)
M.swimming = TRUE
controller.mobs_in_pool.Add(M)
if(locate(/obj/structure/pool/ladder) in M.loc)
return
if(iscarbon(M))
var/mob/living/carbon/H = M
if(filled)
if (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSMOUTH)
H.visible_message("<span class='danger'>[H] falls in the water!</span>",
"<span class='userdanger'>You fall in the water!</span>")
playsound(src, 'sound/effects/splash.ogg', 60, TRUE, 1)
H.Knockdown(20)
return
else
H.Knockdown(60)
H.adjustOxyLoss(5)
H.emote("cough")
H.visible_message("<span class='danger'>[H] falls in and takes a drink!</span>",
"<span class='userdanger'>You fall in and swallow some water!</span>")
playsound(src, 'sound/effects/splash.ogg', 60, TRUE, 1)
else if(!istype(H.head, /obj/item/clothing/head/helmet))
if(prob(75))
H.visible_message("<span class='danger'>[H] falls in the drained pool!</span>",
"<span class='userdanger'>You fall in the drained pool!</span>")
H.adjustBruteLoss(7)
H.Knockdown(80)
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
else
H.visible_message("<span class='danger'>[H] falls in the drained pool, and cracks his skull!</span>",
"<span class='userdanger'>You fall in the drained pool, and crack your skull!</span>")
H.apply_damage(15, BRUTE, "head")
H.Knockdown(200) // This should hurt. And it does.
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
playsound(src, 'sound/misc/crack.ogg', 100, TRUE)
else
H.visible_message("<span class='danger'>[H] falls in the drained pool, but had an helmet!</span>",
"<span class='userdanger'>You fall in the drained pool, but you had an helmet!</span>")
H.Knockdown(40)
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
else if(filled)
M.adjustStaminaLoss(1)
playsound(src, "water_wade", 20, TRUE)
return
/turf/open/pool/attack_hand(mob/living/user)
if(user.stat == CONSCIOUS && !(user.lying || user.resting) && Adjacent(user) && user.swimming && filled && next_splash < world.time) //not drained, user alive and close, and user in water.
if(user.x == x && user.y == y)
return
else
playsound(src, 'sound/effects/watersplash.ogg', 8, TRUE, 1)
next_splash = world.time + 25
var/obj/effect/splash/S = new /obj/effect/splash(user.loc)
animate(S, alpha = 0, time = 8)
S.Move(src)
QDEL_IN(S, 20)
for(var/mob/living/carbon/human/L in src)
if(!L.wear_mask && !user.stat) //Do not affect those underwater or dying.
L.emote("cough")
L.adjustStaminaLoss(4) //You need to give em a break!
/turf/open/pool/attackby(obj/item/W, mob/living/user)
if(istype(W, /obj/item/mop) && filled)
W.reagents.add_reagent("water", 5)
to_chat(user, "<span class='notice'>You wet [W] in [src].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
+44
View File
@@ -0,0 +1,44 @@
//Pool noodles
/obj/item/toy/poolnoodle
icon = 'icons/obj/toy.dmi'
icon_state = "noodle"
name = "pool noodle"
desc = "A strange, bulky, bendable toy that can annoy people."
force = 0
color = "#000000"
w_class = WEIGHT_CLASS_SMALL
throwforce = 1
throw_speed = 10 //weeee
hitsound = 'sound/weapons/tap.ogg'
attack_verb = list("flogged", "poked", "jabbed", "slapped", "annoyed")
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
/obj/item/toy/poolnoodle/attack(target as mob, mob/living/user as mob)
..()
if(prob(80))
user.emote("spin")
if(prob(5))
user.emote("spin")
/obj/item/toy/poolnoodle/red
item_state = "noodlered"
/obj/item/toy/poolnoodle/blue
item_state = "noodleblue"
/obj/item/toy/poolnoodle/yellow
item_state = "noodleyellow"
/obj/item/toy/poolnoodle/red/Initialize()
. = ..()
color = "#ff4c4c"
/obj/item/toy/poolnoodle/blue/Initialize()
. = ..()
color = "#3232ff"
/obj/item/toy/poolnoodle/yellow/Initialize()
. = ..()
color = "#ffff66"
+149
View File
@@ -0,0 +1,149 @@
/obj/structure/pool
name = "pool"
icon = 'icons/obj/machines/pool.dmi'
anchored = TRUE
resistance_flags = UNACIDABLE|INDESTRUCTIBLE
/obj/structure/pool/ladder
name = "Ladder"
icon_state = "ladder"
desc = "Are you getting in or are you getting out?."
layer = ABOVE_MOB_LAYER
dir = EAST
/obj/structure/pool/ladder/attack_hand(mob/living/user as mob)
if(Adjacent(user) && user.y == y && user.swimming == 0)
user.swimming = TRUE
user.forceMove(get_step(user, get_dir(user, src))) //Either way, you're getting IN or OUT of the pool.
else if(user.loc == loc && user.swimming == TRUE)
user.swimming = FALSE
user.forceMove(get_step(user, turn(dir, 180)))
/obj/structure/pool/Rboard
name = "JumpBoard"
density = FALSE
icon_state = "boardright"
desc = "The less-loved portion of the jumping board."
dir = EAST
/obj/structure/pool/Rboard/CheckExit(atom/movable/O as mob|obj, target as turf)
if(istype(O) && O.pass_flags & PASSGLASS)
return TRUE
if(get_dir(O.loc, target) == dir)
return FALSE
return TRUE
/obj/structure/pool/Lboard
name = "JumpBoard"
icon_state = "boardleft"
desc = "Get on there to jump!"
layer = FLY_LAYER
dir = WEST
var/jumping = FALSE
var/timer
/obj/structure/pool/Lboard/proc/backswim(obj/O, mob/living/user) //Puts the sprite back to it's maiden condition after a jump.
if(jumping)
for(var/mob/living/jumpee in loc) //hackzors.
playsound(jumpee, 'sound/effects/splash.ogg', 60, TRUE, 1)
jumpee.layer = 4
jumpee.pixel_x = 0
jumpee.pixel_y = 0
jumpee.Stun(2)
jumpee.swimming = TRUE
/obj/structure/pool/Lboard/attack_hand(mob/living/user)
if(iscarbon(user))
var/mob/living/carbon/jumper = user
if(jumping)
to_chat(user, "<span class='notice'>Someone else is already making a jump!</span>")
return
var/turf/T = get_turf(src)
if(user.swimming)
return
else
for(var/obj/machinery/pool/controller/pc in range(4,src)) //Clunky as fuck I know.
if(pc.drained)
to_chat(user, "<span class='notice'>That would be suicide</span>") //TODO: make this a suicide action.
return
if(Adjacent(jumper))
jumper.visible_message("<span class='notice'>[user] climbs up \the [src]!</span>", \
"<span class='notice'>You climb up \the [src] and prepares to jump!</span>")
jumper.Stun(40)
jumping = TRUE
jumper.layer = RIPPLE_LAYER
jumper.pixel_x = 3
jumper.pixel_y = 7
jumper.dir=8
sleep(1)
jumper.loc = T
addtimer(CALLBACK(src, .proc/dive, jumper), 10)
/obj/structure/pool/Lboard/proc/dive(mob/living/carbon/jumper)
switch(rand(1, 100))
if(1 to 20)
jumper.visible_message("<span class='notice'>[jumper] goes for a small dive!</span>", \
"<span class='notice'>You go for a small dive.</span>")
sleep(15)
backswim()
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 1, 1)
if(21 to 40)
jumper.visible_message("<span class='notice'>[jumper] goes for a dive!</span>", \
"<span class='notice'>You're going for a dive!</span>")
sleep(20)
backswim()
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 2, 1)
if(41 to 60)
jumper.visible_message("<span class='notice'>[jumper] goes for a long dive! Stay far away!</span>", \
"<span class='notice'>You're going for a long dive!!</span>")
sleep(25)
backswim()
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 3, 1)
if(61 to 80)
jumper.visible_message("<span class='notice'>[jumper] goes for an awesome dive! Don't stand in [jumper.p_their()] way!</span>", \
"<span class='notice'>You feel like this dive will be awesome</span>")
sleep(30)
backswim()
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 4, 1)
if(81 to 91)
sleep(20)
backswim()
jumper.visible_message("<span class='danger'>[jumper] misses [jumper.p_their()] step!</span>", \
"<span class='userdanger'>You misstep!</span>")
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 0, 1)
jumper.Knockdown(100)
jumper.adjustBruteLoss(10)
if(91 to 100)
jumper.visible_message("<span class='notice'>[jumper] is preparing for the legendary dive! Can he make it?</span>", \
"<span class='userdanger'>You start preparing for a legendary dive!</span>")
jumper.SpinAnimation(7,1)
sleep(30)
if(prob(75))
backswim()
jumper.visible_message("<span class='notice'>[jumper] fails!</span>", \
"<span class='userdanger'>You can't quite do it!</span>")
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 1, 1)
else
jumper.fire_stacks = min(1,jumper.fire_stacks + 1)
jumper.IgniteMob()
sleep(5)
backswim()
jumper.visible_message("<span class='danger'>[jumper] bursts into flames of pure awesomness!</span>", \
"<span class='userdanger'>No one can stop you now!</span>")
var/atom/throw_target = get_edge_target_turf(src, dir)
jumper.throw_at(throw_target, 6, 1)
addtimer(CALLBACK(src, .proc/togglejumping), 35)
/obj/structure/pool/Lboard/proc/togglejumping()
jumping = FALSE
+59
View File
@@ -0,0 +1,59 @@
#define POOL_WIRE_DRAIN "drain"
#define POOL_WIRE_TEMP "temp"
/datum/wires/poolcontroller
holder_type = /obj/machinery/pool/controller
proper_name = "Pool"
/datum/wires/poolcontroller/New(atom/holder)
wires = list(
POOL_WIRE_DRAIN, WIRE_SHOCK, WIRE_ZAP, POOL_WIRE_TEMP
)
add_duds(3)
..()
/datum/wires/poolcontroller/interactable(mob/user)
var/obj/machinery/pool/controller/P = holder
if(P.panel_open)
return TRUE
/datum/wires/poolcontroller/get_status()
var/obj/machinery/pool/controller/P = holder
var/list/status = list()
status += "The blue light is [P.drainable ? "on" : "off"]."
status += "The red light is [P.tempunlocked ? "on" : "off"]."
status += "The yellow light is [P.shocked ? "on" : "off"]."
return status
/datum/wires/poolcontroller/on_pulse(wire)
var/obj/machinery/pool/controller/P = holder
switch(wire)
if(POOL_WIRE_DRAIN)
P.drainable = FALSE
if(POOL_WIRE_TEMP)
P.tempunlocked = FALSE
if(WIRE_SHOCK)
P.shocked = !P.shocked
addtimer(CALLBACK(P, /obj/machinery/autolathe.proc/reset, wire), 60)
/datum/wires/poolcontroller/on_cut(wire, mend)
var/obj/machinery/pool/controller/P = holder
switch(wire)
if(POOL_WIRE_DRAIN)
if(mend)
P.drainable = FALSE
else
P.drainable = TRUE
if(POOL_WIRE_TEMP)
if(mend)
P.tempunlocked = FALSE
else
P.tempunlocked = TRUE
if(WIRE_ZAP)
P.shock(usr, 50)
if(WIRE_SHOCK)
if(mend)
P.stat &= ~NOPOWER
else
P.stat |= NOPOWER
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+9
View File
@@ -76,6 +76,7 @@
#include "code\__DEFINES\obj_flags.dm"
#include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm"
#include "code\__DEFINES\pool.dm"
#include "code\__DEFINES\preferences.dm"
#include "code\__DEFINES\procpath.dm"
#include "code\__DEFINES\profile.dm"
@@ -2352,6 +2353,7 @@
#include "code\modules\mob\living\simple_animal\hostile\netherworld.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
#include "code\modules\mob\living\simple_animal\hostile\sharks.dm"
#include "code\modules\mob\living\simple_animal\hostile\skeleton.dm"
#include "code\modules\mob\living\simple_animal\hostile\statue.dm"
#include "code\modules\mob\living\simple_animal\hostile\stickman.dm"
@@ -2500,6 +2502,13 @@
#include "code\modules\photography\photos\album.dm"
#include "code\modules\photography\photos\frame.dm"
#include "code\modules\photography\photos\photo.dm"
#include "code\modules\pool\pool_controller.dm"
#include "code\modules\pool\pool_drain.dm"
#include "code\modules\pool\pool_effects.dm"
#include "code\modules\pool\pool_main.dm"
#include "code\modules\pool\pool_noodles.dm"
#include "code\modules\pool\pool_structures.dm"
#include "code\modules\pool\pool_wires.dm"
#include "code\modules\power\apc.dm"
#include "code\modules\power\cable.dm"
#include "code\modules\power\cell.dm"