mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-26 01:52:29 +00:00
Merge branch 'master' into pol-rndconsole
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]'")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
62
code/controllers/subsystems/nightshift.dm
Normal file
62
code/controllers/subsystems/nightshift.dm
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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. \
|
||||
|
||||
@@ -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. \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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!"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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]"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
STANCE_REPOSITION,
|
||||
STANCE_MOVE,
|
||||
STANCE_FOLLOW,
|
||||
STANCE_FLEE
|
||||
STANCE_FLEE,
|
||||
STANCE_DISABLED
|
||||
)
|
||||
var/list/static/noprocess_stances = list(
|
||||
STANCE_SLEEP
|
||||
|
||||
@@ -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//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
93
code/modules/mob/_modifiers/changeling.dm
Normal file
93
code/modules/mob/_modifiers/changeling.dm
Normal 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
Reference in New Issue
Block a user