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
code/__DEFINES/pool.dm Normal file
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"))

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" name = "Recreation Area"
icon_state = "fitness" icon_state = "fitness"
/area/crew_quarters/fitness/pool
name = "Pool Area"
icon_state = "pool"
/area/crew_quarters/cafeteria /area/crew_quarters/cafeteria
name = "Cafeteria" name = "Cafeteria"
icon_state = "cafeteria" icon_state = "cafeteria"

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') 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") if("goose")
soundin = pick('sound/creatures/goose1.ogg', 'sound/creatures/goose2.ogg', 'sound/creatures/goose3.ogg', 'sound/creatures/goose4.ogg') 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 //START OF CIT CHANGES - adds random vore sounds
if ("struggle_sound") if ("struggle_sound")
soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg', soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg',

View File

@@ -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)

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

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)

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

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)

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"

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

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

BIN
icons/mob/sharks.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
icons/obj/machines/pool.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

BIN
icons/turf/pool.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

BIN
sound/effects/pooldrain.ogg Normal file

Binary file not shown.

BIN
sound/effects/splash.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
sound/misc/crack.ogg Normal file

Binary file not shown.

BIN
sound/misc/crunch.ogg Normal file

Binary file not shown.

View File

@@ -76,6 +76,7 @@
#include "code\__DEFINES\obj_flags.dm" #include "code\__DEFINES\obj_flags.dm"
#include "code\__DEFINES\pinpointers.dm" #include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm" #include "code\__DEFINES\pipe_construction.dm"
#include "code\__DEFINES\pool.dm"
#include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\preferences.dm"
#include "code\__DEFINES\procpath.dm" #include "code\__DEFINES\procpath.dm"
#include "code\__DEFINES\profile.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\netherworld.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.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\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\skeleton.dm"
#include "code\modules\mob\living\simple_animal\hostile\statue.dm" #include "code\modules\mob\living\simple_animal\hostile\statue.dm"
#include "code\modules\mob\living\simple_animal\hostile\stickman.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\album.dm"
#include "code\modules\photography\photos\frame.dm" #include "code\modules\photography\photos\frame.dm"
#include "code\modules\photography\photos\photo.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\apc.dm"
#include "code\modules\power\cable.dm" #include "code\modules\power\cable.dm"
#include "code\modules\power\cell.dm" #include "code\modules\power\cell.dm"