Files
Aurora.3/code/game/objects/items/camping.dm
Fluffy a3a4d46fa7 Hitby refactor (#19624)
Refactored hitby to be in line with TG's version.
Refactored item weight defines to a more clear naming scheme, also in
line with TG's version.
Refactored how the movement bumps are handled, ported signals to handle
them, in preparation for the movement update.
Fixed disposal hit bouncing the hitting atom on the wall.
Items do not push other items anymore if they are tiny.
2024-07-28 20:52:08 +00:00

441 lines
14 KiB
Plaintext

/*
Tents
*/
/datum/large_structure/tent
stages = list("poles" = STAGE_DISASSEMBLED,
"canvas" = STAGE_DISASSEMBLED,
"guy lines" = STAGE_DISASSEMBLED,
"pegs" = STAGE_DISASSEMBLED)
component_structure = /obj/structure/component/tent_canvas
source_item_type = /obj/item/tent
/**
* The state name of an overlay in `icons/obj/item/tent_decals.dmi`
* Used for branded tents, such as the SCC base camp tent
*/
var/decal
/datum/large_structure/tent/build_structures()
. = ..()
var/list/roofs = list()
for(var/obj/structure/component/tent_canvas/C in grouped_structures)
var/perspective_fix = FALSE // Used to make E/W facing even tents have similar perspective to odd ones
if(dir & (NORTH | SOUTH))
if(C.x == x1 || C.x == x2)
C.icon_state = "canvas_[get_location(C)]"
var/mid = Mean(x1, x2)
if(C.x < mid)
C.dir = WEST
else
C.dir = EAST
else
var/width = y2 - y1
if(C.y == y1 || C.y == y2)
C.icon_state = "canvas_[get_location(C)]"
if(C.y == y2) //Upper wall
C.layer = ABOVE_TILE_LAYER
var/mid = Mean(y1, y2)
if(C.y < mid)
C.dir = SOUTH
else
if(ISODD(width) && C.y == Ceil(mid)) // `width` is actually 1 less than the width, so we need to check if this is odd
perspective_fix = TRUE
C.dir = NORTH
var/obj/structure/component/tent_canvas/roof/roof = new /obj/structure/component/tent_canvas/roof(C.loc)
roofs += roof
roof.color = color
roof.dir = C.dir
if(decal && C.x == x1 && C.y == y1)
roof.AddOverlays(overlay_image('icons/obj/item/tent_decals.dmi', decal, flags=RESET_COLOR))
roof.icon_state = "roof_[get_location(C)]"
if(perspective_fix)
roof.AddOverlays(overlay_image(roof.icon, "[roof.icon_state]_p"))
grouped_structures += roofs
/datum/large_structure/tent/structure_entered(turf/entry_point, atom/movable/entering)
. = ..()
if(!.)
return
var/mob/M = entering
if(!M.renderers)
return
var/atom/movable/renderer/roofs/roof_plane = M.renderers["[ROOF_PLANE]"]
if(roof_plane)
roof_plane.alpha = 76
/datum/large_structure/tent/mob_moved(mob/mover, turf/exit_point)
. = ..()
if(!.)
var/atom/movable/renderer/roofs/roof_plane = mover.renderers["[ROOF_PLANE]"]
if(roof_plane)
roof_plane.alpha = 255
/**
* Determines the state to use for each section of the tent
* Returns `edge` for structures on the edge of the tent
* Returns `entrance_top` for structures acting as an entrance, at the north/east of the tent
* Returns `entrance_bot` for structures acting as an entrance, at the south/west of the tent
* Returns `edge_entrance_top` for structures on the edge of the tent, and acting as an entrance, at the north/east of the tent
* Returns `edge_entrance_bot` for structures on the edge of the tent, and acting as an entrance, at the south/west of the tent
* Returns `mid` for structures in the exact centre of the tent, for odd number widths
* Returns `mid_entrance_top` for structures in the exact centre of the tent, for odd number widths, acting as an entrance, at the north/east of the tent
* Returns `mid_entrance_bot` for structures in the exact centre of the tent, for odd number widths, acting as an entrance, at the south/west of the tent
* Otherwise returns `norm` for other structures
*/
/datum/large_structure/tent/proc/get_location(var/obj/structure/component/tent_canvas/canvas)
var/edge1
var/edge2
var/side_coord
var/top_coord
var/top_edge
var/bot_edge
if(dir & (NORTH | SOUTH))
edge1 = x1
edge2 = x2
side_coord = canvas.x
top_edge = y2
bot_edge = y1
top_coord = canvas.y
else
edge1 = y1
edge2 = y2
side_coord = canvas.y
top_edge = x2
bot_edge = x1
top_coord = canvas.x
if(side_coord == edge1 || side_coord == edge2)
if(top_coord == top_edge)
return "edge_entrance_top"
else if(top_coord == bot_edge)
return "edge_entrance_bot"
return "edge"
else if(side_coord == Mean(edge1, edge2))
if(top_coord == top_edge)
return "mid_entrance_top"
else if(top_coord == bot_edge)
return "mid_entrance_bot"
return "mid"
else if(top_coord == top_edge)
return "entrance_top"
else if(top_coord == bot_edge)
return "entrance_bot"
return "norm"
/obj/item/tent
name = "expedition tent"
desc = "A rolled up tent, ready to be assembled to make a base camp, shelter, or just a cozy place to chat."
desc_info = "Drag this to yourself to begin assembly. This will take some time, in 4 stages. Others can start working on the other stages by dragging it to themselves as well."
icon = 'icons/obj/item/camping.dmi'
icon_state = "tent"
item_state = "tent"
contained_sprite = TRUE
w_class = WEIGHT_CLASS_BULKY
color = "#58a178"
var/width = 2
var/length = 3
var/decal
var/datum/large_structure/tent/my_tent
/obj/item/tent/Initialize()
. = ..()
w_class = min(ceil(width * length / 1.5), WEIGHT_CLASS_GIGANTIC) // 2x2 = WEIGHT_CLASS_NORMAL
desc += "\nThis one is [width] x [length] in size."
/obj/item/tent/Destroy()
if(my_tent)
my_tent.source_item = null
if(!my_tent.grouped_structures)
QDEL_NULL(my_tent)
return ..()
/obj/item/tent/MouseDrop(over_object, src_location, over_location)
. = ..()
if(use_check(usr) || !Adjacent(usr))
return
var/turf/T = get_turf(src)
if(istype(T))
deploy_tent(T, usr)
/obj/item/tent/proc/deploy_tent(var/turf/target, var/mob/user)
if(my_tent)
if(my_tent.origin == get_turf(src)) //Not moved
my_tent.assemble(1 SECOND, user)
return
else
QDEL_NULL(my_tent)
var/deploy_dir = get_compass_dir(user,target)
if(target == get_turf(user))
deploy_dir = user.dir
my_tent = new /datum/large_structure/tent(src)
setup_my_tent(deploy_dir, target)
my_tent.assemble(1 SECOND, user)
/obj/item/tent/proc/setup_my_tent(var/deploy_dir, var/turf/target)
my_tent.name = name
my_tent.color = color
my_tent.decal = decal
my_tent.dir = deploy_dir
my_tent.z1 = target.z
my_tent.z2 = target.z
my_tent.source_item_type = type
my_tent.source_item = src
my_tent.origin = get_turf(src)
if(deploy_dir & NORTH)
my_tent.x1 = target.x - floor((width-1)/2)
my_tent.x2 = target.x + ceil((width-1)/2)
my_tent.y1 = target.y
my_tent.y2 = target.y + (length-1)
else if(deploy_dir & SOUTH)
my_tent.x1 = target.x - ceil((width-1)/2)
my_tent.x2 = target.x + floor((width-1)/2)
my_tent.y1 = target.y - (length-1)
my_tent.y2 = target.y
else if(deploy_dir & EAST)
my_tent.x1 = target.x
my_tent.x2 = target.x + (length-1)
my_tent.y1 = target.y - ceil((width-1)/2)
my_tent.y2 = target.y + floor((width-1)/2)
else
my_tent.x1 = target.x - (length-1)
my_tent.x2 = target.x
my_tent.y1 = target.y - floor((width-1)/2)
my_tent.y2 = target.y + ceil((width-1)/2)
/obj/item/tent/big
name = "base camp tent"
color = "#2e3763"
width = 3
length = 4
/obj/item/tent/big/scc
name = "scc base camp tent"
decal = "scc"
/obj/item/tent/mining
name = "miners' tent"
color = "#8b7242"
width = 3
length = 3
/obj/structure/component/tent_canvas
name = "tent canvas"
desc = "The fabric and poles which make up the wall of a tent. Not air-tight, but able to keep out the weather, and very cozy."
desc_info = "Drag this to yourself to begin disassembly. This will take some time, in 4 stages. Others can start working on the other stages by dragging it, or other sections, to themselves as well."
icon = 'icons/obj/item/camping.dmi'
icon_state = "canvas"
item_state = "canvas"
anchored = TRUE
density = TRUE
atom_flags = ATOM_FLAG_CHECKS_BORDER
atmos_canpass = CANPASS_ALWAYS //Tents are not air tight
layer = ABOVE_HUMAN_LAYER
/obj/structure/component/tent_canvas/CanPass(atom/movable/mover, turf/target, height, air_group)
. = ..()
if(icon_state in list("canvas", "canvas_mid", "canvas_entrance_top", "canvas_entrace_bot"))
return TRUE //Non-directional, always allow passage
if(get_dir(loc, target) & dir)
return !density
return TRUE
/obj/structure/component/tent_canvas/CheckExit(atom/movable/O, turf/target)
. = ..()
if(icon_state in list("canvas", "canvas_mid", "canvas_entrance_top", "canvas_entrace_bot"))
return TRUE //Non-directional, always allow passage
if(get_dir(O.loc, target) & dir)
return !density
return TRUE
/obj/structure/component/tent_canvas/MouseDrop(over_object, src_location, over_location)
..()
if(use_check(usr, USE_ALLOW_NON_ADJACENT) || (get_dist(usr, src) > 1)) // use_check() can't check for adjacency due to density issues, so we check range as well
return
part_of.disassemble(2 SECONDS, usr, src)
/obj/structure/component/tent_canvas/Destroy() //When we're destroyed, make sure we return the roof plane to anyone inside
for(var/mob/M in loc)
var/atom/movable/renderer/roofs/roof_plane = M.renderers["[ROOF_PLANE]"]
if(roof_plane)
roof_plane.alpha = 255
return ..()
/obj/structure/component/tent_canvas/roof
plane = ROOF_PLANE
/obj/structure/component/tent_canvas/roof/CanPass(atom/movable/mover, turf/target, height, air_group)
return TRUE
/obj/structure/component/tent_canvas/roof/CheckExit(atom/movable/O, turf/target)
return TRUE
//Pre-fabricated tents for mapping
/obj/effect/tent
name = "Pre-frabricated expedition tent"
icon = 'icons/effects/map_effects.dmi'
icon_state = "portal_side_a"
var/builds = /obj/item/tent
/obj/effect/tent/Initialize(mapload, ...)
. = ..()
var/obj/item/tent/tent_item = new builds(src)
var/datum/large_structure/tent/tent = new /datum/large_structure/tent(src)
tent_item.my_tent = tent
tent_item.setup_my_tent(dir, get_turf(src))
tent.get_target_turfs(null, TRUE)
tent.build_structures()
for(var/stage in tent.stages)
tent.stages[stage] = STAGE_ASSEMBLED
qdel(tent_item)
qdel(src)
/*
Sleeping bags
*/
/obj/item/sleeping_bag
name = "sleeping bag"
desc = "A rolled up sleeping bag, ready to be taken on a camping trip."
desc_extended = "This item can be attached to a backpack."
icon = 'icons/obj/item/camping.dmi'
icon_state = "sleepingbag"
item_state = "sleepingbag"
contained_sprite = TRUE
w_class = WEIGHT_CLASS_BULKY
/obj/item/sleeping_bag/Initialize(mapload, ...)
. = ..()
if(!color)
color = pick(COLOR_NAVY_BLUE, COLOR_GREEN, COLOR_MAROON, COLOR_VIOLET, COLOR_OLIVE, COLOR_SEDONA)
/obj/item/sleeping_bag/afterattack(obj/target, mob/user, proximity)
. = ..()
if(!proximity)
return
var/turf/T = target
if(istype(T))
unroll(T, user)
/obj/item/sleeping_bag/attack_self(mob/user)
. = ..()
var/turf/T = get_turf(user)
if(istype(T))
unroll(T, user)
/obj/item/sleeping_bag/MouseDrop(over_object, src_location, over_location)
. = ..()
if(use_check(usr) || !Adjacent(usr))
return
var/turf/T = get_turf(src)
if(istype(T))
unroll(T, usr)
/**
* Creates sleeping bag structure on the target turf, deleting this item in the process
*/
/obj/item/sleeping_bag/proc/unroll(var/turf/target, var/mob/user)
user.visible_message(SPAN_NOTICE("\The [user] unrolls \the [src]."))
var/obj/structure/bed/sleeping_bag/S = new /obj/structure/bed/sleeping_bag(target, MATERIAL_CLOTH)
S.color = color
qdel(src)
/obj/item/sleeping_bag/mining
color = COLOR_DARK_BROWN
/obj/structure/bed/sleeping_bag
name = "sleeping bag"
desc = "A bag for sleeping in. Great for trying to pretend you're somewhere more comfortable than you really are."
icon = 'icons/obj/item/camping.dmi'
icon_state = "sleepingbag_floor"
base_icon = "sleepingbag_floor"
density = FALSE
anchored = FALSE
buckling_sound = 'sound/items/drop/cloth.ogg'
held_item = /obj/item/sleeping_bag
can_dismantle = FALSE
can_pad = FALSE
/obj/structure/bed/sleeping_bag/update_icon()
return
/obj/structure/bed/sleeping_bag/buckle(mob/living/M)
. = ..()
var/image/I = overlay_image(icon, "[base_icon]_top", color)
M.AddOverlays(I)
/obj/structure/bed/sleeping_bag/unbuckle()
if(buckled)
buckled.update_icon()
. = ..()
/obj/structure/bed/sleeping_bag/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
. = ..()
if(use_check(usr) || !Adjacent(usr))
return
if(!ishuman(usr) && (!isrobot(usr) || isDrone(usr))) //Humans and borgs can roll, but not drones
return
if(buckled)
to_chat(usr, SPAN_WARNING("You can't roll up \the [src] while someone is sleeping inside."))
return
var/obj/item/sleeping_bag/S = new held_item(get_turf(src))
S.color = color
usr.visible_message(SPAN_NOTICE("\The [usr] rolls up \the [src]."))
qdel(src)
/*
Folding Tables
*/
/obj/item/material/folding_table
name = "folding table"
desc = "A temporary surface, for when you need a table, but only for a little while."
icon = 'icons/obj/item/camping.dmi'
icon_state = "table_folded"
item_state = "table_folded"
contained_sprite = TRUE
default_material = MATERIAL_ALUMINIUM
/obj/item/material/folding_table/attack_self(mob/user)
if(use_check(user) || !Adjacent(user))
return
deploy(get_turf(user), user.dir, user)
/obj/item/material/folding_table/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(use_check(user) || !user.Adjacent(target))
to_chat(usr, SPAN_WARNING("You fail to set up \the [src] in that location."))
return
if(isturf(target))
deploy(target, user.dir, user)
/obj/item/material/folding_table/proc/deploy(var/turf/T, var/direction, var/mob/user)
new /obj/structure/table/rack/folding_table(T)
user.visible_message(SPAN_NOTICE("\The [user] sets up \the [src]."))
qdel(src)
/obj/structure/table/rack/folding_table
name = "folding table"
desc = "A temporary surface, for when you need a table, but only for a little while."
icon_state = "camping_table"
table_mat = MATERIAL_ALUMINIUM
/obj/structure/table/rack/folding_table/dismantle(obj/item/wrench/W, mob/user)
return FALSE
/obj/structure/table/rack/folding_table/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
. = ..()
if(use_check(usr) || !Adjacent(usr))
return
if(!ishuman(usr) && (!isrobot(usr) || isDrone(usr))) //Humans and borgs can collapse, but not drones
return
new /obj/item/material/folding_table(get_turf(src))
usr.visible_message(SPAN_NOTICE("\The [usr] collapses \the [src]."))
qdel(src)
/obj/item/material/stool/chair/folding/camping
default_material = MATERIAL_ALUMINIUM