mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-20 20:45:28 +01:00
Adds a unit test for techweb design presence, puts some missing designs into protolathes (#90219)
## About The Pull Request Adds a unit test that checks that all designs are accessible through some source, be it techweb, disks, or innate designs. Certain designs, like pocket extinguishers, entertainment screens, etc, that have been present in autolathes but not in the techweb despite having PROTOLATHE flag assigned have been put into protolathes (where it made sense, otherwise the flag was removed). An important change is that restaurant portals are now printable, and thus can be constructed and deconstructed. Indestructible portals have been a major gripe of mine for a while, and I don't see a solid reason for keeping them indestructible if they can easily be printed from the service protolathe. Closes #90212 ## Why It's Good For The Game Initial argument for keeping portals unbreakable was to prevent people from griefing the chef/bartender, but by that logic we can make most machinery unbreakable too. I don't think that having an unbreakable portal is good if its locking us out from allowing chefs/bartenders to reorder or even outright reposition their lunchroom/bar. ## Changelog 🆑 balance: Restaurant portals can now be printed, constructed and deconstructed. They're also no longer completely invulnerable. /🆑
This commit is contained in:
@@ -112,7 +112,8 @@
|
||||
/datum/ai_behavior/leave_venue/setup(datum/ai_controller/controller, venue_key)
|
||||
. = ..()
|
||||
var/datum/venue/attending_venue = controller.blackboard[venue_key]
|
||||
set_movement_target(controller, attending_venue.restaurant_portal)
|
||||
var/datum/weakref/portal_ref = attending_venue.current_visitors[controller.pawn]
|
||||
set_movement_target(controller, portal_ref.resolve())
|
||||
|
||||
/datum/ai_behavior/leave_venue/perform(seconds_per_tick, datum/ai_controller/controller, venue_key)
|
||||
qdel(controller.pawn) //save the world, my final message, goodbye.
|
||||
|
||||
@@ -1505,7 +1505,42 @@
|
||||
name = "Restaurant Portal"
|
||||
greyscale_colors = CIRCUIT_COLOR_SERVICE
|
||||
build_path = /obj/machinery/restaurant_portal
|
||||
req_components = list(
|
||||
/datum/stock_part/scanning_module = 2,
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
needs_anchored = TRUE
|
||||
/// Type of the venue that we're linked to
|
||||
var/venue_type = /datum/venue/restaurant
|
||||
|
||||
/obj/item/circuitboard/machine/restaurant_portal/multitool_act(mob/living/user)
|
||||
var/list/radial_items = list()
|
||||
var/list/radial_results = list()
|
||||
|
||||
for(var/type_key in SSrestaurant.all_venues)
|
||||
var/datum/venue/venue = SSrestaurant.all_venues[type_key]
|
||||
radial_items[venue.name] = image('icons/obj/machines/restaurant_portal.dmi', venue.name)
|
||||
radial_results[venue.name] = type_key
|
||||
|
||||
var/choice = show_radial_menu(user, src, radial_items, null, require_near = TRUE)
|
||||
|
||||
if(!choice)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
venue_type = radial_results[choice]
|
||||
to_chat(user, span_notice("You change [src]'s linked venue."))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/circuitboard/machine/restaurant_portal/examine(mob/user)
|
||||
. = ..()
|
||||
if (venue_type)
|
||||
var/datum/venue/as_venue = venue_type
|
||||
. += span_notice("[src] is linked to \a [initial(as_venue.name)] venue.")
|
||||
|
||||
/obj/item/circuitboard/machine/restaurant_portal/configure_machine(obj/machinery/restaurant_portal/machine)
|
||||
if(!istype(machine))
|
||||
CRASH("Cargo board attempted to configure incorrect machine type: [machine] ([machine?.type])")
|
||||
machine.linked_venue = SSrestaurant.all_venues[venue_type]
|
||||
machine.linked_venue.restaurant_portals += machine
|
||||
|
||||
/obj/item/circuitboard/machine/abductor
|
||||
name = "alien board (Report This)"
|
||||
|
||||
@@ -261,7 +261,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
|
||||
return SUCCESSFUL_UNFASTEN
|
||||
|
||||
/// Try to unwrench an object in a WONDERFUL DYNAMIC WAY
|
||||
/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench, time = 20)
|
||||
/obj/proc/default_unfasten_wrench(mob/user, obj/item/wrench, time = 2 SECONDS)
|
||||
if(wrench.tool_behaviour != TOOL_WRENCH)
|
||||
return CANT_UNFASTEN
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
var/list/customer_types
|
||||
///Is the venue open at the moment?
|
||||
var/open
|
||||
///Portal linked to this venue at the moment
|
||||
var/obj/machinery/restaurant_portal/restaurant_portal
|
||||
///List of portals linked to this venue at the moment
|
||||
var/list/obj/machinery/restaurant_portal/restaurant_portals = list()
|
||||
///Lists the current visitors of a venue
|
||||
var/list/current_visitors = list()
|
||||
///Cooldown for next guest to arrive
|
||||
@@ -42,13 +42,14 @@
|
||||
/datum/venue/proc/create_new_customer()
|
||||
var/list/customer_types_to_choose = customer_types
|
||||
var/datum/customer_data/customer_type
|
||||
var/obj/machinery/restaurant_portal/chosen_portal = pick(restaurant_portals)
|
||||
|
||||
// In practice, the list will never run out, but this is for sanity.
|
||||
while (customer_types_to_choose.len)
|
||||
customer_type = pick_weight(customer_types_to_choose)
|
||||
|
||||
var/datum/customer_data/customer = SSrestaurant.all_customers[customer_type]
|
||||
if (customer.can_use(src))
|
||||
if (customer.can_use(src, chosen_portal))
|
||||
break
|
||||
|
||||
// Only copy the list once, so that we're not mutating ourselves.
|
||||
@@ -60,8 +61,8 @@
|
||||
if (initial(customer_type.is_unique))
|
||||
customer_types -= customer_type
|
||||
|
||||
var/mob/living/basic/robot_customer/new_customer = new /mob/living/basic/robot_customer(get_turf(restaurant_portal), customer_type, src)
|
||||
current_visitors += new_customer
|
||||
var/mob/living/basic/robot_customer/new_customer = new /mob/living/basic/robot_customer(get_turf(chosen_portal), customer_type, src)
|
||||
current_visitors[new_customer] = WEAKREF(chosen_portal)
|
||||
|
||||
/datum/venue/proc/order_food(mob/living/basic/robot_customer/customer_pawn, datum/customer_data/customer_data)
|
||||
var/order = pick_weight(customer_data.orderable_objects[venue_type])
|
||||
@@ -76,7 +77,7 @@
|
||||
order = initial(reagent_order.restaurant_order)
|
||||
|
||||
if(ispath(order, /datum/custom_order)) // generate the special order
|
||||
var/datum/custom_order/custom_order = new order(arglist(order_args || list()))
|
||||
var/datum/custom_order/custom_order = new order(arglist(list("customer" = customer_pawn) + (order_args || list())))
|
||||
food_image = custom_order.get_order_appearance(src)
|
||||
food_line = custom_order.get_order_line(src)
|
||||
order = custom_order.dispense_order()
|
||||
@@ -144,13 +145,15 @@
|
||||
|
||||
/datum/venue/proc/open()
|
||||
open = TRUE
|
||||
restaurant_portal.update_icon()
|
||||
for (var/obj/machinery/restaurant_portal/portal as anything in restaurant_portals)
|
||||
portal.update_icon()
|
||||
COOLDOWN_START(src, visit_cooldown, 4 SECONDS) //First one comes faster
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/datum/venue/proc/close()
|
||||
open = FALSE
|
||||
restaurant_portal.update_icon()
|
||||
for (var/obj/machinery/restaurant_portal/portal as anything in restaurant_portals)
|
||||
portal.update_icon()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
for(var/mob/living/basic/robot_customer as anything in current_visitors)
|
||||
robot_customer.ai_controller.set_blackboard_key(BB_CUSTOMER_LEAVING, TRUE) //LEAVEEEEEE
|
||||
@@ -160,32 +163,51 @@
|
||||
desc = "A robot-only gate into the wonders of Space Station cuisine!"
|
||||
icon = 'icons/obj/machines/restaurant_portal.dmi'
|
||||
icon_state = "portal"
|
||||
base_icon_state = "portal"
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/restaurant_portal
|
||||
layer = BELOW_OBJ_LAYER
|
||||
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
armor_type = /datum/armor/restaurant_portal
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
///What venue is this portal for? Uses a typepath which is turned into an instance on Initialize
|
||||
var/datum/venue/linked_venue = /datum/venue
|
||||
var/datum/venue/linked_venue
|
||||
|
||||
/// A weak reference to the mob who turned on the portal
|
||||
var/datum/weakref/turned_on_portal
|
||||
|
||||
/datum/armor/restaurant_portal
|
||||
melee = 50
|
||||
bullet = 30
|
||||
laser = 50
|
||||
energy = 20
|
||||
bomb = 20
|
||||
fire = 100
|
||||
acid = 100
|
||||
|
||||
/obj/machinery/restaurant_portal/Initialize(mapload)
|
||||
. = ..()
|
||||
if(linked_venue)
|
||||
linked_venue = SSrestaurant.all_venues[linked_venue]
|
||||
linked_venue.restaurant_portal = src
|
||||
register_context()
|
||||
if (!linked_venue)
|
||||
return
|
||||
var/obj/item/circuitboard/machine/restaurant_portal/board = circuit
|
||||
board.venue_type = linked_venue
|
||||
linked_venue = SSrestaurant.all_venues[linked_venue]
|
||||
linked_venue.restaurant_portals += src
|
||||
|
||||
/obj/machinery/restaurant_portal/Destroy()
|
||||
. = ..()
|
||||
turned_on_portal = null
|
||||
linked_venue.restaurant_portal = null
|
||||
linked_venue.restaurant_portals -= src
|
||||
linked_venue = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/restaurant_portal/on_construction(mob/user)
|
||||
. = ..()
|
||||
circuit.configure_machine(src)
|
||||
|
||||
/obj/machinery/restaurant_portal/update_overlays()
|
||||
. = ..()
|
||||
if(!linked_venue.open) //Any open venues
|
||||
if(!linked_venue?.open) //Any open venues
|
||||
. += mutable_appearance(icon, "portal_door")
|
||||
|
||||
/obj/machinery/restaurant_portal/attack_hand(mob/living/user)
|
||||
@@ -217,14 +239,17 @@
|
||||
for(var/type_key in SSrestaurant.all_venues)
|
||||
var/datum/venue/venue = SSrestaurant.all_venues[type_key]
|
||||
radial_items[venue.name] = image('icons/obj/machines/restaurant_portal.dmi', venue.name)
|
||||
radial_results[venue.name] = venue
|
||||
radial_results[venue.name] = type_key
|
||||
|
||||
var/choice = show_radial_menu(user, src, radial_items, null, require_near = TRUE)
|
||||
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
var/datum/venue/chosen_venue = radial_results[choice]
|
||||
var/venue_type = radial_results[choice]
|
||||
var/obj/item/circuitboard/machine/restaurant_portal/board = circuit
|
||||
board.venue_type = venue_type
|
||||
var/datum/venue/chosen_venue = SSrestaurant.all_venues[venue_type]
|
||||
|
||||
turned_on_portal = WEAKREF(user)
|
||||
|
||||
@@ -234,15 +259,54 @@
|
||||
|
||||
to_chat(user, span_notice("You change the portal's linked venue."))
|
||||
|
||||
if(linked_venue && linked_venue.restaurant_portal) //We're already linked, unlink us.
|
||||
if(linked_venue.open)
|
||||
if(linked_venue && (src in linked_venue.restaurant_portals)) //We're already linked, unlink us.
|
||||
linked_venue.restaurant_portals -= src
|
||||
if(linked_venue.open && !length(linked_venue.restaurant_portals))
|
||||
linked_venue.close()
|
||||
linked_venue.restaurant_portal = null
|
||||
linked_venue = null
|
||||
|
||||
linked_venue = chosen_venue
|
||||
linked_venue.restaurant_portal = src
|
||||
linked_venue.restaurant_portals += src
|
||||
|
||||
/obj/machinery/restaurant_portal/screwdriver_act(mob/user, obj/item/tool)
|
||||
if (default_deconstruction_screwdriver(user, "[base_icon_state]-open", base_icon_state, tool))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/machinery/restaurant_portal/crowbar_act(mob/user, obj/item/tool)
|
||||
if(default_deconstruction_crowbar(tool))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/machinery/restaurant_portal/wrench_act(mob/living/user, obj/item/tool)
|
||||
if(!panel_open)
|
||||
balloon_alert(user, "open the panel first!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if (default_unfasten_wrench(user, tool))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/obj/machinery/restaurant_portal/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
. = NONE
|
||||
if(isnull(held_item))
|
||||
return
|
||||
|
||||
if(held_item.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(held_item.tool_behaviour == TOOL_WRENCH)
|
||||
context[SCREENTIP_CONTEXT_LMB] = anchored ? "Unsecure" : "Secure"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(held_item.tool_behaviour == TOOL_CROWBAR && panel_open)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(isidcard(held_item))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Change Venue"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/item/holosign_creator/robot_seat
|
||||
name = "seating indicator placer"
|
||||
|
||||
@@ -41,8 +41,10 @@
|
||||
/// The item type that we want to order, usually clothing
|
||||
var/wanted_clothing_type
|
||||
|
||||
/datum/custom_order/moth_clothing/New(datum/venue/our_venue)
|
||||
var/mob/living/carbon/buffet = our_venue.restaurant_portal?.turned_on_portal?.resolve()
|
||||
/datum/custom_order/moth_clothing/New(mob/living/basic/robot_customer/customer, datum/venue/our_venue)
|
||||
var/datum/weakref/portal_ref = our_venue.current_visitors[customer]
|
||||
var/obj/machinery/restaurant_portal/portal = portal_ref.resolve()
|
||||
var/mob/living/carbon/buffet = portal?.turned_on_portal?.resolve()
|
||||
if (!istype(buffet)) // Always asks for the clothes that you have on, but this is a fallback.
|
||||
wanted_clothing_type = pick_weight(list(
|
||||
/obj/item/clothing/head/utility/chefhat = 3,
|
||||
@@ -90,7 +92,7 @@
|
||||
/// stores tha name of our order generated on New()
|
||||
var/icecream_name
|
||||
|
||||
/datum/custom_order/icecream/New()
|
||||
/datum/custom_order/icecream/New(mob/living/basic/robot_customer/customer)
|
||||
if(prob(33))
|
||||
cone_type = /obj/item/food/icecream/chocolate
|
||||
var/static/list/possible_flavors = list()
|
||||
@@ -136,7 +138,7 @@
|
||||
/// How many reagents is needed
|
||||
var/reagents_needed = VENUE_BAR_MINIMUM_REAGENTS
|
||||
|
||||
/datum/custom_order/reagent/New(reagent_type)
|
||||
/datum/custom_order/reagent/New(mob/living/basic/robot_customer/customer, reagent_type)
|
||||
. = ..()
|
||||
src.reagent_type = reagent_type
|
||||
|
||||
@@ -198,7 +200,7 @@
|
||||
/// What serving we picked for the order
|
||||
var/picked_serving
|
||||
|
||||
/datum/custom_order/reagent/soup/New(reagent_type)
|
||||
/datum/custom_order/reagent/soup/New(mob/living/basic/robot_customer/customer, reagent_type)
|
||||
. = ..()
|
||||
var/list/serving_sizes = list(
|
||||
"small serving (15u)" = 15,
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
orderable_restaurant[/datum/custom_order/icecream] *= 3
|
||||
|
||||
/// Can this customer be chosen for this venue?
|
||||
/datum/customer_data/proc/can_use(datum/venue/venue)
|
||||
/datum/customer_data/proc/can_use(datum/venue/venue, obj/machinery/restaurant_portal/portal)
|
||||
return TRUE
|
||||
|
||||
/datum/customer_data/proc/get_overlays(mob/living/basic/robot_customer/customer)
|
||||
@@ -295,8 +295,8 @@
|
||||
// The whole gag is taking off your hat and giving it to the customer.
|
||||
// If it takes any more effort, it loses a bit of the comedy.
|
||||
// Therefore, only show up if it's reasonable for that gag to happen.
|
||||
/datum/customer_data/moth/can_use(datum/venue/venue)
|
||||
var/mob/living/carbon/buffet = venue.restaurant_portal?.turned_on_portal?.resolve()
|
||||
/datum/customer_data/moth/can_use(datum/venue/venue, obj/machinery/restaurant_portal/portal)
|
||||
var/mob/living/carbon/buffet = portal.turned_on_portal?.resolve()
|
||||
if (!istype(buffet))
|
||||
return FALSE
|
||||
if(QDELETED(buffet.head) && QDELETED(buffet.gloves) && QDELETED(buffet.shoes))
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
/datum/design/toolbox
|
||||
name = "Toolbox"
|
||||
id = "tool_box"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(MAT_CATEGORY_ITEM_MATERIAL =SMALL_MATERIAL_AMOUNT*5)
|
||||
build_path = /obj/item/storage/toolbox
|
||||
category = list(
|
||||
@@ -536,7 +536,7 @@
|
||||
name = "Paper Biscuit"
|
||||
desc = "A paper biscuit which can seal paperwork inside. After sealing it the only way to open is through cracking it, cracking is irreversible and makes it permanently open. Not actually a biscuit."
|
||||
id = "biscuit"
|
||||
build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic =SMALL_MATERIAL_AMOUNT*0.2)
|
||||
build_path = /obj/item/folder/biscuit/unsealed
|
||||
category = list(
|
||||
@@ -549,7 +549,7 @@
|
||||
name = "Confidential Paper Biscuit"
|
||||
desc = "A paper biscuit which can seal paperwork inside, this one is used for confidential Nanotrasen documents. After sealing it the only way to open is through cracking it, cracking is irreversible and makes it permanently open. Not actually a biscuit."
|
||||
id = "confidential_biscuit"
|
||||
build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic = SMALL_MATERIAL_AMOUNT*0.3)
|
||||
build_path = /obj/item/folder/biscuit/unsealed/confidential
|
||||
category = list(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/datum/design/beanbag_slug
|
||||
name = "Beanbag Slug (Less Lethal)"
|
||||
id = "beanbag_slug"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT)
|
||||
build_path = /obj/item/ammo_casing/shotgun/beanbag
|
||||
category = list(
|
||||
@@ -13,7 +13,7 @@
|
||||
/datum/design/rubbershot
|
||||
name = "Rubber Shot (Less Lethal)"
|
||||
id = "rubber_shot"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*2)
|
||||
build_path = /obj/item/ammo_casing/shotgun/rubbershot
|
||||
category = list(
|
||||
@@ -25,7 +25,7 @@
|
||||
/datum/design/c38
|
||||
name = "Speed Loader (.38) (Lethal)"
|
||||
id = "c38"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*10)
|
||||
build_path = /obj/item/ammo_box/c38
|
||||
category = list(
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
/datum/design/plastic_tree
|
||||
name = "Plastic Potted Plant"
|
||||
id = "plastic_trees"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT*4)
|
||||
build_path = /obj/item/kirbyplants/random/fullysynthetic
|
||||
category = list(
|
||||
@@ -434,7 +434,7 @@
|
||||
/datum/design/beads
|
||||
name = "Plastic Bead Necklace"
|
||||
id = "plastic_necklace"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic =SMALL_MATERIAL_AMOUNT*5)
|
||||
build_path = /obj/item/clothing/neck/beads
|
||||
category = list(
|
||||
@@ -446,7 +446,7 @@
|
||||
/datum/design/plastic_ring
|
||||
name = "Plastic Can Rings"
|
||||
id = "ring_holder"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT*1.2)
|
||||
build_path = /obj/item/storage/cans
|
||||
category = list(
|
||||
@@ -458,7 +458,7 @@
|
||||
/datum/design/plastic_box
|
||||
name = "Plastic Box"
|
||||
id = "plastic_box"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/plastic =HALF_SHEET_MATERIAL_AMOUNT)
|
||||
build_path = /obj/item/storage/box/plastic
|
||||
category = list(
|
||||
|
||||
@@ -200,7 +200,6 @@
|
||||
// Intentionally not growable by normal means - for balance conerns.
|
||||
/datum/design/ethereal_heart
|
||||
name = "Crystal Core"
|
||||
id = "etherealheart"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/consumable/liquidelectricity/enriched = 20)
|
||||
build_path = /obj/item/organ/heart/ethereal
|
||||
@@ -231,7 +230,6 @@
|
||||
/datum/design/limb_disk
|
||||
name = "Limb Design Disk"
|
||||
desc = "Contains designs for various limbs."
|
||||
id = "limbdesign_parent"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT * 3, /datum/material/glass =SMALL_MATERIAL_AMOUNT)
|
||||
build_path = /obj/item/disk/design_disk/limbs
|
||||
|
||||
@@ -398,28 +398,6 @@
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design/board/protolathe
|
||||
name = "Protolathe Board"
|
||||
desc = "The circuit board for a protolathe."
|
||||
id = "protolathe"
|
||||
build_type = IMPRINTER
|
||||
build_path = /obj/item/circuitboard/machine/protolathe
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_FAB
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design/board/protolathe/offstation
|
||||
name = "Ancient Protolathe Board"
|
||||
desc = "The circuit board for an ancient protolathe."
|
||||
id = "protolathe_offstation"
|
||||
build_type = AWAY_IMPRINTER
|
||||
build_path = /obj/item/circuitboard/machine/protolathe/offstation
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_FAB
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design/board/circuit_imprinter
|
||||
name = "Circuit Imprinter Board"
|
||||
desc = "The circuit board for a circuit imprinter."
|
||||
|
||||
@@ -1101,7 +1101,6 @@
|
||||
/datum/design/surgery
|
||||
name = "Surgery Design"
|
||||
desc = "what"
|
||||
id = "surgery_parent"
|
||||
research_icon = 'icons/obj/medical/surgery_ui.dmi'
|
||||
research_icon_state = "surgery_any"
|
||||
var/surgery
|
||||
|
||||
@@ -475,18 +475,6 @@
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design/stunshell
|
||||
name = "Stun Shell"
|
||||
desc = "A stunning shell for a shotgun."
|
||||
id = "stunshell"
|
||||
build_type = PROTOLATHE | AWAY_LATHE
|
||||
materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT * 2)
|
||||
build_path = /obj/item/ammo_casing/shotgun/stunslug
|
||||
category = list(
|
||||
RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_AMMO
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SECURITY
|
||||
|
||||
/datum/design/lasershell
|
||||
name = "Scatter Laser Shotgun Shell (Lethal)"
|
||||
desc = "A high-tech shotgun shell which houses an internal capacitor and laser focusing crystal inside of a shell casing. \
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"plasmaman_tank_belt",
|
||||
"plasmarefiller",
|
||||
"extinguisher",
|
||||
"pocketfireextinguisher",
|
||||
"gas_filter",
|
||||
"plasmaman_gas_filter",
|
||||
"analyzer",
|
||||
@@ -40,6 +41,7 @@
|
||||
"turbine_stator",
|
||||
"atmos_thermal",
|
||||
"pneumatic_seal",
|
||||
"large_welding_tool",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS)
|
||||
experiments_to_unlock = list(
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
design_ids = list(
|
||||
"mauna_mug",
|
||||
"rolling_table",
|
||||
"plasticducky",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS)
|
||||
hidden = TRUE
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"comp_soundemitter",
|
||||
"comp_species",
|
||||
"comp_speech",
|
||||
"comp_speech",
|
||||
"comp_split",
|
||||
"comp_string_contains",
|
||||
"comp_tempsensor",
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
"firelock_board",
|
||||
"trapdoor_electronics",
|
||||
"blast",
|
||||
"ignition",
|
||||
"big_manipulator",
|
||||
"tile_sprayer",
|
||||
"airlock_painter",
|
||||
@@ -137,8 +138,8 @@
|
||||
"cable_coil",
|
||||
"welding_helmet",
|
||||
"welding_tool",
|
||||
"mini_welding_tool",
|
||||
"tscanner",
|
||||
"analyzer",
|
||||
"multitool",
|
||||
"wrench",
|
||||
"crowbar",
|
||||
@@ -178,6 +179,7 @@
|
||||
"inducerengi",
|
||||
"welding_goggles",
|
||||
"tray_goggles",
|
||||
"geigercounter",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS)
|
||||
announce_channels = list(RADIO_CHANNEL_ENGINEERING)
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
"normtrash",
|
||||
"wirebrush",
|
||||
"flashlight",
|
||||
"water_balloon",
|
||||
"ticket_machine",
|
||||
"radio_entertainment",
|
||||
)
|
||||
|
||||
/datum/techweb_node/sanitation
|
||||
@@ -77,6 +80,13 @@
|
||||
"custom_vendor_refill",
|
||||
"bounty_pad_control",
|
||||
"bounty_pad",
|
||||
"digital_clock_frame",
|
||||
"telescreen_research",
|
||||
"telescreen_ordnance",
|
||||
"telescreen_interrogation",
|
||||
"telescreen_prison",
|
||||
"telescreen_bar",
|
||||
"telescreen_entertainment",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS)
|
||||
announce_channels = list(RADIO_CHANNEL_SERVICE)
|
||||
@@ -121,6 +131,8 @@
|
||||
"coffeemaker",
|
||||
"coffeepot",
|
||||
"syrup_bottle",
|
||||
"foodtray",
|
||||
"restaurant_portal",
|
||||
)
|
||||
|
||||
/datum/techweb_node/food_proc
|
||||
|
||||
@@ -32,3 +32,58 @@
|
||||
if (isnull(current_design.surgery) || current_design.surgery == default_design_surgery.surgery) //Check if surgery was not set
|
||||
TEST_FAIL("Surgery Design [current_design.type] has default or null surgery var")
|
||||
|
||||
/datum/unit_test/design_source
|
||||
|
||||
/datum/unit_test/design_source/Run()
|
||||
var/list/all_designs = list()
|
||||
var/list/exceptions = list(
|
||||
/datum/design/surgery/healing, // Ignored due to the above test
|
||||
)
|
||||
|
||||
for (var/datum/design/design as anything in subtypesof(/datum/design))
|
||||
var/design_id = design::id
|
||||
if (design_id == DESIGN_ID_IGNORE || (design in exceptions))
|
||||
continue
|
||||
if (design_id in all_designs)
|
||||
TEST_FAIL("Design [design] shares an ID \"[design_id]\" with another design")
|
||||
continue
|
||||
all_designs[design_id] = design
|
||||
|
||||
for (var/datum/techweb_node/node as anything in subtypesof(/datum/techweb_node))
|
||||
node = new node()
|
||||
for (var/design_id in node.design_ids)
|
||||
if (!all_designs[design_id])
|
||||
TEST_FAIL("Techweb node [node.display_name] ([node.id]) has a design_id \"[design_id]\" which doesn't correspond to any existing design!")
|
||||
continue
|
||||
all_designs -= design_id
|
||||
qdel(node)
|
||||
|
||||
// Designs can also be disk-exclusive
|
||||
for (var/obj/item/disk/design_disk/design_disk as anything in subtypesof(/obj/item/disk/design_disk))
|
||||
design_disk = new design_disk()
|
||||
for (var/datum/design/design as anything in design_disk.blueprints)
|
||||
all_designs -= design.id
|
||||
qdel(design_disk)
|
||||
|
||||
for (var/obj/item/disk/surgery/design_disk as anything in subtypesof(/obj/item/disk/surgery))
|
||||
design_disk = new design_disk()
|
||||
for (var/surgery_type as anything in design_disk.surgeries)
|
||||
for (var/design_id in all_designs)
|
||||
var/datum/design/surgery/design = all_designs[design_id]
|
||||
if (ispath(design, /datum/design/surgery) && design::surgery == surgery_type)
|
||||
all_designs -= design::id
|
||||
qdel(design_disk)
|
||||
|
||||
// Or machine-exclusive
|
||||
for (var/datum/techweb/autounlocking/techweb as anything in subtypesof(/datum/techweb/autounlocking))
|
||||
techweb = new techweb()
|
||||
for (var/design_id in techweb.researched_designs + techweb.hacked_designs)
|
||||
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
|
||||
// If we have a design thats supposed to be printable from a protolathe and an autolathe, but only autolathes can print it
|
||||
// then we still should error because then we either have a missing design_id or redundant build flags
|
||||
if (!(design.build_type & (~techweb.allowed_buildtypes)))
|
||||
all_designs -= design_id
|
||||
qdel(techweb)
|
||||
|
||||
for (var/missing_id in all_designs)
|
||||
TEST_FAIL("Design [all_designs[missing_id]] has an ID \"[missing_id]\" which is not in any of the techweb nodes or tech disks, or it is possibly misconfigured!")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.4 KiB |
Reference in New Issue
Block a user