mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-21 03:55:05 +01:00
Beach Expansion Update
Expands the beach away mission to include a brand new scuba-diving area! - Somewhat empty, but has a few points of interest scattered about and can be added to in the future Visually updates the beach - Sand texture changed, and given randomization for a more varied beachfront. - The row of crates and lockers has been replaced with 3 changing rooms/tents so you can change into that mankini in private. - Changes the water texture to be less bland - Expands the water area to give more room for swimmers to play in before they reach the edge Adds in the Diving Point Buoy and Diving Point Anchor objects, used to transition between the beach surface and the underwater area - Hit with an empty hand to transition between the two points The underwater area has a few "minor" dangers to prepare for: - Sea Carp - These carp (unlike their space-faring cousins) won't attack on sight, and will try to swim away when attacked. They still bite if they work up the courage to come back. - Water - Water and lungs don't work well together, who knew!? Skrell, Neara, and anyone who has NO_BREATHE can happily explore, while the rest will want to pack some internals lest they begin to drown. - Drowning in the scuba area doesn't require you to be lying down, unlike the pool. You're in over your head (literally). - Darkness - Not quite a danger in itself, but it's easy to get disoriented in the dark water, and that can be frustrating. CODE STUFF - Broke up the pool controller code into a couple procs for cleanliness and in case we want to have a type of pool controller that doesn't drown or doesn't adjust bodytemp - Made ladders use forceMove instead of directly setting loc - Removed an entirely unused area (/area/beach) Crappy coder-sprites for Buoy and Anchor done by myself. - Ok, they actually aren't THAT bad, but they aren't fantastic.
This commit is contained in:
@@ -17,7 +17,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
|
||||
/area
|
||||
var/fire = null
|
||||
var/atmos = 1
|
||||
var/atmosalm = 0
|
||||
var/poweralm = 1
|
||||
var/party = null
|
||||
@@ -2402,12 +2401,17 @@ area/security/podbay
|
||||
|
||||
/area/awaymission/beach
|
||||
name = "Beach"
|
||||
icon_state = "null"
|
||||
icon_state = "beach"
|
||||
luminosity = 1
|
||||
lighting_use_dynamic = 0
|
||||
requires_power = 0
|
||||
ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg')
|
||||
|
||||
/area/awaymission/undersea
|
||||
name = "Undersea"
|
||||
icon_state = "undersea"
|
||||
|
||||
|
||||
////////////////////////AWAY AREAS///////////////////////////////////
|
||||
|
||||
/area/awaycontent
|
||||
@@ -2576,62 +2580,3 @@ var/list/the_station_areas = list (
|
||||
/area/turret_protected/ai,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
/area/beach
|
||||
name = "Keelin's private beach"
|
||||
icon_state = "null"
|
||||
luminosity = 1
|
||||
lighting_use_dynamic = 0
|
||||
requires_power = 0
|
||||
var/sound/mysound = null
|
||||
|
||||
New()
|
||||
..()
|
||||
var/sound/S = new/sound()
|
||||
mysound = S
|
||||
S.file = 'sound/ambience/shore.ogg'
|
||||
S.repeat = 1
|
||||
S.wait = 0
|
||||
S.channel = 123
|
||||
S.volume = 100
|
||||
S.priority = 255
|
||||
S.status = SOUND_UPDATE
|
||||
process()
|
||||
|
||||
Entered(atom/movable/Obj,atom/OldLoc)
|
||||
if(ismob(Obj))
|
||||
if(Obj:client)
|
||||
mysound.status = SOUND_UPDATE
|
||||
Obj << mysound
|
||||
return
|
||||
|
||||
Exited(atom/movable/Obj)
|
||||
if(ismob(Obj))
|
||||
if(Obj:client)
|
||||
mysound.status = SOUND_PAUSED | SOUND_UPDATE
|
||||
Obj << mysound
|
||||
|
||||
proc/process()
|
||||
//set background = 1
|
||||
|
||||
var/sound/S = null
|
||||
var/sound_delay = 0
|
||||
if(prob(25))
|
||||
S = sound(file=pick('sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag3.ogg'), volume=100)
|
||||
sound_delay = rand(0, 50)
|
||||
|
||||
for(var/mob/living/carbon/human/H in src)
|
||||
// if(H.s_tone > -55) //ugh...nice/novel idea but please no.
|
||||
// H.s_tone--
|
||||
// H.update_body()
|
||||
if(H.client)
|
||||
mysound.status = SOUND_UPDATE
|
||||
H << mysound
|
||||
if(S)
|
||||
spawn(sound_delay)
|
||||
H << S
|
||||
|
||||
spawn(60) .()
|
||||
|
||||
|
||||
@@ -5,15 +5,18 @@
|
||||
icon_state = "airlock_control_standby"
|
||||
anchored = 1 //this is what I get for assuming /obj/machinery has anchored set to 1 by default
|
||||
var/list/linkedturfs = list() //List contains all of the linked pool turfs to this controller, assignment happens on New()
|
||||
var/linked_area = null
|
||||
var/temperature = "normal" //The temperature of the pool, starts off on normal, which has no effects.
|
||||
var/temperaturecolor = "" //used for nanoUI fancyness
|
||||
var/srange = 5 //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/deep_water = 0 //set to 1 to drown even standing people
|
||||
|
||||
|
||||
/obj/machinery/poolcontroller/New() //This proc automatically happens on world start
|
||||
for(var/turf/simulated/floor/beach/water/W in range(srange,src)) //Search for /turf/simulated/floor/beach/water in the range of var/srange
|
||||
linkedturfs += W //Add found pool turfs to the central list.
|
||||
if(!linked_area)
|
||||
for(var/turf/simulated/floor/beach/water/W in range(srange,src)) //Search for /turf/simulated/floor/beach/water in the range of var/srange
|
||||
linkedturfs += W //Add found pool turfs to the central list.
|
||||
..() //Changed to call parent as per MarkvA's recommendation
|
||||
|
||||
/obj/machinery/poolcontroller/emag_act(user as mob) //Emag_act, this is called when it is hit with a cryptographic sequencer.
|
||||
@@ -39,63 +42,73 @@
|
||||
updatePool() //Call the mob affecting/decal cleaning proc
|
||||
|
||||
/obj/machinery/poolcontroller/proc/updatePool()
|
||||
for(var/turf/simulated/floor/beach/water/W in linkedturfs) //Check for pool-turfs linked to the controller.
|
||||
for(var/mob/M in W) //Check for mobs in the linked pool-turfs.
|
||||
//Sanity checks, don't affect robuts, AI eyes, and observers
|
||||
if(isAIEye(M))
|
||||
continue
|
||||
if(issilicon(M))
|
||||
continue
|
||||
if(isobserver(M))
|
||||
continue
|
||||
if(M.stat == DEAD)
|
||||
continue
|
||||
//End sanity checks, go on
|
||||
switch(temperature) //Apply different effects based on what the temperature is set to.
|
||||
if("scalding") //Burn the mob.
|
||||
M.bodytemperature = min(500, M.bodytemperature + 35) //heat mob at 35k(elvin) per cycle
|
||||
M << "<span class='danger'>The water is searing hot!</span>"
|
||||
|
||||
if("warm") //Gently warm the mob.
|
||||
M.bodytemperature = min(330, M.bodytemperature + 10) //Heats up mobs to just over normal, not enough to burn
|
||||
if(prob(50)) //inform the mob of warm water half the time
|
||||
M << "<span class='warning'>The water is quite warm.</span>" //Inform the mob it's warm water.
|
||||
|
||||
if("cool") //Gently cool the mob.
|
||||
M.bodytemperature = max(290, M.bodytemperature - 10) //Cools mobs to just below normal, not enough to burn
|
||||
if(prob(50)) //inform the mob of cold water half the time
|
||||
M << "<span class='warning'>The water is chilly.</span>" //Inform the mob it's chilly water.
|
||||
|
||||
if("frigid") //Freeze the mob.
|
||||
M.bodytemperature = max(80, M.bodytemperature - 35) //cool mob at -35k per cycle
|
||||
M << "<span class='danger'>The water is freezing!</span>"
|
||||
|
||||
for(var/turf/T in linkedturfs) //Check for pool-turfs linked to the controller.
|
||||
for(var/mob/M in T) //Check for mobs in the linked pool-turfs.
|
||||
if(temperature != "normal") //don't bother with this if we aren't going to be changing anything anyways
|
||||
handleTemp(M)
|
||||
|
||||
if(ishuman(M)) //Make sure they are human before typecasting.
|
||||
var/mob/living/carbon/human/drownee = M //Typecast them as human.
|
||||
if(drownee && drownee.lying) //Mob lying down
|
||||
if(drownee.internal)
|
||||
continue //Has internals, no drowning
|
||||
if((drownee.species.flags & NO_BREATHE) || (NO_BREATHE in drownee.mutations))
|
||||
continue //doesn't breathe, no drowning
|
||||
if(drownee.get_species() == "Skrell" || drownee.get_species() == "Neara")
|
||||
continue //fish things don't drown
|
||||
handleDrowning(drownee) //Only human types will drown, to keep things simple for non-human mobs that live in the water
|
||||
|
||||
if(drownee.stat) //Mob is in critical.
|
||||
drownee.adjustOxyLoss(9) //Kill em quickly.
|
||||
add_logs(drownee, src, "drowned")
|
||||
drownee.visible_message("<span class='danger'>\The [drownee] appears to be drowning!</span>","<span class='userdanger'>You're quickly drowning!</span>") //inform them that they are fucked.
|
||||
else
|
||||
drownee.adjustOxyLoss(5) //5 oxyloss per cycle.
|
||||
add_logs(drownee, src, "drowned")
|
||||
if(prob(35)) //35% chance to tell them what is going on. They should probably figure it out before then.
|
||||
drownee.visible_message("<span class='danger'>\The [drownee] flails, almost like they are drowning!</span>","<span class='userdanger'>You're lacking air!</span>") //*gasp* *gasp* *gasp* *gasp* *gasp*
|
||||
|
||||
for(var/obj/effect/decal/cleanable/decal in W)
|
||||
for(var/obj/effect/decal/cleanable/decal in T)
|
||||
animate(decal, alpha = 10, time = 20)
|
||||
spawn(25)
|
||||
qdel(decal)
|
||||
|
||||
/obj/machinery/poolcontroller/proc/handleTemp(var/mob/M)
|
||||
if(!M || isAIEye(M) || issilicon(M) || isobserver(M) || M.stat == DEAD)
|
||||
return
|
||||
|
||||
switch(temperature) //Apply different effects based on what the temperature is set to.
|
||||
if("scalding") //Burn the mob.
|
||||
M.bodytemperature = min(500, M.bodytemperature + 35) //heat mob at 35k(elvin) per cycle
|
||||
M << "<span class='danger'>The water is searing hot!</span>"
|
||||
|
||||
if("warm") //Gently warm the mob.
|
||||
M.bodytemperature = min(330, M.bodytemperature + 10) //Heats up mobs to just over normal, not enough to burn
|
||||
if(prob(50)) //inform the mob of warm water half the time
|
||||
M << "<span class='warning'>The water is quite warm.</span>" //Inform the mob it's warm water.
|
||||
|
||||
if("cool") //Gently cool the mob.
|
||||
M.bodytemperature = max(290, M.bodytemperature - 10) //Cools mobs to just below normal, not enough to burn
|
||||
if(prob(50)) //inform the mob of cold water half the time
|
||||
M << "<span class='warning'>The water is chilly.</span>" //Inform the mob it's chilly water.
|
||||
|
||||
if("frigid") //Freeze the mob.
|
||||
M.bodytemperature = max(80, M.bodytemperature - 35) //cool mob at -35k per cycle
|
||||
M << "<span class='danger'>The water is freezing!</span>"
|
||||
return
|
||||
|
||||
/obj/machinery/poolcontroller/proc/handleDrowning(var/mob/living/carbon/human/drownee)
|
||||
if(!drownee)
|
||||
return
|
||||
|
||||
if(drownee && (drownee.lying || deep_water)) //Mob lying down or water is deep (determined by controller)
|
||||
if(drownee.internal)
|
||||
return //Has internals, no drowning
|
||||
if((drownee.species.flags & NO_BREATHE) || (NO_BREATHE in drownee.mutations))
|
||||
return //doesn't breathe, no drowning
|
||||
if(drownee.get_species() == "Skrell" || drownee.get_species() == "Neara")
|
||||
return //fish things don't drown
|
||||
|
||||
if(drownee.stat == DEAD) //Dead spacemen don't drown more
|
||||
return
|
||||
if(drownee.losebreath > 20) //You've probably got bigger problems than drowning at this point, so we won't add to it until you get that under control.
|
||||
return
|
||||
|
||||
if(drownee.stat) //Mob is in critical.
|
||||
drownee.losebreath -= 3 //You're gonna die here.
|
||||
add_logs(drownee, src, "drowned")
|
||||
drownee.visible_message("<span class='danger'>\The [drownee] appears to be drowning!</span>","<span class='userdanger'>You're quickly drowning!</span>") //inform them that they are fucked.
|
||||
else
|
||||
drownee.losebreath -= 2 //For every time you drown, you miss 2 breath attempts. Hope you catch on quick!
|
||||
add_logs(drownee, src, "drowned")
|
||||
if(prob(35)) //35% chance to tell them what is going on. They should probably figure it out before then.
|
||||
drownee.visible_message("<span class='danger'>\The [drownee] flails, almost like they are drowning!</span>","<span class='userdanger'>You're lacking air!</span>") //*gasp* *gasp* *gasp* *gasp* *gasp*
|
||||
|
||||
|
||||
|
||||
/obj/machinery/poolcontroller/proc/miston() //Spawn /obj/effect/mist (from the shower) on all linked pool tiles
|
||||
if(linkedmist.len)
|
||||
return
|
||||
@@ -155,4 +168,31 @@
|
||||
temperaturecolor = ""
|
||||
mistoff()
|
||||
|
||||
return 1
|
||||
return 1
|
||||
|
||||
/obj/machinery/poolcontroller/seacontroller
|
||||
invisibility = 101
|
||||
unacidable = 1
|
||||
|
||||
name = "Sea Controller"
|
||||
desc = "A controller for the underwater portion of the sea. Players shouldn't see this."
|
||||
deep_water = 1 //deep sea is deep water
|
||||
|
||||
/obj/machinery/poolcontroller/seacontroller/New()
|
||||
linked_area = get_area(src)
|
||||
..()
|
||||
|
||||
/obj/machinery/poolcontroller/seacontroller/updatePool()
|
||||
for(var/turf/T in linked_area)
|
||||
for(var/mob/M in T)
|
||||
if(temperature != "normal") //don't bother with this if we aren't going to be changing anything anyways
|
||||
handleTemp(M)
|
||||
|
||||
if(ishuman(M)) //Make sure they are human before typecasting.
|
||||
var/mob/living/carbon/human/drownee = M //Typecast them as human.
|
||||
handleDrowning(drownee) //Only human types will drown, to keep things simple for non-human mobs that live in the water
|
||||
|
||||
for(var/obj/effect/decal/cleanable/decal in T)
|
||||
animate(decal, alpha = 10, time = 20)
|
||||
spawn(25)
|
||||
qdel(decal)
|
||||
@@ -7,6 +7,7 @@
|
||||
var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher
|
||||
var/obj/structure/ladder/down = null //the ladder below this one
|
||||
var/obj/structure/ladder/up = null //the ladder above this one
|
||||
var/use_verb = "climbs"
|
||||
|
||||
/obj/structure/ladder/New()
|
||||
spawn(8)
|
||||
@@ -14,9 +15,13 @@
|
||||
if(L.id == id)
|
||||
if(L.height == (height - 1))
|
||||
down = L
|
||||
if(isnull(L.up))
|
||||
L.up = src
|
||||
continue
|
||||
if(L.height == (height + 1))
|
||||
up = L
|
||||
if(isnull(L.down))
|
||||
L.down = src
|
||||
continue
|
||||
|
||||
if(up && down) //if both our connections are filled
|
||||
@@ -24,6 +29,9 @@
|
||||
update_icon()
|
||||
|
||||
/obj/structure/ladder/update_icon()
|
||||
if(istype(src, /obj/structure/ladder/dive_point))
|
||||
return
|
||||
|
||||
if(up && down)
|
||||
icon_state = "ladder11"
|
||||
|
||||
@@ -42,12 +50,12 @@
|
||||
if("Up")
|
||||
user.visible_message("<span class='notice'>[user] climbs up \the [src]!</span>", \
|
||||
"<span class='notice'>You climb up \the [src]!</span>")
|
||||
user.loc = get_turf(up)
|
||||
user.forceMove(get_turf(up))
|
||||
up.add_fingerprint(user)
|
||||
if("Down")
|
||||
user.visible_message("<span class='notice'>[user] climbs down \the [src]!</span>", \
|
||||
"<span class='notice'>You climb down \the [src]!</span>")
|
||||
user.loc = get_turf(down)
|
||||
user.forceMove(get_turf(down))
|
||||
down.add_fingerprint(user)
|
||||
if("Cancel")
|
||||
return
|
||||
@@ -55,16 +63,40 @@
|
||||
else if(up)
|
||||
user.visible_message("<span class='notice'>[user] climbs up \the [src]!</span>", \
|
||||
"<span class='notice'>You climb up \the [src]!</span>")
|
||||
user.loc = get_turf(up)
|
||||
user.forceMove(get_turf(up))
|
||||
up.add_fingerprint(user)
|
||||
|
||||
else if(down)
|
||||
user.visible_message("<span class='notice'>[user] climbs down \the [src]!</span>", \
|
||||
"<span class='notice'>You climb down \the [src]!</span>")
|
||||
user.loc = get_turf(down)
|
||||
user.forceMove(get_turf(down))
|
||||
down.add_fingerprint(user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/structure/ladder/attackby(obj/item/weapon/W, mob/user as mob, params)
|
||||
return attack_hand(user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/ladder/dive_point/buoy
|
||||
name = "diving point bouy"
|
||||
desc = "A buoy marking the location of an underwater dive area."
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "buoy"
|
||||
id = "dive"
|
||||
height = 2
|
||||
use_verb = "dives"
|
||||
layer = MOB_LAYER + 0.2 //0.1 higher than the water overlay, this also means people can "swim" behind/under it
|
||||
|
||||
/obj/structure/ladder/dive_point/anchor
|
||||
name = "diving point anchor"
|
||||
desc = "An anchor tethered to the buoy at the surface, to keep the dive area marked."
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "anchor"
|
||||
id = "dive"
|
||||
height = 1
|
||||
use_verb = "ascends"
|
||||
light_range = 5
|
||||
|
||||
/obj/structure/ladder/dive_point/New()
|
||||
..()
|
||||
set_light(light_range, light_power) //magical glowing anchor
|
||||
@@ -1,20 +1,66 @@
|
||||
/turf/unsimulated/beach
|
||||
name = "Beach"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
var/water_overlay_image = null
|
||||
|
||||
/turf/unsimulated/beach/New()
|
||||
..()
|
||||
if(water_overlay_image)
|
||||
overlays += image("icon"='icons/misc/beach.dmi',"icon_state"= water_overlay_image,"layer"=MOB_LAYER+0.1)
|
||||
|
||||
/turf/unsimulated/beach/sand
|
||||
name = "Sand"
|
||||
icon_state = "sand"
|
||||
icon_state = "desert"
|
||||
|
||||
/turf/unsimulated/beach/sand/New() //adds some aesthetic randomness to the beach sand
|
||||
icon_state = pick("desert", "desert0", "desert1", "desert2", "desert3", "desert4")
|
||||
..()
|
||||
|
||||
/turf/unsimulated/beach/sand/dense //for boundary "walls"
|
||||
density = 1
|
||||
|
||||
/turf/unsimulated/beach/coastline
|
||||
name = "Coastline"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
icon_state = "sandwater"
|
||||
//icon = 'icons/misc/beach2.dmi'
|
||||
//icon_state = "sandwater"
|
||||
icon_state = "beach"
|
||||
water_overlay_image = "water_coast"
|
||||
|
||||
/turf/unsimulated/beach/coastline/dense //for boundary "walls"
|
||||
density = 1
|
||||
|
||||
/turf/unsimulated/beach/water
|
||||
name = "Water"
|
||||
icon_state = "water"
|
||||
name = "Shallow Water"
|
||||
icon_state = "seashallow"
|
||||
water_overlay_image = "water_shallow"
|
||||
|
||||
/turf/unsimulated/beach/water/New()
|
||||
..()
|
||||
overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1)
|
||||
/turf/unsimulated/beach/water/drop
|
||||
name = "Water"
|
||||
icon_state = "seadrop"
|
||||
|
||||
/turf/unsimulated/beach/water/dense //for boundary "walls"
|
||||
density = 1
|
||||
|
||||
/turf/unsimulated/beach/water/deep
|
||||
name = "Deep Water"
|
||||
icon_state = "seadeep"
|
||||
water_overlay_image = "water_deep"
|
||||
|
||||
/turf/unsimulated/beach/water/deep/dense
|
||||
density = 1
|
||||
|
||||
/turf/unsimulated/beach/water/deep/wood_floor
|
||||
name = "Sunken Floor"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "wood"
|
||||
|
||||
/turf/unsimulated/beach/water/deep/sand_floor
|
||||
name = "Sea Floor"
|
||||
icon_state = "sand"
|
||||
|
||||
/turf/unsimulated/beach/water/deep/rock_wall
|
||||
name = "Reef Stone"
|
||||
icon_state = "desert7"
|
||||
density = 1
|
||||
opacity = 1
|
||||
explosion_block = 2
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/carp
|
||||
name = "sea carp"
|
||||
desc = "A large fish bearing similarities to a certain space-faring menace."
|
||||
icon_state = "carp"
|
||||
icon_living = "carp"
|
||||
icon_dead = "carp_dead"
|
||||
icon_gib = "carp_gib"
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
|
||||
meat_amount = 1
|
||||
response_help = "pets the"
|
||||
response_disarm = "gently pushes aside the"
|
||||
response_harm = "hits the"
|
||||
speed = 0
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
|
||||
retreat_distance = 6
|
||||
vision_range = 5
|
||||
|
||||
harm_intent_damage = 8
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
speak_emote = list("gnashes")
|
||||
|
||||
faction = list("carp")
|
||||
flying = 1
|
||||
Reference in New Issue
Block a user