Merge branch 'master' into pol-rndconsole

This commit is contained in:
Aronai Sieyes
2020-05-11 14:30:44 -04:00
committed by GitHub
158 changed files with 1850 additions and 1581 deletions

View File

@@ -21,15 +21,9 @@
var/set_temperature = T20C // Thermostat
var/cooling = 0
/obj/machinery/atmospherics/unary/freezer/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/atmospherics/unary/freezer/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/atmospherics/unary/freezer/atmos_init()
if(node)

View File

@@ -21,15 +21,9 @@
var/set_temperature = T20C //thermostat
var/heating = 0 //mainly for icon updates
/obj/machinery/atmospherics/unary/heater/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
/obj/machinery/atmospherics/unary/heater/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/atmospherics/unary/heater/atmos_init()
if(node)

View File

@@ -16,13 +16,19 @@
// Inputs: The turf the airflow is from, which may not be the same as loc. is_zone is for conditionally disallowing merging.
// Outputs: Boolean if airflow can pass.
/atom/proc/CanZASPass(turf/T, is_zone)
// Behaviors defined here so when people directly call c_airblock it will still obey can_atmos_pass
switch(can_atmos_pass)
if(ATMOS_PASS_YES)
return TRUE
if(ATMOS_PASS_NO)
return FALSE
if(ATMOS_PASS_DENSITY)
return !density
if(ATMOS_PASS_PROC)
// Cowardly refuse to recursively self-call CanZASPass. The hero BYOND needs?
CRASH("can_atmos_pass = ATMOS_PASS_PROC but CanZASPass not overridden on [src] ([type])")
else
return can_atmos_pass
/turf/can_atmos_pass = ATMOS_PASS_NO
CRASH("Invalid can_atmos_pass = [can_atmos_pass] on [src] ([type])")
/turf/CanPass(atom/movable/mover, turf/target)
if(!target) return FALSE
@@ -89,6 +95,15 @@ turf/c_airblock(turf/other)
var/result = 0
for(var/mm in contents)
var/atom/movable/M = mm
result |= M.c_airblock(other)
switch(M.can_atmos_pass)
if(ATMOS_PASS_YES)
continue
if(ATMOS_PASS_NO)
return BLOCKED
if(ATMOS_PASS_DENSITY)
if(M.density)
return BLOCKED
if(ATMOS_PASS_PROC)
result |= M.c_airblock(other)
if(result == BLOCKED) return BLOCKED
return result

View File

@@ -4,3 +4,10 @@
#define BLOCKED 3 // Blocked, zone boundaries will not cross even if opened.
#define ZONE_MIN_SIZE 14 // Zones with less than this many turfs will always merge, even if the connection is not direct
// Used for quickly making certain things allow airflow or not.
// More complicated, conditional airflow should override CanZASPass().
#define ATMOS_PASS_YES 1 // Always blocks air and zones.
#define ATMOS_PASS_NO 2 // Never blocks air or zones.
#define ATMOS_PASS_DENSITY 3 // Blocks air and zones if density = 1, allows both if density = 0
#define ATMOS_PASS_PROC 4 // Call CanZASPass() using c_airblock

View File

@@ -94,9 +94,3 @@
#define ATMOSTANK_CO2 25000 // CO2 and PH are not critically important for station, only for toxins and alternative coolants, no need to store a lot of those.
#define ATMOSTANK_PHORON 25000
#define ATMOSTANK_NITROUSOXIDE 10000 // N2O doesn't have a real useful use, i guess it's on station just to allow refilling of sec's riot control canisters?
// Used for quickly making certain things allow airflow or not.
// More complicated, conditional airflow should override CanZASPass().
#define ATMOS_PASS_YES 1
#define ATMOS_PASS_NO 0
#define ATMOS_PASS_DENSITY -1 // Just checks density.

View File

@@ -35,8 +35,8 @@
#define BE_RAIDER 0x800
#define BE_PLANT 0x1000
#define BE_MUTINEER 0x2000
#define BE_PAI 0x4000
#define BE_LOYALIST 0x8000
#define BE_LOYALIST 0x4000
#define BE_PAI 0x8000
var/list/be_special_flags = list(
"Traitor" = BE_TRAITOR,
@@ -45,7 +45,6 @@ var/list/be_special_flags = list(
"Wizard" = BE_WIZARD,
"Malf AI" = BE_MALF,
"Revolutionary" = BE_REV,
"Loyalist" = BE_LOYALIST,
"Xenomorph" = BE_ALIEN,
"Positronic Brain" = BE_AI,
"Cultist" = BE_CULTIST,
@@ -54,7 +53,8 @@ var/list/be_special_flags = list(
"Raider" = BE_RAIDER,
"Diona" = BE_PLANT,
"Mutineer" = BE_MUTINEER,
"pAI" = BE_PAI
"Loyalist" = BE_LOYALIST,
"pAI" = BE_PAI,
)

View File

@@ -53,4 +53,5 @@
//---------------
//#define isturf(D) istype(D, /turf) //Built in
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isspace(A) istype(A, /turf/space)

View File

@@ -82,6 +82,7 @@
#define LIGHT_COLOR_INCANDESCENT_TUBE "#FFFEB8"
#define LIGHT_COLOR_INCANDESCENT_BULB "#FFDDBB"
#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66"
#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86"
//Fake ambient occlusion filter
#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, offset=3, color="#04080F80")

View File

@@ -372,3 +372,8 @@ var/global/list/##LIST_NAME = list();\
// Used by radios to indicate that they have sent a message via something other than subspace
#define RADIO_CONNECTION_FAIL 0
#define RADIO_CONNECTION_NON_SUBSPACE 1
#define JOB_CARBON 0x1
#define JOB_SILICON_ROBOT 0x2
#define JOB_SILICON_AI 0x4
#define JOB_SILICON 0x6 // 2|4, probably don't set jobs to this, but good for checking

View File

@@ -1,6 +1,15 @@
// Modes for examine text output
#define EXAMINE_MODE_DEFAULT 0
#define EXAMINE_MODE_INCLUDE_USAGE 1
#define EXAMINE_MODE_SWITCH_TO_PANEL 2
// Should be one higher than the above
#define EXAMINE_MODE_MAX 3
#define EXAMINE_MODE_MAX 3
// Modes for parsing multilingual speech
#define MULTILINGUAL_DEFAULT 0
#define MULTILINGUAL_SPACE 1
#define MULTILINGUAL_DOUBLE_DELIMITER 2
#define MULTILINGUAL_OFF 3
#define MULTILINGUAL_MODE_MAX 4

View File

@@ -53,7 +53,7 @@
#define LANGUAGE_AKHANI "Akhani"
#define LANGUAGE_ALAI "Alai"
#define LANGUAGE_ZADDAT "Vedahq"
#define LANGUAGE_PROMETHEAN "Promethean"
#define LANGUAGE_PROMETHEAN "Promethean Biolinguistics"
#define LANGUAGE_BLOB "Blob"
#define LANGUAGE_GIBBERISH "Babel"

View File

@@ -68,8 +68,9 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_ASSETS -3
#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_HOLOMAPS -5
#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_ALARM -7
#define INIT_ORDER_NIGHTSHIFT -6
#define INIT_ORDER_OVERLAY -7
#define INIT_ORDER_ALARM -8
#define INIT_ORDER_OPENSPACE -10
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
@@ -84,6 +85,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_SUPPLY 5
#define FIRE_PRIORITY_NIGHTSHIFT 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10

View File

@@ -35,25 +35,25 @@
return wtime + (time_offset + wusage) * world.tick_lag
var/roundstart_hour
GLOBAL_VAR_INIT(roundstart_hour, pick(2,7,12,17))
var/station_date = ""
var/next_station_date_change = 1 DAY
#define duration2stationtime(time) time2text(station_time_in_ticks + time, "hh:mm")
#define worldtime2stationtime(time) time2text(roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0)
#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks)
#define duration2stationtime(time) time2text(station_time_in_ds + time, "hh:mm")
#define worldtime2stationtime(time) time2text(GLOB.roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ds (GLOB.round_start_time ? world.time - GLOB.round_start_time : 0)
#define station_time_in_ds (GLOB.roundstart_hour HOURS + round_duration_in_ds)
/proc/stationtime2text()
return time2text(station_time_in_ticks, "hh:mm")
return time2text(station_time_in_ds + GLOB.timezoneOffset, "hh:mm")
/proc/stationdate2text()
var/update_time = FALSE
if(station_time_in_ticks > next_station_date_change)
if(station_time_in_ds > next_station_date_change)
next_station_date_change += 1 DAY
update_time = TRUE
if(!station_date || update_time)
var/extra_days = round(station_time_in_ticks / (1 DAY)) DAYS
var/extra_days = round(station_time_in_ds / (1 DAY)) DAYS
var/timeofday = world.timeofday + extra_days
station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD")
return station_date
@@ -64,6 +64,13 @@ var/next_station_date_change = 1 DAY
var/time_portion = time2text(world.timeofday, "hh:mm:ss")
return "[date_portion]T[time_portion]"
/proc/get_timezone_offset()
var/midnight_gmt_here = text2num(time2text(0,"hh")) * 36000
if(midnight_gmt_here > 12 HOURS)
return 24 HOURS - midnight_gmt_here
else
return midnight_gmt_here
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
@@ -83,19 +90,19 @@ proc/isDay(var/month, var/day)
var/next_duration_update = 0
var/last_round_duration = 0
var/round_start_time = 0
GLOBAL_VAR_INIT(round_start_time, 0)
/hook/roundstart/proc/start_timer()
round_start_time = world.time
GLOB.round_start_time = world.time
return 1
/proc/roundduration2text()
if(!round_start_time)
if(!GLOB.round_start_time)
return "00:00"
if(last_round_duration && world.time < next_duration_update)
return last_round_duration
var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
var/mills = round_duration_in_ds // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
@@ -112,10 +119,6 @@ var/round_start_time = 0
var/datum/controller/process/process = processScheduler.getProcess(process_name)
return process.schedule_interval
/hook/startup/proc/set_roundstart_hour()
roundstart_hour = pick(2,7,12,17)
return 1
/var/midnight_rollovers = 0
/var/rollovercheck_last_timeofday = 0
/proc/update_midnight_rollover()

View File

@@ -50,8 +50,8 @@
/obj/machinery/teleport/hub/attack_ghost(mob/user as mob)
var/atom/l = loc
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
if(com.locked)
user.loc = get_turf(com.locked)
if(com?.teleport_control.locked)
user.loc = get_turf(com.teleport_control.locked)
/obj/effect/portal/attack_ghost(mob/user as mob)
if(target)

View File

@@ -12,6 +12,6 @@ datum/controller/transfer_controller/Destroy()
datum/controller/transfer_controller/process()
currenttick = currenttick + 1
if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
if (round_duration_in_ds >= timerbuffer - 1 MINUTE)
SSvote.autotransfer()
timerbuffer = timerbuffer + config.vote_autotransfer_interval

View File

@@ -270,6 +270,9 @@ var/list/gamemode_cache = list()
// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
var/disable_cid_warn_popup = FALSE
// whether or not to use the nightshift subsystem to perform lighting changes
var/static/enable_night_shifts = FALSE
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -888,6 +891,9 @@ var/list/gamemode_cache = list()
if("disable_cid_warn_popup")
config.disable_cid_warn_popup = TRUE
if("enable_night_shifts")
config.enable_night_shifts = TRUE
else
log_misc("Unknown setting in configuration: '[name]'")

View File

@@ -109,7 +109,7 @@ SUBSYSTEM_DEF(game_master)
return FALSE
// Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)

View File

@@ -0,0 +1,62 @@
SUBSYSTEM_DEF(nightshift)
name = "Night Shift"
init_order = INIT_ORDER_NIGHTSHIFT
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 60 SECONDS
flags = SS_NO_TICK_CHECK
var/nightshift_active = FALSE
var/nightshift_first_check = 30 SECONDS
var/high_security_mode = FALSE
/datum/controller/subsystem/nightshift/Initialize()
if(!config.enable_night_shifts)
can_fire = FALSE
/*
if(config.randomize_shift_time)
GLOB.gametime_offset = rand(0, 23) HOURS
*/
return ..()
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
if(round_duration_in_ds < nightshift_first_check)
return
check_nightshift()
/datum/controller/subsystem/nightshift/proc/announce(message)
var/announce_z
if(using_map.station_levels.len)
announce_z = pick(using_map.station_levels)
priority_announcement.Announce(message, new_title = "Automated Lighting System Announcement", new_sound = 'sound/misc/notice2.ogg', zlevel = announce_z)
/datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) //This is called from elsewhere, like setting the alert levels
if(check_canfire && !can_fire)
return
var/emergency = security_level > SEC_LEVEL_GREEN
var/announcing = TRUE
var/night_time = using_map.get_nightshift()
if(high_security_mode != emergency)
high_security_mode = emergency
if(night_time)
announcing = FALSE
if(!emergency)
announce("Restoring night lighting configuration to normal operation.")
else
announce("Disabling night lighting: Station is in a state of emergency.")
if(emergency)
night_time = FALSE
if(nightshift_active != night_time)
update_nightshift(night_time, announcing)
/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE)
nightshift_active = active
if(announce)
if(active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
for(var/obj/machinery/power/apc/apc in machines)
if(apc.z in using_map.station_levels)
apc.set_nightshift(active, TRUE)
CHECK_TICK

View File

@@ -6,16 +6,16 @@ SUBSYSTEM_DEF(planets)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/new_outdoor_turfs = list()
var/list/new_outdoor_walls = list()
var/static/list/new_outdoor_turfs = list()
var/static/list/new_outdoor_walls = list()
var/list/planets = list()
var/list/z_to_planet = list()
var/static/list/planets = list()
var/static/list/z_to_planet = list()
var/list/currentrun = list()
var/static/list/currentrun = list()
var/list/needs_sun_update = list()
var/list/needs_temp_update = list()
var/static/list/needs_sun_update = list()
var/static/list/needs_temp_update = list()
/datum/controller/subsystem/planets/Initialize(timeofday)
admin_notice("<span class='danger'>Initializing planetary weather.</span>", R_DEBUG)

View File

@@ -404,16 +404,25 @@ var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/proc/create_characters()
for(var/mob/new_player/player in player_list)
if(player && player.ready && player.mind)
if(player.mind.assigned_role=="AI")
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()
else if(!player.mind.assigned_role)
player.AIize(move = TRUE)
continue
else
player.create_character()
// Ask their new_player mob to spawn them
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 they're a carbon, they can get manifested
if(J.mob_type & JOB_CARBON)
data_core.manifest_inject(new_char)
/datum/controller/subsystem/ticker/proc/collect_minds()
for(var/mob/living/player in player_list)

View File

@@ -4,10 +4,12 @@
var/lock = TRUE
var/turf/lastloc
var/lastprocess
var/matrix/init_transform
/datum/orbit/New(_orbiter, _orbiting, _lock)
/datum/orbit/New(var/atom/movable/_orbiter, var/atom/_orbiting, _lock)
orbiter = _orbiter
orbiting = _orbiting
init_transform = _orbiter.transform
SSorbit.processing += src
if (!orbiting.orbiters)
orbiting.orbiters = list()
@@ -24,6 +26,7 @@
SSorbit.processing -= src
if (orbiter)
orbiter.orbiting = null
orbiter.transform = init_transform
orbiter = null
if (orbiting)
if (orbiting.orbiters)
@@ -84,7 +87,6 @@
new/datum/orbit(src, A, lockinorbit)
if (!orbiting) //something failed, and our orbit datum deleted itself
return
var/matrix/initial_transform = matrix(transform)
//Head first!
if (pre_rotation)
@@ -101,9 +103,6 @@
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
transform = initial_transform
/atom/movable/proc/stop_orbit()
SpinAnimation(0,0)
qdel(orbiting)

View File

@@ -4,6 +4,7 @@
var/list/restricted_jobs = list() // Jobs that cannot be this antagonist (depending on config)
var/list/protected_jobs = list() // As above.
var/list/roundstart_restricted = list() //Jobs that can be this antag, but not at roundstart
var/avoid_silicons = FALSE // If we won't hand this antag role to silicons (AI, borg, etc)
// Strings.
var/welcome_text = "Cry havoc and let slip the dogs of war!"

View File

@@ -10,6 +10,10 @@
return FALSE
if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs))
return FALSE
if(avoid_silicons)
var/datum/job/J = SSjob.get_job(player.assigned_role)
if(J.mob_type & JOB_SILICON)
return FALSE
return TRUE
/datum/antagonist/proc/antags_are_dead()

