diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8db23214265..26bd4c697ae 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -178,7 +178,7 @@ var/const/enterloopsanity = 100 if(!(A.last_move)) return if((istype(A, /mob/) && src.x > 2 && src.x < (world.maxx - 1) && src.y > 2 && src.y < (world.maxy-1))) var/mob/M = A - if(M.Process_Spacemove(1)) + if(M.Allow_Spacemove(1)) M.inertia_dir = 0 return spawn(5) diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 04adf11fb94..8797e040811 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -8,6 +8,12 @@ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) qdel(L) +// Called after turf replaces old one +/turf/proc/post_change() + levelupdate() + var/turf/simulated/open/T = GetAbove(src) + if(istype(T)) + T.update_icon() //Creates a new turf /turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) @@ -17,8 +23,8 @@ // This makes sure that turfs are not changed to space when one side is part of a zone if(N == /turf/space) var/turf/below = GetBelow(src) - if(istype(below) && (air_master.has_valid_zone(below) || air_master.has_valid_zone(src))) - N = /turf/simulated/open + if(istype(below) && !istype(below,/turf/space)) + N = below.density ? /turf/simulated/floor/airless : /turf/simulated/open var/obj/fire/old_fire = fire var/old_opacity = opacity @@ -27,10 +33,13 @@ var/old_lighting_overlay = lighting_overlay var/list/old_corners = corners - //world << "Replacing [src.type] with [N]" +// log_debug("Replacing [src.type] with [N]") + if(connections) connections.erase_all() + overlays.Cut() + underlays.Cut() if(istype(src,/turf/simulated)) //Yeah, we're just going to rebuild the whole thing. //Despite this being called a bunch during explosions, @@ -38,44 +47,27 @@ var/turf/simulated/S = src if(S.zone) S.zone.rebuild() - if(ispath(N, /turf/simulated/floor)) - var/turf/simulated/W = new N( locate(src.x, src.y, src.z) ) + var/turf/simulated/W = new N( locate(src.x, src.y, src.z) ) + + if(ispath(N, /turf/simulated)) if(old_fire) fire = old_fire - if (istype(W,/turf/simulated/floor)) W.RemoveLattice() + else if(old_fire) + old_fire.RemoveFire() - if(tell_universe) - universe.OnTurfChange(W) + if(tell_universe) + universe.OnTurfChange(W) - if(air_master) - air_master.mark_for_update(src) //handle the addition of the new turf. + if(air_master) + air_master.mark_for_update(src) //handle the addition of the new turf. - for(var/turf/space/S in range(W,1)) - S.update_starlight() + for(var/turf/space/S in range(W,1)) + S.update_starlight() - W.levelupdate() - . = W - - else - - var/turf/W = new N( locate(src.x, src.y, src.z) ) - - if(old_fire) - old_fire.RemoveFire() - - if(tell_universe) - universe.OnTurfChange(W) - - if(air_master) - air_master.mark_for_update(src) - - for(var/turf/space/S in range(W,1)) - S.update_starlight() - - W.levelupdate() - . = W + W.post_change() + . = W lighting_overlay = old_lighting_overlay affecting_lights = old_affecting_lights @@ -87,3 +79,26 @@ lighting_build_overlay() else lighting_clear_overlay() + +/turf/proc/transport_properties_from(turf/other) + if(!istype(other, src.type)) + return 0 + + src.set_dir(other.dir) + src.icon_state = other.icon_state + src.icon = other.icon + src.overlays = other.overlays.Copy() + src.underlays = other.underlays.Copy() + return 1 + +//I would name this copy_from() but we remove the other turf from their air zone for some reason +/turf/simulated/transport_properties_from(turf/simulated/other) + if(!..()) + return 0 + + if(other.zone) + if(!src.air) + src.make_air() + src.air.copy_from(other.zone.air) + other.zone.remove(other) + return 1 diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 07efb35d114..4ebdd5de1b1 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -846,9 +846,14 @@ if(!wearer.lastarea) wearer.lastarea = get_area(wearer.loc) - if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0)) - if(!wearer.Process_Spacemove(0)) + if(!wearer.check_solid_ground()) + var/allowmove = wearer.Allow_Spacemove(0) + if(!allowmove) return 0 + else if(allowmove == -1 && wearer.handle_spaceslipping()) //Check to see if we slipped + return 0 + else + wearer.inertia_dir = 0 //If not then we can reset inertia and move if(malfunctioning) direction = pick(cardinal) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index a3f1fa409d2..254e729c773 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -75,7 +75,7 @@ -/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0) +/mob/living/carbon/human/Allow_Spacemove(var/check_drift = 0) //Can we act? if(restrained()) return 0 @@ -89,9 +89,6 @@ for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules) thrust = module.jets break - else if(istype(back,/obj/item/weapon/storage/backpack/typec)) - inertia_dir = 0 - return 1 if(thrust) if(((!check_drift) || (check_drift && thrust.stabilization_on)) && (!lying) && (thrust.allow_thrust(0.01, src))) @@ -99,9 +96,7 @@ return 1 //If no working jetpack then use the other checks - if(..()) - return 1 - return 0 + . = ..() /mob/living/carbon/human/slip_chance(var/prob_slip = 5) diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 99ffce0eebb..2494f00f1e8 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -140,8 +140,8 @@ ..() -/mob/living/carbon/slime/Process_Spacemove() - return 2 +/mob/living/carbon/slime/Allow_Spacemove() + return 1 /mob/living/carbon/slime/Stat() ..() @@ -381,4 +381,4 @@ if(powerlevel > 10) powerlevel = 10 adjustToxLoss(-10) - nutrition = max(nutrition, get_max_nutrition()) \ No newline at end of file + nutrition = max(nutrition, get_max_nutrition()) diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 5897fc6624f..b4c1414f7d9 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -3,23 +3,12 @@ return 0 ..(prob_slip) -/mob/living/silicon/robot/Process_Spacemove(var/check_drift = 0)//Cleaned up, fixed and simplified this function - //If checkdrift is 0, we're checking to see if we can manually move, return true if jetpack is on - //if checkdrift is 1, we're checking to see if we drift. Return true if jetpack AND stabilisers are on - if(jetpack) - //var/obj/item/weapon/tank/jetpack/J = internals - - if (check_drift) - if (jetpack.stabilization_on && jetpack.allow_thrust(0.01)) - inertia_dir = 0 +/mob/living/silicon/robot/Allow_Spacemove() + if(module) + for(var/obj/item/weapon/tank/jetpack/J in module.modules) + if(J && J.allow_thrust(0.01)) return 1 - - else if(jetpack.allow_thrust(0.01)) - inertia_dir = 0 - return 1 - if(..())//The parent function checks for nearby objects to hold onto - return 1 - return 0 + . = ..() //No longer needed, but I'll leave it here incase we plan to re-use it. /mob/living/silicon/robot/movement_delay() @@ -42,4 +31,4 @@ return 0 if (cell_use_power(actuatorComponent.active_usage)) - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index 6beb094c944..e42bc13d04f 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -44,7 +44,7 @@ if(istype(L)) owner = L -/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/scarybat/Allow_Spacemove(var/check_drift = 0) return ..() //No drifting in space for space carp! //original comments do not steal /mob/living/simple_animal/hostile/scarybat/FindTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index a7ce2464778..4fb011c7e29 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -304,7 +304,7 @@ instant_aggro() -/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/bear/Allow_Spacemove(var/check_drift = 0) inertia_dir = 0 return 1 //No drifting in space for space bears! //Fixed this, it wasnt working diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index a3e2724e13c..cca64d099d8 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -39,7 +39,7 @@ faction = "carp" -/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/carp/Allow_Spacemove(var/check_drift = 0) return 1 //No drifting in space for space carp! //original comments do not steal /mob/living/simple_animal/hostile/carp/FindTarget() @@ -68,4 +68,4 @@ /mob/living/simple_animal/hostile/carp/russian/FindTarget() . = ..() if(.) - custom_emote(1,"spots a filthy capitalist!") \ No newline at end of file + custom_emote(1,"spots a filthy capitalist!") diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 44d9c5d1ac4..417be0aa131 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -32,7 +32,7 @@ faction = "faithless" -/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/faithless/Allow_Spacemove(var/check_drift = 0) return 1 /mob/living/simple_animal/hostile/faithless/FindTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm index b4b21e02bcb..054daafeabc 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm @@ -36,7 +36,7 @@ faction = "cavern" -/mob/living/simple_animal/hostile/retaliate/cavern_dweller/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/retaliate/cavern_dweller/Allow_Spacemove(var/check_drift = 0) return 1 /obj/item/projectile/beam/cavern diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm index b8e4bb63bc6..6bf45c5f234 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm @@ -58,7 +58,7 @@ ion_trail.set_up(src) ion_trail.start() -/mob/living/simple_animal/hostile/retaliate/malf_drone/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/retaliate/malf_drone/Allow_Spacemove(var/check_drift = 0) return 1 /mob/living/simple_animal/hostile/retaliate/malf_drone/ListTargets() diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 7f240e8a21e..524f89d0515 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -99,7 +99,7 @@ corpse = /obj/effect/landmark/mobcorpse/syndicatecommando speed = 0 -/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/syndicate/melee/space/Allow_Spacemove(var/check_drift = 0) return /mob/living/simple_animal/hostile/syndicate/ranged @@ -129,7 +129,7 @@ corpse = /obj/effect/landmark/mobcorpse/syndicatecommando speed = 0 -/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(var/check_drift = 0) +/mob/living/simple_animal/hostile/syndicate/ranged/space/Allow_Spacemove(var/check_drift = 0) return diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index acd83da6644..a282a861421 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -244,8 +244,14 @@ if(!mob.lastarea) mob.lastarea = get_area(mob.loc) - if((istype(mob.loc, /turf/space)) || (mob.lastarea.has_gravity == 0)) - if(!mob.Process_Spacemove(0)) return 0 + if(!mob.check_solid_ground()) + var/allowmove = mob.Allow_Spacemove(0) + if(!allowmove) + return 0 + else if(allowmove == -1 && mob.handle_spaceslipping()) //Check to see if we slipped + return 0 + else + mob.inertia_dir = 0 //If not then we can reset inertia and move if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved var/atom/O = mob.loc @@ -460,31 +466,33 @@ /mob/proc/Post_Incorpmove() return -///Process_Spacemove -///Called by /client/Move() -///For moving in space -///Return 1 for movement 0 for none -/mob/proc/Process_Spacemove(var/check_drift = 0) - +// Checks whether this mob is allowed to move in space +// Return 1 for movement, 0 for none, +// -1 to allow movement but with a chance of slipping +/mob/proc/Allow_Spacemove(var/check_drift = 0) if(!Check_Dense_Object()) //Nothing to push off of so end here - update_floating(0) return 0 - update_floating(1) - if(restrained()) //Check to see if we can do things return 0 - //Check to see if we slipped - if(prob(slip_chance(5)) && !buckled) - src << "You slipped!" - src.inertia_dir = src.last_move - step(src, src.inertia_dir) + return -1 + +//Checks if a mob has solid ground to stand on +//If there's no gravity then there's no up or down so naturally you can't stand on anything. +//For the same reason lattices in space don't count - those are things you grip, presumably. +/mob/proc/check_solid_ground() + if(istype(loc, /turf/space)) return 0 - //If not then we can reset inertia and move - inertia_dir = 0 + + if(!lastarea) + lastarea = get_area(loc) + if(!lastarea.has_gravity) + return 0 + return 1 + /mob/proc/Check_Dense_Object() //checks for anything to push off in the vicinity. also handles magboots on gravity-less floors tiles var/shoegrip = Check_Shoegrip() @@ -514,3 +522,12 @@ if(Check_Shoegrip()) return 0 return prob_slip + +//return 1 if slipped, 0 otherwise +/mob/proc/handle_spaceslipping() + if(prob(slip_chance(5)) && !buckled) + to_chat(src, "You slipped!") + src.inertia_dir = src.last_move + step(src, src.inertia_dir) + return 1 + return 0 diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm index e76c6516aa7..0ed4e5364a5 100644 --- a/code/modules/multiz/basic.dm +++ b/code/modules/multiz/basic.dm @@ -11,25 +11,43 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S qdel(src) // The storage of connections between adjacent levels means some bitwise magic is needed. -proc/HasAbove(var/z) +/proc/HasAbove(var/z) if(z >= world.maxz || z > 16 || z < 1) return 0 return z_levels & (1 << (z - 1)) -proc/HasBelow(var/z) +/proc/HasBelow(var/z) if(z > world.maxz || z > 17 || z < 2) return 0 return z_levels & (1 << (z - 2)) // Thankfully, no bitwise magic is needed here. -proc/GetAbove(var/atom/atom) +/proc/GetAbove(var/atom/atom) var/turf/turf = get_turf(atom) if(!turf) return null return HasAbove(turf.z) ? get_step(turf, UP) : null -proc/GetBelow(var/atom/atom) +/proc/GetBelow(var/atom/atom) var/turf/turf = get_turf(atom) if(!turf) return null return HasBelow(turf.z) ? get_step(turf, DOWN) : null + +/proc/GetConnectedZlevels(z) + . = list(z) + for(var/level = z, HasBelow(level), level--) + . |= level-1 + for(var/level = z, HasAbove(level), level++) + . |= level+1 + +proc/AreConnectedZLevels(var/zA, var/zB) + return zA == zB || (zB in GetConnectedZlevels(zA)) + +/proc/get_zstep(ref, dir) + if(dir == UP) + . = GetAbove(ref) + else if (dir == DOWN) + . = GetBelow(ref) + else + . = get_step(ref, dir) \ No newline at end of file diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index dd0a93fec11..98f3c17d123 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -1,51 +1,172 @@ -/obj/item/weapon/tank/jetpack/verb/moveup() +/mob/verb/up() set name = "Move Upwards" - set category = "Object" + set category = "IC" - . = 1 - if(!allow_thrust(0.01, usr)) - usr << "\The [src] is disabled." + if(zMove(UP)) + to_chat(usr, "You move upwards.") + +/mob/verb/down() + set name = "Move Down" + set category = "IC" + + if(zMove(DOWN)) + to_chat(usr, "You move down.") + +/mob/proc/zMove(direction) + if(eyeobj) + return eyeobj.zMove(direction) + if(!can_ztravel()) + to_chat(usr, "You lack means of travel in that direction.") return - var/turf/above = GetAbove(src) - if(!istype(above)) - usr << "There is nothing of interest in this direction." - return + var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) - if(!istype(above, /turf/space) && !istype(above, /turf/simulated/open)) - usr << "You bump against \the [above]." - return + if(!destination) + to_chat(usr, "There is nothing of interest in this direction.") + return 0 - for(var/atom/A in above) - if(A.density) - usr << "\The [A] blocks you." - return + var/turf/start = get_turf(src) + if(!start.CanZPass(src, direction)) + to_chat(usr, "\The [start] is in the way.") + return 0 + if(!destination.CanZPass(src, direction)) + to_chat(usr, "You bump against \the [destination].") + return 0 - usr.Move(above) - usr << "You move upwards." + var/area/area = get_area(src) + if(direction == UP && area.has_gravity) + to_chat(usr, "Gravity stops you from moving upward.") + return 0 -/obj/item/weapon/tank/jetpack/verb/movedown() - set name = "Move Downwards" - set category = "Object" + for(var/atom/A in destination) + if(!A.CanPass(src, start, 1.5, 0)) + to_chat(usr, "\The [A] blocks you.") + return 0 + Move(destination) + return 1 - . = 1 - if(!allow_thrust(0.01, usr)) - usr << "\The [src] is disabled." +/mob/eye/zMove(direction) + var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + if(destination) + forceMove(destination) + else + to_chat(usr, "There is nothing of interest in this direction.") + +/mob/eye/zMove(direction) + var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + if(destination) + setLoc(destination) + else + to_chat(usr, "There is nothing of interest in this direction.") + +/mob/proc/can_ztravel() + return 0 + +/mob/observer/can_ztravel() + return 1 + +/mob/living/carbon/human/can_ztravel() + if(incapacitated()) + return 0 + + if(Allow_Spacemove()) + return 1 + + if(Check_Shoegrip()) //scaling hull with magboots + for(var/turf/simulated/T in trange(1,src)) + if(T.density) + return 1 + +/mob/living/silicon/robot/can_ztravel() + if(incapacitated() || is_dead()) + return 0 + + if(Allow_Spacemove()) //Checks for active jetpack + return 1 + + for(var/turf/simulated/T in trange(1,src)) //Robots get "magboots" + if(T.density) + return 1 + +//FALLING STUFF + +//Holds fall checks that should not be overriden by children +/atom/movable/proc/fall() + if(!isturf(loc)) return var/turf/below = GetBelow(src) - if(!istype(below)) - usr << "There is nothing of interest in this direction." + if(!below) return - if(below.density) - usr << "You bump against \the [below]." + var/turf/T = loc + if(!T.CanZPass(src, DOWN) || !below.CanZPass(src, DOWN)) return + // No gravity in space, apparently. + var/area/area = get_area(src) + if(!area.has_gravity()) + return + + if(throwing) + return + + if(can_fall()) + handle_fall(below) + +//For children to override +/atom/movable/proc/can_fall() + if(anchored) + return FALSE + + if(locate(/obj/structure/lattice, loc)) + return FALSE + + // See if something prevents us from falling. + var/turf/below = GetBelow(src) for(var/atom/A in below) - if(A.density) - usr << "\The [A] blocks you." - return + if(!A.CanPass(src, src.loc)) + return FALSE - usr.Move(below) - usr << "You move downwards." + return TRUE + +/obj/effect/can_fall() + return FALSE + +/obj/effect/decal/cleanable/can_fall() + return TRUE + +/obj/item/pipe/can_fall() + var/turf/simulated/open/below = loc + below = below.below + + . = ..() + + if(anchored) + return FALSE + + if((locate(/obj/structure/disposalpipe/up) in below) || locate(/obj/machinery/atmospherics/pipe/zpipe/up in below)) + return FALSE + +/atom/movable/proc/handle_fall(var/turf/landing) + Move(landing) + if(locate(/obj/structure/stairs) in landing) + return 1 + + if(istype(landing, /turf/simulated/open)) + visible_message("\The [src] falls from the deck above through \the [landing]!", "You hear a whoosh of displaced air.") + else + visible_message("\The [src] falls from the deck above and slams into \the [landing]!", "You hear something slam into the deck.") + +/mob/living/carbon/human/handle_fall(var/turf/landing) + if(..()) + return + var/damage = 10 + apply_damage(rand(0, damage), BRUTE, "head") + apply_damage(rand(0, damage), BRUTE, "chest") + apply_damage(rand(0, damage), BRUTE, "l_leg") + apply_damage(rand(0, damage), BRUTE, "r_leg") + apply_damage(rand(0, damage), BRUTE, "l_arm") + apply_damage(rand(0, damage), BRUTE, "r_arm") + weakened = max(weakened,2) + updatehealth() diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 1cb5b9b4da7..155ef0a7430 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -192,7 +192,6 @@ obj/machinery/atmospherics/pipe/zpipe/up/scrubbers name = "upwards scrubbers pipe" desc = "A scrubbers pipe segment to connect upwards." connect_types = CONNECT_TYPE_SCRUBBER - layer = 2.38 icon_connect_type = "-scrubbers" color = PIPE_COLOR_RED @@ -201,7 +200,6 @@ obj/machinery/atmospherics/pipe/zpipe/up/supply name = "upwards supply pipe" desc = "A supply pipe segment to connect upwards." connect_types = CONNECT_TYPE_SUPPLY - layer = 2.39 icon_connect_type = "-supply" color = PIPE_COLOR_BLUE @@ -210,7 +208,6 @@ obj/machinery/atmospherics/pipe/zpipe/down/scrubbers name = "downwards scrubbers pipe" desc = "A scrubbers pipe segment to connect downwards." connect_types = CONNECT_TYPE_SCRUBBER - layer = 2.38 icon_connect_type = "-scrubbers" color = PIPE_COLOR_RED @@ -219,6 +216,16 @@ obj/machinery/atmospherics/pipe/zpipe/down/supply name = "downwards supply pipe" desc = "A supply pipe segment to connect downwards." connect_types = CONNECT_TYPE_SUPPLY - layer = 2.39 icon_connect_type = "-supply" color = PIPE_COLOR_BLUE + +// Colored misc. pipes +obj/machinery/atmospherics/pipe/zpipe/up/cyan + color = PIPE_COLOR_CYAN +obj/machinery/atmospherics/pipe/zpipe/down/cyan + color = PIPE_COLOR_CYAN + +obj/machinery/atmospherics/pipe/zpipe/up/red + color = PIPE_COLOR_RED +obj/machinery/atmospherics/pipe/zpipe/down/red + color = PIPE_COLOR_RED diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm index 36a606bfcf9..62edc2d7689 100644 --- a/code/modules/multiz/structures.dm +++ b/code/modules/multiz/structures.dm @@ -4,54 +4,123 @@ /obj/structure/ladder name = "ladder" - desc = "A ladder. You can climb it up and down." - icon_state = "ladderdown" + desc = "A ladder. You can climb it up and down." + icon_state = "ladder01" icon = 'icons/obj/structures.dmi' density = 0 opacity = 0 anchored = 1 - var/obj/structure/ladder/target + var/allowed_directions = DOWN + var/obj/structure/ladder/target_up + var/obj/structure/ladder/target_down - initialize() - // the upper will connect to the lower - if(icon_state == "ladderup") - return + var/const/climb_time = 2 SECONDS +/obj/structure/ladder/initialize() + // the upper will connect to the lower + if(allowed_directions & DOWN) //we only want to do the top one, as it will initialize the ones before it. for(var/obj/structure/ladder/L in GetBelow(src)) - if(L.icon_state == "ladderup") - target = L - L.target = src + if(L.allowed_directions & UP) + target_down = L + L.target_up = src return + update_icon() - Destroy() - if(target && icon_state == "ladderdown") - qdel(target) - return ..() +/obj/structure/ladder/Destroy() + if(target_down) + target_down.target_up = null + target_down = null + if(target_up) + target_up.target_down = null + target_up = null + return ..() - attackby(obj/item/C as obj, mob/user as mob) - . = ..() - attack_hand(user) +/obj/structure/ladder/attackby(obj/item/C as obj, mob/user as mob) + attack_hand(user) + return + +/obj/structure/ladder/attack_hand(var/mob/M) + if(!M.may_climb_ladders(src)) return - attack_hand(var/mob/M) - if(!target || !istype(target.loc, /turf)) - M << "\The [src] is incomplete and can't be climbed." + var/obj/structure/ladder/target_ladder = getTargetLadder(M) + if(!target_ladder) + return + if(!M.Move(get_turf(src))) + to_chat(M, "You fail to reach \the [src].") + return + + var/direction = target_ladder == target_up ? "up" : "down" + + M.visible_message("\The [M] begins climbing [direction] \the [src]!", + "You begin climbing [direction] \the [src]!", + "You hear the grunting and clanging of a metal ladder being used.") + + target_ladder.audible_message("You hear something coming [direction] \the [src]") + + if(do_after(M, climb_time, src)) + climbLadder(M, target_ladder) + +/obj/structure/ladder/attack_ghost(var/mob/M) + var/target_ladder = getTargetLadder(M) + if(target_ladder) + M.forceMove(get_turf(target_ladder)) + +/obj/structure/ladder/proc/getTargetLadder(var/mob/M) + if((!target_up && !target_down) || (target_up && !istype(target_up.loc, /turf) || (target_down && !istype(target_down.loc,/turf)))) + to_chat(M, "\The [src] is incomplete and can't be climbed.") + return + if(target_down && target_up) + var/direction = alert(M,"Do you want to go up or down?", "Ladder", "Up", "Down", "Cancel") + + if(direction == "Cancel") return - var/turf/T = target.loc - for(var/atom/A in T) - if(A.density) - M << "\A [A] is blocking \the [src]." - return + if(!M.may_climb_ladders(src)) + return - M.visible_message("\A [M] climbs [icon_state == "ladderup" ? "up" : "down"] \a [src]!", - "You climb [icon_state == "ladderup" ? "up" : "down"] \the [src]!", - "You hear the grunting and clanging of a metal ladder being used.") - M.Move(T) + switch(direction) + if("Up") + return target_up + if("Down") + return target_down + else + return target_down || target_up - CanPass(obj/mover, turf/source, height, airflow) - return airflow || !density +/mob/proc/may_climb_ladders(var/ladder) + if(!Adjacent(ladder)) + to_chat(src, "You need to be next to \the [ladder] to start climbing.") + return FALSE + if(incapacitated()) + to_chat(src, "You are physically unable to climb \the [ladder].") + return FALSE + return TRUE + +/mob/observer/ghost/may_climb_ladders(var/ladder) + return TRUE + +/obj/structure/ladder/proc/climbLadder(var/mob/M, var/target_ladder) + var/turf/T = get_turf(target_ladder) + for(var/atom/A in T) + if(!A.CanPass(M, M.loc, 1.5, 0)) + to_chat(M, "\The [A] is blocking \the [src].") + return FALSE + return M.Move(T) + +/obj/structure/ladder/CanPass(obj/mover, turf/source, height, airflow) + return airflow || !density + +/obj/structure/ladder/update_icon() + icon_state = "ladder[!!(allowed_directions & UP)][!!(allowed_directions & DOWN)]" + +/obj/structure/ladder/up + allowed_directions = UP + icon_state = "ladder10" + +/obj/structure/ladder/updown + allowed_directions = UP|DOWN + icon_state = "ladder11" /obj/structure/stairs name = "Stairs" diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index b358cd0fbbd..c34b395ed1b 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -1,88 +1,76 @@ +/turf/proc/CanZPass(atom/A, direction) + if(z == A.z) //moving FROM this turf + return direction == UP //can't go below + else + if(direction == UP) //on a turf below, trying to enter + return 0 + if(direction == DOWN) //on a turf above, trying to enter + return !density + +/turf/simulated/open/CanZPass(atom, direction) + return 1 + +/turf/space/CanZPass(atom, direction) + return 1 + /turf/simulated/open name = "open space" icon = 'icons/turf/space.dmi' - icon_state = "black" - alpha = 16 - layer = 0 + icon_state = "" + plane = PLANE_SPACE_BACKGROUND density = 0 pathweight = 100000 //Seriously, don't try and path over this one numbnuts var/turf/below - var/list/underlay_references - var/global/overlay_map = list() + +/turf/simulated/open/post_change() + ..() + update() /turf/simulated/open/initialize() ..() + update() + +/turf/simulated/open/proc/update() below = GetBelow(src) - ASSERT(HasBelow(z)) + levelupdate() + for(var/atom/movable/A in src) + A.fall() + update_icon() + +/turf/simulated/open/update_dirt() + return 0 /turf/simulated/open/Entered(var/atom/movable/mover) - // only fall down in defined areas (read: areas with artificial gravitiy) - if(!istype(below)) //make sure that there is actually something below - below = GetBelow(src) - if(!below) - return - - // No gravity in space, apparently. - var/area/area = get_area(src) - if(area.name == "Space") - return - - // Prevent pipes from falling into the void... if there is a pipe to support it. - if(mover.anchored || istype(mover, /obj/item/pipe) && \ - (locate(/obj/structure/disposalpipe/up) in below) || \ - locate(/obj/machinery/atmospherics/pipe/zpipe/up in below)) - return - - // See if something prevents us from falling. - var/soft = 0 - for(var/atom/A in below) - if(A.density) - if(!istype(A, /obj/structure/window)) - return - else - var/obj/structure/window/W = A - if(W.is_fulltile()) - return - // Dont break here, since we still need to be sure that it isnt blocked - if(istype(A, /obj/structure/stairs)) - soft = 1 - - // We've made sure we can move, now. - mover.Move(below) - - if(!soft) - if(!istype(mover, /mob)) - if(istype(below, /turf/simulated/open)) - mover.visible_message("\The [mover] falls from the deck above through \the [below]!", "You hear a whoosh of displaced air.") - else - mover.visible_message("\The [mover] falls from the deck above and slams into \the [below]!", "You hear something slam into the deck.") - else - var/mob/M = mover - if(istype(below, /turf/simulated/open)) - below.visible_message("\The [mover] falls from the deck above through \the [below]!", "You hear a soft whoosh.[M.stat ? "" : ".. and some screaming."]") - else - M.visible_message("\The [mover] falls from the deck above and slams into \the [below]!", "You land on \the [below].", "You hear a soft whoosh and a crunch") - - // Handle people getting hurt, it's funny! - if (istype(mover, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mover - var/damage = 5 - H.apply_damage(rand(0, damage), BRUTE, "head") - H.apply_damage(rand(0, damage), BRUTE, "chest") - H.apply_damage(rand(0, damage), BRUTE, "l_leg") - H.apply_damage(rand(0, damage), BRUTE, "r_leg") - H.apply_damage(rand(0, damage), BRUTE, "l_arm") - H.apply_damage(rand(0, damage), BRUTE, "r_arm") - H.weakened = max(H.weakened,2) - H.updatehealth() + ..() + mover.fall() // override to make sure nothing is hidden /turf/simulated/open/levelupdate() for(var/obj/O in src) O.hide(0) -// Straight copy from space. +/turf/simulated/open/update_icon() + if(below) + underlays = list(image(icon = below.icon, icon_state = below.icon_state)) + + var/list/noverlays = list() + if(!istype(below,/turf/space)) + noverlays += image(icon =icon, icon_state = "empty", layer = 2.45) + + var/turf/simulated/T = get_step(src,NORTH) + if(istype(T) && !istype(T,/turf/simulated/open)) + noverlays += image(icon ='icons/turf/cliff.dmi', icon_state = "metal", layer = 2.45) + + var/obj/structure/stairs/S = locate() in below + if(S && S.loc == below) + var/image/I = image(icon = S.icon, icon_state = "below", dir = S.dir, layer = 2.45) + I.pixel_x = S.pixel_x + I.pixel_y = S.pixel_y + noverlays += I + + overlays = noverlays + /turf/simulated/open/attackby(obj/item/C as obj, mob/user as mob) if (istype(C, /obj/item/stack/rods)) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) @@ -90,12 +78,12 @@ return var/obj/item/stack/rods/R = C if (R.use(1)) - user << "Constructing support lattice ..." + to_chat(user, "You lay down the support lattice.") playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - ReplaceWithLattice() + new /obj/structure/lattice(locate(src.x, src.y, src.z)) return - if (istype(C, /obj/item/stack/tile/floor)) + if (istype(C, /obj/item/stack/tile)) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) var/obj/item/stack/tile/floor/S = C @@ -107,5 +95,15 @@ ChangeTurf(/turf/simulated/floor/airless) return else - user << "The plating is going to need some support." - return \ No newline at end of file + to_chat(user, "The plating is going to need some support.") + + //To lay cable. + if(istype(C, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = C + coil.turf_place(src, user) + return + return + +//Most things use is_plating to test if there is a cover tile on top (like regular floors) +/turf/simulated/open/is_plating() + return 1 diff --git a/icons/turf/cliff.dmi b/icons/turf/cliff.dmi new file mode 100644 index 00000000000..a54e13656ea Binary files /dev/null and b/icons/turf/cliff.dmi differ