Files
CHOMPStation2/code/game/objects/structures/low_wall.dm
CHOMPStation2StaffMirrorBot ba1065b92e [MIRROR] clean up flags (Requires #11623 Merged First) (#11637)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-09-14 20:19:32 +02:00

662 lines
19 KiB
Plaintext

// Basically see-through walls. Used for windows
// If nothing has been built on the low wall, you can climb on it
/obj/structure/low_wall
name = "low wall"
desc = "A low wall section which serves as the base of windows, amongst other things."
layer = TURF_LAYER
icon = null
icon_state = "frame"
//atom_flags = ATOM_FLAG_NO_TEMP_CHANGE | ATOM_FLAG_CLIMBABLE | ATOM_FLAG_CAN_BE_PAINTED | ATOM_FLAG_ADJACENT_EXCEPTION
anchored = TRUE
density = TRUE
throwpass = 1
layer = TABLE_LAYER
var/icon/frame_masks = 'icons/obj/wall_frame_bay.dmi'
var/health = 100
var/stripe_color
//rad_resistance_modifier = 0.5
// blend_objects defined on subtypes
noblend_objects = list(/obj/machinery/door/window, /obj/machinery/door/firedoor)
var/default_material = DEFAULT_WALL_MATERIAL
var/datum/material/material
var/grille_type
/obj/structure/low_wall/Initialize(mapload, var/materialtype)
. = ..()
icon_state = "blank"
var/turf/T = loc
if(!isturf(T) || T.density || T.opacity)
WARNING("[src] on invalid turf [T] at [x],[y],[z]")
return INITIALIZE_HINT_QDEL
if(!materialtype)
materialtype = default_material
material = get_material_by_name(materialtype)
health = material.integrity
AddElement(/datum/element/climbable)
return INITIALIZE_HINT_LATELOAD
/obj/structure/low_wall/LateInitialize()
update_connections(1)
update_icon()
/obj/structure/low_wall/Destroy()
var/turf/location = loc
. = ..()
for(var/obj/structure/low_wall/W in orange(1, location))
W.update_connections()
W.update_icon()
/obj/structure/low_wall/examine(mob/user)
. = ..()
if(health == material.integrity)
to_chat(user, span_notice("It seems to be in fine condition."))
else
var/dam = health / material.integrity
if(dam <= 0.3)
to_chat(user, span_notice("It's got a few dents and scratches."))
else if(dam <= 0.7)
to_chat(user, span_warning("A few pieces of panelling have fallen off."))
else
to_chat(user, span_danger("It's nearly falling to pieces."))
/obj/structure/low_wall/attackby(var/obj/item/W, var/mob/user, var/hit_modifier, var/click_parameters)
src.add_fingerprint(user)
// Making grilles (only works on Bay ones currently)
if(istype(W, /obj/item/stack/rods))
handle_rod_use(user, W)
return
// Making windows, different per subtype
else if(istype(W, /obj/item/stack/material/glass) || istype(W, /obj/item/stack/material/cyborg/glass))
handle_glass_use(user, W)
return
// Dismantling the half wall
if(W.has_tool_quality(TOOL_WRENCH))
for(var/obj/structure/S in loc)
if(istype(S, /obj/structure/window))
to_chat(user, span_notice("There is still a window on the low wall!"))
return
else if(istype(S, /obj/structure/grille))
to_chat(user, span_notice("There is still a grille on the low wall!"))
return
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
to_chat(user, span_notice("Now disassembling the low wall..."))
if(do_after(user, 4 SECONDS, target = src))
to_chat(user, span_notice("You dissasembled the low wall!"))
dismantle()
return
// Handle placing things
if(isrobot(user))
return
if(W.loc != user) // This should stop mounted modules ending up outside the module.
return
if(can_place_items() && user.unEquip(W, 0, src.loc) && user.client?.prefs?.read_preference(/datum/preference/toggle/precision_placement))
auto_align(W, click_parameters)
return 1
return ..()
/obj/structure/low_wall/proc/can_place_items()
for(var/obj/structure/S in loc)
if(S == src)
continue
if(S.density)
return FALSE
return TRUE
/obj/structure/low_wall/MouseDrop_T(atom/movable/AM, mob/user, src_location, over_location, src_control, over_control, params)
if(AM == user)
SEND_SIGNAL(src, COMSIG_CLIMBABLE_START_CLIMB, user)
return
var/obj/O = AM
if(!istype(O))
return
if(istype(O, /obj/structure/window))
var/obj/structure/window/W = O
if(Adjacent(W) && !W.anchored)
to_chat(user, span_notice("You hoist [W] up onto [src]."))
W.forceMove(loc)
return
if(isrobot(user))
return
if(can_place_items())
if(ismob(O.loc)) //If placing an item
if(!isitem(O) || user.get_active_hand() != O)
return ..()
if(isrobot(user))
return
user.drop_item()
if(O.loc != src.loc)
step(O, get_dir(O, src))
else if(isturf(O.loc) && isitem(O)) //If pushing an item on the tabletop
var/obj/item/I = O
if(I.anchored)
return
if((isliving(user)) && (Adjacent(user)) && !(user.incapacitated()))
if(O.w_class <= user.can_pull_size)
O.forceMove(loc)
auto_align(I, params, TRUE)
else
to_chat(user, span_warning("\The [I] is too big for you to move!"))
return
/obj/structure/low_wall/proc/handle_rod_use(mob/user, obj/item/stack/rods/R)
if(!grille_type)
to_chat(user, span_notice("This type of wall frame doesn't support grilles."))
return
for(var/obj/structure/window/WINDOW in loc)
if(WINDOW.dir == get_dir(src, user))
to_chat(user, span_notice("There is a window in the way."))
return
if(R.get_amount() < 2)
to_chat(user, span_warning("You need at least two rods to do this."))
return
to_chat(user, span_notice("Assembling grille..."))
if(!do_after(user, 1 SECONDS, target = R))
return
if(!R.use(2))
return
new grille_type(loc)
return
/obj/structure/low_wall/proc/handle_glass_use(mob/user, obj/item/stack/material/glass/G)
var/window_type = get_window_build_type(user, G)
if(!window_type)
to_chat(user, span_notice("You can't build that type of window on this type of low wall."))
return
for(var/obj/structure/window/WINDOW in loc)
if(WINDOW.dir == get_dir(src, user))
to_chat(user, span_notice("There is already a window here."))
return
if(G.get_amount() < 4)
to_chat(user, span_warning("You need at least four sheets of glass to do this."))
return
to_chat(user, span_notice("Assembling window..."))
if(!do_after(user, 4 SECONDS, target = G))
return
if(!G.use(4))
return
new window_type(loc, null, TRUE)
return
/obj/structure/low_wall/proc/get_window_build_type(mob/user, obj/item/stack/material/glass/G)
return null
/obj/structure/low_wall/CanPass(atom/movable/mover, turf/target)
if(istype(mover,/obj/item/projectile))
return TRUE
if(istype(mover) && mover.checkpass(PASSTABLE))
return TRUE
return FALSE
// Bay's version
/obj/structure/low_wall/bay/update_icon()
cut_overlays()
var/image/I
var/main_color = material.icon_colour
for(var/i = 1 to 4)
if(other_connections[i] != "0")
I = image(icon, "frame_other[other_connections[i]]", dir = 1<<(i-1))
I.color = main_color
else
I = image(icon, "frame[connections[i]]", dir = 1<<(i-1))
I.color = main_color
add_overlay(I)
if(stripe_color)
for(var/i = 1 to 4)
if(other_connections[i] != "0")
I = image(icon, "stripe_other[other_connections[i]]", dir = 1<<(i-1))
else
I = image(icon, "stripe[connections[i]]", dir = 1<<(i-1))
I.color = stripe_color
add_overlay(I)
// Eris's version
/obj/structure/low_wall/eris/update_icon()
cut_overlays()
var/image/I
var/main_color = material.icon_colour
for(var/i = 1 to 4)
I = image(icon, "frame[connections[i]]", dir = 1<<(i-1))
I.color = main_color
add_overlay(I)
if(other_connections[i] != "0")
I = image(icon, "frame_other[other_connections[i]]", dir = 1<<(i-1))
I.plane = ABOVE_OBJ_PLANE
I.layer = ABOVE_WINDOW_LAYER
I.color = main_color
add_overlay(I)
/obj/structure/low_wall/bullet_act(var/obj/item/projectile/Proj)
var/proj_damage = Proj.get_structure_damage()
var/damage = min(proj_damage, 100)
take_damage(damage)
return
/obj/structure/low_wall/hitby(atom/movable/source, var/speed)
..()
var/tforce = 0
if(ismob(source)) // All mobs have a multiplier and a size according to mob_defines.dm
var/mob/I = source
tforce = I.mob_size * (speed/THROWFORCE_SPEED_DIVISOR)
else if(isitem(source))
var/obj/item/O = source
tforce = O.throwforce * (speed/THROWFORCE_SPEED_DIVISOR)
if (tforce < 15)
return
take_damage(tforce)
/obj/structure/low_wall/take_damage(damage)
health -= damage
if(health <= 0)
dismantle()
/obj/structure/low_wall/attack_generic(var/mob/user, var/damage, var/attack_verb)
visible_message(span_danger("[user] [attack_verb] the [src]!"))
user.do_attack_animation(src)
take_damage(damage)
return ..()
/obj/structure/low_wall/proc/dismantle()
var/stacktype = material?.stack_type
if(stacktype)
new stacktype(get_turf(src), 3)
// If we were violently dismantled
for(var/obj/structure/window/W in loc)
if(W.anchored)
W.shatter()
for(var/obj/structure/grille/G in loc)
if(G.anchored)
G.health = 0
G.healthcheck()
qdel(src)
/**
* The two 'real' types
*/
/obj/structure/low_wall/bay
icon = 'icons/obj/wall_frame_bay.dmi'
grille_type = /obj/structure/grille/bay
blend_objects = list(/obj/machinery/door, /turf/simulated/wall/bay, /turf/simulated/wall/tgmc)
/obj/structure/low_wall/bay/reinforced
default_material = MAT_PLASTEEL
/obj/structure/low_wall/bay/get_window_build_type(mob/user, obj/item/stack/material/glass/G)
switch(G.material.name)
if(MAT_GLASS)
return /obj/structure/window/bay
if(MAT_RGLASS)
return /obj/structure/window/bay/reinforced
if(MAT_PGLASS)
return /obj/structure/window/bay/phoronbasic
if(MAT_RPGLASS)
return /obj/structure/window/bay/phoronreinforced
/obj/structure/low_wall/eris
icon = 'icons/obj/wall_frame_eris.dmi'
grille_type = null
blend_objects = list(/obj/machinery/door, /turf/simulated/wall/eris, /turf/simulated/wall/tgmc)
/obj/structure/low_wall/eris/reinforced
default_material = MAT_PLASTEEL
/obj/structure/low_wall/eris/get_window_build_type(mob/user, obj/item/stack/material/glass/G)
switch(G.material.name)
if(MAT_GLASS)
return /obj/structure/window/eris
if(MAT_RGLASS)
return /obj/structure/window/eris/reinforced
if(MAT_PGLASS)
return /obj/structure/window/eris/phoronbasic
if(MAT_RPGLASS)
return /obj/structure/window/eris/phoronreinforced
/**
* Bay's fancier icon grilles
*/
/obj/structure/grille/bay
icon = 'icons/obj/bay_grille.dmi'
blend_objects = list(/obj/machinery/door, /turf/simulated/wall/bay) // Objects which to blend with
noblend_objects = list(/obj/machinery/door/window)
color = "#666666"
/obj/structure/grille/bay/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
/obj/structure/grille/bay/LateInitialize()
update_connections(1)
update_icon()
/obj/structure/grille/bay/Destroy()
var/turf/location = loc
. = ..()
for(var/obj/structure/grille/G in orange(1, location))
G.update_connections()
G.update_icon()
/obj/structure/grille/bay/update_icon()
var/on_frame = locate(/obj/structure/low_wall/bay) in loc
cut_overlays()
if(destroyed)
if(on_frame)
icon_state = "broke_onframe"
else
icon_state = "broken"
else
var/image/I
icon_state = ""
if(on_frame)
for(var/i = 1 to 4)
if(other_connections[i] != "0")
I = image(icon, "grille_other_onframe[connections[i]]", dir = 1<<(i-1))
else
I = image(icon, "grille_onframe[connections[i]]", dir = 1<<(i-1))
add_overlay(I)
else
for(var/i = 1 to 4)
if(other_connections[i] != "0")
I = image(icon, "grille_other[connections[i]]", dir = 1<<(i-1))
else
I = image(icon, "grille[connections[i]]", dir = 1<<(i-1))
add_overlay(I)
/**
* The window types for both types of short walls
*/
/obj/structure/window/bay
icon = 'icons/obj/bay_window.dmi'
blend_objects = list(/obj/machinery/door, /turf/simulated/wall/bay)
noblend_objects = list(/obj/machinery/door/window, /obj/machinery/door/firedoor)
icon_state = "preview_glass"
basestate = "window"
alpha = 180
flags = NONE
fulltile = TRUE
maxhealth = 24
glasstype = /obj/item/stack/material/glass
/obj/structure/window/bay/Initialize(mapload)
. = ..()
var/obj/item/stack/material/glass/G = glasstype
var/datum/material/M = get_material_by_name(initial(G.default_type))
color = M.icon_colour
return INITIALIZE_HINT_LATELOAD
/obj/structure/window/bay/LateInitialize()
icon_state = ""
update_icon()
/obj/structure/window/bay/update_icon()
cut_overlays()
if(!anchored)
connections = list("0","0","0","0")
other_connections = list("0","0","0","0")
else
update_connections()
var/percent_damage = 0 // Used for icon state of damage layer
var/damage_alpha = 0 // Used for alpha blending of damage layer
if (maxhealth && health < maxhealth)
percent_damage = (maxhealth - health) / maxhealth // Percentage of damage received (Not health remaining)
percent_damage = round(percent_damage, 0.25) // Round to nearest multiple of 25
damage_alpha = 256 * percent_damage - 1
var/img_dir
var/image/I
for(var/i = 1 to 4)
img_dir = 1<<(i-1)
if(other_connections[i] != "0")
I = image(icon, "[basestate]_other_onframe[other_connections[i]]", dir = img_dir)
I.color = color
else
I = image(icon, "[basestate]_onframe[connections[i]]", dir = img_dir)
I.color = color
add_overlay(I)
if(damage_alpha)
var/image/D
D = image(icon, "window0_damage", dir = img_dir)
D.blend_mode = BLEND_MULTIPLY
D.alpha = damage_alpha
add_overlay(D)
/obj/structure/window/bay/reinforced
name = "reinforced window"
desc = "It looks rather strong. Might take a few good hits to shatter it."
icon_state = "preview_rglass"
basestate = "rwindow"
maxhealth = 80
reinf = 1
maximal_heat = T0C + 750
damage_per_fire_tick = 2.0
glasstype = /obj/item/stack/material/glass/reinforced
force_threshold = 6
/obj/structure/window/bay/phoronbasic
name = "phoron window"
desc = "A borosilicate alloy window. It seems to be quite strong."
icon_state = "preview_phoron"
shardtype = /obj/item/material/shard/phoron
glasstype = /obj/item/stack/material/glass/phoronglass
maximal_heat = T0C + 2000
damage_per_fire_tick = 1.0
maxhealth = 40.0
force_threshold = 5
maxhealth = 80
/obj/structure/window/bay/phoronreinforced
name = "reinforced borosilicate window"
desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong."
icon_state = "preview_rphoron"
basestate = "rwindow"
shardtype = /obj/item/material/shard/phoron
glasstype = /obj/item/stack/material/glass/phoronrglass
reinf = 1
maximal_heat = T0C + 4000
damage_per_fire_tick = 1.0 // This should last for 80 fire ticks if the window is not damaged at all. The idea is that borosilicate windows have something like ablative layer that protects them for a while.
maxhealth = 160
force_threshold = 10
/obj/structure/window/eris
icon = 'icons/obj/eris_window.dmi'
blend_objects = list(/obj/machinery/door, /turf/simulated/wall/eris)
noblend_objects = list(/obj/machinery/door/window, /obj/machinery/door/firedoor)
icon_state = "preview_glass"
basestate = "window"
fulltile = TRUE
maxhealth = 24
alpha = 150
/obj/structure/window/eris/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
/obj/structure/window/eris/LateInitialize()
icon_state = ""
update_icon()
/obj/structure/window/eris/update_icon()
cut_overlays()
if(!anchored)
connections = list("0","0","0","0")
other_connections = list("0","0","0","0")
else
update_connections()
var/img_dir
var/image/I
for(var/i = 1 to 4)
img_dir = 1<<(i-1)
if(other_connections[i] != "0")
I = image(icon, "[basestate][other_connections[i]]", dir = img_dir)
else
I = image(icon, "[basestate][connections[i]]", dir = img_dir)
add_overlay(I)
/obj/structure/window/eris/reinforced
name = "reinforced window"
desc = "It looks rather strong. Might take a few good hits to shatter it."
icon_state = "preview_rglass"
basestate = "rwindow"
maxhealth = 80
reinf = 1
maximal_heat = T0C + 750
damage_per_fire_tick = 2.0
glasstype = /obj/item/stack/material/glass/reinforced
force_threshold = 6
/obj/structure/window/eris/phoronbasic
name = "phoron window"
desc = "A borosilicate alloy window. It seems to be quite strong."
basestate = "preview_phoron"
icon_state = "pwindow"
shardtype = /obj/item/material/shard/phoron
glasstype = /obj/item/stack/material/glass/phoronglass
maximal_heat = T0C + 2000
damage_per_fire_tick = 1.0
maxhealth = 40.0
force_threshold = 5
maxhealth = 80
/obj/structure/window/eris/phoronreinforced
name = "reinforced borosilicate window"
desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong."
basestate = "preview_rphoron"
icon_state = "rpwindow"
shardtype = /obj/item/material/shard/phoron
glasstype = /obj/item/stack/material/glass/phoronrglass
reinf = 1
maximal_heat = T0C + 4000
damage_per_fire_tick = 1.0 // This should last for 80 fire ticks if the window is not damaged at all. The idea is that borosilicate windows have something like ablative layer that protects them for a while.
maxhealth = 160
force_threshold = 10
/**
* Spawner helpers for mapping these in
*/
/obj/effect/low_wall_spawner
name = "low wall spawner"
var/low_wall_type
var/window_type
var/grille_type
icon = null
/obj/effect/low_wall_spawner/Initialize(mapload)
. = ..()
if(locate(/obj/effect/low_wall_spawner) in oview(0, src))
WARNING("Duplicate low wall spawners in [x],[y],[z]!")
return INITIALIZE_HINT_QDEL
if(low_wall_type)
new low_wall_type(loc)
if(grille_type)
new grille_type(loc)
if(window_type)
new window_type(loc)
return INITIALIZE_HINT_QDEL
// Bay types
/obj/effect/low_wall_spawner/bay
icon = 'icons/obj/wall_frame_bay.dmi'
icon_state = "sp_glass"
low_wall_type = /obj/structure/low_wall/bay
window_type = /obj/structure/window/bay
/obj/effect/low_wall_spawner/bay/rglass
icon_state = "sp_rglass"
window_type = /obj/structure/window/bay/reinforced
/obj/effect/low_wall_spawner/bay/phoron
icon_state = "sp_phoron"
window_type = /obj/structure/window/bay/phoronbasic
/obj/effect/low_wall_spawner/bay/rphoron
icon_state = "sp_rphoron"
window_type = /obj/structure/window/bay/phoronreinforced
/obj/effect/low_wall_spawner/bay/reinforced
icon_state = "spr_glass_g"
low_wall_type = /obj/structure/low_wall/bay/reinforced
grille_type = /obj/structure/grille/bay
window_type = /obj/structure/window/bay
/obj/effect/low_wall_spawner/bay/reinforced/rglass
icon_state = "spr_rglass_g"
window_type = /obj/structure/window/bay/reinforced
/obj/effect/low_wall_spawner/bay/reinforced/phoron
icon_state = "spr_phoron_g"
window_type = /obj/structure/window/bay/phoronbasic
/obj/effect/low_wall_spawner/bay/reinforced/rphoron
icon_state = "spr_rphoron_g"
window_type = /obj/structure/window/bay/phoronreinforced
// Eris types
/obj/effect/low_wall_spawner/eris
icon = 'icons/obj/wall_frame_eris.dmi'
icon_state = "sp_glass"
low_wall_type = /obj/structure/low_wall/eris
window_type = /obj/structure/window/eris
/obj/effect/low_wall_spawner/eris/rglass
icon_state = "sp_rglass"
window_type = /obj/structure/window/eris/reinforced
/obj/effect/low_wall_spawner/eris/phoron
icon_state = "sp_phoron"
window_type = /obj/structure/window/eris/phoronbasic
/obj/effect/low_wall_spawner/eris/rphoron
icon_state = "sp_rphoron"
window_type = /obj/structure/window/eris/phoronreinforced
/obj/effect/low_wall_spawner/eris/reinforced
icon_state = "spr_glass"
low_wall_type = /obj/structure/low_wall/eris/reinforced
window_type = /obj/structure/window/eris
/obj/effect/low_wall_spawner/eris/reinforced/rglass
icon_state = "spr_rglass"
window_type = /obj/structure/window/eris/reinforced
/obj/effect/low_wall_spawner/eris/reinforced/phoron
icon_state = "spr_phoron"
window_type = /obj/structure/window/eris/phoronbasic
/obj/effect/low_wall_spawner/eris/reinforced/rphoron
icon_state = "spr_rphoron"
window_type = /obj/structure/window/eris/phoronreinforced