View File

@@ -5,7 +5,7 @@
role_text_plural = "Changelings"
bantype = "changeling"
feedback_tag = "changeling_objective"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director")
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'

View File

@@ -11,7 +11,8 @@ var/datum/antagonist/cultist/cult
role_text = "Cultist"
role_text_plural = "Cultists"
bantype = "cultist"
restricted_jobs = list("Chaplain","AI", "Cyborg")
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")
role_type = BE_CULTIST

View File

@@ -29,7 +29,7 @@ var/datum/antagonist/loyalists/loyalists
faction_welcome = "Preserve NanoTrasen's interests against the traitorous recidivists amongst the crew. Protect the heads of staff with your life."
faction_indicator = "loyal"
faction_invisible = 1
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
/datum/antagonist/loyalists/New()
..()

View File

@@ -6,7 +6,7 @@ var/datum/antagonist/renegade/renegades
role_text = "Renegade"
role_text_plural = "Renegades"
bantype = "renegade"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
welcome_text = "Something's going to go wrong today, you can just feel it. You're paranoid, you've got a gun, and you're going to survive."
antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are a <b>minor</b> antagonist! Within the rules, \

View File

@@ -29,7 +29,7 @@ var/datum/antagonist/revolutionary/revs
faction_indicator = "rev"
faction_invisible = 1
restricted_jobs = list("AI", "Cyborg")
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")

View File

@@ -6,7 +6,7 @@ var/datum/antagonist/stowaway/stowaways
role_text = "Stowaway"
role_text_plural = "Stowaways"
bantype = "renegade"
restricted_jobs = list("AI")
avoid_silicons = TRUE // This was previously allowing cyborgs to be stowaways, but given that they would just connect to the AI, it didn't make much sense
welcome_text = "People are known to run from many things, or to many things, for many different reasons. You happen to be one of those people."
antag_text = "You are a <b>minor</b> antagonist! Within the server rules, do whatever it is \
that you came to the station to do. Espionage, thievery, or just running from the law are all examples. \

View File

@@ -6,7 +6,7 @@ var/datum/antagonist/thug/thugs
role_text = "Thug"
role_text_plural = "Thugs"
bantype = "renegade"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
welcome_text = "Sometimes, people just need to get messed up. Luckily, that's what you're here to do."
antag_text = "You are a <b>minor</b> antagonist! Within the server rules, do whatever it is \
that you came to the station to do, be it violence, theft, or just extreme self-defense. \

View File

@@ -184,10 +184,10 @@
var/list/output = list("[bicon(src)] That's [f_name] [suffix]", desc)
if(user.client?.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
output += description_info
if(user.client?.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL)
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL)
user.client.statpanel = "Examine" // Switch to stat panel
return output

View File

@@ -56,16 +56,9 @@
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/opened = 0
/obj/machinery/dna_scannernew/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src)
component_parts += new /obj/item/stack/cable_coil(src)
RefreshParts()
/obj/machinery/dna_scannernew/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
if (user.stat)

View File

@@ -24,6 +24,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too.
var/last_shriek = null // world.time when the ling last used a shriek.
var/next_escape = 0 // world.time when the ling can next use Escape Restraints
var/thermal_sight = FALSE // Is our Vision Augmented? With thermals?
/datum/changeling/New(var/gender=FEMALE)
..()
@@ -64,8 +65,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind) return
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
verbs += /datum/changeling/proc/EvolutionMenu
verbs += /mob/proc/changeling_respec
verbs.Add(/datum/changeling/proc/EvolutionMenu)
verbs.Add(/mob/proc/changeling_respec)
add_language("Changeling")
var/lesser_form = !ishuman(src)
@@ -84,7 +85,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform) continue
if(!(P in src.verbs))
src.verbs += P.verbpath
verbs.Add(P.verbpath)
if(P.make_hud_button)
if(!src.ability_master)
src.ability_master = new /obj/screen/movable/ability_master(src)
@@ -111,7 +112,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind || !mind.changeling) return
for(var/datum/power/changeling/P in mind.changeling.purchased_powers)
if(P.isVerb)
verbs -= P.verbpath
verbs.Remove(P.verbpath)
var/obj/screen/ability/verb_based/changeling/C = ability_master.get_ability_by_proc_ref(P.verbpath)
if(C)
ability_master.remove_ability(C)

View File

@@ -1,12 +1,11 @@
//Augmented Eyesight: Gives you thermal and night vision - bye bye, flashlights. Also, high DNA cost because of how powerful it is.
//Augmented Eyesight: Gives you thermal vision. Also, higher DNA cost because of how powerful it is.
/datum/power/changeling/augmented_eyesight
name = "Augmented Eyesight"
desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
helptext = "Grants us night vision and thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
helptext = "Grants us thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
ability_icon_state = "ling_augmented_eyesight"
genomecost = 2
var/active = 0 //Whether or not vision is enhanced
verbpath = /mob/proc/changeling_augmented_eyesight
/mob/proc/changeling_augmented_eyesight()
@@ -17,23 +16,22 @@
var/datum/changeling/changeling = changeling_power(5,0,100,CONSCIOUS)
if(!changeling)
return 0
src.mind.changeling.chem_charges -= 5
src.sight |= SEE_MOBS
/*
var/mob/living/carbon/human/C = src
active = !active
changeling.thermal_sight = !changeling.thermal_sight
var/active = changeling.thermal_sight
if(active)
to_chat(C, "<span class='notice'>We feel a minute twitch in our eyes, and darkness creeps away.</span>")
C.sight |= SEE_MOBS
C.permanent_sight_flags |= SEE_MOBS
C.see_in_dark = 8
C.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
src.mind.changeling.chem_charges -= 5
to_chat(C, "<span class='notice'>We feel a minute twitch in our eyes, and a hidden layer to the world is revealed.</span>")
C.add_modifier(/datum/modifier/changeling/thermal_sight, 0, src)
// C.permanent_sight_flags |= SEE_MOBS
// C.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
else
to_chat(C, "<span class='notice'>Our vision dulls. Shadows gather.</span>")
C.sight &= ~SEE_MOBS
C.permanent_sight_flags &= ~SEE_MOBS
C.see_in_dark = 0
C.dna.species.invis_sight = initial(user.dna.species.invis_sight)
to_chat(C, "<span class='notice'>Our vision dulls.</span>")
C.remove_modifiers_of_type(/datum/modifier/changeling/thermal_sight)
// C.permanent_sight_flags &= ~SEE_MOBS
// C.dna.species.invis_sight = initial(user.dna.species.invis_sight)
return 1
*/

View File

@@ -14,7 +14,6 @@
on_expired_text = "<span class='notice'>Our protective armor underneath our skin fades as we absorb it.</span>"
max_health_flat = 50
//Increases macimum chemical storage
/mob/proc/changeling_endoarmor()
if(ishuman(src))
var/mob/living/carbon/human/H = src

View File

@@ -43,7 +43,10 @@
spawn(rand(2 MINUTES, 4 MINUTES))
//The ling will now be able to choose when to revive
src.verbs += /mob/proc/changeling_revive
verbs.Add(/mob/proc/changeling_revive)
new /obj/changeling_revive_holder(src)
to_chat(src, "<span class='notice'><font size='5'>We are ready to rise. Use the <b>Revive</b> verb when you are ready.</font></span>")
feedback_add_details("changeling_powers","FD")

View File

