Constructing Railings

Allow players to construct railings of their very own, unfasten them from the flooring, deconstruct them including with RCDs, and all the good stuff from grilles, like electrification. Also solves the bug whereby you could climb over railings into solid tiles.
This commit is contained in:
Haha26315
2022-09-07 23:36:07 -04:00
parent e5a6425321
commit 52cce9fbce
5 changed files with 180 additions and 16 deletions
@@ -0,0 +1,392 @@
//ported from virgo
/obj/structure/railing
name = "railing"
desc = "A railing to stop people from falling"
icon = 'hyperstation/icons/obj/railings.dmi'
var/icon_modifier = "grey_"
icon_state = "grey_railing0"
flags_1 = CONDUCT_1
density = FALSE
layer = 4
anchored = TRUE
flags_1 = ON_BORDER_1
max_integrity = 250
var/heat_resistance = 800
var/health = 70
var/maxhealth = 70
var/decon_speed = 5
layer = BELOW_MOB_LAYER
resistance_flags = ACID_PROOF
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
CanAtmosPass = ATMOS_PASS_PROC
var/real_explosion_block //ignore this, just use explosion_block
var/breaksound = "shatter"
var/hitsound = 'sound/effects/Glasshit.ogg'
var/buildstacktype = /obj/item/stack/rods
var/buildstackamount = 1
rad_insulation = RAD_VERY_LIGHT_INSULATION
rad_flags = RAD_PROTECT_CONTENTS
var/check = 0
var/static/list/freepass = typecacheof(list(
/obj/singularity,
/obj/effect/projectile,
/obj/effect/portal,
/obj/effect/abstract,
/obj/effect/hotspot,
/obj/effect/landmark,
/obj/effect/temp_visual,
/obj/effect/light_emitter/tendril,
/obj/effect/collapse,
/obj/effect/particle_effect/ion_trails,
/obj/effect/dummy/phased_mob,
/obj/effect/immovablerod,
/obj/effect/crystalline_reentry
)) //Gotta make sure certain things can phase through it otherwise the railings also block them.
/obj/structure/railing/unachored
anchored = FALSE
/obj/structure/railing/ComponentInitialize()
. = ..()
AddComponent(
/datum/component/simple_rotation,
ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS,
null,
CALLBACK(src, .proc/can_be_rotated),
)
/obj/structure/railing/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && (mover.pass_flags & PASSGLASS) || is_type_in_typecache(mover, freepass))
return 1
if(get_dir(loc, target) != dir)
return 1
if(mover.throwing && !mover.floating)
if(prob(75))
visible_message("<span class='notice'>[mover] sails over the [src].</span>")
return 1 //Flies right over the railing
else
visible_message("<span class='notice'>[mover] bounces off of the [src]'s rods!</span>")
return 0 //Bounces off railing's bulk
if(ismob(mover))
var/mob/M = mover
if(M.is_flying())
visible_message("<span class='notice'>[mover] soars over the [src].</span>")
return 1
if(mover.floating)
visible_message("<span class='notice'>[mover] floats over the [src].</span>")
return 1
if(get_dir(loc, target) == dir)
return 0
/obj/structure/railing/CheckExit(atom/movable/O, turf/target)
if(istype(O) && ((O.pass_flags & PASSGLASS) || is_type_in_typecache(O, freepass)) || CanPass(O, target) == 1)
return 1
if(get_dir(O.loc, target) != dir)
return 1
if(get_dir(O.loc, target) == dir)
return 0
/obj/structure/railing/Initialize()
. = ..()
if(src.anchored)
update_icon(1)
/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)
overlays.Cut()
if (!check || !anchored)//|| !anchored
icon_state = "[icon_modifier]railing0"
else
icon_state = "[icon_modifier]railing1"
if (check & 32)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]corneroverlay")
if ((check & 16) || !(check & 32) || (check & 64))
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_l")
if (!(check & 2) || (check & 1) || (check & 4))
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_r")
if(check & 4)
switch (src.dir)
if (NORTH)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32)
if (SOUTH)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32)
if (EAST)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32)
if (WEST)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32)
/obj/structure/railing/examine(mob/user)
. = ..()
if(health < maxhealth)
switch(health / maxhealth)
if(0.0 to 0.5)
. += "<span class='warning'>It looks severely damaged!</span>"
if(0.25 to 0.5)
. += "<span class='warning'>It looks damaged!</span>"
if(0.5 to 1.0)
. += "<span class='notice'>It has a few scrapes and dents.</span>"
if(anchored)
. += "<span class='notice'>It's secured in place with <b>screws</b>. The [src]'s rods look like they could be <b>cut</b> through.</span>"
else
. += "<span class='notice'>The anchoring screws are <i>unscrewed</i>. The [src]'s rods look like they could be <b>cut</b> through.</span>"
/obj/structure/railing/take_damage(amount)
health -= amount
playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
if(health <= 0)
visible_message("<span class='warning'>\The [src] breaks down!</span>")
new /obj/item/stack/rods(get_turf(src))
qdel(src)
/obj/structure/railing/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
switch(the_rcd.mode)
if(RCD_DECONSTRUCT)
return list("mode" = RCD_DECONSTRUCT, "delay" = 10, "cost" = 5)
return FALSE
/obj/structure/railing/rcd_act(mob/user, var/obj/item/construction/rcd/the_rcd, passed_mode)
switch(passed_mode)
if(RCD_DECONSTRUCT)
to_chat(user, "<span class='notice'>You deconstruct the [src].</span>")
qdel(src)
NeighborsCheck()
return TRUE
return FALSE
/obj/structure/railing/attackby(obj/item/W, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
add_fingerprint(user)
if(istype(W, /obj/item/wirecutters))
if(!shock(user, 100))
W.play_tool_sound(src, 100)
deconstruct()
NeighborsCheck()
else if((istype(W, /obj/item/screwdriver)) && (isturf(loc) || anchored))
if(!shock(user, 90))
W.play_tool_sound(src, 100)
if(W.use_tool(src, user, decon_speed))
setAnchored(!anchored)
user.visible_message("<span class='notice'>[user] [anchored ? "fastens" : "unfastens"] [src].</span>", \
"<span class='notice'>You [anchored ? "fasten [src] to" : "unfasten [src] from"] the floor.</span>")
update_icon(1)
return
else if(istype(W, /obj/item/shard) || !shock(user, 70))
return ..()
/obj/structure/grille/attack_paw(mob/user)
return attack_hand(user)
/obj/structure/grille/hulk_damage()
return 60
/obj/structure/grille/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(user.a_intent == INTENT_HARM)
if(!shock(user, 70))
..(user, 1)
return TRUE
/obj/structure/grille/attack_hand(mob/living/user)
. = ..()
if(.)
return
if(!shock(user, 70))
user.visible_message("<span class='warning'>[user] gets shocked by [src]!</span>", null, null, COMBAT_MESSAGE_RANGE)
take_damage(rand(5,10), BRUTE, "melee", 1)
/obj/structure/grille/attack_alien(mob/living/user)
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
user.visible_message("<span class='warning'>[user] mangles [src].</span>", null, null, COMBAT_MESSAGE_RANGE)
if(!shock(user, 70))
take_damage(20, BRUTE, "melee", 1)
/obj/structure/railing/deconstruct(disassembled = TRUE)
if(!loc) //if already qdel'd somehow, we do nothing
return
if(!(flags_1&NODECONSTRUCT_1))
var/obj/R = new buildstacktype(drop_location(), buildstackamount)
transfer_fingerprints_to(R)
qdel(src)
..()
/obj/structure/railing/Bumped(atom/movable/AM)
if(!ismob(AM))
return
var/mob/M = AM
shock(M, 70)
/obj/structure/railing/attack_animal(mob/user)
. = ..()
if(!shock(user, 70) && !QDELETED(src)) //Last hit still shocks but shouldn't deal damage to the rail.
take_damage(rand(5,10), BRUTE, "melee", 1)
/obj/structure/railing/hulk_damage()
return 60
/obj/structure/railing/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(user.a_intent == INTENT_HARM)
if(!shock(user, 70))
..(user, 1)
return TRUE
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
/obj/structure/railing/proc/shock(mob/user, prb)
if(!anchored) // unanchored railings are never connected
return FALSE
if(!prob(prb))
return FALSE
if(!in_range(src, user))//To prevent TK and mech users from getting shocked
return FALSE
var/turf/T = get_turf(src)
var/obj/structure/cable/C = T.get_cable_node()
if(C)
if(electrocute_mob(user, C, src, 1, TRUE))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
return TRUE
else
return FALSE
return FALSE
/obj/structure/railing/MouseDrop_T(mob/living/M, mob/living/user)
if(!istype(user))
return
if(!isliving(user))
return
//Sanity check so players can't climb over railings into occupied spaces.
var/turf/T = get_step(src, src.dir)
if(CanPass(user, T) == 0)
return FALSE
usr.visible_message("<span class='warning'>[user] starts climbing onto \the [src]!</span>")
if(!do_after(user, 15, src))
return
if(get_turf(user) == get_turf(src))
usr.dir = get_dir(usr.loc, get_step(src, src.dir))//turn and face railing
usr.forceMove(T)
else
usr.dir = get_dir(usr.loc, loc)//turn and face railing
usr.forceMove(get_turf(src))
usr.visible_message("<span class='warning'>[user] climbed over \the [src]!</span>")
usr.do_twist(targetangle = 45, timer = 8)
/obj/structure/railing/proc/can_be_rotated(mob/user,rotation_type)
if(anchored)
to_chat(user, "<span class='warning'>[src] cannot be rotated while it is fastened to the floor!</span>")
return FALSE
var/target_dir = turn(dir, rotation_type == ROTATION_CLOCKWISE ? -90 : 90)
if(!valid_window_location(loc, target_dir))
to_chat(user, "<span class='warning'>[src] cannot be rotated in that direction!</span>")
return FALSE
return TRUE
add_fingerprint(user)
/obj/structure/railing/Initialize(mapload) //mobs will show under the south railing sprite, thanks Cyanosis for helping with the fix
. = ..()
if(!mapload)
return
if(!(dir & SOUTH))
return
layer = ABOVE_MOB_LAYER
/obj/structure/railing/handrail
name = "handrail"
desc = "A waist high handrail, perhaps you could climb over it."
icon = 'hyperstation/icons/obj/railings.dmi'
icon_modifier = "hand_"
icon_state = "hand_railing0"
max_integrity = 100
/obj/structure/railing/handrail/unachored
anchored = FALSE
/obj/structure/railing/handrail/update_icon(var/UpdateNeighbors = 1)
overlays.Cut()
if (!check || !anchored)//|| !anchored
icon_state = "[icon_modifier]railing0"
else
icon_state = "[icon_modifier]railing1"
if (check & 32)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]corneroverlay")
if ((check & 16) || !(check & 32) || (check & 64))
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_l")
if (!(check & 2) || (check & 1) || (check & 4))
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_r")
if(check & 4)
switch (src.dir)
if (NORTH)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32)
if (SOUTH)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32)
layer = ABOVE_MOB_LAYER
if (EAST)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32)
if (WEST)
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32)