diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 6093d73bc54d..1dc6cd9cf71b 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -1,48 +1,55 @@ +// Basic ladder. By default links to the z-level above/below. /obj/structure/ladder name = "ladder" desc = "A sturdy metal ladder." icon = 'icons/obj/structures.dmi' icon_state = "ladder11" - var/id = null - 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/auto_connect = FALSE + anchored = TRUE + var/obj/structure/ladder/down //the ladder below this one + var/obj/structure/ladder/up //the ladder above this one -/obj/structure/ladder/unbreakable //mostly useful for awaymissions to prevent halting progress in a mission - name = "sturdy ladder" - desc = "An extremely sturdy metal ladder." - - -/obj/structure/ladder/Initialize(mapload) - GLOB.ladders += src +/obj/structure/ladder/Initialize(mapload, obj/structure/ladder/up, obj/structure/ladder/down) ..() + if (up) + src.up = up + up.down = src + up.update_icon() + if (down) + src.down = down + down.up = src + down.update_icon() return INITIALIZE_HINT_LATELOAD -/obj/structure/ladder/Destroy() +/obj/structure/ladder/Destroy(force) + if ((resistance_flags & INDESTRUCTIBLE) && !force) + return QDEL_HINT_LETMELIVE + if(up && up.down == src) up.down = null up.update_icon() if(down && down.up == src) down.up = null down.update_icon() - GLOB.ladders -= src - . = ..() + return ..() /obj/structure/ladder/LateInitialize() - for(var/obj/structure/ladder/L in GLOB.ladders) - if(L.id == id || (auto_connect && L.auto_connect && L.x == x && L.y == y)) - if(L.height == (height - 1)) - down = L - continue - if(L.height == (height + 1)) - up = L - continue + // By default, discover ladders above and below us vertically + var/turf/T = get_turf(src) - if(up && down) //if both our connections are filled + if (!down) + for (var/obj/structure/ladder/L in locate(T.x, T.y, T.z - 1)) + down = L + L.up = src // Don't waste effort looping the other way + L.update_icon() + break + if (!up) + for (var/obj/structure/ladder/L in locate(T.x, T.y, T.z + 1)) + up = L + L.down = src // Don't waste effort looping the other way + L.update_icon() break - update_icon() + update_icon() /obj/structure/ladder/update_icon() if(up && down) @@ -57,23 +64,34 @@ else //wtf make your ladders properly assholes icon_state = "ladder00" +/obj/structure/ladder/singularity_pull() + if (!(resistance_flags & INDESTRUCTIBLE)) + visible_message("[src] is torn to pieces by the gravitational pull!") + qdel(src) + /obj/structure/ladder/proc/travel(going_up, mob/user, is_ghost, obj/structure/ladder/ladder) if(!is_ghost) - show_fluff_message(going_up,user) + show_fluff_message(going_up, user) ladder.add_fingerprint(user) + var/turf/T = get_turf(ladder) var/atom/movable/AM if(user.pulling) AM = user.pulling - user.pulling.forceMove(get_turf(ladder)) - user.forceMove(get_turf(ladder)) + AM.forceMove(T) + user.forceMove(T) if(AM) user.start_pulling(AM) +/obj/structure/ladder/proc/use(mob/user, is_ghost=FALSE) + if (!is_ghost && !in_range(src, user)) + return -/obj/structure/ladder/proc/use(mob/user,is_ghost=0) - if(up && down) - switch( alert("Go up or down the ladder?", "Ladder", "Up", "Down", "Cancel") ) + if (up && down) + var/result = alert("Go up or down [src]?", "Ladder", "Up", "Down", "Cancel") + if (!is_ghost && !in_range(src, user)) + return // nice try + switch(result) if("Up") travel(TRUE, user, is_ghost, up) if("Down") @@ -83,7 +101,7 @@ else if(up) travel(TRUE, user, is_ghost, up) else if(down) - travel(FALSE, user,is_ghost, down) + travel(FALSE, user, is_ghost, down) else to_chat(user, "[src] doesn't seem to lead anywhere!") @@ -91,44 +109,66 @@ add_fingerprint(user) /obj/structure/ladder/attack_hand(mob/user) - if(can_use(user)) - use(user) + use(user) /obj/structure/ladder/attack_paw(mob/user) - return attack_hand(user) + return use(user) /obj/structure/ladder/attackby(obj/item/W, mob/user, params) - return attack_hand(user) + return use(user) /obj/structure/ladder/attack_robot(mob/living/silicon/robot/R) if(R.Adjacent(src)) - return attack_hand(R) + return use(R) /obj/structure/ladder/attack_ghost(mob/dead/observer/user) - use(user,1) + use(user, TRUE) -/obj/structure/ladder/proc/show_fluff_message(up,mob/user) - if(up) - user.visible_message("[user] climbs up \the [src].","You climb up \the [src].") +/obj/structure/ladder/proc/show_fluff_message(going_up, mob/user) + if(going_up) + user.visible_message("[user] climbs up [src].","You climb up [src].") else - user.visible_message("[user] climbs down \the [src].","You climb down \the [src].") - -/obj/structure/ladder/proc/can_use(mob/user) - return 1 - -/obj/structure/ladder/unbreakable/Destroy(force) - if(force) - . = ..() - else - return QDEL_HINT_LETMELIVE - -/obj/structure/ladder/unbreakable/singularity_pull() - return - -/obj/structure/ladder/auto_connect //They will connect to ladders with the same X and Y without needing to share an ID - auto_connect = TRUE + user.visible_message("[user] climbs down [src].","You climb down [src].") -/obj/structure/ladder/singularity_pull() - visible_message("[src] is torn to pieces by the gravitational pull!") - qdel(src) +// Indestructible away mission ladders which link based on a mapped ID and height value rather than X/Y/Z. +/obj/structure/ladder/unbreakable + name = "sturdy ladder" + desc = "An extremely sturdy metal ladder." + resistance_flags = INDESTRUCTIBLE + var/id + var/height = 0 // higher numbers are considered physically higher + +/obj/structure/ladder/unbreakable/Initialize() + GLOB.ladders += src + return ..() + +/obj/structure/ladder/unbreakable/Destroy() + . = ..() + if (. != QDEL_HINT_LETMELIVE) + GLOB.ladders -= src + +/obj/structure/ladder/unbreakable/LateInitialize() + // Override the parent to find ladders based on being height-linked + if (!id || (up && down)) + update_icon() + return + + for (var/O in GLOB.ladders) + var/obj/structure/ladder/unbreakable/L = O + if (L.id != id) + continue // not one of our pals + if (!down && L.height == height - 1) + down = L + L.up = src + L.update_icon() + if (up) + break // break if both our connections are filled + else if (!up && L.height == height + 1) + up = L + L.down = src + L.update_icon() + if (down) + break // break if both our connections are filled + + update_icon() diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index 16050059b168..7bc32a6f35b9 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -47,7 +47,7 @@ /obj/item/paper/fluff/awaymissions/academy/grade/aplus name = "Summoning Midterm Exam" info = "Grade: A+ Educator's Notes: Excellent form." - + /obj/item/paper/fluff/awaymissions/academy/grade/bminus name = "Summoning Midterm Exam" info = "Grade: B- Educator's Notes: Keep applying yourself, you're showing improvement." @@ -55,7 +55,7 @@ /obj/item/paper/fluff/awaymissions/academy/grade/dminus name = "Summoning Midterm Exam" info = "Grade: D- Educator's Notes: SEE ME AFTER CLASS." - + /obj/item/paper/fluff/awaymissions/academy/grade/failure name = "Pyromancy Evaluation" info = "Current Grade: F. Educator's Notes: No improvement shown despite multiple private lessons. Suggest additional tutilage." @@ -335,7 +335,7 @@ target_mob.Move(T) /obj/structure/ladder/unbreakable/rune - name = "Teleportation Rune" + name = "\improper Teleportation Rune" desc = "Could lead anywhere." icon = 'icons/obj/rune.dmi' icon_state = "1" @@ -347,7 +347,6 @@ /obj/structure/ladder/unbreakable/rune/show_fluff_message(up,mob/user) user.visible_message("[user] activates \the [src].","You activate \the [src].") -/obj/structure/ladder/can_use(mob/user) - if(user.mind in SSticker.mode.wizards) - return 0 - return 1 +/obj/structure/ladder/unbreakable/rune/use(mob/user, is_ghost=FALSE) + if(is_ghost || !(user.mind in SSticker.mode.wizards)) + ..() diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 9b81477311c9..c1309e50a2ca 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -578,17 +578,18 @@ var/ladder_x = T.x var/ladder_y = T.y to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.") + var/last_ladder = null for(var/i in 1 to world.maxz) - if(i == ZLEVEL_CENTCOM || i == ZLEVEL_TRANSIT) + if(i == ZLEVEL_CENTCOM || i == ZLEVEL_TRANSIT || i == ZLEVEL_CITYOFCOGS) continue var/turf/T2 = locate(ladder_x, ladder_y, i) - new /obj/structure/ladder/unbreakable/jacob(T2) + last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder) qdel(src) +// Inherit from unbreakable but don't set ID, to suppress the default Z linkage /obj/structure/ladder/unbreakable/jacob name = "jacob's ladder" desc = "An indestructible celestial ladder that violates the laws of physics." - auto_connect = TRUE ///Bosses