@@ -17,6 +17,7 @@
ling_datum.purchased_powers = list() //Then wipe all the powers we bought.
ling_datum.geneticpoints = ling_datum.max_geneticpoints //Now refund our points to the maximum.
ling_datum.chem_recharge_rate = 0.5 //If glands were bought, revert that upgrade.
ling_datum.thermal_sight = FALSE
src.mind.changeling.recursive_enhancement = 0 //Ensures this is cleared
ling_datum.chem_storage = 50

View File

@@ -82,10 +82,28 @@
C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
src.verbs -= /mob/proc/changeling_revive
verbs.Remove(/mob/proc/changeling_revive)
// re-add our changeling powers
C.make_changeling()
return 1
//Revive from revival stasis, but one level removed, as the tab refuses to update. Placed in its own tab to avoid hyper-exploding the original tab through the same name being used.
/obj/changeling_revive_holder
name = "strange object"
desc = "Please report this object's existence to the dev team! You shouldn't see it."
mouse_opacity = FALSE
alpha = 1
/obj/changeling_revive_holder/verb/ling_revive()
set src = usr.contents
set category = "Regenerate"
set name = "Revive"
set desc = "We are ready to revive ourselves on command."
if(iscarbon(usr))
var/mob/living/carbon/C = usr
C.changeling_revive()
qdel(src)

View File

@@ -34,7 +34,7 @@
if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT))
return // Don't do anything if the shuttle's coming.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)

View File

@@ -31,6 +31,7 @@
var/outfit_type // What outfit datum does this job use in its default title?
var/offmap_spawn = FALSE // Do we require weird and special spawning and datacore handling?
var/mob_type = JOB_CARBON // Bitflags representing mob type this job spawns
// Description of the job's role and minimum responsibilities.
var/job_description = "This Job doesn't have a description! Please report it!"

View File

@@ -18,6 +18,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
mob_type = JOB_SILICON_AI
outfit_type = /decl/hierarchy/outfit/job/silicon/ai
job_description = "The AI oversees the operation of the station and its crew, but has no real authority over them. \
The AI is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \
@@ -54,6 +55,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
mob_type = JOB_SILICON_ROBOT
outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg
job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \
to follow its Laws."

View File

@@ -360,54 +360,64 @@ var/global/datum/controller/occupations/job_master
//Equip custom gear loadout.
var/list/custom_equip_slots = list() //If more than one item takes the same slot, all after the first one spawn in storage.
var/list/custom_equip_leftovers = list()
if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI")
if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON))
for(var/thing in H.client.prefs.gear)
var/datum/gear/G = gear_datums[thing]
if(G)
var/permitted
if(G.allowed_roles)
for(var/job_name in G.allowed_roles)
if(job.title == job_name)
permitted = 1
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)
for(var/job_name in G.allowed_roles)
if(job.title == job_name)
permitted = 1
else
permitted = 1
// Check if they're whitelisted for this gear (in alien whitelist? seriously?)
if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
permitted = 0
// If they aren't, tell them
if(!permitted)
to_chat(H, "<span class='warning'>Your current species, job or whitelist status does not permit you to spawn with [thing]!</span>")
continue
// Implants get special treatment
if(G.slot == "implant")
var/obj/item/weapon/implant/I = G.spawn_item(H)
I.invisibility = 100
I.implant_loadout(H)
continue
// Try desperately (and sorta poorly) to equip the item
if(G.slot && !(G.slot in custom_equip_slots))
var/metadata = H.client.prefs.gear[G.display_name]
if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
custom_equip_leftovers += thing
else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
to_chat(H, "<span class='notice'>Equipping you with \the [thing]!</span>")
custom_equip_slots.Add(G.slot)
else
permitted = 1
custom_equip_leftovers.Add(thing)
else
spawn_in_storage += thing
if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
//if(G.whitelisted && (G.whitelisted != H.species.name || !is_alien_whitelisted(H, G.whitelisted)))
permitted = 0
if(!permitted)
to_chat(H, "<span class='warning'>Your current species, job or whitelist status does not permit you to spawn with [thing]!</span>")
continue
if(G.slot == "implant")
var/obj/item/weapon/implant/I = G.spawn_item(H)
I.invisibility = 100
I.implant_loadout(H)
continue
if(G.slot && !(G.slot in custom_equip_slots))
// This is a miserable way to fix the loadout overwrite bug, but the alternative requires
// adding an arg to a bunch of different procs. Will look into it after this merge. ~ Z
var/metadata = H.client.prefs.gear[G.display_name]
if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
custom_equip_leftovers += thing
else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
to_chat(H, "<span class='notice'>Equipping you with \the [thing]!</span>")
custom_equip_slots.Add(G.slot)
else
custom_equip_leftovers.Add(thing)
else
spawn_in_storage += thing
//Equip job items.
// 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)
if(job.title != "Cyborg" && job.title != "AI")
// Only non-silicons get post-job-equip equipment
if(!(job.mob_type & JOB_SILICON))
H.equip_post_job()
//If some custom items could not be equipped before, try again now.
// If some custom items could not be equipped before, try again now.
for(var/thing in custom_equip_leftovers)
var/datum/gear/G = gear_datums[thing]
if(G.slot in custom_equip_slots)
@@ -442,14 +452,16 @@ var/global/datum/controller/occupations/job_master
H.mind.assigned_role = rank
alt_title = H.mind.role_alt_title
switch(rank)
if("Cyborg")
return H.Robotize()
if("AI")
return H
if("Colony Director")
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)
// If we're a silicon, we may be done at this point
if(job.mob_type & JOB_SILICON_ROBOT)
return H.Robotize()
if(job.mob_type & JOB_SILICON_AI)
return H
// TWEET PEEP
if(rank == "Colony Director")
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)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
@@ -559,7 +571,7 @@ var/global/datum/controller/occupations/job_master
if(!J) continue
J.total_positions = text2num(value)
J.spawn_positions = text2num(value)
if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now
if(J.mob_type & JOB_SILICON)
J.total_positions = 0
return 1

View File

@@ -180,21 +180,10 @@
idle_power_usage = 15
active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors.
/obj/machinery/sleeper/New()
..()
/obj/machinery/sleeper/Initialize()
. = ..()
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
default_apply_parts()
/obj/machinery/sleeper/Destroy()
if(console)

View File

@@ -15,14 +15,9 @@
light_color = "#00FF00"
var/obj/machinery/body_scanconsole/console
/obj/machinery/bodyscanner/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
/obj/machinery/bodyscanner/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/bodyscanner/Destroy()
if(console)

View File

@@ -1,339 +1,334 @@
/obj/machinery/autolathe
name = "autolathe"
desc = "It produces items using metal and glass."
icon_state = "autolathe"
density = 1
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
var/mat_efficiency = 1
var/build_time = 50
var/datum/wires/autolathe/wires = null
var/filtertext
/obj/machinery/autolathe/New()
..()
wires = new(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
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/interact(mob/user as mob)
update_recipe_list()
if(..() || (disabled && !panel_open))
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)
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)
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()
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(stat)
return
if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(O.is_multitool() || O.is_wirecutter())
wires.Interact(user)
return
if(O.loc != user && !(istype(O,/obj/item/stack)))
return 0
if(is_robot_module(O))
return 0
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38)) // 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
if(!eating.matter)
to_chat(user, "\The [eating] does not contain significant amounts of useful materials and cannot be accepted.")
return
var/filltype = 0 // Used to determine message.
var/total_used = 0 // Amount of material used.
var/mass_per_sheet = 0 // Amount of material constituting one sheet.
for(var/material in eating.matter)
if(isnull(stored_material[material]) || isnull(storage_capacity[material]))
continue
if(stored_material[material] >= storage_capacity[material])
continue
var/total_material = eating.matter[material]
//If it's a stack, we eat multiple sheets.
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
total_material *= stack.get_amount()
if(stored_material[material] + total_material > storage_capacity[material])
total_material = storage_capacity[material] - stored_material[material]
filltype = 1
else
filltype = 2
stored_material[material] += total_material
total_used += total_material
mass_per_sheet += eating.matter[material]
if(!filltype)
to_chat(user, "<span class='notice'>\The [src] is full. Please remove material from the autolathe in order to insert more.</span>")
return
else if(filltype == 1)
to_chat(user, "You fill \the [src] to capacity with \the [eating].")
else
to_chat(user, "You fill \the [src] with \the [eating].")
flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
else
user.remove_from_mob(O)
qdel(O)
updateUsrDialog()
return
/obj/machinery/autolathe/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
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)
if(href_list["change_category"])
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
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
//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
busy = 1
update_use_power(USE_POWER_ACTIVE)
//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
//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)
update_icon() // So lid closes
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)
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()
/obj/machinery/autolathe/update_icon()
if(panel_open)
icon_state = "autolathe_t"
else if(busy)
icon_state = "autolathe_n"
else
if(icon_state == "autolathe_n")
flick("autolathe_u", src) // If lid WAS closed, show opening animation
icon_state = "autolathe"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
var/mb_rating = 0
var/man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
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
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
var/material/M = get_material_by_name(mat)
if(!istype(M))
continue
var/obj/item/stack/material/S = new M.stack_type(get_turf(src))
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
else
qdel(S)
..()
return 1
/obj/machinery/autolathe
name = "autolathe"
desc = "It produces items using metal and glass."
icon_state = "autolathe"
density = 1
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
var/mat_efficiency = 1
var/build_time = 50
var/datum/wires/autolathe/wires = null
var/filtertext
/obj/machinery/autolathe/Initialize()
. = ..()
wires = new(src)
default_apply_parts()
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
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/interact(mob/user as mob)
update_recipe_list()
if(..() || (disabled && !panel_open))
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)
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)
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()
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(stat)
return
if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(O.is_multitool() || O.is_wirecutter())
wires.Interact(user)
return
if(O.loc != user && !(istype(O,/obj/item/stack)))
return 0
if(is_robot_module(O))
return 0
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38)) // 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
if(!eating.matter)
to_chat(user, "\The [eating] does not contain significant amounts of useful materials and cannot be accepted.")
return
var/filltype = 0 // Used to determine message.
var/total_used = 0 // Amount of material used.
var/mass_per_sheet = 0 // Amount of material constituting one sheet.
for(var/material in eating.matter)
if(isnull(stored_material[material]) || isnull(storage_capacity[material]))
continue
if(stored_material[material] >= storage_capacity[material])
continue
var/total_material = eating.matter[material]
//If it's a stack, we eat multiple sheets.
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
total_material *= stack.get_amount()
if(stored_material[material] + total_material > storage_capacity[material])
total_material = storage_capacity[material] - stored_material[material]
filltype = 1
else
filltype = 2
stored_material[material] += total_material
total_used += total_material
mass_per_sheet += eating.matter[material]
if(!filltype)
to_chat(user, "<span class='notice'>\The [src] is full. Please remove material from the autolathe in order to insert more.</span>")
return
else if(filltype == 1)
to_chat(user, "You fill \the [src] to capacity with \the [eating].")
else
to_chat(user, "You fill \the [src] with \the [eating].")
flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
else
user.remove_from_mob(O)
qdel(O)
updateUsrDialog()
return
/obj/machinery/autolathe/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
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)
if(href_list["change_category"])
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
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
//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
busy = 1
update_use_power(USE_POWER_ACTIVE)
//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
//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)
update_icon() // So lid closes
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)
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()
/obj/machinery/autolathe/update_icon()
if(panel_open)
icon_state = "autolathe_t"
else if(busy)
icon_state = "autolathe_n"
else
if(icon_state == "autolathe_n")
flick("autolathe_u", src) // If lid WAS closed, show opening animation
icon_state = "autolathe"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
var/mb_rating = 0
var/man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
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
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
var/material/M = get_material_by_name(mat)
if(!istype(M))
continue
var/obj/item/stack/material/S = new M.stack_type(get_turf(src))
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
else
qdel(S)
..()
return 1

View File

