mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-21 04:48:18 +01:00
ee25c1fac5
Allows the clothing rack and retail shelf to be crafted. Additionally it fixes the duplicate rods from taking apart tables and the racks giving rods when they should give plastic.
486 lines
16 KiB
Plaintext
486 lines
16 KiB
Plaintext
/obj/structure/table
|
|
name = "table frame"
|
|
icon = 'icons/obj/structure/tables/table.dmi'
|
|
icon_state = "frame"
|
|
desc = "It's a table, for putting things on. Or standing on, if you really want to."
|
|
density = TRUE
|
|
anchored = TRUE
|
|
pass_flags_self = PASSTABLE | LETPASSTHROW
|
|
climbable = TRUE
|
|
layer = TABLE_LAYER
|
|
breakable = TRUE
|
|
build_amt = 1
|
|
|
|
//Preset shit
|
|
var/table_mat
|
|
var/table_reinf
|
|
var/no_cargo
|
|
|
|
var/flipped = 0
|
|
var/maxhealth = 10
|
|
var/health = 10
|
|
|
|
// For racks (which cannot be either of these things)
|
|
var/can_reinforce = 1
|
|
var/can_plate = 1
|
|
|
|
var/manipulating = 0
|
|
var/material/reinforced = null
|
|
var/obj/item/stack/dismantle_mat = /obj/item/stack/rods
|
|
|
|
// Gambling tables. I'd prefer reinforced with carpet/felt/cloth/whatever, but AFAIK it's either harder or impossible to get /obj/item/stack/material of those.
|
|
// Convert if/when you can easily get stacks of these.
|
|
var/carpeted = 0
|
|
|
|
var/list/connections = list("nw0", "ne0", "sw0", "se0")
|
|
|
|
/obj/structure/table/condition_hints(mob/user, distance, is_adjacent)
|
|
. += ..()
|
|
if(health < maxhealth)
|
|
switch(health / maxhealth)
|
|
if(0.0 to 0.5)
|
|
. += SPAN_WARNING("It looks severely damaged!")
|
|
if(0.25 to 0.5)
|
|
. += SPAN_WARNING("It looks damaged!")
|
|
if(0.5 to 1.0)
|
|
. += SPAN_NOTICE("It has a few scrapes and dents.")
|
|
|
|
/obj/structure/table/mechanics_hints()
|
|
. = list()
|
|
. += ..()
|
|
. += "Straight tables, so long as they're not too heavy or reinforced, can be flipped over with a verb when adjacent to them!"
|
|
|
|
/obj/structure/table/assembly_hints()
|
|
. = list()
|
|
. += ..()
|
|
// Rule racks out entirely first.
|
|
if(!can_reinforce || !can_plate)
|
|
return FALSE
|
|
|
|
if(health < maxhealth)
|
|
. += "It could be repaired with a few choice <b>welds</b>... no matter what its made of!"
|
|
|
|
// Needs to be plated before it can be carpeted
|
|
if(material && !carpeted)
|
|
. += "It could be surfaced with some <b>carpet</b>."
|
|
// Needs to be plated before it can be reinforced
|
|
if(material)
|
|
. += "It could be reinforced with a <b>stack</b> of an appropriate material."
|
|
// Needs to be plated before we can do much of anything
|
|
else
|
|
. += "It could be plated with a <b>stack</b> of an appropriate material."
|
|
|
|
/obj/structure/table/disassembly_hints()
|
|
. = list()
|
|
. += ..()
|
|
// Rule racks out entirely first. If we ever let them be customized/have health, update this.
|
|
if(!can_reinforce || !can_plate)
|
|
. += "It is held together by a couple of <b>bolts</b>."
|
|
|
|
// Has a carpet
|
|
if(carpeted)
|
|
. += "Its carpeted surface could be <b>pried</b> loose."
|
|
// Has reinforcements
|
|
if(reinforced)
|
|
. += "Its reinforcements have been securely <b>screwed<b/> into place."
|
|
// Is not reinforced or carpeted, but is plated
|
|
else if(material && !carpeted)
|
|
. += "Its plating is secured by a couple of <b>bolts</b>."
|
|
// Table naked!!!
|
|
else if(!material)
|
|
. += "It is held together by a couple of <b>bolts</b>."
|
|
|
|
/obj/structure/table/proc/update_material()
|
|
var/old_maxhealth = maxhealth
|
|
if(!material)
|
|
maxhealth = 10
|
|
else
|
|
maxhealth = material.integrity / 2
|
|
|
|
if(reinforced)
|
|
maxhealth += reinforced.integrity / 2
|
|
|
|
health += maxhealth - old_maxhealth
|
|
|
|
/obj/structure/table/proc/take_damage(amount, msg = TRUE)
|
|
// If the table is made of a brittle material, and is *not* reinforced with a non-brittle material, damage is multiplied by TABLE_BRITTLE_MATERIAL_MULTIPLIER
|
|
if(material && material.is_brittle())
|
|
if(reinforced)
|
|
if(reinforced.is_brittle())
|
|
amount *= TABLE_BRITTLE_MATERIAL_MULTIPLIER
|
|
else
|
|
amount *= TABLE_BRITTLE_MATERIAL_MULTIPLIER
|
|
health -= amount
|
|
if(health <= 0)
|
|
if(msg)
|
|
visible_message(SPAN_WARNING("\The [src] breaks down!"), intent_message = THUNK_SOUND)
|
|
return break_to_parts() // if we break and form shards, return them to the caller to do !FUN! things with
|
|
|
|
/obj/structure/table/attack_generic(mob/user, damage, attack_message, environment_smash, armor_penetration, attack_flags, damage_type)
|
|
if(!damage || !environment_smash)
|
|
return
|
|
user.do_attack_animation(src)
|
|
visible_message(SPAN_DANGER("[user] [attack_message] \the [src]!"))
|
|
take_damage(damage)
|
|
return TRUE
|
|
|
|
/obj/structure/table/ex_act(severity)
|
|
switch(severity)
|
|
if(1.0)
|
|
qdel(src)
|
|
return
|
|
if(2.0)
|
|
take_damage(rand(100,400), FALSE)
|
|
if(3.0)
|
|
take_damage(rand(50,150), FALSE)
|
|
|
|
/obj/structure/table/Initialize()
|
|
if(table_mat)
|
|
material = SSmaterials.get_material_by_name(table_mat)
|
|
if(table_reinf)
|
|
reinforced = SSmaterials.get_material_by_name(table_reinf)
|
|
if(reinforced)
|
|
breakable = FALSE
|
|
|
|
. = ..()
|
|
|
|
// One table per turf.
|
|
for(var/obj/structure/table/T in loc)
|
|
if(T != src)
|
|
// There's another table here that's not us, break to metal.
|
|
// break_to_parts calls qdel(src)
|
|
break_to_parts(full_return = 1)
|
|
return
|
|
|
|
// reset color/alpha and icon, since they're set for nice map previews
|
|
icon = 'icons/obj/structure/tables/table.dmi'
|
|
color = "#ffffff"
|
|
alpha = 255
|
|
update_connections(1)
|
|
queue_icon_update()
|
|
update_desc()
|
|
update_material()
|
|
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
|
)
|
|
|
|
AddElement(/datum/element/connect_loc, loc_connections)
|
|
|
|
/obj/structure/table/Destroy()
|
|
material = null
|
|
reinforced = null
|
|
update_connections(1) // Update tables around us to ignore us (material=null forces no connections)
|
|
for(var/obj/structure/table/T in oview(src, 1))
|
|
T.queue_icon_update()
|
|
return ..()
|
|
|
|
/obj/structure/table/proc/reinforce_table(obj/item/stack/material/S, mob/user)
|
|
if(reinforced)
|
|
to_chat(user, SPAN_WARNING("\The [src] is already reinforced!"))
|
|
return
|
|
|
|
if(!can_reinforce)
|
|
to_chat(user, SPAN_WARNING("\The [src] cannot be reinforced!"))
|
|
return
|
|
|
|
if(!material)
|
|
to_chat(user, SPAN_WARNING("Plate \the [src] before reinforcing it!"))
|
|
return
|
|
|
|
if(flipped)
|
|
to_chat(user, SPAN_WARNING("Put \the [src] back in place before reinforcing it!"))
|
|
return
|
|
|
|
reinforced = common_material_add(S, user, "reinforc")
|
|
if(reinforced)
|
|
breakable = FALSE
|
|
update_desc()
|
|
queue_icon_update()
|
|
update_material()
|
|
|
|
/obj/structure/table/proc/update_desc()
|
|
if(material)
|
|
if(material_alteration & MATERIAL_ALTERATION_NAME)
|
|
name = "[material.display_name] table"
|
|
else
|
|
name = "table frame"
|
|
|
|
if(reinforced)
|
|
name = "reinforced [name]"
|
|
desc = "[initial(desc)] This one seems to be reinforced with [reinforced.display_name]."
|
|
else
|
|
desc = initial(desc)
|
|
|
|
// Returns the material to set the table to.
|
|
/obj/structure/table/proc/common_material_add(obj/item/stack/material/S, mob/user, verb) // Verb is actually verb without 'e' or 'ing', which is added. Works for 'plate'/'plating' and 'reinforce'/'reinforcing'.
|
|
var/material/M = S.get_material()
|
|
if(!istype(M))
|
|
to_chat(user, SPAN_WARNING("You cannot [verb]e \the [src] with \the [S]."))
|
|
return null
|
|
|
|
if(manipulating) return M
|
|
manipulating = 1
|
|
to_chat(user, SPAN_NOTICE("You begin [verb]ing \the [src] with [M.display_name]."))
|
|
if(!do_after(user, 2 SECONDS, src, DO_REPAIR_CONSTRUCT) || !S.use(1))
|
|
manipulating = 0
|
|
return null
|
|
user.visible_message(SPAN_NOTICE("\The [user] [verb]es \the [src] with [M.display_name]."),
|
|
SPAN_NOTICE("You finish [verb]ing \the [src]."))
|
|
|
|
manipulating = 0
|
|
return M
|
|
|
|
// Returns the material to set the table to.
|
|
/obj/structure/table/proc/common_material_remove(mob/user, material/M, delay, what, type_holding, sound)
|
|
if(!M.stack_type)
|
|
to_chat(user, SPAN_WARNING("You are unable to remove the [what] from this table!"))
|
|
return M
|
|
|
|
if(manipulating) return M
|
|
manipulating = 1
|
|
user.visible_message(SPAN_NOTICE("\The [user] begins removing the [type_holding] holding \the [src]'s [M.display_name] [what] in place."),
|
|
SPAN_NOTICE("You begin removing the [type_holding] holding \the [src]'s [M.display_name] [what] in place."))
|
|
if(sound)
|
|
playsound(src.loc, sound, 50, 1)
|
|
if(!do_after(user, 4 SECONDS, src, DO_REPAIR_CONSTRUCT))
|
|
manipulating = 0
|
|
return M
|
|
user.visible_message(SPAN_NOTICE("\The [user] removes the [M.display_name] [what] from \the [src]."),
|
|
SPAN_NOTICE("You remove the [M.display_name] [what] from \the [src]."))
|
|
new M.stack_type(src.loc)
|
|
manipulating = 0
|
|
return null
|
|
|
|
/obj/structure/table/proc/remove_reinforced(obj/item/screwdriver/S, mob/user)
|
|
reinforced = common_material_remove(user, reinforced, 40, "reinforcements", "screws", 'sound/items/Screwdriver.ogg')
|
|
breakable = TRUE
|
|
|
|
/obj/structure/table/proc/remove_material(obj/item/wrench/W, mob/user)
|
|
material = common_material_remove(user, material, 20, "plating", "bolts", W.usesound)
|
|
|
|
/obj/structure/table/dismantle(obj/item/wrench/W, mob/user)
|
|
if(manipulating)
|
|
return
|
|
manipulating = TRUE
|
|
user.visible_message("<b>[user]</b> begins dismantling \the [src].",
|
|
SPAN_NOTICE("You begin dismantling \the [src]."))
|
|
if(!W.use_tool(src, user, 20, volume = 50))
|
|
manipulating = FALSE
|
|
return
|
|
user.visible_message("\The [user] dismantles \the [src].",
|
|
SPAN_NOTICE("You dismantle \the [src]."))
|
|
new dismantle_mat(src.loc)
|
|
qdel(src)
|
|
|
|
// Returns a list of /obj/item/material/shard objects that were created as a result of this table's breakage.
|
|
// Used for !fun! things such as embedding shards in the faces of tableslammed people.
|
|
|
|
// The repeated
|
|
// S = [x].place_shard(loc)
|
|
// if(S) shards += S
|
|
// is to avoid filling the list with nulls, as place_shard won't place shards of certain materials (holo-wood, holo-steel)
|
|
|
|
/obj/structure/table/proc/break_to_parts(full_return = 0)
|
|
var/list/shards = list()
|
|
var/obj/item/material/shard/S = null
|
|
if(reinforced)
|
|
if(reinforced.stack_type && (full_return || prob(20)))
|
|
reinforced.place_sheet(loc)
|
|
else
|
|
S = reinforced.place_shard(loc)
|
|
if(S) shards += S
|
|
if(material)
|
|
if(material.stack_type && (full_return || prob(20)))
|
|
material.place_sheet(loc)
|
|
else
|
|
S = material.place_shard(loc)
|
|
if(S) shards += S
|
|
if(carpeted && (full_return || prob(50))) // Higher chance to get the carpet back intact, since there's no non-intact option
|
|
new /obj/item/stack/tile/carpet(src.loc)
|
|
if(full_return || prob(20))
|
|
new dismantle_mat(src.loc)
|
|
qdel(src)
|
|
return shards
|
|
|
|
/obj/structure/table/update_icon()
|
|
ClearOverlays()
|
|
icon_state = "blank"
|
|
var/image/I
|
|
if(flipped != 1)
|
|
if(material) // Standard table image.
|
|
for(var/i = 1 to 4)
|
|
if(material.table_icon)
|
|
if(reinforced && ("reinf_[material.icon_base]_[connections[i]]" in icon_states(material.table_icon)))
|
|
I = image(material.table_icon, "reinf_[material.icon_base]_[connections[i]]", dir = 1<<(i-1))
|
|
else
|
|
I = image(material.table_icon, "[material.icon_base]_[connections[i]]", dir = 1<<(i-1))
|
|
else
|
|
if(reinforced && ("reinf_[material.icon_base]_[connections[i]]" in icon_states(icon)))
|
|
I = image(icon, "reinf_[material.icon_base]_[connections[i]]", dir = 1<<(i-1))
|
|
else
|
|
I = image(icon, "[material.icon_base]_[connections[i]]", dir = 1<<(i-1))
|
|
if(material.icon_colour)
|
|
I.color = material.icon_colour
|
|
AddOverlays(I)
|
|
else // Table frame
|
|
for(var/i = 1 to 4)
|
|
I = image(icon, "[connections[i]]", dir = 1<<(i-1))
|
|
AddOverlays(I)
|
|
|
|
if(reinforced) // Reinforcements.
|
|
for(var/i = 1 to 4)
|
|
if("reinf_[reinforced.name]_[connections[i]]" in icon_states('icons/obj/structure/tables/table_reinf.dmi')) // if it's got an existing purpose-made reinforced icon, and it isn't already a generic one, use it
|
|
I = image('icons/obj/structure/tables/table_reinf.dmi', "reinf_[reinforced.name]_[connections[i]]", dir = 1<<(i-1))
|
|
else
|
|
I = image('icons/obj/structure/tables/table_reinf.dmi', "[reinforced.reinf_icon]_[connections[i]]", dir = 1<<(i-1)) // else use the generic recolorable one
|
|
if(reinforced.icon_colour && ("reinf_[reinforced.name]" == "[reinforced.reinf_icon]"))
|
|
I.color = reinforced.icon_colour
|
|
AddOverlays(I)
|
|
|
|
if(carpeted)
|
|
for(var/i = 1 to 4)
|
|
I = image(icon, "carpet_[connections[i]]", dir = 1<<(i-1))
|
|
AddOverlays(I)
|
|
|
|
else // Flipped table
|
|
var/type = 0
|
|
var/tabledirs = 0
|
|
for(var/direction in list(turn(dir,90), turn(dir,-90)) )
|
|
var/obj/structure/table/T = locate(/obj/structure/table ,get_step(src,direction))
|
|
if(T && T.flipped == 1 && T.dir == src.dir && material && T.material && T.material.name == material.name)
|
|
type++
|
|
tabledirs |= direction
|
|
|
|
type = "[type]"
|
|
if(type=="1")
|
|
if(tabledirs & turn(dir,90))
|
|
type += "-"
|
|
if(tabledirs & turn(dir,-90))
|
|
type += "+"
|
|
|
|
if(material)
|
|
if(material.table_icon)
|
|
if(reinforced && ("reinf_[material.name]_flip[type]" in icon_states(material.table_icon)))
|
|
I = image(material.table_icon, "reinf_[material.name]_flip[type]")
|
|
else
|
|
I = image(material.table_icon, "[material.name]_flip[type]")
|
|
else
|
|
if(reinforced && ("reinf_[material.icon_base]_flip[type]" in icon_states(icon)))
|
|
I = image(icon, "reinf_[material.icon_base]_flip[type]")
|
|
else
|
|
I = image(icon, "[material.icon_base]_flip[type]")
|
|
if(material.icon_colour)
|
|
I.color = material.icon_colour
|
|
AddOverlays(I)
|
|
if(material.display_name)
|
|
if(material.display_name == "comfy")
|
|
name = "fancy table"
|
|
else
|
|
name = "[material.display_name] table"
|
|
else
|
|
I = image(icon, "flip[type]")
|
|
name = "table frame"
|
|
AddOverlays(I)
|
|
|
|
if(reinforced)
|
|
if("reinf_[reinforced.name]_flip[type]" in icon_states('icons/obj/structure/tables/table_reinf.dmi')) // if it's got an existing purpose-made reinforced icon, and it isn't already a generic one, use it
|
|
I = image('icons/obj/structure/tables/table_reinf.dmi', "reinf_[reinforced.name]_flip[type]")
|
|
else
|
|
I = image('icons/obj/structure/tables/table_reinf.dmi', "[reinforced.reinf_icon]_flip[type]") // else use the generic recolorable one
|
|
if(reinforced.icon_colour && ("reinf_[reinforced.name]" == "[reinforced.reinf_icon]"))
|
|
I.color = reinforced.icon_colour
|
|
AddOverlays(I)
|
|
|
|
if(carpeted)
|
|
AddOverlays("carpet_flip[type]")
|
|
|
|
// set propagate if you're updating a table that should update tables around it too, for example if it's a new table or something important has changed (like material).
|
|
/obj/structure/table/proc/update_connections(propagate=0)
|
|
if(!material)
|
|
connections = list("0", "0", "0", "0")
|
|
|
|
if(propagate)
|
|
for(var/obj/structure/table/T in oview(src, 1))
|
|
T.update_connections()
|
|
return
|
|
|
|
var/list/blocked_dirs = list()
|
|
for(var/obj/structure/window/W in get_turf(src))
|
|
if(W.is_fulltile())
|
|
connections = list("0", "0", "0", "0")
|
|
return
|
|
blocked_dirs |= W.dir
|
|
|
|
for(var/D in list(NORTH, SOUTH, EAST, WEST) - blocked_dirs)
|
|
var/turf/T = get_step(src, D)
|
|
for(var/obj/structure/window/W in T)
|
|
if(W.is_fulltile() || W.dir == REVERSE_DIR(D))
|
|
blocked_dirs |= D
|
|
break
|
|
else
|
|
if(W.dir != D) // it's off to the side
|
|
blocked_dirs |= W.dir|D // blocks the diagonal
|
|
|
|
for(var/D in list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) - blocked_dirs)
|
|
var/turf/T = get_step(src, D)
|
|
|
|
for(var/obj/structure/window/W in T)
|
|
if(W.is_fulltile() || W.dir & REVERSE_DIR(D))
|
|
blocked_dirs |= D
|
|
break
|
|
|
|
// Blocked cardinals block the adjacent diagonals too. Prevents weirdness with tables.
|
|
for(var/x in list(NORTH, SOUTH))
|
|
for(var/y in list(EAST, WEST))
|
|
if((x in blocked_dirs) || (y in blocked_dirs))
|
|
blocked_dirs |= x|y
|
|
|
|
var/list/connection_dirs = list()
|
|
|
|
for(var/obj/structure/table/T in orange(src, 1))
|
|
var/T_dir = get_dir(src, T)
|
|
if(T_dir in blocked_dirs) continue
|
|
if(material && T.material && material.name == T.material.name && flipped == T.flipped)
|
|
connection_dirs |= T_dir
|
|
if(propagate)
|
|
INVOKE_ASYNC(T, PROC_REF(update_connections))
|
|
INVOKE_ASYNC(T, TYPE_PROC_REF(/atom, queue_icon_update))
|
|
|
|
connections = dirs_to_corner_states(connection_dirs)
|
|
|
|
#define CORNER_NONE 0
|
|
#define CORNER_COUNTERCLOCKWISE 1
|
|
#define CORNER_DIAGONAL 2
|
|
#define CORNER_CLOCKWISE 4
|
|
|
|
/*
|
|
turn() is weird:
|
|
turn(icon, angle) turns icon by angle degrees clockwise
|
|
turn(matrix, angle) turns matrix by angle degrees clockwise
|
|
turn(dir, angle) turns dir by angle degrees counter-clockwise
|
|
*/
|
|
|
|
/proc/dirs_to_corner_states(list/dirs)
|
|
if(!istype(dirs)) return
|
|
|
|
var/list/ret = list(NORTHWEST, SOUTHEAST, NORTHEAST, SOUTHWEST)
|
|
|
|
for(var/i = 1 to ret.len)
|
|
var/dir = ret[i]
|
|
. = CORNER_NONE
|
|
if(dir in dirs)
|
|
. |= CORNER_DIAGONAL
|
|
if(turn(dir,45) in dirs)
|
|
. |= CORNER_COUNTERCLOCKWISE
|
|
if(turn(dir,-45) in dirs)
|
|
. |= CORNER_CLOCKWISE
|
|
ret[i] = "[.]"
|
|
|
|
return ret
|
|
|
|
#undef CORNER_NONE
|
|
#undef CORNER_COUNTERCLOCKWISE
|
|
#undef CORNER_DIAGONAL
|
|
#undef CORNER_CLOCKWISE
|