Files
Aurora.3/code/modules/tables/tables.dm
skull132 e9b688e1f6 Merge branch 'development-2' into development
Christ on a stick. SO MANY ERRORS. REEE.

# Conflicts:
#	baystation12.dme
#	code/_helpers/lists.dm
#	code/_helpers/logging.dm
#	code/_helpers/text.dm
#	code/_onclick/click.dm
#	code/controllers/configuration.dm
#	code/controllers/master_controller.dm
#	code/datums/supplypacks.dm
#	code/game/antagonist/antagonist.dm
#	code/game/antagonist/antagonist_print.dm
#	code/game/antagonist/outsider/commando.dm
#	code/game/antagonist/outsider/ninja.dm
#	code/game/area/areas.dm
#	code/game/gamemodes/cult/cult_items.dm
#	code/game/gamemodes/game_mode.dm
#	code/game/jobs/access.dm
#	code/game/machinery/atmoalter/canister.dm
#	code/game/machinery/autolathe.dm
#	code/game/machinery/doors/airlock.dm
#	code/game/machinery/recharger.dm
#	code/game/machinery/suit_storage_unit.dm
#	code/game/mecha/mech_fabricator.dm
#	code/game/mecha/mecha.dm
#	code/game/objects/effects/spiders.dm
#	code/game/objects/items.dm
#	code/game/objects/items/devices/PDA/PDA.dm
#	code/game/objects/items/devices/flash.dm
#	code/game/objects/items/devices/lightreplacer.dm
#	code/game/objects/items/devices/paicard.dm
#	code/game/objects/items/devices/scanners.dm
#	code/game/objects/items/devices/suit_cooling.dm
#	code/game/objects/items/devices/uplink.dm
#	code/game/objects/items/robot/robot_upgrades.dm
#	code/game/objects/items/toys.dm
#	code/game/objects/items/weapons/cards_ids.dm
#	code/game/objects/items/weapons/handcuffs.dm
#	code/game/objects/items/weapons/manuals.dm
#	code/game/objects/items/weapons/material/kitchen.dm
#	code/game/objects/items/weapons/material/misc.dm
#	code/game/objects/items/weapons/material/swords.dm
#	code/game/objects/items/weapons/melee/energy.dm
#	code/game/objects/items/weapons/melee/misc.dm
#	code/game/objects/items/weapons/scrolls.dm
#	code/game/objects/items/weapons/storage/belt.dm
#	code/game/objects/items/weapons/stunbaton.dm
#	code/game/objects/items/weapons/tools.dm
#	code/game/objects/objs.dm
#	code/game/objects/structures/crates_lockers/closets.dm
#	code/game/objects/structures/crates_lockers/closets/secure/security.dm
#	code/game/objects/structures/janicart.dm
#	code/game/sound.dm
#	code/game/turfs/simulated.dm
#	code/game/verbs/ooc.dm
#	code/global.dm
#	code/modules/admin/verbs/debug.dm
#	code/modules/admin/verbs/modifyvariables.dm
#	code/modules/client/client procs.dm
#	code/modules/client/preferences.dm
#	code/modules/clothing/clothing.dm
#	code/modules/clothing/head/hardhat.dm
#	code/modules/clothing/head/helmet.dm
#	code/modules/clothing/head/jobs.dm
#	code/modules/clothing/head/misc_special.dm
#	code/modules/clothing/shoes/jobs.dm
#	code/modules/clothing/spacesuits/alien.dm
#	code/modules/clothing/spacesuits/captain.dm
#	code/modules/clothing/spacesuits/miscellaneous.dm
#	code/modules/clothing/spacesuits/rig/rig_pieces.dm
#	code/modules/clothing/spacesuits/rig/suits/alien.dm
#	code/modules/clothing/spacesuits/spacesuits.dm
#	code/modules/clothing/spacesuits/void/merc.dm
#	code/modules/clothing/spacesuits/void/void.dm
#	code/modules/clothing/suits/armor.dm
#	code/modules/clothing/suits/jobs.dm
#	code/modules/clothing/suits/storage.dm
#	code/modules/clothing/suits/utility.dm
#	code/modules/clothing/suits/wiz_robe.dm
#	code/modules/clothing/under/jobs/security.dm
#	code/modules/economy/Events.dm
#	code/modules/economy/Events_Mundane.dm
#	code/modules/economy/economy_misc.dm
#	code/modules/events/blob.dm
#	code/modules/events/event.dm
#	code/modules/events/event_container.dm
#	code/modules/events/event_manager.dm
#	code/modules/events/money_lotto.dm
#	code/modules/events/prison_break.dm
#	code/modules/events/spacevine.dm
#	code/modules/hydroponics/trays/tray.dm
#	code/modules/mob/dead/observer/observer.dm
#	code/modules/mob/emote.dm
#	code/modules/mob/holder.dm
#	code/modules/mob/language/station.dm
#	code/modules/mob/living/bot/cleanbot.dm
#	code/modules/mob/living/carbon/alien/diona/diona.dm
#	code/modules/mob/living/carbon/alien/diona/diona_attacks.dm
#	code/modules/mob/living/carbon/give.dm
#	code/modules/mob/living/carbon/human/emote.dm
#	code/modules/mob/living/carbon/human/human.dm
#	code/modules/mob/living/carbon/human/human_defense.dm
#	code/modules/mob/living/carbon/human/inventory.dm
#	code/modules/mob/living/carbon/human/life.dm
#	code/modules/mob/living/carbon/human/species/outsider/vox.dm
#	code/modules/mob/living/carbon/human/species/station/golem.dm
#	code/modules/mob/living/carbon/human/species/station/station.dm
#	code/modules/mob/living/carbon/human/update_icons.dm
#	code/modules/mob/living/carbon/metroid/metroid.dm
#	code/modules/mob/living/living.dm
#	code/modules/mob/living/living_defense.dm
#	code/modules/mob/living/living_defines.dm
#	code/modules/mob/living/silicon/ai/ai.dm
#	code/modules/mob/living/silicon/pai/admin.dm
#	code/modules/mob/living/silicon/pai/pai.dm
#	code/modules/mob/living/silicon/robot/drone/drone.dm
#	code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
#	code/modules/mob/living/silicon/robot/emote.dm
#	code/modules/mob/living/silicon/robot/robot_items.dm
#	code/modules/mob/living/silicon/robot/robot_modules.dm
#	code/modules/mob/living/silicon/silicon.dm
#	code/modules/mob/living/simple_animal/bees.dm
#	code/modules/mob/living/simple_animal/friendly/cat.dm
#	code/modules/mob/living/simple_animal/friendly/corgi.dm
#	code/modules/mob/living/simple_animal/friendly/farm_animals.dm
#	code/modules/mob/living/simple_animal/friendly/mouse.dm
#	code/modules/mob/living/simple_animal/friendly/spiderbot.dm
#	code/modules/mob/living/simple_animal/hostile/hostile.dm
#	code/modules/mob/living/simple_animal/simple_animal.dm
#	code/modules/mob/logout.dm
#	code/modules/mob/mob.dm
#	code/modules/mob/mob_grab_specials.dm
#	code/modules/mob/mob_helpers.dm
#	code/modules/mob/new_player/sprite_accessories.dm
#	code/modules/organs/organ.dm
#	code/modules/organs/organ_alien.dm
#	code/modules/organs/organ_external.dm
#	code/modules/paperwork/faxmachine.dm
#	code/modules/projectiles/ammunition/boxes.dm
#	code/modules/projectiles/ammunition/bullets.dm
#	code/modules/projectiles/guns/energy/nuclear.dm
#	code/modules/projectiles/guns/energy/rifle.dm
#	code/modules/projectiles/guns/energy/special.dm
#	code/modules/projectiles/guns/projectile.dm
#	code/modules/projectiles/guns/projectile/automatic.dm
#	code/modules/projectiles/guns/projectile/pistol.dm
#	code/modules/projectiles/guns/projectile/revolver.dm
#	code/modules/projectiles/guns/projectile/shotgun.dm
#	code/modules/projectiles/projectile/bullets.dm
#	code/modules/projectiles/projectile/special.dm
#	code/modules/reagents/reagent_containers.dm
#	code/modules/reagents/reagent_containers/food/drinks.dm
#	code/modules/research/designs.dm
#	code/modules/research/destructive_analyzer.dm
#	code/modules/research/rdconsole.dm
#	code/modules/spells/artifacts.dm
#	code/modules/spells/spellbook.dm
#	code/modules/tables/tables.dm
#	code/world.dm
#	config/example/config.txt
#	icons/mob/items_lefthand.dmi
#	icons/mob/items_righthand.dmi
#	icons/obj/lighting.dmi
2016-10-31 00:01:52 +02:00