@@ -15,17 +15,14 @@
var/build_eff = 1
var/eat_eff = 1
/obj/machinery/biogenerator/New()
..()
/obj/machinery/biogenerator/Initialize()
. = ..()
var/datum/reagents/R = new/datum/reagents(1000)
reagents = R
R.my_atom = src
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
default_apply_parts()
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()

View File

@@ -75,14 +75,10 @@
if(printing)
overlays += "bioprinter_working"
/obj/machinery/organ_printer/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
/obj/machinery/organ_printer/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/organ_printer/examine(var/mob/user)
. = ..()
var/biomass = get_biomass_volume()
@@ -272,7 +268,7 @@
icon_state = "bioprinter"
circuit = /obj/item/weapon/circuitboard/bioprinter
/obj/machinery/organ_printer/flesh/full/New()
/obj/machinery/organ_printer/flesh/full/Initialize()
. = ..()
container = new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src)

View File

@@ -13,13 +13,9 @@
var/chargelevel = -1
circuit = /obj/item/weapon/circuitboard/cell_charger
/obj/machinery/cell_charger/New()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
..()
return
/obj/machinery/cell_charger/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/cell_charger/update_icon()
icon_state = "ccharger[charging ? 1 : 0]"

View File

@@ -46,17 +46,9 @@
var/list/containers = list() // Beakers for our liquid biomass
var/container_limit = 3 // How many beakers can the machine hold?
/obj/machinery/clonepod/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/clonepod/Initialize()
. = ..()
default_apply_parts()
update_icon()
/obj/machinery/clonepod/attack_ai(mob/user as mob)

View File

@@ -2,7 +2,7 @@
name = "automated shutoff valve monitor"
desc = "Console used to remotely monitor shutoff valves on the station."
icon_keyboard = "power_key"
icon_screen = "power:0"
icon_screen = "power_monitor"
light_color = "#a97faa"
circuit = /obj/item/weapon/circuitboard/shutoff_monitor
var/datum/nano_module/shutoff_monitor/monitor

View File

@@ -1,5 +1,3 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/obj/item/weapon/airlock_electronics
name = "airlock electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
@@ -8,106 +6,148 @@
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
req_access = list(access_engine)
req_one_access = list(access_engine) // Access to unlock the device, ignored if emagged
var/list/apply_any_access = list(access_engine) // Can apply any access, not just their own
var/secure = 0 //if set, then wires will be randomized and bolts will drop if the door is broken
var/list/conf_access = null
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
var/last_configurator = null
var/locked = 1
var/emagged = 0
attack_self(mob/user as mob)
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
return ..(user)
/obj/item/weapon/airlock_electronics/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
emagged = 1
to_chat(user, "<span class='notice'>You remove the access restrictions on [src]!</span>")
return 1
var/t1 = text("<B>Access control</B><br>\n")
/obj/item/weapon/airlock_electronics/attack_self(mob/user as mob)
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
return ..(user)
if (last_configurator)
t1 += "Operator: [last_configurator]<br>"
var/t1 = text("<B>Access control</B><br>\n")
if (locked)
t1 += "<a href='?src=\ref[src];login=1'>Swipe ID</a><hr>"
else
t1 += "<a href='?src=\ref[src];logout=1'>Block</a><hr>"
if (last_configurator)
t1 += "Operator: [last_configurator]<br>"
t1 += "Access requirement is set to "
t1 += one_access ? "<a style='color: green' href='?src=\ref[src];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=\ref[src];one_access=1'>ALL</a><hr>"
if (locked)
t1 += "<a href='?src=\ref[src];login=1'>Unlock Interface</a><hr>"
else
t1 += "<a href='?src=\ref[src];logout=1'>Lock Interface</a><hr>"
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=\ref[src];access=all'>All</a><br>"
t1 += "Access requirement is set to "
t1 += one_access ? "<a style='color: green' href='?src=\ref[src];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=\ref[src];one_access=1'>ALL</a><hr>"
t1 += "<br>"
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=\ref[src];access=all'>All</a><br>"
var/list/accesses = get_all_station_access()
for (var/acc in accesses)
var/aname = get_access_desc(acc)
t1 += "<br>"
if (!conf_access || !conf_access.len || !(acc in conf_access))
t1 += "<a href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else if(one_access)
t1 += "<a style='color: green' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else
t1 += "<a style='color: red' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
var/list/accesses = get_available_accesses(user)
for (var/acc in accesses)
var/aname = get_access_desc(acc)
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
user << browse(t1, "window=airlock_electronics")
onclose(user, "airlock")
Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon)))
return
if (href_list["close"])
usr << browse(null, "window=airlock")
return
if (href_list["login"])
if(istype(usr,/mob/living/silicon))
src.locked = 0
src.last_configurator = usr.name
if (!conf_access || !conf_access.len || !(acc in conf_access))
t1 += "<a href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else if(one_access)
t1 += "<a style='color: green' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/device/pda))
var/obj/item/device/pda/pda = I
I = pda.id
if (I && src.check_access(I))
t1 += "<a style='color: red' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
user << browse(t1, "window=airlock_electronics")
onclose(user, "airlock")
/obj/item/weapon/airlock_electronics/Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon)))
return
if (href_list["close"])
usr << browse(null, "window=airlock_electronics")
return
if (href_list["login"])
if(emagged)
src.locked = 0
src.last_configurator = usr.name
else if(issilicon(usr))
src.locked = 0
src.last_configurator = usr.name
else if(isliving(usr))
var/obj/item/weapon/card/id/id
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
id = H.get_idcard()
// In their ID slot?
if(id && src.check_access(id))
src.locked = 0
src.last_configurator = I:registered_name
src.last_configurator = id.registered_name
// Still locked, human handling didn't do it!
if(locked)
var/obj/item/I = usr.get_active_hand()
id = I?.GetID()
if(id && src.check_access(id))
src.locked = 0
src.last_configurator = id.registered_name
if (locked)
return
if (locked)
return
if (href_list["logout"])
locked = 1
if (href_list["logout"])
locked = 1
if (href_list["one_access"])
one_access = !one_access
if (href_list["one_access"])
one_access = !one_access
if (href_list["access"])
toggle_access(href_list["access"])
if (href_list["access"])
toggle_access(href_list["access"])
attack_self(usr)
attack_self(usr)
proc
toggle_access(var/acc)
if (acc == "all")
/obj/item/weapon/airlock_electronics/proc/toggle_access(var/acc)
if (acc == "all")
conf_access = null
else
var/req = text2num(acc)
if (conf_access == null)
conf_access = list()
if (!(req in conf_access))
conf_access += req
else
conf_access -= req
if (!conf_access.len)
conf_access = null
else
var/req = text2num(acc)
if (conf_access == null)
conf_access = list()
if (!(req in conf_access))
conf_access += req
else
conf_access -= req
if (!conf_access.len)
conf_access = null
/obj/item/weapon/airlock_electronics/proc/get_available_accesses(var/mob/user)
var/obj/item/weapon/card/id/id
if(ishuman(user))
var/mob/living/carbon/human/H = user
id = H.get_idcard()
else if(issilicon(user))
var/mob/living/silicon/R = user
id = R.idcard
// Nothing
if(!id || !id.access)
return list()
// Has engineer access, can put any access
else if(has_access(null, apply_any_access, id.access))
return get_all_station_access()
// Not an engineer, can only pick your own accesses to program
else
return id.access
/obj/item/weapon/airlock_electronics/secure
name = "secure airlock electronics"
desc = "designed to be somewhat more resistant to hacking than standard electronics."
origin_tech = list(TECH_DATA = 2)
secure = 1
/obj/item/weapon/airlock_electronics/secure/emag_act(var/remaining_charges, var/mob/user)
to_chat(user, "<span class='warning'>You don't appear to be able to bypass this hardened device!</span>")
return -1

View File

@@ -269,7 +269,7 @@
// If for some reason this is actually needed for something important, uncomment this.
/obj/machinery/door/blast/CanZASPass(turf/T, is_zone)
if(is_zone)
return ATMOS_PASS_YES
return TRUE
return ..()
*/

View File

@@ -9,7 +9,7 @@
anchored = 1
opacity = 1
density = 1
can_atmos_pass = ATMOS_PASS_DENSITY
can_atmos_pass = ATMOS_PASS_PROC
layer = DOOR_OPEN_LAYER
var/open_layer = DOOR_OPEN_LAYER
var/closed_layer = DOOR_CLOSED_LAYER
@@ -143,8 +143,8 @@
/obj/machinery/door/CanZASPass(turf/T, is_zone)
if(is_zone)
return block_air_zones ? ATMOS_PASS_NO : ATMOS_PASS_YES
return ..()
return !block_air_zones // Block merging unless block_air_zones = 0
return !density // Block airflow unless density = 0
/obj/machinery/door/proc/bumpopen(mob/user as mob)
if(operating) return

View File

@@ -14,6 +14,7 @@
opacity = 0
var/obj/item/weapon/airlock_electronics/electronics = null
explosion_resistance = 5
can_atmos_pass = ATMOS_PASS_PROC
air_properties_vary_with_direction = 1
/obj/machinery/door/window/New()
@@ -94,9 +95,9 @@
/obj/machinery/door/window/CanZASPass(turf/T, is_zone)
if(get_dir(T, loc) == turn(dir, 180))
if(is_zone) // No merging allowed.
return ATMOS_PASS_NO
return ..() // Air can flow if open (density == FALSE).
return ATMOS_PASS_YES // Windoors don't block if not facing the right way.
return FALSE
return !density // Air can flow if open (density == FALSE).
return TRUE // Windoors don't block if not facing the right way.
/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
if(istype(mover) && mover.checkpass(PASSGLASS))

View File

@@ -21,21 +21,9 @@
// Proc: New()
// Parameters: None
// Description: Adds components to the machine for deconstruction.
/obj/machinery/exonet_node/map/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/exonet_node/map/Initialize()
. = ..()
default_apply_parts()
desc = "This machine is one of many, many nodes inside [using_map.starsys_name]'s section of the Exonet, connecting the [using_map.station_short] to the rest of the system, at least \
electronically."
@@ -185,7 +173,7 @@
// Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function.
// Communicators are already logged seperately.
/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
//var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss")
//var/timestamp = time2text(station_time_in_ds, "hh:mm:ss")
var/timestamp = "[stationdate2text()] [stationtime2text()]"
var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
logs.Add(msg)

View File

@@ -50,8 +50,8 @@ datum/track/New(var/title_name, var/audio)
new/datum/track("Russkiy rep Diskoteka", 'sound/music/russianrapdisco.ogg')
)
/obj/machinery/media/jukebox/New()
..()
/obj/machinery/media/jukebox/Initialize()
. = ..()
default_apply_parts()
wires = new/datum/wires/jukebox(src)
update_icon()
@@ -60,7 +60,7 @@ datum/track/New(var/title_name, var/audio)
StopPlaying()
qdel(wires)
wires = null
..()
return ..()
/obj/machinery/media/jukebox/proc/set_hacked(var/newhacked)
if (hacked == newhacked) return

View File

@@ -123,12 +123,14 @@ Class Procs:
..(l)
if(d)
set_dir(d)
if(circuit)
if(ispath(circuit))
circuit = new circuit(src)
/obj/machinery/Initialize()
. = ..()
global.machines += src
if(ispath(circuit))
circuit = new circuit(src)
if(!speed_process)
START_MACHINE_PROCESSING(src)
else

View File

