mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-28 23:51:17 +01:00
Expedition Fluff Expansion - Tents & Sleeping Bags (#19362)
Adds tents, in two variants (A larger and smaller one). These utilise a new large structure framework allowing a single item to spawn multiple structures (The parts of the tent) in the correct places. The tents count as inside, so can be used to shelter from weather. Tents have roofs which become semi-transparent when entered. There are also mappable effects which generate a tent at round start for mapping. Adds sleeping bags, which can be attached to the outside of bags for easy carrying. Ideally this would be an accessories interaction, but backpacks aren't clothing and converting them to be such is outside of the scope of this PR. Adds foldable tables, for setting up on expeditions.
This commit is contained in:
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
|
||||
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)
|
||||
if(dir & (NORTH | SOUTH))
|
||||
if(C.x == x1 || C.x == x2)
|
||||
C.icon_state = "canvas_dir"
|
||||
var/mid = Mean(x1, x2)
|
||||
if(C.x < mid)
|
||||
C.dir = WEST
|
||||
else
|
||||
C.dir = EAST
|
||||
else
|
||||
if(C.y == y1 || C.y == y2)
|
||||
C.icon_state = "canvas_dir"
|
||||
var/mid = Mean(y1, y2)
|
||||
if(C.y < mid)
|
||||
C.dir = SOUTH
|
||||
else
|
||||
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_roof_type(C)]"
|
||||
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 roof state over each canvas structure
|
||||
* Returns `edge` for structures on the edge of the tent, so they don't cover the walls
|
||||
* Returns `mid` for structures in the centre of the tent, for odd number widths
|
||||
* Otherwise returns `norm` for other structures
|
||||
*/
|
||||
/datum/large_structure/tent/proc/get_roof_type(var/obj/structure/component/tent_canvas/canvas)
|
||||
var/edge1
|
||||
var/edge2
|
||||
var/axis
|
||||
if(dir & (NORTH | SOUTH))
|
||||
edge1 = x1
|
||||
edge2 = x2
|
||||
axis = canvas.x
|
||||
else
|
||||
edge1 = y1
|
||||
edge2 = y2
|
||||
axis = canvas.y
|
||||
if(axis == edge1 || axis == edge2)
|
||||
return "edge"
|
||||
else if(axis == Mean(edge1, edge2))
|
||||
return "mid"
|
||||
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 = ITEMSIZE_LARGE
|
||||
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), ITEMSIZE_IMMENSE) // 2x2 = ITEMSIZE_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"
|
||||
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 == "canvas")
|
||||
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 == "canvas")
|
||||
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) || !Adjacent(usr))
|
||||
return
|
||||
part_of.disassemble(2 SECONDS, usr, src)
|
||||
|
||||
/obj/structure/component/tent_canvas/roof
|
||||
plane = ROOF_PLANE
|
||||
|
||||
//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()
|
||||
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 = ITEMSIZE_LARGE
|
||||
|
||||
/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) || !Adjacent(user))
|
||||
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
|
||||
@@ -24,6 +24,14 @@
|
||||
allow_quick_empty = TRUE
|
||||
empty_delay = 0.5 SECOND
|
||||
var/straps = FALSE // Only really used for the verb.
|
||||
/**
|
||||
* References a sleeping bag attached to this bag. Should convert this to use accessories later, but that means making backpacks clothing.
|
||||
*/
|
||||
var/obj/item/sleeping_bag/attached_bag
|
||||
/**
|
||||
* Suffix used for overlays with an attached sleeping bag, because satchels are at people's sides while other bags are on people's backs.
|
||||
*/
|
||||
var/attached_icon = "backpack"
|
||||
|
||||
/obj/item/storage/backpack/Initialize()
|
||||
. = ..()
|
||||
@@ -31,6 +39,10 @@
|
||||
alpha_mask = "normal"
|
||||
verbs += /obj/item/storage/backpack/proc/adjust_backpack_straps
|
||||
|
||||
/obj/item/storage/backpack/Destroy()
|
||||
QDEL_NULL(attached_bag)
|
||||
. = ..()
|
||||
|
||||
/obj/item/storage/backpack/proc/adjust_backpack_straps()
|
||||
set name = "Adjust Bag Straps"
|
||||
set desc = "Adjust your bag straps."
|
||||
@@ -79,6 +91,44 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/storage/backpack/attackby(obj/item/attacking_item, mob/user, params)
|
||||
if(istype(attacking_item, /obj/item/sleeping_bag) && !attached_bag && ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
attached_bag = attacking_item
|
||||
update_icon()
|
||||
if(H.back == src)
|
||||
H.update_inv_back() // Add overlay to backpack if on back
|
||||
H.drop_from_inventory(attached_bag)
|
||||
attached_bag.loc = null
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/backpack/update_icon()
|
||||
. = ..()
|
||||
ClearOverlays()
|
||||
if(attached_bag)
|
||||
var/image/I = overlay_image(attached_bag.icon, "[attached_bag.icon_state]_[attached_icon]", attached_bag.color)
|
||||
AddOverlays(I)
|
||||
|
||||
/obj/item/storage/backpack/get_mob_overlay(mob/living/carbon/human/H, mob_icon, mob_state, slot, main_call)
|
||||
var/image/I = ..()
|
||||
if(slot == slot_back_str && attached_bag)
|
||||
var/image/over = overlay_image(attached_bag.icon, "[attached_bag.icon_state]_[attached_icon]_ba", attached_bag.color)
|
||||
I.AddOverlays(over)
|
||||
return I
|
||||
|
||||
/obj/item/storage/backpack/AltClick(mob/usr)
|
||||
if(attached_bag && ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.put_in_hands(attached_bag)
|
||||
attached_bag = null
|
||||
update_icon()
|
||||
if(H.back == src)
|
||||
H.update_inv_back()
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/*
|
||||
* Backpack Types
|
||||
*/
|
||||
@@ -333,6 +383,7 @@
|
||||
icon_state = "satchel"
|
||||
item_state = "satchel"
|
||||
straps = TRUE
|
||||
attached_icon = "satchel"
|
||||
|
||||
/obj/item/storage/backpack/satchel/leather/withwallet/New()
|
||||
..()
|
||||
@@ -927,6 +978,7 @@
|
||||
contained_sprite = FALSE
|
||||
sprite_sheets = list(BODYTYPE_VAURCA = 'icons/mob/species/vaurca/back.dmi', BODYTYPE_VAURCA_BULWARK = 'icons/mob/species/bulwark/back.dmi')
|
||||
var/hooded = FALSE
|
||||
var/cape_backing_state = "cape_backing"
|
||||
|
||||
/obj/item/storage/backpack/cloak/verb/toggle_cloak_hood()
|
||||
set name = "Toggle Cloak Hood"
|
||||
@@ -945,7 +997,7 @@
|
||||
|
||||
/obj/item/storage/backpack/cloak/get_mob_overlay(var/mob/living/carbon/human/human, var/mob_icon, var/mob_state, var/slot)
|
||||
var/image/I = ..()
|
||||
var/image/cape_backing = image(mob_icon, null, "[initial(icon_state)]_backing", MOB_SHADOW_LAYER)
|
||||
var/image/cape_backing = image(mob_icon, null, "[icon_state]_backing", MOB_SHADOW_LAYER)
|
||||
I.AddOverlays(cape_backing)
|
||||
return I
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
new /obj/item/clothing/head/hardhat/orange(src)
|
||||
new /obj/item/device/radio(src)
|
||||
new /obj/item/device/flashlight/lantern(src)
|
||||
new /obj/item/sleeping_bag/mining(src)
|
||||
|
||||
// Merchant
|
||||
/obj/structure/closet/secure_closet/merchant
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* # Large Structure
|
||||
*
|
||||
* This datum controls a large, multi-tile structure, capable of being assembled or disassembled as a unit (i.e. tents).
|
||||
*/
|
||||
/datum/large_structure
|
||||
/**
|
||||
* Name of this structure
|
||||
*/
|
||||
var/name = "structure"
|
||||
/**
|
||||
* Turfs this structure exists on
|
||||
*/
|
||||
var/list/turf/target_turfs = list()
|
||||
/**
|
||||
* Structures that are part of this structure
|
||||
*/
|
||||
var/list/obj/structure/component/grouped_structures = list()
|
||||
/**
|
||||
* Mobs assembling or disassembling this structure
|
||||
*/
|
||||
var/list/mob/interacting = list()
|
||||
/**
|
||||
* A list of the stages required to assemble or disassemble the large structure. Format: "string" = STAGE
|
||||
*/
|
||||
var/list/stages = list()
|
||||
/**
|
||||
* The smaller structure which makes up this large one
|
||||
*/
|
||||
var/component_structure
|
||||
/**
|
||||
* The type item used to set up this structure in the first place, made on disassembly
|
||||
*/
|
||||
var/source_item_type
|
||||
/**
|
||||
* The item used to set up this structure, deleted after assembly
|
||||
*/
|
||||
var/obj/item/source_item
|
||||
/**
|
||||
* The turf this structure started from. Used to check if the source_item building this has moved.
|
||||
*/
|
||||
var/turf/origin
|
||||
var/color
|
||||
var/dir
|
||||
var/x1
|
||||
var/x2
|
||||
var/y1
|
||||
var/y2
|
||||
var/z1
|
||||
var/z2
|
||||
|
||||
/**
|
||||
* Returns the first stage with value `type`
|
||||
*/
|
||||
/datum/large_structure/proc/get_next_stage(var/type)
|
||||
for(var/stage in stages)
|
||||
if(stages[stage] == type)
|
||||
return stage
|
||||
|
||||
/datum/large_structure/proc/assemble(var/time_per_structure, var/mob/user)
|
||||
if(user in interacting)
|
||||
to_chat(user, SPAN_INFO("You are already working on assembling \the [src]."))
|
||||
return FALSE
|
||||
|
||||
var/stage_to_do = get_next_stage(STAGE_DISASSEMBLED)
|
||||
|
||||
if(!stage_to_do)
|
||||
to_chat(user, SPAN_INFO("There is no more work to be done assembling \the [src]."))
|
||||
return FALSE
|
||||
|
||||
|
||||
if(!LAZYLEN(target_turfs))
|
||||
get_target_turfs(user)
|
||||
|
||||
interacting += user
|
||||
|
||||
user.visible_message(SPAN_NOTICE("\The [user] begins assembling \the [src]'s [stage_to_do]."))
|
||||
stages[stage_to_do] = STAGE_PROGRESS
|
||||
if(!do_after(user, time_per_structure * LAZYLEN(target_turfs)))
|
||||
stages[stage_to_do] = STAGE_DISASSEMBLED
|
||||
return
|
||||
user.visible_message(SPAN_NOTICE("\The [user] finishes assembling the [stage_to_do]."))
|
||||
stages[stage_to_do] = STAGE_ASSEMBLED
|
||||
|
||||
interacting -= user
|
||||
|
||||
if(get_next_stage(STAGE_DISASSEMBLED)) //Still work to do
|
||||
assemble(time_per_structure, user)
|
||||
return FALSE
|
||||
|
||||
if(get_next_stage(STAGE_PROGRESS)) //Still work being done
|
||||
return FALSE
|
||||
|
||||
build_structures()
|
||||
QDEL_NULL(source_item)
|
||||
return TRUE
|
||||
|
||||
/datum/large_structure/proc/get_target_turfs(var/mob/user, var/force = FALSE)
|
||||
target_turfs = block(x1,y1,z1,x2,y2,z2)
|
||||
for(var/turf/T in target_turfs)
|
||||
if(!(istype(T) || force))
|
||||
to_chat(user, SPAN_ALERT("You cannot set up \the [src] here. Try and find a big enough solid surface."))
|
||||
return FALSE
|
||||
|
||||
/datum/large_structure/proc/build_structures()
|
||||
for(var/turf/T in target_turfs)
|
||||
var/obj/structure/component/C = new component_structure(T)
|
||||
C.part_of = src
|
||||
C.color = color
|
||||
grouped_structures += C
|
||||
RegisterSignal(T, COMSIG_ATOM_ENTERED, PROC_REF(structure_entered), override = TRUE)
|
||||
|
||||
/datum/large_structure/proc/disassemble(var/time_per_structure, var/mob/user)
|
||||
if(user in interacting)
|
||||
to_chat(user, SPAN_INFO("You are already working on disassembling \the [src]."))
|
||||
return FALSE
|
||||
|
||||
var/stage_to_do = get_next_stage(STAGE_ASSEMBLED)
|
||||
|
||||
if(!stage_to_do)
|
||||
to_chat(user, SPAN_INFO("There is no more work to be done disassembling \the [src]."))
|
||||
return FALSE
|
||||
|
||||
interacting += user
|
||||
|
||||
user.visible_message(SPAN_NOTICE("\The [user] begins disassembling \the [src]'s [stage_to_do]."))
|
||||
stages[stage_to_do] = STAGE_PROGRESS
|
||||
if(!do_after(user, time_per_structure * LAZYLEN(grouped_structures)))
|
||||
stages[stage_to_do] = STAGE_ASSEMBLED
|
||||
return FALSE
|
||||
user.visible_message(SPAN_NOTICE("\The [user] finishes disassembling the [stage_to_do]."))
|
||||
stages[stage_to_do] = STAGE_DISASSEMBLED
|
||||
|
||||
interacting -= user
|
||||
|
||||
if(get_next_stage(STAGE_ASSEMBLED)) //Still work to do
|
||||
return disassemble(time_per_structure, user)
|
||||
|
||||
if(get_next_stage(STAGE_PROGRESS)) //Still work being done
|
||||
return
|
||||
|
||||
QDEL_LIST(grouped_structures)
|
||||
|
||||
var/obj/item/I = new source_item_type(get_turf(user))
|
||||
I.color = color
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/datum/large_structure/proc/structure_entered(var/turf/entry_point, var/atom/movable/entering)
|
||||
if(!isliving(entering))
|
||||
return FALSE
|
||||
RegisterSignal(entering, COMSIG_MOVABLE_MOVED, PROC_REF(mob_moved), override = TRUE)
|
||||
return TRUE
|
||||
|
||||
/datum/large_structure/proc/mob_moved(var/mob/mover)
|
||||
if(!(get_turf(mover) in target_turfs))
|
||||
UnregisterSignal(mover, COMSIG_MOVABLE_MOVED)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/component
|
||||
var/datum/large_structure/part_of
|
||||
|
||||
/obj/structure/component/Destroy()
|
||||
if(part_of)
|
||||
part_of.grouped_structures -= src
|
||||
return ..()
|
||||
Reference in New Issue
Block a user