462 lines
15 KiB
Plaintext

/obj/structure/table
name = "table frame"
icon = 'icons/obj/tables.dmi'
icon_state = "frame"
desc = "It's a table, for putting things on. Or standing on, if you really want to."
density = 1
anchored = 1
climbable = 1
layer = 2.8
throwpass = 1
var/flipped = 0
var/maxhealth = 10
var/health = 10
// For racks.
var/can_reinforce = 1
var/can_plate = 1
var/manipulating = 0
var/material/material = null
var/material/reinforced = null
// 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/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)
// 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)
visible_message("<span class='warning'>\The [src] breaks down!</span>")
return break_to_parts() // if we break and form shards, return them to the caller to do !FUN! things with
/obj/structure/table/ex_act(severity)
switch(severity)
if(1.0)
qdel(src)
return
if(2.0)
take_damage(rand(100,400))
if(3.0)
take_damage(rand(50,150))
/obj/structure/table/initialize()
..()
// 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, since they're set for nice map previews
color = "#ffffff"
alpha = 255
update_connections(1)
update_icon()
update_desc()
update_material()
/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.update_icon()
..()
/obj/structure/table/examine(mob/user)
. = ..()
if(health < maxhealth)
switch(health / maxhealth)
if(0.0 to 0.5)
user << "<span class='warning'>It looks severely damaged!</span>"
if(0.25 to 0.5)
user << "<span class='warning'>It looks damaged!</span>"
if(0.5 to 1.0)
user << "<span class='notice'>It has a few scrapes and dents.</span>"
/obj/structure/table/attackby(obj/item/weapon/W, mob/user)
if(reinforced && istype(W, /obj/item/weapon/screwdriver))
remove_reinforced(W, user)
if(!reinforced)
update_desc()
update_icon()
update_material()
return 1
if(carpeted && istype(W, /obj/item/weapon/crowbar))
user.visible_message("<span class='notice'>\The [user] removes the carpet from \the [src].</span>",
"<span class='notice'>You remove the carpet from \the [src].</span>")
new /obj/item/stack/tile/carpet(loc)
carpeted = 0
update_icon()
return 1
if(!carpeted && material && istype(W, /obj/item/stack/tile/carpet))
var/obj/item/stack/tile/carpet/C = W
if(C.use(1))
user.visible_message("<span class='notice'>\The [user] adds \the [C] to \the [src].</span>",
"<span class='notice'>You add \the [C] to \the [src].</span>")
carpeted = 1
update_icon()
return 1
else
user << "<span class='warning'>You don't have enough carpet!</span>"
if(!reinforced && !carpeted && material && istype(W, /obj/item/weapon/wrench))
remove_material(W, user)
if(!material)
update_connections(1)
update_icon()
for(var/obj/structure/table/T in oview(src, 1))
T.update_icon()
update_desc()
update_material()
return 1
if(!carpeted && !reinforced && !material && istype(W, /obj/item/weapon/wrench))
dismantle(W, user)
return 1
if(health < maxhealth && istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/F = W
if(F.welding)
user << "<span class='notice'>You begin reparing damage to \the [src].</span>"
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
if(!do_after(user, 20) || !F.remove_fuel(1, user))
return
user.visible_message("<span class='notice'>\The [user] repairs some damage to \the [src].</span>",
"<span class='notice'>You repair some damage to \the [src].</span>")
health = max(health+(maxhealth/5), maxhealth) // 20% repair per application
return 1
if(!material && can_plate && istype(W, /obj/item/stack/material))
material = common_material_add(W, user, "plat")
if(material)
update_connections(1)
update_icon()
update_desc()
update_material()
return 1
return ..()
/obj/structure/table/MouseDrop_T(obj/item/stack/material/what)
if(can_reinforce && isliving(usr) && (!usr.stat) && istype(what) && usr.get_active_hand() == what && Adjacent(usr))
reinforce_table(what, usr)
else
return ..()
/obj/structure/table/proc/reinforce_table(obj/item/stack/material/S, mob/user)
if(reinforced)
user << "<span class='warning'>\The [src] is already reinforced!</span>"
return
if(!can_reinforce)
user << "<span class='warning'>\The [src] cannot be reinforced!</span>"
return
if(!material)
user << "<span class='warning'>Plate \the [src] before reinforcing it!</span>"
return
if(flipped)
user << "<span class='warning'>Put \the [src] back in place before reinforcing it!</span>"
return
reinforced = common_material_add(S, user, "reinforc")
if(reinforced)
update_desc()
update_icon()
update_material()
/obj/structure/table/proc/update_desc()
if(material)
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))
user << "<span class='warning'>You cannot [verb]e \the [src] with \the [S].</span>"
return null
if(manipulating) return M
manipulating = 1
user << "<span class='notice'>You begin [verb]ing \the [src] with [M.display_name].</span>"
if(!do_after(user, 20) || !S.use(1))
manipulating = 0
return null
user.visible_message("<span class='notice'>\The [user] [verb]es \the [src] with [M.display_name].</span>", "<span class='notice'>You finish [verb]ing \the [src].</span>")
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)
user << "<span class='warning'>You are unable to remove the [what] from this table!</span>"
return M
if(manipulating) return M
manipulating = 1
user.visible_message("<span class='notice'>\The [user] begins removing the [type_holding] holding \the [src]'s [M.display_name] [what] in place.</span>",
"<span class='notice'>You begin removing the [type_holding] holding \the [src]'s [M.display_name] [what] in place.</span>")
if(sound)
playsound(src.loc, sound, 50, 1)
if(!do_after(user, 40))
manipulating = 0
return M
user.visible_message("<span class='notice'>\The [user] removes the [M.display_name] [what] from \the [src].</span>",
"<span class='notice'>You remove the [M.display_name] [what] from \the [src].</span>")
new M.stack_type(src.loc)
manipulating = 0
return null
/obj/structure/table/proc/remove_reinforced(obj/item/weapon/screwdriver/S, mob/user)
reinforced = common_material_remove(user, reinforced, 40, "reinforcements", "screws", 'sound/items/Screwdriver.ogg')
/obj/structure/table/proc/remove_material(obj/item/weapon/wrench/W, mob/user)
material = common_material_remove(user, material, 20, "plating", "bolts", 'sound/items/Ratchet.ogg')
/obj/structure/table/proc/dismantle(obj/item/weapon/wrench/W, mob/user)
if(manipulating) return
manipulating = 1
user.visible_message("<span class='notice'>\The [user] begins dismantling \the [src].</span>",
"<span class='notice'>You begin dismantling \the [src].</span>")
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
if(!do_after(user, 20))
manipulating = 0
return
user.visible_message("<span class='notice'>\The [user] dismantles \the [src].</span>",
"<span class='notice'>You dismantle \the [src].</span>")
new /obj/item/stack/material/steel(src.loc)
qdel(src)
return
// Returns a list of /obj/item/weapon/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/weapon/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 /obj/item/stack/material/steel(src.loc)
else
var/material/M = get_material_by_name(DEFAULT_WALL_MATERIAL)
S = M.place_shard(loc)
if(S) shards += S
qdel(src)
return shards
/obj/structure/table/update_icon()
if(flipped != 1)
icon_state = "blank"
overlays.Cut()
var/image/I
// Base frame shape. Mostly done for glass/diamond tables, where this is visible.
for(var/i = 1 to 4)
I = image(icon, dir = 1<<(i-1), icon_state = connections[i])
overlays += I
// Standard table image
if(material)
for(var/i = 1 to 4)
I = image(icon, "[material.icon_base]_[connections[i]]", dir = 1<<(i-1))
if(material.icon_colour) I.color = material.icon_colour
I.alpha = 255 * material.opacity
overlays += I
// Reinforcements
if(reinforced)
for(var/i = 1 to 4)
I = image(icon, "[reinforced.icon_reinf]_[connections[i]]", dir = 1<<(i-1))
I.color = reinforced.icon_colour
I.alpha = 255 * reinforced.opacity
overlays += I
if(carpeted)
for(var/i = 1 to 4)
I = image(icon, "carpet_[connections[i]]", dir = 1<<(i-1))
overlays += I
else
overlays.Cut()
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 += "+"
icon_state = "flip[type]"
if(material)
var/image/I = image(icon, "[material.icon_base]_flip[type]")
I.color = material.icon_colour
I.alpha = 255 * material.opacity
overlays += I
name = "[material.display_name] table"
else
name = "table frame"
if(reinforced)
var/image/I = image(icon, "[reinforced.icon_reinf]_flip[type]")
I.color = reinforced.icon_colour
I.alpha = 255 * reinforced.opacity
overlays += I
if(carpeted)
overlays += "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)
spawn(0)
T.update_connections()
T.update_icon()
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