@@ -17,16 +17,8 @@
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
/obj/machinery/mass_driver/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/motor(src)
component_parts += new /obj/item/weapon/stock_parts/motor(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
component_parts += new /obj/item/weapon/stock_parts/spring(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
. = ..()
default_apply_parts()
/obj/machinery/mass_driver/attackby(var/obj/item/I, mob/user)
if(default_deconstruction_screwdriver(user, I))

View File

@@ -79,7 +79,7 @@
newMsg.body = msg
newMsg.time_stamp = "[stationtime2text()]"
newMsg.is_admin_message = adminMessage
newMsg.post_time = round_duration_in_ticks // Should be almost universally unique
newMsg.post_time = round_duration_in_ds // Should be almost universally unique
if(message_type)
newMsg.message_type = message_type
if(photo)

View File

@@ -22,17 +22,9 @@
"cargo" = new /obj/item/device/pda/multicaster/cargo(src),
"civilian" = new /obj/item/device/pda/multicaster/civilian(src))
/obj/machinery/pda_multicaster/prebuilt/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/telecomms/pda_multicaster(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/pda_multicaster/prebuilt/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/pda_multicaster/Destroy()
for(var/atom/movable/AM in contents)

View File

@@ -17,13 +17,9 @@
var/portable = 1
circuit = /obj/item/weapon/circuitboard/recharger
/obj/machinery/recharger/New()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
..()
return
/obj/machinery/recharger/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/recharger/examine(mob/user)
. = ..()

View File

@@ -22,17 +22,9 @@
var/weld_power_use = 2300 // power used per point of brute damage repaired. 2.3 kW ~ about the same power usage of a handheld arc welder
var/wire_power_use = 500 // power used per point of burn damage repaired.
/obj/machinery/recharge_station/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/cell/high(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
/obj/machinery/recharge_station/Initialize()
. = ..()
default_apply_parts()
update_icon()
/obj/machinery/recharge_station/proc/has_cell_power()

View File

@@ -32,13 +32,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/obj/machinery/telecomms/processor/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser/high(src)
component_parts += new /obj/item/stack/cable_coil(src, 1)
default_apply_parts()
/obj/machinery/telecomms/broadcaster/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
@@ -353,7 +347,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
for(var/obj/item/device/radio/R in forced_radios)
//Cursory check to ensure they are 'on' and stuff
if(R.receive_range(display_freq, list(0)))
if(R.receive_range(display_freq, list(0)) > -1)
radios |= R
// --- Broadcast only to intercom devices ---

View File

@@ -265,13 +265,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/receiver/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
RefreshParts()
default_apply_parts()
/obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
@@ -351,32 +345,10 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
circuit = /obj/item/weapon/circuitboard/telecomms/hub
long_range_link = 1
netspeed = 40
var/list/telecomms_map
/obj/machinery/telecomms/hub/Initialize()
. = ..()
LAZYINITLIST(telecomms_map)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/telecomms/hub/process()
. = ..()
telecomms_map.Cut()
if(!on)
return
for(var/M in links)
if(istype(M,/obj/machinery/telecomms/receiver) || istype(M,/obj/machinery/telecomms/relay))
var/obj/machinery/telecomms/R = M
if(!R.on)
continue
telecomms_map |= R.listening_level
default_apply_parts()
/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(is_freq_listening(signal))
@@ -416,13 +388,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/relay/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
default_apply_parts()
/obj/machinery/telecomms/relay/forceMove(var/newloc)
. = ..(newloc)
@@ -479,12 +445,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/bus/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 1)
RefreshParts()
default_apply_parts()
/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
@@ -540,17 +501,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/processor/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/amplifier(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/analyzer(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
default_apply_parts()
/obj/machinery/telecomms/processor/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
@@ -611,12 +562,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
/obj/machinery/telecomms/server/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 1)
RefreshParts()
default_apply_parts()
/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
@@ -750,17 +696,10 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
return FALSE
//Items don't have a Z when inside an object or mob
var/turf/src_turf = get_turf(A)
var/turf/dst_turf = get_turf(B)
var/turf/src_z = get_z(A)
var/turf/dst_z = get_z(B)
//Nullspace, probably.
if(!src_turf || !dst_turf)
return FALSE
var/src_z = src_turf.z
var/dst_z = dst_turf.z
//Mysterious!
if(!src_z || !dst_z)
return FALSE
@@ -768,11 +707,4 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
if(ad_hoc && src_z == dst_z)
return TRUE
//Let's look at hubs and see what we got.
var/can_comm = FALSE
for(var/obj/machinery/telecomms/hub/H in telecomms_list)
if((src_z in H.telecomms_map) && (dst_z in H.telecomms_map))
can_comm = TRUE
break
return can_comm
return src_z in using_map.get_map_levels(dst_z)

View File

@@ -1,3 +1,6 @@
//////
////// Teleporter computer
//////
/obj/machinery/computer/teleporter
name = "teleporter control console"
desc = "Used to control a linked teleportation Hub and Station."
@@ -5,23 +8,23 @@
icon_screen = "teleport"
circuit = /obj/item/weapon/circuitboard/teleporter
dir = 4
var/obj/item/locked = null
var/id = null
var/one_time_use = 0 //Used for one-time-use teleport cards (such as clown planet coordinates.)
//Setting this to 1 will set locked to null after a player enters the portal and will not allow hand-teles to open portals to that location.
var/datum/nano_module/program/teleport_control/teleport_control
/obj/machinery/computer/teleporter/New()
id = "[rand(1000, 9999)]"
..()
underlays.Cut()
underlays += image('icons/obj/stationobjs.dmi', icon_state = "telecomp-wires")
return
teleport_control = new(src)
/obj/machinery/computer/teleporter/Initialize()
. = ..()
var/obj/machinery/teleport/station/station
var/obj/machinery/teleport/hub/hub
var/obj/machinery/teleport/station/station = null
var/obj/machinery/teleport/hub/hub = null
// Search surrounding turfs for the station, and then search the station's surrounding turfs for the hub.
for(var/direction in cardinal)
station = locate(/obj/machinery/teleport/station, get_step(src, direction))
@@ -34,9 +37,15 @@
if(istype(station))
station.com = hub
teleport_control.hub = hub
if(istype(hub))
hub.com = src
teleport_control.station = station
/obj/machinery/computer/teleporter/Destroy()
qdel_null(teleport_control)
return ..()
/obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/card/data/))
@@ -74,7 +83,7 @@
else
for(var/mob/O in hearers(src, null))
O.show_message("<span class='notice'>Locked In</span>", 2)
locked = L
teleport_control.locked = L
one_time_use = 1
add_fingerprint(usr)
@@ -86,57 +95,109 @@
/obj/machinery/teleport/station/attack_ai()
attack_hand()
/obj/machinery/computer/teleporter/attack_hand(user as mob)
if(..()) return
/obj/machinery/computer/teleporter/attack_ai(mob/user)
ui_interact(user)
/* Ghosts can't use this one because it's a direct selection */
if(istype(user, /mob/observer/dead)) return
/obj/machinery/computer/teleporter/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
ui_interact(user)
var/list/L = list()
var/list/areaindex = list()
/obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
teleport_control.ui_interact(user, ui_key, ui, force_open)
for(var/obj/item/device/radio/beacon/R in all_beacons)
var/turf/T = get_turf(R)
if(!T)
continue
if(!(T.z in using_map.player_levels))
continue
var/tmpname = T.loc.name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
L[tmpname] = R
/obj/machinery/computer/teleporter/interact(mob/user)
teleport_control.ui_interact(user)
for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
if(!I.implanted || !ismob(I.loc))
continue
else
var/mob/M = I.loc
if(M.stat == 2)
if(M.timeofdeath + 6000 < world.time)
continue
var/turf/T = get_turf(M)
if(T) continue
if(T.z == 2) continue
var/tmpname = M.real_name
//////
////// Nano-module for teleporter
//////
/datum/nano_module/program/teleport_control
name = "Teleporter Control"
var/locked_name = "Not Locked"
var/obj/item/locked = null
var/obj/machinery/teleport/station/station = null
var/obj/machinery/teleport/hub/hub = null
/datum/nano_module/program/teleport_control/Topic(href, href_list)
if(..()) return 1
if(href_list["select_target"])
var/list/L = list()
var/list/areaindex = list()
for(var/obj/item/device/radio/beacon/R in all_beacons)
var/turf/T = get_turf(R)
if(!T)
continue
if(!(T.z in using_map.player_levels))
continue
var/tmpname = T.loc.name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
L[tmpname] = I
L[tmpname] = R
var/desc = input("Please select a location to lock in.", "Locking Computer") in L|null
if(!desc)
return
if(get_dist(src, usr) > 1 && !issilicon(usr))
return
for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
if(!I.implanted || !ismob(I.loc))
continue
else
var/mob/M = I.loc
if(M.stat == 2)
if(M.timeofdeath + 6000 < world.time)
continue
var/turf/T = get_turf(M)
if(T) continue
if(T.z == 2) continue
var/tmpname = M.real_name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
else
areaindex[tmpname] = 1
L[tmpname] = I
locked = L[desc]
for(var/mob/O in hearers(src, null))
O.show_message("<span class='notice'>Locked In</span>", 2)
add_fingerprint(usr)
return
var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null
if(!desc)
return 0
if(get_dist(host, usr) > 1 && !issilicon(usr))
return 0
locked = L[desc]
locked_name = desc
return 1
if(href_list["test_fire"])
station?.testfire()
return 1
if(href_list["toggle_on"])
if(!station)
return 0
if(station.engaged)
station.disengage()
else
station.engage()
return 1
/datum/nano_module/program/teleport_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
data["locked_name"] = locked_name ? locked_name : "No Target"
data["station_connected"] = station ? 1 : 0
data["hub_connected"] = hub ? 1 : 0
data["calibrated"] = hub ? hub.accurate : 0
data["teleporter_on"] = station ? station.engaged : 0
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "teleport_control.tmpl", "Teleport Control Console", 400, 500, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/teleporter/verb/set_id(t as text)
set category = "Object"
@@ -158,6 +219,9 @@
if(!T || istype(T, /area)) return null
return T
//////
////// Root of all the machinery
//////
/obj/machinery/teleport
name = "teleport"
icon = 'icons/obj/stationobjs.dmi'
@@ -165,6 +229,9 @@
anchored = 1.0
var/lockeddown = 0
//////
////// The part you step into
//////
/obj/machinery/teleport/hub
name = "teleporter hub"
desc = "It's the hub of a teleporting machine."
@@ -177,22 +244,15 @@
circuit = /obj/item/weapon/circuitboard/teleporter_hub
var/obj/machinery/computer/teleporter/com
/obj/machinery/teleport/hub/New()
..()
underlays.Cut()
/obj/machinery/teleport/hub/Initialize()
. = ..()
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
default_apply_parts()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/stack/cable_coil(src, 10)
RefreshParts()
/obj/machinery/teleport/hub/Destroy()
com?.teleport_control.hub = null
com = null
return ..()
/obj/machinery/teleport/hub/Bumped(M as mob|obj)
spawn()
@@ -204,7 +264,7 @@
/obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj)
if(!com)
return
if(!com.locked)
if(!com.teleport_control.locked)
for(var/mob/O in hearers(src, null))
O.show_message("<span class='warning'>Failure: Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.</span>")
return
@@ -212,11 +272,11 @@
if(prob(5) && !accurate) //oh dear a problem, put em in deep space
do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), 3), 2)
else
do_teleport(M, com.locked) //dead-on precision
do_teleport(M, com.teleport_control.locked) //dead-on precision
if(com.one_time_use) //Make one-time-use cards only usable one time!
com.one_time_use = 0
com.locked = null
com.teleport_control.locked = null
else
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
@@ -226,92 +286,10 @@
for(var/mob/B in hearers(src, null))
B.show_message("<span class='notice'>Test fire completed.</span>")
return
/*
/proc/do_teleport(atom/movable/M as mob|obj, atom/destination, precision)
if(istype(M, /obj/effect))
qdel(M)
return
if(istype(M, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite
for(var/mob/O in viewers(M, null))
O.show_message(text("<span class='danger'>The [] bounces off of the portal!</span>", M.name), 1)
return
if(istype(M, /mob/living))
var/mob/living/MM = M
if(MM.check_contents_for(/obj/item/weapon/disk/nuclear))
to_chat(MM, "<span class='warning'>Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.</span>")
return
var/disky = 0
for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite
if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift))
for (var/obj/OO in O.contents)
if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift))
for (var/obj/OOO in OO.contents)
if(istype(OOO, /obj/item/weapon/disk/nuclear))
disky = 1
if(istype(OO, /obj/item/weapon/disk/nuclear))
disky = 1
if(istype(O, /obj/item/weapon/disk/nuclear))
disky = 1
if(istype(O, /mob/living))
var/mob/living/MM = O
if(MM.check_contents_for(/obj/item/weapon/disk/nuclear))
disky = 1
if(disky)
for(var/mob/P in viewers(M, null))
P.show_message(text("<span class='danger'>The [] bounces off of the portal!</span>", M.name), 1)
return
//Bags of Holding cause bluespace teleportation to go funky. --NeoFite
if(istype(M, /mob/living))
var/mob/living/MM = M
if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding))
to_chat(MM, "<span class='warning'>The Bluespace interface on your Bag of Holding interferes with the teleport!</span>")
precision = rand(1,100)
if(istype(M, /obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite
if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift))
for (var/obj/OO in O.contents)
if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift))
for (var/obj/OOO in OO.contents)
if(istype(OOO, /obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
if(istype(OO, /obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
if(istype(O, /obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
if(istype(O, /mob/living))
var/mob/living/MM = O
if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
var/turf/destturf = get_turf(destination)
var/tx = destturf.x + rand(precision * -1, precision)
var/ty = destturf.y + rand(precision * -1, precision)
var/tmploc
if(ismob(destination.loc)) //If this is an implant.
tmploc = locate(tx, ty, destturf.z)
else
tmploc = locate(tx, ty, destination.z)
if(tx == destturf.x && ty == destturf.y && (istype(destination.loc, /obj/structure/closet) || istype(destination.loc, /obj/structure/closet/secure_closet)))
tmploc = destination.loc
if(tmploc==null)
return
M.loc = tmploc
sleep(2)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, M)
s.start()
return
*/
//////
////// The middle part
//////
/obj/machinery/teleport/station
name = "station"
desc = "It's the station thingy of a teleport thingy." //seriously, wtf.
@@ -325,29 +303,15 @@
circuit = /obj/item/weapon/circuitboard/teleporter_station
var/obj/machinery/teleport/hub/com
/obj/machinery/teleport/station/New()
..()
overlays.Cut()
overlays += image('icons/obj/stationobjs.dmi', icon_state = "controller-wires")
/obj/machinery/teleport/station/Initialize()
. = ..()
add_overlay("controller-wires")
default_apply_parts()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 10)
RefreshParts()
/obj/machinery/teleport/station/attackby(var/obj/item/weapon/W)
attack_hand()
/obj/machinery/teleport/station/attack_ai()
attack_hand()
/obj/machinery/teleport/station/attack_hand()
if(engaged)
disengage()
else
engage()
/obj/machinery/teleport/station/Destroy()
com?.com?.teleport_control.station = null
com = null
return ..()
/obj/machinery/teleport/station/proc/engage()
if(stat & (BROKEN|NOPOWER))
@@ -379,26 +343,16 @@
engaged = 0
return
/obj/machinery/teleport/station/verb/testfire()
set name = "Test Fire Teleporter"
set category = "Object"
set src in oview(1)
if(stat & (BROKEN|NOPOWER) || !istype(usr,/mob/living))
/obj/machinery/teleport/station/proc/testfire()
if(!com || active)
return
if(com && !active)
active = 1
for(var/mob/O in hearers(src, null))
O.show_message("<span class='notice'>Test firing!</span>", 2)
com.teleport()
use_power(5000)
active = TRUE
visible_message("<span class='notice'>Test firing!</span>")
com.teleport()
use_power(5000)
spawn(30)
active=0
add_fingerprint(usr)
return
VARSET_IN(src, active, FALSE, 3 SECONDS)
/obj/machinery/teleport/station/power_change()
..()

