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:
FalseIncarnate
2016-03-01 21:02:15 -05:00
parent 38075f4beb
commit 374c2db600
9 changed files with 654 additions and 284 deletions
+6 -61
View File
@@ -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) .()
+92 -52
View File
@@ -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)
+37 -5
View File
@@ -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
+54 -8
View File
@@ -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