Merge pull request #8879 from VOREStation/master

August 28th 2020 Release
This commit is contained in:
Novacat
2020-08-28 18:18:36 -04:00
committed by GitHub
945 changed files with 166389 additions and 207622 deletions
+11
View File
@@ -0,0 +1,11 @@
# This list auto requests reviews from the specified org members
# when a PR that modifies the file in question is opened
# This list is alphabetized by User -> Filename KEEP IT THAT WAY
# In the event that multiple org members are to be informed of changes
# to the same file or dir, add them to the end under Multiple Owners
# ShadowLarkens
/code/__DEFINES/tgui.dm @ShadowLarkens
/code/controllers/subsystem/tgui.dm @ShadowLarkens
/code/modules/tgui @ShadowLarkens
/tgui @ShadowLarkens
@@ -103,7 +103,7 @@
if(ATM_P)
return "phoron"
if(ATM_N2O)
return "sleeping_agent"
return "nitrous_oxide"
else
return null
@@ -24,7 +24,7 @@
1: Oxygen: Oxygen ONLY
2: Nitrogen: Nitrogen ONLY
3: Carbon Dioxide: Carbon Dioxide ONLY
4: Sleeping Agent (N2O)
4: Nitrous Oxide (Formerly called Sleeping Agent) (N2O)
*/
var/filter_type = -1
var/list/filtered_out = list()
@@ -51,7 +51,7 @@
if(3) //removing CO2
filtered_out = list("carbon_dioxide")
if(4)//removing N2O
filtered_out = list("sleeping_agent")
filtered_out = list("nitrous_oxide")
air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
@@ -216,7 +216,7 @@
if(3) //removing CO2
filtered_out += "carbon_dioxide"
if(4)//removing N2O
filtered_out += "sleeping_agent"
filtered_out += "nitrous_oxide"
add_fingerprint(usr)
update_icon()
@@ -107,7 +107,7 @@
"filter_n2" = ("nitrogen" in scrubbing_gas),
"filter_co2" = ("carbon_dioxide" in scrubbing_gas),
"filter_phoron" = ("phoron" in scrubbing_gas),
"filter_n2o" = ("sleeping_agent" in scrubbing_gas),
"filter_n2o" = ("nitrous_oxide" in scrubbing_gas),
"filter_fuel" = ("volatile_fuel" in scrubbing_gas),
"sigtype" = "status"
)
@@ -230,10 +230,10 @@
else if(signal.data["toggle_tox_scrub"])
toggle += "phoron"
if(!isnull(signal.data["n2o_scrub"]) && text2num(signal.data["n2o_scrub"]) != ("sleeping_agent" in scrubbing_gas))
toggle += "sleeping_agent"
if(!isnull(signal.data["n2o_scrub"]) && text2num(signal.data["n2o_scrub"]) != ("nitrous_oxide" in scrubbing_gas))
toggle += "nitrous_oxide"
else if(signal.data["toggle_n2o_scrub"])
toggle += "sleeping_agent"
toggle += "nitrous_oxide"
if(!isnull(signal.data["fuel_scrub"]) && text2num(signal.data["fuel_scrub"]) != ("volatile_fuel" in scrubbing_gas))
toggle += "volatile_fuel"
+1 -1
View File
@@ -157,7 +157,7 @@
air_temporary.volume = volume
air_temporary.temperature = T0C
air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
air_temporary.adjust_gas("nitrous_oxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "n2o"
+28
View File
@@ -0,0 +1,28 @@
/// Module is compatible with Security Cyborg models
#define BORG_MODULE_SECURITY (1<<0)
/// Module is compatible with Miner Cyborg models
#define BORG_MODULE_MINER (1<<1)
/// Module is compatible with Janitor Cyborg models
#define BORG_MODULE_JANITOR (1<<2)
/// Module is compatible with Medical Cyborg models
#define BORG_MODULE_MEDICAL (1<<3)
/// Module is compatible with Engineering Cyborg models
#define BORG_MODULE_ENGINEERING (1<<4)
/// Module is compatible with Ripley Exosuit models
#define EXOSUIT_MODULE_RIPLEY (1<<0)
/// Module is compatible with Odyseeus Exosuit models
#define EXOSUIT_MODULE_ODYSSEUS (1<<1)
/// Module is compatible with Gygax Exosuit models
#define EXOSUIT_MODULE_GYGAX (1<<2)
/// Module is compatible with Durand Exosuit models
#define EXOSUIT_MODULE_DURAND (1<<3)
/// Module is compatible with Phazon Exosuit models
#define EXOSUIT_MODULE_PHAZON (1<<4)
/// Module is compatible with "Working" Exosuit models - Ripley
#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY
/// Module is compatible with "Combat" Exosuit models - Gygax, Durand and Phazon
#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS
+4
View File
@@ -463,10 +463,13 @@ var/global/list/##LIST_NAME = list();\
#define FONT_GIANT(X) "<font size='5'>[X]</font>"
// Volume Channel Defines
#define VOLUME_CHANNEL_MASTER "Master"
#define VOLUME_CHANNEL_AMBIENCE "Ambience"
#define VOLUME_CHANNEL_ALARMS "Alarms"
#define VOLUME_CHANNEL_VORE "Vore"
#define VOLUME_CHANNEL_DOORS "Doors"
// Make sure you update this or clients won't be able to adjust the channel
GLOBAL_LIST_INIT(all_volume_channels, list(
@@ -474,4 +477,5 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
VOLUME_CHANNEL_AMBIENCE,
VOLUME_CHANNEL_ALARMS,
VOLUME_CHANNEL_VORE,
VOLUME_CHANNEL_DOORS,
))
+47 -6
View File
@@ -70,7 +70,9 @@
// Restricted, military, or mercenary aligned locations like the armory, the merc ship/base, BSD, etc.
#define AMBIENCE_HIGHSEC list(\
'sound/ambience/highsec/highsec1.ogg',\
'sound/ambience/highsec/highsec2.ogg'\
'sound/ambience/highsec/highsec2.ogg',\
'sound/ambience/highsec/highsec3.ogg',\
'sound/ambience/highsec/highsec4.ogg'\
)
// Ruined structures found on the surface or in the caves.
@@ -108,14 +110,19 @@
#define AMBIENCE_GENERIC list(\
'sound/ambience/generic/generic1.ogg',\
'sound/ambience/generic/generic2.ogg',\
'sound/ambience/generic/generic3.ogg',\
'sound/ambience/generic/generic4.ogg'\
'sound/ambience/generic/generic3.ogg'\
)
// 'sound/ambience/generic/generic4.ogg'\ // VOREStation Edit: Comment out entry 4 as this doesn't fit on Virgo, and we have our own weather system.
// Sounds of PA announcements, presumably involving shuttles?
#define AMBIENCE_ARRIVALS list(\
'sound/ambience/arrivals/arrivals1.ogg',\
'sound/ambience/arrivals/arrivals2.ogg'\
'sound/ambience/arrivals/arrivals2.ogg',\
'sound/ambience/arrivals/arrivals3.ogg',\
'sound/ambience/arrivals/arrivals4.ogg',\
'sound/ambience/arrivals/arrivals5.ogg',\
'sound/ambience/arrivals/arrivals6.ogg',\
'sound/ambience/arrivals/arrivals7.ogg'\
)
// Sounds suitable for being inside dark, tight corridors in the underbelly of the station.
@@ -124,7 +131,11 @@
'sound/ambience/maintenance/maintenance2.ogg',\
'sound/ambience/maintenance/maintenance3.ogg',\
'sound/ambience/maintenance/maintenance4.ogg',\
'sound/ambience/maintenance/maintenance5.ogg'\
'sound/ambience/maintenance/maintenance5.ogg',\
'sound/ambience/maintenance/maintenance6.ogg',\
'sound/ambience/maintenance/maintenance7.ogg',\
'sound/ambience/maintenance/maintenance8.ogg',\
'sound/ambience/maintenance/maintenance9.ogg'\
)
// Life support machinery at work, keeping everyone breathing.
@@ -136,7 +147,9 @@
// Creepy AI/borg stuff.
#define AMBIENCE_AI list(\
'sound/ambience/ai/ai1.ogg'\
'sound/ambience/ai/ai1.ogg',\
'sound/ambience/ai/ai2.ogg',\
'sound/ambience/ai/ai3.ogg'\
)
// Peaceful sounds when floating in the void.
@@ -179,4 +192,32 @@
// For the memes.
#define AMBIENCE_AESTHETIC list(\
'sound/ambience/vaporwave.ogg'\
)
#define AMBIENCE_OUTPOST list(\
'sound/ambience/expoutpost/expoutpost1.ogg',\
'sound/ambience/expoutpost/expoutpost2.ogg',\
'sound/ambience/expoutpost/expoutpost3.ogg',\
'sound/ambience/expoutpost/expoutpost4.ogg'\
)
#define AMBIENCE_SUBSTATION list(\
'sound/ambience/substation/substation1.ogg',\
'sound/ambience/substation/substation2.ogg'\
)
#define AMBIENCE_HANGAR list(\
'sound/ambience/hangar/hangar1.ogg',\
'sound/ambience/hangar/hangar2.ogg',\
'sound/ambience/hangar/hangar3.ogg',\
'sound/ambience/hangar/hangar4.ogg',\
'sound/ambience/hangar/hangar5.ogg',\
'sound/ambience/hangar/hangar6.ogg'\
)
#define AMBIENCE_ATMOS list(\
'sound/ambience/engineering/engineering1.ogg',\
'sound/ambience/engineering/engineering2.ogg',\
'sound/ambience/engineering/engineering3.ogg',\
'sound/ambience/atmospherics/atmospherics1.ogg'\
)
+3 -1
View File
@@ -49,7 +49,9 @@
#define LANGUAGE_SIIK "Siik"
#define LANGUAGE_SKRELLIAN "Common Skrellian"
#define LANGUAGE_TRADEBAND "Tradeband"
#define LANGUAGE_GUTTER "Gutter"
//VOREStation edit 08/23/20
#define LANGUAGE_GUTTER "Gutterband"
//VS edit end
#define LANGUAGE_SIGN "Sign Language"
#define LANGUAGE_SCHECHI "Schechi"
#define LANGUAGE_ROOTLOCAL "Local Rootspeak"
+2
View File
@@ -57,6 +57,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_SKYBOX 30
#define INIT_ORDER_MAPPING 25
#define INIT_ORDER_DECALS 20
#define INIT_ORDER_PLANTS 18 // Must initialize before atoms.
#define INIT_ORDER_JOB 17
#define INIT_ORDER_ALARM 16 // Must initialize before atoms.
#define INIT_ORDER_ATOMS 15
@@ -87,6 +88,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_SUPPLY 5
#define FIRE_PRIORITY_NIGHTSHIFT 5
#define FIRE_PRIORITY_PLANTS 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
+1
View File
@@ -49,6 +49,7 @@
#define DIGSITE_TECHNICAL 4
#define DIGSITE_TEMPLE 5
#define DIGSITE_WAR 6
#define DIGSITE_MIDDEN 7
#define EFFECT_TOUCH 0
#define EFFECT_AURA 1
+1 -1
View File
@@ -12,7 +12,7 @@
clear_fullscreen(category, FALSE)
screen = null
else if(!severity || severity == screen.severity)
return null
return screen
if(!screen)
screen = new type()
+40
View File
@@ -633,3 +633,43 @@
/obj/screen/setup_preview/bg/Click(params)
pref?.bgstate = next_in_list(pref.bgstate, pref.bgstate_options)
pref?.update_preview_icon()
/obj/screen/splash
screen_loc = "1,1"
layer = LAYER_HUD_ABOVE
plane = PLANE_PLAYER_HUD_ABOVE
var/client/holder
/obj/screen/splash/New(client/C, visible)
. = ..()
holder = C
if(!visible)
alpha = 0
if(!lobby_image)
qdel(src)
return
icon = lobby_image.icon
icon_state = lobby_image.icon_state
holder.screen += src
/obj/screen/splash/proc/Fade(out, qdel_after = TRUE)
if(QDELETED(src))
return
if(out)
animate(src, alpha = 0, time = 30)
else
alpha = 0
animate(src, alpha = 255, time = 30)
if(qdel_after)
QDEL_IN(src, 30)
/obj/screen/splash/Destroy()
if(holder)
holder.screen -= src
holder = null
return ..()
File diff suppressed because it is too large Load Diff
-3
View File
@@ -3,7 +3,6 @@
//
/datum/configuration
var/static/list/engine_map // Comma separated list of engines to choose from. Blank means fully random.
var/static/time_off = FALSE
var/static/pto_job_change = FALSE
var/static/limit_interns = -1 //Unlimited by default
@@ -42,8 +41,6 @@
config.chat_webhook_url = value
if ("chat_webhook_key")
config.chat_webhook_key = value
if ("engine_map")
config.engine_map = splittext(value, ",")
if ("fax_export_dir")
config.fax_export_dir = value
if ("items_survive_digestion")
+96 -1
View File
@@ -6,6 +6,12 @@ SUBSYSTEM_DEF(mapping)
var/list/map_templates = list()
var/dmm_suite/maploader = null
var/obj/effect/landmark/engine_loader/engine_loader
var/list/shelter_templates = list()
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT // Make extra sure we don't initialize twice.
shelter_templates = SSmapping.shelter_templates
/datum/controller/subsystem/mapping/Initialize(timeofday)
if(subsystem_initialized)
@@ -17,7 +23,15 @@ SUBSYSTEM_DEF(mapping)
if(config.generate_map)
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
using_map.perform_map_generation()
loadEngine()
preloadShelterTemplates() // VOREStation EDIT: Re-enable Shelter Capsules
// Mining generation probably should be here too
// TODO - Other stuff related to maps and areas could be moved here too. Look at /tg
// Lateload Code related to Expedition areas.
if(using_map) // VOREStation Edit: Re-enable this.
loadLateMaps()
..()
/datum/controller/subsystem/mapping/proc/load_map_templates()
for(var/T in subtypesof(/datum/map_template))
@@ -27,3 +41,84 @@ SUBSYSTEM_DEF(mapping)
template = new T()
map_templates[template.name] = template
return TRUE
/datum/controller/subsystem/mapping/proc/loadEngine()
if(!engine_loader)
return // Seems this map doesn't need an engine loaded.
var/turf/T = get_turf(engine_loader)
if(!isturf(T))
to_world_log("[log_info_line(engine_loader)] not on a turf! Cannot place engine template.")
return
// Choose an engine type
var/datum/map_template/engine/chosen_type = null
if (LAZYLEN(config.engine_map))
var/chosen_name = pick(config.engine_map)
chosen_type = map_templates[chosen_name]
if(!istype(chosen_type))
error("Configured engine map [chosen_name] is not a valid engine map name!")
if(!istype(chosen_type))
var/list/engine_types = list()
for(var/map in map_templates)
var/datum/map_template/engine/MT = map_templates[map]
if(istype(MT))
engine_types += MT
chosen_type = pick(engine_types)
to_world_log("Chose Engine Map: [chosen_type.name]")
admin_notice("<span class='danger'>Chose Engine Map: [chosen_type.name]</span>", R_DEBUG)
// Annihilate movable atoms
engine_loader.annihilate_bounds()
//CHECK_TICK //Don't let anything else happen for now
// Actually load it
chosen_type.load(T)
// VOREStation Edit Start: Enable This
/datum/controller/subsystem/mapping/proc/loadLateMaps()
var/list/deffo_load = using_map.lateload_z_levels
var/list/maybe_load = using_map.lateload_single_pick
for(var/list/maplist in deffo_load)
if(!islist(maplist))
error("Lateload Z level [maplist] is not a list! Must be in a list!")
continue
for(var/mapname in maplist)
var/datum/map_template/MT = map_templates[mapname]
if(!istype(MT))
error("Lateload Z level \"[mapname]\" is not a valid map!")
continue
MT.load_new_z(centered = FALSE)
CHECK_TICK
if(LAZYLEN(maybe_load))
var/picklist = pick(maybe_load)
if(!picklist) //No lateload maps at all
return
if(!islist(picklist)) //So you can have a 'chain' of z-levels that make up one away mission
error("Randompick Z level [picklist] is not a list! Must be in a list!")
return
for(var/map in picklist)
var/datum/map_template/MT = map_templates[map]
if(!istype(MT))
error("Randompick Z level \"[map]\" is not a valid map!")
else
MT.load_new_z(centered = FALSE)
/datum/controller/subsystem/mapping/proc/preloadShelterTemplates()
for(var/item in subtypesof(/datum/map_template/shelter))
var/datum/map_template/shelter/shelter_type = item
if(!(initial(shelter_type.mappath)))
continue
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
// VOREStation Edit End: Re-enable this
/datum/controller/subsystem/mapping/stat_entry(msg)
if (!Debug2)
return // Only show up in stat panel if debugging is enabled.
. = ..()
-124
View File
@@ -1,124 +0,0 @@
//
// Mapping subsystem handles initialization of random map elements at server start
// On VOREStation that means loading our random roundstart engine!
//
SUBSYSTEM_DEF(mapping)
name = "Mapping"
init_order = INIT_ORDER_MAPPING
flags = SS_NO_FIRE
var/list/map_templates = list()
var/dmm_suite/maploader = null
var/obj/effect/landmark/engine_loader/engine_loader
var/list/shelter_templates = list()
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT // Make extra sure we don't initialize twice.
shelter_templates = SSmapping.shelter_templates
/datum/controller/subsystem/mapping/Initialize(timeofday)
if(subsystem_initialized)
return
world.max_z_changed() // This is to set up the player z-level list, maxz hasn't actually changed (probably)
maploader = new()
load_map_templates()
if(config.generate_map)
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
using_map.perform_map_generation()
loadEngine()
preloadShelterTemplates()
// Mining generation probably should be here too
// TODO - Other stuff related to maps and areas could be moved here too. Look at /tg
if(using_map)
loadLateMaps()
..()
/datum/controller/subsystem/mapping/proc/load_map_templates()
for(var/T in subtypesof(/datum/map_template))
var/datum/map_template/template = T
if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence.
continue
template = new T()
map_templates[template.name] = template
return TRUE
/datum/controller/subsystem/mapping/proc/loadEngine()
if(!engine_loader)
return // Seems this map doesn't need an engine loaded.
var/turf/T = get_turf(engine_loader)
if(!isturf(T))
to_world_log("[log_info_line(engine_loader)] not on a turf! Cannot place engine template.")
return
// Choose an engine type
var/datum/map_template/engine/chosen_type = null
if (LAZYLEN(config.engine_map))
var/chosen_name = pick(config.engine_map)
chosen_type = map_templates[chosen_name]
if(!istype(chosen_type))
error("Configured engine map [chosen_name] is not a valid engine map name!")
if(!istype(chosen_type))
var/list/engine_types = list()
for(var/map in map_templates)
var/datum/map_template/engine/MT = map_templates[map]
if(istype(MT))
engine_types += MT
chosen_type = pick(engine_types)
to_world_log("Chose Engine Map: [chosen_type.name]")
admin_notice("<span class='danger'>Chose Engine Map: [chosen_type.name]</span>", R_DEBUG)
// Annihilate movable atoms
engine_loader.annihilate_bounds()
//CHECK_TICK //Don't let anything else happen for now
// Actually load it
chosen_type.load(T)
/datum/controller/subsystem/mapping/proc/loadLateMaps()
var/list/deffo_load = using_map.lateload_z_levels
var/list/maybe_load = using_map.lateload_single_pick
for(var/list/maplist in deffo_load)
if(!islist(maplist))
error("Lateload Z level [maplist] is not a list! Must be in a list!")
continue
for(var/mapname in maplist)
var/datum/map_template/MT = map_templates[mapname]
if(!istype(MT))
error("Lateload Z level \"[mapname]\" is not a valid map!")
continue
MT.load_new_z(centered = FALSE)
CHECK_TICK
if(LAZYLEN(maybe_load))
var/picklist = pick(maybe_load)
if(!picklist) //No lateload maps at all
return
if(!islist(picklist)) //So you can have a 'chain' of z-levels that make up one away mission
error("Randompick Z level [picklist] is not a list! Must be in a list!")
return
for(var/map in picklist)
var/datum/map_template/MT = map_templates[map]
if(!istype(MT))
error("Randompick Z level \"[map]\" is not a valid map!")
else
MT.load_new_z(centered = FALSE)
/datum/controller/subsystem/mapping/proc/preloadShelterTemplates()
for(var/item in subtypesof(/datum/map_template/shelter))
var/datum/map_template/shelter/shelter_type = item
if(!(initial(shelter_type.mappath)))
continue
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
/datum/controller/subsystem/mapping/stat_entry(msg)
if (!Debug2)
return // Only show up in stat panel if debugging is enabled.
. = ..()
@@ -1,32 +1,12 @@
// Attempts to offload processing for the spreading plants from the MC.
// Processes vines/spreading plants.
#define PLANTS_PER_TICK 500 // Cap on number of plant segments processed.
#define PLANT_TICK_TIME 75 // Number of ticks between the plant processor cycling.
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
SUBSYSTEM_DEF(plants)
name = "Plants"
init_order = INIT_ORDER_PLANTS
priority = FIRE_PRIORITY_PLANTS
wait = PLANT_TICK_TIME
if(!holder) return
if(!plant_controller || !plant_controller.gene_tag_masks)
to_chat(usr, "Gene masks not set.")
return
for(var/mask in plant_controller.gene_tag_masks)
to_chat(usr, "[mask]: [plant_controller.gene_tag_masks[mask]]")
var/global/datum/controller/plants/plant_controller // Set in New().
/datum/controller/plants
var/plants_per_tick = PLANTS_PER_TICK
var/plant_tick_time = PLANT_TICK_TIME
var/list/product_descs = list() // Stores generated fruit descs.
var/list/plant_queue = list() // All queued plants.
var/list/seeds = list() // All seed data stored here.
var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
var/list/plant_icon_cache = list() // Stores images of growth, fruits and seeds.
@@ -34,24 +14,26 @@ var/global/datum/controller/plants/plant_controller // Set in New().
var/list/accessible_plant_sprites = list() // List of all plant sprites allowed to appear in random generation.
var/list/plant_product_sprites = list() // List of all harvested product sprites.
var/list/accessible_product_sprites = list() // List of all product sprites allowed to appear in random generation.
var/processing = 0 // Off/on.
var/list/gene_masked_list = list() // Stored gene masked list, rather than recreating it when needed.
var/list/plant_gene_datums = list() // Stored datum versions of the gene masked list.
/datum/controller/plants/New()
if(plant_controller && plant_controller != src)
log_debug("Rebuilding plant controller.")
qdel(plant_controller)
plant_controller = src
// To be clear, the only thing this processes are spreading plants
// Hydro trays and growing food normally just chill in SSobj
var/list/processing = list()
var/list/currentrun = list()
/datum/controller/subsystem/plants/stat_entry()
..("P:[processing.len]|S:[seeds.len]")
/datum/controller/subsystem/plants/Initialize(timeofday)
setup()
process()
return ..()
// Predefined/roundstart varieties use a string key to make it
// easier to grab the new variety when mutating. Post-roundstart
// and mutant varieties use their uid converted to a string instead.
// Looks like shit but it's sort of necessary.
/datum/controller/plants/proc/setup()
/datum/controller/subsystem/plants/proc/setup()
// Build the icon lists.
for(var/icostate in cached_icon_states('icons/obj/hydroponics_growing.dmi'))
var/split = findtext(icostate,"-")
@@ -116,10 +98,10 @@ var/global/datum/controller/plants/plant_controller // Set in New().
gene_masked_list.Add(list(list("tag" = gene_tag, "mask" = gene_mask)))
// Proc for creating a random seed type.
/datum/controller/plants/proc/create_random_seed(var/survive_on_station)
/datum/controller/subsystem/plants/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = plant_controller.seeds.len + 1
seed.uid = SSplants.seeds.len + 1
seed.name = "[seed.uid]"
seeds[seed.name] = seed
@@ -138,32 +120,41 @@ var/global/datum/controller/plants/plant_controller // Set in New().
seed.set_trait(TRAIT_HIGHKPA_TOLERANCE,200)
return seed
/datum/controller/plants/process()
processing = 1
spawn(0)
set background = 1
var/processed = 0
while(1)
if(!processing)
sleep(plant_tick_time)
else
processed = 0
if(plant_queue.len)
var/target_to_process = min(plant_queue.len,plants_per_tick)
for(var/x=0;x<target_to_process;x++)
if(!plant_queue.len)
break
var/obj/effect/plant/plant = pick(plant_queue)
plant_queue -= plant
if(!istype(plant))
continue
plant.process()
processed++
sleep(1) // Stagger processing out so previous tick can resolve (overlapping plant segments etc)
sleep(max(1,(plant_tick_time-processed)))
/datum/controller/subsystem/plants/fire(resumed = 0)
if(!resumed)
src.currentrun = processing.Copy()
/datum/controller/plants/proc/add_plant(var/obj/effect/plant/plant)
plant_queue |= plant
// Caching
var/list/currentrun = src.currentrun
while(currentrun.len)
var/obj/effect/plant/P = currentrun[currentrun.len]
--currentrun.len
if(!P || QDELETED(P))
continue
P.process()
/datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant)
plant_queue -= plant
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/plants/proc/add_plant(var/obj/effect/plant/plant)
processing |= plant
/datum/controller/subsystem/plants/proc/remove_plant(var/obj/effect/plant/plant)
processing -= plant
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
if(!holder) return
if(!SSplants || !SSplants.gene_tag_masks)
to_chat(usr, "Gene masks not set.")
return
for(var/mask in SSplants.gene_tag_masks)
to_chat(usr, "[mask]: [SSplants.gene_tag_masks[mask]]")
+9 -5
View File
@@ -78,6 +78,7 @@ var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/proc/pregame_welcome()
to_world("<span class='boldannounce notice'><em>Welcome to the pregame lobby!</em></span>")
to_world("<span class='boldannounce notice'>Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.</span>")
world << sound('sound/misc/server-ready.ogg', volume = 100)
// Called during GAME_STATE_PREGAME (RUNLEVEL_LOBBY)
/datum/controller/subsystem/ticker/proc/pregame_tick()
@@ -402,20 +403,23 @@ var/global/datum/controller/subsystem/ticker/ticker
for(var/mob/new_player/player in player_list)
if(player && player.ready && player.mind?.assigned_role)
var/datum/job/J = SSjob.get_job(player.mind.assigned_role)
// Snowflakey AI treatment
if(J?.mob_type & JOB_SILICON_AI)
player.close_spawn_windows()
player.AIize(move = TRUE)
continue
// Ask their new_player mob to spawn them
if(!player.spawn_checks_vr(player.mind.assigned_role)) continue //VOREStation Add
var/mob/living/carbon/human/new_char = player.create_character()
// Created their playable character, delete their /mob/new_player
if(new_char)
qdel(player)
if(new_char.client)
var/obj/screen/splash/S = new(new_char.client, TRUE)
S.Fade(TRUE)
// If they're a carbon, they can get manifested
if(J?.mob_type & JOB_CARBON)
@@ -431,7 +435,7 @@ var/global/datum/controller/subsystem/ticker/ticker
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Colony Director")
if(player.mind.assigned_role == "Site Manager")
captainless=0
if(!player_is_antag(player.mind, only_offstation_roles = 1))
job_master.EquipRank(player, player.mind.assigned_role, 0)
@@ -441,7 +445,7 @@ var/global/datum/controller/subsystem/ticker/ticker
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
to_chat(M, "<span class='notice'>Colony Directorship not forced on anyone.</span>")
to_chat(M, "<span class='notice'>Site Management is not forced on anyone.</span>")
/datum/controller/subsystem/ticker/proc/declare_completion()
-1
View File
@@ -97,7 +97,6 @@
options["LEGACY: cameranet"] = cameranet
options["LEGACY: transfer_controller"] = transfer_controller
options["LEGACY: gas_data"] = gas_data
options["LEGACY: plant_controller"] = plant_controller
var/pick = input(mob, "Choose a controller to debug/view variables of.", "VV controller:") as null|anything in options
if(!pick)
+30 -30
View File
@@ -48,7 +48,7 @@
/datum/category_item/autolathe/arms/pistol_5mm
name = "pistol magazine (5mm)"
path =/obj/item/ammo_magazine/c5mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
*/
@@ -237,93 +237,93 @@
/datum/category_item/autolathe/arms/pistol_5mm
name = "pistol magazine (5mm)"
path =/obj/item/ammo_magazine/c5mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/smg_5mm
name = "top-mounted SMG magazine (5mm)"
path =/obj/item/ammo_magazine/c5mmt/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_45
name = "pistol magazine (.45)"
path =/obj/item/ammo_magazine/m45/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_45uzi
name = "uzi magazine (.45)"
path =/obj/item/ammo_magazine/m45uzi/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/tommymag
name = "Tommy Gun magazine (.45)"
path =/obj/item/ammo_magazine/m45tommy/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/tommydrum
name = "Tommy Gun drum magazine (.45)"
path =/obj/item/ammo_magazine/m45tommydrum/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_9mm
name = "pistol magazine (9mm)"
path =/obj/item/ammo_magazine/m9mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/smg_9mm
name = "top-mounted SMG magazine (9mm)"
path =/obj/item/ammo_magazine/m9mmt/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/smg_10mm
name = "SMG magazine (10mm)"
path =/obj/item/ammo_magazine/m10mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_44
name = "pistol magazine (.44)"
path =/obj/item/ammo_magazine/m44/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_545
name = "10rnd rifle magazine (5.45mm)"
path =/obj/item/ammo_magazine/m545saw/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/rifle_545m
name = "20rnd rifle magazine (5.45mm)"
path =/obj/item/ammo_magazine/m545sawm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_SVD
name = "10rnd rifle magazine (7.62mm)"
path =/obj/item/ammo_magazine/m762svd/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_762
name = "20rnd rifle magazine (7.62mm)"
path =/obj/item/ammo_magazine/m762/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/machinegun_762
name = "machinegun box magazine (7.62)"
path =/obj/item/ammo_magazine/a762/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/shotgun_magazine
name = "24rnd shotgun magazine (12g)"
path =/obj/item/ammo_magazine/m12gdrum/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1*/
///////////////////////////////
@@ -357,73 +357,73 @@
/*/datum/category_item/autolathe/arms/pistol_clip_45
name = "ammo clip (.45)"
path =/obj/item/ammo_magazine/clip/c45
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_45r
name = "ammo clip (.45 rubber)"
path =/obj/item/ammo_magazine/clip/c45/rubber
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_45f
name = "ammo clip (.45 flash)"
path =/obj/item/ammo_magazine/clip/c45/flash
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_45p
name = "ammo clip (.45 practice)"
path =/obj/item/ammo_magazine/clip/c45/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mm
name = "ammo clip (9mm)"
path =/obj/item/ammo_magazine/clip/c9mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_9mmr
name = "ammo clip (9mm rubber)"
path =/obj/item/ammo_magazine/clip/c9mm/rubber
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mmp
name = "ammo clip (9mm practice)"
path =/obj/item/ammo_magazine/clip/c9mm/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mmf
name = "ammo clip (9mm flash)"
path =/obj/item/ammo_magazine/clip/c9mm/flash
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_5mm
name = "ammo clip (5mm)"
path =/obj/item/ammo_magazine/clip/c5mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_10mm
name = "ammo clip (10mm)"
path =/obj/item/ammo_magazine/clip/c10mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_50
name = "ammo clip (.44)"
path =/obj/item/ammo_magazine/clip/c50
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
*/
/datum/category_item/autolathe/arms/rifle_clip_545
name = "ammo clip (5.45mm)"
path =/obj/item/ammo_magazine/clip/c545
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_clip_545_practice
name = "ammo clip (5.45mm practice)"
path =/obj/item/ammo_magazine/clip/c545/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/rifle_clip_762
name = "ammo clip (7.62mm)"
-2
View File
@@ -1,5 +1,3 @@
var/datum/category_collection/autolathe/autolathe_recipes
/datum/category_item/autolathe/New()
..()
var/obj/item/I = new path()
+1 -1
View File
@@ -218,7 +218,7 @@ var/global/list/PDA_Manifest = list()
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
depthead = 1
if(rank=="Colony Director" && heads.len != 1)
if(rank=="Site Manager" && heads.len != 1)
heads.Swap(1,heads.len)
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SECURITY))
+3 -1
View File
@@ -28,6 +28,8 @@
var/volume = 100
var/max_loops
var/direct
var/vary
var/extra_range
var/opacity_check
var/pref_check
@@ -89,7 +91,7 @@
continue
SEND_SOUND(thing, S)
else
playsound(thing, S, volume, ignore_walls = !opacity_check, preference = pref_check)
playsound(thing, S, volume, vary, extra_range, ignore_walls = !opacity_check, preference = pref_check)
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
if(!_mid_sounds)
+59 -9
View File
@@ -9,9 +9,10 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/supermatter
mid_sounds = list('sound/machines/sm/supermatter1.ogg'=1,'sound/machines/sm/supermatter2.ogg'=1,'sound/machines/sm/supermatter3.ogg'=1)
mid_length = 10
volume = 1
mid_sounds = list('sound/machines/sm/loops/calm.ogg'=1)
mid_length = 60
volume = 40
extra_range = 10
pref_check = /datum/client_preference/supermatter_hum
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -28,25 +29,74 @@
/datum/looping_sound/deep_fryer
start_sound = 'sound/machines/fryer/deep_fryer_immerse.ogg' //my immersions
start_sound = 'sound/machines/kitchen/fryer/deep_fryer_immerse.ogg' //my immersions
start_length = 10
mid_sounds = list('sound/machines/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/fryer/deep_fryer_2.ogg' = 1)
mid_sounds = list('sound/machines/kitchen/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/kitchen/fryer/deep_fryer_2.ogg' = 1)
mid_length = 2
end_sound = 'sound/machines/fryer/deep_fryer_emerge.ogg'
end_sound = 'sound/machines/kitchen/fryer/deep_fryer_emerge.ogg'
volume = 15
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/microwave
start_sound = 'sound/machines/microwave/microwave-start.ogg'
start_sound = 'sound/machines/kitchen/microwave/microwave-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/microwave/microwave-mid1.ogg'=10, 'sound/machines/microwave/microwave-mid2.ogg'=1)
mid_sounds = list('sound/machines/kitchen/microwave/microwave-mid1.ogg'=10, 'sound/machines/kitchen/microwave/microwave-mid2.ogg'=1)
mid_length = 10
end_sound = 'sound/machines/microwave/microwave-end.ogg'
end_sound = 'sound/machines/kitchen/microwave/microwave-end.ogg'
volume = 90
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/oven
start_sound = 'sound/machines/kitchen/oven/oven-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/kitchen/oven/oven-mid1.ogg'=10)
mid_length = 40
end_sound = 'sound/machines/kitchen/oven/oven-stop.ogg'
volume = 50
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/grill
start_sound = 'sound/machines/kitchen/grill/grill-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/kitchen/grill/grill-mid1.ogg'=10)
mid_length = 40
end_sound = 'sound/machines/kitchen/grill/grill-stop.ogg'
volume = 50
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/mixer
start_sound = 'sound/machines/kitchen/mixer/mixer-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/kitchen/mixer/mixer-mid1.ogg'=10)
mid_length = 10
end_sound = 'sound/machines/kitchen/mixer/mixer-stop.ogg'
volume = 50
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/cerealmaker
start_sound = 'sound/machines/kitchen/cerealmaker/cerealmaker-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/kitchen/cerealmaker/cerealmaker-mid1.ogg'=10)
mid_length = 60
end_sound = 'sound/machines/kitchen/cerealmaker/cerealmaker-stop.ogg'
volume = 50
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/candymaker
start_sound = 'sound/machines/kitchen/candymaker/candymaker-start.ogg'
start_length = 10
mid_sounds = list('sound/machines/kitchen/candymaker/candymaker-mid1.ogg'=10)
mid_length = 40
end_sound = 'sound/machines/kitchen/candymaker/candymaker-stop.ogg'
volume = 20
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/air_pump
start_sound = 'sound/machines/air_pump/airpumpstart.ogg'
start_length = 10
+2 -2
View File
@@ -50,13 +50,13 @@
access = access_atmospherics
contains = list(/obj/machinery/portable_atmospherics/canister/phoron)
/datum/supply_pack/atmos/canister_sleeping_agent
/datum/supply_pack/atmos/canister_nitrous_oxide
name = "N2O gas canister"
cost = 15
containername = "N2O gas canister crate"
containertype = /obj/structure/closet/crate/secure/large/aether
access = access_atmospherics
contains = list(/obj/machinery/portable_atmospherics/canister/sleeping_agent)
contains = list(/obj/machinery/portable_atmospherics/canister/nitrous_oxide)
/datum/supply_pack/atmos/canister_carbon_dioxide
name = "Carbon dioxide gas canister"
+1 -1
View File
@@ -101,7 +101,7 @@
/obj/item/clothing/under/lawyer/bluesuit,
/obj/item/clothing/under/lawyer/purpsuit,
/obj/item/clothing/shoes/black = 2,
/obj/item/clothing/shoes/leather,
/obj/item/clothing/shoes/laceup/brown,
/obj/item/clothing/accessory/wcoat
)
name = "Formalwear (Suits)"
+22 -2
View File
@@ -174,7 +174,7 @@
/obj/item/clothing/under/pants/chaps,
/obj/item/clothing/under/pants/chaps/black,
/obj/item/clothing/under/harness,
/obj/item/clothing/shoes/leather,
/obj/item/clothing/shoes/laceup/brown,
/obj/item/clothing/shoes/boots/jungle,
/obj/item/clothing/shoes/boots/jackboots,
/obj/item/clothing/shoes/boots/cowboy,
@@ -261,4 +261,24 @@
)
cost = 60
containertype = /obj/structure/closet/crate
containername = "Saddlebags crate"
containername = "Saddlebags crate"
/datum/supply_pack/costumes/knights_gear
name = "Knights Gear"
contains = list(
/obj/item/clothing/suit/storage/hooded/knight_costume,
/obj/item/clothing/suit/storage/hooded/knight_costume/galahad,
/obj/item/clothing/suit/storage/hooded/knight_costume/lancelot,
/obj/item/clothing/suit/storage/hooded/knight_costume/robin,
/obj/item/clothing/suit/armor/combat/crusader_costume,
/obj/item/clothing/suit/armor/combat/crusader_costume/bedevere,
/obj/item/clothing/head/helmet/combat/crusader_costume,
/obj/item/clothing/head/helmet/combat/bedevere_costume,
/obj/item/clothing/gloves/combat/knight_costume,
/obj/item/clothing/gloves/combat/knight_costume/brown,
/obj/item/clothing/shoes/knight_costume,
/obj/item/clothing/shoes/knight_costume/black
)
cost = 10
containertype = /obj/structure/closet/crate
containername = "Knights Gear Crate"
+8 -11
View File
@@ -54,19 +54,12 @@
containertype = /obj/structure/largecrate
containername = "cooking oil tank crate"
/datum/supply_pack/randomised/hospitality/
group = "Hospitality"
/datum/supply_pack/randomised/hospitality/pizza
/datum/supply_pack/hospitality/pizza
name = "Surprise pack of five pizzas"
contains = list(
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox = 5,
/obj/item/weapon/material/knife/plastic
)
name = "Surprise pack of five pizzas"
cost = 15
containertype = /obj/structure/closet/crate/freezer/centauri
containername = "Pizza crate"
@@ -83,4 +76,8 @@
)
cost = 10
containertype = /obj/structure/closet/crate/allico
containername = "crate of gifts"
containername = "crate of gifts"
/datum/supply_pack/randomised/hospitality/
group = "Hospitality"
+3
View File
@@ -25,6 +25,7 @@
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.hacked = !mend
A.update_tgui_static_data(usr)
if(WIRE_ELECTRIFY)
A.shocked = !mend
if(WIRE_AUTOLATHE_DISABLE)
@@ -38,9 +39,11 @@
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.hacked = !A.hacked
A.update_tgui_static_data(usr)
spawn(50)
if(A && !is_cut(wire))
A.hacked = 0
A.update_tgui_static_data(usr)
if(WIRE_ELECTRIFY)
A.shocked = !A.shocked
spawn(50)
+4 -4
View File
@@ -43,12 +43,12 @@
flags = XGM_GAS_FUEL
/decl/xgm_gas/sleeping_agent
id = "sleeping_agent"
name = "Sleeping Agent"
/decl/xgm_gas/nitrous_oxide
id = "nitrous_oxide"
name = "Nitrous Oxide"
specific_heat = 40 // J/(mol*K)
molar_mass = 0.044 // kg/mol. N2O
tile_overlay = "sleeping_agent"
tile_overlay = "nitrous_oxide"
overlay_limit = 1
flags = XGM_GAS_OXIDIZER
+1
View File
@@ -97,6 +97,7 @@
throw_speed = 1
throw_range = 20
drop_sound = 'sound/items/drop/rubber.ogg'
pickup_sound = 'sound/items/pickup/rubber.ogg'
afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
user.drop_item()
+2
View File
@@ -79,6 +79,8 @@
/obj/item/weapon/disk
name = "disk"
icon = 'icons/obj/discs_vr.dmi' //VOREStation Edit
drop_sound = 'sound/items/drop/disk.ogg'
pickup_sound = 'sound/items/pickup/disk.ogg'
/obj/item/weapon/disk/nuclear
name = "nuclear authentication disk"
+3 -3
View File
@@ -6,7 +6,7 @@ var/datum/antagonist/mutineer/mutineers
role_text_plural = "Mutineers"
id = MODE_MUTINEER
antag_indicator = "mutineer"
restricted_jobs = list("Colony Director")
restricted_jobs = list("Site Manager")
/datum/antagonist/mutineer/New(var/no_reference)
..()
@@ -39,7 +39,7 @@ var/datum/antagonist/mutineer/mutineers
proc/get_head_loyalist_candidates()
var/list/candidates[0]
for(var/mob/loyalist in player_list)
if(loyalist.mind && loyalist.mind.assigned_role == "Colony Director")
if(loyalist.mind && loyalist.mind.assigned_role == "Site Manager")
candidates.Add(loyalist.mind)
return candidates
@@ -47,7 +47,7 @@ var/datum/antagonist/mutineer/mutineers
var/list/candidates[0]
for(var/mob/mutineer in player_list)
if(mutineer.client.prefs.be_special & BE_MUTINEER)
for(var/job in command_positions - "Colony Director")
for(var/job in command_positions - "Site Manager")
if(mutineer.mind && mutineer.mind.assigned_role == job)
candidates.Add(mutineer.mind)
return candidates
+1 -1
View File
@@ -14,7 +14,7 @@ var/datum/antagonist/ert/ert
and before taking extreme actions, please try to also contact the administration! \
Think through your actions and make the roleplay immersive! <b>Please remember all \
rules aside from those without explicit exceptions apply to the ERT.</b>"
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to the Company, and have authority to override the Colony Director where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the Colony Director where possible, however."
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to the Company, and have authority to override the Site Manager where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the Site Manager where possible, however."
landmark_id = "Response Team"
id_type = /obj/item/weapon/card/id/centcom/ERT
+1 -1
View File
@@ -6,7 +6,7 @@
bantype = "changeling"
feedback_tag = "changeling_objective"
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Site Manager")
welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
antag_sound = 'sound/effects/antag_notice/ling_alert.ogg'
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
+2 -2
View File
@@ -13,8 +13,8 @@ var/datum/antagonist/cultist/cult
bantype = "cultist"
restricted_jobs = list("Chaplain")
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Colony Director")
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Site Manager")
role_type = BE_CULTIST
feedback_tag = "cult_objective"
antag_indicator = "cult"
+1 -1
View File
@@ -11,7 +11,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
role_text = "Infiltrator"
role_text_plural = "Infiltrators"
welcome_text = "To speak on your team's private channel, use :t."
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = TRUE
@@ -30,8 +30,8 @@ var/datum/antagonist/revolutionary/revs
faction_invisible = 1
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
roundstart_restricted = list("Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Site Manager", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
roundstart_restricted = list("Internal Affairs Agent", "Site Manager", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
/datum/antagonist/revolutionary/New()
..()
+1 -1
View File
@@ -4,7 +4,7 @@ var/datum/antagonist/traitor/traitors
/datum/antagonist/traitor
id = MODE_TRAITOR
antag_sound = 'sound/effects/antag_notice/traitor_alert.ogg'
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = FALSE // If they want to plot and plan as this sort of traitor, they'll need to do it ICly.
+9 -1
View File
@@ -280,6 +280,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/centcom/bathroom
name = "\improper CentCom Bathroom"
icon_state = "centcom_crew"
sound_env = SMALL_ENCLOSED
//SYNDICATES
@@ -736,6 +737,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Substation"
icon_state = "substation"
sound_env = SMALL_ENCLOSED
ambience = AMBIENCE_SUBSTATION
/area/maintenance/substation/engineering // Probably will be connected to engineering SMES room, as wires cannot be crossed properly without them sharing powernets.
name = "Engineering Substation"
@@ -950,7 +952,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
sound_env = MEDIUM_SOFTFLOOR
/area/crew_quarters/captain
name = "\improper Command - Colony Director's Office"
name = "\improper Command - Site Manager's Office"
icon_state = "captain"
sound_env = MEDIUM_SOFTFLOOR
@@ -1207,6 +1209,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/recreation_area_restroom
name = "\improper Recreation Area Restroom"
icon_state = "recreation_area_restroom"
sound_env = SMALL_ENCLOSED
/area/crew_quarters/pool
name = "\improper Pool"
@@ -1232,6 +1235,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/barrestroom
name = "\improper Cafeteria Restroom"
icon_state = "bar"
sound_env = SMALL_ENCLOSED
/area/crew_quarters/theatre
name = "\improper Theatre"
@@ -1381,6 +1385,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Atmospherics"
icon_state = "atmos"
sound_env = LARGE_ENCLOSED
ambience = AMBIENCE_ATMOS
/area/engineering/atmos/monitoring
name = "\improper Atmospherics Monitoring Room"
@@ -1603,6 +1608,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/medical_restroom
name = "\improper Medbay Restroom"
icon_state = "medbay_restroom"
sound_env = SMALL_ENCLOSED
/area/medical/patients_rooms
name = "\improper Patient's Rooms"
@@ -1796,6 +1802,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/security/security_bathroom
name = "\improper Security - Restroom"
icon_state = "security_bathroom"
sound_env = SMALL_ENCLOSED
/area/security/security_cell_hallway
name = "\improper Security - Cell Hallway"
@@ -1944,6 +1951,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/rnd/research_restroom
name = "\improper Research Restroom"
icon_state = "research_restroom"
sound_env = SMALL_ENCLOSED
/area/rnd/research_storage
name = "\improper Research Storage"
+3 -1
View File
@@ -488,7 +488,7 @@
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/atom/proc/visible_message(var/message, var/blind_message)
/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs = null)
//VOREStation Edit
var/list/see
@@ -501,6 +501,8 @@
var/list/seeing_mobs = see["mobs"]
var/list/seeing_objs = see["objs"]
if(LAZYLEN(exclude_mobs))
seeing_mobs -= exclude_mobs
for(var/obj in seeing_objs)
var/obj/O = obj
+2
View File
@@ -7,6 +7,8 @@
force = 30
throwforce = 10
hitsound = 'sound/weapons/bladeslice.ogg'
drop_sound = 'sound/items/drop/sword.ogg'
pickup_sound = 'sound/items/pickup/sword.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
edge = 1
sharp = 1
+2 -2
View File
@@ -297,9 +297,9 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
M.add_ion_law("HUMANS NEED TO EAT [what2pref] [what2] TO SURVIVE")
if(5)
to_chat(M, "<br>")
to_chat(M, "<span class='danger'>THE COLONY DIRECTOR, HOP AND HOS ARE [who2]...LAWS UPDATED</span>")
to_chat(M, "<span class='danger'>THE SITE MANAGER, HOP AND HOS ARE [who2]...LAWS UPDATED</span>")
to_chat(M, "<br>")
M.add_ion_law("THE COLONY DIRECTOR, HOP AND HOS ARE [who2]")
M.add_ion_law("THE SITE MANAGER, HOP AND HOS ARE [who2]")
if(6)
to_chat(M, "<br>")
to_chat(M, "<span class='danger'>THE STATION IS BUILT FOR [who2]...LAWS UPDATED</span>")
+1 -1
View File
@@ -564,7 +564,7 @@ datum
captainslaser
steal_target = /obj/item/weapon/gun/energy/captain
explanation_text = "Steal the Colony Director's antique laser gun."
explanation_text = "Steal the Site Manager's antique laser gun."
weight = 20
get_points(var/job)
+3 -3
View File
@@ -427,11 +427,11 @@ datum/objective/steal
var/target_name
var/global/possible_items[] = list(
"the Colony Director's antique laser gun" = /obj/item/weapon/gun/energy/captain,
"the Site Manager's antique laser gun" = /obj/item/weapon/gun/energy/captain,
"a hand teleporter" = /obj/item/weapon/hand_tele,
"an RCD" = /obj/item/weapon/rcd,
"a jetpack" = /obj/item/weapon/tank/jetpack,
"a colony director's jumpsuit" = /obj/item/clothing/under/rank/captain,
"a site manager's jumpsuit" = /obj/item/clothing/under/rank/captain,
"a functional AI" = /obj/item/device/aicard,
"a pair of magboots" = /obj/item/clothing/shoes/magboots,
"the station blueprints" = /obj/item/blueprints,
@@ -445,7 +445,7 @@ datum/objective/steal
"a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security,
"a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel,
"the hypospray" = /obj/item/weapon/reagent_containers/hypospray/vial,
"the colony director's pinpointer" = /obj/item/weapon/pinpointer,
"the site manager's pinpointer" = /obj/item/weapon/pinpointer,
"an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof,
)
+1 -1
View File
@@ -127,7 +127,7 @@
/var/const/access_captain = 20
/datum/access/captain
id = access_captain
desc = "Colony Director"
desc = "Site Manager"
region = ACCESS_REGION_COMMAND
/var/const/access_all_personal_lockers = 21
+5 -9
View File
@@ -5,7 +5,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
//////////////////////////////////
/datum/job/captain
title = "Colony Director"
title = "Site Manager"
flag = CAPTAIN
departments = list(DEPARTMENT_COMMAND)
sorting_order = 3 // Above everyone.
@@ -26,11 +26,10 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
ideal_character_age = 70 // Old geezer captains ftw
outfit_type = /decl/hierarchy/outfit/job/captain
job_description = "The Colony Director manages the other Command Staff, and through them the rest of the station. Though they have access to everything, \
they do not understand everything, and are expected to delegate tasks to the appropriate crew member. The Colony Director is expected to \
job_description = "The Site Manager manages the other Command Staff, and through them the rest of the station. Though they have access to everything, \
they do not understand everything, and are expected to delegate tasks to the appropriate crew member. The Site Manager is expected to \
have an understanding of Standard Operating Procedure, and is subject to it, and legal action, in the same way as every other crew member."
alt_titles = list("Site Manager" = /datum/alt_title/site_manager,
"Overseer" = /datum/alt_title/overseer)
alt_titles = list("Overseer"= /datum/alt_title/overseer)
/*
/datum/job/captain/equip(var/mob/living/carbon/human/H)
@@ -44,9 +43,6 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
// Captain Alt Titles
/datum/alt_title/site_manager
title = "Site Manager"
/datum/alt_title/overseer
title = "Overseer"
@@ -63,7 +59,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Colony Director"
supervisors = "the Site Manager"
selection_color = "#1D1D4F"
req_admin_notify = 1
minimal_player_age = 10
+1 -1
View File
@@ -11,7 +11,7 @@
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Colony Director"
supervisors = "the Site Manager"
selection_color = "#7F6E2C"
req_admin_notify = 1
economic_modifier = 10
+1 -1
View File
@@ -11,7 +11,7 @@
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Colony Director"
supervisors = "the Site Manager"
selection_color = "#026865"
req_admin_notify = 1
economic_modifier = 10
+1 -1
View File
@@ -11,7 +11,7 @@
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Colony Director"
supervisors = "the Site Manager"
selection_color = "#AD6BAD"
req_admin_notify = 1
economic_modifier = 15
+5
View File
@@ -18,6 +18,11 @@
alt_titles = list("Xenoarchaeologist" = /datum/alt_title/xenoarch, "Anomalist" = /datum/alt_title/anomalist, \
"Phoron Researcher" = /datum/alt_title/phoron_research, "Circuit Designer" = /datum/alt_title/circuit_designer)
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch, access_xenobotany)
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch) // Unchanged (for now?), mostly here for reference
/datum/alt_title/circuit_designer
title = "Circuit Designer"
title_blurb = "A Circuit Designer is a Scientist whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
+1 -1
View File
@@ -11,7 +11,7 @@
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Colony Director"
supervisors = "the Site Manager"
selection_color = "#8E2929"
req_admin_notify = 1
economic_modifier = 10
+7 -7
View File
@@ -394,7 +394,7 @@ var/global/datum/controller/occupations/job_master
var/datum/gear/G = gear_datums[thing]
if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile)
continue
var/permitted
// Check if it is restricted to certain roles
if(G.allowed_roles)
@@ -435,13 +435,13 @@ var/global/datum/controller/occupations/job_master
// Set up their account
job.setup_account(H)
// Equip job items.
job.equip(H, H.mind ? H.mind.role_alt_title : "")
// Stick their fingerprints on literally everything
job.apply_fingerprints(H)
// Only non-silicons get post-job-equip equipment
if(!(job.mob_type & JOB_SILICON))
H.equip_post_job()
@@ -487,11 +487,11 @@ var/global/datum/controller/occupations/job_master
return H.Robotize()
if(job.mob_type & JOB_SILICON_AI)
return H
// TWEET PEEP
if(rank == "Colony Director")
if(rank == "Site Manager")
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Site Manager"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
+3
View File
@@ -57,6 +57,7 @@
M.forceMove(src)
occupant = M
update_icon() //icon_state = "body_scanner_1" //VOREStation Edit - Health display for consoles with light and such.
playsound(src, 'sound/machines/medbayscanner1.ogg', 50) // Beepboop you're being scanned. <3
add_fingerprint(user)
qdel(G)
SStgui.update_uis(src)
@@ -101,6 +102,7 @@
O.forceMove(src)
occupant = O
update_icon() //icon_state = "body_scanner_1" //VOREStation Edit - Health display for consoles with light and such.
playsound(src, 'sound/machines/medbayscanner1.ogg', 50) // Beepboop you're being scanned. <3
add_fingerprint(user)
SStgui.update_uis(src)
@@ -332,6 +334,7 @@
if("print_p")
var/atom/target = console ? console : src
visible_message("<span class='notice'>[target] rattles and prints out a sheet of paper.</span>")
playsound(src, 'sound/machines/printer.ogg', 50, 1)
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(target))
var/name = occupant ? occupant.name : "Unknown"
P.info = "<CENTER><B>Body Scan - [name]</B></CENTER><BR>"
+1 -1
View File
@@ -66,7 +66,7 @@
var/datum/radio_frequency/radio_connection
var/list/TLV = list()
var/list/trace_gas = list("sleeping_agent", "volatile_fuel") //list of other gases that this air alarm is able to detect
var/list/trace_gas = list("nitrous_oxide", "volatile_fuel") //list of other gases that this air alarm is able to detect
var/danger_level = 0
var/pressure_dangerlevel = 0
+6 -6
View File
@@ -26,7 +26,7 @@
/obj/machinery/portable_atmospherics/canister/drain_power()
return -1
/obj/machinery/portable_atmospherics/canister/sleeping_agent
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
name = "Canister: \[N2O\]"
icon_state = "redws"
canister_color = "redws"
@@ -88,7 +88,7 @@
name = "Canister \[CO2\]"
icon_state = "black"
canister_color = "black"
/obj/machinery/portable_atmospherics/canister/empty/sleeping_agent
/obj/machinery/portable_atmospherics/canister/empty/nitrous_oxide
name = "Canister \[N2O\]"
icon_state = "redws"
canister_color = "redws"
@@ -390,17 +390,17 @@ update_flag
src.update_icon()
return 1
/obj/machinery/portable_atmospherics/canister/sleeping_agent/New()
/obj/machinery/portable_atmospherics/canister/nitrous_oxide/New()
..()
air_contents.adjust_gas("sleeping_agent", MolesForPressure())
air_contents.adjust_gas("nitrous_oxide", MolesForPressure())
src.update_icon()
return 1
//Dirty way to fill room with gas. However it is a bit easier to do than creating some floor/engine/n2o -rastaf0
/obj/machinery/portable_atmospherics/canister/sleeping_agent/roomfiller/Initialize()
/obj/machinery/portable_atmospherics/canister/nitrous_oxide/roomfiller/Initialize()
. = ..()
air_contents.gas["sleeping_agent"] = 9*4000
air_contents.gas["nitrous_oxide"] = 9*4000
var/turf/simulated/location = src.loc
if (istype(src.loc))
location.assume_air(air_contents)
+1 -1
View File
@@ -18,7 +18,7 @@
var/minrate = 0
var/maxrate = 10 * ONE_ATMOSPHERE
var/list/scrubbing_gas = list("phoron", "carbon_dioxide", "sleeping_agent", "volatile_fuel")
var/list/scrubbing_gas = list("phoron", "carbon_dioxide", "nitrous_oxide", "volatile_fuel")
/obj/machinery/portable_atmospherics/powered/scrubber/New()
..()
+142 -147
View File
@@ -11,10 +11,10 @@
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/static/datum/category_collection/autolathe/autolathe_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
@@ -33,6 +33,8 @@
/obj/machinery/autolathe/Initialize()
. = ..()
if(!autolathe_recipes)
autolathe_recipes = new()
wires = new(src)
default_apply_parts()
RefreshParts()
@@ -42,87 +44,77 @@
wires = null
return ..()
/obj/machinery/autolathe/proc/update_recipe_list()
if(!machine_recipes)
if(!autolathe_recipes)
autolathe_recipes = new()
machine_recipes = autolathe_recipes
current_category = machine_recipes.categories[1]
/obj/machinery/autolathe/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Autolathe", name)
ui.open()
/obj/machinery/autolathe/interact(mob/user as mob)
update_recipe_list()
/obj/machinery/autolathe/tgui_status(mob/user)
if(disabled)
return STATUS_CLOSE
return ..()
if(..() || (disabled && !panel_open))
/obj/machinery/autolathe/tgui_static_data(mob/user)
var/list/data = ..()
var/list/categories = list()
var/list/recipes = list()
for(var/datum/category_group/autolathe/A in autolathe_recipes.categories)
categories += A.name
for(var/datum/category_item/autolathe/M in A.items)
if(M.hidden && !hacked)
continue
if(M.man_rating > man_rating)
continue
recipes.Add(list(list(
"category" = A.name,
"name" = M.name,
"ref" = REF(M),
"requirements" = M.resources,
"hidden" = M.hidden,
"coeff_applies" = !M.no_scale,
)))
data["recipes"] = recipes
data["categories"] = categories
return data
/obj/machinery/autolathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
/obj/machinery/autolathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/material_data = list()
for(var/mat_id in stored_material)
var/amount = stored_material[mat_id]
var/list/material_info = list(
"name" = mat_id,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT
)
material_data += list(material_info)
data["busy"] = busy
data["materials"] = material_data
data["mat_efficiency"] = mat_efficiency
return data
/obj/machinery/autolathe/interact(mob/user)
if(panel_open)
return wires.Interact(user)
if(disabled)
to_chat(user, "<span class='danger'>\The [src] is disabled!</span>")
return
if(shocked)
shock(user, 50)
var/list/dat = list()
dat += "<center><h1>Autolathe Control Panel</h1><hr/>"
if(!disabled)
dat += "<table width = '100%'>"
var/list/material_top = list("<tr>")
var/list/material_bottom = list("<tr>")
for(var/material in stored_material)
if(material != DEFAULT_WALL_MATERIAL && material != MAT_GLASS) // Don't show the Extras unless people care enough to put them in.
if(stored_material[material] <= 0)
continue
material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
dat += "[material_top.Join()]</tr>[material_bottom.Join()]</tr></table><hr>"
dat += "<b>Filter:</b> <a href='?src=\ref[src];setfilter=1'>[filtertext ? filtertext : "None Set"]</a><br>"
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked) // Illegal or nonstandard.
continue
if(R.man_rating > man_rating) // Advanced parts.
continue
if(filtertext && findtext(R.name, filtertext) == 0)
continue
var/can_make = 1
var/list/material_string = list()
var/list/multiplier_string = list()
var/max_sheets
var/comma
if(!R.resources || !R.resources.len)
material_string += "No resources required.</td>"
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
var/coeff = (R.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(R.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(R.resources[material]*coeff))
can_make = 0
if(!comma)
comma = 1
else
material_string += ", "
material_string += "[round(R.resources[material] * coeff)] [material]"
material_string += ".<br></td>"
//Build list of multipliers for sheets.
if(R.is_stack)
if(max_sheets && max_sheets > 0)
max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type.
multiplier_string += "<br>"
for(var/i = 5;i<max_sheets;i*=2) //5,10,20,40...
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[i]'>\[x[i]\]</a>"
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[max_sheets]'>\[x[max_sheets]\]</a>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : "<span class='linkOff'>"][R.name][can_make ? "</a>" : "</span>"]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string.Join()]</td><td align = right>[material_string.Join()]</tr>"
dat += "</table><hr>"
dat = jointext(dat, null)
var/datum/browser/popup = new(user, "autolathe", "Autolathe Production Menu", 550, 700)
popup.set_content(dat)
popup.open()
tgui_interact(user)
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
@@ -130,7 +122,7 @@
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
interact(user)
return
if(default_deconstruction_crowbar(user, O))
return
@@ -155,18 +147,6 @@
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38) || istype (O,/obj/item/ammo_magazine/s44)/* VOREstation Edit*/) // Prevents ammo recycling exploit with speedloaders.
to_chat(user, "\The [O] is too hazardous to recycle with the autolathe!")
return
/* ToDo: Make this actually check for ammo and change the value of the magazine if it's empty. -Spades
var/obj/item/ammo_magazine/speedloader = O
if(speedloader.stored_ammo)
to_chat(user, "\The [speedloader] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return
else
speedloader.matter = list(DEFAULT_WALL_MATERIAL = 75) // It's just a hunk of scrap metal now.
if(istype(O,/obj/item/ammo_magazine)) // This was just for immersion consistency with above.
var/obj/item/ammo_magazine/mag = O
if(mag.stored_ammo)
to_chat(user, "\The [mag] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return*/
//Resources are being loaded.
var/obj/item/eating = O
@@ -227,9 +207,9 @@
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
/obj/machinery/autolathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
usr.set_machine(src)
add_fingerprint(usr)
@@ -237,72 +217,69 @@
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
return
switch(action)
if("make")
var/datum/category_item/autolathe/making = locate(params["make"])
if(!istype(making))
return
if(making.hidden && !hacked)
return
else if(href_list["setfilter"])
var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", filtertext) as null|text
if(!Adjacent(usr))
return
if(isnull(filterstring)) //Clicked Cancel
return
if(filterstring == "") //Cleared value
filtertext = null
filtertext = sanitize(filterstring, 25)
var/multiplier = 1
if(href_list["change_category"])
if(making.is_stack)
var/max_sheets
for(var/material in making.resources)
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(making.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(making.resources[material]*coeff))
max_sheets = 0
//Build list of multipliers for sheets.
multiplier = input(usr, "How many do you want to print? (0-[max_sheets])") as num|null
if(!multiplier || multiplier <= 0 || multiplier > max_sheets || tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
busy = making.name
update_use_power(USE_POWER_ACTIVE)
if(href_list["make"] && machine_recipes)
var/multiplier = text2num(href_list["multiplier"])
var/datum/category_item/autolathe/making = locate(href_list["make"]) in current_category.items
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
//Exploit detection, not sure if necessary after rewrite.
if(!making || multiplier < 0 || multiplier > 100)
var/turf/exploit_loc = get_turf(usr)
message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate an item! ([exploit_loc ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[exploit_loc.x];Y=[exploit_loc.y];Z=[exploit_loc.z]'>JMP</a>" : "null"])", 0)
log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate an item!")
return
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
busy = 1
update_use_power(USE_POWER_ACTIVE)
update_icon() // So lid closes
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
sleep(build_time)
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
update_icon() // So lid closes
//Sanity check.
if(!making || !src)
return
sleep(build_time)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
if(!making || !src) return
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
updateUsrDialog()
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
return TRUE
return FALSE
/obj/machinery/autolathe/update_icon()
overlays.Cut()
@@ -332,6 +309,7 @@
storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
update_tgui_static_data(usr)
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
@@ -345,3 +323,20 @@
qdel(S)
..()
return 1
/obj/machinery/autolathe/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
var/material/M = get_material_by_name(matstring)
var/obj/item/stack/material/S = M.place_sheet(get_turf(src))
if(amount <= 0)
amount = S.max_amount
var/ejected = min(round(stored_material[matstring] / S.perunit), amount)
S.amount = min(ejected, amount)
if(S.amount <= 0)
qdel(S)
return
stored_material[matstring] -= ejected * S.perunit
if(recursive && stored_material[matstring] >= S.perunit)
eject_materials(matstring, -1)
+178 -185
View File
@@ -1,3 +1,17 @@
// Use this define to register something as a creatable!
// * n - The proper name of the purchasable
// * o - The object type path of the purchasable to spawn
// * r - The amount to dispense
// * p - The price of the purchasable in biomass
#define BIOGEN_ITEM(n, o, r, p) n = new /datum/data/biogenerator_item(n, o, r, p)
// Use this define to register something as dispensable
// * n - The proper name of the purchasable
// * o - The reagent ID
// * r - The amount of reagent to dispense
// * p - The price of the purchasable in biomass
#define BIOGEN_REAGENT(n, o, r, p) n = new /datum/data/biogenerator_reagent(n, o, r, p)
/obj/machinery/biogenerator
name = "biogenerator"
desc = "Converts plants into biomass, which can be used for fertilizer and sort-of-synthetic products."
@@ -11,10 +25,34 @@
var/processing = 0
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/points = 0
var/menustat = "menu"
var/build_eff = 1
var/eat_eff = 1
var/list/item_list
/datum/data/biogenerator_item
var/equipment_path = null
var/equipment_amt = 1
var/cost = 0
/datum/data/biogenerator_item/New(name, path, amt, cost)
src.name = name
src.equipment_path = path
src.equipment_amt = amt
src.cost = cost
/datum/data/biogenerator_reagent
var/reagent_id = null
var/reagent_amt = 0
var/cost = 0
/datum/data/biogenerator_reagent/New(name, id, amt, cost)
src.name = name
src.reagent_id = id
src.reagent_amt = amt
src.cost = cost
/obj/machinery/biogenerator/Initialize()
. = ..()
var/datum/reagents/R = new/datum/reagents(1000)
@@ -24,6 +62,139 @@
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
default_apply_parts()
item_list = list()
item_list["Food Items"] = list(
BIOGEN_REAGENT("10 milk", "milk", 10, 20),
BIOGEN_REAGENT("50 milk", "milk", 50, 95),
BIOGEN_REAGENT("10 Cream", "cream", 10, 30),
BIOGEN_REAGENT("50 Cream", "cream", 50, 120),
BIOGEN_ITEM("Slab of meat", /obj/item/weapon/reagent_containers/food/snacks/meat, 1, 50),
BIOGEN_ITEM("5 slabs of meat", /obj/item/weapon/reagent_containers/food/snacks/meat, 5, 250),
)
item_list["Cooking Ingredients"] = list(
BIOGEN_REAGENT("10 Universal Enzyme", "enzyme", 10, 30),
BIOGEN_REAGENT("50 Universal Enzyme", "enzyme", 50, 120),
BIOGEN_ITEM("Nutri-spread", /obj/item/weapon/reagent_containers/food/snacks/spreads, 1, 30),
BIOGEN_ITEM("5 nutri-spread", /obj/item/weapon/reagent_containers/food/snacks/spreads, 5, 120),
)
item_list["Gardening Nutrients"] = list(
BIOGEN_ITEM("E-Z-Nutrient", /obj/item/weapon/reagent_containers/glass/bottle/eznutrient, 1, 60),
BIOGEN_ITEM("5 E-Z-Nutrient", /obj/item/weapon/reagent_containers/glass/bottle/eznutrient, 5, 300),
BIOGEN_ITEM("Left 4 Zed", /obj/item/weapon/reagent_containers/glass/bottle/left4zed, 1, 120),
BIOGEN_ITEM("5 Left 4 Zed", /obj/item/weapon/reagent_containers/glass/bottle/left4zed, 5, 600),
BIOGEN_ITEM("Robust Harvest", /obj/item/weapon/reagent_containers/glass/bottle/robustharvest, 1, 150),
BIOGEN_ITEM("5 Robust Harvest", /obj/item/weapon/reagent_containers/glass/bottle/robustharvest, 5, 750),
)
item_list["Leather Products"] = list(
BIOGEN_ITEM("Wallet", /obj/item/weapon/storage/wallet, 1, 100),
BIOGEN_ITEM("Botanical gloves", /obj/item/clothing/gloves/botanic_leather, 1, 250),
BIOGEN_ITEM("Plant bag", /obj/item/weapon/storage/bag/plants, 1, 320),
BIOGEN_ITEM("Large plant bag", /obj/item/weapon/storage/bag/plants/large, 1, 640),
BIOGEN_ITEM("Utility belt", /obj/item/weapon/storage/belt/utility, 1, 300),
BIOGEN_ITEM("Leather Satchel", /obj/item/weapon/storage/backpack/satchel, 1, 400),
BIOGEN_ITEM("Cash Bag", /obj/item/weapon/storage/bag/cash, 1, 400),
BIOGEN_ITEM("Chemistry Bag", /obj/item/weapon/storage/bag/chemistry, 1, 400),
BIOGEN_ITEM("Workboots", /obj/item/clothing/shoes/boots/workboots, 1, 400),
BIOGEN_ITEM("Leather Chaps", /obj/item/clothing/under/pants/chaps, 1, 400),
BIOGEN_ITEM("Leather Coat", /obj/item/clothing/suit/leathercoat, 1, 500),
BIOGEN_ITEM("Leather Jacket", /obj/item/clothing/suit/storage/toggle/brown_jacket, 1, 500),
BIOGEN_ITEM("Winter Coat", /obj/item/clothing/suit/storage/hooded/wintercoat, 1, 500),
//VOREStation Edit - Algae for oxygen generator
BIOGEN_ITEM("4 Algae Sheets", /obj/item/stack/material/algae, 4, 400),
)
/obj/machinery/biogenerator/tgui_static_data(mob/user)
var/list/static_data[0]
// Available items - in static data because we don't wanna compute this list every time! It hardly changes.
static_data["items"] = list()
for(var/cat in item_list)
var/list/cat_items = list()
for(var/prize_name in item_list[cat])
var/datum/data/biogenerator_reagent/prize = item_list[cat][prize_name]
cat_items[prize_name] = list("name" = prize_name, "price" = prize.cost, "reagent" = istype(prize))
static_data["items"][cat] = cat_items
return static_data
/obj/machinery/biogenerator/tgui_data(mob/user)
var/list/data = ..()
data["build_eff"] = build_eff
data["points"] = points
data["processing"] = processing
data["beaker"] = !!beaker
return data
/obj/machinery/biogenerator/tgui_interact(mob/user, datum/tgui/ui = null)
// Open the window
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Biogenerator", name)
ui.open()
/obj/machinery/biogenerator/tgui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("activate")
INVOKE_ASYNC(src, .proc/activate)
return TRUE
if("detach")
if(beaker)
beaker.forceMove(loc)
beaker = null
update_icon()
return TRUE
if("purchase")
var/category = params["cat"] // meow
var/name = params["name"]
if(!(category in item_list) || !(name in item_list[category])) // Not trying something that's not in the list, are you?
return
var/datum/data/biogenerator_item/bi = item_list[category][name]
if(!istype(bi))
var/datum/data/biogenerator_reagent/br = item_list[category][name]
if(!istype(br))
return
if(!beaker)
return
var/cost = round(br.cost / build_eff)
if(cost > points)
to_chat(usr, "<span class='danger'>Insufficient biomass.</span>")
return
var/amt_to_actually_dispense = round(min(beaker.reagents.get_free_space(), br.reagent_amt))
if(amt_to_actually_dispense <= 0)
to_chat(usr, "<span class='danger'>The loaded beaker is full!</span>")
return
points -= (cost * (amt_to_actually_dispense / br.reagent_amt))
beaker.reagents.add_reagent(br.reagent_id, amt_to_actually_dispense)
playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
return
var/cost = round(bi.cost / build_eff)
if(cost > points)
to_chat(usr, "<span class='danger'>Insufficient biomass.</span>")
return
points -= cost
if(ispath(bi.equipment_path, /obj/item/stack))
var/obj/item/stack/S = new bi.equipment_path(loc)
S.amount = bi.equipment_amt
playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1)
return TRUE
for(var/i in 1 to bi.equipment_amt)
new bi.equipment_path(loc)
playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1)
return TRUE
else
return FALSE
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
@@ -87,68 +258,10 @@
update_icon()
return
/obj/machinery/biogenerator/interact(mob/user as mob)
/obj/machinery/biogenerator/attack_hand(mob/user as mob)
if(stat & BROKEN)
return
user.set_machine(src)
var/dat = "<TITLE>Biogenerator</TITLE>Biogenerator:<BR>"
if(processing)
dat += "<FONT COLOR=red>Biogenerator is processing! Please wait...</FONT>"
else
dat += "Biomass: [points] points.<HR>"
switch(menustat)
if("menu")
if(beaker)
dat += "<A href='?src=\ref[src];action=activate'>Activate Biogenerator!</A><BR>"
dat += "<A href='?src=\ref[src];action=detach'>Detach Container</A><BR><BR>"
dat += "Food Items:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=milk;cost=20'>10 milk</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=milk5;cost=95'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=cream;cost=30'>10 cream</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=cream5;cost=120'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=meat;cost=50'>Slab of meat</A> <FONT COLOR=blue>([round(50/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=meat5;cost=250'>x5</A><BR>"
dat += "Cooking Ingredient:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=30'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme50;cost=120'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=nutrispread;cost=30'>Nutri-Spread</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=nutrispread5;cost=120'>x5</A><BR>"
// dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=50'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme;cost=180'>x5</A><BR>"
// dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=50'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme;cost=180'>x5</A><BR>"
dat += "Gardening Nutrients:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=60'>E-Z-Nutrient</A> <FONT COLOR=green>([round(60/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=300'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=120'>Left 4 Zed</A> <FONT COLOR=green>([round(120/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=600'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=150'>Robust Harvest</A> <FONT COLOR=green>([round(150/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=750'>x5</A><BR>"
dat += "Leather Products:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=wallet;cost=100'>Wallet</A> <FONT COLOR=brown>([round(100/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=gloves;cost=250'>Botanical gloves</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=plantbag;cost=320'>Plant bag</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=plantbaglarge;cost=640'>Large plant bag</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=tbelt;cost=300'>Utility belt</A> <FONT COLOR=brown>([round(300/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=satchel;cost=400'>Leather Satchel</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=cashbag;cost=400'>Cash Bag</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=chembag;cost=400'>Chemistry Bag</A> <FONT COLOR=green>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=workboots;cost=400'>Workboots</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leathershoes;cost=400'>Leather Shoes</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leatherchaps;cost=400'>Leather Chaps</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leathercoat;cost=500'>Leather Coat</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leatherjacket;cost=500'>Leather Jacket</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=wintercoat;cost=500'>Winter Coat</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=algae;cost=400'>4 Algae Sheets</A> <FONT COLOR=green>([round(400/build_eff)])</FONT><BR>" //VOREStation Edit - Algae for oxygen generator
//dat += "Other<BR>"
//dat += "<A href='?src=\ref[src];action=create;item=monkey;cost=500'>Monkey</A> <FONT COLOR=blue>(500)</FONT><BR>"
else
dat += "<BR><FONT COLOR=red>No beaker inside. Please insert a beaker.</FONT><BR>"
if("nopoints")
dat += "You do not have biomass to create products.<BR>Please, put growns into reactor and activate it.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
if("complete")
dat += "Operation complete.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
if("void")
dat += "<FONT COLOR=red>Error: No growns inside.</FONT><BR>Please, put growns into reactor.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
user << browse(dat, "window=biogenerator")
onclose(user, "biogenerator")
return
/obj/machinery/biogenerator/attack_hand(mob/user as mob)
interact(user)
tgui_interact(user)
/obj/machinery/biogenerator/proc/activate()
if(usr.stat)
@@ -168,139 +281,17 @@
if(S)
processing = 1
update_icon()
updateUsrDialog()
playsound(src, 'sound/machines/blender.ogg', 40, 1)
use_power(S * 30)
sleep((S + 15) / eat_eff)
processing = 0
SStgui.update_uis(src)
playsound(src, 'sound/machines/biogenerator_end.ogg', 40, 1)
update_icon()
else
menustat = "void"
to_chat(usr, "<span class='warning'>Error: No growns inside. Please insert growns.</span>")
return
/obj/machinery/biogenerator/proc/create_product(var/item, var/cost)
cost = round(cost/build_eff)
if(cost > points)
menustat = "nopoints"
return 0
processing = 1
update_icon()
updateUsrDialog()
points -= cost
sleep(30)
switch(item)
if("milk")
beaker.reagents.add_reagent("milk", 10)
if("milk5")
beaker.reagents.add_reagent("milk", 50)
if("cream")
beaker.reagents.add_reagent("cream", 10)
if("cream5")
beaker.reagents.add_reagent("cream", 50)
if("meat")
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("meat5")
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc) //This is ugly.
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("unizyme")
beaker.reagents.add_reagent("enzyme", 10)
if("unizyme50")
beaker.reagents.add_reagent("enzyme", 50)
if("nutrispread")
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
if("nutrispread5")
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
if("ez")
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z")
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh")
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z5")
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh5")
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("wallet")
new/obj/item/weapon/storage/wallet(loc)
if("gloves")
new/obj/item/clothing/gloves/botanic_leather(loc)
if("plantbag")
new/obj/item/weapon/storage/bag/plants(loc)
if("plantbaglarge")
new/obj/item/weapon/storage/bag/plants/large(loc)
if("tbelt")
new/obj/item/weapon/storage/belt/utility(loc)
if("satchel")
new/obj/item/weapon/storage/backpack/satchel(loc)
if("cashbag")
new/obj/item/weapon/storage/bag/cash(loc)
if("chembag")
new/obj/item/weapon/storage/bag/chemistry(loc)
if("monkey")
new/mob/living/carbon/human/monkey(loc)
if("workboots")
new/obj/item/clothing/shoes/boots/workboots(loc)
if("leathershoes")
new/obj/item/clothing/shoes/leather(loc)
if("leatherchaps")
new/obj/item/clothing/under/pants/chaps
if("leathercoat")
new/obj/item/clothing/suit/leathercoat(loc)
if("leatherjacket")
new/obj/item/clothing/suit/storage/toggle/brown_jacket(loc)
if("wintercoat")
new/obj/item/clothing/suit/storage/hooded/wintercoat(loc)
if("algae") //VOREStation Edit - Algae for oxygen generator
var/obj/item/stack/material/algae/A = new(loc)
A.amount = 4 //VOREStation Edit End
processing = 0
menustat = "complete"
update_icon()
return 1
/obj/machinery/biogenerator/Topic(href, href_list)
if(stat & BROKEN) return
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
usr.set_machine(src)
switch(href_list["action"])
if("activate")
activate()
if("detach")
if(beaker)
beaker.loc = src.loc
beaker = null
update_icon()
if("create")
create_product(href_list["item"], text2num(href_list["cost"]))
if("menu")
menustat = "menu"
updateUsrDialog()
/obj/machinery/biogenerator/RefreshParts()
..()
var/man_rating = 0
@@ -314,3 +305,5 @@
build_eff = man_rating
eat_eff = bin_rating
#undef BIOGENITEM
+93 -99
View File
@@ -101,137 +101,128 @@
else
tank2 = I
update_icon()
updateUsrDialog()
SStgui.update_uis(src)
to_chat(user, "<span class='notice'>You connect \the [I] to \the [src]'s [I==tank1 ? "primary" : "secondary"] slot.</span>")
return
..()
/obj/machinery/bomb_tester/attack_hand(var/mob/user)
add_fingerprint(user)
interact(user)
tgui_interact(user)
/obj/machinery/bomb_tester/interact(var/mob/user)
if(stat & NOPOWER)
return
/obj/machinery/bomb_tester/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BombTester", name)
ui.open()
var/dat = "<HEAD><TITLE>Bomb Tester</TITLE></HEAD>"
/obj/machinery/bomb_tester/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["simulating"] = simulating
if(!simulating)
data["mode"] = sim_mode
data["tank1"] = tank1
data["tank1ref"] = REF(tank1)
data["tank2"] = tank2
data["tank2ref"] = REF(tank2)
data["canister"] = test_canister
data["sim_canister_output"] = sim_canister_output
return data
dat += "<font face='terminal' size ='3'>Virtual Explosive Simulator v1.03</font>"
dat += "<br>"
if(simulating)
dat += "<br><center>Simulation in progress! Please wait for results.</center>"
else
dat += "<br><center>Mode: [sim_mode==MODE_SINGLE?"Single Tank":"<A href='?src=\ref[src];set_mode=1'>Single Tank</a>"] -- [sim_mode==MODE_DOUBLE?"Transfer Valve":"<A href='?src=\ref[src];set_mode=2'>Transfer Valve</a>"] -- [sim_mode==MODE_CANISTER?"Canister":"<A href='?src=\ref[src];set_mode=3'>Canister</a>"]</center>"
dat += "<br>"
dat += "<br><center><u>Gas Sources</u></center>"
dat += "<br><center><A href='?src=\ref[src];tank=1'>[tank1?"\[[tank1.name]\]":"\[Primary Slot\]"]</a> -- <A href='?src=\ref[src];tank=2'>[tank2?"\[[tank2.name]\]":"\[Secondary Slot\]"]</a></center>"
dat += "<br><center>Connected Canister: [test_canister?"[test_canister.name] -- ":"None -- "]<A href='?src=\ref[src];canister_scan=1'>[test_canister?"\[Rescan\]":"\[Scan for canister\]"]</a></center>"
if(test_canister)
dat += "<br><center>Canister Release Pressure: [sim_canister_output] Kilopascals</center>"
dat += "<br><center>"
dat += "<A href='?src=\ref[src];set_can_pressure=-1000'>-1000</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-100'>-100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-10'>-10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-1'>-1</a> ||| "
dat += "<A href='?src=\ref[src];set_can_pressure=1'>+1</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=10'>+10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=100'>+100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=1000'>+1000</a>"
dat += "</center>"
dat += "<br><br>"
dat += "<br><center><font size='6'><b><A href='?src=\ref[src];start_sim=1'>BEGIN SIMULATION</a></b></font></center>"
user.set_machine(src)
user << browse(dat, "window=bomb_tester")
onclose(user, "bomb_tester")
/obj/machinery/bomb_tester/Topic(href, href_list)
/obj/machinery/bomb_tester/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
if(stat & NOPOWER)
return
if(!usr.Adjacent(src))
usr << browse(null, "window=bomb_tester")
usr.unset_machine()
return
return TRUE
if(simulating)
return
if(href_list["set_mode"])
sim_mode = text2num(href_list["set_mode"])
var/text_mode
switch(sim_mode)
if(MODE_SINGLE)
text_mode = "single gas tank detonation"
if(MODE_DOUBLE)
text_mode = "tank transfer valve detonation"
if(MODE_CANISTER)
text_mode = "canister-assisted single gas tank detonation"
to_chat(usr, "<span class='notice'>[src] set to simulate a [text_mode].</span>")
if(href_list["tank"])
var/tankvar = "tank[href_list["tank"]]"
var/obj/item/weapon/tank/T
if(vars[tankvar])
T = vars[tankvar]
T.forceMove(get_turf(src))
vars[tankvar] = null
else if(istype(usr.get_active_hand(),/obj/item/weapon/tank))
T = usr.get_active_hand()
usr.drop_item(T)
T.forceMove(src)
vars[tankvar] = T
update_icon()
if(href_list["canister_scan"])
for(var/obj/machinery/portable_atmospherics/canister/C in orange(1,src))
if(C && C == test_canister)
continue
else if(C)
test_canister = C
break
switch(action)
if("set_mode")
sim_mode = clamp(text2num(params["mode"]), MODE_SINGLE, MODE_CANISTER)
var/text_mode
switch(sim_mode)
if(MODE_SINGLE)
text_mode = "single gas tank detonation"
if(MODE_DOUBLE)
text_mode = "tank transfer valve detonation"
if(MODE_CANISTER)
text_mode = "canister-assisted single gas tank detonation"
to_chat(usr, "<span class='notice'>[src] set to simulate a [text_mode].</span>")
return TRUE
if("add_tank")
if(istype(usr.get_active_hand(), /obj/item/weapon/tank))
var/obj/item/weapon/tank/T = usr.get_active_hand()
var/slot = params["slot"]
if(slot == 1 && !tank1)
tank1 = T
else if(slot == 2 && !tank2)
tank2 = T
else
to_chat(usr, "<span class='warning'>Slot [slot] is full.</span>")
return
usr.drop_item(T)
T.forceMove(src)
return TRUE
else
test_canister = null
to_chat(usr, "<span class='warning'>You must be wielding a tank to insert it!</span>")
if(href_list["set_can_pressure"])
var/change = text2num(href_list["set_can_pressure"])
sim_canister_output = CLAMP(sim_canister_output+change, ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10)
if("remove_tank")
var/obj/item/weapon/tank/T = locate(params["ref"]) in list(tank1, tank2)
if(istype(T))
if(T == tank1)
tank1 = null
if(T == tank2)
tank2 = null
T.forceMove(get_turf(src))
update_icon()
return TRUE
if(href_list["start_sim"])
start_simulating()
if("canister_scan")
for(var/obj/machinery/portable_atmospherics/canister/C in orange(1,src))
if(C && C == test_canister)
continue
else if(C)
test_canister = C
break
else
test_canister = null
return TRUE
updateUsrDialog()
if("set_can_pressure")
sim_canister_output = CLAMP(text2num(params["pressure"]), ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10)
return TRUE
if("start_sim")
start_simulating()
return TRUE
/obj/machinery/bomb_tester/proc/start_simulating()
if(!tank1 || (sim_mode == MODE_DOUBLE && !tank2) || (sim_mode == MODE_CANISTER && !test_canister))
simulation_results = "Error"
simulation_finish()
return
if((tank1?.air_contents.return_pressure() > TANK_RUPTURE_PRESSURE) || (tank2?.air_contents.return_pressure() > TANK_RUPTURE_PRESSURE))
simulation_results = "Unstable"
simulation_finish()
return
simulating = 1
update_use_power(USE_POWER_ACTIVE)
simulation_started = world.time
update_icon()
switch(sim_mode)
if(MODE_SINGLE)
if(!tank1)
simulation_results = "Error"
return
spawn()
single_tank_sim()
if(MODE_DOUBLE)
if(!tank1 || !tank2)
simulation_results = "Error"
return
spawn()
ttv_sim()
if(MODE_CANISTER)
if(!tank1 || !test_canister)
simulation_results = "Error"
return
spawn()
canister_sim()
@@ -361,9 +352,12 @@
if(simulation_results == "Error")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
state("Invalid parameters.")
else if(simulation_results == "Unstable")
playsound(src, 'sound/machines/buzz-two.ogg', 50, 0)
state("Tank instability detected. Please step away from the device.")
else
ping("Simulation complete!")
playsound(src, "sound/effects/printer.ogg", 50, 1)
playsound(src, "sound/machines/printer.ogg", 50, 1)
var/obj/item/weapon/paper/P = new(get_turf(src))
P.name = "Explosive Simulator printout"
P.info = simulation_results
@@ -383,4 +377,4 @@
#undef MODE_SINGLE
#undef MODE_DOUBLE
#undef MODE_CANISTER
#undef MODE_CANISTER
+1 -1
View File
@@ -205,7 +205,7 @@
return
else if((occupant.health >= heal_level || occupant.health == occupant.getMaxHealth()) && (!eject_wait))
playsound(src, 'sound/machines/ding.ogg', 50, 1)
playsound(src, 'sound/machines/medbayscanner1.ogg', 50, 1)
audible_message("\The [src] signals that the cloning process is complete.")
connected_message("Cloning Process Complete.")
locked = 0
+1
View File
@@ -342,6 +342,7 @@
cloneresult = pod.growclone(C)
if(cloneresult)
set_temp("Initiating cloning cycle...", "success")
playsound(src, 'sound/machines/medbayscanner1.ogg', 100, 1)
records.Remove(C)
qdel(C)
menu = MENU_MAIN
+203 -140
View File
@@ -6,162 +6,225 @@
light_color = "#a97faa"
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/robotics
var/safety = 1
/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob)
ui_interact(user)
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
data["robots"] = get_cyborgs(user)
data["is_ai"] = issilicon(user)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/robotics/Topic(href, href_list)
if(..())
return
var/mob/user = usr
if(!src.allowed(user))
to_chat(user, "Access Denied")
if(stat & (NOPOWER|BROKEN))
return
tgui_interact(user)
// Locks or unlocks the cyborg
if (href_list["lockdown"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
var/failmsg = ""
if(!target || !istype(target))
return
/obj/machinery/computer/robotics/proc/is_authenticated(mob/user)
if(!istype(user))
return FALSE
if(isobserver(user))
var/mob/observer/dead/D = user
if(D.can_admin_interact())
return TRUE
if(allowed(user))
return TRUE
return FALSE
if(isAI(user) && (target.connected_ai != user))
to_chat(user, "Access Denied. This robot is not linked to you.")
return
/**
* Does this borg show up in the console
*
* Returns TRUE if a robot will show up in the console
* Returns FALSE if a robot will not show up in the console
* Arguments:
* * R - The [mob/living/silicon/robot] to be checked
*/
/obj/machinery/computer/robotics/proc/console_shows(mob/living/silicon/robot/R)
if(!istype(R))
return FALSE
if(istype(R, /mob/living/silicon/robot/drone))
return FALSE
if(R.scrambledcodes)
return FALSE
if(!AreConnectedZLevels(get_z(src), get_z(R)))
return FALSE
return TRUE
if(isrobot(user))
to_chat(user, "Access Denied.")
return
/**
* Check if a user can send a lockdown/detonate command to a specific borg
*
* Returns TRUE if a user can send the command (does not guarantee it will work)
* Returns FALSE if a user cannot
* Arguments:
* * user - The [mob/user] to be checked
* * R - The [mob/living/silicon/robot] to be checked
* * telluserwhy - Bool of whether the user should be sent a to_chat message if they don't have access
*/
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R, telluserwhy = FALSE)
if(!istype(user))
return FALSE
if(!console_shows(R))
return FALSE
if(isAI(user))
if(R.connected_ai != user)
if(telluserwhy)
to_chat(user, "<span class='warning'>AIs can only control cyborgs which are linked to them.</span>")
return FALSE
if(isrobot(user))
if(R != user)
if(telluserwhy)
to_chat(user, "<span class='warning'>Cyborgs cannot control other cyborgs.</span>")
return FALSE
return TRUE
var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No")
if(choice != "Yes")
return
/**
* Check if the user is the right kind of entity to be able to hack borgs
*
* Returns TRUE if a user is a traitor AI, or aghost
* Returns FALSE otherwise
* Arguments:
* * user - The [mob/user] to be checked
*/
/obj/machinery/computer/robotics/proc/can_hack_any(mob/user)
if(!istype(user))
return FALSE
if(isobserver(user))
var/mob/observer/dead/D = user
if(D.can_admin_interact())
return TRUE
if(!isAI(user))
return FALSE
return (user.mind.special_role && user.mind.original == user)
if(!target || !istype(target))
return
var/istraitor = target.mind.special_role
if (istraitor)
failmsg = "failed (target is traitor) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
to_chat(target, "Someone tried to lock you down!")
else
to_chat(target, "Someone tried to lift your lockdown!")
else if (target.emagged)
failmsg = "failed (target is hacked) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
to_chat(target, "Someone tried to lock you down!")
else
to_chat(target, "Someone tried to lift your lockdown!")
else
target.canmove = !target.canmove
target.lockcharge = !target.canmove //when canmove is 1, lockcharge should be 0
target.lockdown = !target.canmove
if (target.lockcharge)
to_chat(target, "You have been locked down!")
else
to_chat(target, "Your lockdown has been lifted!")
message_admins("<span class='notice'>[key_name_admin(usr)] [failmsg][target.lockcharge ? "lockdown" : "release"] on [target.name]!</span>")
log_game("[key_name(usr)] attempted to [target.lockcharge ? "lockdown" : "release"] [target.name] on the robotics console!")
/**
* Check if the user is allowed to hack a specific borg
*
* Returns TRUE if a user can hack the specific cyborg
* Returns FALSE if a user cannot
* Arguments:
* * user - The [mob/user] to be checked
* * R - The [mob/living/silicon/robot] to be checked
*/
/obj/machinery/computer/robotics/proc/can_hack(mob/user, mob/living/silicon/robot/R)
if(!can_hack_any(user))
return FALSE
if(!istype(R))
return FALSE
if(R.emagged)
return FALSE
if(R.connected_ai != user)
return FALSE
return TRUE
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
else if (href_list["hack"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
if(!target || !istype(target))
return
// Antag synthetic checks
if(!istype(user, /mob/living/silicon) || !(user.mind.special_role && user.mind.original == user))
to_chat(user, "Access Denied")
return
if(target.emagged)
to_chat(user, "Robot is already hacked.")
return
var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No")
if(choice != "Yes")
return
if(!target || !istype(target))
return
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [target.name] using the robotic console!</span>")
log_game("[key_name(usr)] emagged [target.name] using robotic console!")
target.emagged = 1
to_chat(target, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
// Proc: get_cyborgs()
// Parameters: 1 (operator - mob which is operating the console.)
// Description: Returns NanoUI-friendly list of accessible cyborgs.
/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
var/list/robots = list()
/obj/machinery/computer/robotics/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RoboticsControlConsole", name)
ui.open()
/obj/machinery/computer/robotics/tgui_data(mob/user)
var/list/data = list()
data["auth"] = is_authenticated(user)
data["can_hack"] = can_hack_any(user)
data["cyborgs"] = list()
data["safety"] = safety
for(var/mob/living/silicon/robot/R in mob_list)
// Ignore drones
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
if(!console_shows(R))
continue
var/area/A = get_area(R)
var/turf/T = get_turf(R)
var/list/cyborg_data = list(
name = R.name,
ref = REF(R),
locked_down = R.lockcharge,
locstring = "[A.name] ([T.x], [T.y])",
status = R.stat,
health = round(R.health * 100 / R.maxHealth, 0.1),
charge = R.cell ? round(R.cell.percent()) : null,
cell_capacity = R.cell ? R.cell.maxcharge : null,
module = R.module ? R.module.name : "No Module Detected",
synchronization = R.connected_ai,
is_hacked = R.connected_ai && R.emagged,
hackable = can_hack(user, R),
)
data["cyborgs"] += list(cyborg_data)
data["show_detonate_all"] = (data["auth"] && length(data["cyborgs"]) > 0 && ishuman(user))
return data
var/list/robot = list()
robot["name"] = R.name
if(R.stat)
robot["status"] = "Not Responding"
else if (R.lockcharge)
robot["status"] = "Lockdown"
else
robot["status"] = "Operational"
if(R.cell)
robot["cell"] = 1
robot["cell_capacity"] = R.cell.maxcharge
robot["cell_current"] = R.cell.charge
robot["cell_percentage"] = round(R.cell.percent())
else
robot["cell"] = 0
robot["module"] = R.module ? R.module.name : "None"
robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
robot["hackable"] = 0
//Antag synths should be able to hack themselves and see their hacked status.
if(operator && isrobot(operator) && (operator.mind.special_role && operator.mind.original == operator) && (operator == R))
robot["hacked"] = R.emagged ? 1 : 0
robot["hackable"] = R.emagged? 0 : 1
// Antag AIs know whether linked cyborgs are hacked or not.
if(operator && isAI(operator) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
robot["hacked"] = R.emagged ? 1 : 0
robot["hackable"] = R.emagged? 0 : 1
robots.Add(list(robot))
return robots
// Proc: get_cyborg_by_name()
// Parameters: 1 (name - Cyborg we are trying to find)
// Description: Helper proc for finding cyborg by name
/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
if (!name)
/obj/machinery/computer/robotics/tgui_act(action, params)
if(..())
return
for(var/mob/living/silicon/robot/R in mob_list)
if(R.name == name)
return R
. = FALSE
if(!is_authenticated(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
switch(action)
if("arm") // Arms the emergency self-destruct system
if(issilicon(usr))
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
return
safety = !safety
to_chat(usr, "<span class='notice'>You [safety ? "disarm" : "arm"] the emergency self destruct.</span>")
. = TRUE
if("nuke") // Destroys all accessible cyborgs if safety is disabled
if(issilicon(usr))
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
return
if(safety)
to_chat(usr, "<span class='danger'>Self-destruct aborted - safety active</span>")
return
message_admins("<span class='notice'>[key_name_admin(usr)] detonated all cyborgs!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated all cyborgs!</span>")
for(var/mob/living/silicon/robot/R in mob_list)
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
continue
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.self_destruct()
. = TRUE
if("killbot") // destroys one specific cyborg
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_control(usr, R, TRUE))
return
if(R.mind && R.mind.special_role && R.emagged)
to_chat(R, "<span class='userdanger'>Extreme danger! Termination codes detected. Scrambling security codes and automatic AI unlink triggered.</span>")
R.ResetSecurityCodes()
. = TRUE
return
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[key_name_admin(usr)] detonated [key_name_admin(R)] ([ADMIN_COORDJMP(T)])!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.self_destruct()
. = TRUE
if("stopbot") // lock or unlock the borg
if(isrobot(usr))
to_chat(usr, "<span class='danger'>Access Denied.</span>")
return
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_control(usr, R, TRUE))
return
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.lockcharge)
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted</span>" : "<span class='alert'>ALERT - Cyborg lockdown detected</span>"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
. = TRUE
if("hackbot") // AIs hacking/emagging a borg
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_hack(usr, R))
return
var/choice = input("Really hack [R.name]? This cannot be undone.") in list("Yes", "No")
if(choice != "Yes")
return
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!</span>")
R.emagged = TRUE
to_chat(R, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
. = TRUE
+1 -1
View File
@@ -509,4 +509,4 @@
/obj/machinery/computer/secure_data/detective_computer
icon_state = "messyfiles"
#undef FIELD
#undef FIELD
+1
View File
@@ -34,6 +34,7 @@
if(..())
return
if(!allowed(user))
to_chat(user, "<span class='warning'>You don't have the required access to use this console.</span>")
return
user.set_machine(src)
tgui_interact(user)
@@ -35,8 +35,8 @@
var jobs_all = ""
jobs_all += "<table><tr><td></td><td><b>Command</b></td>"
jobs_all += "</tr><tr height='20'><td><b>Special</b></td>"//Colony Director in special because he is head of heads ~Intercross21
jobs_all += "<td weight='100'><a href='?src=\ref[src];;assign=Colony Director'>Colony Director</a></td>"
jobs_all += "</tr><tr height='20'><td><b>Special</b></td>"//Site Manager in special because he is head of heads ~Intercross21
jobs_all += "<td weight='100'><a href='?src=\ref[src];;assign=Site Manager'>Site Manager</a></td>"
jobs_all += "<td weight='100'><a href='?src=\ref[src];;assign=Custom'>Custom</a></td>"
counter = 0
+76 -11
View File
@@ -39,9 +39,9 @@
var/secured_wires = 0
var/datum/wires/airlock/wires = null
var/open_sound_powered = 'sound/machines/airlock.ogg'
var/open_sound_powered = 'sound/machines/door/covert1o.ogg'
var/open_sound_unpowered = 'sound/machines/airlockforced.ogg'
var/close_sound_powered = 'sound/machines/airlockclose.ogg'
var/close_sound_powered = 'sound/machines/door/covert1c.ogg'
var/denied_sound = 'sound/machines/deniedbeep.ogg'
var/bolt_up_sound = 'sound/machines/boltsup.ogg'
var/bolt_down_sound = 'sound/machines/boltsdown.ogg'
@@ -81,7 +81,7 @@
if(do_after(user,5 SECONDS,src))
visible_message("<span class='danger'>\The [user] forces \the [src] open, sparks flying from its electronics!</span>")
src.do_animate("spark")
playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS)
src.locked = 0
src.welded = 0
update_icon()
@@ -90,7 +90,7 @@
else if(src.density)
visible_message("<span class='alium'>\The [user] begins forcing \the [src] open!</span>")
if(do_after(user, 5 SECONDS,src))
playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1)
playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS)
visible_message("<span class='danger'>\The [user] forces \the [src] open!</span>")
open(1)
else
@@ -112,40 +112,54 @@
icon = 'icons/obj/doors/Doorcom.dmi'
req_one_access = list(access_heads)
assembly_type = /obj/structure/door_assembly/door_assembly_com
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
/obj/machinery/door/airlock/security
name = "Security Airlock"
icon = 'icons/obj/doors/Doorsec.dmi'
req_one_access = list(access_security)
assembly_type = /obj/structure/door_assembly/door_assembly_sec
open_sound_powered = 'sound/machines/door/sec1o.ogg'
close_sound_powered = 'sound/machines/door/sec1c.ogg'
/obj/machinery/door/airlock/engineering
name = "Engineering Airlock"
icon = 'icons/obj/doors/Dooreng.dmi'
req_one_access = list(access_engine)
assembly_type = /obj/structure/door_assembly/door_assembly_eng
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/engineeringatmos
name = "Atmospherics Airlock"
icon = 'icons/obj/doors/Doorengatmos.dmi'
req_one_access = list(access_atmospherics)
assembly_type = /obj/structure/door_assembly/door_assembly_eat
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/medical
name = "Medical Airlock"
icon = 'icons/obj/doors/Doormed.dmi'
req_one_access = list(access_medical)
assembly_type = /obj/structure/door_assembly/door_assembly_med
open_sound_powered = 'sound/machines/door/med1o.ogg'
close_sound_powered = 'sound/machines/door/med1c.ogg'
/obj/machinery/door/airlock/maintenance
name = "Maintenance Access"
icon = 'icons/obj/doors/Doormaint.dmi'
//req_one_access = list(access_maint_tunnels) //VOREStation Edit - Maintenance is open access
assembly_type = /obj/structure/door_assembly/door_assembly_mai
open_sound_powered = 'sound/machines/door/door2o.ogg'
close_sound_powered = 'sound/machines/door/door2c.ogg'
/obj/machinery/door/airlock/maintenance/cargo
icon = 'icons/obj/doors/Doormaint_cargo.dmi'
req_one_access = list(access_cargo)
open_sound_powered = 'sound/machines/door/door2o.ogg'
close_sound_powered = 'sound/machines/door/door2c.ogg'
/obj/machinery/door/airlock/maintenance/command
icon = 'icons/obj/doors/Doormaint_command.dmi'
@@ -153,6 +167,8 @@
/obj/machinery/door/airlock/maintenance/common
icon = 'icons/obj/doors/Doormaint_common.dmi'
open_sound_powered = 'sound/machines/door/hall3o.ogg'
close_sound_powered = 'sound/machines/door/hall3c.ogg'
/obj/machinery/door/airlock/maintenance/engi
icon = 'icons/obj/doors/Doormaint_engi.dmi'
@@ -177,6 +193,8 @@
name = "External Airlock"
icon = 'icons/obj/doors/Doorext.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_ext
open_sound_powered = 'sound/machines/door/space1o.ogg'
close_sound_powered = 'sound/machines/door/space1c.ogg'
/obj/machinery/door/airlock/external/glass/bolted
icon_state = "door_locked" // So it looks visibly bolted in map editor
@@ -193,12 +211,15 @@
opacity = 0
glass = 1
req_one_access = list(access_external_airlocks)
open_sound_powered = 'sound/machines/door/space1o.ogg'
close_sound_powered = 'sound/machines/door/space1c.ogg'
/obj/machinery/door/airlock/glass
name = "Glass Airlock"
icon = 'icons/obj/doors/Doorglass.dmi'
hitsound = 'sound/effects/Glasshit.ogg'
open_sound_powered = 'sound/machines/windowdoor.ogg'
open_sound_powered = 'sound/machines/door/hall1o.ogg'
close_sound_powered = 'sound/machines/door/hall1c.ogg'
maxhealth = 300
explosion_resistance = 5
opacity = 0
@@ -209,12 +230,16 @@
icon = 'icons/obj/doors/Doorele.dmi'
req_one_access = list(access_cent_general)
opacity = 1
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
/obj/machinery/door/airlock/glass_centcom
name = "Airlock"
icon = 'icons/obj/doors/Dooreleglass.dmi'
opacity = 0
glass = 1
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
/obj/machinery/door/airlock/vault
name = "Vault"
@@ -224,6 +249,8 @@
secured_wires = 1
assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity //Until somebody makes better sprites.
req_one_access = list(access_heads_vault)
open_sound_powered = 'sound/machines/door/vault1o.ogg'
close_sound_powered = 'sound/machines/door/vault1c.ogg'
/obj/machinery/door/airlock/vault/bolted
icon_state = "door_locked"
@@ -242,6 +269,9 @@
opacity = 1
assembly_type = /obj/structure/door_assembly/door_assembly_hatch
req_one_access = list(access_maint_tunnels)
open_sound_powered = 'sound/machines/door/hatchopen.ogg'
close_sound_powered = 'sound/machines/door/hatchclose.ogg'
open_sound_unpowered = 'sound/machines/door/hatchforced.ogg'
/obj/machinery/door/airlock/maintenance_hatch
name = "Maintenance Hatch"
@@ -250,6 +280,9 @@
opacity = 1
assembly_type = /obj/structure/door_assembly/door_assembly_mhatch
req_one_access = list(access_maint_tunnels)
open_sound_powered = 'sound/machines/door/hatchopen.ogg'
close_sound_powered = 'sound/machines/door/hatchclose.ogg'
open_sound_unpowered = 'sound/machines/door/hatchforced.ogg'
/obj/machinery/door/airlock/glass_command
name = "Command Airlock"
@@ -261,6 +294,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_com
glass = 1
req_one_access = list(access_heads)
open_sound_powered = 'sound/machines/door/cmd1o.ogg'
close_sound_powered = 'sound/machines/door/cmd1c.ogg'
/obj/machinery/door/airlock/glass_engineering
name = "Engineering Airlock"
@@ -272,6 +307,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_eng
glass = 1
req_one_access = list(access_engine)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/glass_engineeringatmos
name = "Atmospherics Airlock"
@@ -283,6 +320,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_eat
glass = 1
req_one_access = list(access_atmospherics)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/glass_security
name = "Security Airlock"
@@ -294,6 +333,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_sec
glass = 1
req_one_access = list(access_security)
open_sound_powered = 'sound/machines/door/sec1o.ogg'
close_sound_powered = 'sound/machines/door/sec1c.ogg'
/obj/machinery/door/airlock/glass_medical
name = "Medical Airlock"
@@ -305,23 +346,31 @@
assembly_type = /obj/structure/door_assembly/door_assembly_med
glass = 1
req_one_access = list(access_medical)
open_sound_powered = 'sound/machines/door/med1o.ogg'
close_sound_powered = 'sound/machines/door/med1c.ogg'
/obj/machinery/door/airlock/mining
name = "Mining Airlock"
icon = 'icons/obj/doors/Doormining.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_min
req_one_access = list(access_mining)
open_sound_powered = 'sound/machines/door/cgo1o.ogg'
close_sound_powered = 'sound/machines/door/cgo1c.ogg'
/obj/machinery/door/airlock/atmos
name = "Atmospherics Airlock"
icon = 'icons/obj/doors/Dooratmo.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_atmo
req_one_access = list(access_atmospherics)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/research
name = "Research Airlock"
icon = 'icons/obj/doors/Doorresearch.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_research
open_sound_powered = 'sound/machines/door/sci1o.ogg'
close_sound_powered = 'sound/machines/door/sci1c.ogg'
/obj/machinery/door/airlock/glass_research
name = "Research Airlock"
@@ -333,6 +382,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_research
glass = 1
req_one_access = list(access_research)
open_sound_powered = 'sound/machines/door/sci1o.ogg'
close_sound_powered = 'sound/machines/door/sci1c.ogg'
/obj/machinery/door/airlock/glass_mining
name = "Mining Airlock"
@@ -344,6 +395,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_min
glass = 1
req_one_access = list(access_mining)
open_sound_powered = 'sound/machines/door/cgo1o.ogg'
close_sound_powered = 'sound/machines/door/cgo1c.ogg'
/obj/machinery/door/airlock/glass_atmos
name = "Atmospherics Airlock"
@@ -355,6 +408,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_atmo
glass = 1
req_one_access = list(access_atmospherics)
open_sound_powered = 'sound/machines/door/eng1o.ogg'
close_sound_powered = 'sound/machines/door/eng1c.ogg'
/obj/machinery/door/airlock/gold
name = "Gold Airlock"
@@ -435,6 +490,8 @@
icon = 'icons/obj/doors/Doorsci.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_science
req_one_access = list(access_research)
open_sound_powered = 'sound/machines/door/sci1o.ogg'
close_sound_powered = 'sound/machines/door/sci1c.ogg'
/obj/machinery/door/airlock/glass_science
name = "Glass Airlocks"
@@ -443,6 +500,8 @@
assembly_type = /obj/structure/door_assembly/door_assembly_science
glass = 1
req_one_access = list(access_research)
open_sound_powered = 'sound/machines/door/sci1o.ogg'
close_sound_powered = 'sound/machines/door/sci1c.ogg'
/obj/machinery/door/airlock/highsecurity
name = "Secure Airlock"
@@ -451,6 +510,8 @@
secured_wires = 1
assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity
req_one_access = list(access_heads_vault)
open_sound_powered = 'sound/machines/door/secure1o.ogg'
close_sound_powered = 'sound/machines/door/secure1c.ogg'
/obj/machinery/door/airlock/voidcraft
name = "voidcraft hatch"
@@ -460,11 +521,15 @@
opacity = 0
glass = 1
assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft
open_sound_powered = 'sound/machines/door/shuttle1o.ogg'
close_sound_powered = 'sound/machines/door/shuttle1c.ogg'
// Airlock opens from top-bottom instead of left-right.
/obj/machinery/door/airlock/voidcraft/vertical
icon = 'icons/obj/doors/shuttledoors_vertical.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical
open_sound_powered = 'sound/machines/door/shuttle1o.ogg'
close_sound_powered = 'sound/machines/door/shuttle1c.ogg'
/datum/category_item/catalogue/anomalous/precursor_a/alien_airlock
@@ -1108,9 +1173,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
playsound(src, open_sound_powered, 50, 1)
playsound(src, open_sound_powered, 50, 1, volume_channel = VOLUME_CHANNEL_DOORS)
else
playsound(src, open_sound_unpowered, 75, 1)
playsound(src, open_sound_unpowered, 75, 1, volume_channel = VOLUME_CHANNEL_DOORS)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -1206,9 +1271,9 @@ About the new airlock wires panel:
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0
if(arePowerSystemsOn())
playsound(src, close_sound_powered, 50, 1)
playsound(src, close_sound_powered, 50, 1, volume_channel = VOLUME_CHANNEL_DOORS)
else
playsound(src, open_sound_unpowered, 75, 1)
playsound(src, open_sound_unpowered, 75, 1, volume_channel = VOLUME_CHANNEL_DOORS)
for(var/turf/turf in locs)
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis)
@@ -1222,7 +1287,7 @@ About the new airlock wires panel:
if (operating && !forced) return 0
src.locked = 1
playsound(src, bolt_down_sound, 30, 0, 3)
playsound(src, bolt_down_sound, 30, 0, 3, volume_channel = VOLUME_CHANNEL_DOORS)
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
update_icon()
@@ -1236,7 +1301,7 @@ About the new airlock wires panel:
if(operating || !src.arePowerSystemsOn() || wires.is_cut(WIRE_DOOR_BOLTS)) return
src.locked = 0
playsound(src, bolt_up_sound, 30, 0, 3)
playsound(src, bolt_up_sound, 30, 0, 3, volume_channel = VOLUME_CHANNEL_DOORS)
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
update_icon()
+2
View File
@@ -4,6 +4,8 @@
appearance_flags = 0
var/obj/machinery/filler_object/filler1
var/obj/machinery/filler_object/filler2
open_sound_powered = 'sound/machines/door/WideOpen.ogg'
close_sound_powered = 'sound/machines/door/WideClose.ogg'
/obj/machinery/door/airlock/multi_tile/New()
..()
+5
View File
@@ -68,6 +68,11 @@
var/flash_time = strength
if(istype(O, /mob/living/carbon/human))
var/mob/living/carbon/human/H = O
//VOREStation Edit Start
if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION))
H.nif.notify("High intensity light detected, and blocked!",TRUE)
continue
//VOREStation Edit End
if(!H.eyecheck() <= 0)
continue
flash_time *= H.species.flash_mod
+1
View File
@@ -810,6 +810,7 @@ GLOBAL_LIST_BOILERPLATE(allCasters, /obj/machinery/newscaster)
var/scribble=""
var/scribble_page = null
drop_sound = 'sound/items/drop/wrapper.ogg'
pickup_sound = 'sound/items/pickup/wrapper.ogg'
obj/item/weapon/newspaper/attack_self(mob/user as mob)
if(ishuman(user))
+76 -69
View File
@@ -234,116 +234,123 @@
if(..())
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/partslathe/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
/obj/machinery/partslathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
var/data[0]
/obj/machinery/partslathe/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PartsLathe", name)
ui.open()
/obj/machinery/partslathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["panelOpen"] = panel_open
var/materials_ui[0]
var/list/materials_ui = list()
for(var/M in materials)
materials_ui[++materials_ui.len] = list(
"name" = M,
"display" = material_display_name(M),
"qty" = materials[M],
"max" = storage_capacity[M],
"percent" = (materials[M] / storage_capacity[M] * 100))
materials_ui.Add(list(list(
"name" = M,
"amount" = materials[M],
"sheets" = round(materials[M] / SHEET_MATERIAL_AMOUNT),
"removable" = materials[M] >= SHEET_MATERIAL_AMOUNT,
)))
data["materials"] = materials_ui
data["copyBoard"] = null
data["copyBoardReqComponents"] = null
if(istype(copy_board))
data["copyBoard"] = copy_board.name
var/req_components_ui[0]
var/list/req_components_ui = list()
for(var/CP in (copy_board.req_components || list()))
var/obj/comp_path = CP
var/comp_amt = copy_board.req_components[comp_path]
if(comp_amt && (comp_path in partslathe_recipies))
req_components_ui[++req_components_ui.len] = list("name" = initial(comp_path.name), "qty" = comp_amt)
req_components_ui.Add(list(list("name" = initial(comp_path.name), "qty" = comp_amt)))
data["copyBoardReqComponents"] = req_components_ui
data["queue"] = list()
for(var/datum/category_item/partslathe/Q in queue)
data["queue"] += Q.name
data["building"] = null
data["buildPercent"] = null
if(busy && queue.len > 0)
var/datum/category_item/partslathe/current = queue[1]
data["building"] = current.name
data["buildProgress"] = progress
data["buildTime"] = current.time
data["buildPercent"] = (progress / current.time * 100)
data["error"] = null
if(queue.len > 0 && !canBuild(queue[1]))
data["error"] = getLackingMaterials(queue[1])
var/recipies_ui[0]
var/list/recipies_ui = list()
for(var/T in partslathe_recipies)
var/datum/category_item/partslathe/R = partslathe_recipies[T]
recipies_ui[++recipies_ui.len] = list("name" = R.name, "type" = "[T]")
recipies_ui.Add(list(list("name" = R.name, "type" = "[T]")))
data["recipies"] = recipies_ui
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "partslathe.tmpl", "Parts Lathe UI", 500, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
return data
/obj/machinery/partslathe/Topic(href, href_list)
/obj/machinery/partslathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
usr.set_machine(src)
return TRUE
add_fingerprint(usr)
// Queue management can be done even while busy
if(href_list["queue"])
var/type_to_build = text2path(href_list["queue"])
var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build]
if(to_build)
addToQueue(to_build)
updateUsrDialog()
return
if(href_list["queueBoard"])
if(!istype(copy_board) || !copy_board.req_components)
return
for(var/comp_path in copy_board.req_components)
var/comp_amt = copy_board.req_components[comp_path]
if(!comp_amt)
continue
var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path]
if(!to_build)
continue // We don't support building whatever this is
for(var/i in 1 to comp_amt)
switch(action)
// Queue management can be done even while busy
if("queue")
var/type_to_build = text2path(params["queue"])
var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build]
if(to_build)
addToQueue(to_build)
return
return TRUE
if(href_list["cancel"])
var/index = text2num(href_list["cancel"])
if(index < 1 || index > queue.len)
return
if(busy && index == 1)
return
removeFromQueue(index)
return
if("queueBoard")
if(!istype(copy_board) || !copy_board.req_components)
return
for(var/comp_path in copy_board.req_components)
var/comp_amt = copy_board.req_components[comp_path]
if(!comp_amt)
continue
var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path]
if(!to_build)
continue // We don't support building whatever this is
for(var/i in 1 to comp_amt)
addToQueue(to_build)
return TRUE
if("cancel")
var/index = text2num(params["cancel"])
if(index < 1 || index > queue.len)
return
if(busy && index == 1)
return
removeFromQueue(index)
return TRUE
if(busy)
to_chat(usr, "<span class='notice'>\The [src]is busy. Please wait for completion of previous operation.</span>")
to_chat(usr, "<span class='notice'>[src] is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["ejectBoard"])
if(copy_board)
visible_message("<span class='notice'>\The [copy_board] is ejected from \the [src]'s circuit reader</span>.")
copy_board.forceMove(src.loc)
copy_board = null
updateUsrDialog()
return
switch(action)
if("ejectBoard")
if(copy_board)
visible_message("<span class='notice'>[copy_board] is ejected from [src]'s circuit reader</span>.")
copy_board.forceMove(src.loc)
copy_board = null
return TRUE
if(href_list["ejectMaterial"])
var/matName = href_list["ejectMaterial"]
if(!(matName in materials))
if("remove_mat")
// Remove a material from the fab
var/mat_id = params["id"]
var/amount = text2num(params["amount"])
eject_materials(mat_id, amount)
return
eject_materials(matName, 0)
updateUsrDialog()
return
/** Build list of recipies to include all tech level 1 stock parts. */
/obj/machinery/partslathe/proc/update_recipe_list()
+2 -2
View File
@@ -16,10 +16,10 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob
var/datum/seed/new_seed_type
if(istype(O, /obj/item/weapon/grown))
var/obj/item/weapon/grown/F = O
new_seed_type = plant_controller.seeds[F.plantname]
new_seed_type = SSplants.seeds[F.plantname]
else
var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O
new_seed_type = plant_controller.seeds[F.plantname]
new_seed_type = SSplants.seeds[F.plantname]
if(new_seed_type)
to_chat(user, "<span class='notice'>You extract some seeds from [O].</span>")
+16 -16
View File
@@ -139,7 +139,7 @@
if("door")
toggle_open(usr)
. = TRUE
if("dispense")
if("dispense")
switch(params["item"])
if("helmet")
dispense_helmet(usr)
@@ -653,12 +653,12 @@
name = "Vintage Pilot suit cycler"
model_text = "Vintage Pilot"
departments = list("Vintage Pilot (Bubble Helm)","Vintage Pilot (Closed Helm)")
/obj/machinery/suit_cycler/vintage/medsci
name = "Vintage MedSci suit cycler"
model_text = "Vintage MedSci"
departments = list("Vintage Medical (Bubble Helm)","Vintage Medical (Closed Helm)","Vintage Research (Bubble Helm)","Vintage Research (Closed Helm)")
/obj/machinery/suit_cycler/vintage/rugged
name = "Vintage Ruggedized suit cycler"
model_text = "Vintage Ruggedized"
@@ -751,7 +751,7 @@
if(istype(I,/obj/item/clothing/head/helmet/space/void/autolok))
to_chat(user, "You cannot refit an autolok helmet. In fact you shouldn't even be able to remove it in the first place. Inform an admin!")
return
//Ditto the Mk7
if(istype(I,/obj/item/clothing/head/helmet/space/void/responseteam))
to_chat(user, "The cycler indicates that the Mark VII Emergency Response Helmet is not compatible with the refitting system. How did you manage to detach it anyway? Inform an admin!")
@@ -791,13 +791,13 @@
if(istype(I,/obj/item/clothing/suit/space/void/autolok))
to_chat(user, "You cannot refit an autolok suit.")
return
//Ditto the Mk7
if(istype(I,/obj/item/clothing/suit/space/void/responseteam))
to_chat(user, "The cycler indicates that the Mark VII Emergency Response Suit is not compatible with the refitting system.")
return
//VOREStation Edit ENDS
to_chat(user, "You fit \the [I] into the suit cycler.")
user.drop_item()
I.loc = src
@@ -886,7 +886,7 @@
return TRUE
switch(action)
if("dispense")
if("dispense")
switch(params["item"])
if("helmet")
helmet.forceMove(get_turf(src))
@@ -895,23 +895,23 @@
suit.forceMove(get_turf(src))
suit = null
. = TRUE
if("department")
var/choice = params["department"]
if(choice in departments)
target_department = choice
. = TRUE
if("species")
var/choice = params["species"]
if(choice in species)
target_species = choice
. = TRUE
if("radlevel")
radiation_level = clamp(params["radlevel"], 1, emagged ? 5 : 3)
. = TRUE
if("repair_suit")
if(!suit || !can_repair)
return
@@ -1055,7 +1055,7 @@
if(target_species)
if(helmet) helmet.refit_for_species(target_species)
if(suit)
if(suit)
suit.refit_for_species(target_species)
if(suit.helmet)
suit.helmet.refit_for_species(target_species)
@@ -1176,7 +1176,7 @@
parent_suit = /obj/item/clothing/suit/space/void/refurb/mercenary
//BEGIN: Space for additional downstream variants
//VOREStation Addition Start
if("Director")
if("Manager")
parent_helmet = /obj/item/clothing/head/helmet/space/void/captain
parent_suit = /obj/item/clothing/suit/space/void/captain
if("Prototype")
@@ -1217,7 +1217,7 @@
parent_suit = /obj/item/clothing/suit/space/void/refurb/mercenary/talon
//VOREStation Addition End
//END: downstream variant space
//look at this! isn't it beautiful? -KK (well ok not beautiful but it's a lot cleaner)
if(helmet && target_department != "No Change")
var/obj/item/clothing/H = new parent_helmet
@@ -1235,9 +1235,9 @@
suit.desc = initial(parent_suit.desc)
suit.icon_state = initial(parent_suit.icon_state)
suit.item_state = initial(parent_suit.item_state)
suit.item_state_slots = S.item_state_slots
suit.item_state_slots = S.item_state_slots
qdel(S)
//can't believe I forgot to fix this- now helmets will properly cycle if they're attached to a suit -KK
if(suit.helmet && target_department != "No Change")
var/obj/item/clothing/AH = new parent_helmet
+4 -4
View File
@@ -1,5 +1,5 @@
/obj/machinery/suit_cycler
departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control","Exploration","Pilot Blue","Pilot","Director","Prototype")
departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control","Exploration","Pilot Blue","Pilot","Manager","Prototype")
species = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJ, SPECIES_TESHARI, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_VULPKANIN)
// Old Exploration is too WIP to use right now
@@ -11,10 +11,10 @@
req_access = list(access_pilot)
/obj/machinery/suit_cycler/captain
name = "Director suit cycler"
model_text = "Director"
name = "Manager suit cycler"
model_text = "Manager"
req_access = list(access_captain)
departments = list("Director")
departments = list("Manager")
/obj/machinery/suit_cycler/captain/Initialize() //No Teshari Sprites
species -= SPECIES_TESHARI
+28 -4
View File
@@ -170,7 +170,7 @@
/obj/item/clothing/shoes/brown = 5,
/obj/item/clothing/shoes/laceup = 5,
/obj/item/clothing/shoes/green = 5,
/obj/item/clothing/shoes/leather = 5,
/obj/item/clothing/shoes/laceup/brown = 5,
/obj/item/clothing/shoes/orange = 5,
/obj/item/clothing/shoes/purple = 5,
/obj/item/clothing/shoes/red = 5,
@@ -228,7 +228,7 @@
/obj/item/clothing/shoes/brown = 50,
/obj/item/clothing/shoes/laceup = 50,
/obj/item/clothing/shoes/green = 50,
/obj/item/clothing/shoes/leather = 50,
/obj/item/clothing/shoes/laceup/brown = 50,
/obj/item/clothing/shoes/orange = 50,
/obj/item/clothing/shoes/purple = 50,
/obj/item/clothing/shoes/red = 50,
@@ -1172,7 +1172,19 @@
/obj/item/clothing/mask/gas/sexyclown = 3,
/obj/item/clothing/under/sexyclown = 3,
/obj/item/clothing/mask/gas/sexymime = 3,
/obj/item/clothing/under/sexymime = 3)
/obj/item/clothing/under/sexymime = 3,
/obj/item/clothing/suit/storage/hooded/knight_costume = 3,
/obj/item/clothing/suit/storage/hooded/knight_costume/galahad = 3,
/obj/item/clothing/suit/storage/hooded/knight_costume/lancelot = 3,
/obj/item/clothing/suit/storage/hooded/knight_costume/robin = 3,
/obj/item/clothing/suit/armor/combat/crusader_costume = 3,
/obj/item/clothing/suit/armor/combat/crusader_costume/bedevere = 3,
/obj/item/clothing/head/helmet/combat/crusader_costume = 3,
/obj/item/clothing/head/helmet/combat/bedevere_costume = 3,
/obj/item/clothing/gloves/combat/knight_costume = 3,
/obj/item/clothing/gloves/combat/knight_costume/brown = 3,
/obj/item/clothing/shoes/knight_costume = 3,
/obj/item/clothing/shoes/knight_costume/black = 3)
prices = list(/obj/item/clothing/suit/storage/hooded/carp_costume = 200,
/obj/item/clothing/suit/storage/hooded/carp_costume = 200,
/obj/item/clothing/suit/chickensuit = 200,
@@ -1225,7 +1237,19 @@
/obj/item/clothing/mask/gas/sexyclown = 600,
/obj/item/clothing/under/sexyclown = 200,
/obj/item/clothing/mask/gas/sexymime = 600,
/obj/item/clothing/under/sexymime = 200)
/obj/item/clothing/under/sexymime = 200,
/obj/item/clothing/suit/storage/hooded/knight_costume = 200,
/obj/item/clothing/suit/storage/hooded/knight_costume/galahad = 200,
/obj/item/clothing/suit/storage/hooded/knight_costume/lancelot = 200,
/obj/item/clothing/suit/storage/hooded/knight_costume/robin = 200,
/obj/item/clothing/suit/armor/combat/crusader_costume = 200,
/obj/item/clothing/suit/armor/combat/crusader_costume/bedevere = 200,
/obj/item/clothing/head/helmet/combat/crusader_costume = 200,
/obj/item/clothing/head/helmet/combat/bedevere_costume = 200,
/obj/item/clothing/gloves/combat/knight_costume = 200,
/obj/item/clothing/gloves/combat/knight_costume/brown = 200,
/obj/item/clothing/shoes/knight_costume = 200,
/obj/item/clothing/shoes/knight_costume/black = 200)
premium = list(/obj/item/clothing/suit/imperium_monk = 3,
/obj/item/clothing/suit/barding/agatha = 2,
/obj/item/clothing/suit/barding/alt_agatha = 2,
@@ -21,6 +21,8 @@
var/energy_drain = 0
var/obj/mecha/chassis = null
var/range = MELEE //bitflags
/// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
var/mech_flags = NONE
var/salvageable = 1
var/required_type = /obj/mecha //may be either a type or a list of allowed types
var/equip_type = null //mechaequip2
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/extinguisher
name = "extinguisher"
desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)"
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
icon_state = "mecha_exting"
equip_cooldown = 5
energy_drain = 0
+1
View File
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/rcd
name = "mounted RCD"
desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)"
mech_flags = EXOSUIT_MODULE_WORKING|EXOSUIT_MODULE_COMBAT|EXOSUIT_MODULE_MEDICAL
icon_state = "mecha_rcd"
origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4)
equip_cooldown = 10
@@ -7,6 +7,7 @@
energy_drain = 20
range = MELEE
equip_cooldown = 30
mech_flags = EXOSUIT_MODULE_MEDICAL
var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 5
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
name = "syringe gun"
desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)"
mech_flags = EXOSUIT_MODULE_MEDICAL
icon = 'icons/obj/gun.dmi'
icon_state = "syringegun"
var/list/syringes
@@ -4,9 +4,6 @@
step_delay = 0.5
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
AM.throw_at(target,missile_range, missile_speed, chassis)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare
name = "\improper BNI Flare Launcher"
desc = "A flare-gun, but bigger."
@@ -34,51 +31,19 @@
name = "\improper SRM-8 missile rack"
desc = "A missile battery that holds eight missiles."
icon_state = "mecha_missilerack"
projectile = /obj/item/missile
projectile = /obj/item/projectile/bullet/srmrocket
fire_sound = 'sound/weapons/rpg.ogg'
projectiles = 8
projectile_energy_cost = 1000
equip_cooldown = 60
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target)
var/obj/item/missile/M = AM
M.primed = 1
..()
/obj/item/missile
icon = 'icons/obj/grenade.dmi'
icon_state = "missile"
var/primed = null
throwforce = 15
catchable = 0
var/devastation = 0
var/heavy_blast = 1
var/light_blast = 2
var/flash_blast = 4
does_spin = FALSE // No fun corkscrew missiles.
/obj/item/missile/proc/warhead_special(var/target)
explosion(target, devastation, heavy_blast, light_blast, flash_blast)
return
/obj/item/missile/throw_impact(atom/hit_atom)
if(primed)
warhead_special(hit_atom)
qdel(src)
else
..()
return
/obj/item/missile/light
throwforce = 10
heavy_blast = 0
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/rigged
name = "jury-rigged rocket pod"
desc = "A series of pipes, tubes, and cables that resembles a rocket pod."
icon_state = "mecha_missilerack-rig"
projectile = /obj/item/missile/light
projectile = /obj/item/projectile/bullet/srmrocket/weak
projectiles = 3
projectile_energy_cost = 800
equip_type = EQUIP_UTILITY
equip_type = EQUIP_UTILITY
+553 -182
View File
@@ -11,47 +11,80 @@
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/mechfab
var/speed = 1
var/mat_efficiency = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0, MAT_METALHYDROGEN = 0, MAT_SUPERMATTER = 0)
var/list/hidden_materials = list(MAT_PLASTEEL, MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM, MAT_METALHYDROGEN, MAT_SUPERMATTER)
/// Current items in the build queue.
var/list/queue = list()
/// Whether or not the machine is building the entire queue automagically.
var/process_queue = FALSE
/// The current design datum that the machine is building.
var/datum/design/being_built
/// World time when the build will finish.
var/build_finish = 0
/// World time when the build started.
var/build_start = 0
/// Reference to all materials used in the creation of the item being_built.
var/list/build_materials
/// Part currently stored in the Exofab.
var/obj/item/stored_part
/// Coefficient for the speed of item building. Based on the installed parts.
var/time_coeff = 1
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
var/component_coeff = 1
var/loading_icon_state = "mechfab-idle"
var/list/materials = list(
DEFAULT_WALL_MATERIAL = 0,
"glass" = 0,
"plastic" = 0,
MAT_GRAPHITE = 0,
MAT_PLASTEEL = 0,
"gold" = 0,
"silver" = 0,
MAT_LEAD = 0,
"osmium" = 0,
"diamond" = 0,
MAT_DURASTEEL = 0,
"phoron" = 0,
"uranium" = 0,
MAT_VERDANTIUM = 0,
MAT_MORPHIUM = 0,
MAT_METALHYDROGEN = 0,
MAT_SUPERMATTER = 0)
var/res_max_amount = 200000
var/datum/research/files
var/list/datum/design/queue = list()
var/progress = 0
var/busy = 0
var/list/categories = list()
var/category = null
var/sync_message = ""
var/valid_buildtype = MECHFAB
/// A list of categories that valid MECHFAB design datums will broadly categorise themselves under.
var/list/part_sets = list(
"Cyborg",
"Ripley",
"Odysseus",
"Gygax",
"Durand",
"Janus",
"Vehicle",
"Rigsuit",
"Phazon",
"Gopher", // VOREStation Add
"Polecat", // VOREStation Add
"Weasel", // VOREStation Add
"Exosuit Equipment",
"Exosuit Internals",
"Exosuit Ammunition",
"Cyborg Upgrade Modules",
"Cybernetics",
"Implants",
"Control Interfaces",
"Other",
"Misc",
)
/obj/machinery/mecha_part_fabricator/Initialize()
. = ..()
default_apply_parts()
files = new /datum/research(src) //Setup the research data holder.
update_categories()
/obj/machinery/mecha_part_fabricator/process()
..()
if(stat)
return
if(busy)
update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/update_icon()
overlays.Cut()
if(panel_open)
icon_state = "mechfab-o"
else
icon_state = "mechfab-idle"
if(busy)
overlays += "mechfab-active"
/obj/machinery/mecha_part_fabricator/dismantle()
for(var/f in materials)
@@ -65,67 +98,507 @@
var/T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
mat_efficiency = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
component_coeff = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; time_coeff is affected by both
T += M.rating
speed = T / 2 // 1 -> 3
time_coeff = T / 2 // 1 -> 3
update_tgui_static_data(usr)
/**
* Generates an info list for a given part.
*
* Returns a list of part information.
* * D - Design datum to get information on.
* * categories - Boolean, whether or not to parse snowflake categories into the part information list.
*/
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, var/categories = FALSE)
var/cost = list()
for(var/c in D.materials)
cost[c] = get_resource_cost_w_coeff(D, D.materials[c])
var/obj/built_item = D.build_path
var/list/category_override = null
var/list/sub_category = null
if(categories)
// Handle some special cases to build up sub-categories for the fab interface.
// Start with checking if this design builds a cyborg module.
if(built_item in typesof(/obj/item/borg/upgrade))
var/obj/item/borg/upgrade/U = built_item
var/module_types = initial(U.module_flags)
sub_category = list()
if(module_types)
if(module_types & BORG_MODULE_SECURITY)
sub_category += "Security"
if(module_types & BORG_MODULE_MINER)
sub_category += "Mining"
if(module_types & BORG_MODULE_JANITOR)
sub_category += "Janitor"
if(module_types & BORG_MODULE_MEDICAL)
sub_category += "Medical"
if(module_types & BORG_MODULE_ENGINEERING)
sub_category += "Engineering"
else
sub_category += "All Cyborgs"
// Else check if this design builds a piece of exosuit equipment.
else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = built_item
var/mech_types = initial(E.mech_flags)
sub_category = "Equipment"
if(mech_types)
category_override = list()
if(mech_types & EXOSUIT_MODULE_RIPLEY)
category_override += "Ripley"
if(mech_types & EXOSUIT_MODULE_ODYSSEUS)
category_override += "Odysseus"
if(mech_types & EXOSUIT_MODULE_GYGAX)
category_override += "Gygax"
if(mech_types & EXOSUIT_MODULE_DURAND)
category_override += "Durand"
if(mech_types & EXOSUIT_MODULE_PHAZON)
category_override += "Phazon"
var/list/part = list(
"name" = D.name,
"desc" = initial(built_item.desc),
"printTime" = get_construction_time_w_coeff(initial(D.time))/10,
"cost" = cost,
"id" = D.id,
"subCategory" = sub_category,
"categoryOverride" = category_override,
"searchMeta" = D.search_metadata
)
return part
/**
* Generates a list of resources / materials available to this Exosuit Fab
*
* Returns null if there is no material container available.
* List format is list(material_name = list(amount = ..., ref = ..., etc.))
*/
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/list/material_data = list()
for(var/mat_id in materials)
var/amount = materials[mat_id]
var/list/material_info = list(
"name" = mat_id,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT
)
material_data += list(material_info)
return material_data
/**
* Intended to be called when an item starts printing.
*
* Adds the overlay to show the fab working and sets active power usage settings.
*/
/obj/machinery/mecha_part_fabricator/proc/on_start_printing()
add_overlay("fab-active")
use_power = USE_POWER_ACTIVE
/**
* Intended to be called when the exofab has stopped working and is no longer printing items.
*
* Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing.
*/
/obj/machinery/mecha_part_fabricator/proc/on_finish_printing()
cut_overlay("fab-active")
use_power = USE_POWER_IDLE
desc = initial(desc)
process_queue = FALSE
/**
* Calculates resource/material costs for printing an item based on the machine's resource coefficient.
*
* Returns a list of k,v resources with their amounts.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
var/list/resources = list()
for(var/mat_id in D.materials)
resources[mat_id] = get_resource_cost_w_coeff(D, D.materials[mat_id])
return resources
/**
* Checks if the Exofab has enough resources to print a given item.
*
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
* Returns TRUE if there are sufficient resources to print the item.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(length(D.chemicals)) // No reagents storage - no reagent designs.
return FALSE
. = TRUE
var/list/coeff_required = get_resources_w_coeff(D)
for(var/mat_id in coeff_required)
if(materials[mat_id] < coeff_required[mat_id])
return FALSE
/**
* Attempts to build the next item in the build queue.
*
* Returns FALSE if either there are no more parts to build or the next part is not buildable.
* Returns TRUE if the next part has started building.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE)
if(!length(queue))
return FALSE
var/datum/design/D = queue[1]
if(build_part(D, verbose))
remove_from_queue(1)
return TRUE
return FALSE
/**
* Starts the build process for a given design datum.
*
* Returns FALSE if the procedure fails. Returns TRUE when being_built is set.
* Uses materials.
* * D - Design datum to attempt to print.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE)
if(!D)
return FALSE
if(!check_resources(D))
if(verbose)
atom_say("Not enough resources. Processing stopped.")
return FALSE
build_materials = get_resources_w_coeff(D)
for(var/mat_id in build_materials)
materials[mat_id] -= build_materials[mat_id]
being_built = D
build_finish = world.time + get_construction_time_w_coeff(initial(D.time))
build_start = world.time
desc = "It's building \a [D.name]."
return TRUE
/obj/machinery/mecha_part_fabricator/process()
..()
// If there's a stored part to dispense due to an obstruction, try to dispense it.
if(stored_part)
var/turf/exit = get_step(src,(dir))
if(exit.density)
return TRUE
atom_say("Obstruction cleared. \The [stored_part] is complete.")
stored_part.forceMove(exit)
stored_part = null
// If there's nothing being built, try to build something
if(!being_built)
// If we're not processing the queue anymore or there's nothing to build, end processing.
if(!process_queue || !build_next_in_queue())
on_finish_printing()
return PROCESS_KILL
on_start_printing()
// If there's an item being built, check if it is complete.
if(being_built && (build_finish < world.time))
// Then attempt to dispense it and if appropriate build the next item.
dispense_built_part(being_built)
if(process_queue)
build_next_in_queue(FALSE)
return TRUE
/**
* Dispenses a part to the tile infront of the Exosuit Fab.
*
* Returns FALSE is the machine cannot dispense the part on the appropriate turf.
* Return TRUE if the part was successfully dispensed.
* * D - Design datum to attempt to dispense.
*/
/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D)
var/obj/item/I = D.Fabricate(src, src)
// I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
// I.set_custom_materials(build_materials)
being_built = null
var/turf/exit = get_step(src,(dir))
if(exit.density)
atom_say("Error! Part outlet is obstructed.")
desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed."
stored_part = I
return FALSE
atom_say("\The [I] is complete.")
I.forceMove(exit)
return I
/**
* Adds a list of datum designs to the build queue.
*
* Will only add designs that are in this machine's stored techweb.
* Does final checks for datum IDs and makes sure this machine can build the designs.
* * part_list - List of datum design ids for designs to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list)
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && (D.id in part_list))
add_to_queue(D)
/**
* Adds a datum design to the build queue.
*
* Returns TRUE if successful and FALSE if the design was not added to the queue.
* * D - Datum design to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D)
if(!istype(queue))
queue = list()
if(D)
queue[++queue.len] = D
return TRUE
return FALSE
/**
* Removes datum design from the build queue based on index.
*
* Returns TRUE if successful and FALSE if a design was not removed from the queue.
* * index - Index in the build queue of the element to remove.
*/
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue)))
return FALSE
queue.Cut(index,++index)
return TRUE
/**
* Generates a list of parts formatted for tgui based on the current build queue.
*
* Returns a formatted list of lists containing formatted part information for every part in the build queue.
*/
/obj/machinery/mecha_part_fabricator/proc/list_queue()
if(!istype(queue) || !length(queue))
return null
var/list/queued_parts = list()
for(var/datum/design/D in queue)
var/list/part = output_part_info(D)
queued_parts += list(part)
return queued_parts
/obj/machinery/mecha_part_fabricator/proc/sync()
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
update_tgui_static_data(usr)
atom_say("Successfully synchronized with R&D server.")
return
atom_say("Unable to connect to local R&D server.")
return
/**
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
*
* Returns coefficient-modified resource cost for the given material component.
* * D - Design datum to pull the resource cost from.
* * resource - Material datum reference to the resource to calculate the cost of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/amt, roundto = 1)
return round(amt * component_coeff, roundto)
/**
* Calculates the coefficient-modified build time of a design.
*
* Returns coefficient-modified build time of a given design.
* * D - Design datum to calculate the modified build time of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran
return round(construction_time * time_coeff, roundto)
/obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
/obj/machinery/mecha_part_fabricator/attack_hand(var/mob/user)
if(..())
return
if(!allowed(user))
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/design/current = queue.len ? queue[1] : null
if(current)
data["current"] = current.name
data["queue"] = get_queue_names()
data["buildable"] = get_build_options()
data["category"] = category
data["categories"] = categories
data["materials"] = get_materials()
data["maxres"] = res_max_amount
data["sync"] = sync_message
if(current)
data["builtperc"] = round((progress / current.time) * 100)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
/obj/machinery/mecha_part_fabricator/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "mechfab.tmpl", "Exosuit Fabricator UI", 800, 600)
ui.set_initial_data(data)
ui = new(user, src, "ExosuitFabricator", name)
ui.open()
ui.set_auto_update(1)
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
if(..())
return
/obj/machinery/mecha_part_fabricator/tgui_static_data(mob/user)
var/list/data = list()
if(href_list["build"])
add_to_queue(text2num(href_list["build"]))
var/list/final_sets = list()
var/list/buildable_parts = list()
if(href_list["remove"])
remove_from_queue(text2num(href_list["remove"]))
for(var/part_set in part_sets)
final_sets += part_set
if(href_list["category"])
if(href_list["category"] in categories)
category = href_list["category"]
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && D.id != "id") // bugfix for weird null entries
// This is for us.
var/list/part = output_part_info(D, TRUE)
if(href_list["eject"])
eject_materials(href_list["eject"], text2num(href_list["amount"]))
if(part["categoryOverride"])
for(var/cat in part["categoryOverride"])
buildable_parts[cat] += list(part)
if(!(cat in part_sets))
final_sets += cat
continue
if(href_list["sync"])
sync()
for(var/cat in part_sets)
// Find all matching categories.
if(!(cat in D.category))
continue
buildable_parts[cat] += list(part)
data["partSets"] = final_sets
data["buildableParts"] = buildable_parts
return data
/obj/machinery/mecha_part_fabricator/tgui_data(mob/user)
var/list/data = list()
data["materials"] = output_available_resources()
if(being_built)
var/list/part = list(
"name" = being_built.name,
"duration" = build_finish - world.time,
"printTime" = get_construction_time_w_coeff(initial(being_built.time))
)
data["buildingPart"] = part
else
sync_message = ""
data["buildingPart"] = null
return 1
data["queue"] = list_queue()
if(stored_part)
data["storedPart"] = stored_part.name
else
data["storedPart"] = null
data["isProcessingQueue"] = process_queue
return data
/obj/machinery/mecha_part_fabricator/tgui_act(action, var/list/params)
if(..())
return TRUE
. = TRUE
add_fingerprint(usr)
usr.set_machine(src)
switch(action)
if("sync_rnd")
// Sync with R&D Servers
sync()
return
if("add_queue_set")
// Add all parts of a set to queue
var/part_list = params["part_list"]
add_part_set_to_queue(part_list)
return
if("add_queue_part")
// Add a specific part to queue
var/T = params["id"]
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && (D.id == T))
add_to_queue(D)
break
return
if("del_queue_part")
// Delete a specific from from the queue
var/index = text2num(params["index"])
remove_from_queue(index)
return
if("clear_queue")
// Delete everything from queue
queue.Cut()
return
if("build_queue")
// Build everything in queue
if(process_queue)
return
process_queue = TRUE
if(!being_built)
START_PROCESSING(SSobj, src)
return
if("stop_queue")
// Pause queue building. Also known as stop.
process_queue = FALSE
return
if("build_part")
// Build a single part
if(being_built || process_queue)
return
var/id = params["id"]
var/datum/design/D = null
for(var/datum/design/D_new in files.known_designs)
if((D_new.build_type == valid_buildtype) && (D_new.id == id))
D = D_new
break
if(!D)
return
if(build_part(D))
on_start_printing()
START_PROCESSING(SSobj, src)
return
if("move_queue_part")
// Moves a part up or down in the queue.
var/index = text2num(params["index"])
var/new_index = index + text2num(params["newindex"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,length(queue)))
queue.Swap(index,new_index)
return
if("remove_mat")
// Remove a material from the fab
var/mat_id = params["id"]
var/amount = text2num(params["amount"])
eject_materials(mat_id, amount)
return
return FALSE
/obj/machinery/mecha_part_fabricator/attackby(var/obj/item/I, var/mob/user)
if(busy)
if(being_built)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return 1
if(default_deconstruction_screwdriver(user, I))
@@ -146,15 +619,17 @@
if(materials[S.material.name] + amnt <= res_max_amount)
if(S && S.get_amount() >= 1)
var/count = 0
overlays += "mechfab-load-metal"
spawn(10)
overlays -= "mechfab-load-metal"
flick("[loading_icon_state]", src)
// yess hacky but whatever
if(loading_icon_state == "mechfab-idle")
overlays += "mechfab-load-metal"
spawn(10)
overlays -= "mechfab-load-metal"
while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1)
materials[S.material.name] += amnt
S.use(1)
count++
to_chat(user, "You insert [count] [sname] into the fabricator.")
update_busy()
else
to_chat(user, "The fabricator cannot hold more [sname].")
@@ -181,96 +656,6 @@
if(1)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"No records in User DB\"")
/obj/machinery/mecha_part_fabricator/proc/update_busy()
if(queue.len)
if(can_build(queue[1]))
busy = 1
else
busy = 0
else
busy = 0
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(var/index)
var/datum/design/D = files.known_designs[index]
queue += D
update_busy()
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(var/index)
if(index == 1)
progress = 0
queue.Cut(index, index + 1)
update_busy()
/obj/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D)
for(var/M in D.materials)
if(materials[M] < (D.materials[M] * mat_efficiency))
return 0
return 1
/obj/machinery/mecha_part_fabricator/proc/check_build()
if(!queue.len)
progress = 0
return
var/datum/design/D = queue[1]
if(!can_build(D))
progress = 0
return
if(D.time > progress)
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
if(D.build_path)
var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src)
visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
if(mat_efficiency != 1)
if(new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
new_item.matter[i] = new_item.matter[i] * mat_efficiency
remove_from_queue(1)
/obj/machinery/mecha_part_fabricator/proc/get_queue_names()
. = list()
for(var/i = 2 to queue.len)
var/datum/design/D = queue[i]
. += D.name
/obj/machinery/mecha_part_fabricator/proc/get_build_options()
. = list()
for(var/i = 1 to files.known_designs.len)
var/datum/design/D = files.known_designs[i]
if(!D.build_path || !(D.build_type & MECHFAB))
continue
. += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
/obj/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D)
var/list/F = list()
for(var/T in D.materials)
F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]"
return english_list(F, and_text = ", ")
/obj/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D)
return time2text(round(10 * D.time / speed), "mm:ss")
/obj/machinery/mecha_part_fabricator/proc/update_categories()
categories = list()
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & MECHFAB))
continue
categories |= D.category
if(!category || !(category in categories))
category = categories[1]
/obj/machinery/mecha_part_fabricator/proc/get_materials()
. = list()
for(var/T in materials)
var/hidden_mat = FALSE
for(var/HM in hidden_materials) // Direct list contents comparison was failing.
if(T == HM && materials[T] == 0)
hidden_mat = TRUE
continue
if(!hidden_mat)
. += list(list("mat" = capitalize(T), "amt" = materials[T]))
/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
@@ -287,17 +672,3 @@
materials[matstring] -= ejected * S.perunit
if(recursive && materials[matstring] >= S.perunit)
eject_materials(matstring, -1)
update_busy()
/obj/machinery/mecha_part_fabricator/proc/sync()
sync_message = "Error: no console found."
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
sync_message = "Sync complete."
update_categories()
+93 -290
View File
@@ -1,4 +1,4 @@
/obj/machinery/pros_fabricator
/obj/machinery/mecha_part_fabricator/pros
icon = 'icons/obj/robotics.dmi'
icon_state = "prosfab"
name = "Prosthetics Fabricator"
@@ -11,158 +11,126 @@
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/prosthetics
var/speed = 1
var/mat_efficiency = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0)
var/list/hidden_materials = list(MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM)
var/res_max_amount = 200000
var/datum/research/files
var/list/datum/design/queue = list()
var/progress = 0
var/busy = 0
var/list/categories = list()
var/category = null
// Prosfab specific stuff
var/manufacturer = null
var/species_types = list("Human")
var/species = "Human"
var/sync_message = ""
/obj/machinery/pros_fabricator/Initialize()
. = ..()
default_apply_parts()
loading_icon_state = "prosfab_loading"
files = new /datum/research(src) //Setup the research data holder.
materials = list(
DEFAULT_WALL_MATERIAL = 0,
"glass" = 0,
"plastic" = 0,
MAT_GRAPHITE = 0,
MAT_PLASTEEL = 0,
"gold" = 0,
"silver" = 0,
MAT_LEAD = 0,
"osmium" = 0,
"diamond" = 0,
MAT_DURASTEEL = 0,
"phoron" = 0,
"uranium" = 0,
MAT_VERDANTIUM = 0,
MAT_MORPHIUM = 0)
res_max_amount = 200000
/obj/machinery/pros_fabricator/Initialize()
valid_buildtype = PROSFAB
/// A list of categories that valid PROSFAB design datums will broadly categorise themselves under.
part_sets = list(
"Cyborg",
"Ripley",
"Odysseus",
"Gygax",
"Durand",
"Janus",
"Vehicle",
"Rigsuit",
"Phazon",
"Gopher", // VOREStation Add
"Polecat", // VOREStation Add
"Weasel", // VOREStation Add
"Exosuit Equipment",
"Exosuit Internals",
"Exosuit Ammunition",
"Cyborg Modules",
"Prosthetics",
"Prosthetics, Internal",
"Cyborg Parts",
"Cyborg Internals",
"Cybernetics",
"Implants",
"Control Interfaces",
"Other",
"Misc",
)
/obj/machinery/mecha_part_fabricator/pros/Initialize()
. = ..()
manufacturer = basic_robolimb.company
update_categories()
/obj/machinery/pros_fabricator/process()
..()
if(stat)
return
if(busy)
update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/pros/dispense_built_part(datum/design/D)
var/obj/item/I = ..()
if(isobj(I) && I.matter && I.matter.len > 0)
for(var/i in I.matter)
I.matter[i] = I.matter[i] * component_coeff
/obj/machinery/pros_fabricator/update_icon()
overlays.Cut()
icon_state = initial(icon_state)
/obj/machinery/mecha_part_fabricator/pros/tgui_data(mob/user)
var/list/data = ..()
if(panel_open)
overlays.Add(image(icon, "[icon_state]_panel"))
if(stat & NOPOWER)
return
if(busy)
icon_state = "[icon_state]_work"
/obj/machinery/pros_fabricator/dismantle()
for(var/f in materials)
eject_materials(f, -1)
..()
/obj/machinery/pros_fabricator/RefreshParts()
res_max_amount = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
res_max_amount += M.rating * 100000 // 200k -> 600k
var/T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
mat_efficiency = max(0.2, 1 - (T - 1) / 4) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
T += M.rating
speed = T / 2 // 1 -> 3
/obj/machinery/pros_fabricator/attack_hand(var/mob/user)
if(..())
return
if(!allowed(user))
return
ui_interact(user)
/obj/machinery/pros_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/design/current = queue.len ? queue[1] : null
if(current)
data["current"] = current.name
data["queue"] = get_queue_names()
data["buildable"] = get_build_options()
data["category"] = category
data["categories"] = categories
data["species_types"] = species_types
data["species"] = species
if(all_robolimbs)
var/list/T = list()
for(var/A in all_robolimbs)
var/datum/robolimb/R = all_robolimbs[A]
if(R.unavailable_to_build) continue
if(species in R.species_cannot_use) continue
if(R.unavailable_to_build)
continue
if(species in R.species_cannot_use)
continue
T += list(list("id" = A, "company" = R.company))
data["manufacturers"] = T
data["manufacturer"] = manufacturer
data["materials"] = get_materials()
data["maxres"] = res_max_amount
data["sync"] = sync_message
if(current)
data["builtperc"] = round((progress / current.time) * 100)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "mechfab.tmpl", "Prosthetics Fab UI", 800, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["manufacturer"] = manufacturer
/obj/machinery/pros_fabricator/Topic(href, href_list)
return data
/obj/machinery/mecha_part_fabricator/pros/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
if(href_list["build"])
add_to_queue(text2num(href_list["build"]))
. = TRUE
if(href_list["remove"])
remove_from_queue(text2num(href_list["remove"]))
add_fingerprint(usr)
usr.set_machine(src)
if(href_list["category"])
if(href_list["category"] in categories)
category = href_list["category"]
switch(action)
if("species")
var/new_species = input(usr, "Select a new species", "Prosfab Species Selection", "Human") as null|anything in species_types
if(new_species && tgui_status(usr, state) == STATUS_INTERACTIVE)
species = new_species
return
if("manufacturer")
var/list/new_manufacturers = list()
for(var/A in all_robolimbs)
var/datum/robolimb/R = all_robolimbs[A]
if(R.unavailable_to_build)
continue
if(species in R.species_cannot_use)
continue
new_manufacturers += A
if(href_list["species"])
if(href_list["species"] in species_types)
species = href_list["species"]
var/new_manufacturer = input(usr, "Select a new manufacturer", "Prosfab Species Selection", "Unbranded") as null|anything in new_manufacturers
if(new_manufacturer && tgui_status(usr, state) == STATUS_INTERACTIVE)
manufacturer = new_manufacturer
return
return FALSE
if(href_list["manufacturer"])
if(href_list["manufacturer"] in all_robolimbs)
manufacturer = href_list["manufacturer"]
if(href_list["eject"])
eject_materials(href_list["eject"], text2num(href_list["amount"]))
if(href_list["sync"])
sync()
else
sync_message = ""
return 1
/obj/machinery/pros_fabricator/attackby(var/obj/item/I, var/mob/user)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
/obj/machinery/mecha_part_fabricator/pros/attackby(var/obj/item/I, var/mob/user)
if(..())
return 1
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
if(istype(I,/obj/item/weapon/disk/limb))
var/obj/item/weapon/disk/limb/D = I
@@ -188,168 +156,3 @@
to_chat(user, "<span class='notice'>Uploaded [D.species] files!</span>")
qdel(I)
return
if(istype(I,/obj/item/stack/material))
var/obj/item/stack/material/S = I
if(!(S.material.name in materials))
to_chat(user, "<span class='warning'>The [src] doesn't accept [S.material]!</span>")
return
var/sname = "[S.name]"
var/amnt = S.perunit
if(materials[S.material.name] + amnt <= res_max_amount)
if(S && S.get_amount() >= 1)
var/count = 0
flick("[initial(icon_state)]_loading", src)
while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1)
materials[S.material.name] += amnt
S.use(1)
count++
to_chat(user, "You insert [count] [sname] into the fabricator.")
update_busy()
else
to_chat(user, "The fabricator cannot hold more [sname].")
return
..()
/obj/machinery/pros_fabricator/emag_act(var/remaining_charges, var/mob/user)
switch(emagged)
if(0)
emagged = 0.5
visible_message("[bicon(src)] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
sleep(10)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"Attempting auto-repair\"")
sleep(15)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
sleep(30)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
req_access = null
emagged = 1
return 1
if(0.5)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
if(1)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"No records in User DB\"")
/obj/machinery/pros_fabricator/proc/update_busy()
if(queue.len)
if(can_build(queue[1]))
busy = 1
else
busy = 0
else
busy = 0
/obj/machinery/pros_fabricator/proc/add_to_queue(var/index)
var/datum/design/D = files.known_designs[index]
queue += D
update_busy()
/obj/machinery/pros_fabricator/proc/remove_from_queue(var/index)
if(index == 1)
progress = 0
queue.Cut(index, index + 1)
update_busy()
/obj/machinery/pros_fabricator/proc/can_build(var/datum/design/D)
for(var/M in D.materials)
if(materials[M] < (D.materials[M] * mat_efficiency))
return 0
return 1
/obj/machinery/pros_fabricator/proc/check_build()
if(!queue.len)
progress = 0
return
var/datum/design/D = queue[1]
if(!can_build(D))
progress = 0
return
if(D.time > progress)
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
if(D.build_path)
var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src) // Sometimes returns a mob. Beware!
flick("[initial(icon_state)]_finish", src)
visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
if(mat_efficiency != 1)
if(istype(new_item, /obj/) && new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
new_item.matter[i] = new_item.matter[i] * mat_efficiency
remove_from_queue(1)
/obj/machinery/pros_fabricator/proc/get_queue_names()
. = list()
for(var/i = 2 to queue.len)
var/datum/design/D = queue[i]
. += D.name
/obj/machinery/pros_fabricator/proc/get_build_options()
. = list()
for(var/i = 1 to files.known_designs.len)
var/datum/design/D = files.known_designs[i]
if(D.build_path && (D.build_type & PROSFAB))
. += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
/obj/machinery/pros_fabricator/proc/get_design_resourses(var/datum/design/D)
var/list/F = list()
for(var/T in D.materials)
F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]"
return english_list(F, and_text = ", ")
/obj/machinery/pros_fabricator/proc/get_design_time(var/datum/design/D)
return time2text(round(10 * D.time / speed), "mm:ss")
/obj/machinery/pros_fabricator/proc/update_categories()
categories = list()
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & PROSFAB))
continue
categories |= D.category
if(!category || !(category in categories))
category = categories[1]
/obj/machinery/pros_fabricator/proc/get_materials()
. = list()
for(var/T in materials)
var/hidden_mat = FALSE
for(var/HM in hidden_materials) // Direct list contents comparison was failing.
if(T == HM && materials[T] == 0)
hidden_mat = TRUE
continue
if(!hidden_mat)
. += list(list("mat" = capitalize(T), "amt" = materials[T]))
/obj/machinery/pros_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
var/material/M = get_material_by_name(matstring)
var/obj/item/stack/material/S = M.place_sheet(get_turf(src))
if(amount <= 0)
amount = S.max_amount
var/ejected = min(round(materials[matstring] / S.perunit), amount)
S.amount = min(ejected, amount)
if(S.amount <= 0)
qdel(S)
return
materials[matstring] -= ejected * S.perunit
if(recursive && materials[matstring] >= S.perunit)
eject_materials(matstring, -1)
update_busy()
/obj/machinery/pros_fabricator/proc/sync()
sync_message = "Error: no console found."
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
sync_message = "Sync complete."
update_categories()
+10
View File
@@ -2243,6 +2243,16 @@
output += "</body></html>"
return output
/obj/mecha/proc/get_log_tgui()
var/list/data = list()
for(var/list/entry in log)
data.Add(list(list(
"time" = time2text(entry["time"], "DDD MMM DD hh:mm:ss"),
"year" = game_year,
"message" = entry["message"],
)))
return data
/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user)
if(!id_card || !user) return
+107 -94
View File
@@ -8,61 +8,65 @@
circuit = /obj/item/weapon/circuitboard/mecha_control
var/list/located = list()
var/screen = 0
var/stored_data
var/list/stored_data
attack_ai(var/mob/user as mob)
return src.attack_hand(user)
/obj/machinery/computer/mecha/attack_ai(mob/user)
return attack_hand(user)
attack_hand(var/mob/user as mob)
if(..())
return
user.set_machine(src)
var/dat = "<html><head><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=\ref[src];send_message=\ref[TR]'>Send message</a><br/>
<a href='?src=\ref[src];get_log=\ref[TR]'>Show exosuit log</a> | <a style='color: #f00;' href='?src=\ref[src];shock=\ref[TR]'>(EMP pulse)</a><br>"}
if(screen==1)
dat += "<h3>Log contents</h3>"
dat += "<a href='?src=\ref[src];return=1'>Return</a><hr>"
dat += "[stored_data]"
dat += "<A href='?src=\ref[src];refresh=1'>(Refresh)</A><BR>"
dat += "</body></html>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
/obj/machinery/computer/mecha/attack_hand(mob/user)
if(..())
return
tgui_interact(user)
Topic(href, href_list)
if(..())
return
var/datum/topic_input/top_filter = new /datum/topic_input(href,href_list)
if(href_list["send_message"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("send_message")
var/message = sanitize(input(usr,"Input message","Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return
if(href_list["shock"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("shock")
MT.shock()
if(href_list["get_log"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("get_log")
stored_data = MT.get_mecha_log()
screen = 1
if(href_list["return"])
screen = 0
src.updateUsrDialog()
return
/obj/machinery/computer/mecha/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MechaControlConsole", name)
ui.open()
/obj/machinery/computer/mecha/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["beacons"] = list()
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/list/tr_data = TR.tgui_data(user)
if(tr_data)
data["beacons"].Add(list(tr_data))
LAZYINITLIST(stored_data)
data["stored_data"] = stored_data
return data
/obj/machinery/computer/mecha/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("send_message")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
var/message = sanitize(input(usr, "Input message", "Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return TRUE
if("shock")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
MT.shock()
return TRUE
if("get_log")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
stored_data = MT.get_mecha_log()
return TRUE
if("clear_log")
stored_data = null
return TRUE
/obj/item/mecha_parts/mecha_tracking
name = "Exosuit tracking beacon"
@@ -71,58 +75,67 @@
icon_state = "motion2"
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
proc/get_mecha_info()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/answer = {"<b>Name:</b> [M.name]<br>
<b>Integrity:</b> [M.health/initial(M.health)*100]%<br>
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]<br>
<b>Airtank:</b> [M.return_pressure()]kPa<br>
<b>Pilot:</b> [M.occupant||"None"]<br>
<b>Location:</b> [get_area(M)||"Unknown"]<br>
<b>Active equipment:</b> [M.selected||"None"]"}
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
/obj/item/mecha_parts/mecha_tracking/tgui_data(mob/user)
var/list/data = ..()
if(!in_mecha())
return FALSE
return answer
var/obj/mecha/M = loc
data["ref"] = REF(src)
data["charge"] = M.get_charge()
data["name"] = M.name
data["health"] = M.health
data["maxHealth"] = initial(M.health)
data["cell"] = M.cell
if(M.cell)
data["cellCharge"] = M.cell.charge
data["cellMaxCharge"] = M.cell.charge
data["airtank"] = M.return_pressure()
data["pilot"] = M.occupant
data["location"] = get_area(M)
data["active"] = M.selected
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
data["cargoUsed"] = RM.cargo.len
data["cargoMax"] = RM.cargo_capacity
emp_act()
qdel(src)
return
return data
ex_act()
qdel(src)
return
/obj/item/mecha_parts/mecha_tracking/emp_act()
qdel(src)
return
proc/in_mecha()
if(istype(src.loc, /obj/mecha))
return src.loc
return 0
/obj/item/mecha_parts/mecha_tracking/ex_act()
qdel(src)
return
proc/shock()
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(4)
qdel(src)
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
if(istype(loc, /obj/mecha))
return loc
return 0
proc/get_mecha_log()
if(!src.in_mecha())
return 0
var/obj/mecha/M = src.loc
return M.get_log_html()
/obj/item/mecha_parts/mecha_tracking/proc/shock()
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(4)
qdel(src)
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
if(!in_mecha())
return list()
var/obj/mecha/M = loc
return M.get_log_tgui()
/obj/item/weapon/storage/box/mechabeacons
name = "Exosuit Tracking Beacons"
New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
/obj/item/weapon/storage/box/mechabeacons/New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
+3 -3
View File
@@ -1,5 +1,5 @@
/datum/design/item/mechfab/gopher
category = "Gopher"
category = list("Gopher")
time = 5
/datum/design/item/mechfab/gopher/chassis
@@ -55,7 +55,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 2500)
/datum/design/item/mechfab/polecat
category = "Polecat"
category = list("Polecat")
time = 10
/datum/design/item/mechfab/polecat/chassis
@@ -134,7 +134,7 @@
build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/microshotgun
/datum/design/item/mechfab/weasel
category = "Weasel"
category = list("Weasel")
time = 5
/datum/design/item/mechfab/weasel/chassis
@@ -12,6 +12,8 @@
name = "rolled-up poster"
desc = "The poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface."
icon_state = "rolled_poster"
drop_sound = 'sound/items/drop/wrapper.ogg'
pickup_sound = 'sound/items/pickup/wrapper.ogg'
var/serial_number = null
var/poster_type = /obj/structure/sign/poster
@@ -9,6 +9,11 @@ Portals do have some specific requirements when mapping them in;
- There must by one, and only one `/obj/effect/map_effect/portal/master` for each side of a portal.
- Both sides need to have matching `portal_id`s in order to link to each other.
- Each side must face opposite directions, e.g. if side A faces SOUTH, side B must face NORTH.
- Clarification on the above - you will be moved in the direction that the portal faces.
If Side A faces south, you will be moved south. Dirs are 1/2/4/8, 1: NORTH, 2: SOUTH, 4: EAST, 8: WEST.
To further explain: If your cave entrance is on the NORTH side of the map on ENTRY side, and SOUTH side on EXIT side:
You will need to set the ENTRY side's dir to 2, IE SOUTH, as that's the direction you will moving coming FROM the EXIT side.
IE: Directions should be set based on the direction of travel.
- Each side must have the same orientation, e.g. horizontal on both sides, or vertical on both sides.
- Portals can be made to be longer than 1x1 with `/obj/effect/map_effect/portal/line`s,
but both sides must have the same length.
@@ -341,4 +346,4 @@ when portals are shortly lived, or when portals are made to be obvious with spec
/obj/effect/map_effect/portal/line/side_b
name = "portal line B"
icon_state = "portal_line_side_b"
icon_state = "portal_line_side_b"
+1 -1
View File
@@ -113,7 +113,7 @@
triggered = 1
for (var/turf/simulated/floor/target in range(1,src))
if(!target.blocks_air)
target.assume_gas("sleeping_agent", 30)
target.assume_gas("nitrous_oxide", 30)
visible_message("\The [src.name] detonates!")
spawn(0)
qdel(src)
+38 -4
View File
@@ -91,8 +91,16 @@
var/icon/default_worn_icon //Default on-mob icon
var/worn_layer //Default on-mob layer
var/drop_sound = 'sound/items/drop/device.ogg' // drop sound - this is the default
// Pickup/Drop/Equip/Throw Sounds
///Used when thrown into a mob
var/mob_throw_hit_sound
// Sound used when equipping the items into a valid slot.
var/equip_sound
// pickup sound - this is the default
var/pickup_sound = 'sound/items/pickup/device.ogg'
// drop sound - this is the default
var/drop_sound = 'sound/items/drop/device.ogg'
var/tip_timer // reference to timer id for a tooltip we might open soon
@@ -278,10 +286,29 @@
/obj/item/proc/moved(mob/user as mob, old_loc as turf)
return
/obj/item/proc/get_volume_by_throwforce_and_or_w_class() // This is used for figuring out how loud our sounds are for throwing.
if(throwforce && w_class)
return CLAMP((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return CLAMP(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
/obj/item/throw_impact(atom/hit_atom)
..()
if(drop_sound)
playsound(src, drop_sound, 50, 0, preference = /datum/client_preference/drop_sounds)
if(isliving(hit_atom)) //Living mobs handle hit sounds differently.
var/volume = get_volume_by_throwforce_and_or_w_class()
if (throwforce > 0)
if (mob_throw_hit_sound)
playsound(hit_atom, mob_throw_hit_sound, volume, TRUE, -1)
else if(hitsound)
playsound(hit_atom, hitsound, volume, TRUE, -1)
else
playsound(hit_atom, 'sound/weapons/genhit.ogg', volume, TRUE, -1)
else
playsound(hit_atom, 'sound/weapons/throwtap.ogg', 1, volume, -1)
else
playsound(src, drop_sound, 30, preference = /datum/client_preference/drop_sounds)
// apparently called whenever an item is removed from a slot, container, or anything else.
/obj/item/proc/dropped(mob/user as mob)
@@ -318,6 +345,13 @@
user.position_hud_item(src,slot)
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
if((slot_flags & slot))
if(equip_sound)
playsound(src, equip_sound, 30)
else
playsound(src, drop_sound, 30)
else if(slot == slot_l_hand || slot == slot_r_hand)
playsound(src, pickup_sound, 20, preference = /datum/client_preference/pickup_sounds)
return
//Defines which slots correspond to which slot flags
@@ -51,6 +51,8 @@ var/list/civilian_cartridges = list(
icon_state = "cart"
item_state = "electronic"
w_class = ITEMSIZE_TINY
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
var/obj/item/radio/integrated/radio = null
var/access_security = 0
@@ -239,6 +239,8 @@
desc = "A pen-sized light, used by medical staff."
icon_state = "penlight"
item_state = "pen"
drop_sound = 'sound/items/drop/accessory.ogg'
pickup_sound = 'sound/items/pickup/accessory.ogg'
slot_flags = SLOT_EARS
brightness_on = 2
w_class = ITEMSIZE_TINY
@@ -330,6 +332,8 @@
var/on_damage = 7
var/produce_heat = 1500
power_use = 0
drop_sound = 'sound/items/drop/gloves.ogg'
pickup_sound = 'sound/items/pickup/gloves.ogg'
/obj/item/device/flashlight/flare/New()
fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
+3 -1
View File
@@ -7,13 +7,15 @@
/obj/item/device/multitool
name = "multitool"
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
description_info = "You can use this on airlocks or APCs to try to hack them without cutting wires."
icon_state = "multitool"
force = 5.0
w_class = ITEMSIZE_SMALL
throwforce = 5.0
throw_range = 15
throw_speed = 3
desc = "You can use this on airlocks or APCs to try to hack them without cutting wires."
drop_sound = 'sound/items/drop/multitool.ogg'
pickup_sound = 'sound/items/pickup/multitool.ogg'
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
@@ -66,7 +66,7 @@
channels = list("Command" = 1)
/obj/item/device/encryptionkey/heads/captain
name = "colony director's encryption key"
name = "site manager's encryption key"
icon_state = "cap_cypherkey"
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1)
@@ -10,7 +10,7 @@
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1, "AI Private" = 1, "Explorer" = 1)
/obj/item/device/encryptionkey/heads/captain
name = "colony director's encryption key"
name = "site manager's encryption key"
icon_state = "cap_cypherkey"
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1, "Explorer" = 1)
@@ -16,6 +16,9 @@
var/obj/item/device/encryptionkey/keyslot2 = null
var/ks1type = null
var/ks2type = null
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
/obj/item/device/radio/headset/New()
..()
@@ -77,6 +80,9 @@
return "[..()][append]"
/obj/item/device/radio/headset/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/radio/headset/syndicate
origin_tech = list(TECH_ILLEGAL = 3)
syndie = 1
@@ -170,13 +176,13 @@
/obj/item/device/radio/headset/heads/captain
name = "colony director's headset"
name = "site manager's headset"
desc = "The headset of the boss."
icon_state = "com_headset"
ks2type = /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/captain/alt
name = "colony director's bowman headset"
name = "site manager's bowman headset"
desc = "The headset of the boss."
icon_state = "com_headset_alt"
ks2type = /obj/item/device/encryptionkey/heads/captain
@@ -252,13 +258,13 @@
/obj/item/device/radio/headset/heads/hop
name = "head of personnel's headset"
desc = "The headset of the guy who will one day be Colony Director."
desc = "The headset of the guy who will one day be Site Manager."
icon_state = "com_headset"
ks2type = /obj/item/device/encryptionkey/heads/hop
/obj/item/device/radio/headset/heads/hop/alt
name = "head of personnel's bowman headset"
desc = "The headset of the guy who will one day be Colony Director."
desc = "The headset of the guy who will one day be Site Manager."
icon_state = "com_headset_alt"
ks2type = /obj/item/device/encryptionkey/heads/hop
@@ -168,7 +168,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/tgui_data(mob/user)
var/data[0]
data["rawfreq"] = num2text(frequency)
data["rawfreq"] = frequency
data["listening"] = listening
data["broadcasting"] = broadcasting
data["subspace"] = subspace_transmission
@@ -5,7 +5,7 @@
icon_state = "valve_1"
var/obj/item/weapon/tank/tank_one
var/obj/item/weapon/tank/tank_two
var/obj/item/device/attached_device
var/obj/item/device/assembly/attached_device
var/mob/attacher = null
var/valve_open = 0
var/toggle = 1
@@ -20,18 +20,18 @@
if(!tank_one)
tank_one = item
user.drop_item()
item.loc = src
item.forceMove(src)
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
else if(!tank_two)
tank_two = item
user.drop_item()
item.loc = src
item.forceMove(src)
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
message_admins("[key_name_admin(user)] attached both tanks to a transfer valve. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
log_game("[key_name_admin(user)] attached both tanks to a transfer valve.")
update_icon()
SSnanoui.update_uis(src) // update all UIs attached to src
SStgui.update_uis(src) // update all UIs attached to src
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/device/assembly/A = item
@@ -43,7 +43,7 @@
return
user.remove_from_mob(item)
attached_device = A
A.loc = src
A.forceMove(src)
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
A.holder = src
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
@@ -52,7 +52,7 @@
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
attacher = user
SSnanoui.update_uis(src) // update all UIs attached to src
SStgui.update_uis(src) // update all UIs attached to src
return
@@ -66,53 +66,51 @@
if(isturf(loc))
sense_proximity(callback = .HasProximity)
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
ui_interact(user)
/obj/item/device/transfer_valve/attack_self(mob/user)
tgui_interact(user)
/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/item/device/transfer_valve/tgui_state(mob/user)
return GLOB.tgui_inventory_state
// this is the data which will be sent to the ui
var/data[0]
data["attachmentOne"] = tank_one ? tank_one.name : null
data["attachmentTwo"] = tank_two ? tank_two.name : null
data["valveAttachment"] = attached_device ? attached_device.name : null
data["valveOpen"] = valve_open ? 1 : 0
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
/obj/item/device/transfer_valve/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TransferValve", name) // 460, 320
ui.open()
// auto update every Master Controller tick
//ui.set_auto_update(1)
/obj/item/device/transfer_valve/Topic(href, href_list)
..()
if ( usr.stat || usr.restrained() )
return 0
if (src.loc != usr)
return 0
if(tank_one && href_list["tankone"])
remove_tank(tank_one)
else if(tank_two && href_list["tanktwo"])
remove_tank(tank_two)
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.loc = get_turf(src)
attached_device:holder = null
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
src.add_fingerprint(usr)
return 1 // Returning 1 sends an update to attached UIs
/obj/item/device/transfer_valve/tgui_data(mob/user)
var/list/data = list()
data["tank_one"] = tank_one ? tank_one.name : null
data["tank_two"] = tank_two ? tank_two.name : null
data["attached_device"] = attached_device ? attached_device.name : null
data["valve"] = valve_open
return data
/obj/item/device/transfer_valve/tgui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("tankone")
remove_tank(tank_one)
if("tanktwo")
remove_tank(tank_two)
if("toggle")
toggle_valve()
if("device")
if(attached_device)
attached_device.attack_self(usr)
if("remove_device")
if(attached_device)
attached_device.forceMove(get_turf(src))
attached_device.holder = null
attached_device = null
update_icon()
else
. = FALSE
if(.)
update_icon()
add_fingerprint(usr)
/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D)
if(toggle)
@@ -148,7 +146,7 @@
else
return
T.loc = get_turf(src)
T.forceMove(get_turf(src))
update_icon()
/obj/item/device/transfer_valve/proc/merge_gases()

Some files were not shown because too many files have changed in this diff Show More