View File

@@ -23,13 +23,9 @@
active_power_usage = 200
light_color = "#FF0000"
/obj/machinery/vr_sleeper/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
/obj/machinery/vr_sleeper/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/vr_sleeper/Initialize()
. = ..()

View File

@@ -29,14 +29,10 @@
/obj/item/clothing/head/helmet/space
)
/obj/machinery/washing_machine/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/motor(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
RefreshParts()
/obj/machinery/washing_machine/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/washing_machine/verb/start()
set name = "Start Washing"
set category = "Object"

View File

@@ -12,15 +12,9 @@
var/charge = 45
var/repair = 0
/obj/machinery/mech_recharger/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
/obj/machinery/mech_recharger/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/mech_recharger/Crossed(var/obj/mecha/M)
. = ..()

View File

@@ -26,22 +26,11 @@
var/category = null
var/sync_message = ""
/obj/machinery/mecha_part_fabricator/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
files = new /datum/research(src) //Setup the research data holder.
return
/obj/machinery/mecha_part_fabricator/Initialize()
update_categories()
. = ..()
default_apply_parts()
files = new /datum/research(src) //Setup the research data holder.
update_categories()
/obj/machinery/mecha_part_fabricator/process()
..()

View File

@@ -29,18 +29,11 @@
var/species = "Human"
var/sync_message = ""
/obj/machinery/pros_fabricator/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
/obj/machinery/pros_fabricator/Initialize()
. = ..()
default_apply_parts()
files = new /datum/research(src) //Setup the research data holder.
return
/obj/machinery/pros_fabricator/Initialize()
. = ..()

View File

@@ -95,6 +95,11 @@
var/list/cargo = list()
var/cargo_capacity = 3
var/static/image/radial_image_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject"),
var/static/image/radial_image_airtoggle = image(icon= 'icons/mob/radial.dmi', icon_state = "radial_airtank"),
var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light"),
var/static/image/radial_image_statpanel = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine2")
/obj/mecha/drain_power(var/drain_check)
@@ -292,6 +297,51 @@
if(M == occupant && radio.broadcasting)
radio.talk_into(M, message_pieces)
/obj/mecha/proc/check_occupant_radial(var/mob/user)
if(!user)
return FALSE
if(user.stat)
return FALSE
if(user != occupant)
return FALSE
if(user.incapacitated())
return FALSE
return TRUE
/obj/mecha/proc/show_radial_occupant(var/mob/user)
var/list/choices = list(
"Eject" = radial_image_eject,
"Toggle Airtank" = radial_image_airtoggle,
"Toggle Light" = radial_image_lighttoggle,
"View Stats" = radial_image_statpanel
)
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_occupant_radial, user), require_near = TRUE, tooltips = TRUE)
if(!check_occupant_radial(user))
return
if(!choice)
return
switch(choice)
if("Eject")
go_out()
add_fingerprint(usr)
if("Toggle Airtank")
use_internal_tank = !use_internal_tank
occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
if("Toggle Light")
lights = !lights
if(lights)
set_light(light_range + lights_power)
else
set_light(light_range - lights_power)
occupant_message("Toggled lights [lights?"on":"off"].")
log_message("Toggled lights [lights?"on":"off"].")
playsound(src, 'sound/mecha/heavylightswitch.ogg', 50, 1)
if("View Stats")
occupant << browse(src.get_stats_html(), "window=exosuit")
////////////////////////////
///// Action processing ////
////////////////////////////
@@ -321,6 +371,9 @@
/obj/mecha/proc/click_action(atom/target,mob/user, params)
if(!src.occupant || src.occupant != user ) return
if(user.stat) return
if(target == src && user == occupant)
show_radial_occupant(user)
return
if(state)
occupant_message("<font color='red'>Maintenance protocols in effect</font>")
return
@@ -605,6 +658,10 @@
return
/obj/mecha/attack_hand(mob/user as mob)
if(user == occupant)
show_radial_occupant(user)
return
user.setClickCooldown(user.get_attack_speed())
src.log_message("Attack by hand/paw. Attacker - [user].",1)

View File

@@ -163,15 +163,29 @@
name = "growth"
desc = "Weird organic growth."
icon_state = "weeds"
anchored = 1
density = 0
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
var/health = 15
var/obj/effect/alien/weeds/node/linked_node = null
var/static/list/weedImageCache
/obj/effect/alien/weeds/Initialize(var/mapload, var/node, var/newcolor)
. = ..()
if(isspace(loc))
return INITIALIZE_HINT_QDEL
linked_node = node
if(newcolor)
color = newcolor
if(icon_state == "weeds")
icon_state = pick("weeds", "weeds1", "weeds2")
fullUpdateWeedOverlays()
/obj/effect/alien/weeds/Destroy()
var/turf/T = get_turf(src)
// To not mess up the overlay updates.
@@ -181,7 +195,7 @@
W.updateWeedOverlays()
linked_node = null
..()
return ..()
/obj/effect/alien/weeds/node
icon_state = "weednode"
@@ -189,45 +203,35 @@
desc = "Weird glowing organic growth."
layer = ABOVE_TURF_LAYER+0.01
light_range = NODERANGE
var/node_range = NODERANGE
var/set_color = "#321D37"
var/set_color = null
/obj/effect/alien/weeds/node/Initialize(var/mapload, var/node, var/newcolor)
. = ..()
/obj/effect/alien/weeds/node/New(var/newloc, var/newcolor = "#321D37")
var/obj/effect/alien/weeds/existing = locate() in get_turf(newloc)
if(existing)
qdel(existing)
for(var/obj/effect/alien/weeds/existing in loc)
if(existing == src)
continue
else
qdel(existing)
if(newcolor)
set_color = newcolor
if(set_color)
color = set_color
..(newloc, src)
/obj/effect/alien/weeds/node/Initialize()
..()
START_PROCESSING(SSobj, src)
START_PROCESSING(SSobj, src) // Only the node processes in a subsystem, the rest are process()'d by the node
/obj/effect/alien/weeds/node/Destroy()
STOP_PROCESSING(SSobj, src)
..()
/obj/effect/alien/weeds/New(pos, node)
..()
if(istype(loc, /turf/space))
qdel(src)
return
linked_node = node
if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2")
fullUpdateWeedOverlays()
return ..()
/obj/effect/alien/weeds/proc/updateWeedOverlays()
cut_overlays()
overlays.Cut()
if(!weedImageCache || !weedImageCache.len)
if(!weedImageCache)
weedImageCache = list()
// weedImageCache.len = 4
weedImageCache[WEED_NORTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_n", layer=2.11, pixel_y = -32)
weedImageCache[WEED_SOUTH_EDGING] = image('icons/mob/alien.dmi', "weeds_side_s", layer=2.11, pixel_y = 32)
weedImageCache[WEED_EAST_EDGING] = image('icons/mob/alien.dmi', "weeds_side_e", layer=2.11, pixel_x = -32)
@@ -237,18 +241,14 @@
var/turf/S = get_step(src, SOUTH)
var/turf/E = get_step(src, EAST)
var/turf/W = get_step(src, WEST)
if(!locate(/obj/effect/alien) in N.contents)
if(istype(N, /turf/simulated/floor))
overlays += weedImageCache[WEED_SOUTH_EDGING]
if(!locate(/obj/effect/alien) in S.contents)
if(istype(S, /turf/simulated/floor))
overlays += weedImageCache[WEED_NORTH_EDGING]
if(!locate(/obj/effect/alien) in E.contents)
if(istype(E, /turf/simulated/floor))
overlays += weedImageCache[WEED_WEST_EDGING]
if(!locate(/obj/effect/alien) in W.contents)
if(istype(W, /turf/simulated/floor))
overlays += weedImageCache[WEED_EAST_EDGING]
if(istype(N, /turf/simulated/floor) && !locate(/obj/effect/alien) in N.contents)
add_overlay(weedImageCache[WEED_SOUTH_EDGING])
if(istype(S, /turf/simulated/floor) && !locate(/obj/effect/alien) in S.contents)
add_overlay(weedImageCache[WEED_NORTH_EDGING])
if(istype(E, /turf/simulated/floor) && !locate(/obj/effect/alien) in E.contents)
add_overlay(weedImageCache[WEED_WEST_EDGING])
if(istype(W, /turf/simulated/floor) && !locate(/obj/effect/alien) in W.contents)
add_overlay(weedImageCache[WEED_EAST_EDGING])
/obj/effect/alien/weeds/proc/fullUpdateWeedOverlays()
for (var/obj/effect/alien/weeds/W in range(1,src))
@@ -256,73 +256,51 @@
return
// NB: This is not actually called by a processing subsystem, it's called by the node processing
/obj/effect/alien/weeds/process()
set background = 1
var/turf/U = get_turf(src)
/*
if (locate(/obj/movable, U))
U = locate(/obj/movable, U)
if(U.density == 1)
qdel(src)
return
Alien plants should do something if theres a lot of poison
if(U.poison> 200000)
health -= round(U.poison/200000)
update()
return
*/
if (istype(U, /turf/space))
if(isspace(U))
qdel(src)
return
if(!linked_node)
return
if(linked_node != src)
color = linked_node.set_color
if(get_dist(linked_node, src) > linked_node.node_range)
return
direction_loop:
for(var/dirn in cardinal)
var/turf/T = get_step(src, dirn)
for(var/dirn in cardinal)
var/turf/T1 = get_turf(src)
var/turf/T2 = get_step(src, dirn)
if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space))
continue
if(!istype(T2) || locate(/obj/effect/alien/weeds) in T2 || istype(T2.loc, /area/arrival) || isspace(T2))
continue
// if (locate(/obj/movable, T)) // don't propogate into movables
// continue
if(T1.c_airblock(T2) == BLOCKED)
continue
for(var/obj/O in T)
if(!O.CanZASPass(U))
continue direction_loop
new /obj/effect/alien/weeds(T2, linked_node, color)
var/obj/effect/E = new /obj/effect/alien/weeds(T, linked_node)
/obj/effect/alien/weeds/node/process()
set background = 1
. = ..()
E.color = color
var/list/nearby_weeds = list()
for(var/obj/effect/alien/weeds/W in orange(node_range, src))
nearby_weeds |= W
if(istype(src, /obj/effect/alien/weeds/node))
var/obj/effect/alien/weeds/node/N = src
var/list/nearby_weeds = list()
for(var/obj/effect/alien/weeds/W in range(N.node_range,src))
nearby_weeds |= W
for(var/nbw in nearby_weeds)
var/obj/effect/alien/weeds/W = nbw
for(var/obj/effect/alien/weeds/W in nearby_weeds)
if(!W)
continue
if(!W.linked_node)
W.linked_node = src
if(!W.linked_node)
W.linked_node = src
W.color = W.linked_node.set_color
if(W == src)
continue
if(prob(max(10, 40 - (5 * nearby_weeds.len))))
W.process()
W.color = W.linked_node.set_color
if(prob(max(10, 40 - (5 * nearby_weeds.len))))
W.process()
/obj/effect/alien/weeds/ex_act(severity)
switch(severity)

