From a6ae62b13b5cdffa178c463dcebd18291795cada Mon Sep 17 00:00:00 2001 From: Leshana Date: Sun, 16 Apr 2017 21:53:56 -0400 Subject: [PATCH] Ported Eris's "railings" * Railings are an ON_BORDER object that looks like a railing; you can throw and reach across it, but it stops you from falling into holes or whatever. * Mobs can climb over them (or throw other mobs over them!) * They are construtable/deconstructable. * Smoothly auto-joining sprites to look like a railing. * Changes from Eris: Converted << to to_chat(), Desnowflaked some code, Fixed being able to climb over when windows are in the way. --- code/game/objects/structures/railing.dm | 318 +++++++++++++++++++++ code/modules/materials/material_recipes.dm | 1 + icons/obj/railing.dmi | Bin 0 -> 815 bytes vorestation.dme | 1 + 4 files changed, 320 insertions(+) create mode 100644 code/game/objects/structures/railing.dm create mode 100644 icons/obj/railing.dmi diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm new file mode 100644 index 0000000000..7f9a6a98d3 --- /dev/null +++ b/code/game/objects/structures/railing.dm @@ -0,0 +1,318 @@ +// Based on railing.dmi from https://github.com/Endless-Horizon/CEV-Eris +/obj/structure/railing + name = "railing" + desc = "A standard steel railing. Play stupid games win stupid prizes." + icon = 'icons/obj/railing.dmi' + density = 1 + throwpass = 1 + climbable = 1 + layer = 3.2 //Just above doors + anchored = 1 + flags = ON_BORDER + icon_state = "railing0" + var/broken = FALSE + var/health = 70 + var/maxhealth = 70 + var/check = 0 + +/obj/structure/railing/New(loc, constructed = 0) + ..() + // TODO - "constructed" is not passed to us. We need to find a way to do this safely. + if (constructed) // player-constructed railings + anchored = 0 + if(climbable) + verbs += /obj/structure/proc/climb_on + +/obj/structure/railing/initialize() + ..() + if(src.anchored) + update_icon(0) + +/obj/structure/railing/Destroy() + for(var/obj/structure/railing/R in oview(src, 1)) + R.update_icon() + ..() + +/obj/structure/railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(!mover) + return 1 + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + if(get_dir(loc, target) == dir) + return !density + else + return 1 + +/obj/structure/railing/examine(mob/user) + . = ..() + if(health < maxhealth) + switch(health / maxhealth) + if(0.0 to 0.5) + to_chat(user, "It looks severely damaged!") + if(0.25 to 0.5) + to_chat(user, "It looks damaged!") + if(0.5 to 1.0) + to_chat(user, "It has a few scrapes and dents.") + +/obj/structure/railing/proc/take_damage(amount) + health -= amount + if(health <= 0) + visible_message("\The [src] breaks down!") + playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) + new /obj/item/stack/rods(get_turf(usr)) + qdel(src) + +/obj/structure/railing/proc/NeighborsCheck(var/UpdateNeighbors = 1) + check = 0 + //if (!anchored) return + var/Rturn = turn(src.dir, -90) + var/Lturn = turn(src.dir, 90) + + for(var/obj/structure/railing/R in src.loc) + if ((R.dir == Lturn) && R.anchored) + check |= 32 + if (UpdateNeighbors) + R.update_icon(0) + if ((R.dir == Rturn) && R.anchored) + check |= 2 + if (UpdateNeighbors) + R.update_icon(0) + + for (var/obj/structure/railing/R in get_step(src, Lturn)) + if ((R.dir == src.dir) && R.anchored) + check |= 16 + if (UpdateNeighbors) + R.update_icon(0) + for (var/obj/structure/railing/R in get_step(src, Rturn)) + if ((R.dir == src.dir) && R.anchored) + check |= 1 + if (UpdateNeighbors) + R.update_icon(0) + + for (var/obj/structure/railing/R in get_step(src, (Lturn + src.dir))) + if ((R.dir == Rturn) && R.anchored) + check |= 64 + if (UpdateNeighbors) + R.update_icon(0) + for (var/obj/structure/railing/R in get_step(src, (Rturn + src.dir))) + if ((R.dir == Lturn) && R.anchored) + check |= 4 + if (UpdateNeighbors) + R.update_icon(0) + +/obj/structure/railing/update_icon(var/UpdateNeighgors = 1) + NeighborsCheck(UpdateNeighgors) + layer = (dir == SOUTH) ? FLY_LAYER : initial(layer) + overlays.Cut() + if (!check || !anchored)//|| !anchored + icon_state = "railing0" + else + icon_state = "railing1" + if (check & 32) + overlays += image ('icons/obj/railing.dmi', src, "corneroverlay") + if ((check & 16) || !(check & 32) || (check & 64)) + overlays += image ('icons/obj/railing.dmi', src, "frontoverlay_l") + if (!(check & 2) || (check & 1) || (check & 4)) + overlays += image ('icons/obj/railing.dmi', src, "frontoverlay_r") + if(check & 4) + switch (src.dir) + if (NORTH) + overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_x = 32) + if (SOUTH) + overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_x = -32) + if (EAST) + overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_y = -32) + if (WEST) + overlays += image ('icons/obj/railing.dmi', src, "mcorneroverlay", pixel_y = 32) + +/obj/structure/railing/verb/rotate() + set name = "Rotate Railing Counter-Clockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + set_dir(turn(dir, 90)) + update_icon() + return + +/obj/structure/railing/verb/revrotate() + set name = "Rotate Railing Clockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + set_dir(turn(dir, -90)) + update_icon() + return + +/obj/structure/railing/verb/flip() // This will help push railing to remote places, such as open space turfs + set name = "Flip Railing" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't flip it!") + return 0 + + var/obj/occupied = neighbor_turf_impassable() + if(occupied) + to_chat(usr, "You can't flip \the [src] because there's \a [occupied] in the way.") + return 0 + + src.loc = get_step(src, src.dir) + set_dir(turn(dir, 180)) + update_icon() + return + +/obj/structure/railing/CheckExit(atom/movable/O as mob|obj, target as turf) + if(istype(O) && O.checkpass(PASSTABLE)) + return 1 + if(get_dir(O.loc, target) == dir) + return 0 + return 1 + +/obj/structure/railing/attackby(obj/item/W as obj, mob/user as mob) + // Dismantle + if(istype(W, /obj/item/weapon/wrench) && !anchored) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 20, src)) + user.visible_message("\The [user] dismantles \the [src].", "You dismantle \the [src].") + new /obj/item/stack/material/steel(get_turf(usr), 2) + qdel(src) + return + + // Repair + if(health < maxhealth && istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/F = W + if(F.welding) + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + if(do_after(user, 20, src)) + user.visible_message("\The [user] repairs some damage to \the [src].", "You repair some damage to \the [src].") + health = min(health+(maxhealth/5), maxhealth) // 20% repair per application + return + + // Install + if(istype(W, /obj/item/weapon/screwdriver)) + user.visible_message(anchored ? "\The [user] begins unscrewing \the [src]." : "\The [user] begins fasten \the [src]." ) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + if(do_after(user, 10, src)) + to_chat(user, (anchored ? "You have unfastened \the [src] from the floor." : "You have fastened \the [src] to the floor.")) + anchored = !anchored + update_icon() + return + + // Handle harm intent grabbing/tabling. + if(istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) + var/obj/item/weapon/grab/G = W + if (istype(G.affecting, /mob/living)) + var/mob/living/M = G.affecting + var/obj/occupied = turf_is_crowded() + if(occupied) + to_chat(user, "There's \a [occupied] in the way.") + return + if (G.state < 2) + if(user.a_intent == I_HURT) + if (prob(15)) M.Weaken(5) + M.apply_damage(8,def_zone = "head") + take_damage(8) + visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") + playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) + else + to_chat(user, "You need a better grip to do that!") + return + else + if (get_turf(G.affecting) == get_turf(src)) + G.affecting.forceMove(get_step(src, src.dir)) + else + G.affecting.forceMove(get_turf(src)) + G.affecting.Weaken(5) + visible_message("[G.assailant] throws [G.affecting] over \the [src]!") + qdel(W) + return + + else + playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) + take_damage(W.force) + + return ..() + +/obj/structure/railing/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + qdel(src) + return + if(3.0) + qdel(src) + return + else + return + +// Duplicated from structures.dm, but its a bit different. +/obj/structure/railing/do_climb(var/mob/living/user) + if(!can_climb(user)) + return + + usr.visible_message("[user] starts climbing onto \the [src]!") + climbers |= user + + if(!do_after(user,(issmall(user) ? 20 : 34))) + climbers -= user + return + + if(!can_climb(user, post_climb_check=1)) + climbers -= user + return + + if(get_turf(user) == get_turf(src)) + usr.forceMove(get_step(src, src.dir)) + else + usr.forceMove(get_turf(src)) + + usr.visible_message("[user] climbed over \the [src]!") + if(!anchored) take_damage(maxhealth) // Fatboy + climbers -= user + +/obj/structure/railing/can_climb(var/mob/living/user, post_climb_check=0) + if(!..()) + return 0 + + // Normal can_climb() handles climbing from adjacent turf onto our turf. But railings also allow climbing + // from our turf onto an adjacent! If that is the case we need to do checks for that too... + if(get_turf(user) == get_turf(src)) + var/obj/occupied = neighbor_turf_impassable() + if(occupied) + to_chat(user, "You can't climb there, there's \a [occupied] in the way.") + return 0 + return 1 + +// TODO - This here might require some investigation +/obj/structure/proc/neighbor_turf_impassable() + var/turf/T = get_step(src, src.dir) + if(!T || !istype(T)) + return 0 + if(T.density == 1) + return T + for(var/obj/O in T.contents) + if(istype(O,/obj/structure)) + var/obj/structure/S = O + if(S.climbable) continue + if(O && O.density && !(O.flags & ON_BORDER && !(turn(O.dir, 180) & dir))) + return O diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 11f6021c75..ae72c7a9ec 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -54,6 +54,7 @@ recipes += new/datum/stack_recipe("fire extinguisher cabinet frame", /obj/item/frame/extinguisher_cabinet, 4, time = 5, one_per_turf = 0, on_floor = 1) //recipes += new/datum/stack_recipe("fire axe cabinet frame", /obj/item/frame/fireaxe_cabinet, 4, time = 5, one_per_turf = 0, on_floor = 1) recipes += new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1) + recipes += new/datum/stack_recipe("railing", /obj/structure/railing, 2, time = 50, one_per_turf = 0, on_floor = 1) recipes += new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1) recipes += new/datum/stack_recipe_list("airlock assemblies", list( \ new/datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \ diff --git a/icons/obj/railing.dmi b/icons/obj/railing.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c37c89c1597b73b9caf121e3f673905c415701df GIT binary patch literal 815 zcmV+~1JL}5P)005u_0{{R3dEt5<0000FP)t-s1qB68 zA`gH#8Ki7Y1qB6daF^l$0004WQchCV=-0C=2J zR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5 zsVFfsCo?bIP>G8(C9|j)q>qa;ttc@!6~s2gP-s9=aAl>}9%73JrZ zKo!U5kfywdpz>Uz9HXq@>gNIuJpk~RVAUZ@)4u=!0x(HLK~!jg?V16ugCGosQ7^E# z3xHl=)BE3T;v`Qh)VA=P>5!_k6=Cf#482>vYC*es)1wm5 ztG!i(d3~V`lbV)~8JCX&KN$El&&J-(y&7;@)Q^3|TXvHh7gYl;x7^;U-ty%~S%G;4 zhbsAz8E9<`E?)xl*M;l-F|@Z*cmIg5Z$o=yg+Lo$->l!?X+!6PKo?){%=RBcJQ#(A zBL8RKhY-tj`#zEX%Nce3honcXi3c+|>?~j(Pq!@&4Dn#Q?;`;l&~4v`qzy^H9!$7m z8;;xK7F2A*(aImIRnnz2h;N~KbLu7HEqWD8vr@) zNJ&7>J5mzR)&^eBhOj=!v7xUo9vWeNkP`s<`r`Rn$igiv^wb6pIFP?FV18i0PLx*U zfwE1B`P__Ksb4h=NOU#{Hdmm#4m;WQ50y%#QV|>|Z`(J)#iL6E6m1d03yhIy%OqZ4 tjDduO918>z!1GW83sq9U^OOD>_yWmMZlkP7yX*h}002ovPDHLkV1jC)ZFc|w literal 0 HcmV?d00001 diff --git a/vorestation.dme b/vorestation.dme index 21b4fe41af..11721aa4e2 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1003,6 +1003,7 @@ #include "code\game\objects\structures\morgue_vr.dm" #include "code\game\objects\structures\musician.dm" #include "code\game\objects\structures\noticeboard.dm" +#include "code\game\objects\structures\railing.dm" #include "code\game\objects\structures\safe.dm" #include "code\game\objects\structures\signs.dm" #include "code\game\objects\structures\simple_doors.dm"