View File

@@ -49,6 +49,9 @@
if(triggered)
return
if(istype(M, /obj/mecha))
explode(M)
if(istype(M, /mob/living/))
if(!M.hovering)
explode(M)
@@ -79,7 +82,7 @@
triggered = 1
s.set_up(3, 1, src)
s.start()
if(M)
if(istype(M))
M.radiation += 50
randmutb(M)
domutcheck(M,null)
@@ -96,7 +99,7 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src)
s.start()
if(M)
if(istype(M))
M.Stun(30)
visible_message("\The [src.name] flashes violently before disintegrating!")
spawn(0)
@@ -136,7 +139,10 @@
triggered = 1
s.set_up(3, 1, src)
s.start()
if(M)
if(istype(M, /obj/mecha))
var/obj/mecha/E = M
M = E.occupant
if(istype(M))
qdel(M.client)
spawn(0)
qdel(s)
@@ -195,7 +201,7 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src)
s.start()
if(M)
if(istype(M))
M.adjust_fire_stacks(5)
M.fire_act()
visible_message("\The [src.name] bursts into flames!")

View File

@@ -7,6 +7,7 @@
anchored = 1
density = 0
opacity = 0
can_atmos_pass = ATMOS_PASS_PROC
/obj/effect/zone_divider/CanZASPass(turf/T, is_zone)
// Special case to prevent us from being part of a zone during the first air master tick.
@@ -15,5 +16,5 @@
if(air_master && air_master.current_cycle == 0)
spawn(1)
air_master.mark_for_update(get_turf(src))
return ATMOS_PASS_NO
return is_zone ? ATMOS_PASS_NO : ATMOS_PASS_YES // Anything except zones can pass
return FALSE
return is_zone ? FALSE : TRUE // Anything except zones can pass

View File

@@ -132,22 +132,13 @@
return -1
if(!listening)
return -1
if(is_jammed(src))
if(!on)
return -1
if (!on)
if(!freq)
return -1
if (!freq) //recieved on main frequency
if (!listening)
return -1
else
var/accept = (freq==frequency && listening)
if (!accept)
for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
if (RF && RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
if (!accept)
return -1
return canhear_range
//Only listen on main freq
if(freq == frequency)
return canhear_range
else
return -1

View File

@@ -9,9 +9,13 @@
/obj/fiftyspawner/Initialize()
..() //We're not returning . because we're going to ask to be deleted.
var/obj/item/stack/M = new type_to_spawn(get_turf(src))
var/turf/T = get_turf(src)
var/obj/item/stack/M = new type_to_spawn(T)
M.amount = M.max_amount //some stuff spawns with 60, we're still calling it fifty
M.update_icon() // Some stacks have different sprites depending on how full they are.
var/obj/structure/closet/C = locate() in T
if(C)
C.contents += M
return INITIALIZE_HINT_QDEL //Bye!
/obj/fiftyspawner/rods

View File

@@ -14,7 +14,6 @@
desc = "Murder device."
icon = 'icons/obj/weapons.dmi'
icon_state = "baton"
item_state = "classic_baton"
slot_flags = SLOT_BELT
force = 10
drop_sound = 'sound/items/drop/metalweapon.ogg'

View File

@@ -147,11 +147,11 @@ Frequency:
if(com)
break
break
if (istype(com, /obj/machinery/computer/teleporter) && com.locked && !com.one_time_use)
if (istype(com, /obj/machinery/computer/teleporter) && com.teleport_control.locked && !com.one_time_use)
if(R.icon_state == "tele1")
L["[com.id] (Active)"] = com.locked
L["[com.id] (Active)"] = com.teleport_control.locked
else
L["[com.id] (Inactive)"] = com.locked
L["[com.id] (Inactive)"] = com.teleport_control.locked
var/list/turfs = list( )
for(var/turf/T in orange(10))
if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb

View File

@@ -3,7 +3,7 @@
desc = "A window."
icon = 'icons/obj/structures.dmi'
density = 1
can_atmos_pass = ATMOS_PASS_DENSITY
can_atmos_pass = ATMOS_PASS_PROC
w_class = ITEMSIZE_NORMAL
layer = WINDOW_LAYER
@@ -143,8 +143,8 @@
/obj/structure/window/CanZASPass(turf/T, is_zone)
if(is_fulltile() || get_dir(T, loc) == turn(dir, 180)) // Make sure we're handling the border correctly.
return anchored ? ATMOS_PASS_NO : ATMOS_PASS_YES // If it's anchored, it'll block air.
return ATMOS_PASS_YES // Don't stop airflow from the other sides.
return !anchored // If it's anchored, it'll block air.
return TRUE // Don't stop airflow from the other sides.
/obj/structure/window/CheckExit(atom/movable/O as mob|obj, target as turf)
if(istype(O) && O.checkpass(PASSGLASS))

View File

@@ -216,7 +216,7 @@ var/list/flooring_types
icon_base = "lino"
can_paint = 1
build_type = /obj/item/stack/tile/linoleum
flags = TURF_REMOVE_SCREWDRIVER
flags = TURF_REMOVE_SCREWDRIVER | TURF_CAN_BREAK | TURF_CAN_BURN
/decl/flooring/tiling/red
name = "floor"
@@ -239,7 +239,6 @@ var/list/flooring_types
name = "floor"
icon_base = "asteroidfloor"
has_damage_range = null
flags = TURF_REMOVE_CROWBAR
build_type = /obj/item/stack/tile/floor/steel
/decl/flooring/tiling/white
@@ -252,7 +251,6 @@ var/list/flooring_types
name = "floor"
icon_base = "white"
has_damage_range = null
flags = TURF_REMOVE_CROWBAR
build_type = /obj/item/stack/tile/floor/yellow
/decl/flooring/tiling/dark
@@ -260,7 +258,6 @@ var/list/flooring_types
desc = "How ominous."
icon_base = "dark"
has_damage_range = null
flags = TURF_REMOVE_CROWBAR
build_type = /obj/item/stack/tile/floor/dark
/decl/flooring/tiling/hydro
@@ -308,7 +305,7 @@ var/list/flooring_types
desc = "Heavily reinforced with steel rods."
icon = 'icons/turf/flooring/tiles.dmi'
icon_base = "reinforced"
flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE
flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE | TURF_CAN_BURN | TURF_CAN_BREAK
build_type = /obj/item/stack/rods
build_cost = 2
build_time = 30
@@ -321,7 +318,7 @@ var/list/flooring_types
icon = 'icons/turf/flooring/circuit.dmi'
icon_base = "bcircuit"
build_type = null
flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR
flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_CAN_BURN | TURF_REMOVE_CROWBAR
can_paint = 1
/decl/flooring/reinforced/circuit/green

View File

@@ -1,4 +1,4 @@
var/list/flooring_cache = list()
GLOBAL_LIST_EMPTY(flooring_cache)
var/image/no_ceiling_image = null
@@ -79,10 +79,11 @@ var/image/no_ceiling_image = null
icon = 'icons/turf/flooring/plating.dmi'
icon_state = "dmg[rand(1,4)]"
else if(flooring)
var/rand_key = rand(0,2)
if(!isnull(broken) && (flooring.flags & TURF_CAN_BREAK))
add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[broken]","[flooring.icon_base]_broken[broken]"))
add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[rand_key]","broken[rand_key]"))
if(!isnull(burnt) && (flooring.flags & TURF_CAN_BURN))
add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","[flooring.icon_base]_burned[burnt]"))
add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[rand_key]","burned[rand_key]"))
if(update_neighbors)
for(var/turf/simulated/floor/F in range(src, 1))
@@ -96,8 +97,8 @@ var/image/no_ceiling_image = null
add_overlay(no_ceiling_image)
/turf/simulated/floor/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0)
if(!flooring_cache[cache_key])
if(!GLOB.flooring_cache[cache_key])
var/image/I = image(icon = flooring.icon, icon_state = icon_base, dir = icon_dir)
I.layer = layer
flooring_cache[cache_key] = I
return flooring_cache[cache_key]
GLOB.flooring_cache[cache_key] = I
return GLOB.flooring_cache[cache_key]

View File

@@ -11,14 +11,14 @@ var/list/grass_types = list(
/turf/simulated/floor/outdoors/dirt
)
var/grass_chance = 20
/*
var/animal_chance = 1
// Weighted spawn list.
var/list/animal_types = list(
/mob/living/simple_mob/animal/passive/tindalos = 1
)
*/
var/list/grass_types = list(
/obj/structure/flora/ausbushes/sparsegrass,
/obj/structure/flora/ausbushes/fullgrass
@@ -38,7 +38,7 @@ var/list/grass_types = list(
edge_blending_priority = 4
grass_chance = 5
var/tree_chance = 2
/*
animal_chance = 0.5
animal_types = list(
@@ -48,7 +48,7 @@ var/list/grass_types = list(
/mob/living/simple_mob/animal/sif/shantak/retaliate = 2,
/obj/random/mob/multiple/sifmobs = 1
)
*/
grass_types = list(
/obj/structure/flora/sif/eyes = 1,
/obj/structure/flora/sif/tendrils = 10
@@ -70,11 +70,11 @@ var/list/grass_types = list(
if(grass_chance && prob(grass_chance) && !check_density())
var/grass_type = pickweight(grass_types)
new grass_type(src)
/*
if(animal_chance && prob(animal_chance) && !check_density())
var/animal_type = pickweight(animal_types)
new animal_type(src)
*/
. = ..()
/turf/simulated/floor/outdoors/grass/forest

View File

@@ -16,7 +16,7 @@
if(config && config.log_runtime)
log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log")
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
init_vchat()

View File

@@ -142,6 +142,7 @@
hostile = FALSE
retaliate = FALSE
cooperative = FALSE
holder.a_intent = I_HELP
// The holder's attack changes based on intent. This lets the AI choose what effect is desired.
/datum/ai_holder/simple_mob/xenobio_slime/pre_melee_attack(atom/A)
@@ -178,6 +179,7 @@
if(!(H in grudges)) // Unless they're an ass.
return FALSE
if(discipline && !rabid)
holder.a_intent = I_HELP
return FALSE // We're a good slime.
/datum/ai_holder/simple_mob/xenobio_slime/react_to_attack(atom/movable/attacker)

View File

@@ -44,7 +44,8 @@
STANCE_REPOSITION,
STANCE_MOVE,
STANCE_FOLLOW,
STANCE_FLEE
STANCE_FLEE,
STANCE_DISABLED
)
var/list/static/noprocess_stances = list(
STANCE_SLEEP

View File

@@ -28,8 +28,6 @@
var/chatOutputLoadedAt
var/adminhelped = 0
var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel.
///////////////
//SOUND STUFF//

View File

@@ -5,17 +5,18 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
"operative" = 1, // 1
"changeling" = 1, // 2
"wizard" = 1, // 3
"malf AI" = 1, // 4
"malf AI" = 1, // 4
"revolutionary" = 1, // 5
"alien candidate" = 1, // 6
"positronic brain" = 1, // 7
"cultist" = 1, // 8
"renegade" = 1, // 9
"ninja" = 1, // 10
"renegade" = 1, // 9
"ninja" = 1, // 10
"raider" = 1, // 11
"diona" = 1, // 12
"loyalist" = 1, // 13
"pAI candidate" = 1, // -- TLE // 14
"diona" = 1, // 12
"mutineer" = 1, // 13
"loyalist" = 1, // 14
"pAI candidate" = 1, // 15
)
/datum/category_item/player_setup_item/antagonism/candidacy

View File

@@ -131,6 +131,10 @@ datum/preferences
var/lastnews // Hash of last seen lobby news content.
var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel.
var/multilingual_mode = 0 // Default behaviour, delimiter-key-space, delimiter-key-delimiter, off
/datum/preferences/New(client/C)
player_setup = new(src)
set_biological_gender(pick(MALE, FEMALE))

View File

@@ -81,6 +81,8 @@
else
player_setup.load_character(S)
S.cd = "/character[default_slot]"
player_setup.save_character(S)
sanitize_preferences()
player_setup.load_character(S)
return 1

View File

@@ -13,6 +13,7 @@ var/list/spawntypes = list()
var/list/restrict_job = null
var/list/disallow_job = null
var/announce_channel = "Common"
var/allowed_mob_types = JOB_SILICON|JOB_CARBON
proc/check_job_spawning(job)
if(restrict_job && !(job in restrict_job))
@@ -22,9 +23,15 @@ var/list/spawntypes = list()
return 0
var/datum/job/J = SSjob.get_job(job)
if(J?.offmap_spawn && !(job in restrict_job))
if(!J) // Couldn't find, admin shenanigans? Allow it
return 1
if(J.offmap_spawn && !(job in restrict_job))
return 0
if(!(J.mob_type & allowed_mob_types))
return 0
return 1
/datum/spawnpoint/proc/get_spawn_position()
@@ -57,7 +64,7 @@ var/list/spawntypes = list()
/datum/spawnpoint/cryo
display_name = "Cryogenic Storage"
msg = "has completed cryogenic revival"
disallow_job = list("Cyborg")
allowed_mob_types = JOB_CARBON
/datum/spawnpoint/cryo/New()
..()
@@ -66,7 +73,7 @@ var/list/spawntypes = list()
/datum/spawnpoint/cyborg
display_name = "Cyborg Storage"
msg = "has been activated from storage"
restrict_job = list("Cyborg")
allowed_mob_types = JOB_SILICON
/datum/spawnpoint/cyborg/New()
..()

View File

@@ -313,17 +313,34 @@
set category = "Preferences"
set desc = "Control the additional behaviour of examining things"
examine_text_mode++
examine_text_mode %= EXAMINE_MODE_MAX // This cycles through them because if you're already specifically being routed to the examine panel, you probably don't need to have the extra text printed to chat
switch(examine_text_mode) // ... And I only wanted to add one verb
prefs.examine_text_mode++
prefs.examine_text_mode %= EXAMINE_MODE_MAX // This cycles through them because if you're already specifically being routed to the examine panel, you probably don't need to have the extra text printed to chat
switch(prefs.examine_text_mode) // ... And I only wanted to add one verb
if(EXAMINE_MODE_DEFAULT)
to_chat(src, "Examining things will only output the base examine text, and you will not be redirected to the examine panel automatically.")
to_chat(src, "<span class='filter_system'>Examining things will only output the base examine text, and you will not be redirected to the examine panel automatically.</span>")
if(EXAMINE_MODE_INCLUDE_USAGE)
to_chat(src, "Examining things will also print any extra usage information normally included in the examine panel to the chat.")
to_chat(src, "<span class='filter_system'>Examining things will also print any extra usage information normally included in the examine panel to the chat.</span>")
if(EXAMINE_MODE_SWITCH_TO_PANEL)
to_chat(src, "Examining things will direct you to the examine panel, where you can view extended information about the thing.")
to_chat(src, "<span class='filter_system'>Examining things will direct you to the examine panel, where you can view extended information about the thing.</span>")
/client/verb/toggle_multilingual_mode()
set name = "Toggle Multilingual Mode"
set category = "Preferences"
set desc = "Control the behaviour of multilingual speech parsing"
prefs.multilingual_mode++
prefs.multilingual_mode %= MULTILINGUAL_MODE_MAX // Cycles through the various options
switch(prefs.multilingual_mode)
if(MULTILINGUAL_DEFAULT)
to_chat(src, "<span class='filter_system'>Multilingual parsing will only check for the delimiter-key combination (,0galcom-2tradeband).</span>")
if(MULTILINGUAL_SPACE)
to_chat(src, "<span class='filter_system'>Multilingual parsing will enforce a space after the delimiter-key combination (,0 galcom -2still galcom). The extra space will be consumed by the pattern-matching.</span>")
if(MULTILINGUAL_DOUBLE_DELIMITER)
to_chat(src, "<span class='filter_system'>Multilingual parsing will enforce the a language delimiter after the delimiter-key combination (,0,galcom -2 still galcom). The extra delimiter will be consumed by the pattern-matching.</span>")
if(MULTILINGUAL_OFF)
to_chat(src, "<span class='filter_system'>Multilingual parsing is now disabled. Entire messages will be in the language specified at the start of the message.</span>")
//Toggles for Staff

View File

@@ -16,14 +16,9 @@
var/last_process_worldtime = 0
var/report_num = 0
/obj/machinery/dnaforensics/New()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
RefreshParts()
..()
/obj/machinery/dnaforensics/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/dnaforensics/attackby(var/obj/item/W, mob/user as mob)

View File

@@ -22,7 +22,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
var/last_world_time = 0
/datum/event_container/process()
if(!round_start_time)
if(!GLOB.round_start_time)
return //don't do events if the round hasn't even started yet
if(!next_event_time)

View File

@@ -12,7 +12,7 @@
var/lid_color = "black"
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/Initialize()
..()
. = ..()
lid_color = pick("black", "red", "blue")
update_icon()
@@ -24,8 +24,14 @@
name = "protein shake"
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake/Initialize()
..()
. = ..()
reagents.add_reagent("nutriment", 30)
reagents.add_reagent("iron", 10)
reagents.add_reagent("protein", 35)
reagents.add_reagent("water", 25)
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake/update_icon()
..()
// And now set half the stuff back because our name shouldn't change
name = initial(name)
desc = initial(desc)

View File

@@ -26,6 +26,8 @@
return
/obj/item/weapon/reagent_containers/food/condiment/afterattack(var/obj/target, var/mob/user, var/flag)
if(!user.Adjacent(target))
return
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))

View File

@@ -31,13 +31,11 @@
********************/
/obj/machinery/microwave/Initialize()
. = ..()
reagents = new/datum/reagents(100)
reagents.my_atom = src
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/weapon/stock_parts/motor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
default_apply_parts()
if (!available_recipes)
available_recipes = new
@@ -60,9 +58,7 @@
acceptable_items |= /obj/item/device/soulstone
acceptable_items |= /obj/item/weapon/fuel_assembly/supermatter
RefreshParts()
soundloop = new(list(src), FALSE)
return ..()
/obj/machinery/microwave/Destroy()
QDEL_NULL(soundloop)

View File

@@ -126,9 +126,11 @@
"mutagen" = 15
)
/obj/machinery/portable_atmospherics/hydroponics/AltClick()
if(mechanical && !usr.incapacitated() && Adjacent(usr))
close_lid(usr)
/obj/machinery/portable_atmospherics/hydroponics/AltClick(var/mob/living/user)
if(!istype(user))
return
if(mechanical && !user.incapacitated() && Adjacent(user))
close_lid(user)
return 1
return ..()

View File

@@ -86,10 +86,10 @@
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ds, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ds, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ds, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ds, "ss") ) )
push_data()
activate_pin(2)

View File

@@ -52,16 +52,9 @@
var/need_update_field = 0
var/need_player_check = 0
/obj/machinery/mining/drill/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/cell/high(src)
RefreshParts()
/obj/machinery/mining/drill/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/mining/drill/process()

View File

@@ -0,0 +1,93 @@
/datum/modifier/changeling
name = "changeling"
desc = "Changeling modifier."
var/required_chems = 1 // Default is to require at least 1 chem unit. This does not consume it.
var/chem_maintenance = 1 // How many chems are expended per cycle, if we are consuming chems.
var/max_genetic_damage = 100
var/max_stat = 0
var/use_chems = FALSE // Do we have an upkeep cost on chems?
var/exterior_modifier = FALSE // Should we be checking the origin mob for chems?
/datum/modifier/changeling/check_if_valid()
var/mob/living/L = null
if(exterior_modifier)
if(origin)
L = origin.resolve()
else
expire()
return
if((!exterior_modifier && !holder.changeling_power(required_chems, 0, max_genetic_damage, max_stat)) || (exterior_modifier && L && !L.changeling_power(required_chems, 0, max_genetic_damage, max_stat)))
expire()
else
..()
/datum/modifier/changeling/tick()
..()
if(use_chems)
var/mob/living/L = null
if(exterior_modifier)
L = origin.resolve()
else
L = holder
L.mind.changeling.chem_charges = between(0, L.mind.changeling.chem_charges - chem_maintenance, L.mind.changeling.chem_storage)
/datum/modifier/changeling/thermal_sight
name = "Thermal Adaptation"
desc = "Our eyes are capable of seeing into the infrared spectrum to accurately identify prey through walls."
vision_flags = SEE_MOBS
on_expired_text = "<span class='alien'>Your sight returns to what it once was.</span>"
stacks = MODIFIER_STACK_EXTEND
/datum/modifier/changeling/thermal_sight/check_if_valid()
var/mob/living/L = null
if(exterior_modifier)
L = origin.resolve()
else
L = holder
if(!L)
expire()
return
var/datum/changeling/changeling = L.changeling_power(0,0,100,CONSCIOUS)
if(!changeling)
expire()
return
if(!changeling.thermal_sight)
expire()
return
..()
/datum/modifier/changeling/thermal_sight/expire()
var/mob/living/L = null
if(exterior_modifier)
L = origin.resolve()
else
L = holder
if(L)
var/datum/changeling/changeling = L.changeling_power(0,0,100,CONSCIOUS)
if(changeling)
changeling.thermal_sight = FALSE
..()

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