Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into one-more-dojo-tweak
This commit is contained in:
+1352
-1352
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,31 @@
|
||||
/area/ai_monitored
|
||||
name = "AI Monitored Area"
|
||||
clockwork_warp_allowed = FALSE
|
||||
var/list/obj/machinery/camera/motioncameras = list()
|
||||
var/list/datum/weakref/motionTargets = list()
|
||||
|
||||
/area/ai_monitored/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload)
|
||||
for (var/obj/machinery/camera/M in src)
|
||||
if(M.isMotion())
|
||||
motioncameras.Add(M)
|
||||
M.area_motion = src
|
||||
|
||||
//Only need to use one camera
|
||||
|
||||
/area/ai_monitored/Entered(atom/movable/O)
|
||||
..()
|
||||
if (ismob(O) && motioncameras.len)
|
||||
for(var/X in motioncameras)
|
||||
var/obj/machinery/camera/cam = X
|
||||
cam.newTarget(O)
|
||||
return
|
||||
|
||||
/area/ai_monitored/Exited(atom/movable/O)
|
||||
..()
|
||||
if (ismob(O) && motioncameras.len)
|
||||
for(var/X in motioncameras)
|
||||
var/obj/machinery/camera/cam = X
|
||||
cam.lostTargetRef(WEAKREF(O))
|
||||
/area/ai_monitored
|
||||
name = "AI Monitored Area"
|
||||
clockwork_warp_allowed = FALSE
|
||||
var/list/obj/machinery/camera/motioncameras = list()
|
||||
var/list/datum/weakref/motionTargets = list()
|
||||
|
||||
/area/ai_monitored/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload)
|
||||
for (var/obj/machinery/camera/M in src)
|
||||
if(M.isMotion())
|
||||
motioncameras.Add(M)
|
||||
M.area_motion = src
|
||||
|
||||
//Only need to use one camera
|
||||
|
||||
/area/ai_monitored/Entered(atom/movable/O)
|
||||
..()
|
||||
if (ismob(O) && motioncameras.len)
|
||||
for(var/X in motioncameras)
|
||||
var/obj/machinery/camera/cam = X
|
||||
cam.newTarget(O)
|
||||
return
|
||||
|
||||
/area/ai_monitored/Exited(atom/movable/O)
|
||||
..()
|
||||
if (ismob(O) && motioncameras.len)
|
||||
for(var/X in motioncameras)
|
||||
var/obj/machinery/camera/cam = X
|
||||
cam.lostTargetRef(WEAKREF(O))
|
||||
return
|
||||
+865
-865
File diff suppressed because it is too large
Load Diff
+874
-874
File diff suppressed because it is too large
Load Diff
+199
-199
@@ -1,199 +1,199 @@
|
||||
/*
|
||||
HOW IT WORKS
|
||||
|
||||
The SSradio is a global object maintaining all radio transmissions, think about it as about "ether".
|
||||
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
|
||||
procs:
|
||||
|
||||
add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null)
|
||||
Adds listening object.
|
||||
parameters:
|
||||
device - device receiving signals, must have proc receive_signal (see description below).
|
||||
one device may listen several frequencies, but not same frequency twice.
|
||||
new_frequency - see possibly frequencies below;
|
||||
filter - thing for optimization. Optional, but recommended.
|
||||
All filters should be consolidated in this file, see defines later.
|
||||
Device without listening filter will receive all signals (on specified frequency).
|
||||
Device with filter will receive any signals sent without filter.
|
||||
Device with filter will not receive any signals sent with different filter.
|
||||
returns:
|
||||
Reference to frequency object.
|
||||
|
||||
remove_object (obj/device, old_frequency)
|
||||
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
|
||||
Other frequencies will left unaffected.
|
||||
|
||||
return_frequency(var/frequency as num)
|
||||
returns:
|
||||
Reference to frequency object. Use it if you need to send and do not need to listen.
|
||||
|
||||
radio_frequency is a global object maintaining list of devices that listening specific frequency.
|
||||
procs:
|
||||
|
||||
post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null)
|
||||
Sends signal to all devices that wants such signal.
|
||||
parameters:
|
||||
source - object, emitted signal. Usually, devices will not receive their own signals.
|
||||
signal - see description below.
|
||||
filter - described above.
|
||||
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
|
||||
|
||||
obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param)
|
||||
Handler from received signals. By default does nothing. Define your own for your object.
|
||||
Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please.
|
||||
parameters:
|
||||
signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
|
||||
receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
|
||||
TRANSMISSION_WIRE is currently unused.
|
||||
receive_param - for TRANSMISSION_RADIO here comes frequency.
|
||||
|
||||
datum/signal
|
||||
vars:
|
||||
source
|
||||
an object that emitted signal. Used for debug and bearing.
|
||||
data
|
||||
list with transmitting data. Usual use pattern:
|
||||
data["msg"] = "hello world"
|
||||
encryption
|
||||
Some number symbolizing "encryption key".
|
||||
Note that game actually do not use any cryptography here.
|
||||
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
|
||||
|
||||
*/
|
||||
/* the radio controller is a confusing piece of shit and didnt work
|
||||
so i made radios not use the radio controller.
|
||||
*/
|
||||
GLOBAL_LIST_EMPTY(all_radios)
|
||||
/proc/add_radio(obj/item/radio, freq)
|
||||
if(!freq || !radio)
|
||||
return
|
||||
if(!GLOB.all_radios["[freq]"])
|
||||
GLOB.all_radios["[freq]"] = list(radio)
|
||||
return freq
|
||||
|
||||
GLOB.all_radios["[freq]"] |= radio
|
||||
return freq
|
||||
|
||||
/proc/remove_radio(obj/item/radio, freq)
|
||||
if(!freq || !radio)
|
||||
return
|
||||
if(!GLOB.all_radios["[freq]"])
|
||||
return
|
||||
|
||||
GLOB.all_radios["[freq]"] -= radio
|
||||
|
||||
/proc/remove_radio_all(obj/item/radio)
|
||||
for(var/freq in GLOB.all_radios)
|
||||
GLOB.all_radios["[freq]"] -= radio
|
||||
|
||||
// For information on what objects or departments use what frequencies,
|
||||
// see __DEFINES/radio.dm. Mappers may also select additional frequencies for
|
||||
// use in maps, such as in intercoms.
|
||||
|
||||
GLOBAL_LIST_INIT(radiochannels, list(
|
||||
RADIO_CHANNEL_COMMON = FREQ_COMMON,
|
||||
RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE,
|
||||
RADIO_CHANNEL_COMMAND = FREQ_COMMAND,
|
||||
RADIO_CHANNEL_MEDICAL = FREQ_MEDICAL,
|
||||
RADIO_CHANNEL_ENGINEERING = FREQ_ENGINEERING,
|
||||
RADIO_CHANNEL_SECURITY = FREQ_SECURITY,
|
||||
RADIO_CHANNEL_CENTCOM = FREQ_CENTCOM,
|
||||
RADIO_CHANNEL_SYNDICATE = FREQ_SYNDICATE,
|
||||
RADIO_CHANNEL_SUPPLY = FREQ_SUPPLY,
|
||||
RADIO_CHANNEL_SERVICE = FREQ_SERVICE,
|
||||
RADIO_CHANNEL_AI_PRIVATE = FREQ_AI_PRIVATE,
|
||||
RADIO_CHANNEL_CTF_RED = FREQ_CTF_RED,
|
||||
RADIO_CHANNEL_CTF_BLUE = FREQ_CTF_BLUE
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(reverseradiochannels, list(
|
||||
"[FREQ_COMMON]" = RADIO_CHANNEL_COMMON,
|
||||
"[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE,
|
||||
"[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND,
|
||||
"[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL,
|
||||
"[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING,
|
||||
"[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY,
|
||||
"[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM,
|
||||
"[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE,
|
||||
"[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY,
|
||||
"[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE,
|
||||
"[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE,
|
||||
"[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED,
|
||||
"[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE
|
||||
))
|
||||
|
||||
/datum/radio_frequency
|
||||
var/frequency as num
|
||||
var/list/list/obj/devices = list()
|
||||
|
||||
/datum/radio_frequency/New(freq)
|
||||
frequency = freq
|
||||
|
||||
//If range > 0, only post to devices on the same z_level and within range
|
||||
//Use range = -1, to restrain to the same z_level without limiting range
|
||||
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null)
|
||||
// Ensure the signal's data is fully filled
|
||||
signal.source = source
|
||||
signal.frequency = frequency
|
||||
|
||||
//Apply filter to the signal. If none supply, broadcast to every devices
|
||||
//_default channel is always checked
|
||||
var/list/filter_list
|
||||
|
||||
if(filter)
|
||||
filter_list = list(filter,"_default")
|
||||
else
|
||||
filter_list = devices
|
||||
|
||||
//If checking range, find the source turf
|
||||
var/turf/start_point
|
||||
if(range)
|
||||
start_point = get_turf(source)
|
||||
if(!start_point)
|
||||
return 0
|
||||
|
||||
//Send the data
|
||||
for(var/current_filter in filter_list)
|
||||
for(var/obj/device in devices[current_filter])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range))
|
||||
continue
|
||||
device.receive_signal(signal)
|
||||
|
||||
/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null)
|
||||
if (!filter)
|
||||
filter = "_default"
|
||||
|
||||
var/list/devices_line = devices[filter]
|
||||
if(!devices_line)
|
||||
devices[filter] = devices_line = list()
|
||||
devices_line += device
|
||||
|
||||
|
||||
/datum/radio_frequency/proc/remove_listener(obj/device)
|
||||
for(var/devices_filter in devices)
|
||||
var/list/devices_line = devices[devices_filter]
|
||||
if(!devices_line)
|
||||
devices -= devices_filter
|
||||
devices_line -= device
|
||||
if(!devices_line.len)
|
||||
devices -= devices_filter
|
||||
|
||||
|
||||
/obj/proc/receive_signal(datum/signal/signal)
|
||||
return
|
||||
|
||||
/datum/signal
|
||||
var/obj/source
|
||||
var/frequency = 0
|
||||
var/transmission_method
|
||||
var/list/data
|
||||
|
||||
/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO)
|
||||
src.data = data || list()
|
||||
src.transmission_method = transmission_method
|
||||
/*
|
||||
HOW IT WORKS
|
||||
|
||||
The SSradio is a global object maintaining all radio transmissions, think about it as about "ether".
|
||||
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
|
||||
procs:
|
||||
|
||||
add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null)
|
||||
Adds listening object.
|
||||
parameters:
|
||||
device - device receiving signals, must have proc receive_signal (see description below).
|
||||
one device may listen several frequencies, but not same frequency twice.
|
||||
new_frequency - see possibly frequencies below;
|
||||
filter - thing for optimization. Optional, but recommended.
|
||||
All filters should be consolidated in this file, see defines later.
|
||||
Device without listening filter will receive all signals (on specified frequency).
|
||||
Device with filter will receive any signals sent without filter.
|
||||
Device with filter will not receive any signals sent with different filter.
|
||||
returns:
|
||||
Reference to frequency object.
|
||||
|
||||
remove_object (obj/device, old_frequency)
|
||||
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
|
||||
Other frequencies will left unaffected.
|
||||
|
||||
return_frequency(var/frequency as num)
|
||||
returns:
|
||||
Reference to frequency object. Use it if you need to send and do not need to listen.
|
||||
|
||||
radio_frequency is a global object maintaining list of devices that listening specific frequency.
|
||||
procs:
|
||||
|
||||
post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null)
|
||||
Sends signal to all devices that wants such signal.
|
||||
parameters:
|
||||
source - object, emitted signal. Usually, devices will not receive their own signals.
|
||||
signal - see description below.
|
||||
filter - described above.
|
||||
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
|
||||
|
||||
obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param)
|
||||
Handler from received signals. By default does nothing. Define your own for your object.
|
||||
Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please.
|
||||
parameters:
|
||||
signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
|
||||
receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
|
||||
TRANSMISSION_WIRE is currently unused.
|
||||
receive_param - for TRANSMISSION_RADIO here comes frequency.
|
||||
|
||||
datum/signal
|
||||
vars:
|
||||
source
|
||||
an object that emitted signal. Used for debug and bearing.
|
||||
data
|
||||
list with transmitting data. Usual use pattern:
|
||||
data["msg"] = "hello world"
|
||||
encryption
|
||||
Some number symbolizing "encryption key".
|
||||
Note that game actually do not use any cryptography here.
|
||||
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
|
||||
|
||||
*/
|
||||
/* the radio controller is a confusing piece of shit and didnt work
|
||||
so i made radios not use the radio controller.
|
||||
*/
|
||||
GLOBAL_LIST_EMPTY(all_radios)
|
||||
/proc/add_radio(obj/item/radio, freq)
|
||||
if(!freq || !radio)
|
||||
return
|
||||
if(!GLOB.all_radios["[freq]"])
|
||||
GLOB.all_radios["[freq]"] = list(radio)
|
||||
return freq
|
||||
|
||||
GLOB.all_radios["[freq]"] |= radio
|
||||
return freq
|
||||
|
||||
/proc/remove_radio(obj/item/radio, freq)
|
||||
if(!freq || !radio)
|
||||
return
|
||||
if(!GLOB.all_radios["[freq]"])
|
||||
return
|
||||
|
||||
GLOB.all_radios["[freq]"] -= radio
|
||||
|
||||
/proc/remove_radio_all(obj/item/radio)
|
||||
for(var/freq in GLOB.all_radios)
|
||||
GLOB.all_radios["[freq]"] -= radio
|
||||
|
||||
// For information on what objects or departments use what frequencies,
|
||||
// see __DEFINES/radio.dm. Mappers may also select additional frequencies for
|
||||
// use in maps, such as in intercoms.
|
||||
|
||||
GLOBAL_LIST_INIT(radiochannels, list(
|
||||
RADIO_CHANNEL_COMMON = FREQ_COMMON,
|
||||
RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE,
|
||||
RADIO_CHANNEL_COMMAND = FREQ_COMMAND,
|
||||
RADIO_CHANNEL_MEDICAL = FREQ_MEDICAL,
|
||||
RADIO_CHANNEL_ENGINEERING = FREQ_ENGINEERING,
|
||||
RADIO_CHANNEL_SECURITY = FREQ_SECURITY,
|
||||
RADIO_CHANNEL_CENTCOM = FREQ_CENTCOM,
|
||||
RADIO_CHANNEL_SYNDICATE = FREQ_SYNDICATE,
|
||||
RADIO_CHANNEL_SUPPLY = FREQ_SUPPLY,
|
||||
RADIO_CHANNEL_SERVICE = FREQ_SERVICE,
|
||||
RADIO_CHANNEL_AI_PRIVATE = FREQ_AI_PRIVATE,
|
||||
RADIO_CHANNEL_CTF_RED = FREQ_CTF_RED,
|
||||
RADIO_CHANNEL_CTF_BLUE = FREQ_CTF_BLUE
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(reverseradiochannels, list(
|
||||
"[FREQ_COMMON]" = RADIO_CHANNEL_COMMON,
|
||||
"[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE,
|
||||
"[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND,
|
||||
"[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL,
|
||||
"[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING,
|
||||
"[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY,
|
||||
"[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM,
|
||||
"[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE,
|
||||
"[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY,
|
||||
"[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE,
|
||||
"[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE,
|
||||
"[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED,
|
||||
"[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE
|
||||
))
|
||||
|
||||
/datum/radio_frequency
|
||||
var/frequency as num
|
||||
var/list/list/obj/devices = list()
|
||||
|
||||
/datum/radio_frequency/New(freq)
|
||||
frequency = freq
|
||||
|
||||
//If range > 0, only post to devices on the same z_level and within range
|
||||
//Use range = -1, to restrain to the same z_level without limiting range
|
||||
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null)
|
||||
// Ensure the signal's data is fully filled
|
||||
signal.source = source
|
||||
signal.frequency = frequency
|
||||
|
||||
//Apply filter to the signal. If none supply, broadcast to every devices
|
||||
//_default channel is always checked
|
||||
var/list/filter_list
|
||||
|
||||
if(filter)
|
||||
filter_list = list(filter,"_default")
|
||||
else
|
||||
filter_list = devices
|
||||
|
||||
//If checking range, find the source turf
|
||||
var/turf/start_point
|
||||
if(range)
|
||||
start_point = get_turf(source)
|
||||
if(!start_point)
|
||||
return 0
|
||||
|
||||
//Send the data
|
||||
for(var/current_filter in filter_list)
|
||||
for(var/obj/device in devices[current_filter])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range))
|
||||
continue
|
||||
device.receive_signal(signal)
|
||||
|
||||
/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null)
|
||||
if (!filter)
|
||||
filter = "_default"
|
||||
|
||||
var/list/devices_line = devices[filter]
|
||||
if(!devices_line)
|
||||
devices[filter] = devices_line = list()
|
||||
devices_line += device
|
||||
|
||||
|
||||
/datum/radio_frequency/proc/remove_listener(obj/device)
|
||||
for(var/devices_filter in devices)
|
||||
var/list/devices_line = devices[devices_filter]
|
||||
if(!devices_line)
|
||||
devices -= devices_filter
|
||||
devices_line -= device
|
||||
if(!devices_line.len)
|
||||
devices -= devices_filter
|
||||
|
||||
|
||||
/obj/proc/receive_signal(datum/signal/signal)
|
||||
return
|
||||
|
||||
/datum/signal
|
||||
var/obj/source
|
||||
var/frequency = 0
|
||||
var/transmission_method
|
||||
var/list/data
|
||||
|
||||
/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO)
|
||||
src.data = data || list()
|
||||
src.transmission_method = transmission_method
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \
|
||||
/datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee)
|
||||
// The antags you're allowed to be if turning Vassal.
|
||||
/proc/isvamp(mob/living/M)
|
||||
return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/bloodsucker)
|
||||
|
||||
/datum/game_mode/bloodsucker
|
||||
name = "bloodsucker"
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/brothers = list()
|
||||
var/list/datum/team/brother_team/brother_teams = list()
|
||||
|
||||
/datum/game_mode/traitor/bros
|
||||
name = "traitor+brothers"
|
||||
config_tag = "traitorbro"
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='danger'>Blood Brothers</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors or brothers succeed!"
|
||||
|
||||
var/list/datum/team/brother_team/pre_brother_teams = list()
|
||||
var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off
|
||||
var/const/min_team_size = 2
|
||||
traitors_required = FALSE //Only teams are possible
|
||||
|
||||
/datum/game_mode/traitor/bros/pre_setup()
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER)
|
||||
|
||||
var/num_teams = team_amount
|
||||
var/bsc = CONFIG_GET(number/brother_scaling_coeff)
|
||||
if(bsc)
|
||||
num_teams = max(1, round(num_players() / bsc))
|
||||
|
||||
for(var/j = 1 to num_teams)
|
||||
if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies)
|
||||
break
|
||||
var/datum/team/brother_team/team = new
|
||||
var/team_size = prob(10) ? min(3, possible_brothers.len) : 2
|
||||
for(var/k = 1 to team_size)
|
||||
var/datum/mind/bro = antag_pick(possible_brothers)
|
||||
possible_brothers -= bro
|
||||
antag_candidates -= bro
|
||||
team.add_member(bro)
|
||||
bro.special_role = "brother"
|
||||
bro.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(bro)] has been selected as a Brother")
|
||||
pre_brother_teams += team
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/post_setup()
|
||||
for(var/datum/team/brother_team/team in pre_brother_teams)
|
||||
team.pick_meeting_area()
|
||||
team.forge_brother_objectives()
|
||||
for(var/datum/mind/M in team.members)
|
||||
M.add_antag_datum(/datum/antagonist/brother, team)
|
||||
team.update_name()
|
||||
brother_teams += pre_brother_teams
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/generate_report()
|
||||
return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust."
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.join_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, "brother")
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_removed(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.leave_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, null)
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/brothers = list()
|
||||
var/list/datum/team/brother_team/brother_teams = list()
|
||||
|
||||
/datum/game_mode/traitor/bros
|
||||
name = "traitor+brothers"
|
||||
config_tag = "traitorbro"
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='danger'>Blood Brothers</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors or brothers succeed!"
|
||||
|
||||
var/list/datum/team/brother_team/pre_brother_teams = list()
|
||||
var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off
|
||||
var/const/min_team_size = 2
|
||||
traitors_required = FALSE //Only teams are possible
|
||||
|
||||
/datum/game_mode/traitor/bros/pre_setup()
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER)
|
||||
|
||||
var/num_teams = team_amount
|
||||
var/bsc = CONFIG_GET(number/brother_scaling_coeff)
|
||||
if(bsc)
|
||||
num_teams = max(1, round(num_players() / bsc))
|
||||
|
||||
for(var/j = 1 to num_teams)
|
||||
if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies)
|
||||
break
|
||||
var/datum/team/brother_team/team = new
|
||||
var/team_size = prob(10) ? min(3, possible_brothers.len) : 2
|
||||
for(var/k = 1 to team_size)
|
||||
var/datum/mind/bro = antag_pick(possible_brothers)
|
||||
possible_brothers -= bro
|
||||
antag_candidates -= bro
|
||||
team.add_member(bro)
|
||||
bro.special_role = "brother"
|
||||
bro.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(bro)] has been selected as a Brother")
|
||||
pre_brother_teams += team
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/post_setup()
|
||||
for(var/datum/team/brother_team/team in pre_brother_teams)
|
||||
team.pick_meeting_area()
|
||||
team.forge_brother_objectives()
|
||||
for(var/datum/mind/M in team.members)
|
||||
M.add_antag_datum(/datum/antagonist/brother, team)
|
||||
team.update_name()
|
||||
brother_teams += pre_brother_teams
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/generate_report()
|
||||
return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust."
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.join_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, "brother")
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_removed(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.leave_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, null)
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"))
|
||||
GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store"))
|
||||
GLOBAL_LIST_INIT(slot2slot, list("head" = SLOT_HEAD, "wear_mask" = SLOT_WEAR_MASK, "neck" = SLOT_NECK, "back" = SLOT_BACK, "wear_suit" = SLOT_WEAR_SUIT, "w_uniform" = SLOT_W_UNIFORM, "shoes" = SLOT_SHOES, "belt" = SLOT_BELT, "gloves" = SLOT_GLOVES, "glasses" = SLOT_GLASSES, "ears" = SLOT_EARS, "wear_id" = SLOT_WEAR_ID, "s_store" = SLOT_S_STORE))
|
||||
GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling))
|
||||
GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings
|
||||
|
||||
|
||||
/datum/game_mode/changeling
|
||||
name = "changeling"
|
||||
config_tag = "changeling"
|
||||
antag_flag = ROLE_CHANGELING
|
||||
false_report_weight = 10
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist
|
||||
required_players = 15
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = 1
|
||||
|
||||
announce_span = "green"
|
||||
announce_text = "Alien changelings have infiltrated the crew!\n\
|
||||
<span class='green'>Changelings</span>: Accomplish the objectives assigned to you.\n\
|
||||
<span class='notice'>Crew</span>: Root out and eliminate the changeling menace."
|
||||
|
||||
var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off
|
||||
var/list/changelings = list()
|
||||
|
||||
/datum/game_mode/changeling/pre_setup()
|
||||
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 2)) + 2, round(num_players() / csc)))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount))
|
||||
|
||||
if(antag_candidates.len>0)
|
||||
for(var/i = 0, i < num_changelings, i++)
|
||||
if(!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/changeling = antag_pick(antag_candidates)
|
||||
antag_candidates -= changeling
|
||||
changelings += changeling
|
||||
changeling.special_role = ROLE_CHANGELING
|
||||
changeling.restricted_roles = restricted_jobs
|
||||
return 1
|
||||
else
|
||||
setup_error = "Not enough changeling candidates"
|
||||
return 0
|
||||
|
||||
/datum/game_mode/changeling/post_setup()
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
log_game("[key_name(changeling)] has been selected as a changeling")
|
||||
var/datum/antagonist/changeling/new_antag = new()
|
||||
new_antag.team_mode = TRUE
|
||||
changeling.add_antag_datum(new_antag)
|
||||
..()
|
||||
|
||||
/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc))
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
return
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changeling()
|
||||
changelings += character.mind
|
||||
|
||||
/datum/game_mode/changeling/generate_report()
|
||||
return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \
|
||||
codenamed \"Thing\", and it was highly adaptive and extremely dangerous. We have reason to believe that the Thing has allied with the Syndicate, and you should note that likelihood \
|
||||
of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \
|
||||
as paranoia may spread and inhibit workplace efficiency."
|
||||
|
||||
/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof)
|
||||
var/datum/dna/chosen_dna = chosen_prof.dna
|
||||
user.real_name = chosen_prof.name
|
||||
user.underwear = chosen_prof.underwear
|
||||
user.undie_color = chosen_prof.undie_color
|
||||
user.undershirt = chosen_prof.undershirt
|
||||
user.shirt_color =chosen_prof.shirt_color
|
||||
user.socks = chosen_prof.socks
|
||||
user.socks_color =chosen_prof.socks_color
|
||||
|
||||
chosen_dna.transfer_identity(user, 1)
|
||||
user.updateappearance(mutcolor_update=1)
|
||||
user.update_body()
|
||||
user.domutcheck()
|
||||
|
||||
//vars hackery. not pretty, but better than the alternative.
|
||||
for(var/slot in GLOB.slots)
|
||||
if(istype(user.vars[slot], GLOB.slot2type[slot]) && !(chosen_prof.exists_list[slot])) //remove unnecessary flesh items
|
||||
qdel(user.vars[slot])
|
||||
continue
|
||||
|
||||
if((user.vars[slot] && !istype(user.vars[slot], GLOB.slot2type[slot])) || !(chosen_prof.exists_list[slot]))
|
||||
continue
|
||||
|
||||
var/obj/item/C
|
||||
var/equip = 0
|
||||
if(!user.vars[slot])
|
||||
var/thetype = GLOB.slot2type[slot]
|
||||
equip = 1
|
||||
C = new thetype(user)
|
||||
|
||||
else if(istype(user.vars[slot], GLOB.slot2type[slot]))
|
||||
C = user.vars[slot]
|
||||
|
||||
C.appearance = chosen_prof.appearance_list[slot]
|
||||
C.name = chosen_prof.name_list[slot]
|
||||
C.flags_cover = chosen_prof.flags_cover_list[slot]
|
||||
C.item_color = chosen_prof.item_color_list[slot]
|
||||
C.item_state = chosen_prof.item_state_list[slot]
|
||||
if(equip)
|
||||
user.equip_to_slot_or_del(C, GLOB.slot2slot[slot])
|
||||
|
||||
user.regenerate_icons()
|
||||
GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"))
|
||||
GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store"))
|
||||
GLOBAL_LIST_INIT(slot2slot, list("head" = SLOT_HEAD, "wear_mask" = SLOT_WEAR_MASK, "neck" = SLOT_NECK, "back" = SLOT_BACK, "wear_suit" = SLOT_WEAR_SUIT, "w_uniform" = SLOT_W_UNIFORM, "shoes" = SLOT_SHOES, "belt" = SLOT_BELT, "gloves" = SLOT_GLOVES, "glasses" = SLOT_GLASSES, "ears" = SLOT_EARS, "wear_id" = SLOT_WEAR_ID, "s_store" = SLOT_S_STORE))
|
||||
GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling))
|
||||
GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings
|
||||
|
||||
|
||||
/datum/game_mode/changeling
|
||||
name = "changeling"
|
||||
config_tag = "changeling"
|
||||
antag_flag = ROLE_CHANGELING
|
||||
false_report_weight = 10
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist
|
||||
required_players = 15
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = 1
|
||||
|
||||
announce_span = "green"
|
||||
announce_text = "Alien changelings have infiltrated the crew!\n\
|
||||
<span class='green'>Changelings</span>: Accomplish the objectives assigned to you.\n\
|
||||
<span class='notice'>Crew</span>: Root out and eliminate the changeling menace."
|
||||
|
||||
var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off
|
||||
var/list/changelings = list()
|
||||
|
||||
/datum/game_mode/changeling/pre_setup()
|
||||
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 2)) + 2, round(num_players() / csc)))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount))
|
||||
|
||||
if(antag_candidates.len>0)
|
||||
for(var/i = 0, i < num_changelings, i++)
|
||||
if(!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/changeling = antag_pick(antag_candidates)
|
||||
antag_candidates -= changeling
|
||||
changelings += changeling
|
||||
changeling.special_role = ROLE_CHANGELING
|
||||
changeling.restricted_roles = restricted_jobs
|
||||
return 1
|
||||
else
|
||||
setup_error = "Not enough changeling candidates"
|
||||
return 0
|
||||
|
||||
/datum/game_mode/changeling/post_setup()
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
log_game("[key_name(changeling)] has been selected as a changeling")
|
||||
var/datum/antagonist/changeling/new_antag = new()
|
||||
new_antag.team_mode = TRUE
|
||||
changeling.add_antag_datum(new_antag)
|
||||
..()
|
||||
|
||||
/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc))
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
return
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changeling()
|
||||
changelings += character.mind
|
||||
|
||||
/datum/game_mode/changeling/generate_report()
|
||||
return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \
|
||||
codenamed \"Thing\", and it was highly adaptive and extremely dangerous. We have reason to believe that the Thing has allied with the Syndicate, and you should note that likelihood \
|
||||
of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \
|
||||
as paranoia may spread and inhibit workplace efficiency."
|
||||
|
||||
/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof)
|
||||
var/datum/dna/chosen_dna = chosen_prof.dna
|
||||
user.real_name = chosen_prof.name
|
||||
user.underwear = chosen_prof.underwear
|
||||
user.undie_color = chosen_prof.undie_color
|
||||
user.undershirt = chosen_prof.undershirt
|
||||
user.shirt_color =chosen_prof.shirt_color
|
||||
user.socks = chosen_prof.socks
|
||||
user.socks_color =chosen_prof.socks_color
|
||||
|
||||
chosen_dna.transfer_identity(user, 1)
|
||||
user.updateappearance(mutcolor_update=1)
|
||||
user.update_body()
|
||||
user.domutcheck()
|
||||
|
||||
//vars hackery. not pretty, but better than the alternative.
|
||||
for(var/slot in GLOB.slots)
|
||||
if(istype(user.vars[slot], GLOB.slot2type[slot]) && !(chosen_prof.exists_list[slot])) //remove unnecessary flesh items
|
||||
qdel(user.vars[slot])
|
||||
continue
|
||||
|
||||
if((user.vars[slot] && !istype(user.vars[slot], GLOB.slot2type[slot])) || !(chosen_prof.exists_list[slot]))
|
||||
continue
|
||||
|
||||
var/obj/item/C
|
||||
var/equip = 0
|
||||
if(!user.vars[slot])
|
||||
var/thetype = GLOB.slot2type[slot]
|
||||
equip = 1
|
||||
C = new thetype(user)
|
||||
|
||||
else if(istype(user.vars[slot], GLOB.slot2type[slot]))
|
||||
C = user.vars[slot]
|
||||
|
||||
C.appearance = chosen_prof.appearance_list[slot]
|
||||
C.name = chosen_prof.name_list[slot]
|
||||
C.flags_cover = chosen_prof.flags_cover_list[slot]
|
||||
C.item_color = chosen_prof.item_color_list[slot]
|
||||
C.item_state = chosen_prof.item_state_list[slot]
|
||||
if(equip)
|
||||
user.equip_to_slot_or_del(C, GLOB.slot2slot[slot])
|
||||
|
||||
user.regenerate_icons()
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
/datum/game_mode/traitor/changeling
|
||||
name = "traitor+changeling"
|
||||
config_tag = "traitorchan"
|
||||
false_report_weight = 10
|
||||
traitors_possible = 3 //hard limit on traitors if scaling is turned off
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
required_players = 25
|
||||
required_enemies = 1 // how many of each type are required
|
||||
recommended_enemies = 3
|
||||
reroll_friendly = 1
|
||||
|
||||
var/list/possible_changelings = list()
|
||||
var/list/changelings = list()
|
||||
var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off
|
||||
|
||||
/datum/game_mode/traitor/changeling/announce()
|
||||
to_chat(world, "<B>The current game mode is - Traitor+Changeling!</B>")
|
||||
to_chat(world, "<B>There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!</B>")
|
||||
|
||||
/datum/game_mode/traitor/changeling/can_start()
|
||||
if(!..())
|
||||
return 0
|
||||
possible_changelings = get_players_for_role(ROLE_CHANGELING)
|
||||
if(possible_changelings.len < required_enemies)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/game_mode/traitor/changeling/pre_setup()
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING)
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 4)) + 2, round(num_players() / (csc * 2))))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount/2))
|
||||
|
||||
if(possible_changelings.len>0)
|
||||
for(var/j = 0, j < num_changelings, j++)
|
||||
if(!possible_changelings.len)
|
||||
break
|
||||
var/datum/mind/changeling = antag_pick(possible_changelings)
|
||||
antag_candidates -= changeling
|
||||
possible_changelings -= changeling
|
||||
changeling.special_role = ROLE_CHANGELING
|
||||
changelings += changeling
|
||||
changeling.restricted_roles = restricted_jobs
|
||||
return ..()
|
||||
else
|
||||
return 0
|
||||
|
||||
/datum/game_mode/traitor/changeling/post_setup()
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
changeling.add_antag_datum(/datum/antagonist/changeling)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2)))
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
..()
|
||||
return
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changeling()
|
||||
changelings += character.mind
|
||||
if(QDELETED(character))
|
||||
return
|
||||
..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/generate_report()
|
||||
return "The Syndicate has started some experimental research regarding humanoid shapeshifting. There are rumors that this technology will be field tested on a Nanotrasen station \
|
||||
for infiltration purposes. Be advised that support personel may also be deployed to defend these shapeshifters. Trust nobody - suspect everybody. Do not announce this to the crew, \
|
||||
as paranoia may spread and inhibit workplace efficiency."
|
||||
/datum/game_mode/traitor/changeling
|
||||
name = "traitor+changeling"
|
||||
config_tag = "traitorchan"
|
||||
false_report_weight = 10
|
||||
traitors_possible = 3 //hard limit on traitors if scaling is turned off
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
required_players = 25
|
||||
required_enemies = 1 // how many of each type are required
|
||||
recommended_enemies = 3
|
||||
reroll_friendly = 1
|
||||
|
||||
var/list/possible_changelings = list()
|
||||
var/list/changelings = list()
|
||||
var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off
|
||||
|
||||
/datum/game_mode/traitor/changeling/announce()
|
||||
to_chat(world, "<B>The current game mode is - Traitor+Changeling!</B>")
|
||||
to_chat(world, "<B>There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!</B>")
|
||||
|
||||
/datum/game_mode/traitor/changeling/can_start()
|
||||
if(!..())
|
||||
return 0
|
||||
possible_changelings = get_players_for_role(ROLE_CHANGELING)
|
||||
if(possible_changelings.len < required_enemies)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/game_mode/traitor/changeling/pre_setup()
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING)
|
||||
|
||||
var/num_changelings = 1
|
||||
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
if(csc)
|
||||
num_changelings = max(1, min(round(num_players() / (csc * 4)) + 2, round(num_players() / (csc * 2))))
|
||||
else
|
||||
num_changelings = max(1, min(num_players(), changeling_amount/2))
|
||||
|
||||
if(possible_changelings.len>0)
|
||||
for(var/j = 0, j < num_changelings, j++)
|
||||
if(!possible_changelings.len)
|
||||
break
|
||||
var/datum/mind/changeling = antag_pick(possible_changelings)
|
||||
antag_candidates -= changeling
|
||||
possible_changelings -= changeling
|
||||
changeling.special_role = ROLE_CHANGELING
|
||||
changelings += changeling
|
||||
changeling.restricted_roles = restricted_jobs
|
||||
return ..()
|
||||
else
|
||||
return 0
|
||||
|
||||
/datum/game_mode/traitor/changeling/post_setup()
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
changeling.add_antag_datum(/datum/antagonist/changeling)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2)))
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
..()
|
||||
return
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changeling()
|
||||
changelings += character.mind
|
||||
if(QDELETED(character))
|
||||
return
|
||||
..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/generate_report()
|
||||
return "The Syndicate has started some experimental research regarding humanoid shapeshifting. There are rumors that this technology will be field tested on a Nanotrasen station \
|
||||
for infiltration purposes. Be advised that support personel may also be deployed to defend these shapeshifters. Trust nobody - suspect everybody. Do not announce this to the crew, \
|
||||
as paranoia may spread and inhibit workplace efficiency."
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
spray_range = 1
|
||||
stream_range = 1
|
||||
volume = 30
|
||||
list_reagents = list("lube" = 30)
|
||||
list_reagents = list(/datum/reagent/lube = 30)
|
||||
|
||||
//COMBAT CLOWN SHOES
|
||||
//Clown shoes with combat stats and noslip. Of course they still squeak.
|
||||
@@ -165,7 +165,7 @@
|
||||
customfoodfilling = FALSE
|
||||
seed = null
|
||||
tastes = list("explosives" = 10)
|
||||
list_reagents = list("vitamin" = 1)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 1)
|
||||
|
||||
/obj/item/grown/bananapeel/bombanana
|
||||
desc = "A peel from a banana. Why is it beeping?"
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
/proc/power_failure()
|
||||
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z))
|
||||
continue
|
||||
S.charge = 0
|
||||
S.output_level = 0
|
||||
S.output_attempt = 0
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
|
||||
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
|
||||
|
||||
for(var/area/A in world)
|
||||
if( !A.requires_power || A.always_unpowered )
|
||||
continue
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(A.contents)
|
||||
for(var/atom/AT in A.contents)
|
||||
if(!is_station_level(AT.z)) //Only check one, it's enough.
|
||||
skip = 1
|
||||
break
|
||||
if(skip)
|
||||
continue
|
||||
A.power_light = FALSE
|
||||
A.power_equip = FALSE
|
||||
A.power_environ = FALSE
|
||||
A.power_change()
|
||||
|
||||
for(var/obj/machinery/power/apc/C in GLOB.apcs_list)
|
||||
if(C.cell && is_station_level(C.z))
|
||||
var/area/A = C.area
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(skip)
|
||||
continue
|
||||
|
||||
C.cell.charge = 0
|
||||
|
||||
/proc/power_restore()
|
||||
|
||||
priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
|
||||
for(var/obj/machinery/power/apc/C in GLOB.machines)
|
||||
if(C.cell && is_station_level(C.z))
|
||||
C.cell.charge = C.cell.maxcharge
|
||||
C.failure_timer = 0
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(!is_station_level(S.z))
|
||||
continue
|
||||
S.charge = S.capacity
|
||||
S.output_level = S.output_level_max
|
||||
S.output_attempt = 1
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
for(var/area/A in world)
|
||||
if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival))
|
||||
A.power_light = TRUE
|
||||
A.power_equip = TRUE
|
||||
A.power_environ = TRUE
|
||||
A.power_change()
|
||||
|
||||
/proc/power_restore_quick()
|
||||
|
||||
priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(!is_station_level(S.z))
|
||||
continue
|
||||
S.charge = S.capacity
|
||||
S.output_level = S.output_level_max
|
||||
S.output_attempt = 1
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
|
||||
/proc/power_failure()
|
||||
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z))
|
||||
continue
|
||||
S.charge = 0
|
||||
S.output_level = 0
|
||||
S.output_attempt = 0
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
|
||||
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
|
||||
|
||||
for(var/area/A in world)
|
||||
if( !A.requires_power || A.always_unpowered )
|
||||
continue
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(A.contents)
|
||||
for(var/atom/AT in A.contents)
|
||||
if(!is_station_level(AT.z)) //Only check one, it's enough.
|
||||
skip = 1
|
||||
break
|
||||
if(skip)
|
||||
continue
|
||||
A.power_light = FALSE
|
||||
A.power_equip = FALSE
|
||||
A.power_environ = FALSE
|
||||
A.power_change()
|
||||
|
||||
for(var/obj/machinery/power/apc/C in GLOB.apcs_list)
|
||||
if(C.cell && is_station_level(C.z))
|
||||
var/area/A = C.area
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(skip)
|
||||
continue
|
||||
|
||||
C.cell.charge = 0
|
||||
|
||||
/proc/power_restore()
|
||||
|
||||
priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
|
||||
for(var/obj/machinery/power/apc/C in GLOB.machines)
|
||||
if(C.cell && is_station_level(C.z))
|
||||
C.cell.charge = C.cell.maxcharge
|
||||
C.failure_timer = 0
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(!is_station_level(S.z))
|
||||
continue
|
||||
S.charge = S.capacity
|
||||
S.output_level = S.output_level_max
|
||||
S.output_attempt = 1
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
for(var/area/A in world)
|
||||
if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival))
|
||||
A.power_light = TRUE
|
||||
A.power_equip = TRUE
|
||||
A.power_environ = TRUE
|
||||
A.power_change()
|
||||
|
||||
/proc/power_restore_quick()
|
||||
|
||||
priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
|
||||
for(var/obj/machinery/power/smes/S in GLOB.machines)
|
||||
if(!is_station_level(S.z))
|
||||
continue
|
||||
S.charge = S.capacity
|
||||
S.output_level = S.output_level_max
|
||||
S.output_attempt = 1
|
||||
S.update_icon()
|
||||
S.power_change()
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/datum/game_mode/extended
|
||||
name = "secret extended"
|
||||
config_tag = "secret_extended"
|
||||
false_report_weight = 5
|
||||
required_players = 0
|
||||
|
||||
announce_span = "notice"
|
||||
announce_text = "Just have fun and enjoy the game!"
|
||||
|
||||
/datum/game_mode/extended/pre_setup()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/extended/generate_report()
|
||||
return "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift."
|
||||
|
||||
/datum/game_mode/extended/announced
|
||||
name = "extended"
|
||||
config_tag = "extended"
|
||||
false_report_weight = 0
|
||||
|
||||
/datum/game_mode/extended/announced/generate_station_goals()
|
||||
if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart
|
||||
return ..()
|
||||
for(var/T in subtypesof(/datum/station_goal))
|
||||
var/datum/station_goal/G = new T
|
||||
station_goals += G
|
||||
G.on_report()
|
||||
|
||||
/datum/game_mode/extended/announced/send_intercept(report = 0)
|
||||
if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart
|
||||
return ..()
|
||||
priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport")
|
||||
/datum/game_mode/extended
|
||||
name = "secret extended"
|
||||
config_tag = "secret_extended"
|
||||
false_report_weight = 5
|
||||
required_players = 0
|
||||
|
||||
announce_span = "notice"
|
||||
announce_text = "Just have fun and enjoy the game!"
|
||||
|
||||
/datum/game_mode/extended/pre_setup()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/extended/generate_report()
|
||||
return "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift."
|
||||
|
||||
/datum/game_mode/extended/announced
|
||||
name = "extended"
|
||||
config_tag = "extended"
|
||||
false_report_weight = 0
|
||||
|
||||
/datum/game_mode/extended/announced/generate_station_goals()
|
||||
if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart
|
||||
return ..()
|
||||
for(var/T in subtypesof(/datum/station_goal))
|
||||
var/datum/station_goal/G = new T
|
||||
station_goals += G
|
||||
G.on_report()
|
||||
|
||||
/datum/game_mode/extended/announced/send_intercept(report = 0)
|
||||
if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart
|
||||
return ..()
|
||||
priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport")
|
||||
|
||||
+606
-606
File diff suppressed because it is too large
Load Diff
@@ -1,59 +1,59 @@
|
||||
/datum/game_mode/meteor
|
||||
name = "meteor"
|
||||
config_tag = "meteor"
|
||||
false_report_weight = 1
|
||||
var/meteordelay = 2000
|
||||
var/nometeors = 0
|
||||
var/rampupdelta = 5
|
||||
required_players = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "A major meteor shower is bombarding the station! The crew needs to evacuate or survive the onslaught."
|
||||
|
||||
|
||||
/datum/game_mode/meteor/process()
|
||||
if(nometeors || meteordelay > world.time - SSticker.round_start_time)
|
||||
return
|
||||
|
||||
var/list/wavetype = GLOB.meteors_normal
|
||||
var/meteorminutes = (world.time - SSticker.round_start_time - meteordelay) / 10 / 60
|
||||
|
||||
|
||||
if (prob(meteorminutes))
|
||||
wavetype = GLOB.meteors_threatening
|
||||
|
||||
if (prob(meteorminutes/2))
|
||||
wavetype = GLOB.meteors_catastrophic
|
||||
|
||||
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
|
||||
|
||||
spawn_meteors(ramp_up_final, wavetype)
|
||||
|
||||
|
||||
/datum/game_mode/meteor/special_report()
|
||||
var/survivors = 0
|
||||
var/list/survivor_list = list()
|
||||
|
||||
for(var/mob/living/player in GLOB.player_list)
|
||||
if(player.stat != DEAD)
|
||||
++survivors
|
||||
|
||||
if(player.onCentCom())
|
||||
survivor_list += "<span class='greentext'>[player.real_name] escaped to the safety of CentCom.</span>"
|
||||
else if(player.onSyndieBase())
|
||||
survivor_list += "<span class='greentext'>[player.real_name] escaped to the (relative) safety of Syndicate Space.</span>"
|
||||
else
|
||||
survivor_list += "<span class='neutraltext'>[player.real_name] survived but is stranded without any hope of rescue.</span>"
|
||||
|
||||
if(survivors)
|
||||
return "<div class='panel greenborder'><span class='header'>The following survived the meteor storm:</span><br>[survivor_list.Join("<br>")]</div>"
|
||||
else
|
||||
return "<div class='panel redborder'><span class='redtext big'>Nobody survived the meteor storm!</span></div>"
|
||||
|
||||
/datum/game_mode/meteor/set_round_result()
|
||||
..()
|
||||
SSticker.mode_result = "end - evacuation"
|
||||
|
||||
/datum/game_mode/meteor/generate_report()
|
||||
return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \
|
||||
though unlikely. Be prepared for largescale impacts and destruction. Please note that the debris will prevent the escape shuttle from arriving quickly."
|
||||
/datum/game_mode/meteor
|
||||
name = "meteor"
|
||||
config_tag = "meteor"
|
||||
false_report_weight = 1
|
||||
var/meteordelay = 2000
|
||||
var/nometeors = 0
|
||||
var/rampupdelta = 5
|
||||
required_players = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "A major meteor shower is bombarding the station! The crew needs to evacuate or survive the onslaught."
|
||||
|
||||
|
||||
/datum/game_mode/meteor/process()
|
||||
if(nometeors || meteordelay > world.time - SSticker.round_start_time)
|
||||
return
|
||||
|
||||
var/list/wavetype = GLOB.meteors_normal
|
||||
var/meteorminutes = (world.time - SSticker.round_start_time - meteordelay) / 10 / 60
|
||||
|
||||
|
||||
if (prob(meteorminutes))
|
||||
wavetype = GLOB.meteors_threatening
|
||||
|
||||
if (prob(meteorminutes/2))
|
||||
wavetype = GLOB.meteors_catastrophic
|
||||
|
||||
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
|
||||
|
||||
spawn_meteors(ramp_up_final, wavetype)
|
||||
|
||||
|
||||
/datum/game_mode/meteor/special_report()
|
||||
var/survivors = 0
|
||||
var/list/survivor_list = list()
|
||||
|
||||
for(var/mob/living/player in GLOB.player_list)
|
||||
if(player.stat != DEAD)
|
||||
++survivors
|
||||
|
||||
if(player.onCentCom())
|
||||
survivor_list += "<span class='greentext'>[player.real_name] escaped to the safety of CentCom.</span>"
|
||||
else if(player.onSyndieBase())
|
||||
survivor_list += "<span class='greentext'>[player.real_name] escaped to the (relative) safety of Syndicate Space.</span>"
|
||||
else
|
||||
survivor_list += "<span class='neutraltext'>[player.real_name] survived but is stranded without any hope of rescue.</span>"
|
||||
|
||||
if(survivors)
|
||||
return "<div class='panel greenborder'><span class='header'>The following survived the meteor storm:</span><br>[survivor_list.Join("<br>")]</div>"
|
||||
else
|
||||
return "<div class='panel redborder'><span class='redtext big'>Nobody survived the meteor storm!</span></div>"
|
||||
|
||||
/datum/game_mode/meteor/set_round_result()
|
||||
..()
|
||||
SSticker.mode_result = "end - evacuation"
|
||||
|
||||
/datum/game_mode/meteor/generate_report()
|
||||
return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \
|
||||
though unlikely. Be prepared for largescale impacts and destruction. Please note that the debris will prevent the escape shuttle from arriving quickly."
|
||||
|
||||
@@ -1,265 +1,265 @@
|
||||
//Contains the target item datums for Steal objectives.
|
||||
|
||||
/datum/objective_item
|
||||
var/name = "A silly bike horn! Honk!"
|
||||
var/targetitem = /obj/item/bikehorn //typepath of the objective item
|
||||
var/difficulty = 9001 //vaguely how hard it is to do this objective
|
||||
var/list/excludefromjob = list() //If you don't want a job to get a certain objective (no captain stealing his own medal, etcetc)
|
||||
var/list/altitems = list() //Items which can serve as an alternative to the objective (darn you blueprints)
|
||||
var/list/special_equipment = list()
|
||||
|
||||
/datum/objective_item/proc/check_special_completion() //for objectives with special checks (is that slime extract unused? does that intellicard have an ai in it? etcetc)
|
||||
return 1
|
||||
|
||||
/datum/objective_item/proc/TargetExists()
|
||||
return TRUE
|
||||
|
||||
/datum/objective_item/steal/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/steal/Destroy()
|
||||
GLOB.possible_items -= src
|
||||
return ..()
|
||||
|
||||
/datum/objective_item/steal/caplaser
|
||||
name = "the captain's antique laser gun."
|
||||
targetitem = /obj/item/gun/energy/laser/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/hoslaser
|
||||
name = "the head of security's personal laser gun."
|
||||
targetitem = /obj/item/gun/energy/e_gun/hos
|
||||
difficulty = 10
|
||||
excludefromjob = list("Head Of Security")
|
||||
|
||||
/datum/objective_item/steal/handtele
|
||||
name = "a hand teleporter."
|
||||
targetitem = /obj/item/hand_tele
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain", "Research Director")
|
||||
|
||||
/datum/objective_item/steal/jetpack
|
||||
name = "the Captain's jetpack."
|
||||
targetitem = /obj/item/tank/jetpack/oxygen/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/magboots
|
||||
name = "the chief engineer's advanced magnetic boots."
|
||||
targetitem = /obj/item/clothing/shoes/magboots/advance
|
||||
difficulty = 5
|
||||
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
|
||||
/datum/objective_item/steal/capmedal
|
||||
name = "the medal of captaincy."
|
||||
targetitem = /obj/item/clothing/accessory/medal/gold/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/hypo
|
||||
name = "the Chief Medical Officer's MKII hypospray."
|
||||
targetitem = /obj/item/hypospray/mkii/CMO //CITADEL EDIT, changing theft objective for the Hypo MK II
|
||||
difficulty = 5
|
||||
excludefromjob = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Geneticist")
|
||||
|
||||
/datum/objective_item/steal/nukedisc
|
||||
name = "the nuclear authentication disk."
|
||||
targetitem = /obj/item/disk/nuclear
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N)
|
||||
return !N.fake
|
||||
|
||||
/datum/objective_item/steal/reflector
|
||||
name = "a reflector vest."
|
||||
targetitem = /obj/item/clothing/suit/armor/laserproof
|
||||
difficulty = 3
|
||||
excludefromjob = list("Head of Security", "Warden")
|
||||
|
||||
/datum/objective_item/steal/reactive
|
||||
name = "a reactive teleport armor."
|
||||
targetitem = /obj/item/clothing/suit/armor/reactive
|
||||
difficulty = 5
|
||||
excludefromjob = list("Research Director","Scientist", "Roboticist")
|
||||
|
||||
/datum/objective_item/steal/documents
|
||||
name = "any set of secret documents of any organization."
|
||||
targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/steal/nuke_core
|
||||
name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!"
|
||||
targetitem = /obj/item/nuke_core
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/steal/nuke_core/New()
|
||||
special_equipment += /obj/item/storage/box/syndie_kit/nuke
|
||||
..()
|
||||
|
||||
/datum/objective_item/steal/supermatter
|
||||
name = "a sliver of a supermatter crystal. Be sure to use the proper safety equipment when extracting the sliver!"
|
||||
targetitem = /obj/item/nuke_core/supermatter_sliver
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/steal/supermatter/New()
|
||||
special_equipment += /obj/item/storage/box/syndie_kit/supermatter
|
||||
..()
|
||||
|
||||
/datum/objective_item/steal/supermatter/TargetExists()
|
||||
return GLOB.main_supermatter_engine != null
|
||||
|
||||
//Items with special checks!
|
||||
/datum/objective_item/steal/plasma
|
||||
name = "28 moles of plasma (full tank)."
|
||||
targetitem = /obj/item/tank
|
||||
difficulty = 3
|
||||
excludefromjob = list("Chief Engineer","Research Director","Station Engineer","Scientist","Atmospheric Technician")
|
||||
|
||||
/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T)
|
||||
var/target_amount = text2num(name)
|
||||
var/found_amount = 0
|
||||
found_amount += T.air_contents.gases[/datum/gas/plasma]
|
||||
return found_amount>=target_amount
|
||||
|
||||
|
||||
/datum/objective_item/steal/functionalai
|
||||
name = "a functional AI."
|
||||
targetitem = /obj/item/aicard
|
||||
difficulty = 20 //beyond the impossible
|
||||
|
||||
/datum/objective_item/steal/functionalai/check_special_completion(obj/item/aicard/C)
|
||||
for(var/mob/living/silicon/ai/A in C)
|
||||
if(isAI(A) && A.stat != DEAD) //See if any AI's are alive inside that card.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective_item/steal/blueprints
|
||||
name = "the station blueprints."
|
||||
targetitem = /obj/item/areaeditor/blueprints
|
||||
difficulty = 10
|
||||
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
altitems = list(/obj/item/photo)
|
||||
|
||||
/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I)
|
||||
if(istype(I, /obj/item/areaeditor/blueprints))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/photo))
|
||||
var/obj/item/photo/P = I
|
||||
if(P.picture.has_blueprints) //if the blueprints are in frame
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_item/steal/slime
|
||||
name = "an unused sample of slime extract."
|
||||
targetitem = /obj/item/slime_extract
|
||||
difficulty = 3
|
||||
excludefromjob = list("Research Director","Scientist", "Roboticist")
|
||||
|
||||
/datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E)
|
||||
if(E.Uses > 0)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Unique Objectives
|
||||
/datum/objective_item/unique/docs_red
|
||||
name = "the \"Red\" secret documents."
|
||||
targetitem = /obj/item/documents/syndicate/red
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/unique/docs_blue
|
||||
name = "the \"Blue\" secret documents."
|
||||
targetitem = /obj/item/documents/syndicate/blue
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items_special += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/special/Destroy()
|
||||
GLOB.possible_items_special -= src
|
||||
return ..()
|
||||
|
||||
//Old ninja objectives.
|
||||
/datum/objective_item/special/pinpointer/nuke
|
||||
name = "the captain's pinpointer."
|
||||
targetitem = /obj/item/pinpointer
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/aegun
|
||||
name = "an advanced energy gun."
|
||||
targetitem = /obj/item/gun/energy/e_gun/nuclear
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/ddrill
|
||||
name = "a diamond drill."
|
||||
targetitem = /obj/item/pickaxe/drill/diamonddrill
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/boh
|
||||
name = "a bag of holding."
|
||||
targetitem = /obj/item/storage/backpack/holding
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/hypercell
|
||||
name = "a hyper-capacity power cell."
|
||||
targetitem = /obj/item/stock_parts/cell/hyper
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/special/laserpointer
|
||||
name = "a laser pointer."
|
||||
targetitem = /obj/item/laser_pointer
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/special/corgimeat
|
||||
name = "a piece of corgi meat."
|
||||
targetitem = /obj/item/reagent_containers/food/snacks/meat/slab/corgi
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/stack/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items_special += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/stack/Destroy()
|
||||
GLOB.possible_items_special -= src
|
||||
return ..()
|
||||
|
||||
//Stack objectives get their own subtype
|
||||
/datum/objective_item/stack
|
||||
name = "5 cardboard."
|
||||
targetitem = /obj/item/stack/sheet/cardboard
|
||||
difficulty = 9001
|
||||
|
||||
/datum/objective_item/stack/check_special_completion(obj/item/stack/S)
|
||||
var/target_amount = text2num(name)
|
||||
var/found_amount = 0
|
||||
|
||||
if(istype(S, targetitem))
|
||||
found_amount = S.amount
|
||||
return found_amount>=target_amount
|
||||
|
||||
/datum/objective_item/stack/diamond
|
||||
name = "10 diamonds."
|
||||
targetitem = /obj/item/stack/sheet/mineral/diamond
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/stack/gold
|
||||
name = "50 gold bars."
|
||||
targetitem = /obj/item/stack/sheet/mineral/gold
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/stack/uranium
|
||||
name = "25 refined uranium bars."
|
||||
targetitem = /obj/item/stack/sheet/mineral/uranium
|
||||
difficulty = 10
|
||||
//Contains the target item datums for Steal objectives.
|
||||
|
||||
/datum/objective_item
|
||||
var/name = "A silly bike horn! Honk!"
|
||||
var/targetitem = /obj/item/bikehorn //typepath of the objective item
|
||||
var/difficulty = 9001 //vaguely how hard it is to do this objective
|
||||
var/list/excludefromjob = list() //If you don't want a job to get a certain objective (no captain stealing his own medal, etcetc)
|
||||
var/list/altitems = list() //Items which can serve as an alternative to the objective (darn you blueprints)
|
||||
var/list/special_equipment = list()
|
||||
|
||||
/datum/objective_item/proc/check_special_completion() //for objectives with special checks (is that slime extract unused? does that intellicard have an ai in it? etcetc)
|
||||
return 1
|
||||
|
||||
/datum/objective_item/proc/TargetExists()
|
||||
return TRUE
|
||||
|
||||
/datum/objective_item/steal/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/steal/Destroy()
|
||||
GLOB.possible_items -= src
|
||||
return ..()
|
||||
|
||||
/datum/objective_item/steal/caplaser
|
||||
name = "the captain's antique laser gun."
|
||||
targetitem = /obj/item/gun/energy/laser/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/hoslaser
|
||||
name = "the head of security's personal laser gun."
|
||||
targetitem = /obj/item/gun/energy/e_gun/hos
|
||||
difficulty = 10
|
||||
excludefromjob = list("Head Of Security")
|
||||
|
||||
/datum/objective_item/steal/handtele
|
||||
name = "a hand teleporter."
|
||||
targetitem = /obj/item/hand_tele
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain", "Research Director")
|
||||
|
||||
/datum/objective_item/steal/jetpack
|
||||
name = "the Captain's jetpack."
|
||||
targetitem = /obj/item/tank/jetpack/oxygen/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/magboots
|
||||
name = "the chief engineer's advanced magnetic boots."
|
||||
targetitem = /obj/item/clothing/shoes/magboots/advance
|
||||
difficulty = 5
|
||||
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
|
||||
/datum/objective_item/steal/capmedal
|
||||
name = "the medal of captaincy."
|
||||
targetitem = /obj/item/clothing/accessory/medal/gold/captain
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/hypo
|
||||
name = "the Chief Medical Officer's MKII hypospray."
|
||||
targetitem = /obj/item/hypospray/mkii/CMO //CITADEL EDIT, changing theft objective for the Hypo MK II
|
||||
difficulty = 5
|
||||
excludefromjob = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Geneticist")
|
||||
|
||||
/datum/objective_item/steal/nukedisc
|
||||
name = "the nuclear authentication disk."
|
||||
targetitem = /obj/item/disk/nuclear
|
||||
difficulty = 5
|
||||
excludefromjob = list("Captain")
|
||||
|
||||
/datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N)
|
||||
return !N.fake
|
||||
|
||||
/datum/objective_item/steal/reflector
|
||||
name = "a reflector vest."
|
||||
targetitem = /obj/item/clothing/suit/armor/laserproof
|
||||
difficulty = 3
|
||||
excludefromjob = list("Head of Security", "Warden")
|
||||
|
||||
/datum/objective_item/steal/reactive
|
||||
name = "a reactive teleport armor."
|
||||
targetitem = /obj/item/clothing/suit/armor/reactive
|
||||
difficulty = 5
|
||||
excludefromjob = list("Research Director","Scientist", "Roboticist")
|
||||
|
||||
/datum/objective_item/steal/documents
|
||||
name = "any set of secret documents of any organization."
|
||||
targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/steal/nuke_core
|
||||
name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!"
|
||||
targetitem = /obj/item/nuke_core
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/steal/nuke_core/New()
|
||||
special_equipment += /obj/item/storage/box/syndie_kit/nuke
|
||||
..()
|
||||
|
||||
/datum/objective_item/steal/supermatter
|
||||
name = "a sliver of a supermatter crystal. Be sure to use the proper safety equipment when extracting the sliver!"
|
||||
targetitem = /obj/item/nuke_core/supermatter_sliver
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/steal/supermatter/New()
|
||||
special_equipment += /obj/item/storage/box/syndie_kit/supermatter
|
||||
..()
|
||||
|
||||
/datum/objective_item/steal/supermatter/TargetExists()
|
||||
return GLOB.main_supermatter_engine != null
|
||||
|
||||
//Items with special checks!
|
||||
/datum/objective_item/steal/plasma
|
||||
name = "28 moles of plasma (full tank)."
|
||||
targetitem = /obj/item/tank
|
||||
difficulty = 3
|
||||
excludefromjob = list("Chief Engineer","Research Director","Station Engineer","Scientist","Atmospheric Technician")
|
||||
|
||||
/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T)
|
||||
var/target_amount = text2num(name)
|
||||
var/found_amount = 0
|
||||
found_amount += T.air_contents.gases[/datum/gas/plasma]
|
||||
return found_amount>=target_amount
|
||||
|
||||
|
||||
/datum/objective_item/steal/functionalai
|
||||
name = "a functional AI."
|
||||
targetitem = /obj/item/aicard
|
||||
difficulty = 20 //beyond the impossible
|
||||
|
||||
/datum/objective_item/steal/functionalai/check_special_completion(obj/item/aicard/C)
|
||||
for(var/mob/living/silicon/ai/A in C)
|
||||
if(isAI(A) && A.stat != DEAD) //See if any AI's are alive inside that card.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective_item/steal/blueprints
|
||||
name = "the station blueprints."
|
||||
targetitem = /obj/item/areaeditor/blueprints
|
||||
difficulty = 10
|
||||
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
altitems = list(/obj/item/photo)
|
||||
|
||||
/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I)
|
||||
if(istype(I, /obj/item/areaeditor/blueprints))
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/photo))
|
||||
var/obj/item/photo/P = I
|
||||
if(P.picture.has_blueprints) //if the blueprints are in frame
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_item/steal/slime
|
||||
name = "an unused sample of slime extract."
|
||||
targetitem = /obj/item/slime_extract
|
||||
difficulty = 3
|
||||
excludefromjob = list("Research Director","Scientist", "Roboticist")
|
||||
|
||||
/datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E)
|
||||
if(E.Uses > 0)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Unique Objectives
|
||||
/datum/objective_item/unique/docs_red
|
||||
name = "the \"Red\" secret documents."
|
||||
targetitem = /obj/item/documents/syndicate/red
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/unique/docs_blue
|
||||
name = "the \"Blue\" secret documents."
|
||||
targetitem = /obj/item/documents/syndicate/blue
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items_special += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/special/Destroy()
|
||||
GLOB.possible_items_special -= src
|
||||
return ..()
|
||||
|
||||
//Old ninja objectives.
|
||||
/datum/objective_item/special/pinpointer/nuke
|
||||
name = "the captain's pinpointer."
|
||||
targetitem = /obj/item/pinpointer
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/aegun
|
||||
name = "an advanced energy gun."
|
||||
targetitem = /obj/item/gun/energy/e_gun/nuclear
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/ddrill
|
||||
name = "a diamond drill."
|
||||
targetitem = /obj/item/pickaxe/drill/diamonddrill
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/boh
|
||||
name = "a bag of holding."
|
||||
targetitem = /obj/item/storage/backpack/holding
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/hypercell
|
||||
name = "a hyper-capacity power cell."
|
||||
targetitem = /obj/item/stock_parts/cell/hyper
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/special/laserpointer
|
||||
name = "a laser pointer."
|
||||
targetitem = /obj/item/laser_pointer
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/special/corgimeat
|
||||
name = "a piece of corgi meat."
|
||||
targetitem = /obj/item/reagent_containers/food/snacks/meat/slab/corgi
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/stack/New()
|
||||
..()
|
||||
if(TargetExists())
|
||||
GLOB.possible_items_special += src
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/objective_item/stack/Destroy()
|
||||
GLOB.possible_items_special -= src
|
||||
return ..()
|
||||
|
||||
//Stack objectives get their own subtype
|
||||
/datum/objective_item/stack
|
||||
name = "5 cardboard."
|
||||
targetitem = /obj/item/stack/sheet/cardboard
|
||||
difficulty = 9001
|
||||
|
||||
/datum/objective_item/stack/check_special_completion(obj/item/stack/S)
|
||||
var/target_amount = text2num(name)
|
||||
var/found_amount = 0
|
||||
|
||||
if(istype(S, targetitem))
|
||||
found_amount = S.amount
|
||||
return found_amount>=target_amount
|
||||
|
||||
/datum/objective_item/stack/diamond
|
||||
name = "10 diamonds."
|
||||
targetitem = /obj/item/stack/sheet/mineral/diamond
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/stack/gold
|
||||
name = "50 gold bars."
|
||||
targetitem = /obj/item/stack/sheet/mineral/gold
|
||||
difficulty = 15
|
||||
|
||||
/datum/objective_item/stack/uranium
|
||||
name = "25 refined uranium bars."
|
||||
targetitem = /obj/item/stack/sheet/mineral/uranium
|
||||
difficulty = 10
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
/*
|
||||
This is for the sandbox for now,
|
||||
maybe useful later for an actual thing?
|
||||
-Sayu
|
||||
*/
|
||||
|
||||
/obj/structure/door_assembly
|
||||
var/datum/airlock_maker/maker = null
|
||||
|
||||
/obj/structure/door_assembly/attack_hand()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(maker)
|
||||
maker.interact()
|
||||
|
||||
/datum/airlock_maker
|
||||
var/obj/structure/door_assembly/linked = null
|
||||
|
||||
var/list/access_used = null
|
||||
var/require_all = 1
|
||||
|
||||
var/paintjob = "none"
|
||||
var/glassdoor = 0
|
||||
|
||||
var/doorname = "airlock"
|
||||
|
||||
/datum/airlock_maker/New(var/atom/target_loc)
|
||||
linked = new(target_loc)
|
||||
linked.maker = src
|
||||
linked.anchored = FALSE
|
||||
access_used = list()
|
||||
|
||||
interact()
|
||||
|
||||
/datum/airlock_maker/proc/linkpretty(href,desc,active)
|
||||
if(!desc)
|
||||
var/static/list/defaults = list("No","Yes")
|
||||
desc = defaults[active+1]
|
||||
if(active)
|
||||
return "<a href='?src=[REF(src)];[href]'><b>[desc]</b></a>"
|
||||
return "<a href='?src=[REF(src)];[href]'><i>[desc]</i></a>"
|
||||
|
||||
/datum/airlock_maker/proc/interact()
|
||||
var/list/leftcolumn = list()
|
||||
var/list/rightcolumn = list()
|
||||
leftcolumn += "<u><b>Required Access</b></u>"
|
||||
for(var/access in get_all_accesses())
|
||||
leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used)
|
||||
leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]"
|
||||
|
||||
rightcolumn += "<u><b>Paintjob</b></u>"
|
||||
for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity"))
|
||||
rightcolumn += linkpretty("paint=[option]",option,option == paintjob)
|
||||
rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "<br><br>"
|
||||
var/length = max(leftcolumn.len,rightcolumn.len)
|
||||
|
||||
var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.<hr><br>"
|
||||
dat += "<a href='?src=[REF(src)];rename'>Door name</a>: \"[doorname]\""
|
||||
dat += "<table>"
|
||||
for(var/i=1; i<=length; i++)
|
||||
dat += "<tr><td>"
|
||||
if(i<=leftcolumn.len)
|
||||
dat += leftcolumn[i]
|
||||
dat += "</td><td>"
|
||||
if(i<=rightcolumn.len)
|
||||
dat += rightcolumn[i]
|
||||
dat += "</td></tr>"
|
||||
|
||||
dat += "</table><hr><a href='?src=[REF(src)];done'>Finalize Airlock Construction</a> | <a href='?src=[REF(src)];cancel'>Cancel and Destroy Airlock</a>"
|
||||
usr << browse(dat,"window=airlockmaker")
|
||||
|
||||
/datum/airlock_maker/Topic(var/href,var/list/href_list)
|
||||
if(!usr)
|
||||
return
|
||||
if(!src || !linked || !linked.loc)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
if("rename" in href_list)
|
||||
var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname)
|
||||
if(newname)
|
||||
doorname = newname
|
||||
if("access" in href_list)
|
||||
var/value = text2num(href_list["access"])
|
||||
access_used ^= value
|
||||
if("reqall" in href_list)
|
||||
require_all = !require_all
|
||||
if("paint" in href_list)
|
||||
paintjob = href_list["paint"]
|
||||
if("glass" in href_list)
|
||||
glassdoor = !glassdoor
|
||||
|
||||
if("cancel" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
qdel(linked)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if("done" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
var/turf/t_loc = linked.loc
|
||||
qdel(linked)
|
||||
if(!istype(t_loc))
|
||||
return
|
||||
|
||||
var/target_type = "/obj/machinery/door/airlock"
|
||||
if(glassdoor)
|
||||
if(paintjob != "none")
|
||||
if(paintjob in list("external","highsecurity","maintenance")) // no glass version
|
||||
target_type += "/[paintjob]"
|
||||
else
|
||||
target_type += "/glass_[paintjob]"
|
||||
else
|
||||
target_type += "/glass"
|
||||
else if(paintjob != "none")
|
||||
target_type += "/[paintjob]"
|
||||
var/final = target_type
|
||||
target_type = text2path(final)
|
||||
if(!target_type)
|
||||
to_chat(usr, "Didn't work, contact Sayu with this: [final]")
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
var/obj/machinery/door/D = new target_type(t_loc)
|
||||
|
||||
D.name = doorname
|
||||
|
||||
if(access_used.len == 0)
|
||||
D.req_access = null
|
||||
D.req_one_access = null
|
||||
else if(require_all)
|
||||
D.req_access = access_used.Copy()
|
||||
D.req_one_access = null
|
||||
else
|
||||
D.req_access = null
|
||||
D.req_one_access = access_used.Copy()
|
||||
|
||||
return
|
||||
|
||||
interact()
|
||||
/*
|
||||
This is for the sandbox for now,
|
||||
maybe useful later for an actual thing?
|
||||
-Sayu
|
||||
*/
|
||||
|
||||
/obj/structure/door_assembly
|
||||
var/datum/airlock_maker/maker = null
|
||||
|
||||
/obj/structure/door_assembly/attack_hand()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(maker)
|
||||
maker.interact()
|
||||
|
||||
/datum/airlock_maker
|
||||
var/obj/structure/door_assembly/linked = null
|
||||
|
||||
var/list/access_used = null
|
||||
var/require_all = 1
|
||||
|
||||
var/paintjob = "none"
|
||||
var/glassdoor = 0
|
||||
|
||||
var/doorname = "airlock"
|
||||
|
||||
/datum/airlock_maker/New(var/atom/target_loc)
|
||||
linked = new(target_loc)
|
||||
linked.maker = src
|
||||
linked.anchored = FALSE
|
||||
access_used = list()
|
||||
|
||||
interact()
|
||||
|
||||
/datum/airlock_maker/proc/linkpretty(href,desc,active)
|
||||
if(!desc)
|
||||
var/static/list/defaults = list("No","Yes")
|
||||
desc = defaults[active+1]
|
||||
if(active)
|
||||
return "<a href='?src=[REF(src)];[href]'><b>[desc]</b></a>"
|
||||
return "<a href='?src=[REF(src)];[href]'><i>[desc]</i></a>"
|
||||
|
||||
/datum/airlock_maker/proc/interact()
|
||||
var/list/leftcolumn = list()
|
||||
var/list/rightcolumn = list()
|
||||
leftcolumn += "<u><b>Required Access</b></u>"
|
||||
for(var/access in get_all_accesses())
|
||||
leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used)
|
||||
leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]"
|
||||
|
||||
rightcolumn += "<u><b>Paintjob</b></u>"
|
||||
for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity"))
|
||||
rightcolumn += linkpretty("paint=[option]",option,option == paintjob)
|
||||
rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "<br><br>"
|
||||
var/length = max(leftcolumn.len,rightcolumn.len)
|
||||
|
||||
var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.<hr><br>"
|
||||
dat += "<a href='?src=[REF(src)];rename'>Door name</a>: \"[doorname]\""
|
||||
dat += "<table>"
|
||||
for(var/i=1; i<=length; i++)
|
||||
dat += "<tr><td>"
|
||||
if(i<=leftcolumn.len)
|
||||
dat += leftcolumn[i]
|
||||
dat += "</td><td>"
|
||||
if(i<=rightcolumn.len)
|
||||
dat += rightcolumn[i]
|
||||
dat += "</td></tr>"
|
||||
|
||||
dat += "</table><hr><a href='?src=[REF(src)];done'>Finalize Airlock Construction</a> | <a href='?src=[REF(src)];cancel'>Cancel and Destroy Airlock</a>"
|
||||
usr << browse(dat,"window=airlockmaker")
|
||||
|
||||
/datum/airlock_maker/Topic(var/href,var/list/href_list)
|
||||
if(!usr)
|
||||
return
|
||||
if(!src || !linked || !linked.loc)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
if("rename" in href_list)
|
||||
var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname)
|
||||
if(newname)
|
||||
doorname = newname
|
||||
if("access" in href_list)
|
||||
var/value = text2num(href_list["access"])
|
||||
access_used ^= value
|
||||
if("reqall" in href_list)
|
||||
require_all = !require_all
|
||||
if("paint" in href_list)
|
||||
paintjob = href_list["paint"]
|
||||
if("glass" in href_list)
|
||||
glassdoor = !glassdoor
|
||||
|
||||
if("cancel" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
qdel(linked)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if("done" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
var/turf/t_loc = linked.loc
|
||||
qdel(linked)
|
||||
if(!istype(t_loc))
|
||||
return
|
||||
|
||||
var/target_type = "/obj/machinery/door/airlock"
|
||||
if(glassdoor)
|
||||
if(paintjob != "none")
|
||||
if(paintjob in list("external","highsecurity","maintenance")) // no glass version
|
||||
target_type += "/[paintjob]"
|
||||
else
|
||||
target_type += "/glass_[paintjob]"
|
||||
else
|
||||
target_type += "/glass"
|
||||
else if(paintjob != "none")
|
||||
target_type += "/[paintjob]"
|
||||
var/final = target_type
|
||||
target_type = text2path(final)
|
||||
if(!target_type)
|
||||
to_chat(usr, "Didn't work, contact Sayu with this: [final]")
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
var/obj/machinery/door/D = new target_type(t_loc)
|
||||
|
||||
D.name = doorname
|
||||
|
||||
if(access_used.len == 0)
|
||||
D.req_access = null
|
||||
D.req_one_access = null
|
||||
else if(require_all)
|
||||
D.req_access = access_used.Copy()
|
||||
D.req_one_access = null
|
||||
else
|
||||
D.req_access = null
|
||||
D.req_one_access = access_used.Copy()
|
||||
|
||||
return
|
||||
|
||||
interact()
|
||||
|
||||
@@ -1,303 +1,303 @@
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
|
||||
/mob
|
||||
var/datum/hSB/sandbox = null
|
||||
/mob/proc/CanBuild()
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
if(src.client.holder)
|
||||
sandbox.admin = 1
|
||||
verbs += new/mob/proc/sandbox_panel
|
||||
/mob/proc/sandbox_panel()
|
||||
set name = "Sandbox Panel"
|
||||
if(sandbox)
|
||||
sandbox.update()
|
||||
|
||||
/datum/hSB
|
||||
var/owner = null
|
||||
var/admin = 0
|
||||
|
||||
var/static/clothinfo = null
|
||||
var/static/reaginfo = null
|
||||
var/static/objinfo = null
|
||||
var/canisterinfo = null
|
||||
var/hsbinfo = null
|
||||
//items that shouldn't spawn on the floor because they would bug or act weird
|
||||
var/static/list/spawn_forbidden = list(
|
||||
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
|
||||
/obj/item/assembly, /obj/item/onetankbomb, /obj/item/pda/ai,
|
||||
/obj/item/smallDelivery, /obj/item/projectile,
|
||||
/obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module)
|
||||
|
||||
/datum/hSB/proc/update()
|
||||
var/static/list/hrefs = list(
|
||||
"Space Gear",
|
||||
"Suit Up (Space Travel Gear)" = "hsbsuit",
|
||||
"Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]",
|
||||
"Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]",
|
||||
|
||||
"Standard Tools",
|
||||
"Spawn Flashlight" = "hsbspawn&path=[/obj/item/flashlight]",
|
||||
"Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]",
|
||||
"Spawn Light Replacer" = "hsbspawn&path=[/obj/item/lightreplacer]",
|
||||
"Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]",
|
||||
"Spawn All-Access ID" = "hsbaaid",
|
||||
|
||||
"Building Supplies",
|
||||
"Spawn 50 Wood" = "hsbwood",
|
||||
"Spawn 50 Metal" = "hsbmetal",
|
||||
"Spawn 50 Plasteel" = "hsbplasteel",
|
||||
"Spawn 50 Reinforced Glass" = "hsbrglass",
|
||||
"Spawn 50 Glass" = "hsbglass",
|
||||
"Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]",
|
||||
"Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]",
|
||||
"Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]",
|
||||
"Spawn Rapid Construction Device" = "hsbrcd",
|
||||
"Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]",
|
||||
"Spawn Airlock" = "hsbairlock",
|
||||
|
||||
"Miscellaneous",
|
||||
"Spawn Air Scrubber" = "hsbscrubber",
|
||||
"Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]",
|
||||
"Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]",
|
||||
|
||||
"Bots",
|
||||
"Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]",
|
||||
"Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]",
|
||||
"Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]",
|
||||
|
||||
"Canisters",
|
||||
"Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]",
|
||||
"Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]")
|
||||
|
||||
|
||||
if(!hsbinfo)
|
||||
hsbinfo = "<center><b>Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbinfo += "<b>Administration</b><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "<b>Canister Spawning</b><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
else
|
||||
hsbinfo += "<i>Some item spawning may be disabled by the administrators.</i><br>"
|
||||
hsbinfo += "<i>Only administrators may spawn dangerous canisters.</i><br>"
|
||||
for(var/T in hrefs)
|
||||
var/href = hrefs[T]
|
||||
if(href)
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
else
|
||||
hsbinfo += "<br><b>[T]</b><br>"
|
||||
hsbinfo += "<hr>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
|
||||
usr << browse(hsbinfo, "window=hsbpanel")
|
||||
|
||||
/datum/hSB/Topic(href, href_list)
|
||||
if(!usr || !src || !(src.owner == usr.ckey))
|
||||
if(usr)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
if(href_list["hsb"])
|
||||
switch(href_list["hsb"])
|
||||
//
|
||||
// Admin: toggle spawning
|
||||
//
|
||||
if("hsbtobj")
|
||||
if(!admin) return
|
||||
if(GLOB.hsboxspawn)
|
||||
to_chat(world, "<span class='boldannounce'>Sandbox:</span> <b>\black[usr.key] has disabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = FALSE
|
||||
return
|
||||
else
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black[usr.key] has enabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = TRUE
|
||||
return
|
||||
//
|
||||
// Admin: Toggle auto-close
|
||||
//
|
||||
if("hsbtac")
|
||||
if(!admin) return
|
||||
var/sbac = CONFIG_GET(flag/sandbox_autoclose)
|
||||
if(sbac)
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black [usr.key] has removed the object spawn limiter.</b>")
|
||||
else
|
||||
to_chat(world, "<span class='danger'>Sandbox:</span> <b>\black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.</b>")
|
||||
CONFIG_SET(flag/sandbox_autoclose, !sbac)
|
||||
return
|
||||
//
|
||||
// Spacesuit with full air jetpack set as internals
|
||||
//
|
||||
if("hsbsuit")
|
||||
var/mob/living/carbon/human/P = usr
|
||||
if(!istype(P)) return
|
||||
if(P.wear_suit)
|
||||
P.wear_suit.forceMove(P.drop_location())
|
||||
P.wear_suit.layer = initial(P.wear_suit.layer)
|
||||
P.wear_suit.plane = initial(P.wear_suit.plane)
|
||||
P.wear_suit = null
|
||||
P.wear_suit = new/obj/item/clothing/suit/space(P)
|
||||
P.wear_suit.layer = ABOVE_HUD_LAYER
|
||||
P.wear_suit.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_suit()
|
||||
if(P.head)
|
||||
P.head.forceMove(P.drop_location())
|
||||
P.head.layer = initial(P.head.layer)
|
||||
P.head.plane = initial(P.head.plane)
|
||||
P.head = null
|
||||
P.head = new/obj/item/clothing/head/helmet/space(P)
|
||||
P.head.layer = ABOVE_HUD_LAYER
|
||||
P.head.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_head()
|
||||
if(P.wear_mask)
|
||||
P.wear_mask.forceMove(P.drop_location())
|
||||
P.wear_mask.layer = initial(P.wear_mask.layer)
|
||||
P.wear_mask.plane = initial(P.wear_mask.plane)
|
||||
P.wear_mask = null
|
||||
P.wear_mask = new/obj/item/clothing/mask/gas(P)
|
||||
P.wear_mask.layer = ABOVE_HUD_LAYER
|
||||
P.wear_mask.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_mask()
|
||||
if(P.back)
|
||||
P.back.forceMove(P.drop_location())
|
||||
P.back.layer = initial(P.back.layer)
|
||||
P.back.plane = initial(P.back.plane)
|
||||
P.back = null
|
||||
P.back = new/obj/item/tank/jetpack/oxygen(P)
|
||||
P.back.layer = ABOVE_HUD_LAYER
|
||||
P.back.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_back()
|
||||
P.internal = P.back
|
||||
P.update_internals_hud_icon(1)
|
||||
|
||||
if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it
|
||||
var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc)
|
||||
hsb.update_icon() // hackish but it wasn't meant to be spawned I guess?
|
||||
|
||||
//
|
||||
// Stacked Materials
|
||||
//
|
||||
|
||||
if("hsbrglass")
|
||||
new/obj/item/stack/sheet/rglass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbmetal")
|
||||
new/obj/item/stack/sheet/metal{amount=50}(usr.loc)
|
||||
|
||||
if("hsbplasteel")
|
||||
new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc)
|
||||
|
||||
if("hsbglass")
|
||||
new/obj/item/stack/sheet/glass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbwood")
|
||||
new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc)
|
||||
|
||||
//
|
||||
// All access ID
|
||||
//
|
||||
if("hsbaaid")
|
||||
var/obj/item/card/id/gold/ID = new(usr.loc)
|
||||
ID.registered_name = usr.real_name
|
||||
ID.assignment = "Sandbox"
|
||||
ID.access = get_all_accesses()
|
||||
ID.update_label()
|
||||
|
||||
//
|
||||
// RCD - starts with full clip
|
||||
// Spawn check due to grief potential (destroying floors, walls, etc)
|
||||
//
|
||||
if("hsbrcd")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
new/obj/item/construction/rcd/combat(usr.loc)
|
||||
|
||||
//
|
||||
// New sandbox airlock maker
|
||||
//
|
||||
if("hsbairlock")
|
||||
new /datum/airlock_maker(usr.loc)
|
||||
|
||||
//
|
||||
// Object spawn window
|
||||
//
|
||||
|
||||
// Clothing
|
||||
if("hsbcloth")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!clothinfo)
|
||||
clothinfo = "<b>Clothing</b> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/clothing)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
clothinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(clothinfo,"window=sandbox")
|
||||
|
||||
// Reagent containers
|
||||
if("hsbreag")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!reaginfo)
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
reaginfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(reaginfo,"window=sandbox")
|
||||
|
||||
// Other items
|
||||
if("hsbobj")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!objinfo)
|
||||
objinfo = "<b>Other Items</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
|
||||
for(var/O in reverseRange(all_items))
|
||||
objinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(objinfo,"window=sandbox")
|
||||
|
||||
//
|
||||
// Safespawn checks to see if spawning is disabled.
|
||||
//
|
||||
if("hsb_safespawn")
|
||||
if(!GLOB.hsboxspawn)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
//
|
||||
// For everything else in the href list
|
||||
//
|
||||
if("hsbspawn")
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
|
||||
/mob
|
||||
var/datum/hSB/sandbox = null
|
||||
/mob/proc/CanBuild()
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
if(src.client.holder)
|
||||
sandbox.admin = 1
|
||||
verbs += new/mob/proc/sandbox_panel
|
||||
/mob/proc/sandbox_panel()
|
||||
set name = "Sandbox Panel"
|
||||
if(sandbox)
|
||||
sandbox.update()
|
||||
|
||||
/datum/hSB
|
||||
var/owner = null
|
||||
var/admin = 0
|
||||
|
||||
var/static/clothinfo = null
|
||||
var/static/reaginfo = null
|
||||
var/static/objinfo = null
|
||||
var/canisterinfo = null
|
||||
var/hsbinfo = null
|
||||
//items that shouldn't spawn on the floor because they would bug or act weird
|
||||
var/static/list/spawn_forbidden = list(
|
||||
/obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you
|
||||
/obj/item/assembly, /obj/item/onetankbomb, /obj/item/pda/ai,
|
||||
/obj/item/smallDelivery, /obj/item/projectile,
|
||||
/obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module)
|
||||
|
||||
/datum/hSB/proc/update()
|
||||
var/static/list/hrefs = list(
|
||||
"Space Gear",
|
||||
"Suit Up (Space Travel Gear)" = "hsbsuit",
|
||||
"Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]",
|
||||
"Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]",
|
||||
|
||||
"Standard Tools",
|
||||
"Spawn Flashlight" = "hsbspawn&path=[/obj/item/flashlight]",
|
||||
"Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]",
|
||||
"Spawn Light Replacer" = "hsbspawn&path=[/obj/item/lightreplacer]",
|
||||
"Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]",
|
||||
"Spawn All-Access ID" = "hsbaaid",
|
||||
|
||||
"Building Supplies",
|
||||
"Spawn 50 Wood" = "hsbwood",
|
||||
"Spawn 50 Metal" = "hsbmetal",
|
||||
"Spawn 50 Plasteel" = "hsbplasteel",
|
||||
"Spawn 50 Reinforced Glass" = "hsbrglass",
|
||||
"Spawn 50 Glass" = "hsbglass",
|
||||
"Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]",
|
||||
"Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]",
|
||||
"Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]",
|
||||
"Spawn Rapid Construction Device" = "hsbrcd",
|
||||
"Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]",
|
||||
"Spawn Airlock" = "hsbairlock",
|
||||
|
||||
"Miscellaneous",
|
||||
"Spawn Air Scrubber" = "hsbscrubber",
|
||||
"Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]",
|
||||
"Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]",
|
||||
|
||||
"Bots",
|
||||
"Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]",
|
||||
"Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]",
|
||||
"Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]",
|
||||
|
||||
"Canisters",
|
||||
"Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]",
|
||||
"Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]")
|
||||
|
||||
|
||||
if(!hsbinfo)
|
||||
hsbinfo = "<center><b>Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbinfo += "<b>Administration</b><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "<b>Canister Spawning</b><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
else
|
||||
hsbinfo += "<i>Some item spawning may be disabled by the administrators.</i><br>"
|
||||
hsbinfo += "<i>Only administrators may spawn dangerous canisters.</i><br>"
|
||||
for(var/T in hrefs)
|
||||
var/href = hrefs[T]
|
||||
if(href)
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
else
|
||||
hsbinfo += "<br><b>[T]</b><br>"
|
||||
hsbinfo += "<hr>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
|
||||
usr << browse(hsbinfo, "window=hsbpanel")
|
||||
|
||||
/datum/hSB/Topic(href, href_list)
|
||||
if(!usr || !src || !(src.owner == usr.ckey))
|
||||
if(usr)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
if(href_list["hsb"])
|
||||
switch(href_list["hsb"])
|
||||
//
|
||||
// Admin: toggle spawning
|
||||
//
|
||||
if("hsbtobj")
|
||||
if(!admin) return
|
||||
if(GLOB.hsboxspawn)
|
||||
to_chat(world, "<span class='boldannounce'>Sandbox:</span> <b>\black[usr.key] has disabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = FALSE
|
||||
return
|
||||
else
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black[usr.key] has enabled object spawning!</b>")
|
||||
GLOB.hsboxspawn = TRUE
|
||||
return
|
||||
//
|
||||
// Admin: Toggle auto-close
|
||||
//
|
||||
if("hsbtac")
|
||||
if(!admin) return
|
||||
var/sbac = CONFIG_GET(flag/sandbox_autoclose)
|
||||
if(sbac)
|
||||
to_chat(world, "<span class='boldnotice'>Sandbox:</span> <b>\black [usr.key] has removed the object spawn limiter.</b>")
|
||||
else
|
||||
to_chat(world, "<span class='danger'>Sandbox:</span> <b>\black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.</b>")
|
||||
CONFIG_SET(flag/sandbox_autoclose, !sbac)
|
||||
return
|
||||
//
|
||||
// Spacesuit with full air jetpack set as internals
|
||||
//
|
||||
if("hsbsuit")
|
||||
var/mob/living/carbon/human/P = usr
|
||||
if(!istype(P)) return
|
||||
if(P.wear_suit)
|
||||
P.wear_suit.forceMove(P.drop_location())
|
||||
P.wear_suit.layer = initial(P.wear_suit.layer)
|
||||
P.wear_suit.plane = initial(P.wear_suit.plane)
|
||||
P.wear_suit = null
|
||||
P.wear_suit = new/obj/item/clothing/suit/space(P)
|
||||
P.wear_suit.layer = ABOVE_HUD_LAYER
|
||||
P.wear_suit.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_suit()
|
||||
if(P.head)
|
||||
P.head.forceMove(P.drop_location())
|
||||
P.head.layer = initial(P.head.layer)
|
||||
P.head.plane = initial(P.head.plane)
|
||||
P.head = null
|
||||
P.head = new/obj/item/clothing/head/helmet/space(P)
|
||||
P.head.layer = ABOVE_HUD_LAYER
|
||||
P.head.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_head()
|
||||
if(P.wear_mask)
|
||||
P.wear_mask.forceMove(P.drop_location())
|
||||
P.wear_mask.layer = initial(P.wear_mask.layer)
|
||||
P.wear_mask.plane = initial(P.wear_mask.plane)
|
||||
P.wear_mask = null
|
||||
P.wear_mask = new/obj/item/clothing/mask/gas(P)
|
||||
P.wear_mask.layer = ABOVE_HUD_LAYER
|
||||
P.wear_mask.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_wear_mask()
|
||||
if(P.back)
|
||||
P.back.forceMove(P.drop_location())
|
||||
P.back.layer = initial(P.back.layer)
|
||||
P.back.plane = initial(P.back.plane)
|
||||
P.back = null
|
||||
P.back = new/obj/item/tank/jetpack/oxygen(P)
|
||||
P.back.layer = ABOVE_HUD_LAYER
|
||||
P.back.plane = ABOVE_HUD_PLANE
|
||||
P.update_inv_back()
|
||||
P.internal = P.back
|
||||
P.update_internals_hud_icon(1)
|
||||
|
||||
if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it
|
||||
var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc)
|
||||
hsb.update_icon() // hackish but it wasn't meant to be spawned I guess?
|
||||
|
||||
//
|
||||
// Stacked Materials
|
||||
//
|
||||
|
||||
if("hsbrglass")
|
||||
new/obj/item/stack/sheet/rglass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbmetal")
|
||||
new/obj/item/stack/sheet/metal{amount=50}(usr.loc)
|
||||
|
||||
if("hsbplasteel")
|
||||
new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc)
|
||||
|
||||
if("hsbglass")
|
||||
new/obj/item/stack/sheet/glass{amount=50}(usr.loc)
|
||||
|
||||
if("hsbwood")
|
||||
new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc)
|
||||
|
||||
//
|
||||
// All access ID
|
||||
//
|
||||
if("hsbaaid")
|
||||
var/obj/item/card/id/gold/ID = new(usr.loc)
|
||||
ID.registered_name = usr.real_name
|
||||
ID.assignment = "Sandbox"
|
||||
ID.access = get_all_accesses()
|
||||
ID.update_label()
|
||||
|
||||
//
|
||||
// RCD - starts with full clip
|
||||
// Spawn check due to grief potential (destroying floors, walls, etc)
|
||||
//
|
||||
if("hsbrcd")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
new/obj/item/construction/rcd/combat(usr.loc)
|
||||
|
||||
//
|
||||
// New sandbox airlock maker
|
||||
//
|
||||
if("hsbairlock")
|
||||
new /datum/airlock_maker(usr.loc)
|
||||
|
||||
//
|
||||
// Object spawn window
|
||||
//
|
||||
|
||||
// Clothing
|
||||
if("hsbcloth")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!clothinfo)
|
||||
clothinfo = "<b>Clothing</b> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/clothing)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
clothinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(clothinfo,"window=sandbox")
|
||||
|
||||
// Reagent containers
|
||||
if("hsbreag")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!reaginfo)
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
reaginfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(reaginfo,"window=sandbox")
|
||||
|
||||
// Other items
|
||||
if("hsbobj")
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!objinfo)
|
||||
objinfo = "<b>Other Items</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
|
||||
for(var/O in reverseRange(all_items))
|
||||
objinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(objinfo,"window=sandbox")
|
||||
|
||||
//
|
||||
// Safespawn checks to see if spawning is disabled.
|
||||
//
|
||||
if("hsb_safespawn")
|
||||
if(!GLOB.hsboxspawn)
|
||||
usr << browse(null,"window=sandbox")
|
||||
return
|
||||
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
//
|
||||
// For everything else in the href list
|
||||
//
|
||||
if("hsbspawn")
|
||||
var/typepath = text2path(href_list["path"])
|
||||
if(!typepath)
|
||||
to_chat(usr, "Bad path: \"[href_list["path"]]\"")
|
||||
return
|
||||
new typepath(usr.loc)
|
||||
|
||||
if(CONFIG_GET(flag/sandbox_autoclose))
|
||||
usr << browse(null,"window=sandbox")
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/datum/game_mode/sandbox
|
||||
name = "sandbox"
|
||||
config_tag = "sandbox"
|
||||
required_players = 0
|
||||
|
||||
announce_span = "info"
|
||||
announce_text = "Build your own station... or just shoot each other!"
|
||||
|
||||
allow_persistence_save = FALSE
|
||||
|
||||
/datum/game_mode/sandbox/pre_setup()
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M.CanBuild()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/sandbox/post_setup()
|
||||
..()
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
|
||||
/datum/game_mode/sandbox/generate_report()
|
||||
return "Sensors indicate that crewmembers have been all given psychic powers from which they can manifest various objects.<br><br>This can only end poorly."
|
||||
/datum/game_mode/sandbox
|
||||
name = "sandbox"
|
||||
config_tag = "sandbox"
|
||||
required_players = 0
|
||||
|
||||
announce_span = "info"
|
||||
announce_text = "Build your own station... or just shoot each other!"
|
||||
|
||||
allow_persistence_save = FALSE
|
||||
|
||||
/datum/game_mode/sandbox/pre_setup()
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M.CanBuild()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/sandbox/post_setup()
|
||||
..()
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
|
||||
/datum/game_mode/sandbox/generate_report()
|
||||
return "Sensors indicate that crewmembers have been all given psychic powers from which they can manifest various objects.<br><br>This can only end poorly."
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
/datum/game_mode
|
||||
var/list/target_list = list()
|
||||
var/list/late_joining_list = list()
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs
|
||||
name = "Internal Affairs"
|
||||
config_tag = "internal_affairs"
|
||||
false_report_weight = 10
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
recommended_enemies = 8
|
||||
reroll_friendly = 0
|
||||
traitor_name = "Nanotrasen Internal Affairs Agent"
|
||||
antag_flag = ROLE_INTERNAL_AFFAIRS
|
||||
|
||||
traitors_possible = 10 //hard limit on traitors if scaling is turned off
|
||||
num_modifier = 4 // Four additional traitors
|
||||
antag_datum = /datum/antagonist/traitor/internal_affairs
|
||||
|
||||
announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\
|
||||
<span class='danger'>IAA</span>: Eliminate your targets and protect yourself!\n\
|
||||
<span class='notice'>Crew</span>: Stop the IAA agents before they can cause too much mayhem."
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/post_setup()
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in pre_traitors)
|
||||
i++
|
||||
if(i + 1 > pre_traitors.len)
|
||||
i = 0
|
||||
target_list[traitor] = pre_traitors[i+1]
|
||||
..()
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character)
|
||||
|
||||
check_potential_agents()
|
||||
|
||||
// As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other.
|
||||
if(late_joining_list.len >= rand(3, 4))
|
||||
// True randomness
|
||||
shuffle_inplace(late_joining_list)
|
||||
// Reset the target_list, it'll be used again in force_traitor_objectives
|
||||
target_list = list()
|
||||
|
||||
// Basically setting the target_list for who is killing who
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in late_joining_list)
|
||||
i++
|
||||
if(i + 1 > late_joining_list.len)
|
||||
i = 0
|
||||
target_list[traitor] = late_joining_list[i + 1]
|
||||
traitor.special_role = traitor_name
|
||||
|
||||
// Now, give them their targets
|
||||
for(var/datum/mind/traitor in target_list)
|
||||
..(traitor)
|
||||
|
||||
late_joining_list = list()
|
||||
else
|
||||
late_joining_list += character
|
||||
return
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents()
|
||||
|
||||
for(var/M in late_joining_list)
|
||||
if(istype(M, /datum/mind))
|
||||
var/datum/mind/agent_mind = M
|
||||
if(ishuman(agent_mind.current))
|
||||
var/mob/living/carbon/human/H = agent_mind.current
|
||||
if(H.stat != DEAD)
|
||||
if(H.client)
|
||||
continue // It all checks out.
|
||||
|
||||
// If any check fails, remove them from our list
|
||||
late_joining_list -= M
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/generate_report()
|
||||
return "Nanotrasen denies any accusations of placing internal affairs agents onboard your station to eliminate inconvenient employees. Any further accusations against CentCom for such \
|
||||
actions will be met with a conversation with an official internal affairs agent."
|
||||
/datum/game_mode
|
||||
var/list/target_list = list()
|
||||
var/list/late_joining_list = list()
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs
|
||||
name = "Internal Affairs"
|
||||
config_tag = "internal_affairs"
|
||||
false_report_weight = 10
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
recommended_enemies = 8
|
||||
reroll_friendly = 0
|
||||
traitor_name = "Nanotrasen Internal Affairs Agent"
|
||||
antag_flag = ROLE_INTERNAL_AFFAIRS
|
||||
|
||||
traitors_possible = 10 //hard limit on traitors if scaling is turned off
|
||||
num_modifier = 4 // Four additional traitors
|
||||
antag_datum = /datum/antagonist/traitor/internal_affairs
|
||||
|
||||
announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\
|
||||
<span class='danger'>IAA</span>: Eliminate your targets and protect yourself!\n\
|
||||
<span class='notice'>Crew</span>: Stop the IAA agents before they can cause too much mayhem."
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/post_setup()
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in pre_traitors)
|
||||
i++
|
||||
if(i + 1 > pre_traitors.len)
|
||||
i = 0
|
||||
target_list[traitor] = pre_traitors[i+1]
|
||||
..()
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character)
|
||||
|
||||
check_potential_agents()
|
||||
|
||||
// As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other.
|
||||
if(late_joining_list.len >= rand(3, 4))
|
||||
// True randomness
|
||||
shuffle_inplace(late_joining_list)
|
||||
// Reset the target_list, it'll be used again in force_traitor_objectives
|
||||
target_list = list()
|
||||
|
||||
// Basically setting the target_list for who is killing who
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in late_joining_list)
|
||||
i++
|
||||
if(i + 1 > late_joining_list.len)
|
||||
i = 0
|
||||
target_list[traitor] = late_joining_list[i + 1]
|
||||
traitor.special_role = traitor_name
|
||||
|
||||
// Now, give them their targets
|
||||
for(var/datum/mind/traitor in target_list)
|
||||
..(traitor)
|
||||
|
||||
late_joining_list = list()
|
||||
else
|
||||
late_joining_list += character
|
||||
return
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents()
|
||||
|
||||
for(var/M in late_joining_list)
|
||||
if(istype(M, /datum/mind))
|
||||
var/datum/mind/agent_mind = M
|
||||
if(ishuman(agent_mind.current))
|
||||
var/mob/living/carbon/human/H = agent_mind.current
|
||||
if(H.stat != DEAD)
|
||||
if(H.client)
|
||||
continue // It all checks out.
|
||||
|
||||
// If any check fails, remove them from our list
|
||||
late_joining_list -= M
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/generate_report()
|
||||
return "Nanotrasen denies any accusations of placing internal affairs agents onboard your station to eliminate inconvenient employees. Any further accusations against CentCom for such \
|
||||
actions will be met with a conversation with an official internal affairs agent."
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
/datum/game_mode
|
||||
var/traitor_name = "traitor"
|
||||
var/list/datum/mind/traitors = list()
|
||||
|
||||
var/datum/mind/exchange_red
|
||||
var/datum/mind/exchange_blue
|
||||
|
||||
/datum/game_mode/traitor
|
||||
name = "traitor"
|
||||
config_tag = "traitor"
|
||||
antag_flag = ROLE_TRAITOR
|
||||
false_report_weight = 20 //Reports of traitors are pretty common.
|
||||
restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist
|
||||
required_players = 0
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = 1
|
||||
enemy_minimum_age = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are Syndicate agents on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors succeed!"
|
||||
|
||||
var/list/datum/mind/pre_traitors = list()
|
||||
var/traitors_possible = 4 //hard limit on traitors if scaling is turned off
|
||||
var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
|
||||
var/antag_datum = /datum/antagonist/traitor //what type of antag to create
|
||||
var/traitors_required = TRUE //Will allow no traitors
|
||||
|
||||
|
||||
/datum/game_mode/traitor/pre_setup()
|
||||
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_traitors = 1
|
||||
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
if(tsc)
|
||||
num_traitors = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier))
|
||||
else
|
||||
num_traitors = max(1, min(num_players(), traitors_possible))
|
||||
|
||||
for(var/j = 0, j < num_traitors, j++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/traitor = antag_pick(antag_candidates)
|
||||
pre_traitors += traitor
|
||||
traitor.special_role = traitor_name
|
||||
traitor.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(traitor)] has been selected as a [traitor_name]")
|
||||
antag_candidates.Remove(traitor)
|
||||
|
||||
var/enough_tators = !traitors_required || pre_traitors.len > 0
|
||||
|
||||
if(!enough_tators)
|
||||
setup_error = "Not enough traitor candidates"
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/traitor/post_setup()
|
||||
for(var/datum/mind/traitor in pre_traitors)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum()
|
||||
addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100))
|
||||
if(!exchange_blue)
|
||||
exchange_blue = -1 //Block latejoiners from getting exchange objectives
|
||||
..()
|
||||
|
||||
//We're not actually ready until all traitors are assigned.
|
||||
gamemode_ready = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, gamemode_ready, TRUE), 101)
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
var/traitorcap = min(round(GLOB.joined_player_list.len / (tsc * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len / tsc) + num_modifier)
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists
|
||||
return
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2)))
|
||||
if(antag_flag in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_TRAITOR) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
add_latejoin_traitor(character.mind)
|
||||
|
||||
/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum()
|
||||
character.add_antag_datum(new_antag)
|
||||
|
||||
/datum/game_mode/traitor/generate_report()
|
||||
return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \
|
||||
Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions."
|
||||
/datum/game_mode
|
||||
var/traitor_name = "traitor"
|
||||
var/list/datum/mind/traitors = list()
|
||||
|
||||
var/datum/mind/exchange_red
|
||||
var/datum/mind/exchange_blue
|
||||
|
||||
/datum/game_mode/traitor
|
||||
name = "traitor"
|
||||
config_tag = "traitor"
|
||||
antag_flag = ROLE_TRAITOR
|
||||
false_report_weight = 20 //Reports of traitors are pretty common.
|
||||
restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist
|
||||
required_players = 0
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = 1
|
||||
enemy_minimum_age = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are Syndicate agents on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors succeed!"
|
||||
|
||||
var/list/datum/mind/pre_traitors = list()
|
||||
var/traitors_possible = 4 //hard limit on traitors if scaling is turned off
|
||||
var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
|
||||
var/antag_datum = /datum/antagonist/traitor //what type of antag to create
|
||||
var/traitors_required = TRUE //Will allow no traitors
|
||||
|
||||
|
||||
/datum/game_mode/traitor/pre_setup()
|
||||
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/num_traitors = 1
|
||||
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
if(tsc)
|
||||
num_traitors = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier))
|
||||
else
|
||||
num_traitors = max(1, min(num_players(), traitors_possible))
|
||||
|
||||
for(var/j = 0, j < num_traitors, j++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/traitor = antag_pick(antag_candidates)
|
||||
pre_traitors += traitor
|
||||
traitor.special_role = traitor_name
|
||||
traitor.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(traitor)] has been selected as a [traitor_name]")
|
||||
antag_candidates.Remove(traitor)
|
||||
|
||||
var/enough_tators = !traitors_required || pre_traitors.len > 0
|
||||
|
||||
if(!enough_tators)
|
||||
setup_error = "Not enough traitor candidates"
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/traitor/post_setup()
|
||||
for(var/datum/mind/traitor in pre_traitors)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum()
|
||||
addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100))
|
||||
if(!exchange_blue)
|
||||
exchange_blue = -1 //Block latejoiners from getting exchange objectives
|
||||
..()
|
||||
|
||||
//We're not actually ready until all traitors are assigned.
|
||||
gamemode_ready = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, gamemode_ready, TRUE), 101)
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners
|
||||
var/tsc = CONFIG_GET(number/traitor_scaling_coeff)
|
||||
var/traitorcap = min(round(GLOB.joined_player_list.len / (tsc * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len / tsc) + num_modifier)
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists
|
||||
return
|
||||
if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2)))
|
||||
if(antag_flag in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_TRAITOR) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
add_latejoin_traitor(character.mind)
|
||||
|
||||
/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum()
|
||||
character.add_antag_datum(new_antag)
|
||||
|
||||
/datum/game_mode/traitor/generate_report()
|
||||
return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \
|
||||
Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions."
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/wizards = list()
|
||||
var/list/datum/mind/apprentices = list()
|
||||
|
||||
/datum/game_mode/wizard
|
||||
name = "wizard"
|
||||
config_tag = "wizard"
|
||||
antag_flag = ROLE_WIZARD
|
||||
false_report_weight = 10
|
||||
required_players = 20
|
||||
required_enemies = 1
|
||||
recommended_enemies = 1
|
||||
enemy_minimum_age = 7
|
||||
round_ends_with_antag_death = 1
|
||||
announce_span = "danger"
|
||||
announce_text = "There is a space wizard attacking the station!\n\
|
||||
<span class='danger'>Wizard</span>: Accomplish your objectives and cause mayhem on the station.\n\
|
||||
<span class='notice'>Crew</span>: Eliminate the wizard before they can succeed!"
|
||||
var/finished = 0
|
||||
|
||||
/datum/game_mode/wizard/pre_setup()
|
||||
var/datum/mind/wizard = antag_pick(antag_candidates)
|
||||
wizards += wizard
|
||||
wizard.assigned_role = ROLE_WIZARD
|
||||
wizard.special_role = ROLE_WIZARD
|
||||
log_game("[key_name(wizard)] has been selected as a Wizard") //TODO: Move these to base antag datum
|
||||
if(GLOB.wizardstart.len == 0)
|
||||
setup_error = "No wizard starting location found"
|
||||
return FALSE
|
||||
for(var/datum/mind/wiz in wizards)
|
||||
wiz.current.forceMove(pick(GLOB.wizardstart))
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/wizard/post_setup()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
wizard.add_antag_datum(/datum/antagonist/wizard)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/wizard/generate_report()
|
||||
return "A dangerous Wizards' Federation individual by the name of [pick(GLOB.wizard_first)] [pick(GLOB.wizard_second)] has recently escaped confinement from an unlisted prison facility. This \
|
||||
man is a dangerous mutant with the ability to alter himself and the world around him by what he and his leaders believe to be magic. If this man attempts an attack on your station, \
|
||||
his execution is highly encouraged, as is the preservation of his body for later study."
|
||||
|
||||
|
||||
/datum/game_mode/wizard/are_special_antags_dead()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
return FALSE
|
||||
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
|
||||
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
|
||||
return FALSE
|
||||
|
||||
if(SSevents.wizardmode) //If summon events was active, turn it off
|
||||
SSevents.toggleWizardmode()
|
||||
SSevents.resetFrequency()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/wizard/set_round_result()
|
||||
..()
|
||||
if(finished)
|
||||
SSticker.mode_result = "loss - wizard killed"
|
||||
SSticker.news_report = WIZARD_KILLED
|
||||
|
||||
/datum/game_mode/wizard/special_report()
|
||||
if(finished)
|
||||
return "<span class='redtext big'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>"
|
||||
|
||||
//returns whether the mob is a wizard (or apprentice)
|
||||
/proc/iswizard(mob/living/M)
|
||||
return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE)
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/wizards = list()
|
||||
var/list/datum/mind/apprentices = list()
|
||||
|
||||
/datum/game_mode/wizard
|
||||
name = "wizard"
|
||||
config_tag = "wizard"
|
||||
antag_flag = ROLE_WIZARD
|
||||
false_report_weight = 10
|
||||
required_players = 20
|
||||
required_enemies = 1
|
||||
recommended_enemies = 1
|
||||
enemy_minimum_age = 7
|
||||
round_ends_with_antag_death = 1
|
||||
announce_span = "danger"
|
||||
announce_text = "There is a space wizard attacking the station!\n\
|
||||
<span class='danger'>Wizard</span>: Accomplish your objectives and cause mayhem on the station.\n\
|
||||
<span class='notice'>Crew</span>: Eliminate the wizard before they can succeed!"
|
||||
var/finished = 0
|
||||
|
||||
/datum/game_mode/wizard/pre_setup()
|
||||
var/datum/mind/wizard = antag_pick(antag_candidates)
|
||||
wizards += wizard
|
||||
wizard.assigned_role = ROLE_WIZARD
|
||||
wizard.special_role = ROLE_WIZARD
|
||||
log_game("[key_name(wizard)] has been selected as a Wizard") //TODO: Move these to base antag datum
|
||||
if(GLOB.wizardstart.len == 0)
|
||||
setup_error = "No wizard starting location found"
|
||||
return FALSE
|
||||
for(var/datum/mind/wiz in wizards)
|
||||
wiz.current.forceMove(pick(GLOB.wizardstart))
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/wizard/post_setup()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
wizard.add_antag_datum(/datum/antagonist/wizard)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/wizard/generate_report()
|
||||
return "A dangerous Wizards' Federation individual by the name of [pick(GLOB.wizard_first)] [pick(GLOB.wizard_second)] has recently escaped confinement from an unlisted prison facility. This \
|
||||
man is a dangerous mutant with the ability to alter himself and the world around him by what he and his leaders believe to be magic. If this man attempts an attack on your station, \
|
||||
his execution is highly encouraged, as is the preservation of his body for later study."
|
||||
|
||||
|
||||
/datum/game_mode/wizard/are_special_antags_dead()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
return FALSE
|
||||
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
|
||||
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
|
||||
return FALSE
|
||||
|
||||
if(SSevents.wizardmode) //If summon events was active, turn it off
|
||||
SSevents.toggleWizardmode()
|
||||
SSevents.resetFrequency()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/wizard/set_round_result()
|
||||
..()
|
||||
if(finished)
|
||||
SSticker.mode_result = "loss - wizard killed"
|
||||
SSticker.news_report = WIZARD_KILLED
|
||||
|
||||
/datum/game_mode/wizard/special_report()
|
||||
if(finished)
|
||||
return "<span class='redtext big'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>"
|
||||
|
||||
//returns whether the mob is a wizard (or apprentice)
|
||||
/proc/iswizard(mob/living/M)
|
||||
return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE)
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
/obj/machinery/bluespace_beacon
|
||||
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "floor_beaconf"
|
||||
name = "bluespace gigabeacon"
|
||||
desc = "A device that draws power from bluespace and creates a permanent tracking beacon."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 0
|
||||
var/obj/item/beacon/Beacon
|
||||
|
||||
/obj/machinery/bluespace_beacon/Initialize()
|
||||
. = ..()
|
||||
var/turf/T = loc
|
||||
Beacon = new(T)
|
||||
Beacon.invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
hide(T.intact)
|
||||
|
||||
/obj/machinery/bluespace_beacon/Destroy()
|
||||
QDEL_NULL(Beacon)
|
||||
return ..()
|
||||
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/bluespace_beacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/bluespace_beacon/update_icon()
|
||||
var/state="floor_beacon"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state]f"
|
||||
|
||||
else
|
||||
icon_state = "[state]"
|
||||
|
||||
/obj/machinery/bluespace_beacon/process()
|
||||
if(!Beacon)
|
||||
var/turf/T = loc
|
||||
Beacon = new(T)
|
||||
Beacon.invisibility = INVISIBILITY_MAXIMUM
|
||||
else if (Beacon.loc != loc)
|
||||
Beacon.forceMove(loc)
|
||||
|
||||
update_icon()
|
||||
/obj/machinery/bluespace_beacon
|
||||
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "floor_beaconf"
|
||||
name = "bluespace gigabeacon"
|
||||
desc = "A device that draws power from bluespace and creates a permanent tracking beacon."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 0
|
||||
var/obj/item/beacon/Beacon
|
||||
|
||||
/obj/machinery/bluespace_beacon/Initialize()
|
||||
. = ..()
|
||||
var/turf/T = loc
|
||||
Beacon = new(T)
|
||||
Beacon.invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
hide(T.intact)
|
||||
|
||||
/obj/machinery/bluespace_beacon/Destroy()
|
||||
QDEL_NULL(Beacon)
|
||||
return ..()
|
||||
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/bluespace_beacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/bluespace_beacon/update_icon()
|
||||
var/state="floor_beacon"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state]f"
|
||||
|
||||
else
|
||||
icon_state = "[state]"
|
||||
|
||||
/obj/machinery/bluespace_beacon/process()
|
||||
if(!Beacon)
|
||||
var/turf/T = loc
|
||||
Beacon = new(T)
|
||||
Beacon.invisibility = INVISIBILITY_MAXIMUM
|
||||
else if (Beacon.loc != loc)
|
||||
Beacon.forceMove(loc)
|
||||
|
||||
update_icon()
|
||||
|
||||
+143
-143
@@ -1,143 +1,143 @@
|
||||
/obj/machinery/pdapainter
|
||||
name = "\improper PDA painter"
|
||||
desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pdapainter"
|
||||
density = TRUE
|
||||
max_integrity = 200
|
||||
var/obj/item/pda/storedpda = null
|
||||
var/list/colorlist = list()
|
||||
|
||||
|
||||
/obj/machinery/pdapainter/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
add_overlay("[initial(icon_state)]-closed")
|
||||
|
||||
if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/pdapainter/Initialize()
|
||||
. = ..()
|
||||
var/list/blocked = list(
|
||||
/obj/item/pda/ai/pai,
|
||||
/obj/item/pda/ai,
|
||||
/obj/item/pda/heads,
|
||||
/obj/item/pda/clear,
|
||||
/obj/item/pda/syndicate,
|
||||
/obj/item/pda/chameleon,
|
||||
/obj/item/pda/chameleon/broken,
|
||||
/obj/item/pda/lieutenant)
|
||||
|
||||
for(var/A in typesof(/obj/item/pda) - blocked)
|
||||
var/obj/item/pda/P = A
|
||||
var/PDA_name = initial(P.name)
|
||||
colorlist += PDA_name
|
||||
colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons))
|
||||
|
||||
/obj/machinery/pdapainter/Destroy()
|
||||
QDEL_NULL(storedpda)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pdapainter/on_deconstruction()
|
||||
if(storedpda)
|
||||
storedpda.forceMove(loc)
|
||||
storedpda = null
|
||||
|
||||
/obj/machinery/pdapainter/contents_explosion(severity, target)
|
||||
if(storedpda)
|
||||
storedpda.ex_act(severity, target)
|
||||
|
||||
/obj/machinery/pdapainter/handle_atom_del(atom/A)
|
||||
if(A == storedpda)
|
||||
storedpda = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pdapainter/attackby(obj/item/O, mob/user, params)
|
||||
if(default_unfasten_wrench(user, O))
|
||||
power_change()
|
||||
return
|
||||
|
||||
else if(istype(O, /obj/item/pda))
|
||||
if(storedpda)
|
||||
to_chat(user, "<span class='warning'>There is already a PDA inside!</span>")
|
||||
return
|
||||
else if(!user.transferItemToLoc(O, src))
|
||||
return
|
||||
storedpda = O
|
||||
O.add_fingerprint(user)
|
||||
update_icon()
|
||||
|
||||
else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
|
||||
if(stat & BROKEN)
|
||||
if(!O.tool_start_check(user, amount=0))
|
||||
return
|
||||
user.visible_message("[user] is repairing [src].", \
|
||||
"<span class='notice'>You begin repairing [src]...</span>", \
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
if(O.use_tool(src, user, 40, volume=50))
|
||||
if(!(stat & BROKEN))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You repair [src].</span>")
|
||||
stat &= ~BROKEN
|
||||
obj_integrity = max_integrity
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] does not need repairs.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pdapainter/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(!(stat & BROKEN))
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pdapainter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!storedpda)
|
||||
to_chat(user, "<span class='notice'>[src] is empty.</span>")
|
||||
return
|
||||
var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist
|
||||
if(!choice || !storedpda || !in_range(src, user))
|
||||
return
|
||||
var/list/P = colorlist[choice]
|
||||
storedpda.icon_state = P[1]
|
||||
storedpda.desc = P[2]
|
||||
storedpda.overlays_offsets = P[3]
|
||||
storedpda.overlays_icons = P[4]
|
||||
storedpda.set_new_overlays()
|
||||
storedpda.update_icon()
|
||||
ejectpda()
|
||||
|
||||
/obj/machinery/pdapainter/verb/ejectpda()
|
||||
set name = "Eject PDA"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
storedpda.forceMove(drop_location())
|
||||
storedpda = null
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>[src] is empty.</span>")
|
||||
|
||||
|
||||
/obj/machinery/pdapainter/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
/obj/machinery/pdapainter
|
||||
name = "\improper PDA painter"
|
||||
desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pdapainter"
|
||||
density = TRUE
|
||||
max_integrity = 200
|
||||
var/obj/item/pda/storedpda = null
|
||||
var/list/colorlist = list()
|
||||
|
||||
|
||||
/obj/machinery/pdapainter/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
add_overlay("[initial(icon_state)]-closed")
|
||||
|
||||
if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/pdapainter/Initialize()
|
||||
. = ..()
|
||||
var/list/blocked = list(
|
||||
/obj/item/pda/ai/pai,
|
||||
/obj/item/pda/ai,
|
||||
/obj/item/pda/heads,
|
||||
/obj/item/pda/clear,
|
||||
/obj/item/pda/syndicate,
|
||||
/obj/item/pda/chameleon,
|
||||
/obj/item/pda/chameleon/broken,
|
||||
/obj/item/pda/lieutenant)
|
||||
|
||||
for(var/A in typesof(/obj/item/pda) - blocked)
|
||||
var/obj/item/pda/P = A
|
||||
var/PDA_name = initial(P.name)
|
||||
colorlist += PDA_name
|
||||
colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons))
|
||||
|
||||
/obj/machinery/pdapainter/Destroy()
|
||||
QDEL_NULL(storedpda)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pdapainter/on_deconstruction()
|
||||
if(storedpda)
|
||||
storedpda.forceMove(loc)
|
||||
storedpda = null
|
||||
|
||||
/obj/machinery/pdapainter/contents_explosion(severity, target)
|
||||
if(storedpda)
|
||||
storedpda.ex_act(severity, target)
|
||||
|
||||
/obj/machinery/pdapainter/handle_atom_del(atom/A)
|
||||
if(A == storedpda)
|
||||
storedpda = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pdapainter/attackby(obj/item/O, mob/user, params)
|
||||
if(default_unfasten_wrench(user, O))
|
||||
power_change()
|
||||
return
|
||||
|
||||
else if(istype(O, /obj/item/pda))
|
||||
if(storedpda)
|
||||
to_chat(user, "<span class='warning'>There is already a PDA inside!</span>")
|
||||
return
|
||||
else if(!user.transferItemToLoc(O, src))
|
||||
return
|
||||
storedpda = O
|
||||
O.add_fingerprint(user)
|
||||
update_icon()
|
||||
|
||||
else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
|
||||
if(stat & BROKEN)
|
||||
if(!O.tool_start_check(user, amount=0))
|
||||
return
|
||||
user.visible_message("[user] is repairing [src].", \
|
||||
"<span class='notice'>You begin repairing [src]...</span>", \
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
if(O.use_tool(src, user, 40, volume=50))
|
||||
if(!(stat & BROKEN))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You repair [src].</span>")
|
||||
stat &= ~BROKEN
|
||||
obj_integrity = max_integrity
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] does not need repairs.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pdapainter/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(!(stat & BROKEN))
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pdapainter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!storedpda)
|
||||
to_chat(user, "<span class='notice'>[src] is empty.</span>")
|
||||
return
|
||||
var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist
|
||||
if(!choice || !storedpda || !in_range(src, user))
|
||||
return
|
||||
var/list/P = colorlist[choice]
|
||||
storedpda.icon_state = P[1]
|
||||
storedpda.desc = P[2]
|
||||
storedpda.overlays_offsets = P[3]
|
||||
storedpda.overlays_icons = P[4]
|
||||
storedpda.set_new_overlays()
|
||||
storedpda.update_icon()
|
||||
ejectpda()
|
||||
|
||||
/obj/machinery/pdapainter/verb/ejectpda()
|
||||
set name = "Eject PDA"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
storedpda.forceMove(drop_location())
|
||||
storedpda = null
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>[src] is empty.</span>")
|
||||
|
||||
|
||||
/obj/machinery/pdapainter/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
+412
-412
@@ -1,412 +1,412 @@
|
||||
/obj/machinery/sleep_console
|
||||
name = "sleeper console"
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "console"
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/sleeper
|
||||
name = "sleeper"
|
||||
desc = "An enclosed machine used to stabilize and heal patients."
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "sleeper"
|
||||
density = FALSE
|
||||
state_open = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/sleeper
|
||||
req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines
|
||||
var/efficiency = 1
|
||||
var/min_health = -25
|
||||
var/list/available_chems
|
||||
var/controls_inside = FALSE
|
||||
var/list/possible_chems = list(
|
||||
list("epinephrine", "morphine", "salbutamol", "bicaridine", "kelotane"),
|
||||
list("oculine","inacusiate"),
|
||||
list("antitoxin", "mutadone", "mannitol", "pen_acid"),
|
||||
list("omnizine")
|
||||
)
|
||||
var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine
|
||||
var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning
|
||||
var/enter_message = "<span class='notice'><b>You feel cool air surround you. You go numb as your senses turn inward.</b></span>"
|
||||
|
||||
/obj/machinery/sleeper/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500, NO_REACT)
|
||||
occupant_typecache = GLOB.typecache_living
|
||||
update_icon()
|
||||
reset_chem_buttons()
|
||||
RefreshParts()
|
||||
add_inital_chems()
|
||||
|
||||
/obj/machinery/sleeper/on_deconstruction()
|
||||
var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc)
|
||||
buffer.volume = reagents.maximum_volume
|
||||
buffer.reagents.maximum_volume = reagents.maximum_volume
|
||||
reagents.trans_to(buffer.reagents, reagents.total_volume)
|
||||
|
||||
/obj/machinery/sleeper/proc/add_inital_chems()
|
||||
for(var/i in available_chems)
|
||||
var/datum/reagent/R = reagents.has_reagent(i)
|
||||
if(!R)
|
||||
reagents.add_reagent(i, (20))
|
||||
continue
|
||||
if(R.volume < 20)
|
||||
reagents.add_reagent(i, (20 - R.volume))
|
||||
|
||||
/obj/machinery/sleeper/RefreshParts()
|
||||
var/E
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
E += B.rating
|
||||
var/I
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
I += M.rating
|
||||
|
||||
efficiency = initial(efficiency)* E
|
||||
min_health = initial(min_health) - (10*(E-1)) // CIT CHANGE - changes min health equation to be min_health - (matterbin rating * 10)
|
||||
available_chems = list()
|
||||
for(var/i in 1 to I)
|
||||
available_chems |= possible_chems[i]
|
||||
reset_chem_buttons()
|
||||
|
||||
//Total container size 500 - 2000u
|
||||
if(reagents)
|
||||
reagents.maximum_volume = (500*E)
|
||||
|
||||
|
||||
/obj/machinery/sleeper/update_icon()
|
||||
icon_state = initial(icon_state)
|
||||
if(state_open)
|
||||
icon_state += "-open"
|
||||
|
||||
/obj/machinery/sleeper/container_resist(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/Exited(atom/movable/user)
|
||||
if (!state_open && user == occupant)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/sleeper/relaymove(mob/user)
|
||||
if (!state_open)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/sleeper/open_machine()
|
||||
if(!state_open && !panel_open)
|
||||
..()
|
||||
|
||||
/obj/machinery/sleeper/close_machine(mob/user)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "[enter_message]")
|
||||
|
||||
/obj/machinery/sleeper/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(is_operational() && occupant)
|
||||
var/datum/reagent/R = pick(reagents.reagent_list)
|
||||
inject_chem(R.id, occupant)
|
||||
open_machine()
|
||||
//Is this too much?
|
||||
if(severity == EMP_HEAVY)
|
||||
var/chem = pick(available_chems)
|
||||
available_chems -= chem
|
||||
available_chems += get_random_reagent_id()
|
||||
reset_chem_buttons()
|
||||
|
||||
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/reagent_containers/sleeper_buffer))
|
||||
var/obj/item/reagent_containers/sleeper_buffer/SB = I
|
||||
if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume)
|
||||
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
|
||||
visible_message("[user] places the [SB] into the [src].")
|
||||
qdel(SB)
|
||||
return
|
||||
else
|
||||
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
|
||||
visible_message("[user] adds as much as they can to the [src] from the [SB].")
|
||||
return
|
||||
if(istype(I, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/RC = I
|
||||
if(RC.reagents.total_volume == 0)
|
||||
to_chat(user, "<span class='notice'>The [I] is empty!</span>")
|
||||
for(var/datum/reagent/R in RC.reagents.reagent_list)
|
||||
if((obj_flags & EMAGGED) || (allowed(usr)))
|
||||
break
|
||||
if(!istype(R, /datum/reagent/medicine))
|
||||
visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"")
|
||||
return
|
||||
RC.reagents.trans_to(reagents, 1000)
|
||||
visible_message("[user] adds as much as they can to the [src] from the [I].")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(..())
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_pry_open(I))
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew
|
||||
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
|
||||
if(.)
|
||||
I.play_tool_sound(src, 50)
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
|
||||
if(controls_inside && state == GLOB.notcontained_state)
|
||||
state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it.
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/sleeper/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["efficiency"] = efficiency
|
||||
data["current_vol"] = reagents.total_volume
|
||||
data["tot_capacity"] = reagents.maximum_volume
|
||||
|
||||
data["chems"] = list()
|
||||
for(var/chem in available_chems)
|
||||
var/datum/reagent/R = reagents.has_reagent(chem)
|
||||
R = GLOB.chemical_reagents_list[chem]
|
||||
data["synthchems"] += list(list("name" = R.name, "id" = R.id, "synth_allowed" = synth_allowed(chem)))
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
data["chems"] += list(list("name" = R.name, "id" = R.id, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.id)))
|
||||
|
||||
data["occupant"] = list()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
data["occupant"]["name"] = mob_occupant.name
|
||||
switch(mob_occupant.stat)
|
||||
if(CONSCIOUS)
|
||||
data["occupant"]["stat"] = "Conscious"
|
||||
data["occupant"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["occupant"]["stat"] = "Conscious"
|
||||
data["occupant"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["occupant"]["stat"] = "Unconscious"
|
||||
data["occupant"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["occupant"]["stat"] = "Dead"
|
||||
data["occupant"]["statstate"] = "bad"
|
||||
data["occupant"]["health"] = mob_occupant.health
|
||||
data["occupant"]["maxHealth"] = mob_occupant.maxHealth
|
||||
data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss()
|
||||
data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss()
|
||||
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
|
||||
data["occupant"]["failing_organs"] = list()
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
if(C)
|
||||
for(var/obj/item/organ/Or in C.getFailingOrgans())
|
||||
if(istype(Or, /obj/item/organ/brain))
|
||||
continue
|
||||
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
|
||||
|
||||
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
|
||||
var/blood_id = C.get_blood_id()
|
||||
if(blood_id)
|
||||
data["occupant"]["blood"] = list() // We can start populating this list.
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(blood_id != "blood") // special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
else
|
||||
blood_type = blood_id
|
||||
data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio)
|
||||
data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume
|
||||
data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE
|
||||
data["occupant"]["blood"]["bloodType"] = blood_type
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
. = TRUE
|
||||
if("inject")
|
||||
var/chem = params["chem"]
|
||||
var/amount = text2num(params["volume"])
|
||||
if(!is_operational() || !mob_occupant)
|
||||
return
|
||||
if(mob_occupant.health < min_health && chem != "epinephrine")
|
||||
return
|
||||
if(inject_chem(chem, usr, amount))
|
||||
. = TRUE
|
||||
if(scrambled_chems && prob(5))
|
||||
to_chat(usr, "<span class='warning'>Chemical system re-route detected, results may not be as expected!</span>")
|
||||
if("synth")
|
||||
var/chem = params["chem"]
|
||||
if(!is_operational())
|
||||
return
|
||||
reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in
|
||||
if("purge")
|
||||
var/chem = params["chem"]
|
||||
if(allowed(usr))
|
||||
if(!is_operational())
|
||||
return
|
||||
reagents.remove_reagent(chem, 10)
|
||||
return
|
||||
if(chem in available_chems)
|
||||
if(!is_operational())
|
||||
return
|
||||
/*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
|
||||
if(R.purity < 0.8)*/
|
||||
reagents.remove_reagent(chem, 10)
|
||||
else
|
||||
visible_message("<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
|
||||
/obj/machinery/sleeper/emag_act(mob/user)
|
||||
. = ..()
|
||||
obj_flags |= EMAGGED
|
||||
scramble_chem_buttons()
|
||||
to_chat(user, "<span class='warning'>You scramble the sleeper's user interface!</span>")
|
||||
return TRUE
|
||||
|
||||
//trans to
|
||||
/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10)
|
||||
if(chem_allowed(chem))
|
||||
reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
|
||||
if(user)
|
||||
log_combat(user, occupant, "injected [chem] into", addition = "via [src]")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/proc/chem_allowed(chem)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(!mob_occupant || !mob_occupant.reagents)
|
||||
return
|
||||
var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
|
||||
var/occ_health = mob_occupant.health > min_health || chem == "epinephrine"
|
||||
return amount && occ_health
|
||||
|
||||
/obj/machinery/sleeper/proc/synth_allowed(chem)
|
||||
var/datum/reagent/R = reagents.has_reagent(chem)
|
||||
if(!R)
|
||||
return TRUE
|
||||
if(R.volume < 50)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/sleeper/proc/reset_chem_buttons()
|
||||
scrambled_chems = FALSE
|
||||
LAZYINITLIST(chem_buttons)
|
||||
for(var/chem in available_chems)
|
||||
chem_buttons[chem] = chem
|
||||
|
||||
/obj/machinery/sleeper/proc/scramble_chem_buttons()
|
||||
scrambled_chems = TRUE
|
||||
var/list/av_chem = available_chems.Copy()
|
||||
for(var/chem in av_chem)
|
||||
chem_buttons[chem] = pick_n_take(av_chem) //no dupes, allow for random buttons to still be correct
|
||||
|
||||
|
||||
/obj/machinery/sleeper/syndie
|
||||
icon_state = "sleeper_s"
|
||||
controls_inside = TRUE
|
||||
|
||||
/obj/machinery/sleeper/syndie/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/sleeper(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/super(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/pico(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/sleeper/syndie/fullupgrade/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/sleeper(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/sleeper/clockwork
|
||||
name = "soothing sleeper"
|
||||
desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."
|
||||
icon_state = "sleeper_clockwork"
|
||||
enter_message = "<span class='bold inathneq_small'>You hear the gentle hum and click of machinery, and are lulled into a sense of peace.</span>"
|
||||
possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol"))
|
||||
|
||||
/obj/machinery/sleeper/clockwork/process()
|
||||
if(occupant && isliving(occupant))
|
||||
var/mob/living/L = occupant
|
||||
if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing
|
||||
GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1)
|
||||
L.adjustBruteLoss(-1)
|
||||
L.adjustFireLoss(-1)
|
||||
L.adjustOxyLoss(-5)
|
||||
|
||||
/obj/machinery/sleeper/old
|
||||
icon_state = "oldpod"
|
||||
/obj/machinery/sleep_console
|
||||
name = "sleeper console"
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "console"
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/sleeper
|
||||
name = "sleeper"
|
||||
desc = "An enclosed machine used to stabilize and heal patients."
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "sleeper"
|
||||
density = FALSE
|
||||
state_open = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/sleeper
|
||||
req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines
|
||||
var/efficiency = 1
|
||||
var/min_health = 30
|
||||
var/list/available_chems
|
||||
var/controls_inside = FALSE
|
||||
var/list/possible_chems = list(
|
||||
list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/morphine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane),
|
||||
list(/datum/reagent/medicine/oculine,/datum/reagent/medicine/inacusiate),
|
||||
list(/datum/reagent/medicine/antitoxin, /datum/reagent/medicine/mutadone, /datum/reagent/medicine/mannitol, /datum/reagent/medicine/pen_acid),
|
||||
list(/datum/reagent/medicine/omnizine)
|
||||
)
|
||||
var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine
|
||||
var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning
|
||||
var/enter_message = "<span class='notice'><b>You feel cool air surround you. You go numb as your senses turn inward.</b></span>"
|
||||
|
||||
/obj/machinery/sleeper/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500, NO_REACT)
|
||||
occupant_typecache = GLOB.typecache_living
|
||||
update_icon()
|
||||
reset_chem_buttons()
|
||||
RefreshParts()
|
||||
add_inital_chems()
|
||||
|
||||
/obj/machinery/sleeper/on_deconstruction()
|
||||
var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc)
|
||||
buffer.volume = reagents.maximum_volume
|
||||
buffer.reagents.maximum_volume = reagents.maximum_volume
|
||||
reagents.trans_to(buffer.reagents, reagents.total_volume)
|
||||
|
||||
/obj/machinery/sleeper/proc/add_inital_chems()
|
||||
for(var/i in available_chems)
|
||||
var/datum/reagent/R = reagents.has_reagent(i)
|
||||
if(!R)
|
||||
reagents.add_reagent(i, (20))
|
||||
continue
|
||||
if(R.volume < 20)
|
||||
reagents.add_reagent(i, (20 - R.volume))
|
||||
|
||||
/obj/machinery/sleeper/RefreshParts()
|
||||
var/E
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
E += B.rating
|
||||
var/I
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
I += M.rating
|
||||
|
||||
efficiency = initial(efficiency)* E
|
||||
min_health = initial(min_health) - (10*(E-1)) // CIT CHANGE - changes min health equation to be min_health - (matterbin rating * 10)
|
||||
available_chems = list()
|
||||
for(var/i in 1 to I)
|
||||
available_chems |= possible_chems[i]
|
||||
reset_chem_buttons()
|
||||
|
||||
//Total container size 500 - 2000u
|
||||
if(reagents)
|
||||
reagents.maximum_volume = (500*E)
|
||||
|
||||
|
||||
/obj/machinery/sleeper/update_icon()
|
||||
icon_state = initial(icon_state)
|
||||
if(state_open)
|
||||
icon_state += "-open"
|
||||
|
||||
/obj/machinery/sleeper/container_resist(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/Exited(atom/movable/user)
|
||||
if (!state_open && user == occupant)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/sleeper/relaymove(mob/user)
|
||||
if (!state_open)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/sleeper/open_machine()
|
||||
if(!state_open && !panel_open)
|
||||
..()
|
||||
|
||||
/obj/machinery/sleeper/close_machine(mob/user)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "[enter_message]")
|
||||
|
||||
/obj/machinery/sleeper/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(is_operational() && occupant)
|
||||
var/datum/reagent/R = pick(reagents.reagent_list)
|
||||
inject_chem(R.type, occupant)
|
||||
open_machine()
|
||||
//Is this too much?
|
||||
if(severity == EMP_HEAVY)
|
||||
var/chem = pick(available_chems)
|
||||
available_chems -= chem
|
||||
available_chems += get_random_reagent_id()
|
||||
reset_chem_buttons()
|
||||
|
||||
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/reagent_containers/sleeper_buffer))
|
||||
var/obj/item/reagent_containers/sleeper_buffer/SB = I
|
||||
if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume)
|
||||
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
|
||||
visible_message("[user] places the [SB] into the [src].")
|
||||
qdel(SB)
|
||||
return
|
||||
else
|
||||
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
|
||||
visible_message("[user] adds as much as they can to the [src] from the [SB].")
|
||||
return
|
||||
if(istype(I, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/RC = I
|
||||
if(RC.reagents.total_volume == 0)
|
||||
to_chat(user, "<span class='notice'>The [I] is empty!</span>")
|
||||
for(var/datum/reagent/R in RC.reagents.reagent_list)
|
||||
if((obj_flags & EMAGGED) || (allowed(usr)))
|
||||
break
|
||||
if(!istype(R, /datum/reagent/medicine))
|
||||
visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"")
|
||||
return
|
||||
RC.reagents.trans_to(reagents, 1000)
|
||||
visible_message("[user] adds as much as they can to the [src] from the [I].")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(..())
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_pry_open(I))
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew
|
||||
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
|
||||
if(.)
|
||||
I.play_tool_sound(src, 50)
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
|
||||
if(controls_inside && state == GLOB.notcontained_state)
|
||||
state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it.
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/sleeper/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["efficiency"] = efficiency
|
||||
data["current_vol"] = reagents.total_volume
|
||||
data["tot_capacity"] = reagents.maximum_volume
|
||||
|
||||
data["chems"] = list()
|
||||
for(var/chem in available_chems)
|
||||
var/datum/reagent/R = reagents.has_reagent(chem)
|
||||
R = GLOB.chemical_reagents_list[chem]
|
||||
data["synthchems"] += list(list("name" = R.name, "id" = R.type, "synth_allowed" = synth_allowed(chem)))
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
data["chems"] += list(list("name" = R.name, "id" = R.type, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.type)))
|
||||
|
||||
data["occupant"] = list()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
data["occupant"]["name"] = mob_occupant.name
|
||||
switch(mob_occupant.stat)
|
||||
if(CONSCIOUS)
|
||||
data["occupant"]["stat"] = "Conscious"
|
||||
data["occupant"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["occupant"]["stat"] = "Conscious"
|
||||
data["occupant"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["occupant"]["stat"] = "Unconscious"
|
||||
data["occupant"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["occupant"]["stat"] = "Dead"
|
||||
data["occupant"]["statstate"] = "bad"
|
||||
data["occupant"]["health"] = mob_occupant.health
|
||||
data["occupant"]["maxHealth"] = mob_occupant.maxHealth
|
||||
data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss()
|
||||
data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss()
|
||||
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
|
||||
data["occupant"]["failing_organs"] = list()
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
if(C)
|
||||
for(var/obj/item/organ/Or in C.getFailingOrgans())
|
||||
if(istype(Or, /obj/item/organ/brain))
|
||||
continue
|
||||
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
|
||||
|
||||
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
|
||||
var/blood_id = C.get_blood_id()
|
||||
if(blood_id)
|
||||
data["occupant"]["blood"] = list() // We can start populating this list.
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(blood_id != "blood") // special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
else
|
||||
blood_type = blood_id
|
||||
data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio)
|
||||
data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume
|
||||
data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE
|
||||
data["occupant"]["blood"]["bloodType"] = blood_type
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
. = TRUE
|
||||
if("inject")
|
||||
var/chem = text2path(params["chem"])
|
||||
var/amount = text2num(params["volume"])
|
||||
if(!is_operational() || !mob_occupant || isnull(chem))
|
||||
return
|
||||
if(mob_occupant.health < min_health && chem != /datum/reagent/medicine/epinephrine)
|
||||
return
|
||||
if(inject_chem(chem, usr, amount))
|
||||
. = TRUE
|
||||
if(scrambled_chems && prob(5))
|
||||
to_chat(usr, "<span class='warning'>Chemical system re-route detected, results may not be as expected!</span>")
|
||||
if("synth")
|
||||
var/chem = text2path(params["chem"])
|
||||
if(!is_operational())
|
||||
return
|
||||
reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in
|
||||
if("purge")
|
||||
var/chem = text2path(params["chem"])
|
||||
if(allowed(usr))
|
||||
if(!is_operational())
|
||||
return
|
||||
reagents.remove_reagent(chem, 10)
|
||||
return
|
||||
if(chem in available_chems)
|
||||
if(!is_operational())
|
||||
return
|
||||
/*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
|
||||
if(R.purity < 0.8)*/
|
||||
reagents.remove_reagent(chem, 10)
|
||||
else
|
||||
visible_message("<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
|
||||
/obj/machinery/sleeper/emag_act(mob/user)
|
||||
. = ..()
|
||||
obj_flags |= EMAGGED
|
||||
scramble_chem_buttons()
|
||||
to_chat(user, "<span class='warning'>You scramble the sleeper's user interface!</span>")
|
||||
return TRUE
|
||||
|
||||
//trans to
|
||||
/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10)
|
||||
if(chem_allowed(chem))
|
||||
reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
|
||||
if(user)
|
||||
log_combat(user, occupant, "injected [chem] into", addition = "via [src]")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/proc/chem_allowed(chem)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(!mob_occupant || !mob_occupant.reagents)
|
||||
return
|
||||
var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
|
||||
var/occ_health = mob_occupant.health > min_health || chem == /datum/reagent/medicine/epinephrine
|
||||
return amount && occ_health
|
||||
|
||||
/obj/machinery/sleeper/proc/synth_allowed(chem)
|
||||
var/datum/reagent/R = reagents.has_reagent(chem)
|
||||
if(!R)
|
||||
return TRUE
|
||||
if(R.volume < 50)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/sleeper/proc/reset_chem_buttons()
|
||||
scrambled_chems = FALSE
|
||||
LAZYINITLIST(chem_buttons)
|
||||
for(var/chem in available_chems)
|
||||
chem_buttons[chem] = chem
|
||||
|
||||
/obj/machinery/sleeper/proc/scramble_chem_buttons()
|
||||
scrambled_chems = TRUE
|
||||
var/list/av_chem = available_chems.Copy()
|
||||
for(var/chem in av_chem)
|
||||
chem_buttons[chem] = pick_n_take(av_chem) //no dupes, allow for random buttons to still be correct
|
||||
|
||||
|
||||
/obj/machinery/sleeper/syndie
|
||||
icon_state = "sleeper_s"
|
||||
controls_inside = TRUE
|
||||
|
||||
/obj/machinery/sleeper/syndie/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/super(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/pico(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/sleeper/syndie/fullupgrade/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/sleeper/clockwork
|
||||
name = "soothing sleeper"
|
||||
desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."
|
||||
icon_state = "sleeper_clockwork"
|
||||
enter_message = "<span class='bold inathneq_small'>You hear the gentle hum and click of machinery, and are lulled into a sense of peace.</span>"
|
||||
possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol"))
|
||||
|
||||
/obj/machinery/sleeper/clockwork/process()
|
||||
if(occupant && isliving(occupant))
|
||||
var/mob/living/L = occupant
|
||||
if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing
|
||||
GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1)
|
||||
L.adjustBruteLoss(-1)
|
||||
L.adjustFireLoss(-1)
|
||||
L.adjustOxyLoss(-5)
|
||||
|
||||
/obj/machinery/sleeper/old
|
||||
icon_state = "oldpod"
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
/obj/machinery/ai_slipper
|
||||
name = "foam dispenser"
|
||||
desc = "A remotely-activatable dispenser for crowd-controlling foam."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "ai-slipper0"
|
||||
layer = PROJECTILE_HIT_THRESHHOLD_LAYER
|
||||
plane = FLOOR_PLANE
|
||||
max_integrity = 200
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
|
||||
|
||||
var/uses = 20
|
||||
var/cooldown = 0
|
||||
var/cooldown_time = 100
|
||||
req_access = list(ACCESS_AI_UPLOAD)
|
||||
|
||||
/obj/machinery/ai_slipper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>It has <b>[uses]</b> uses of foam remaining.</span>"
|
||||
|
||||
/obj/machinery/ai_slipper/power_change()
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
else
|
||||
if(powered())
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
if((stat & (NOPOWER|BROKEN)) || cooldown_time > world.time || !uses)
|
||||
icon_state = "ai-slipper0"
|
||||
else
|
||||
icon_state = "ai-slipper1"
|
||||
|
||||
/obj/machinery/ai_slipper/interact(mob/user)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
if(!uses)
|
||||
to_chat(user, "<span class='danger'>[src] is out of foam and cannot be activated.</span>")
|
||||
return
|
||||
if(cooldown_time > world.time)
|
||||
to_chat(user, "<span class='danger'>[src] cannot be activated for <b>[DisplayTimeText(world.time - cooldown_time)]</b>.</span>")
|
||||
return
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
uses--
|
||||
to_chat(user, "<span class='notice'>You activate [src]. It now has <b>[uses]</b> uses of foam remaining.</span>")
|
||||
cooldown = world.time + cooldown_time
|
||||
power_change()
|
||||
addtimer(CALLBACK(src, .proc/power_change), cooldown_time)
|
||||
/obj/machinery/ai_slipper
|
||||
name = "foam dispenser"
|
||||
desc = "A remotely-activatable dispenser for crowd-controlling foam."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "ai-slipper0"
|
||||
layer = PROJECTILE_HIT_THRESHHOLD_LAYER
|
||||
plane = FLOOR_PLANE
|
||||
max_integrity = 200
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
|
||||
|
||||
var/uses = 20
|
||||
var/cooldown = 0
|
||||
var/cooldown_time = 100
|
||||
req_access = list(ACCESS_AI_UPLOAD)
|
||||
|
||||
/obj/machinery/ai_slipper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>It has <b>[uses]</b> uses of foam remaining.</span>"
|
||||
|
||||
/obj/machinery/ai_slipper/power_change()
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
else
|
||||
if(powered())
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
if((stat & (NOPOWER|BROKEN)) || cooldown_time > world.time || !uses)
|
||||
icon_state = "ai-slipper0"
|
||||
else
|
||||
icon_state = "ai-slipper1"
|
||||
|
||||
/obj/machinery/ai_slipper/interact(mob/user)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
if(!uses)
|
||||
to_chat(user, "<span class='danger'>[src] is out of foam and cannot be activated.</span>")
|
||||
return
|
||||
if(cooldown_time > world.time)
|
||||
to_chat(user, "<span class='danger'>[src] cannot be activated for <b>[DisplayTimeText(world.time - cooldown_time)]</b>.</span>")
|
||||
return
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
uses--
|
||||
to_chat(user, "<span class='notice'>You activate [src]. It now has <b>[uses]</b> uses of foam remaining.</span>")
|
||||
cooldown = world.time + cooldown_time
|
||||
power_change()
|
||||
addtimer(CALLBACK(src, .proc/power_change), cooldown_time)
|
||||
|
||||
@@ -1,164 +1,164 @@
|
||||
#define AIRLOCK_CONTROL_RANGE 5
|
||||
|
||||
// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access)
|
||||
/obj/machinery/door/airlock
|
||||
var/id_tag
|
||||
var/frequency
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
if(id_tag != signal.data["tag"] || !signal.data["command"])
|
||||
return
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("open")
|
||||
open(1)
|
||||
|
||||
if("close")
|
||||
close(1)
|
||||
|
||||
if("unlock")
|
||||
locked = FALSE
|
||||
update_icon()
|
||||
|
||||
if("lock")
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
|
||||
if("secure_open")
|
||||
locked = FALSE
|
||||
update_icon()
|
||||
|
||||
sleep(2)
|
||||
open(1)
|
||||
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
|
||||
if("secure_close")
|
||||
locked = FALSE
|
||||
close(1)
|
||||
|
||||
locked = TRUE
|
||||
sleep(2)
|
||||
update_icon()
|
||||
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/proc/send_status()
|
||||
if(radio_connection)
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"door_status" = density ? "closed" : "open",
|
||||
"lock_status" = locked ? "locked" : "unlocked"
|
||||
))
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/open(surpress_send)
|
||||
. = ..()
|
||||
if(!surpress_send)
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/close(surpress_send)
|
||||
. = ..()
|
||||
if(!surpress_send)
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
if(new_frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
|
||||
|
||||
/obj/machinery/door/airlock/Destroy()
|
||||
if(frequency)
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/airlock_sensor
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_sensor_off"
|
||||
name = "airlock sensor"
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
power_channel = ENVIRON
|
||||
|
||||
var/id_tag
|
||||
var/master_tag
|
||||
var/frequency = FREQ_AIRLOCK_CONTROL
|
||||
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
var/on = TRUE
|
||||
var/alert = FALSE
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_toxmix
|
||||
id_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_atmos
|
||||
id_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_syndicatelava
|
||||
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/update_icon()
|
||||
if(on)
|
||||
if(alert)
|
||||
icon_state = "airlock_sensor_alert"
|
||||
else
|
||||
icon_state = "airlock_sensor_standby"
|
||||
else
|
||||
icon_state = "airlock_sensor_off"
|
||||
|
||||
/obj/machinery/airlock_sensor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = master_tag,
|
||||
"command" = "cycle"
|
||||
))
|
||||
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
flick("airlock_sensor_cycle", src)
|
||||
|
||||
/obj/machinery/airlock_sensor/process()
|
||||
if(on)
|
||||
var/datum/gas_mixture/air_sample = return_air()
|
||||
var/pressure = round(air_sample.return_pressure(),0.1)
|
||||
alert = (pressure < ONE_ATMOSPHERE*0.8)
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"pressure" = num2text(pressure)
|
||||
))
|
||||
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/airlock_sensor/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
|
||||
|
||||
/obj/machinery/airlock_sensor/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/airlock_sensor/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
#define AIRLOCK_CONTROL_RANGE 5
|
||||
|
||||
// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access)
|
||||
/obj/machinery/door/airlock
|
||||
var/id_tag
|
||||
var/frequency
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
if(id_tag != signal.data["tag"] || !signal.data["command"])
|
||||
return
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("open")
|
||||
open(1)
|
||||
|
||||
if("close")
|
||||
close(1)
|
||||
|
||||
if("unlock")
|
||||
locked = FALSE
|
||||
update_icon()
|
||||
|
||||
if("lock")
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
|
||||
if("secure_open")
|
||||
locked = FALSE
|
||||
update_icon()
|
||||
|
||||
sleep(2)
|
||||
open(1)
|
||||
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
|
||||
if("secure_close")
|
||||
locked = FALSE
|
||||
close(1)
|
||||
|
||||
locked = TRUE
|
||||
sleep(2)
|
||||
update_icon()
|
||||
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/proc/send_status()
|
||||
if(radio_connection)
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"door_status" = density ? "closed" : "open",
|
||||
"lock_status" = locked ? "locked" : "unlocked"
|
||||
))
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/open(surpress_send)
|
||||
. = ..()
|
||||
if(!surpress_send)
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/close(surpress_send)
|
||||
. = ..()
|
||||
if(!surpress_send)
|
||||
send_status()
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
if(new_frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
|
||||
|
||||
/obj/machinery/door/airlock/Destroy()
|
||||
if(frequency)
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/airlock_sensor
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_sensor_off"
|
||||
name = "airlock sensor"
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
power_channel = ENVIRON
|
||||
|
||||
var/id_tag
|
||||
var/master_tag
|
||||
var/frequency = FREQ_AIRLOCK_CONTROL
|
||||
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
var/on = TRUE
|
||||
var/alert = FALSE
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_toxmix
|
||||
id_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_atmos
|
||||
id_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/incinerator_syndicatelava
|
||||
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/update_icon()
|
||||
if(on)
|
||||
if(alert)
|
||||
icon_state = "airlock_sensor_alert"
|
||||
else
|
||||
icon_state = "airlock_sensor_standby"
|
||||
else
|
||||
icon_state = "airlock_sensor_off"
|
||||
|
||||
/obj/machinery/airlock_sensor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = master_tag,
|
||||
"command" = "cycle"
|
||||
))
|
||||
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
flick("airlock_sensor_cycle", src)
|
||||
|
||||
/obj/machinery/airlock_sensor/process()
|
||||
if(on)
|
||||
var/datum/gas_mixture/air_sample = return_air()
|
||||
var/pressure = round(air_sample.return_pressure(),0.1)
|
||||
alert = (pressure < ONE_ATMOSPHERE*0.8)
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"pressure" = num2text(pressure)
|
||||
))
|
||||
|
||||
radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/airlock_sensor/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK)
|
||||
|
||||
/obj/machinery/airlock_sensor/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/airlock_sensor/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
+382
-382
@@ -1,383 +1,383 @@
|
||||
#define AUTOLATHE_MAIN_MENU 1
|
||||
#define AUTOLATHE_CATEGORY_MENU 2
|
||||
#define AUTOLATHE_SEARCH_MENU 3
|
||||
|
||||
/obj/machinery/autolathe
|
||||
name = "autolathe"
|
||||
desc = "It produces items using metal and glass."
|
||||
icon_state = "autolathe"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
circuit = /obj/item/circuitboard/machine/autolathe
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
var/operating = FALSE
|
||||
var/list/L = list()
|
||||
var/list/LL = list()
|
||||
var/hacked = FALSE
|
||||
var/disabled = 0
|
||||
var/shocked = FALSE
|
||||
var/hack_wire
|
||||
var/disable_wire
|
||||
var/shock_wire
|
||||
|
||||
var/busy = FALSE
|
||||
var/prod_coeff = 1
|
||||
|
||||
var/datum/design/being_built
|
||||
var/datum/techweb/stored_research
|
||||
var/list/datum/design/matching_designs
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
|
||||
var/list/categories = list(
|
||||
"Tools",
|
||||
"Electronics",
|
||||
"Construction",
|
||||
"T-Comm",
|
||||
"Security",
|
||||
"Machinery",
|
||||
"Medical",
|
||||
"Misc",
|
||||
"Dinnerware",
|
||||
"Imported"
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
|
||||
matching_designs = list()
|
||||
|
||||
/obj/machinery/autolathe/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
|
||||
var/dat
|
||||
|
||||
switch(screen)
|
||||
if(AUTOLATHE_MAIN_MENU)
|
||||
dat = main_win(user)
|
||||
if(AUTOLATHE_CATEGORY_MENU)
|
||||
dat = category_win(user,selected_category)
|
||||
if(AUTOLATHE_SEARCH_MENU)
|
||||
dat = search_win(user)
|
||||
|
||||
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/autolathe/on_deconstruction()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
|
||||
/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The autolathe is busy. Please wait for completion of previous operation.</span>")
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O))
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_crowbar(O))
|
||||
return TRUE
|
||||
|
||||
if(panel_open && is_wire_tool(O))
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
|
||||
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
if(stat)
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/disk/design_disk))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a design from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
busy = TRUE
|
||||
var/obj/item/disk/design_disk/D = O
|
||||
if(do_after(user, 14.4, target = src))
|
||||
for(var/B in D.blueprints)
|
||||
if(B)
|
||||
stored_research.add_design(B)
|
||||
busy = FALSE
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
|
||||
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else
|
||||
switch(id_inserted)
|
||||
if (MAT_METAL)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
if (MAT_GLASS)
|
||||
flick("autolathe_r",src)//plays glass insertion animation
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/autolathe/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if (!busy)
|
||||
if(href_list["menu"])
|
||||
screen = text2num(href_list["menu"])
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["category"])
|
||||
selected_category = href_list["category"]
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["make"])
|
||||
|
||||
/////////////////
|
||||
//href protection
|
||||
being_built = stored_research.isDesignResearchedID(href_list["make"])
|
||||
if(!being_built)
|
||||
return
|
||||
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
|
||||
multiplier = CLAMP(multiplier,1,50)
|
||||
|
||||
/////////////////
|
||||
|
||||
var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
|
||||
var/metal_cost = being_built.materials[MAT_METAL]
|
||||
var/glass_cost = being_built.materials[MAT_GLASS]
|
||||
|
||||
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
icon_state = "autolathe_n"
|
||||
var/time = is_stack ? 32 : 32*coeff*multiplier
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time)
|
||||
|
||||
if(href_list["search"])
|
||||
matching_designs.Cut()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(findtext(D.name,href_list["to_search"]))
|
||||
matching_designs.Add(D)
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The autolathe is busy. Please wait for completion of previous operation.</span>")
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/atom/A = drop_location()
|
||||
use_power(power)
|
||||
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
|
||||
materials.use_amount(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
|
||||
N.update_icon()
|
||||
N.autolathe_crafted(src)
|
||||
else
|
||||
for(var/i=1, i<=multiplier, i++)
|
||||
var/obj/item/new_item = new being_built.build_path(A)
|
||||
new_item.materials = new_item.materials.Copy()
|
||||
for(var/mat in materials_used)
|
||||
new_item.materials[mat] = materials_used[mat] / multiplier
|
||||
new_item.autolathe_crafted(src)
|
||||
icon_state = "autolathe"
|
||||
busy = FALSE
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/autolathe/RefreshParts()
|
||||
var/T = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
|
||||
T += MB.rating*75000
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = T
|
||||
T=1.2
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T -= M.rating*0.2
|
||||
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
|
||||
|
||||
/obj/machinery/autolathe/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Autolathe Menu:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
dat += "<form name='search' action='?src=[REF(src)]'>\
|
||||
<input type='hidden' name='src' value='[REF(src)]'>\
|
||||
<input type='hidden' name='search' value='to_search'>\
|
||||
<input type='hidden' name='menu' value='[AUTOLATHE_SEARCH_MENU]'>\
|
||||
<input type='text' name='to_search'>\
|
||||
<input type='submit' value='Search'>\
|
||||
</form><hr>"
|
||||
|
||||
var/line_length = 1
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
|
||||
for(var/C in categories)
|
||||
if(line_length > 2)
|
||||
dat += "</tr><tr>"
|
||||
line_length = 1
|
||||
|
||||
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[AUTOLATHE_CATEGORY_MENU]'>[C]</A></td>"
|
||||
line_length++
|
||||
|
||||
dat += "</tr></table></div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/category_win(mob/user,selected_category)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(!(selected_category in D.category))
|
||||
continue
|
||||
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
else
|
||||
if(!disabled && can_build(D, 5))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=5'>x5</a>"
|
||||
if(!disabled && can_build(D, 10))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/search_win(mob/user)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Search results:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in matching_designs)
|
||||
var/datum/design/D = v
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/materials_printout()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
dat += "<b>[M.name] amount:</b> [M.amount] cm<sup>3</sup><br>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1)
|
||||
if(D.make_reagents.len)
|
||||
return FALSE
|
||||
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
|
||||
return FALSE
|
||||
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
var/dat
|
||||
if(D.materials[MAT_METAL])
|
||||
dat += "[D.materials[MAT_METAL] * coeff] metal "
|
||||
if(D.materials[MAT_GLASS])
|
||||
dat += "[D.materials[MAT_GLASS] * coeff] glass"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/reset(wire)
|
||||
switch(wire)
|
||||
if(WIRE_HACK)
|
||||
if(!wires.is_cut(wire))
|
||||
adjust_hacked(FALSE)
|
||||
if(WIRE_SHOCK)
|
||||
if(!wires.is_cut(wire))
|
||||
shocked = FALSE
|
||||
if(WIRE_DISABLE)
|
||||
if(!wires.is_cut(wire))
|
||||
disabled = FALSE
|
||||
|
||||
/obj/machinery/autolathe/proc/shock(mob/user, prb)
|
||||
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
||||
return FALSE
|
||||
if(!prob(prb))
|
||||
return FALSE
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/autolathe/proc/adjust_hacked(state)
|
||||
hacked = state
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
|
||||
if(hacked)
|
||||
stored_research.add_design(D)
|
||||
else
|
||||
stored_research.remove_design(D)
|
||||
|
||||
/obj/machinery/autolathe/hacked/Initialize()
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
|
||||
//Called when the object is constructed by an autolathe
|
||||
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
||||
#define AUTOLATHE_MAIN_MENU 1
|
||||
#define AUTOLATHE_CATEGORY_MENU 2
|
||||
#define AUTOLATHE_SEARCH_MENU 3
|
||||
|
||||
/obj/machinery/autolathe
|
||||
name = "autolathe"
|
||||
desc = "It produces items using metal and glass."
|
||||
icon_state = "autolathe"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
circuit = /obj/item/circuitboard/machine/autolathe
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
var/operating = FALSE
|
||||
var/list/L = list()
|
||||
var/list/LL = list()
|
||||
var/hacked = FALSE
|
||||
var/disabled = 0
|
||||
var/shocked = FALSE
|
||||
var/hack_wire
|
||||
var/disable_wire
|
||||
var/shock_wire
|
||||
|
||||
var/busy = FALSE
|
||||
var/prod_coeff = 1
|
||||
|
||||
var/datum/design/being_built
|
||||
var/datum/techweb/stored_research
|
||||
var/list/datum/design/matching_designs
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
|
||||
var/list/categories = list(
|
||||
"Tools",
|
||||
"Electronics",
|
||||
"Construction",
|
||||
"T-Comm",
|
||||
"Security",
|
||||
"Machinery",
|
||||
"Medical",
|
||||
"Misc",
|
||||
"Dinnerware",
|
||||
"Imported"
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
|
||||
matching_designs = list()
|
||||
|
||||
/obj/machinery/autolathe/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
|
||||
var/dat
|
||||
|
||||
switch(screen)
|
||||
if(AUTOLATHE_MAIN_MENU)
|
||||
dat = main_win(user)
|
||||
if(AUTOLATHE_CATEGORY_MENU)
|
||||
dat = category_win(user,selected_category)
|
||||
if(AUTOLATHE_SEARCH_MENU)
|
||||
dat = search_win(user)
|
||||
|
||||
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/autolathe/on_deconstruction()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
|
||||
/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The autolathe is busy. Please wait for completion of previous operation.</span>")
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O))
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_crowbar(O))
|
||||
return TRUE
|
||||
|
||||
if(panel_open && is_wire_tool(O))
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
|
||||
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
if(stat)
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/disk/design_disk))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a design from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
busy = TRUE
|
||||
var/obj/item/disk/design_disk/D = O
|
||||
if(do_after(user, 14.4, target = src))
|
||||
for(var/B in D.blueprints)
|
||||
if(B)
|
||||
stored_research.add_design(B)
|
||||
busy = FALSE
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
|
||||
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else
|
||||
switch(id_inserted)
|
||||
if (MAT_METAL)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
if (MAT_GLASS)
|
||||
flick("autolathe_r",src)//plays glass insertion animation
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/autolathe/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if (!busy)
|
||||
if(href_list["menu"])
|
||||
screen = text2num(href_list["menu"])
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["category"])
|
||||
selected_category = href_list["category"]
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["make"])
|
||||
|
||||
/////////////////
|
||||
//href protection
|
||||
being_built = stored_research.isDesignResearchedID(href_list["make"])
|
||||
if(!being_built)
|
||||
return
|
||||
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
|
||||
multiplier = CLAMP(multiplier,1,50)
|
||||
|
||||
/////////////////
|
||||
|
||||
var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
|
||||
var/metal_cost = being_built.materials[MAT_METAL]
|
||||
var/glass_cost = being_built.materials[MAT_GLASS]
|
||||
|
||||
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
icon_state = "autolathe_n"
|
||||
var/time = is_stack ? 32 : 32*coeff*multiplier
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time)
|
||||
|
||||
if(href_list["search"])
|
||||
matching_designs.Cut()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(findtext(D.name,href_list["to_search"]))
|
||||
matching_designs.Add(D)
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The autolathe is busy. Please wait for completion of previous operation.</span>")
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/atom/A = drop_location()
|
||||
use_power(power)
|
||||
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
|
||||
materials.use_amount(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
|
||||
N.update_icon()
|
||||
N.autolathe_crafted(src)
|
||||
else
|
||||
for(var/i=1, i<=multiplier, i++)
|
||||
var/obj/item/new_item = new being_built.build_path(A)
|
||||
new_item.materials = new_item.materials.Copy()
|
||||
for(var/mat in materials_used)
|
||||
new_item.materials[mat] = materials_used[mat] / multiplier
|
||||
new_item.autolathe_crafted(src)
|
||||
icon_state = "autolathe"
|
||||
busy = FALSE
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/autolathe/RefreshParts()
|
||||
var/T = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
|
||||
T += MB.rating*75000
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = T
|
||||
T=1.2
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T -= M.rating*0.2
|
||||
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
|
||||
|
||||
/obj/machinery/autolathe/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Autolathe Menu:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
dat += "<form name='search' action='?src=[REF(src)]'>\
|
||||
<input type='hidden' name='src' value='[REF(src)]'>\
|
||||
<input type='hidden' name='search' value='to_search'>\
|
||||
<input type='hidden' name='menu' value='[AUTOLATHE_SEARCH_MENU]'>\
|
||||
<input type='text' name='to_search'>\
|
||||
<input type='submit' value='Search'>\
|
||||
</form><hr>"
|
||||
|
||||
var/line_length = 1
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
|
||||
for(var/C in categories)
|
||||
if(line_length > 2)
|
||||
dat += "</tr><tr>"
|
||||
line_length = 1
|
||||
|
||||
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[AUTOLATHE_CATEGORY_MENU]'>[C]</A></td>"
|
||||
line_length++
|
||||
|
||||
dat += "</tr></table></div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/category_win(mob/user,selected_category)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(!(selected_category in D.category))
|
||||
continue
|
||||
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
else
|
||||
if(!disabled && can_build(D, 5))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=5'>x5</a>"
|
||||
if(!disabled && can_build(D, 10))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/search_win(mob/user)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Search results:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in matching_designs)
|
||||
var/datum/design/D = v
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/materials_printout()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
dat += "<b>[M.name] amount:</b> [M.amount] cm<sup>3</sup><br>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1)
|
||||
if(D.make_reagents.len)
|
||||
return FALSE
|
||||
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
|
||||
return FALSE
|
||||
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
var/dat
|
||||
if(D.materials[MAT_METAL])
|
||||
dat += "[D.materials[MAT_METAL] * coeff] metal "
|
||||
if(D.materials[MAT_GLASS])
|
||||
dat += "[D.materials[MAT_GLASS] * coeff] glass"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/reset(wire)
|
||||
switch(wire)
|
||||
if(WIRE_HACK)
|
||||
if(!wires.is_cut(wire))
|
||||
adjust_hacked(FALSE)
|
||||
if(WIRE_SHOCK)
|
||||
if(!wires.is_cut(wire))
|
||||
shocked = FALSE
|
||||
if(WIRE_DISABLE)
|
||||
if(!wires.is_cut(wire))
|
||||
disabled = FALSE
|
||||
|
||||
/obj/machinery/autolathe/proc/shock(mob/user, prb)
|
||||
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
||||
return FALSE
|
||||
if(!prob(prb))
|
||||
return FALSE
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/autolathe/proc/adjust_hacked(state)
|
||||
hacked = state
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
|
||||
if(hacked)
|
||||
stored_research.add_design(D)
|
||||
else
|
||||
stored_research.remove_design(D)
|
||||
|
||||
/obj/machinery/autolathe/hacked/Initialize()
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
|
||||
//Called when the object is constructed by an autolathe
|
||||
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
||||
return
|
||||
@@ -123,15 +123,15 @@
|
||||
if(reagents.total_volume >= reagents.maximum_volume || !bag || !bag.reagents.total_volume)
|
||||
beep_stop_pumping()
|
||||
return
|
||||
var/blood_amount = bag.reagents.get_reagent_amount("blood")
|
||||
var/blood_amount = bag.reagents.get_reagent_amount(/datum/reagent/blood)
|
||||
//monitor the machine and blood bag's reagents storage.
|
||||
var/amount = min(blood_amount, min(transfer_amount, reagents.maximum_volume - reagents.total_volume))
|
||||
if(!amount)
|
||||
beep_stop_pumping()
|
||||
return
|
||||
var/bonus = bag.blood_type == "SY" ? 0 : 5 * efficiency //no infinite loops using synthetics.
|
||||
reagents.add_reagent("syntheticblood", amount + bonus)
|
||||
bag.reagents.remove_reagent("blood", amount)
|
||||
reagents.add_reagent(/datum/reagent/blood/synthetics, amount + bonus)
|
||||
bag.reagents.remove_reagent(/datum/reagent/blood, amount)
|
||||
update_icon()
|
||||
|
||||
if(filling)
|
||||
|
||||
+268
-268
@@ -1,268 +1,268 @@
|
||||
/obj/machinery/button
|
||||
name = "button"
|
||||
desc = "A remote control switch."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "doorctrl"
|
||||
var/skin = "doorctrl"
|
||||
power_channel = ENVIRON
|
||||
var/obj/item/assembly/device
|
||||
var/obj/item/electronics/airlock/board
|
||||
var/device_type = null
|
||||
var/id = null
|
||||
var/initialized_button = 0
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 70)
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
|
||||
. = ..()
|
||||
if(built)
|
||||
setDir(ndir)
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
|
||||
panel_open = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
if(!built && !device && device_type)
|
||||
device = new device_type(src)
|
||||
|
||||
src.check_access(null)
|
||||
|
||||
if(req_access.len || req_one_access.len)
|
||||
board = new(src)
|
||||
if(req_access.len)
|
||||
board.accesses = req_access
|
||||
else
|
||||
board.one_access = 1
|
||||
board.accesses = req_one_access
|
||||
|
||||
/obj/machinery/button/update_icon_state()
|
||||
if(panel_open)
|
||||
icon_state = "button-open"
|
||||
else if(stat & (NOPOWER|BROKEN))
|
||||
icon_state = "[skin]-p"
|
||||
else
|
||||
icon_state = skin
|
||||
|
||||
/obj/machinery/button/update_overlays()
|
||||
. = ..()
|
||||
if(!panel_open)
|
||||
return
|
||||
if(device)
|
||||
. += "button-device"
|
||||
if(board)
|
||||
. += "button-board"
|
||||
|
||||
/obj/machinery/button/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(panel_open || allowed(user))
|
||||
default_deconstruction_screwdriver(user, "button-open", "[skin]",W)
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Maintenance Access Denied</span>")
|
||||
flick("[skin]-denied", src)
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
if(!device && istype(W, /obj/item/assembly))
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to you!</span>")
|
||||
return
|
||||
device = W
|
||||
to_chat(user, "<span class='notice'>You add [W] to the button.</span>")
|
||||
|
||||
if(!board && istype(W, /obj/item/electronics/airlock))
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to you!</span>")
|
||||
return
|
||||
board = W
|
||||
if(board.one_access)
|
||||
req_one_access = board.accesses
|
||||
else
|
||||
req_access = board.accesses
|
||||
to_chat(user, "<span class='notice'>You add [W] to the button.</span>")
|
||||
|
||||
if(!device && !board && istype(W, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start unsecuring the button frame...</span>")
|
||||
W.play_tool_sound(src)
|
||||
if(W.use_tool(src, user, 40))
|
||||
to_chat(user, "<span class='notice'>You unsecure the button frame.</span>")
|
||||
transfer_fingerprints_to(new /obj/item/wallframe/button(get_turf(src)))
|
||||
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
qdel(src)
|
||||
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON))
|
||||
return attack_hand(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/button/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
playsound(src, "sparks", 100, 1)
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/button/attack_ai(mob/user)
|
||||
if(!panel_open)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/button/attack_robot(mob/user)
|
||||
return attack_ai(user)
|
||||
|
||||
/obj/machinery/button/proc/setup_device()
|
||||
if(id && istype(device, /obj/item/assembly/control))
|
||||
var/obj/item/assembly/control/A = device
|
||||
A.id = id
|
||||
initialized_button = 1
|
||||
|
||||
/obj/machinery/button/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!initialized_button)
|
||||
setup_device()
|
||||
add_fingerprint(user)
|
||||
if(panel_open)
|
||||
if(device || board)
|
||||
if(device)
|
||||
device.forceMove(drop_location())
|
||||
device = null
|
||||
if(board)
|
||||
board.forceMove(drop_location())
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
board = null
|
||||
update_icon()
|
||||
to_chat(user, "<span class='notice'>You remove electronics from the button frame.</span>")
|
||||
|
||||
else
|
||||
if(skin == "doorctrl")
|
||||
skin = "launcher"
|
||||
else
|
||||
skin = "doorctrl"
|
||||
to_chat(user, "<span class='notice'>You change the button frame's front panel.</span>")
|
||||
return
|
||||
|
||||
if((stat & (NOPOWER|BROKEN)))
|
||||
return
|
||||
|
||||
if(device && device.next_activate > world.time)
|
||||
return
|
||||
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='danger'>Access Denied</span>")
|
||||
flick("[skin]-denied", src)
|
||||
return
|
||||
|
||||
use_power(5)
|
||||
icon_state = "[skin]1"
|
||||
|
||||
if(device)
|
||||
device.pulsed()
|
||||
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 15)
|
||||
|
||||
/obj/machinery/button/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/button/door
|
||||
name = "door button"
|
||||
desc = "A door remote control switch."
|
||||
var/normaldoorcontrol = FALSE
|
||||
var/specialfunctions = OPEN // Bitflag, see assembly file
|
||||
|
||||
/obj/machinery/button/door/setup_device()
|
||||
if(!device)
|
||||
if(normaldoorcontrol)
|
||||
var/obj/item/assembly/control/airlock/A = new(src)
|
||||
device = A
|
||||
A.specialfunctions = specialfunctions
|
||||
else
|
||||
device = new /obj/item/assembly/control(src)
|
||||
..()
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_toxmix
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_TOXMIX_VENT
|
||||
req_access = list(ACCESS_TOX)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_atmos_main
|
||||
name = "turbine vent control"
|
||||
id = INCINERATOR_ATMOS_MAINVENT
|
||||
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_atmos_aux
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_ATMOS_AUXVENT
|
||||
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_syndicatelava_main
|
||||
name = "turbine vent control"
|
||||
id = INCINERATOR_SYNDICATELAVA_MAINVENT
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_syndicatelava_aux
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_SYNDICATELAVA_AUXVENT
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/button/massdriver
|
||||
name = "mass driver button"
|
||||
desc = "A remote control switch for a mass driver."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/massdriver
|
||||
|
||||
/obj/machinery/button/ignition
|
||||
name = "ignition switch"
|
||||
desc = "A remote control switch for a mounted igniter."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/igniter
|
||||
|
||||
/obj/machinery/button/ignition/incinerator
|
||||
name = "combustion chamber ignition switch"
|
||||
desc = "A remote control switch for the combustion chamber's igniter."
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/atmos
|
||||
id = INCINERATOR_ATMOS_IGNITER
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/syndicatelava
|
||||
id = INCINERATOR_SYNDICATELAVA_IGNITER
|
||||
|
||||
/obj/machinery/button/flasher
|
||||
name = "flasher button"
|
||||
desc = "A remote control switch for a mounted flasher."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/flasher
|
||||
|
||||
/obj/machinery/button/crematorium
|
||||
name = "crematorium igniter"
|
||||
desc = "Burn baby burn!"
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/crematorium
|
||||
req_access = list()
|
||||
id = 1
|
||||
|
||||
/obj/item/wallframe/button
|
||||
name = "button frame"
|
||||
desc = "Used for building buttons."
|
||||
icon_state = "button"
|
||||
result_path = /obj/machinery/button
|
||||
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
|
||||
/obj/machinery/button
|
||||
name = "button"
|
||||
desc = "A remote control switch."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "doorctrl"
|
||||
var/skin = "doorctrl"
|
||||
power_channel = ENVIRON
|
||||
var/obj/item/assembly/device
|
||||
var/obj/item/electronics/airlock/board
|
||||
var/device_type = null
|
||||
var/id = null
|
||||
var/initialized_button = 0
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 70)
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
|
||||
. = ..()
|
||||
if(built)
|
||||
setDir(ndir)
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
|
||||
panel_open = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
if(!built && !device && device_type)
|
||||
device = new device_type(src)
|
||||
|
||||
src.check_access(null)
|
||||
|
||||
if(req_access.len || req_one_access.len)
|
||||
board = new(src)
|
||||
if(req_access.len)
|
||||
board.accesses = req_access
|
||||
else
|
||||
board.one_access = 1
|
||||
board.accesses = req_one_access
|
||||
|
||||
/obj/machinery/button/update_icon_state()
|
||||
if(panel_open)
|
||||
icon_state = "button-open"
|
||||
else if(stat & (NOPOWER|BROKEN))
|
||||
icon_state = "[skin]-p"
|
||||
else
|
||||
icon_state = skin
|
||||
|
||||
/obj/machinery/button/update_overlays()
|
||||
. = ..()
|
||||
if(!panel_open)
|
||||
return
|
||||
if(device)
|
||||
. += "button-device"
|
||||
if(board)
|
||||
. += "button-board"
|
||||
|
||||
/obj/machinery/button/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(panel_open || allowed(user))
|
||||
default_deconstruction_screwdriver(user, "button-open", "[skin]",W)
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Maintenance Access Denied</span>")
|
||||
flick("[skin]-denied", src)
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
if(!device && istype(W, /obj/item/assembly))
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to you!</span>")
|
||||
return
|
||||
device = W
|
||||
to_chat(user, "<span class='notice'>You add [W] to the button.</span>")
|
||||
|
||||
if(!board && istype(W, /obj/item/electronics/airlock))
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to you!</span>")
|
||||
return
|
||||
board = W
|
||||
if(board.one_access)
|
||||
req_one_access = board.accesses
|
||||
else
|
||||
req_access = board.accesses
|
||||
to_chat(user, "<span class='notice'>You add [W] to the button.</span>")
|
||||
|
||||
if(!device && !board && istype(W, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start unsecuring the button frame...</span>")
|
||||
W.play_tool_sound(src)
|
||||
if(W.use_tool(src, user, 40))
|
||||
to_chat(user, "<span class='notice'>You unsecure the button frame.</span>")
|
||||
transfer_fingerprints_to(new /obj/item/wallframe/button(get_turf(src)))
|
||||
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
qdel(src)
|
||||
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON))
|
||||
return attack_hand(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/button/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
playsound(src, "sparks", 100, 1)
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/button/attack_ai(mob/user)
|
||||
if(!panel_open)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/button/attack_robot(mob/user)
|
||||
return attack_ai(user)
|
||||
|
||||
/obj/machinery/button/proc/setup_device()
|
||||
if(id && istype(device, /obj/item/assembly/control))
|
||||
var/obj/item/assembly/control/A = device
|
||||
A.id = id
|
||||
initialized_button = 1
|
||||
|
||||
/obj/machinery/button/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!initialized_button)
|
||||
setup_device()
|
||||
add_fingerprint(user)
|
||||
if(panel_open)
|
||||
if(device || board)
|
||||
if(device)
|
||||
device.forceMove(drop_location())
|
||||
device = null
|
||||
if(board)
|
||||
board.forceMove(drop_location())
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
board = null
|
||||
update_icon()
|
||||
to_chat(user, "<span class='notice'>You remove electronics from the button frame.</span>")
|
||||
|
||||
else
|
||||
if(skin == "doorctrl")
|
||||
skin = "launcher"
|
||||
else
|
||||
skin = "doorctrl"
|
||||
to_chat(user, "<span class='notice'>You change the button frame's front panel.</span>")
|
||||
return
|
||||
|
||||
if((stat & (NOPOWER|BROKEN)))
|
||||
return
|
||||
|
||||
if(device && device.next_activate > world.time)
|
||||
return
|
||||
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='danger'>Access Denied</span>")
|
||||
flick("[skin]-denied", src)
|
||||
return
|
||||
|
||||
use_power(5)
|
||||
icon_state = "[skin]1"
|
||||
|
||||
if(device)
|
||||
device.pulsed()
|
||||
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 15)
|
||||
|
||||
/obj/machinery/button/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/button/door
|
||||
name = "door button"
|
||||
desc = "A door remote control switch."
|
||||
var/normaldoorcontrol = FALSE
|
||||
var/specialfunctions = OPEN // Bitflag, see assembly file
|
||||
|
||||
/obj/machinery/button/door/setup_device()
|
||||
if(!device)
|
||||
if(normaldoorcontrol)
|
||||
var/obj/item/assembly/control/airlock/A = new(src)
|
||||
device = A
|
||||
A.specialfunctions = specialfunctions
|
||||
else
|
||||
device = new /obj/item/assembly/control(src)
|
||||
..()
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_toxmix
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_TOXMIX_VENT
|
||||
req_access = list(ACCESS_TOX)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_atmos_main
|
||||
name = "turbine vent control"
|
||||
id = INCINERATOR_ATMOS_MAINVENT
|
||||
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_atmos_aux
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_ATMOS_AUXVENT
|
||||
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_syndicatelava_main
|
||||
name = "turbine vent control"
|
||||
id = INCINERATOR_SYNDICATELAVA_MAINVENT
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/button/door/incinerator_vent_syndicatelava_aux
|
||||
name = "combustion chamber vent control"
|
||||
id = INCINERATOR_SYNDICATELAVA_AUXVENT
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/button/massdriver
|
||||
name = "mass driver button"
|
||||
desc = "A remote control switch for a mass driver."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/massdriver
|
||||
|
||||
/obj/machinery/button/ignition
|
||||
name = "ignition switch"
|
||||
desc = "A remote control switch for a mounted igniter."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/igniter
|
||||
|
||||
/obj/machinery/button/ignition/incinerator
|
||||
name = "combustion chamber ignition switch"
|
||||
desc = "A remote control switch for the combustion chamber's igniter."
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/atmos
|
||||
id = INCINERATOR_ATMOS_IGNITER
|
||||
|
||||
/obj/machinery/button/ignition/incinerator/syndicatelava
|
||||
id = INCINERATOR_SYNDICATELAVA_IGNITER
|
||||
|
||||
/obj/machinery/button/flasher
|
||||
name = "flasher button"
|
||||
desc = "A remote control switch for a mounted flasher."
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/flasher
|
||||
|
||||
/obj/machinery/button/crematorium
|
||||
name = "crematorium igniter"
|
||||
desc = "Burn baby burn!"
|
||||
icon_state = "launcher"
|
||||
skin = "launcher"
|
||||
device_type = /obj/item/assembly/control/crematorium
|
||||
req_access = list()
|
||||
id = 1
|
||||
|
||||
/obj/item/wallframe/button
|
||||
name = "button frame"
|
||||
desc = "Used for building buttons."
|
||||
icon_state = "button"
|
||||
result_path = /obj/machinery/button
|
||||
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
/obj/item/wallframe/camera
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/machines/camera.dmi'
|
||||
icon_state = "cameracase"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=250)
|
||||
result_path = /obj/structure/camera_assembly
|
||||
|
||||
|
||||
/obj/structure/camera_assembly
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/machines/camera.dmi'
|
||||
icon_state = "camera1"
|
||||
max_integrity = 150
|
||||
// Motion, EMP-Proof, X-ray
|
||||
var/static/list/possible_upgrades = typecacheof(list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer))
|
||||
var/list/upgrades
|
||||
var/state = 1
|
||||
|
||||
/*
|
||||
1 = Wrenched in place
|
||||
2 = Welded in place
|
||||
3 = Wires attached to it (you can now attach/dettach upgrades)
|
||||
4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
|
||||
*/
|
||||
|
||||
/obj/structure/camera_assembly/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
upgrades = list()
|
||||
|
||||
/obj/structure/camera_assembly/Destroy()
|
||||
QDEL_LIST(upgrades)
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
// State 1
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You weld the assembly securely into place.</span>")
|
||||
setAnchored(TRUE)
|
||||
state = 2
|
||||
return
|
||||
if(2)
|
||||
// State 2
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if(C.use(2))
|
||||
to_chat(user, "<span class='notice'>You add wires to the assembly.</span>")
|
||||
state = 3
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two lengths of cable to wire a camera!</span>")
|
||||
return
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weldingtool))
|
||||
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You unweld the assembly from its place.</span>")
|
||||
state = 1
|
||||
setAnchored(TRUE)
|
||||
return
|
||||
|
||||
// Upgrades!
|
||||
if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already.
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You attach \the [W] into the assembly inner circuits.</span>")
|
||||
upgrades += W
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/crowbar_act(mob/user, obj/item/tool)
|
||||
if(!upgrades.len)
|
||||
return FALSE
|
||||
var/obj/U = locate(/obj) in upgrades
|
||||
if(U)
|
||||
to_chat(user, "<span class='notice'>You detach an upgrade from the assembly.</span>")
|
||||
tool.play_tool_sound(src)
|
||||
U.forceMove(drop_location())
|
||||
upgrades -= U
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
if(state != 3)
|
||||
return FALSE
|
||||
|
||||
tool.play_tool_sound(src)
|
||||
var/input = stripped_input(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")
|
||||
if(!input)
|
||||
to_chat(user, "<span class='warning'>No input found, please hang up and try your call again!</span>")
|
||||
return
|
||||
var/list/tempnetwork = splittext(input, ",")
|
||||
if(tempnetwork.len < 1)
|
||||
to_chat(user, "<span class='warning'>No network found, please hang up and try your call again!</span>")
|
||||
return
|
||||
for(var/i in tempnetwork)
|
||||
tempnetwork -= i
|
||||
tempnetwork += lowertext(i)
|
||||
state = 4
|
||||
var/obj/machinery/camera/C = new(loc, src)
|
||||
forceMove(C)
|
||||
C.setDir(src.dir)
|
||||
|
||||
C.network = tempnetwork
|
||||
var/area/A = get_area(src)
|
||||
C.c_tag = "[A.name] ([rand(1, 999)])"
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/wirecutter_act(mob/user, obj/item/I)
|
||||
if(state != 3)
|
||||
return FALSE
|
||||
|
||||
new /obj/item/stack/cable_coil(drop_location(), 2)
|
||||
I.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from the circuits.</span>")
|
||||
state = 2
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/wrench_act(mob/user, obj/item/I)
|
||||
if(state != 1)
|
||||
return FALSE
|
||||
I.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You detach the assembly from its place.</span>")
|
||||
new /obj/item/wallframe/camera(drop_location())
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You start to weld \the [src]...</span>")
|
||||
if(W.use_tool(src, user, 20, volume=50))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/camera_assembly/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc)
|
||||
qdel(src)
|
||||
/obj/item/wallframe/camera
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/machines/camera.dmi'
|
||||
icon_state = "cameracase"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=250)
|
||||
result_path = /obj/structure/camera_assembly
|
||||
|
||||
|
||||
/obj/structure/camera_assembly
|
||||
name = "camera assembly"
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/machines/camera.dmi'
|
||||
icon_state = "camera1"
|
||||
max_integrity = 150
|
||||
// Motion, EMP-Proof, X-ray
|
||||
var/static/list/possible_upgrades = typecacheof(list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer))
|
||||
var/list/upgrades
|
||||
var/state = 1
|
||||
|
||||
/*
|
||||
1 = Wrenched in place
|
||||
2 = Welded in place
|
||||
3 = Wires attached to it (you can now attach/dettach upgrades)
|
||||
4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
|
||||
*/
|
||||
|
||||
/obj/structure/camera_assembly/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
upgrades = list()
|
||||
|
||||
/obj/structure/camera_assembly/Destroy()
|
||||
QDEL_LIST(upgrades)
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
// State 1
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You weld the assembly securely into place.</span>")
|
||||
setAnchored(TRUE)
|
||||
state = 2
|
||||
return
|
||||
if(2)
|
||||
// State 2
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if(C.use(2))
|
||||
to_chat(user, "<span class='notice'>You add wires to the assembly.</span>")
|
||||
state = 3
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two lengths of cable to wire a camera!</span>")
|
||||
return
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weldingtool))
|
||||
|
||||
if(weld(W, user))
|
||||
to_chat(user, "<span class='notice'>You unweld the assembly from its place.</span>")
|
||||
state = 1
|
||||
setAnchored(TRUE)
|
||||
return
|
||||
|
||||
// Upgrades!
|
||||
if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already.
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You attach \the [W] into the assembly inner circuits.</span>")
|
||||
upgrades += W
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/camera_assembly/crowbar_act(mob/user, obj/item/tool)
|
||||
if(!upgrades.len)
|
||||
return FALSE
|
||||
var/obj/U = locate(/obj) in upgrades
|
||||
if(U)
|
||||
to_chat(user, "<span class='notice'>You detach an upgrade from the assembly.</span>")
|
||||
tool.play_tool_sound(src)
|
||||
U.forceMove(drop_location())
|
||||
upgrades -= U
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
if(state != 3)
|
||||
return FALSE
|
||||
|
||||
tool.play_tool_sound(src)
|
||||
var/input = stripped_input(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")
|
||||
if(!input)
|
||||
to_chat(user, "<span class='warning'>No input found, please hang up and try your call again!</span>")
|
||||
return
|
||||
var/list/tempnetwork = splittext(input, ",")
|
||||
if(tempnetwork.len < 1)
|
||||
to_chat(user, "<span class='warning'>No network found, please hang up and try your call again!</span>")
|
||||
return
|
||||
for(var/i in tempnetwork)
|
||||
tempnetwork -= i
|
||||
tempnetwork += lowertext(i)
|
||||
state = 4
|
||||
var/obj/machinery/camera/C = new(loc, src)
|
||||
forceMove(C)
|
||||
C.setDir(src.dir)
|
||||
|
||||
C.network = tempnetwork
|
||||
var/area/A = get_area(src)
|
||||
C.c_tag = "[A.name] ([rand(1, 999)])"
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/wirecutter_act(mob/user, obj/item/I)
|
||||
if(state != 3)
|
||||
return FALSE
|
||||
|
||||
new /obj/item/stack/cable_coil(drop_location(), 2)
|
||||
I.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from the circuits.</span>")
|
||||
state = 2
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/wrench_act(mob/user, obj/item/I)
|
||||
if(state != 1)
|
||||
return FALSE
|
||||
I.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You detach the assembly from its place.</span>")
|
||||
new /obj/item/wallframe/camera(drop_location())
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You start to weld \the [src]...</span>")
|
||||
if(W.use_tool(src, user, 20, volume=50))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/camera_assembly/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc)
|
||||
qdel(src)
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/obj/machinery/camera
|
||||
|
||||
var/list/datum/weakref/localMotionTargets = list()
|
||||
var/detectTime = 0
|
||||
var/area/ai_monitored/area_motion = null
|
||||
var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
|
||||
|
||||
/obj/machinery/camera/process()
|
||||
// motion camera event loop
|
||||
if(!isMotion())
|
||||
. = PROCESS_KILL
|
||||
return
|
||||
if(stat & EMPED)
|
||||
return
|
||||
if (detectTime > 0)
|
||||
var/elapsed = world.time - detectTime
|
||||
if (elapsed > alarm_delay)
|
||||
triggerAlarm()
|
||||
else if (detectTime == -1)
|
||||
for (var/datum/weakref/targetref in getTargetList())
|
||||
var/mob/target = targetref.resolve()
|
||||
if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target)))
|
||||
//If not part of a monitored area and the camera is not in range or the target is dead
|
||||
lostTargetRef(targetref)
|
||||
|
||||
/obj/machinery/camera/proc/getTargetList()
|
||||
if(area_motion)
|
||||
return area_motion.motionTargets
|
||||
return localMotionTargets
|
||||
|
||||
/obj/machinery/camera/proc/newTarget(mob/target)
|
||||
if(isAI(target))
|
||||
return FALSE
|
||||
if (detectTime == 0)
|
||||
detectTime = world.time // start the clock
|
||||
var/list/targets = getTargetList()
|
||||
targets |= WEAKREF(target)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
var/area/ai_monitored/A = get_area(src)
|
||||
localMotionTargets = null
|
||||
if(istype(A))
|
||||
A.motioncameras -= src
|
||||
cancelAlarm()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/camera/proc/lostTargetRef(datum/weakref/R)
|
||||
var/list/targets = getTargetList()
|
||||
targets -= R
|
||||
if (targets.len == 0)
|
||||
cancelAlarm()
|
||||
|
||||
/obj/machinery/camera/proc/cancelAlarm()
|
||||
if (detectTime == -1)
|
||||
for (var/i in GLOB.silicon_mobs)
|
||||
var/mob/living/silicon/aiPlayer = i
|
||||
if (status)
|
||||
aiPlayer.cancelAlarm("Motion", get_area(src), src)
|
||||
detectTime = 0
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/proc/triggerAlarm()
|
||||
if (!detectTime)
|
||||
return FALSE
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
|
||||
visible_message("<span class='warning'>A red light flashes on the [src]!</span>")
|
||||
detectTime = -1
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
|
||||
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
|
||||
if (!area_motion)
|
||||
if(isliving(AM))
|
||||
newTarget(AM)
|
||||
/obj/machinery/camera
|
||||
|
||||
var/list/datum/weakref/localMotionTargets = list()
|
||||
var/detectTime = 0
|
||||
var/area/ai_monitored/area_motion = null
|
||||
var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
|
||||
|
||||
/obj/machinery/camera/process()
|
||||
// motion camera event loop
|
||||
if(!isMotion())
|
||||
. = PROCESS_KILL
|
||||
return
|
||||
if(stat & EMPED)
|
||||
return
|
||||
if (detectTime > 0)
|
||||
var/elapsed = world.time - detectTime
|
||||
if (elapsed > alarm_delay)
|
||||
triggerAlarm()
|
||||
else if (detectTime == -1)
|
||||
for (var/datum/weakref/targetref in getTargetList())
|
||||
var/mob/target = targetref.resolve()
|
||||
if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target)))
|
||||
//If not part of a monitored area and the camera is not in range or the target is dead
|
||||
lostTargetRef(targetref)
|
||||
|
||||
/obj/machinery/camera/proc/getTargetList()
|
||||
if(area_motion)
|
||||
return area_motion.motionTargets
|
||||
return localMotionTargets
|
||||
|
||||
/obj/machinery/camera/proc/newTarget(mob/target)
|
||||
if(isAI(target))
|
||||
return FALSE
|
||||
if (detectTime == 0)
|
||||
detectTime = world.time // start the clock
|
||||
var/list/targets = getTargetList()
|
||||
targets |= WEAKREF(target)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
var/area/ai_monitored/A = get_area(src)
|
||||
localMotionTargets = null
|
||||
if(istype(A))
|
||||
A.motioncameras -= src
|
||||
cancelAlarm()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/camera/proc/lostTargetRef(datum/weakref/R)
|
||||
var/list/targets = getTargetList()
|
||||
targets -= R
|
||||
if (targets.len == 0)
|
||||
cancelAlarm()
|
||||
|
||||
/obj/machinery/camera/proc/cancelAlarm()
|
||||
if (detectTime == -1)
|
||||
for (var/i in GLOB.silicon_mobs)
|
||||
var/mob/living/silicon/aiPlayer = i
|
||||
if (status)
|
||||
aiPlayer.cancelAlarm("Motion", get_area(src), src)
|
||||
detectTime = 0
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/proc/triggerAlarm()
|
||||
if (!detectTime)
|
||||
return FALSE
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
|
||||
visible_message("<span class='warning'>A red light flashes on the [src]!</span>")
|
||||
detectTime = -1
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
|
||||
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
|
||||
if (!area_motion)
|
||||
if(isliving(AM))
|
||||
newTarget(AM)
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
// PRESETS
|
||||
|
||||
// EMP
|
||||
/obj/machinery/camera/emp_proof
|
||||
start_active = TRUE
|
||||
|
||||
/obj/machinery/camera/emp_proof/Initialize()
|
||||
. = ..()
|
||||
upgradeEmpProof()
|
||||
|
||||
// X-ray
|
||||
|
||||
/obj/machinery/camera/xray
|
||||
start_active = TRUE
|
||||
icon_state = "xraycam" // Thanks to Krutchen for the icons.
|
||||
|
||||
/obj/machinery/camera/xray/Initialize()
|
||||
. = ..()
|
||||
upgradeXRay()
|
||||
|
||||
// MOTION
|
||||
/obj/machinery/camera/motion
|
||||
start_active = TRUE
|
||||
name = "motion-sensitive security camera"
|
||||
|
||||
/obj/machinery/camera/motion/Initialize()
|
||||
. = ..()
|
||||
upgradeMotion()
|
||||
|
||||
// ALL UPGRADES
|
||||
/obj/machinery/camera/all
|
||||
start_active = TRUE
|
||||
|
||||
/obj/machinery/camera/all/Initialize()
|
||||
. = ..()
|
||||
upgradeEmpProof()
|
||||
upgradeXRay()
|
||||
upgradeMotion()
|
||||
|
||||
// AUTONAME
|
||||
|
||||
/obj/machinery/camera/autoname
|
||||
var/number = 0 //camera number in area
|
||||
|
||||
//This camera type automatically sets it's name to whatever the area that it's in is called.
|
||||
/obj/machinery/camera/autoname/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/camera/autoname/LateInitialize()
|
||||
. = ..()
|
||||
number = 1
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
for(var/obj/machinery/camera/autoname/C in GLOB.machines)
|
||||
if(C == src)
|
||||
continue
|
||||
var/area/CA = get_area(C)
|
||||
if(CA.type == A.type)
|
||||
if(C.number)
|
||||
number = max(number, C.number+1)
|
||||
c_tag = "[A.name] #[number]"
|
||||
|
||||
// CHECKS
|
||||
|
||||
/obj/machinery/camera/proc/isEmpProof()
|
||||
return upgrades & CAMERA_UPGRADE_EMP_PROOF
|
||||
|
||||
/obj/machinery/camera/proc/isXRay()
|
||||
return upgrades & CAMERA_UPGRADE_XRAY
|
||||
|
||||
/obj/machinery/camera/proc/isMotion()
|
||||
return upgrades & CAMERA_UPGRADE_MOTION
|
||||
|
||||
// UPGRADE PROCS
|
||||
|
||||
/obj/machinery/camera/proc/upgradeEmpProof()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
|
||||
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_EMP_PROOF
|
||||
|
||||
/obj/machinery/camera/proc/upgradeXRay()
|
||||
assembly.upgrades.Add(new /obj/item/analyzer(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_XRAY
|
||||
|
||||
// If you are upgrading Motion, and it isn't in the camera's Initialize(), add it to the machines list.
|
||||
/obj/machinery/camera/proc/upgradeMotion()
|
||||
assembly.upgrades.Add(new /obj/item/assembly/prox_sensor(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_MOTION
|
||||
// PRESETS
|
||||
|
||||
// EMP
|
||||
/obj/machinery/camera/emp_proof
|
||||
start_active = TRUE
|
||||
|
||||
/obj/machinery/camera/emp_proof/Initialize()
|
||||
. = ..()
|
||||
upgradeEmpProof()
|
||||
|
||||
// X-ray
|
||||
|
||||
/obj/machinery/camera/xray
|
||||
start_active = TRUE
|
||||
icon_state = "xraycam" // Thanks to Krutchen for the icons.
|
||||
|
||||
/obj/machinery/camera/xray/Initialize()
|
||||
. = ..()
|
||||
upgradeXRay()
|
||||
|
||||
// MOTION
|
||||
/obj/machinery/camera/motion
|
||||
start_active = TRUE
|
||||
name = "motion-sensitive security camera"
|
||||
|
||||
/obj/machinery/camera/motion/Initialize()
|
||||
. = ..()
|
||||
upgradeMotion()
|
||||
|
||||
// ALL UPGRADES
|
||||
/obj/machinery/camera/all
|
||||
start_active = TRUE
|
||||
|
||||
/obj/machinery/camera/all/Initialize()
|
||||
. = ..()
|
||||
upgradeEmpProof()
|
||||
upgradeXRay()
|
||||
upgradeMotion()
|
||||
|
||||
// AUTONAME
|
||||
|
||||
/obj/machinery/camera/autoname
|
||||
var/number = 0 //camera number in area
|
||||
|
||||
//This camera type automatically sets it's name to whatever the area that it's in is called.
|
||||
/obj/machinery/camera/autoname/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/camera/autoname/LateInitialize()
|
||||
. = ..()
|
||||
number = 1
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
for(var/obj/machinery/camera/autoname/C in GLOB.machines)
|
||||
if(C == src)
|
||||
continue
|
||||
var/area/CA = get_area(C)
|
||||
if(CA.type == A.type)
|
||||
if(C.number)
|
||||
number = max(number, C.number+1)
|
||||
c_tag = "[A.name] #[number]"
|
||||
|
||||
// CHECKS
|
||||
|
||||
/obj/machinery/camera/proc/isEmpProof()
|
||||
return upgrades & CAMERA_UPGRADE_EMP_PROOF
|
||||
|
||||
/obj/machinery/camera/proc/isXRay()
|
||||
return upgrades & CAMERA_UPGRADE_XRAY
|
||||
|
||||
/obj/machinery/camera/proc/isMotion()
|
||||
return upgrades & CAMERA_UPGRADE_MOTION
|
||||
|
||||
// UPGRADE PROCS
|
||||
|
||||
/obj/machinery/camera/proc/upgradeEmpProof()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
|
||||
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_EMP_PROOF
|
||||
|
||||
/obj/machinery/camera/proc/upgradeXRay()
|
||||
assembly.upgrades.Add(new /obj/item/analyzer(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_XRAY
|
||||
|
||||
// If you are upgrading Motion, and it isn't in the camera's Initialize(), add it to the machines list.
|
||||
/obj/machinery/camera/proc/upgradeMotion()
|
||||
assembly.upgrades.Add(new /obj/item/assembly/prox_sensor(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_MOTION
|
||||
|
||||
@@ -1,151 +1,151 @@
|
||||
/mob/living/silicon/ai/proc/get_camera_list()
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
|
||||
var/list/T = list()
|
||||
|
||||
for (var/obj/machinery/camera/C in L)
|
||||
var/list/tempnetwork = C.network&src.network
|
||||
if (tempnetwork.len)
|
||||
T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
|
||||
|
||||
return T
|
||||
|
||||
/mob/living/silicon/ai/proc/show_camera_list()
|
||||
var/list/cameras = get_camera_list()
|
||||
var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras
|
||||
switchCamera(cameras[camera])
|
||||
|
||||
/datum/trackable
|
||||
var/initialized = FALSE
|
||||
var/list/names = list()
|
||||
var/list/namecounts = list()
|
||||
var/list/humans = list()
|
||||
var/list/others = list()
|
||||
|
||||
/mob/living/silicon/ai/proc/trackable_mobs()
|
||||
track.initialized = TRUE
|
||||
track.names.Cut()
|
||||
track.namecounts.Cut()
|
||||
track.humans.Cut()
|
||||
track.others.Cut()
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
return list()
|
||||
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
if(!L.can_track(usr))
|
||||
continue
|
||||
|
||||
var/name = L.name
|
||||
while(name in track.names)
|
||||
track.namecounts[name]++
|
||||
name = text("[] ([])", name, track.namecounts[name])
|
||||
track.names.Add(name)
|
||||
track.namecounts[name] = 1
|
||||
|
||||
if(ishuman(L))
|
||||
track.humans[name] = L
|
||||
else
|
||||
track.others[name] = L
|
||||
|
||||
var/list/targets = sortList(track.humans) + sortList(track.others)
|
||||
|
||||
return targets
|
||||
|
||||
/mob/living/silicon/ai/verb/ai_camera_track(target_name in trackable_mobs())
|
||||
set name = "track"
|
||||
set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass
|
||||
|
||||
if(!target_name)
|
||||
return
|
||||
|
||||
if(!track.initialized)
|
||||
trackable_mobs()
|
||||
|
||||
var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name])
|
||||
|
||||
ai_actual_track(target)
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target)
|
||||
if(!istype(target))
|
||||
return
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
|
||||
U.cameraFollow = target
|
||||
U.tracking = 1
|
||||
|
||||
if(!target || !target.can_track(usr))
|
||||
to_chat(U, "<span class='warning'>Target is not near any active cameras.</span>")
|
||||
U.cameraFollow = null
|
||||
return
|
||||
|
||||
to_chat(U, "<span class='notice'>Now tracking [target.get_visible_name()] on camera.</span>")
|
||||
|
||||
var/cameraticks = 0
|
||||
spawn(0)
|
||||
while(U.cameraFollow == target)
|
||||
if(U.cameraFollow == null)
|
||||
return
|
||||
|
||||
if(!target.can_track(usr))
|
||||
U.tracking = 1
|
||||
if(!cameraticks)
|
||||
to_chat(U, "<span class='warning'>Target is not near any active cameras. Attempting to reacquire...</span>")
|
||||
cameraticks++
|
||||
if(cameraticks > 9)
|
||||
U.cameraFollow = null
|
||||
to_chat(U, "<span class='warning'>Unable to reacquire, cancelling track...</span>")
|
||||
tracking = 0
|
||||
return
|
||||
else
|
||||
sleep(10)
|
||||
continue
|
||||
|
||||
else
|
||||
cameraticks = 0
|
||||
U.tracking = 0
|
||||
|
||||
if(U.eyeobj)
|
||||
U.eyeobj.setLoc(get_turf(target))
|
||||
|
||||
else
|
||||
view_core()
|
||||
U.cameraFollow = null
|
||||
return
|
||||
|
||||
sleep(10)
|
||||
|
||||
/proc/near_camera(mob/living/M)
|
||||
if (!isturf(M.loc))
|
||||
return FALSE
|
||||
if(issilicon(M))
|
||||
var/mob/living/silicon/S = M
|
||||
if((QDELETED(S.builtInCamera) || !S.builtInCamera.can_use()) && !GLOB.cameranet.checkCameraVis(M))
|
||||
return FALSE
|
||||
else if(!GLOB.cameranet.checkCameraVis(M))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
if (!can_use())
|
||||
return
|
||||
user.switchCamera(src)
|
||||
|
||||
/proc/camera_sort(list/L)
|
||||
var/obj/machinery/camera/a
|
||||
var/obj/machinery/camera/b
|
||||
|
||||
for (var/i = L.len, i > 0, i--)
|
||||
for (var/j = 1 to i - 1)
|
||||
a = L[j]
|
||||
b = L[j + 1]
|
||||
if (sorttext(a.c_tag, b.c_tag) < 0)
|
||||
L.Swap(j, j + 1)
|
||||
return L
|
||||
/mob/living/silicon/ai/proc/get_camera_list()
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
|
||||
var/list/T = list()
|
||||
|
||||
for (var/obj/machinery/camera/C in L)
|
||||
var/list/tempnetwork = C.network&src.network
|
||||
if (tempnetwork.len)
|
||||
T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
|
||||
|
||||
return T
|
||||
|
||||
/mob/living/silicon/ai/proc/show_camera_list()
|
||||
var/list/cameras = get_camera_list()
|
||||
var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras
|
||||
switchCamera(cameras[camera])
|
||||
|
||||
/datum/trackable
|
||||
var/initialized = FALSE
|
||||
var/list/names = list()
|
||||
var/list/namecounts = list()
|
||||
var/list/humans = list()
|
||||
var/list/others = list()
|
||||
|
||||
/mob/living/silicon/ai/proc/trackable_mobs()
|
||||
track.initialized = TRUE
|
||||
track.names.Cut()
|
||||
track.namecounts.Cut()
|
||||
track.humans.Cut()
|
||||
track.others.Cut()
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
return list()
|
||||
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
if(!L.can_track(usr))
|
||||
continue
|
||||
|
||||
var/name = L.name
|
||||
while(name in track.names)
|
||||
track.namecounts[name]++
|
||||
name = text("[] ([])", name, track.namecounts[name])
|
||||
track.names.Add(name)
|
||||
track.namecounts[name] = 1
|
||||
|
||||
if(ishuman(L))
|
||||
track.humans[name] = L
|
||||
else
|
||||
track.others[name] = L
|
||||
|
||||
var/list/targets = sortList(track.humans) + sortList(track.others)
|
||||
|
||||
return targets
|
||||
|
||||
/mob/living/silicon/ai/verb/ai_camera_track(target_name in trackable_mobs())
|
||||
set name = "track"
|
||||
set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass
|
||||
|
||||
if(!target_name)
|
||||
return
|
||||
|
||||
if(!track.initialized)
|
||||
trackable_mobs()
|
||||
|
||||
var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name])
|
||||
|
||||
ai_actual_track(target)
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target)
|
||||
if(!istype(target))
|
||||
return
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
|
||||
U.cameraFollow = target
|
||||
U.tracking = 1
|
||||
|
||||
if(!target || !target.can_track(usr))
|
||||
to_chat(U, "<span class='warning'>Target is not near any active cameras.</span>")
|
||||
U.cameraFollow = null
|
||||
return
|
||||
|
||||
to_chat(U, "<span class='notice'>Now tracking [target.get_visible_name()] on camera.</span>")
|
||||
|
||||
var/cameraticks = 0
|
||||
spawn(0)
|
||||
while(U.cameraFollow == target)
|
||||
if(U.cameraFollow == null)
|
||||
return
|
||||
|
||||
if(!target.can_track(usr))
|
||||
U.tracking = 1
|
||||
if(!cameraticks)
|
||||
to_chat(U, "<span class='warning'>Target is not near any active cameras. Attempting to reacquire...</span>")
|
||||
cameraticks++
|
||||
if(cameraticks > 9)
|
||||
U.cameraFollow = null
|
||||
to_chat(U, "<span class='warning'>Unable to reacquire, cancelling track...</span>")
|
||||
tracking = 0
|
||||
return
|
||||
else
|
||||
sleep(10)
|
||||
continue
|
||||
|
||||
else
|
||||
cameraticks = 0
|
||||
U.tracking = 0
|
||||
|
||||
if(U.eyeobj)
|
||||
U.eyeobj.setLoc(get_turf(target))
|
||||
|
||||
else
|
||||
view_core()
|
||||
U.cameraFollow = null
|
||||
return
|
||||
|
||||
sleep(10)
|
||||
|
||||
/proc/near_camera(mob/living/M)
|
||||
if (!isturf(M.loc))
|
||||
return FALSE
|
||||
if(issilicon(M))
|
||||
var/mob/living/silicon/S = M
|
||||
if((QDELETED(S.builtInCamera) || !S.builtInCamera.can_use()) && !GLOB.cameranet.checkCameraVis(M))
|
||||
return FALSE
|
||||
else if(!GLOB.cameranet.checkCameraVis(M))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
if (!can_use())
|
||||
return
|
||||
user.switchCamera(src)
|
||||
|
||||
/proc/camera_sort(list/L)
|
||||
var/obj/machinery/camera/a
|
||||
var/obj/machinery/camera/b
|
||||
|
||||
for (var/i = L.len, i > 0, i--)
|
||||
for (var/j = 1 to i - 1)
|
||||
a = L[j]
|
||||
b = L[j + 1]
|
||||
if (sorttext(a.c_tag, b.c_tag) < 0)
|
||||
L.Swap(j, j + 1)
|
||||
return L
|
||||
|
||||
+130
-130
@@ -1,130 +1,130 @@
|
||||
/obj/machinery/cell_charger
|
||||
name = "cell charger"
|
||||
desc = "It charges power cells."
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "ccharger"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 60
|
||||
power_channel = EQUIP
|
||||
circuit = /obj/item/circuitboard/machine/cell_charger
|
||||
pass_flags = PASSTABLE
|
||||
var/obj/item/stock_parts/cell/charging = null
|
||||
var/chargelevel = -1
|
||||
var/charge_rate = 500
|
||||
|
||||
/obj/machinery/cell_charger/update_icon()
|
||||
cut_overlays()
|
||||
if(charging)
|
||||
add_overlay(image(charging.icon, charging.icon_state))
|
||||
add_overlay("ccharger-on")
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
var/newlevel = round(charging.percent() * 4 / 100)
|
||||
chargelevel = newlevel
|
||||
add_overlay("ccharger-o[newlevel]")
|
||||
|
||||
/obj/machinery/cell_charger/examine(mob/user)
|
||||
. = ..()
|
||||
. += "There's [charging ? "a" : "no"] cell in the charger."
|
||||
if(charging)
|
||||
. += "Current charge: [round(charging.percent(), 1)]%."
|
||||
|
||||
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='warning'>[src] is broken!</span>")
|
||||
return
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='warning'>[src] isn't attached to the ground!</span>")
|
||||
return
|
||||
if(charging)
|
||||
to_chat(user, "<span class='warning'>There is already a cell in the charger!</span>")
|
||||
return
|
||||
else
|
||||
var/area/a = loc.loc // Gets our locations location, like a dream within a dream
|
||||
if(!isarea(a))
|
||||
return
|
||||
if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power!
|
||||
to_chat(user, "<span class='warning'>[src] blinks red as you try to insert the cell!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W,src))
|
||||
return
|
||||
|
||||
charging = W
|
||||
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
else
|
||||
if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W))
|
||||
return
|
||||
if(default_deconstruction_crowbar(W))
|
||||
return
|
||||
if(!charging && default_unfasten_wrench(user, W))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/deconstruct()
|
||||
if(charging)
|
||||
charging.forceMove(drop_location())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/Destroy()
|
||||
QDEL_NULL(charging)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/proc/removecell()
|
||||
charging.update_icon()
|
||||
charging = null
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/cell_charger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
user.put_in_hands(charging)
|
||||
charging.add_fingerprint(user)
|
||||
|
||||
user.visible_message("[user] removes [charging] from [src].", "<span class='notice'>You remove [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
|
||||
/obj/machinery/cell_charger/attack_tk(mob/user)
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
charging.forceMove(loc)
|
||||
to_chat(user, "<span class='notice'>You telekinetically remove [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
|
||||
/obj/machinery/cell_charger/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/cell_charger/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS)
|
||||
return
|
||||
|
||||
if(charging)
|
||||
charging.emp_act(severity)
|
||||
|
||||
/obj/machinery/cell_charger/RefreshParts()
|
||||
charge_rate = 500
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
charge_rate *= C.rating
|
||||
|
||||
/obj/machinery/cell_charger/process()
|
||||
if(!charging || !anchored || (stat & (BROKEN|NOPOWER)))
|
||||
return
|
||||
|
||||
if(charging.percent() >= 100)
|
||||
return
|
||||
use_power(charge_rate)
|
||||
charging.give(charge_rate) //this is 2558, efficient batteries exist
|
||||
|
||||
update_icon()
|
||||
/obj/machinery/cell_charger
|
||||
name = "cell charger"
|
||||
desc = "It charges power cells."
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "ccharger"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 60
|
||||
power_channel = EQUIP
|
||||
circuit = /obj/item/circuitboard/machine/cell_charger
|
||||
pass_flags = PASSTABLE
|
||||
var/obj/item/stock_parts/cell/charging = null
|
||||
var/chargelevel = -1
|
||||
var/charge_rate = 500
|
||||
|
||||
/obj/machinery/cell_charger/update_icon()
|
||||
cut_overlays()
|
||||
if(charging)
|
||||
add_overlay(image(charging.icon, charging.icon_state))
|
||||
add_overlay("ccharger-on")
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
var/newlevel = round(charging.percent() * 4 / 100)
|
||||
chargelevel = newlevel
|
||||
add_overlay("ccharger-o[newlevel]")
|
||||
|
||||
/obj/machinery/cell_charger/examine(mob/user)
|
||||
. = ..()
|
||||
. += "There's [charging ? "a" : "no"] cell in the charger."
|
||||
if(charging)
|
||||
. += "Current charge: [round(charging.percent(), 1)]%."
|
||||
|
||||
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='warning'>[src] is broken!</span>")
|
||||
return
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='warning'>[src] isn't attached to the ground!</span>")
|
||||
return
|
||||
if(charging)
|
||||
to_chat(user, "<span class='warning'>There is already a cell in the charger!</span>")
|
||||
return
|
||||
else
|
||||
var/area/a = loc.loc // Gets our locations location, like a dream within a dream
|
||||
if(!isarea(a))
|
||||
return
|
||||
if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power!
|
||||
to_chat(user, "<span class='warning'>[src] blinks red as you try to insert the cell!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W,src))
|
||||
return
|
||||
|
||||
charging = W
|
||||
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
else
|
||||
if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W))
|
||||
return
|
||||
if(default_deconstruction_crowbar(W))
|
||||
return
|
||||
if(!charging && default_unfasten_wrench(user, W))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/deconstruct()
|
||||
if(charging)
|
||||
charging.forceMove(drop_location())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/Destroy()
|
||||
QDEL_NULL(charging)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cell_charger/proc/removecell()
|
||||
charging.update_icon()
|
||||
charging = null
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/cell_charger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
user.put_in_hands(charging)
|
||||
charging.add_fingerprint(user)
|
||||
|
||||
user.visible_message("[user] removes [charging] from [src].", "<span class='notice'>You remove [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
|
||||
/obj/machinery/cell_charger/attack_tk(mob/user)
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
charging.forceMove(loc)
|
||||
to_chat(user, "<span class='notice'>You telekinetically remove [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
|
||||
/obj/machinery/cell_charger/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/cell_charger/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS)
|
||||
return
|
||||
|
||||
if(charging)
|
||||
charging.emp_act(severity)
|
||||
|
||||
/obj/machinery/cell_charger/RefreshParts()
|
||||
charge_rate = 500
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
charge_rate *= C.rating
|
||||
|
||||
/obj/machinery/cell_charger/process()
|
||||
if(!charging || !anchored || (stat & (BROKEN|NOPOWER)))
|
||||
return
|
||||
|
||||
if(charging.percent() >= 100)
|
||||
return
|
||||
use_power(charge_rate)
|
||||
charging.give(charge_rate) //this is 2558, efficient batteries exist
|
||||
|
||||
update_icon()
|
||||
|
||||
+556
-554
File diff suppressed because it is too large
Load Diff
@@ -1,128 +1,128 @@
|
||||
#define MENU_OPERATION 1
|
||||
#define MENU_SURGERIES 2
|
||||
|
||||
/obj/machinery/computer/operating
|
||||
name = "operating computer"
|
||||
desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/operating
|
||||
var/mob/living/carbon/human/patient
|
||||
var/obj/structure/table/optable/table
|
||||
var/list/advanced_surgeries = list()
|
||||
var/datum/techweb/linked_techweb
|
||||
var/menu = MENU_OPERATION
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/operating/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
find_table()
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/disk/surgery))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a surgery protocol from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
var/obj/item/disk/surgery/D = O
|
||||
if(do_after(user, 10, target = src))
|
||||
advanced_surgeries |= D.surgeries
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/operating/proc/sync_surgeries()
|
||||
for(var/i in linked_techweb.researched_designs)
|
||||
var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i)
|
||||
if(!istype(D))
|
||||
continue
|
||||
advanced_surgeries |= D.surgery
|
||||
|
||||
/obj/machinery/computer/operating/proc/find_table()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
table = locate(/obj/structure/table/optable, get_step(src, direction))
|
||||
if(table)
|
||||
table.computer = src
|
||||
break
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["table"] = table
|
||||
if(table)
|
||||
data["menu"] = menu
|
||||
|
||||
var/list/surgeries = list()
|
||||
for(var/X in advanced_surgeries)
|
||||
var/datum/surgery/S = X
|
||||
var/list/surgery = list()
|
||||
surgery["name"] = initial(S.name)
|
||||
surgery["desc"] = initial(S.desc)
|
||||
surgeries += list(surgery)
|
||||
data["surgeries"] = surgeries
|
||||
|
||||
data["patient"] = list()
|
||||
if(table.check_patient())
|
||||
patient = table.patient
|
||||
switch(patient.stat)
|
||||
if(CONSCIOUS)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["patient"]["stat"] = "Unconscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["patient"]["stat"] = "Dead"
|
||||
data["patient"]["statstate"] = "bad"
|
||||
data["patient"]["health"] = patient.health
|
||||
data["patient"]["blood_type"] = patient.dna.blood_type
|
||||
data["patient"]["maxHealth"] = patient.maxHealth
|
||||
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["patient"]["bruteLoss"] = patient.getBruteLoss()
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
if(patient.surgeries.len)
|
||||
data["procedures"] = list()
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
var/chems_needed = surgery_step.get_chem_list()
|
||||
var/alternative_step
|
||||
var/alt_chems_needed = ""
|
||||
if(surgery_step.repeatable)
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
alternative_step = capitalize(next_step.name)
|
||||
alt_chems_needed = next_step.get_chem_list()
|
||||
else
|
||||
alternative_step = "Finish operation"
|
||||
data["procedures"] += list(list(
|
||||
"name" = capitalize(procedure.name),
|
||||
"next_step" = capitalize(surgery_step.name),
|
||||
"chems_needed" = chems_needed,
|
||||
"alternative_step" = alternative_step,
|
||||
"alt_chems_needed" = alt_chems_needed
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("change_menu")
|
||||
menu = text2num(params["menu"])
|
||||
. = TRUE
|
||||
if("sync")
|
||||
sync_surgeries()
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
#undef MENU_OPERATION
|
||||
#undef MENU_SURGERIES
|
||||
#define MENU_OPERATION 1
|
||||
#define MENU_SURGERIES 2
|
||||
|
||||
/obj/machinery/computer/operating
|
||||
name = "operating computer"
|
||||
desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/operating
|
||||
var/mob/living/carbon/human/patient
|
||||
var/obj/structure/table/optable/table
|
||||
var/list/advanced_surgeries = list()
|
||||
var/datum/techweb/linked_techweb
|
||||
var/menu = MENU_OPERATION
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/operating/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
find_table()
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/disk/surgery))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a surgery protocol from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
var/obj/item/disk/surgery/D = O
|
||||
if(do_after(user, 10, target = src))
|
||||
advanced_surgeries |= D.surgeries
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/operating/proc/sync_surgeries()
|
||||
for(var/i in linked_techweb.researched_designs)
|
||||
var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i)
|
||||
if(!istype(D))
|
||||
continue
|
||||
advanced_surgeries |= D.surgery
|
||||
|
||||
/obj/machinery/computer/operating/proc/find_table()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
table = locate(/obj/structure/table/optable, get_step(src, direction))
|
||||
if(table)
|
||||
table.computer = src
|
||||
break
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["table"] = table
|
||||
if(table)
|
||||
data["menu"] = menu
|
||||
|
||||
var/list/surgeries = list()
|
||||
for(var/X in advanced_surgeries)
|
||||
var/datum/surgery/S = X
|
||||
var/list/surgery = list()
|
||||
surgery["name"] = initial(S.name)
|
||||
surgery["desc"] = initial(S.desc)
|
||||
surgeries += list(surgery)
|
||||
data["surgeries"] = surgeries
|
||||
|
||||
data["patient"] = list()
|
||||
if(table.check_patient())
|
||||
patient = table.patient
|
||||
switch(patient.stat)
|
||||
if(CONSCIOUS)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["patient"]["stat"] = "Unconscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["patient"]["stat"] = "Dead"
|
||||
data["patient"]["statstate"] = "bad"
|
||||
data["patient"]["health"] = patient.health
|
||||
data["patient"]["blood_type"] = patient.dna.blood_type
|
||||
data["patient"]["maxHealth"] = patient.maxHealth
|
||||
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["patient"]["bruteLoss"] = patient.getBruteLoss()
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
if(patient.surgeries.len)
|
||||
data["procedures"] = list()
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
var/chems_needed = surgery_step.get_chem_list()
|
||||
var/alternative_step
|
||||
var/alt_chems_needed = ""
|
||||
if(surgery_step.repeatable)
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
alternative_step = capitalize(next_step.name)
|
||||
alt_chems_needed = next_step.get_chem_list()
|
||||
else
|
||||
alternative_step = "Finish operation"
|
||||
data["procedures"] += list(list(
|
||||
"name" = capitalize(procedure.name),
|
||||
"next_step" = capitalize(surgery_step.name),
|
||||
"chems_needed" = chems_needed,
|
||||
"alternative_step" = alternative_step,
|
||||
"alt_chems_needed" = alt_chems_needed
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("change_menu")
|
||||
menu = text2num(params["menu"])
|
||||
. = TRUE
|
||||
if("sync")
|
||||
sync_surgeries()
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
#undef MENU_OPERATION
|
||||
#undef MENU_SURGERIES
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
/obj/machinery/computer/aifixer
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
|
||||
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = 0
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge and it emits a warning beep.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
var/dat = ""
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++)
|
||||
var/law = src.occupier.laws.hacked[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
var/law = src.occupier.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
|
||||
var/law = src.occupier.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (src.occupier.stat == DEAD)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!src.active)
|
||||
dat += {"<br><br><A href='byond://?src=[REF(src)];fix=1'>Begin Reconstruction</A>"}
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += {"<br><A href='?src=[REF(user)];mach_close=computer'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
occupier.adjustOxyLoss(-1, 0)
|
||||
occupier.adjustFireLoss(-1, 0)
|
||||
occupier.adjustToxLoss(-1, 0)
|
||||
occupier.adjustBruteLoss(-1, 0)
|
||||
occupier.updatehealth()
|
||||
if(occupier.health >= 0 && occupier.stat == DEAD)
|
||||
occupier.revive()
|
||||
return occupier.health < 100
|
||||
|
||||
/obj/machinery/computer/aifixer/process()
|
||||
if(..())
|
||||
if(active)
|
||||
var/oldstat = occupier.stat
|
||||
active = Fix()
|
||||
if(oldstat != occupier.stat)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["fix"])
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
active = TRUE
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
else
|
||||
if(active)
|
||||
add_overlay("ai-fixer-on")
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
add_overlay("ai-fixer-full")
|
||||
if (2)
|
||||
add_overlay("ai-fixer-404")
|
||||
else
|
||||
add_overlay("ai-fixer-empty")
|
||||
|
||||
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
|
||||
if(!..())
|
||||
return
|
||||
//Downloading AI from card to terminal.
|
||||
if(interaction == AI_TRANS_FROM_CARD)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "[src] is offline and cannot take an AI at this time!")
|
||||
return
|
||||
AI.forceMove(src)
|
||||
occupier = AI
|
||||
AI.control_disabled = 1
|
||||
AI.radio_enabled = 0
|
||||
to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
card.AI = null
|
||||
update_icon()
|
||||
|
||||
else //Uploading AI from terminal to card
|
||||
if(occupier && !active)
|
||||
to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
occupier.forceMove(card)
|
||||
card.AI = occupier
|
||||
occupier = null
|
||||
update_icon()
|
||||
else if (active)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Reconstruction in progress.")
|
||||
else if (!occupier)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Unable to locate artificial intelligence.")
|
||||
/obj/machinery/computer/aifixer
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
|
||||
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = 0
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge and it emits a warning beep.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
var/dat = ""
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++)
|
||||
var/law = src.occupier.laws.hacked[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
var/law = src.occupier.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
|
||||
var/law = src.occupier.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (src.occupier.stat == DEAD)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!src.active)
|
||||
dat += {"<br><br><A href='byond://?src=[REF(src)];fix=1'>Begin Reconstruction</A>"}
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += {"<br><A href='?src=[REF(user)];mach_close=computer'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
occupier.adjustOxyLoss(-1, 0)
|
||||
occupier.adjustFireLoss(-1, 0)
|
||||
occupier.adjustToxLoss(-1, 0)
|
||||
occupier.adjustBruteLoss(-1, 0)
|
||||
occupier.updatehealth()
|
||||
if(occupier.health >= 0 && occupier.stat == DEAD)
|
||||
occupier.revive()
|
||||
return occupier.health < 100
|
||||
|
||||
/obj/machinery/computer/aifixer/process()
|
||||
if(..())
|
||||
if(active)
|
||||
var/oldstat = occupier.stat
|
||||
active = Fix()
|
||||
if(oldstat != occupier.stat)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["fix"])
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
active = TRUE
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
else
|
||||
if(active)
|
||||
add_overlay("ai-fixer-on")
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
add_overlay("ai-fixer-full")
|
||||
if (2)
|
||||
add_overlay("ai-fixer-404")
|
||||
else
|
||||
add_overlay("ai-fixer-empty")
|
||||
|
||||
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
|
||||
if(!..())
|
||||
return
|
||||
//Downloading AI from card to terminal.
|
||||
if(interaction == AI_TRANS_FROM_CARD)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
to_chat(user, "[src] is offline and cannot take an AI at this time!")
|
||||
return
|
||||
AI.forceMove(src)
|
||||
occupier = AI
|
||||
AI.control_disabled = 1
|
||||
AI.radio_enabled = 0
|
||||
to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
|
||||
card.AI = null
|
||||
update_icon()
|
||||
|
||||
else //Uploading AI from terminal to card
|
||||
if(occupier && !active)
|
||||
to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
occupier.forceMove(card)
|
||||
card.AI = occupier
|
||||
occupier = null
|
||||
update_icon()
|
||||
else if (active)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Reconstruction in progress.")
|
||||
else if (!occupier)
|
||||
to_chat(user, "<span class='boldannounce'>ERROR</span>: Unable to locate artificial intelligence.")
|
||||
|
||||
@@ -1,100 +1,100 @@
|
||||
/obj/machinery/computer/atmos_alert
|
||||
name = "atmospheric alert console"
|
||||
desc = "Used to monitor the station's air alarms."
|
||||
circuit = /obj/item/circuitboard/computer/atmos_alert
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
var/list/priority_alarms = list()
|
||||
var/list/minor_alarms = list()
|
||||
var/receive_frequency = FREQ_ATMOS_ALARMS
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/atmos_alert/Initialize()
|
||||
. = ..()
|
||||
set_frequency(receive_frequency)
|
||||
|
||||
/obj/machinery/computer/atmos_alert/Destroy()
|
||||
SSradio.remove_object(src, receive_frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["priority"] = list()
|
||||
for(var/zone in priority_alarms)
|
||||
data["priority"] += zone
|
||||
data["minor"] = list()
|
||||
for(var/zone in minor_alarms)
|
||||
data["minor"] += zone
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("clear")
|
||||
var/zone = params["zone"]
|
||||
if(zone in priority_alarms)
|
||||
to_chat(usr, "Priority alarm for [zone] cleared.")
|
||||
priority_alarms -= zone
|
||||
. = TRUE
|
||||
if(zone in minor_alarms)
|
||||
to_chat(usr, "Minor alarm for [zone] cleared.")
|
||||
minor_alarms -= zone
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, receive_frequency)
|
||||
receive_frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, receive_frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/computer/atmos_alert/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/zone = signal.data["zone"]
|
||||
var/severity = signal.data["alert"]
|
||||
|
||||
if(!zone || !severity)
|
||||
return
|
||||
|
||||
minor_alarms -= zone
|
||||
priority_alarms -= zone
|
||||
if(severity == "severe")
|
||||
priority_alarms += zone
|
||||
else if (severity == "minor")
|
||||
minor_alarms += zone
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/atmos_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
if(priority_alarms.len)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else if(minor_alarms.len)
|
||||
overlay_state = "alert:1"
|
||||
add_overlay("alert:1")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
/obj/machinery/computer/atmos_alert
|
||||
name = "atmospheric alert console"
|
||||
desc = "Used to monitor the station's air alarms."
|
||||
circuit = /obj/item/circuitboard/computer/atmos_alert
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
var/list/priority_alarms = list()
|
||||
var/list/minor_alarms = list()
|
||||
var/receive_frequency = FREQ_ATMOS_ALARMS
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/atmos_alert/Initialize()
|
||||
. = ..()
|
||||
set_frequency(receive_frequency)
|
||||
|
||||
/obj/machinery/computer/atmos_alert/Destroy()
|
||||
SSradio.remove_object(src, receive_frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["priority"] = list()
|
||||
for(var/zone in priority_alarms)
|
||||
data["priority"] += zone
|
||||
data["minor"] = list()
|
||||
for(var/zone in minor_alarms)
|
||||
data["minor"] += zone
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("clear")
|
||||
var/zone = params["zone"]
|
||||
if(zone in priority_alarms)
|
||||
to_chat(usr, "Priority alarm for [zone] cleared.")
|
||||
priority_alarms -= zone
|
||||
. = TRUE
|
||||
if(zone in minor_alarms)
|
||||
to_chat(usr, "Minor alarm for [zone] cleared.")
|
||||
minor_alarms -= zone
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, receive_frequency)
|
||||
receive_frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, receive_frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/computer/atmos_alert/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/zone = signal.data["zone"]
|
||||
var/severity = signal.data["alert"]
|
||||
|
||||
if(!zone || !severity)
|
||||
return
|
||||
|
||||
minor_alarms -= zone
|
||||
priority_alarms -= zone
|
||||
if(severity == "severe")
|
||||
priority_alarms += zone
|
||||
else if (severity == "minor")
|
||||
minor_alarms += zone
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/atmos_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
if(priority_alarms.len)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else if(minor_alarms.len)
|
||||
overlay_state = "alert:1"
|
||||
add_overlay("alert:1")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -1,305 +1,305 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
// AIR SENSOR (found in gas tanks)
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/air_sensor
|
||||
name = "gas sensor"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "gsensor1"
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
var/id_tag
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/air_sensor/atmos/toxin_tank
|
||||
name = "plasma tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_TOX
|
||||
/obj/machinery/air_sensor/atmos/toxins_mixing_tank
|
||||
name = "toxins mixing gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB
|
||||
/obj/machinery/air_sensor/atmos/oxygen_tank
|
||||
name = "oxygen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_O2
|
||||
/obj/machinery/air_sensor/atmos/nitrogen_tank
|
||||
name = "nitrogen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2
|
||||
/obj/machinery/air_sensor/atmos/mix_tank
|
||||
name = "mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX
|
||||
/obj/machinery/air_sensor/atmos/nitrous_tank
|
||||
name = "nitrous oxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O
|
||||
/obj/machinery/air_sensor/atmos/air_tank
|
||||
name = "air mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR
|
||||
/obj/machinery/air_sensor/atmos/carbon_tank
|
||||
name = "carbon dioxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2
|
||||
/obj/machinery/air_sensor/atmos/incinerator_tank
|
||||
name = "incinerator chamber gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR
|
||||
|
||||
/obj/machinery/air_sensor/update_icon()
|
||||
icon_state = "gsensor[on]"
|
||||
|
||||
/obj/machinery/air_sensor/process_atmos()
|
||||
if(on)
|
||||
var/datum/gas_mixture/air_sample = return_air()
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"sigtype" = "status",
|
||||
"id_tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"pressure" = air_sample.return_pressure(),
|
||||
"temperature" = air_sample.temperature,
|
||||
"gases" = list()
|
||||
))
|
||||
var/total_moles = air_sample.total_moles()
|
||||
if(total_moles)
|
||||
for(var/gas_id in air_sample.gases)
|
||||
var/gas_name = GLOB.meta_gas_names[gas_id]
|
||||
signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
|
||||
/obj/machinery/air_sensor/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/air_sensor/Initialize()
|
||||
. = ..()
|
||||
SSair.atmos_machinery += src
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/air_sensor/Destroy()
|
||||
SSair.atmos_machinery -= src
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// GENERAL AIR CONTROL (a.k.a atmos computer)
|
||||
/////////////////////////////////////////////////////////////
|
||||
GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
|
||||
/obj/machinery/computer/atmos_control
|
||||
name = "atmospherics monitoring"
|
||||
desc = "Used to monitor the station's atmospherics sensors."
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
|
||||
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
|
||||
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
|
||||
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
|
||||
ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber"
|
||||
)
|
||||
var/list/sensor_information = list()
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/atmos_control/Initialize()
|
||||
. = ..()
|
||||
GLOB.atmos_air_controllers += src
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/computer/atmos_control/Destroy()
|
||||
GLOB.atmos_air_controllers -= src
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_control", name, 400, 925, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_data(mob/user)
|
||||
var/data = list()
|
||||
|
||||
data["sensors"] = list()
|
||||
for(var/id_tag in sensors)
|
||||
var/long_name = sensors[id_tag]
|
||||
var/list/info = sensor_information[id_tag]
|
||||
if(!info)
|
||||
continue
|
||||
data["sensors"] += list(list(
|
||||
"id_tag" = id_tag,
|
||||
"long_name" = sanitize(long_name),
|
||||
"pressure" = info["pressure"],
|
||||
"temperature" = info["temperature"],
|
||||
"gases" = info["gases"]
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["id_tag"]
|
||||
if(!id_tag || !sensors.Find(id_tag))
|
||||
return
|
||||
|
||||
sensor_information[id_tag] = signal.data
|
||||
|
||||
/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// LARGE TANK CONTROL
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank
|
||||
var/input_tag
|
||||
var/output_tag
|
||||
frequency = FREQ_ATMOS_STORAGE
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank
|
||||
|
||||
var/list/input_info
|
||||
var/list/output_info
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/oxygen_tank
|
||||
name = "Oxygen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/toxin_tank
|
||||
name = "Plasma Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_TOX
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_TOX
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/air_tank
|
||||
name = "Mixed Air Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_AIR
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/mix_tank
|
||||
name = "Gas Mix Tank Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_MIX
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrous_tank
|
||||
name = "Nitrous Oxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2O
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrogen_tank
|
||||
name = "Nitrogen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/carbon_tank
|
||||
name = "Carbon Dioxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_CO2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/incinerator
|
||||
name = "Incinerator Air Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_INCINERATOR
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
|
||||
|
||||
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
|
||||
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
|
||||
var/list/IO = list()
|
||||
var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
|
||||
var/list/devices = freq.devices["_default"]
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
IO |= text[1]
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
var/list/text = splittext(U.id, "_")
|
||||
IO |= text[1]
|
||||
if(!IO.len)
|
||||
to_chat(user, "<span class='alert'>No machinery detected.</span>")
|
||||
var/S = input("Select the device set: ", "Selection", IO[1]) as anything in IO
|
||||
if(src)
|
||||
src.input_tag = "[S]_in"
|
||||
src.output_tag = "[S]_out"
|
||||
name = "[uppertext(S)] Supply Control"
|
||||
var/list/new_devices = freq.devices["4"]
|
||||
for(var/obj/machinery/air_sensor/U in new_devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
if(text[1] == S)
|
||||
sensors = list("[S]_sensor" = "Tank")
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
U.broadcast_status()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
U.broadcast_status()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_control", name, 500, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["tank"] = TRUE
|
||||
data["inputting"] = input_info ? input_info["power"] : FALSE
|
||||
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
|
||||
data["outputting"] = output_info ? output_info["power"] : FALSE
|
||||
data["outputPressure"] = output_info ? output_info["internal"] : 0
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
|
||||
if(..() || !radio_connection)
|
||||
return
|
||||
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
|
||||
switch(action)
|
||||
if("reconnect")
|
||||
reconnect(usr)
|
||||
. = TRUE
|
||||
if("input")
|
||||
signal.data += list("tag" = input_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("output")
|
||||
signal.data += list("tag" = output_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("pressure")
|
||||
var/target = input("New target pressure:", name, output_info ? output_info["internal"] : 0) as num|null
|
||||
if(!isnull(target) && !..())
|
||||
target = CLAMP(target, 0, 50 * ONE_ATMOSPHERE)
|
||||
signal.data += list("tag" = output_tag, "set_internal_pressure" = target)
|
||||
. = TRUE
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["tag"]
|
||||
|
||||
if(input_tag == id_tag)
|
||||
input_info = signal.data
|
||||
else if(output_tag == id_tag)
|
||||
output_info = signal.data
|
||||
else
|
||||
..(signal)
|
||||
/////////////////////////////////////////////////////////////
|
||||
// AIR SENSOR (found in gas tanks)
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/air_sensor
|
||||
name = "gas sensor"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "gsensor1"
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
var/id_tag
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/air_sensor/atmos/toxin_tank
|
||||
name = "plasma tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_TOX
|
||||
/obj/machinery/air_sensor/atmos/toxins_mixing_tank
|
||||
name = "toxins mixing gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB
|
||||
/obj/machinery/air_sensor/atmos/oxygen_tank
|
||||
name = "oxygen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_O2
|
||||
/obj/machinery/air_sensor/atmos/nitrogen_tank
|
||||
name = "nitrogen tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2
|
||||
/obj/machinery/air_sensor/atmos/mix_tank
|
||||
name = "mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX
|
||||
/obj/machinery/air_sensor/atmos/nitrous_tank
|
||||
name = "nitrous oxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O
|
||||
/obj/machinery/air_sensor/atmos/air_tank
|
||||
name = "air mix tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR
|
||||
/obj/machinery/air_sensor/atmos/carbon_tank
|
||||
name = "carbon dioxide tank gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2
|
||||
/obj/machinery/air_sensor/atmos/incinerator_tank
|
||||
name = "incinerator chamber gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR
|
||||
|
||||
/obj/machinery/air_sensor/update_icon()
|
||||
icon_state = "gsensor[on]"
|
||||
|
||||
/obj/machinery/air_sensor/process_atmos()
|
||||
if(on)
|
||||
var/datum/gas_mixture/air_sample = return_air()
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"sigtype" = "status",
|
||||
"id_tag" = id_tag,
|
||||
"timestamp" = world.time,
|
||||
"pressure" = air_sample.return_pressure(),
|
||||
"temperature" = air_sample.temperature,
|
||||
"gases" = list()
|
||||
))
|
||||
var/total_moles = air_sample.total_moles()
|
||||
if(total_moles)
|
||||
for(var/gas_id in air_sample.gases)
|
||||
var/gas_name = GLOB.meta_gas_names[gas_id]
|
||||
signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
|
||||
/obj/machinery/air_sensor/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/air_sensor/Initialize()
|
||||
. = ..()
|
||||
SSair.atmos_machinery += src
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/air_sensor/Destroy()
|
||||
SSair.atmos_machinery -= src
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// GENERAL AIR CONTROL (a.k.a atmos computer)
|
||||
/////////////////////////////////////////////////////////////
|
||||
GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
|
||||
/obj/machinery/computer/atmos_control
|
||||
name = "atmospherics monitoring"
|
||||
desc = "Used to monitor the station's atmospherics sensors."
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
|
||||
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
|
||||
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
|
||||
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
|
||||
ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber"
|
||||
)
|
||||
var/list/sensor_information = list()
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/atmos_control/Initialize()
|
||||
. = ..()
|
||||
GLOB.atmos_air_controllers += src
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/computer/atmos_control/Destroy()
|
||||
GLOB.atmos_air_controllers -= src
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_control", name, 400, 925, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_data(mob/user)
|
||||
var/data = list()
|
||||
|
||||
data["sensors"] = list()
|
||||
for(var/id_tag in sensors)
|
||||
var/long_name = sensors[id_tag]
|
||||
var/list/info = sensor_information[id_tag]
|
||||
if(!info)
|
||||
continue
|
||||
data["sensors"] += list(list(
|
||||
"id_tag" = id_tag,
|
||||
"long_name" = sanitize(long_name),
|
||||
"pressure" = info["pressure"],
|
||||
"temperature" = info["temperature"],
|
||||
"gases" = info["gases"]
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["id_tag"]
|
||||
if(!id_tag || !sensors.Find(id_tag))
|
||||
return
|
||||
|
||||
sensor_information[id_tag] = signal.data
|
||||
|
||||
/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// LARGE TANK CONTROL
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank
|
||||
var/input_tag
|
||||
var/output_tag
|
||||
frequency = FREQ_ATMOS_STORAGE
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank
|
||||
|
||||
var/list/input_info
|
||||
var/list/output_info
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/oxygen_tank
|
||||
name = "Oxygen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/toxin_tank
|
||||
name = "Plasma Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_TOX
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_TOX
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/air_tank
|
||||
name = "Mixed Air Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_AIR
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/mix_tank
|
||||
name = "Gas Mix Tank Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_MIX
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrous_tank
|
||||
name = "Nitrous Oxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2O
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/nitrogen_tank
|
||||
name = "Nitrogen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_N2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/carbon_tank
|
||||
name = "Carbon Dioxide Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_CO2
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank")
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/incinerator
|
||||
name = "Incinerator Air Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_INCINERATOR
|
||||
output_tag = ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
|
||||
|
||||
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
|
||||
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
|
||||
var/list/IO = list()
|
||||
var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
|
||||
var/list/devices = freq.devices["_default"]
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
IO |= text[1]
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
var/list/text = splittext(U.id, "_")
|
||||
IO |= text[1]
|
||||
if(!IO.len)
|
||||
to_chat(user, "<span class='alert'>No machinery detected.</span>")
|
||||
var/S = input("Select the device set: ", "Selection", IO[1]) as anything in IO
|
||||
if(src)
|
||||
src.input_tag = "[S]_in"
|
||||
src.output_tag = "[S]_out"
|
||||
name = "[uppertext(S)] Supply Control"
|
||||
var/list/new_devices = freq.devices["4"]
|
||||
for(var/obj/machinery/air_sensor/U in new_devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
if(text[1] == S)
|
||||
sensors = list("[S]_sensor" = "Tank")
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
U.broadcast_status()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
U.broadcast_status()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "atmos_control", name, 500, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["tank"] = TRUE
|
||||
data["inputting"] = input_info ? input_info["power"] : FALSE
|
||||
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
|
||||
data["outputting"] = output_info ? output_info["power"] : FALSE
|
||||
data["outputPressure"] = output_info ? output_info["internal"] : 0
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
|
||||
if(..() || !radio_connection)
|
||||
return
|
||||
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
|
||||
switch(action)
|
||||
if("reconnect")
|
||||
reconnect(usr)
|
||||
. = TRUE
|
||||
if("input")
|
||||
signal.data += list("tag" = input_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("output")
|
||||
signal.data += list("tag" = output_tag, "power_toggle" = TRUE)
|
||||
. = TRUE
|
||||
if("pressure")
|
||||
var/target = input("New target pressure:", name, output_info ? output_info["internal"] : 0) as num|null
|
||||
if(!isnull(target) && !..())
|
||||
target = CLAMP(target, 0, 50 * ONE_ATMOSPHERE)
|
||||
signal.data += list("tag" = output_tag, "set_internal_pressure" = target)
|
||||
. = TRUE
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
var/id_tag = signal.data["tag"]
|
||||
|
||||
if(input_tag == id_tag)
|
||||
input_info = signal.data
|
||||
else if(output_tag == id_tag)
|
||||
output_info = signal.data
|
||||
else
|
||||
..(signal)
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
/obj/structure/frame/computer
|
||||
name = "computer frame"
|
||||
icon_state = "0"
|
||||
state = 0
|
||||
|
||||
/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
switch(state)
|
||||
if(0)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start wrenching the frame into place...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50))
|
||||
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
|
||||
setAnchored(TRUE)
|
||||
state = 1
|
||||
return
|
||||
if(istype(P, /obj/item/weldingtool))
|
||||
if(!P.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start deconstructing the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 0)
|
||||
to_chat(user, "<span class='notice'>You deconstruct the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (drop_location(), 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
return
|
||||
if(1)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start to unfasten the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 1)
|
||||
to_chat(user, "<span class='notice'>You unfasten the frame.</span>")
|
||||
setAnchored(FALSE)
|
||||
state = 0
|
||||
return
|
||||
if(istype(P, /obj/item/circuitboard/computer) && !circuit)
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You place [P] inside the frame.</span>")
|
||||
icon_state = "1"
|
||||
circuit = P
|
||||
circuit.add_fingerprint(user)
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard) && !circuit)
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You screw [circuit] into place.</span>")
|
||||
state = 2
|
||||
icon_state = "2"
|
||||
return
|
||||
if(istype(P, /obj/item/crowbar) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove [circuit].</span>")
|
||||
state = 1
|
||||
icon_state = "0"
|
||||
circuit.forceMove(drop_location())
|
||||
circuit.add_fingerprint(user)
|
||||
circuit = null
|
||||
return
|
||||
if(2)
|
||||
if(istype(P, /obj/item/screwdriver) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You unfasten the circuit board.</span>")
|
||||
state = 1
|
||||
icon_state = "1"
|
||||
return
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2)))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
state = 3
|
||||
icon_state = "3"
|
||||
return
|
||||
if(3)
|
||||
if(istype(P, /obj/item/wirecutters))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the cables.</span>")
|
||||
state = 2
|
||||
icon_state = "2"
|
||||
var/obj/item/stack/cable_coil/A = new (drop_location(), 5)
|
||||
A.add_fingerprint(user)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/stack/sheet/glass))
|
||||
if(!P.tool_start_check(user, amount=2))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You start to put in the glass panel...</span>")
|
||||
if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3)))
|
||||
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
|
||||
state = 4
|
||||
src.icon_state = "4"
|
||||
return
|
||||
if(4)
|
||||
if(istype(P, /obj/item/crowbar))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the glass panel.</span>")
|
||||
state = 3
|
||||
icon_state = "3"
|
||||
var/obj/item/stack/sheet/glass/G = new(drop_location(), 2)
|
||||
G.add_fingerprint(user)
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
|
||||
var/obj/B = new circuit.build_path (loc, circuit)
|
||||
B.setDir(dir)
|
||||
transfer_fingerprints_to(B)
|
||||
qdel(src)
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking.
|
||||
/obj/structure/frame/computer/proc/check_state(target_state)
|
||||
if(state == target_state)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/frame/computer/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(state == 4)
|
||||
new /obj/item/shard(drop_location())
|
||||
new /obj/item/shard(drop_location())
|
||||
if(state >= 3)
|
||||
new /obj/item/stack/cable_coil(drop_location(), 5)
|
||||
..()
|
||||
|
||||
/obj/structure/frame/computer/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "<span class='warning'>You must unwrench [src] before rotating it!</span>")
|
||||
return TRUE
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
return TRUE
|
||||
/obj/structure/frame/computer
|
||||
name = "computer frame"
|
||||
icon_state = "0"
|
||||
state = 0
|
||||
|
||||
/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
switch(state)
|
||||
if(0)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start wrenching the frame into place...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50))
|
||||
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
|
||||
setAnchored(TRUE)
|
||||
state = 1
|
||||
return
|
||||
if(istype(P, /obj/item/weldingtool))
|
||||
if(!P.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start deconstructing the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 0)
|
||||
to_chat(user, "<span class='notice'>You deconstruct the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (drop_location(), 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
return
|
||||
if(1)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start to unfasten the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 1)
|
||||
to_chat(user, "<span class='notice'>You unfasten the frame.</span>")
|
||||
setAnchored(FALSE)
|
||||
state = 0
|
||||
return
|
||||
if(istype(P, /obj/item/circuitboard/computer) && !circuit)
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You place [P] inside the frame.</span>")
|
||||
icon_state = "1"
|
||||
circuit = P
|
||||
circuit.add_fingerprint(user)
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard) && !circuit)
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You screw [circuit] into place.</span>")
|
||||
state = 2
|
||||
icon_state = "2"
|
||||
return
|
||||
if(istype(P, /obj/item/crowbar) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove [circuit].</span>")
|
||||
state = 1
|
||||
icon_state = "0"
|
||||
circuit.forceMove(drop_location())
|
||||
circuit.add_fingerprint(user)
|
||||
circuit = null
|
||||
return
|
||||
if(2)
|
||||
if(istype(P, /obj/item/screwdriver) && circuit)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You unfasten the circuit board.</span>")
|
||||
state = 1
|
||||
icon_state = "1"
|
||||
return
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2)))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
state = 3
|
||||
icon_state = "3"
|
||||
return
|
||||
if(3)
|
||||
if(istype(P, /obj/item/wirecutters))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the cables.</span>")
|
||||
state = 2
|
||||
icon_state = "2"
|
||||
var/obj/item/stack/cable_coil/A = new (drop_location(), 5)
|
||||
A.add_fingerprint(user)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/stack/sheet/glass))
|
||||
if(!P.tool_start_check(user, amount=2))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You start to put in the glass panel...</span>")
|
||||
if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3)))
|
||||
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
|
||||
state = 4
|
||||
src.icon_state = "4"
|
||||
return
|
||||
if(4)
|
||||
if(istype(P, /obj/item/crowbar))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the glass panel.</span>")
|
||||
state = 3
|
||||
icon_state = "3"
|
||||
var/obj/item/stack/sheet/glass/G = new(drop_location(), 2)
|
||||
G.add_fingerprint(user)
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
|
||||
var/obj/B = new circuit.build_path (loc, circuit)
|
||||
B.setDir(dir)
|
||||
transfer_fingerprints_to(B)
|
||||
qdel(src)
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking.
|
||||
/obj/structure/frame/computer/proc/check_state(target_state)
|
||||
if(state == target_state)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/frame/computer/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(state == 4)
|
||||
new /obj/item/shard(drop_location())
|
||||
new /obj/item/shard(drop_location())
|
||||
if(state >= 3)
|
||||
new /obj/item/stack/cable_coil(drop_location(), 5)
|
||||
..()
|
||||
|
||||
/obj/structure/frame/computer/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "<span class='warning'>You must unwrench [src] before rotating it!</span>")
|
||||
return TRUE
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
return TRUE
|
||||
|
||||
@@ -1,254 +1,254 @@
|
||||
/obj/machinery/computer/security
|
||||
name = "security camera console"
|
||||
desc = "Used to access the various cameras on the station."
|
||||
icon_screen = "cameras"
|
||||
icon_keyboard = "security_key"
|
||||
circuit = /obj/item/circuitboard/computer/security
|
||||
var/last_pic = 1
|
||||
var/list/network = list("ss13")
|
||||
var/list/watchers = list() //who's using the console, associated with the camera they're on.
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/machinery/computer/security/Initialize()
|
||||
. = ..()
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += lowertext(i)
|
||||
|
||||
/obj/machinery/computer/security/check_eye(mob/user)
|
||||
if(!can_interact(user) || !(user in watchers) || !watchers[user])
|
||||
user.unset_machine()
|
||||
return
|
||||
var/obj/machinery/camera/C = watchers[user]
|
||||
if(!C.can_use())
|
||||
user.unset_machine()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/on_unset_machine(mob/user)
|
||||
watchers.Remove(user)
|
||||
user.reset_perspective(null)
|
||||
|
||||
/obj/machinery/computer/security/Destroy()
|
||||
if(watchers.len)
|
||||
for(var/mob/M in watchers)
|
||||
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/can_interact(mob/user)
|
||||
if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/interact(mob/user, special_state)
|
||||
. = ..()
|
||||
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
|
||||
return
|
||||
if (!network)
|
||||
CRASH("No camera network")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
if (!(islist(network)))
|
||||
CRASH("Camera network is not a list")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
|
||||
var/list/camera_list = get_available_cameras()
|
||||
if(!(user in watchers))
|
||||
for(var/Num in camera_list)
|
||||
var/obj/machinery/camera/CAM = camera_list[Num]
|
||||
if(istype(CAM) && CAM.can_use())
|
||||
watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
|
||||
break
|
||||
if(!(user in watchers))
|
||||
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
|
||||
return FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
|
||||
use_camera_console(user)
|
||||
|
||||
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
|
||||
var/list/camera_list = get_available_cameras()
|
||||
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
|
||||
if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
|
||||
return
|
||||
if(!t || t == "Cancel")
|
||||
user.unset_machine()
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
|
||||
return
|
||||
|
||||
var/obj/machinery/camera/C = camera_list[t]
|
||||
|
||||
if(!C || !C.can_use() || !can_interact(user))
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
if(isAI(user))
|
||||
var/mob/living/silicon/ai/A = user
|
||||
A.eyeobj.setLoc(get_turf(C))
|
||||
A.client.eye = A.eyeobj
|
||||
else
|
||||
user.reset_perspective(C)
|
||||
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
||||
user.clear_fullscreen("flash", 5)
|
||||
watchers[user] = C
|
||||
use_power(50)
|
||||
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
|
||||
|
||||
//returns the list of cameras accessible from this computer
|
||||
/obj/machinery/computer/security/proc/get_available_cameras()
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras
|
||||
continue
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
|
||||
var/list/D = list()
|
||||
D["Cancel"] = "Cancel"
|
||||
for(var/obj/machinery/camera/C in L)
|
||||
if(!C.network)
|
||||
stack_trace("Camera in a cameranet has no camera network")
|
||||
continue
|
||||
if(!(islist(C.network)))
|
||||
stack_trace("Camera in a cameranet has a non-list camera network")
|
||||
continue
|
||||
var/list/tempnetwork = C.network&network
|
||||
if(tempnetwork.len)
|
||||
D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C
|
||||
return D
|
||||
|
||||
// SECURITY MONITORS
|
||||
|
||||
/obj/machinery/computer/security/wooden_tv
|
||||
name = "security camera monitor"
|
||||
desc = "An old TV hooked into the station's camera network."
|
||||
icon_state = "television"
|
||||
icon_keyboard = null
|
||||
icon_screen = "detective_tv"
|
||||
clockwork = TRUE //it'd look weird
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
/obj/machinery/computer/security/mining
|
||||
name = "outpost camera console"
|
||||
desc = "Used to access the various cameras on the outpost."
|
||||
icon_screen = "mining"
|
||||
icon_keyboard = "mining_key"
|
||||
network = list("mine", "auxbase")
|
||||
circuit = /obj/item/circuitboard/computer/mining
|
||||
|
||||
/obj/machinery/computer/security/research
|
||||
name = "research camera console"
|
||||
desc = "Used to access the various cameras in science."
|
||||
network = list("rd")
|
||||
circuit = /obj/item/circuitboard/computer/research
|
||||
|
||||
/obj/machinery/computer/security/hos
|
||||
name = "Head of Security's camera console"
|
||||
desc = "A custom security console with added access to the labor camp network."
|
||||
network = list("ss13", "labor")
|
||||
circuit = null
|
||||
|
||||
/obj/machinery/computer/security/labor
|
||||
name = "labor camp monitoring"
|
||||
desc = "Used to access the various cameras on the labor camp."
|
||||
network = list("labor")
|
||||
circuit = null
|
||||
|
||||
/obj/machinery/computer/security/qm
|
||||
name = "Quartermaster's camera console"
|
||||
desc = "A console with access to the mining, auxillary base and vault camera networks."
|
||||
network = list("mine", "auxbase", "vault")
|
||||
circuit = null
|
||||
|
||||
// TELESCREENS
|
||||
|
||||
/obj/machinery/computer/security/telescreen
|
||||
name = "\improper Telescreen"
|
||||
desc = "Used for watching an empty arena."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "telescreen"
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
clockwork = TRUE //it'd look very weird
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/update_icon()
|
||||
icon_state = initial(icon_state)
|
||||
if(stat & BROKEN)
|
||||
icon_state += "b"
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment
|
||||
name = "entertainment monitor"
|
||||
desc = "Damn, they better have the /tg/ channel on these things."
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "entertainment"
|
||||
network = list("thunder")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/rd
|
||||
name = "Research Director's telescreen"
|
||||
desc = "Used for watching the AI and the RD's goons from the safety of his office."
|
||||
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/circuitry
|
||||
name = "circuitry telescreen"
|
||||
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
|
||||
network = list("rd")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/ce
|
||||
name = "Chief Engineer's telescreen"
|
||||
desc = "Used for watching the engine, telecommunications and the minisat."
|
||||
network = list("engine", "singularity", "tcomms", "minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/cmo
|
||||
name = "Chief Medical Officer's telescreen"
|
||||
desc = "A telescreen with access to the medbay's camera network."
|
||||
network = list("medbay")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/vault
|
||||
name = "Vault monitor"
|
||||
desc = "A telescreen that connects to the vault's camera network."
|
||||
network = list("vault")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/toxins
|
||||
name = "Bomb test site monitor"
|
||||
desc = "A telescreen that connects to the bomb test site's camera."
|
||||
network = list("toxin")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/engine
|
||||
name = "engine monitor"
|
||||
desc = "A telescreen that connects to the engine's camera network."
|
||||
network = list("engine")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/turbine
|
||||
name = "turbine monitor"
|
||||
desc = "A telescreen that connects to the turbine's camera."
|
||||
network = list("turbine")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/interrogation
|
||||
name = "interrogation room monitor"
|
||||
desc = "A telescreen that connects to the interrogation room's camera."
|
||||
network = list("interrogation")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/prison
|
||||
name = "prison monitor"
|
||||
desc = "A telescreen that connects to the permabrig's camera network."
|
||||
network = list("prison")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/auxbase
|
||||
name = "auxillary base monitor"
|
||||
desc = "A telescreen that connects to the auxillary base's camera."
|
||||
network = list("auxbase")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/minisat
|
||||
name = "minisat monitor"
|
||||
desc = "A telescreen that connects to the minisat's camera network."
|
||||
network = list("minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/aiupload
|
||||
name = "AI upload monitor"
|
||||
desc = "A telescreen that connects to the AI upload's camera network."
|
||||
network = list("aiupload")
|
||||
/obj/machinery/computer/security
|
||||
name = "security camera console"
|
||||
desc = "Used to access the various cameras on the station."
|
||||
icon_screen = "cameras"
|
||||
icon_keyboard = "security_key"
|
||||
circuit = /obj/item/circuitboard/computer/security
|
||||
var/last_pic = 1
|
||||
var/list/network = list("ss13")
|
||||
var/list/watchers = list() //who's using the console, associated with the camera they're on.
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/machinery/computer/security/Initialize()
|
||||
. = ..()
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += lowertext(i)
|
||||
|
||||
/obj/machinery/computer/security/check_eye(mob/user)
|
||||
if(!can_interact(user) || !(user in watchers) || !watchers[user])
|
||||
user.unset_machine()
|
||||
return
|
||||
var/obj/machinery/camera/C = watchers[user]
|
||||
if(!C.can_use())
|
||||
user.unset_machine()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/on_unset_machine(mob/user)
|
||||
watchers.Remove(user)
|
||||
user.reset_perspective(null)
|
||||
|
||||
/obj/machinery/computer/security/Destroy()
|
||||
if(watchers.len)
|
||||
for(var/mob/M in watchers)
|
||||
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/can_interact(mob/user)
|
||||
if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/interact(mob/user, special_state)
|
||||
. = ..()
|
||||
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
|
||||
return
|
||||
if (!network)
|
||||
CRASH("No camera network")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
if (!(islist(network)))
|
||||
CRASH("Camera network is not a list")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
|
||||
var/list/camera_list = get_available_cameras()
|
||||
if(!(user in watchers))
|
||||
for(var/Num in camera_list)
|
||||
var/obj/machinery/camera/CAM = camera_list[Num]
|
||||
if(istype(CAM) && CAM.can_use())
|
||||
watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
|
||||
break
|
||||
if(!(user in watchers))
|
||||
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
|
||||
return FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
|
||||
use_camera_console(user)
|
||||
|
||||
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
|
||||
var/list/camera_list = get_available_cameras()
|
||||
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
|
||||
if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
|
||||
return
|
||||
if(!t || t == "Cancel")
|
||||
user.unset_machine()
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
|
||||
return
|
||||
|
||||
var/obj/machinery/camera/C = camera_list[t]
|
||||
|
||||
if(!C || !C.can_use() || !can_interact(user))
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
if(isAI(user))
|
||||
var/mob/living/silicon/ai/A = user
|
||||
A.eyeobj.setLoc(get_turf(C))
|
||||
A.client.eye = A.eyeobj
|
||||
else
|
||||
user.reset_perspective(C)
|
||||
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
||||
user.clear_fullscreen("flash", 5)
|
||||
watchers[user] = C
|
||||
use_power(50)
|
||||
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
|
||||
|
||||
//returns the list of cameras accessible from this computer
|
||||
/obj/machinery/computer/security/proc/get_available_cameras()
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras
|
||||
continue
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
|
||||
var/list/D = list()
|
||||
D["Cancel"] = "Cancel"
|
||||
for(var/obj/machinery/camera/C in L)
|
||||
if(!C.network)
|
||||
stack_trace("Camera in a cameranet has no camera network")
|
||||
continue
|
||||
if(!(islist(C.network)))
|
||||
stack_trace("Camera in a cameranet has a non-list camera network")
|
||||
continue
|
||||
var/list/tempnetwork = C.network&network
|
||||
if(tempnetwork.len)
|
||||
D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C
|
||||
return D
|
||||
|
||||
// SECURITY MONITORS
|
||||
|
||||
/obj/machinery/computer/security/wooden_tv
|
||||
name = "security camera monitor"
|
||||
desc = "An old TV hooked into the station's camera network."
|
||||
icon_state = "television"
|
||||
icon_keyboard = null
|
||||
icon_screen = "detective_tv"
|
||||
clockwork = TRUE //it'd look weird
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
/obj/machinery/computer/security/mining
|
||||
name = "outpost camera console"
|
||||
desc = "Used to access the various cameras on the outpost."
|
||||
icon_screen = "mining"
|
||||
icon_keyboard = "mining_key"
|
||||
network = list("mine", "auxbase")
|
||||
circuit = /obj/item/circuitboard/computer/mining
|
||||
|
||||
/obj/machinery/computer/security/research
|
||||
name = "research camera console"
|
||||
desc = "Used to access the various cameras in science."
|
||||
network = list("rd")
|
||||
circuit = /obj/item/circuitboard/computer/research
|
||||
|
||||
/obj/machinery/computer/security/hos
|
||||
name = "Head of Security's camera console"
|
||||
desc = "A custom security console with added access to the labor camp network."
|
||||
network = list("ss13", "labor")
|
||||
circuit = null
|
||||
|
||||
/obj/machinery/computer/security/labor
|
||||
name = "labor camp monitoring"
|
||||
desc = "Used to access the various cameras on the labor camp."
|
||||
network = list("labor")
|
||||
circuit = null
|
||||
|
||||
/obj/machinery/computer/security/qm
|
||||
name = "Quartermaster's camera console"
|
||||
desc = "A console with access to the mining, auxillary base and vault camera networks."
|
||||
network = list("mine", "auxbase", "vault")
|
||||
circuit = null
|
||||
|
||||
// TELESCREENS
|
||||
|
||||
/obj/machinery/computer/security/telescreen
|
||||
name = "\improper Telescreen"
|
||||
desc = "Used for watching an empty arena."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "telescreen"
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
clockwork = TRUE //it'd look very weird
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/update_icon()
|
||||
icon_state = initial(icon_state)
|
||||
if(stat & BROKEN)
|
||||
icon_state += "b"
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment
|
||||
name = "entertainment monitor"
|
||||
desc = "Damn, they better have the /tg/ channel on these things."
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "entertainment"
|
||||
network = list("thunder")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/rd
|
||||
name = "Research Director's telescreen"
|
||||
desc = "Used for watching the AI and the RD's goons from the safety of his office."
|
||||
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/circuitry
|
||||
name = "circuitry telescreen"
|
||||
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
|
||||
network = list("rd")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/ce
|
||||
name = "Chief Engineer's telescreen"
|
||||
desc = "Used for watching the engine, telecommunications and the minisat."
|
||||
network = list("engine", "singularity", "tcomms", "minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/cmo
|
||||
name = "Chief Medical Officer's telescreen"
|
||||
desc = "A telescreen with access to the medbay's camera network."
|
||||
network = list("medbay")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/vault
|
||||
name = "Vault monitor"
|
||||
desc = "A telescreen that connects to the vault's camera network."
|
||||
network = list("vault")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/toxins
|
||||
name = "Bomb test site monitor"
|
||||
desc = "A telescreen that connects to the bomb test site's camera."
|
||||
network = list("toxin")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/engine
|
||||
name = "engine monitor"
|
||||
desc = "A telescreen that connects to the engine's camera network."
|
||||
network = list("engine")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/turbine
|
||||
name = "turbine monitor"
|
||||
desc = "A telescreen that connects to the turbine's camera."
|
||||
network = list("turbine")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/interrogation
|
||||
name = "interrogation room monitor"
|
||||
desc = "A telescreen that connects to the interrogation room's camera."
|
||||
network = list("interrogation")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/prison
|
||||
name = "prison monitor"
|
||||
desc = "A telescreen that connects to the permabrig's camera network."
|
||||
network = list("prison")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/auxbase
|
||||
name = "auxillary base monitor"
|
||||
desc = "A telescreen that connects to the auxillary base's camera."
|
||||
network = list("auxbase")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/minisat
|
||||
name = "minisat monitor"
|
||||
desc = "A telescreen that connects to the minisat's camera network."
|
||||
network = list("minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/aiupload
|
||||
name = "AI upload monitor"
|
||||
desc = "A telescreen that connects to the AI upload's camera network."
|
||||
network = list("aiupload")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,210 +1,210 @@
|
||||
#define SENSORS_UPDATE_PERIOD 100 //How often the sensor data updates.
|
||||
|
||||
/obj/machinery/computer/crew
|
||||
name = "crew monitoring console"
|
||||
desc = "Used to monitor active health sensors built into most of the crew's uniforms."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 250
|
||||
active_power_usage = 500
|
||||
circuit = /obj/item/circuitboard/computer/crew
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/crew/syndie
|
||||
icon_keyboard = "syndie_key"
|
||||
|
||||
/obj/machinery/computer/crew/interact(mob/user)
|
||||
GLOB.crewmonitor.show(user,src)
|
||||
|
||||
GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
|
||||
/datum/crewmonitor
|
||||
var/list/ui_sources = list() //List of user -> ui source
|
||||
var/list/jobs
|
||||
var/list/data_by_z = list()
|
||||
var/list/last_update = list()
|
||||
|
||||
/datum/crewmonitor/New()
|
||||
. = ..()
|
||||
|
||||
var/list/jobs = new/list()
|
||||
jobs["Captain"] = 00
|
||||
jobs["Head of Security"] = 10
|
||||
jobs["Warden"] = 11
|
||||
jobs["Security Officer"] = 12
|
||||
jobs["Detective"] = 13
|
||||
jobs["Chief Medical Officer"] = 20
|
||||
jobs["Chemist"] = 21
|
||||
jobs["Geneticist"] = 22
|
||||
jobs["Virologist"] = 23
|
||||
jobs["Medical Doctor"] = 24
|
||||
jobs["Research Director"] = 30
|
||||
jobs["Scientist"] = 31
|
||||
jobs["Roboticist"] = 32
|
||||
jobs["Chief Engineer"] = 40
|
||||
jobs["Station Engineer"] = 41
|
||||
jobs["Atmospheric Technician"] = 42
|
||||
jobs["Quartermaster"] = 50
|
||||
jobs["Shaft Miner"] = 51
|
||||
jobs["Cargo Technician"] = 52
|
||||
jobs["Head of Personnel"] = 60
|
||||
jobs["Bartender"] = 61
|
||||
jobs["Cook"] = 62
|
||||
jobs["Botanist"] = 63
|
||||
jobs["Curator"] = 64
|
||||
jobs["Chaplain"] = 65
|
||||
jobs["Clown"] = 66
|
||||
jobs["Mime"] = 67
|
||||
jobs["Janitor"] = 68
|
||||
jobs["Lawyer"] = 69
|
||||
jobs["Admiral"] = 200
|
||||
jobs["CentCom Commander"] = 210
|
||||
jobs["Custodian"] = 211
|
||||
jobs["Medical Officer"] = 212
|
||||
jobs["Research Officer"] = 213
|
||||
jobs["Emergency Response Team Commander"] = 220
|
||||
jobs["Security Response Officer"] = 221
|
||||
jobs["Engineer Response Officer"] = 222
|
||||
jobs["Medical Response Officer"] = 223
|
||||
jobs["Assistant"] = 999 //Unknowns/custom jobs should appear after civilians, and before assistants
|
||||
|
||||
src.jobs = jobs
|
||||
|
||||
/datum/crewmonitor/Destroy()
|
||||
return ..()
|
||||
|
||||
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
ui_sources[M] = source
|
||||
ui_interact(M)
|
||||
|
||||
/datum/crewmonitor/ui_host(mob/user)
|
||||
return ui_sources[user]
|
||||
|
||||
/datum/crewmonitor/ui_data(mob/user)
|
||||
var/z = user.z
|
||||
if(!z)
|
||||
var/turf/T = get_turf(user)
|
||||
z = T.z
|
||||
var/list/zdata = update_data(z)
|
||||
. = list()
|
||||
.["sensors"] = zdata
|
||||
.["link_allowed"] = isAI(user)
|
||||
|
||||
/datum/crewmonitor/proc/update_data(z)
|
||||
if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD)
|
||||
return data_by_z["[z]"]
|
||||
|
||||
var/list/results_damaged = list()
|
||||
var/list/results_undamaged = list()
|
||||
|
||||
var/obj/item/clothing/under/U
|
||||
var/obj/item/card/id/I
|
||||
var/turf/pos
|
||||
var/ijob
|
||||
var/name
|
||||
var/assignment
|
||||
var/oxydam
|
||||
var/toxdam
|
||||
var/burndam
|
||||
var/brutedam
|
||||
var/totaldam
|
||||
var/area
|
||||
var/pos_x
|
||||
var/pos_y
|
||||
var/life_status
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
|
||||
var/nanite_sensors = FALSE
|
||||
if(H in SSnanites.nanite_monitored_mobs)
|
||||
nanite_sensors = TRUE
|
||||
// Check if their z-level is correct and if they are wearing a uniform.
|
||||
// Accept H.z==0 as well in case the mob is inside an object.
|
||||
if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under) || nanite_sensors)
|
||||
U = H.w_uniform
|
||||
|
||||
// Are the suit sensors on?
|
||||
if (nanite_sensors || ((U.has_sensor > 0) && U.sensor_mode))
|
||||
pos = H.z == 0 || (nanite_sensors || U.sensor_mode == SENSOR_COORDS) ? get_turf(H) : null
|
||||
|
||||
// Special case: If the mob is inside an object confirm the z-level on turf level.
|
||||
if (H.z == 0 && (!pos || pos.z != z))
|
||||
continue
|
||||
|
||||
I = H.wear_id ? H.wear_id.GetID() : null
|
||||
|
||||
if (I)
|
||||
name = I.registered_name
|
||||
assignment = I.assignment
|
||||
ijob = jobs[I.assignment]
|
||||
else
|
||||
name = "Unknown"
|
||||
assignment = ""
|
||||
ijob = 80
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_LIVING)
|
||||
life_status = (!H.stat ? TRUE : FALSE)
|
||||
else
|
||||
life_status = null
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_VITALS)
|
||||
oxydam = round(H.getOxyLoss(),1)
|
||||
toxdam = round(H.getToxLoss(),1)
|
||||
burndam = round(H.getFireLoss(),1)
|
||||
brutedam = round(H.getBruteLoss(),1)
|
||||
totaldam = oxydam + toxdam + burndam + brutedam
|
||||
else
|
||||
oxydam = null
|
||||
toxdam = null
|
||||
burndam = null
|
||||
brutedam = null
|
||||
totaldam = 0
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos)
|
||||
pos = get_turf(H)
|
||||
area = get_area_name(H, TRUE)
|
||||
pos_x = pos.x
|
||||
pos_y = pos.y
|
||||
else
|
||||
area = null
|
||||
pos_x = null
|
||||
pos_y = null
|
||||
|
||||
var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null))
|
||||
|
||||
if(totaldam)
|
||||
results_damaged[++results_damaged.len] = total_list
|
||||
else
|
||||
results_undamaged[++results_undamaged.len] = total_list
|
||||
|
||||
var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare)
|
||||
|
||||
data_by_z["[z]"] = returning
|
||||
last_update["[z]"] = world.time
|
||||
|
||||
return returning
|
||||
|
||||
/proc/ijob_compare(list/a,list/b)
|
||||
return a["ijob"] - b["ijob"]
|
||||
|
||||
/proc/damage_compare(list/a,list/b)
|
||||
return b["totaldam"] - a["totaldam"]
|
||||
|
||||
/datum/crewmonitor/ui_act(action,params)
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
if(!istype(AI))
|
||||
return
|
||||
switch (action)
|
||||
if ("select_person")
|
||||
AI.ai_camera_track(params["name"])
|
||||
|
||||
#define SENSORS_UPDATE_PERIOD 100 //How often the sensor data updates.
|
||||
|
||||
/obj/machinery/computer/crew
|
||||
name = "crew monitoring console"
|
||||
desc = "Used to monitor active health sensors built into most of the crew's uniforms."
|
||||
icon_screen = "crew"
|
||||
icon_keyboard = "med_key"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 250
|
||||
active_power_usage = 500
|
||||
circuit = /obj/item/circuitboard/computer/crew
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/crew/syndie
|
||||
icon_keyboard = "syndie_key"
|
||||
|
||||
/obj/machinery/computer/crew/interact(mob/user)
|
||||
GLOB.crewmonitor.show(user,src)
|
||||
|
||||
GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
|
||||
/datum/crewmonitor
|
||||
var/list/ui_sources = list() //List of user -> ui source
|
||||
var/list/jobs
|
||||
var/list/data_by_z = list()
|
||||
var/list/last_update = list()
|
||||
|
||||
/datum/crewmonitor/New()
|
||||
. = ..()
|
||||
|
||||
var/list/jobs = new/list()
|
||||
jobs["Captain"] = 00
|
||||
jobs["Head of Security"] = 10
|
||||
jobs["Warden"] = 11
|
||||
jobs["Security Officer"] = 12
|
||||
jobs["Detective"] = 13
|
||||
jobs["Chief Medical Officer"] = 20
|
||||
jobs["Chemist"] = 21
|
||||
jobs["Geneticist"] = 22
|
||||
jobs["Virologist"] = 23
|
||||
jobs["Medical Doctor"] = 24
|
||||
jobs["Research Director"] = 30
|
||||
jobs["Scientist"] = 31
|
||||
jobs["Roboticist"] = 32
|
||||
jobs["Chief Engineer"] = 40
|
||||
jobs["Station Engineer"] = 41
|
||||
jobs["Atmospheric Technician"] = 42
|
||||
jobs["Quartermaster"] = 50
|
||||
jobs["Shaft Miner"] = 51
|
||||
jobs["Cargo Technician"] = 52
|
||||
jobs["Head of Personnel"] = 60
|
||||
jobs["Bartender"] = 61
|
||||
jobs["Cook"] = 62
|
||||
jobs["Botanist"] = 63
|
||||
jobs["Curator"] = 64
|
||||
jobs["Chaplain"] = 65
|
||||
jobs["Clown"] = 66
|
||||
jobs["Mime"] = 67
|
||||
jobs["Janitor"] = 68
|
||||
jobs["Lawyer"] = 69
|
||||
jobs["Admiral"] = 200
|
||||
jobs["CentCom Commander"] = 210
|
||||
jobs["Custodian"] = 211
|
||||
jobs["Medical Officer"] = 212
|
||||
jobs["Research Officer"] = 213
|
||||
jobs["Emergency Response Team Commander"] = 220
|
||||
jobs["Security Response Officer"] = 221
|
||||
jobs["Engineer Response Officer"] = 222
|
||||
jobs["Medical Response Officer"] = 223
|
||||
jobs["Assistant"] = 999 //Unknowns/custom jobs should appear after civilians, and before assistants
|
||||
|
||||
src.jobs = jobs
|
||||
|
||||
/datum/crewmonitor/Destroy()
|
||||
return ..()
|
||||
|
||||
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
ui_sources[M] = source
|
||||
ui_interact(M)
|
||||
|
||||
/datum/crewmonitor/ui_host(mob/user)
|
||||
return ui_sources[user]
|
||||
|
||||
/datum/crewmonitor/ui_data(mob/user)
|
||||
var/z = user.z
|
||||
if(!z)
|
||||
var/turf/T = get_turf(user)
|
||||
z = T.z
|
||||
var/list/zdata = update_data(z)
|
||||
. = list()
|
||||
.["sensors"] = zdata
|
||||
.["link_allowed"] = isAI(user)
|
||||
|
||||
/datum/crewmonitor/proc/update_data(z)
|
||||
if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD)
|
||||
return data_by_z["[z]"]
|
||||
|
||||
var/list/results_damaged = list()
|
||||
var/list/results_undamaged = list()
|
||||
|
||||
var/obj/item/clothing/under/U
|
||||
var/obj/item/card/id/I
|
||||
var/turf/pos
|
||||
var/ijob
|
||||
var/name
|
||||
var/assignment
|
||||
var/oxydam
|
||||
var/toxdam
|
||||
var/burndam
|
||||
var/brutedam
|
||||
var/totaldam
|
||||
var/area
|
||||
var/pos_x
|
||||
var/pos_y
|
||||
var/life_status
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
|
||||
var/nanite_sensors = FALSE
|
||||
if(H in SSnanites.nanite_monitored_mobs)
|
||||
nanite_sensors = TRUE
|
||||
// Check if their z-level is correct and if they are wearing a uniform.
|
||||
// Accept H.z==0 as well in case the mob is inside an object.
|
||||
if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under) || nanite_sensors)
|
||||
U = H.w_uniform
|
||||
|
||||
// Are the suit sensors on?
|
||||
if (nanite_sensors || ((U.has_sensor > 0) && U.sensor_mode))
|
||||
pos = H.z == 0 || (nanite_sensors || U.sensor_mode == SENSOR_COORDS) ? get_turf(H) : null
|
||||
|
||||
// Special case: If the mob is inside an object confirm the z-level on turf level.
|
||||
if (H.z == 0 && (!pos || pos.z != z))
|
||||
continue
|
||||
|
||||
I = H.wear_id ? H.wear_id.GetID() : null
|
||||
|
||||
if (I)
|
||||
name = I.registered_name
|
||||
assignment = I.assignment
|
||||
ijob = jobs[I.assignment]
|
||||
else
|
||||
name = "Unknown"
|
||||
assignment = ""
|
||||
ijob = 80
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_LIVING)
|
||||
life_status = (!H.stat ? TRUE : FALSE)
|
||||
else
|
||||
life_status = null
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_VITALS)
|
||||
oxydam = round(H.getOxyLoss(),1)
|
||||
toxdam = round(H.getToxLoss(),1)
|
||||
burndam = round(H.getFireLoss(),1)
|
||||
brutedam = round(H.getBruteLoss(),1)
|
||||
totaldam = oxydam + toxdam + burndam + brutedam
|
||||
else
|
||||
oxydam = null
|
||||
toxdam = null
|
||||
burndam = null
|
||||
brutedam = null
|
||||
totaldam = 0
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos)
|
||||
pos = get_turf(H)
|
||||
area = get_area_name(H, TRUE)
|
||||
pos_x = pos.x
|
||||
pos_y = pos.y
|
||||
else
|
||||
area = null
|
||||
pos_x = null
|
||||
pos_y = null
|
||||
|
||||
var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null))
|
||||
|
||||
if(totaldam)
|
||||
results_damaged[++results_damaged.len] = total_list
|
||||
else
|
||||
results_undamaged[++results_undamaged.len] = total_list
|
||||
|
||||
var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare)
|
||||
|
||||
data_by_z["[z]"] = returning
|
||||
last_update["[z]"] = world.time
|
||||
|
||||
return returning
|
||||
|
||||
/proc/ijob_compare(list/a,list/b)
|
||||
return a["ijob"] - b["ijob"]
|
||||
|
||||
/proc/damage_compare(list/a,list/b)
|
||||
return b["totaldam"] - a["totaldam"]
|
||||
|
||||
/datum/crewmonitor/ui_act(action,params)
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
if(!istype(AI))
|
||||
return
|
||||
switch (action)
|
||||
if ("select_person")
|
||||
AI.ai_camera_track(params["name"])
|
||||
|
||||
#undef SENSORS_UPDATE_PERIOD
|
||||
@@ -88,7 +88,7 @@
|
||||
occupant_status += "</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Health:</div><div class='progressBar'><div style='width: [viable_occupant.health]%;' class='progressFill good'></div></div><div class='statusValue'>[viable_occupant.health] %</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Radiation Level:</div><div class='progressBar'><div style='width: [viable_occupant.radiation/(RAD_MOB_SAFE/100)]%;' class='progressFill bad'></div></div><div class='statusValue'>[viable_occupant.radiation/(RAD_MOB_SAFE/100)] %</div></div>"
|
||||
var/rejuvenators = viable_occupant.reagents.get_reagent_amount("potass_iodide")
|
||||
var/rejuvenators = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Rejuvenators:</div><div class='progressBar'><div style='width: [round((rejuvenators / REJUVENATORS_MAX) * 100)]%;' class='progressFill highlight'></div></div><div class='statusValue'>[rejuvenators] units</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Unique Enzymes :</div><div class='statusValue'><span class='highlight'>[viable_occupant.dna.unique_enzymes]</span></div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Last Operation:</div><div class='statusValue'>[last_change ? last_change : "----"]</div></div>"
|
||||
@@ -342,9 +342,9 @@
|
||||
current_screen = href_list["text"]
|
||||
if("rejuv")
|
||||
if(viable_occupant && viable_occupant.reagents)
|
||||
var/potassiodide_amount = viable_occupant.reagents.get_reagent_amount("potass_iodide")
|
||||
var/potassiodide_amount = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
|
||||
var/can_add = max(min(REJUVENATORS_MAX - potassiodide_amount, REJUVENATORS_INJECT), 0)
|
||||
viable_occupant.reagents.add_reagent("potass_iodide", can_add)
|
||||
viable_occupant.reagents.add_reagent(/datum/reagent/medicine/potass_iodide, can_add)
|
||||
if("setbufferlabel")
|
||||
var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
|
||||
if(num && text)
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
|
||||
|
||||
/obj/machinery/computer/upload
|
||||
var/mob/living/silicon/current = null //The target of future law uploads
|
||||
icon_screen = "command"
|
||||
|
||||
/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/aiModule))
|
||||
var/obj/item/aiModule/M = O
|
||||
if(src.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return
|
||||
if(!current)
|
||||
to_chat(user, "<span class='caution'>You haven't selected anything to transmit laws to!</span>")
|
||||
return
|
||||
if(!can_upload_to(current))
|
||||
to_chat(user, "<span class='caution'>Upload failed!</span> Check to make sure [current.name] is functioning properly.")
|
||||
current = null
|
||||
return
|
||||
var/turf/currentloc = get_turf(current)
|
||||
if(currentloc && user.z != currentloc.z)
|
||||
to_chat(user, "<span class='caution'>Upload failed!</span> Unable to establish a connection to [current.name]. You're too far away!")
|
||||
current = null
|
||||
return
|
||||
M.install(current.laws, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S)
|
||||
if(S.stat == DEAD)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/upload/ai
|
||||
name = "\improper AI upload console"
|
||||
desc = "Used to upload laws to the AI."
|
||||
circuit = /obj/item/circuitboard/computer/aiupload
|
||||
|
||||
/obj/machinery/computer/upload/ai/interact(mob/user)
|
||||
src.current = select_active_ai(user)
|
||||
|
||||
if (!src.current)
|
||||
to_chat(user, "<span class='caution'>No active AIs detected!</span>")
|
||||
else
|
||||
to_chat(user, "[src.current.name] selected for law changes.")
|
||||
|
||||
/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A)
|
||||
if(!A || !isAI(A))
|
||||
return 0
|
||||
if(A.control_disabled)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/computer/upload/borg
|
||||
name = "cyborg upload console"
|
||||
desc = "Used to upload laws to Cyborgs."
|
||||
circuit = /obj/item/circuitboard/computer/borgupload
|
||||
|
||||
/obj/machinery/computer/upload/borg/interact(mob/user)
|
||||
src.current = select_active_free_borg(user)
|
||||
|
||||
if(!src.current)
|
||||
to_chat(user, "<span class='caution'>No active unslaved cyborgs detected!</span>")
|
||||
else
|
||||
to_chat(user, "[src.current.name] selected for law changes.")
|
||||
|
||||
/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B)
|
||||
if(!B || !iscyborg(B))
|
||||
return 0
|
||||
if(B.scrambledcodes || B.emagged)
|
||||
return 0
|
||||
|
||||
|
||||
/obj/machinery/computer/upload
|
||||
var/mob/living/silicon/current = null //The target of future law uploads
|
||||
icon_screen = "command"
|
||||
|
||||
/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/aiModule))
|
||||
var/obj/item/aiModule/M = O
|
||||
if(src.stat & (NOPOWER|BROKEN|MAINT))
|
||||
return
|
||||
if(!current)
|
||||
to_chat(user, "<span class='caution'>You haven't selected anything to transmit laws to!</span>")
|
||||
return
|
||||
if(!can_upload_to(current))
|
||||
to_chat(user, "<span class='caution'>Upload failed!</span> Check to make sure [current.name] is functioning properly.")
|
||||
current = null
|
||||
return
|
||||
var/turf/currentloc = get_turf(current)
|
||||
if(currentloc && user.z != currentloc.z)
|
||||
to_chat(user, "<span class='caution'>Upload failed!</span> Unable to establish a connection to [current.name]. You're too far away!")
|
||||
current = null
|
||||
return
|
||||
M.install(current.laws, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S)
|
||||
if(S.stat == DEAD)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/upload/ai
|
||||
name = "\improper AI upload console"
|
||||
desc = "Used to upload laws to the AI."
|
||||
circuit = /obj/item/circuitboard/computer/aiupload
|
||||
|
||||
/obj/machinery/computer/upload/ai/interact(mob/user)
|
||||
src.current = select_active_ai(user)
|
||||
|
||||
if (!src.current)
|
||||
to_chat(user, "<span class='caution'>No active AIs detected!</span>")
|
||||
else
|
||||
to_chat(user, "[src.current.name] selected for law changes.")
|
||||
|
||||
/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A)
|
||||
if(!A || !isAI(A))
|
||||
return 0
|
||||
if(A.control_disabled)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/computer/upload/borg
|
||||
name = "cyborg upload console"
|
||||
desc = "Used to upload laws to Cyborgs."
|
||||
circuit = /obj/item/circuitboard/computer/borgupload
|
||||
|
||||
/obj/machinery/computer/upload/borg/interact(mob/user)
|
||||
src.current = select_active_free_borg(user)
|
||||
|
||||
if(!src.current)
|
||||
to_chat(user, "<span class='caution'>No active unslaved cyborgs detected!</span>")
|
||||
else
|
||||
to_chat(user, "[src.current.name] selected for law changes.")
|
||||
|
||||
/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B)
|
||||
if(!B || !iscyborg(B))
|
||||
return 0
|
||||
if(B.scrambledcodes || B.emagged)
|
||||
return 0
|
||||
return ..()
|
||||
File diff suppressed because it is too large
Load Diff
+133
-133
@@ -1,133 +1,133 @@
|
||||
/obj/machinery/computer/pod
|
||||
name = "mass driver launch control"
|
||||
desc = "A combined blastdoor and mass driver control unit."
|
||||
var/obj/machinery/mass_driver/connected = null
|
||||
var/title = "Mass Driver Controls"
|
||||
var/id = 1
|
||||
var/timing = 0
|
||||
var/time = 30
|
||||
var/range = 4
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
connected = M
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/proc/alarm()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(!connected)
|
||||
say("Cannot locate mass driver connector. Cancelling firing sequence!")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.open()
|
||||
|
||||
sleep(20)
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
|
||||
sleep(50)
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.close()
|
||||
|
||||
/obj/machinery/computer/pod/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
if(connected)
|
||||
var/d2
|
||||
if(timing) //door controls do not need timers.
|
||||
d2 = "<A href='?src=[REF(src)];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=[REF(src)];time=1'>Initiate Time Launch</A>"
|
||||
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if(t == connected.power)
|
||||
temp += "[t] "
|
||||
else
|
||||
temp += "<A href = '?src=[REF(src)];power=[t]'>[t]</A> "
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=[REF(src)];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=[REF(src)];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=[REF(user)];mach_close=computer'>Close</A>"
|
||||
add_fingerprint(usr)
|
||||
var/datum/browser/popup = new(user, "computer", title, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/pod/process()
|
||||
if(!..())
|
||||
return
|
||||
if(timing)
|
||||
if(time > 0)
|
||||
time = round(time) - 1
|
||||
else
|
||||
alarm()
|
||||
time = 0
|
||||
timing = 0
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if(connected)
|
||||
connected.power = t
|
||||
if(href_list["alarm"])
|
||||
alarm()
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 120)
|
||||
if(href_list["door"])
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
if(href_list["drive"])
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/pod/old
|
||||
name = "\improper DoorMex control console"
|
||||
title = "Door Controls"
|
||||
icon_state = "oldcomp"
|
||||
icon_screen = "library"
|
||||
icon_keyboard = null
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate
|
||||
name = "\improper ProComp Executive IIc"
|
||||
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
|
||||
title = "External Airlock Controls"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/computer/pod/old/swf
|
||||
name = "\improper Magix System IV"
|
||||
desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorcerer's Edition."
|
||||
/obj/machinery/computer/pod
|
||||
name = "mass driver launch control"
|
||||
desc = "A combined blastdoor and mass driver control unit."
|
||||
var/obj/machinery/mass_driver/connected = null
|
||||
var/title = "Mass Driver Controls"
|
||||
var/id = 1
|
||||
var/timing = 0
|
||||
var/time = 30
|
||||
var/range = 4
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
connected = M
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/proc/alarm()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(!connected)
|
||||
say("Cannot locate mass driver connector. Cancelling firing sequence!")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.open()
|
||||
|
||||
sleep(20)
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
|
||||
sleep(50)
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.close()
|
||||
|
||||
/obj/machinery/computer/pod/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
if(connected)
|
||||
var/d2
|
||||
if(timing) //door controls do not need timers.
|
||||
d2 = "<A href='?src=[REF(src)];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=[REF(src)];time=1'>Initiate Time Launch</A>"
|
||||
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if(t == connected.power)
|
||||
temp += "[t] "
|
||||
else
|
||||
temp += "<A href = '?src=[REF(src)];power=[t]'>[t]</A> "
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=[REF(src)];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=[REF(src)];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=[REF(user)];mach_close=computer'>Close</A>"
|
||||
add_fingerprint(usr)
|
||||
var/datum/browser/popup = new(user, "computer", title, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/pod/process()
|
||||
if(!..())
|
||||
return
|
||||
if(timing)
|
||||
if(time > 0)
|
||||
time = round(time) - 1
|
||||
else
|
||||
alarm()
|
||||
time = 0
|
||||
timing = 0
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if(connected)
|
||||
connected.power = t
|
||||
if(href_list["alarm"])
|
||||
alarm()
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 120)
|
||||
if(href_list["door"])
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
if(href_list["drive"])
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/pod/old
|
||||
name = "\improper DoorMex control console"
|
||||
title = "Door Controls"
|
||||
icon_state = "oldcomp"
|
||||
icon_screen = "library"
|
||||
icon_keyboard = null
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate
|
||||
name = "\improper ProComp Executive IIc"
|
||||
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
|
||||
title = "External Airlock Controls"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/computer/pod/old/swf
|
||||
name = "\improper Magix System IV"
|
||||
desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorcerer's Edition."
|
||||
|
||||
@@ -1,165 +1,165 @@
|
||||
/obj/machinery/computer/robotics
|
||||
name = "robotics control console"
|
||||
desc = "Used to remotely lockdown or detonate linked Cyborgs and Drones."
|
||||
icon_screen = "robot"
|
||||
icon_keyboard = "rd_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/computer/robotics
|
||||
var/temp = null
|
||||
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
|
||||
if(!istype(R))
|
||||
return 0
|
||||
if(isAI(user))
|
||||
if (R.connected_ai != user)
|
||||
return 0
|
||||
if(iscyborg(user))
|
||||
if (R != user)
|
||||
return 0
|
||||
if(R.scrambledcodes)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if (src.z > 6)
|
||||
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
var/robots = 0
|
||||
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
|
||||
if(!can_control(user, R))
|
||||
continue
|
||||
robots++
|
||||
dat += "[R.name] |"
|
||||
if(R.stat)
|
||||
dat += " Not Responding |"
|
||||
else if (!R.canmove)
|
||||
dat += " Locked Down |"
|
||||
else
|
||||
dat += " Operating Normally |"
|
||||
if (!R.canmove)
|
||||
else if(R.cell)
|
||||
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
|
||||
else
|
||||
dat += " No Cell Installed |"
|
||||
if(R.module)
|
||||
dat += " Module Installed ([R.module.name]) |"
|
||||
else
|
||||
dat += " No Module Installed |"
|
||||
if(R.connected_ai)
|
||||
dat += " Slaved to [R.connected_ai.name] |"
|
||||
else
|
||||
dat += " Independent from AI |"
|
||||
if(issilicon(user) && user != R)
|
||||
var/mob/living/silicon/S = user
|
||||
if(is_servant_of_ratvar(S))
|
||||
dat += "<A href='?src=[REF(src)];convert=[REF(R)]'>(<font color=#BE8700><i>Convert</i></font>)</A> "
|
||||
else if(S.hack_software && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
else if(IsAdminGhost(user) && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.canmove ? "Lockdown" : "Release"]</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];killbot=[REF(R)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(!robots)
|
||||
dat += "No Cyborg Units detected within access parameters."
|
||||
dat += "<BR>"
|
||||
|
||||
var/drones = 0
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
|
||||
if(D.hacked)
|
||||
continue
|
||||
drones++
|
||||
dat += "[D.name] |"
|
||||
if(D.stat)
|
||||
dat += " Not Responding |"
|
||||
dat += "<A href='?src=[REF(src)];killdrone=[REF(D)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(!drones)
|
||||
dat += "No Drone Units detected within access parameters."
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/robotics/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
else if (href_list["killbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
var/turf/T = get_turf(R)
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
R.self_destruct()
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["stopbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
|
||||
R.SetLockdown(!R.lockcharge)
|
||||
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["magbot"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
|
||||
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
|
||||
R.SetEmagged(1)
|
||||
|
||||
else if(href_list["convert"])
|
||||
if(isAI(usr) && is_servant_of_ratvar(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
|
||||
log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
|
||||
add_servant_of_ratvar(R)
|
||||
|
||||
else if (href_list["killdrone"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list
|
||||
if(D.hacked)
|
||||
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
|
||||
else
|
||||
var/turf/T = get_turf(D)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
|
||||
log_game("[key_name(usr)] detonated [key_name(D)]!")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, D)
|
||||
s.start()
|
||||
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
|
||||
D.gib()
|
||||
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
/obj/machinery/computer/robotics
|
||||
name = "robotics control console"
|
||||
desc = "Used to remotely lockdown or detonate linked Cyborgs and Drones."
|
||||
icon_screen = "robot"
|
||||
icon_keyboard = "rd_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/computer/robotics
|
||||
var/temp = null
|
||||
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
|
||||
if(!istype(R))
|
||||
return 0
|
||||
if(isAI(user))
|
||||
if (R.connected_ai != user)
|
||||
return 0
|
||||
if(iscyborg(user))
|
||||
if (R != user)
|
||||
return 0
|
||||
if(R.scrambledcodes)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if (src.z > 6)
|
||||
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
var/robots = 0
|
||||
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
|
||||
if(!can_control(user, R))
|
||||
continue
|
||||
robots++
|
||||
dat += "[R.name] |"
|
||||
if(R.stat)
|
||||
dat += " Not Responding |"
|
||||
else if (!R.canmove)
|
||||
dat += " Locked Down |"
|
||||
else
|
||||
dat += " Operating Normally |"
|
||||
if (!R.canmove)
|
||||
else if(R.cell)
|
||||
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
|
||||
else
|
||||
dat += " No Cell Installed |"
|
||||
if(R.module)
|
||||
dat += " Module Installed ([R.module.name]) |"
|
||||
else
|
||||
dat += " No Module Installed |"
|
||||
if(R.connected_ai)
|
||||
dat += " Slaved to [R.connected_ai.name] |"
|
||||
else
|
||||
dat += " Independent from AI |"
|
||||
if(issilicon(user) && user != R)
|
||||
var/mob/living/silicon/S = user
|
||||
if(is_servant_of_ratvar(S))
|
||||
dat += "<A href='?src=[REF(src)];convert=[REF(R)]'>(<font color=#BE8700><i>Convert</i></font>)</A> "
|
||||
else if(S.hack_software && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
else if(IsAdminGhost(user) && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.canmove ? "Lockdown" : "Release"]</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];killbot=[REF(R)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(!robots)
|
||||
dat += "No Cyborg Units detected within access parameters."
|
||||
dat += "<BR>"
|
||||
|
||||
var/drones = 0
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
|
||||
if(D.hacked)
|
||||
continue
|
||||
drones++
|
||||
dat += "[D.name] |"
|
||||
if(D.stat)
|
||||
dat += " Not Responding |"
|
||||
dat += "<A href='?src=[REF(src)];killdrone=[REF(D)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(!drones)
|
||||
dat += "No Drone Units detected within access parameters."
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/robotics/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
else if (href_list["killbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
var/turf/T = get_turf(R)
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
R.self_destruct()
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["stopbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
|
||||
R.SetLockdown(!R.lockcharge)
|
||||
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["magbot"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
|
||||
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
|
||||
R.SetEmagged(1)
|
||||
|
||||
else if(href_list["convert"])
|
||||
if(isAI(usr) && is_servant_of_ratvar(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
|
||||
log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
|
||||
add_servant_of_ratvar(R)
|
||||
|
||||
else if (href_list["killdrone"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list
|
||||
if(D.hacked)
|
||||
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
|
||||
else
|
||||
var/turf/T = get_turf(D)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
|
||||
log_game("[key_name(usr)] detonated [key_name(D)]!")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, D)
|
||||
s.start()
|
||||
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
|
||||
D.gib()
|
||||
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,98 +1,98 @@
|
||||
/obj/machinery/computer/station_alert
|
||||
name = "station alert console"
|
||||
desc = "Used to access the station's automated alert system."
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/stationalert
|
||||
var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list())
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/station_alert/Initialize()
|
||||
. = ..()
|
||||
GLOB.alert_consoles += src
|
||||
|
||||
/obj/machinery/computer/station_alert/Destroy()
|
||||
GLOB.alert_consoles -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
. = list()
|
||||
|
||||
.["alarms"] = list()
|
||||
for(var/class in alarms)
|
||||
.["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
.["alarms"][class] += area
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
if(source.z != z)
|
||||
return
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
|
||||
var/list/L = alarms[class]
|
||||
for(var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if(O && islist(O))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if(O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C ? C : O), list(source))
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
active_alarms = TRUE
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
/obj/machinery/computer/station_alert
|
||||
name = "station alert console"
|
||||
desc = "Used to access the station's automated alert system."
|
||||
icon_screen = "alert:0"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/stationalert
|
||||
var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list())
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/station_alert/Initialize()
|
||||
. = ..()
|
||||
GLOB.alert_consoles += src
|
||||
|
||||
/obj/machinery/computer/station_alert/Destroy()
|
||||
GLOB.alert_consoles -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
. = list()
|
||||
|
||||
.["alarms"] = list()
|
||||
for(var/class in alarms)
|
||||
.["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
.["alarms"][class] += area
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
if(source.z != z)
|
||||
return
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
|
||||
var/list/L = alarms[class]
|
||||
for(var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if(O && islist(O))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if(O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C ? C : O), list(source))
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
active_alarms = TRUE
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -1,215 +1,215 @@
|
||||
#define NUKESCALINGMODIFIER 1
|
||||
|
||||
GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner"))
|
||||
|
||||
/obj/machinery/computer/telecrystals
|
||||
name = "\improper telecrystal assignment station"
|
||||
desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..."
|
||||
icon_state = "tcstation"
|
||||
icon_keyboard = "tcstation_key"
|
||||
icon_screen = "syndie"
|
||||
clockwork = TRUE //it'd look weird, at least if ratvar ever got there
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/obj/machinery/computer/telecrystals/uplinker
|
||||
name = "\improper telecrystal upload/receive station"
|
||||
desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \
|
||||
you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant."
|
||||
var/obj/item/uplinkholder = null
|
||||
var/obj/machinery/computer/telecrystals/boss/linkedboss = null
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/Initialize()
|
||||
. = ..()
|
||||
|
||||
var/ID = pick_n_take(GLOB.possible_uplinker_IDs)
|
||||
if(!ID)
|
||||
ID = rand(1,999)
|
||||
name = "[name] [ID]"
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/attackby(obj/item/I, mob/user, params)
|
||||
if(uplinkholder)
|
||||
to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>")
|
||||
return
|
||||
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
|
||||
if(hidden_uplink)
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
uplinkholder = I
|
||||
I.add_fingerprint(user)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[I] doesn't appear to be an uplink...</span>")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/update_icon()
|
||||
..()
|
||||
if(uplinkholder)
|
||||
add_overlay("[initial(icon_state)]-closed")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink()
|
||||
if(uplinkholder)
|
||||
uplinkholder.forceMove(drop_location())
|
||||
uplinkholder = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
if(amt < 0)
|
||||
linkedboss.storedcrystals += hidden_uplink.telecrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].")
|
||||
hidden_uplink.telecrystals = 0
|
||||
else if(amt <= hidden_uplink.telecrystals)
|
||||
hidden_uplink.telecrystals -= amt
|
||||
linkedboss.storedcrystals += amt
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
if(amt < 0)
|
||||
hidden_uplink.telecrystals += linkedboss.storedcrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
|
||||
linkedboss.storedcrystals = 0
|
||||
else if(amt <= linkedboss.storedcrystals)
|
||||
hidden_uplink.telecrystals += amt
|
||||
linkedboss.storedcrystals -= amt
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].")
|
||||
|
||||
///////
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = ""
|
||||
if(linkedboss)
|
||||
dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution. <BR><BR>"
|
||||
else
|
||||
dat += "No linked management consoles detected. Scan for uplink stations using the management console.<BR><BR>"
|
||||
|
||||
if(uplinkholder)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
|
||||
if(linkedboss)
|
||||
dat += "Donate TC: <a href='byond://?src=[REF(src)];donate=1'>1</a> | <a href='byond://?src=[REF(src)];donate=5'>5</a> | <a href='byond://?src=[REF(src)];donate=-1'>All</a>"
|
||||
dat += "<br><a href='byond://?src=[REF(src)];eject=1'>Eject Uplink</a>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["donate"])
|
||||
var/tcamt = text2num(href_list["donate"])
|
||||
donateTC(tcamt)
|
||||
|
||||
if(href_list["eject"])
|
||||
ejectuplink()
|
||||
|
||||
src.updateUsrDialog()
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
/obj/machinery/computer/telecrystals/boss
|
||||
name = "team telecrystal management console"
|
||||
desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \
|
||||
Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \
|
||||
based on the danger rating of the mission."
|
||||
icon_state = "computer"
|
||||
icon_screen = "tcboss"
|
||||
icon_keyboard = "syndie_key"
|
||||
var/virgin = 1
|
||||
var/scanrange = 10
|
||||
var/storedcrystals = 0
|
||||
var/list/TCstations = list()
|
||||
var/list/transferlog = list()
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage)
|
||||
transferlog += ("<b>[STATION_TIME_TIMESTAMP("hh:mm:ss")]</b> [logmessage]")
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc))
|
||||
if(!A.linkedboss)
|
||||
TCstations += A
|
||||
A.linkedboss = src
|
||||
if(virgin)
|
||||
getDangerous()
|
||||
virgin = 0
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
|
||||
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
|
||||
var/danger = GLOB.joined_player_list.len - nukeops.len
|
||||
danger = CEILING(danger, 10)
|
||||
scaleTC(danger)
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/scaleTC(amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc.
|
||||
storedcrystals += amt * NUKESCALINGMODIFIER
|
||||
|
||||
/////////
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=[REF(src)];scan=1'>Scan for TC stations.</a><BR>"
|
||||
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
|
||||
dat += "<BR><BR>"
|
||||
|
||||
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
|
||||
dat += "[A.name] | "
|
||||
if(A.uplinkholder)
|
||||
var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink)
|
||||
dat += "[hidden_uplink.telecrystals] telecrystals."
|
||||
if(storedcrystals)
|
||||
dat+= "<BR>Add TC: <a href ='?src=[REF(src)];target=[REF(A)];give=1'>1</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=5'>5</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=10'>10</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=-1'>All</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(TCstations.len && storedcrystals)
|
||||
dat += "<BR><BR><a href='byond://?src=[REF(src)];distrib=1'>Evenly distribute remaining TC.</a><BR><BR>"
|
||||
|
||||
|
||||
for(var/entry in transferlog)
|
||||
dat += "<small>[entry]</small><BR>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["scan"])
|
||||
scanUplinkers()
|
||||
|
||||
if(href_list["give"])
|
||||
var/tcamt = text2num(href_list["give"])
|
||||
if(TCstations.len) // sanity
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
|
||||
A.giveTC(tcamt)
|
||||
|
||||
if(href_list["distrib"])
|
||||
var/sanity = 0
|
||||
while(storedcrystals && sanity < 100)
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
|
||||
A.giveTC(1,0)
|
||||
sanity++
|
||||
logTransfer("[src] evenly distributed telecrystals.")
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
#undef NUKESCALINGMODIFIER
|
||||
#define NUKESCALINGMODIFIER 1
|
||||
|
||||
GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner"))
|
||||
|
||||
/obj/machinery/computer/telecrystals
|
||||
name = "\improper telecrystal assignment station"
|
||||
desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..."
|
||||
icon_state = "tcstation"
|
||||
icon_keyboard = "tcstation_key"
|
||||
icon_screen = "syndie"
|
||||
clockwork = TRUE //it'd look weird, at least if ratvar ever got there
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/obj/machinery/computer/telecrystals/uplinker
|
||||
name = "\improper telecrystal upload/receive station"
|
||||
desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \
|
||||
you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant."
|
||||
var/obj/item/uplinkholder = null
|
||||
var/obj/machinery/computer/telecrystals/boss/linkedboss = null
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/Initialize()
|
||||
. = ..()
|
||||
|
||||
var/ID = pick_n_take(GLOB.possible_uplinker_IDs)
|
||||
if(!ID)
|
||||
ID = rand(1,999)
|
||||
name = "[name] [ID]"
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/attackby(obj/item/I, mob/user, params)
|
||||
if(uplinkholder)
|
||||
to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>")
|
||||
return
|
||||
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
|
||||
if(hidden_uplink)
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
uplinkholder = I
|
||||
I.add_fingerprint(user)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[I] doesn't appear to be an uplink...</span>")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/update_icon()
|
||||
..()
|
||||
if(uplinkholder)
|
||||
add_overlay("[initial(icon_state)]-closed")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink()
|
||||
if(uplinkholder)
|
||||
uplinkholder.forceMove(drop_location())
|
||||
uplinkholder = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
if(amt < 0)
|
||||
linkedboss.storedcrystals += hidden_uplink.telecrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].")
|
||||
hidden_uplink.telecrystals = 0
|
||||
else if(amt <= hidden_uplink.telecrystals)
|
||||
hidden_uplink.telecrystals -= amt
|
||||
linkedboss.storedcrystals += amt
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
if(amt < 0)
|
||||
hidden_uplink.telecrystals += linkedboss.storedcrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
|
||||
linkedboss.storedcrystals = 0
|
||||
else if(amt <= linkedboss.storedcrystals)
|
||||
hidden_uplink.telecrystals += amt
|
||||
linkedboss.storedcrystals -= amt
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].")
|
||||
|
||||
///////
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = ""
|
||||
if(linkedboss)
|
||||
dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution. <BR><BR>"
|
||||
else
|
||||
dat += "No linked management consoles detected. Scan for uplink stations using the management console.<BR><BR>"
|
||||
|
||||
if(uplinkholder)
|
||||
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
|
||||
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
|
||||
if(linkedboss)
|
||||
dat += "Donate TC: <a href='byond://?src=[REF(src)];donate=1'>1</a> | <a href='byond://?src=[REF(src)];donate=5'>5</a> | <a href='byond://?src=[REF(src)];donate=-1'>All</a>"
|
||||
dat += "<br><a href='byond://?src=[REF(src)];eject=1'>Eject Uplink</a>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["donate"])
|
||||
var/tcamt = text2num(href_list["donate"])
|
||||
donateTC(tcamt)
|
||||
|
||||
if(href_list["eject"])
|
||||
ejectuplink()
|
||||
|
||||
src.updateUsrDialog()
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
/obj/machinery/computer/telecrystals/boss
|
||||
name = "team telecrystal management console"
|
||||
desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \
|
||||
Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \
|
||||
based on the danger rating of the mission."
|
||||
icon_state = "computer"
|
||||
icon_screen = "tcboss"
|
||||
icon_keyboard = "syndie_key"
|
||||
var/virgin = 1
|
||||
var/scanrange = 10
|
||||
var/storedcrystals = 0
|
||||
var/list/TCstations = list()
|
||||
var/list/transferlog = list()
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage)
|
||||
transferlog += ("<b>[STATION_TIME_TIMESTAMP("hh:mm:ss")]</b> [logmessage]")
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc))
|
||||
if(!A.linkedboss)
|
||||
TCstations += A
|
||||
A.linkedboss = src
|
||||
if(virgin)
|
||||
getDangerous()
|
||||
virgin = 0
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
|
||||
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
|
||||
var/danger = GLOB.joined_player_list.len - nukeops.len
|
||||
danger = CEILING(danger, 10)
|
||||
scaleTC(danger)
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/scaleTC(amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc.
|
||||
storedcrystals += amt * NUKESCALINGMODIFIER
|
||||
|
||||
/////////
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=[REF(src)];scan=1'>Scan for TC stations.</a><BR>"
|
||||
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
|
||||
dat += "<BR><BR>"
|
||||
|
||||
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
|
||||
dat += "[A.name] | "
|
||||
if(A.uplinkholder)
|
||||
var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink)
|
||||
dat += "[hidden_uplink.telecrystals] telecrystals."
|
||||
if(storedcrystals)
|
||||
dat+= "<BR>Add TC: <a href ='?src=[REF(src)];target=[REF(A)];give=1'>1</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=5'>5</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=10'>10</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=-1'>All</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(TCstations.len && storedcrystals)
|
||||
dat += "<BR><BR><a href='byond://?src=[REF(src)];distrib=1'>Evenly distribute remaining TC.</a><BR><BR>"
|
||||
|
||||
|
||||
for(var/entry in transferlog)
|
||||
dat += "<small>[entry]</small><BR>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["scan"])
|
||||
scanUplinkers()
|
||||
|
||||
if(href_list["give"])
|
||||
var/tcamt = text2num(href_list["give"])
|
||||
if(TCstations.len) // sanity
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
|
||||
A.giveTC(tcamt)
|
||||
|
||||
if(href_list["distrib"])
|
||||
var/sanity = 0
|
||||
while(storedcrystals && sanity < 100)
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
|
||||
A.giveTC(1,0)
|
||||
sanity++
|
||||
logTransfer("[src] evenly distributed telecrystals.")
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
#undef NUKESCALINGMODIFIER
|
||||
|
||||
@@ -1,279 +1,279 @@
|
||||
/obj/structure/frame
|
||||
name = "frame"
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "box_0"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
var/obj/item/circuitboard/machine/circuit = null
|
||||
var/state = 1
|
||||
|
||||
/obj/structure/frame/examine(user)
|
||||
. = ..()
|
||||
if(circuit)
|
||||
. += "It has \a [circuit] installed."
|
||||
|
||||
|
||||
/obj/structure/frame/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc, 5)
|
||||
if(circuit)
|
||||
circuit.forceMove(loc)
|
||||
circuit = null
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/structure/frame/machine
|
||||
name = "machine frame"
|
||||
var/list/components = null
|
||||
var/list/req_components = null
|
||||
var/list/req_component_names = null // user-friendly names of components
|
||||
|
||||
/obj/structure/frame/machine/examine(user)
|
||||
. = ..()
|
||||
if(state == 3 && req_components && req_component_names)
|
||||
var/hasContent = 0
|
||||
var/requires = "It requires"
|
||||
|
||||
for(var/i = 1 to req_components.len)
|
||||
var/tname = req_components[i]
|
||||
var/amt = req_components[tname]
|
||||
if(amt == 0)
|
||||
continue
|
||||
var/use_and = i == req_components.len
|
||||
requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]"
|
||||
hasContent = 1
|
||||
|
||||
if(hasContent)
|
||||
. += requires + "."
|
||||
else
|
||||
. += "It does not require any more components."
|
||||
|
||||
/obj/structure/frame/machine/proc/update_namelist()
|
||||
if(!req_components)
|
||||
return
|
||||
|
||||
req_component_names = new()
|
||||
for(var/tname in req_components)
|
||||
if(ispath(tname, /obj/item/stack))
|
||||
var/obj/item/stack/S = tname
|
||||
var/singular_name = initial(S.singular_name)
|
||||
if(singular_name)
|
||||
req_component_names[tname] = singular_name
|
||||
else
|
||||
req_component_names[tname] = initial(S.name)
|
||||
else
|
||||
var/obj/O = tname
|
||||
req_component_names[tname] = initial(O.name)
|
||||
|
||||
/obj/structure/frame/machine/proc/get_req_components_amt()
|
||||
var/amt = 0
|
||||
for(var/path in req_components)
|
||||
amt += req_components[path]
|
||||
return amt
|
||||
|
||||
/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
to_chat(user, "<span class='warning'>The frame needs wiring first!</span>")
|
||||
return
|
||||
else if(istype(P, /obj/item/circuitboard))
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start to add cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50, amount=5))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
state = 2
|
||||
icon_state = "box_1"
|
||||
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver) && !anchored)
|
||||
user.visible_message("<span class='warning'>[user] disassembles the frame.</span>", \
|
||||
"<span class='notice'>You start to disassemble the frame...</span>", "You hear banging and clanking.")
|
||||
if(P.use_tool(src, user, 40, volume=50))
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You disassemble the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (loc, 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(2)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
var/obj/item/circuitboard/machine/B = P
|
||||
if(!anchored && B.needs_anchored)
|
||||
to_chat(user, "<span class='warning'>The frame needs to be secured first!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(B, src))
|
||||
return
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You add the circuit board to the frame.</span>")
|
||||
circuit = B
|
||||
icon_state = "box_2"
|
||||
state = 3
|
||||
components = list()
|
||||
req_components = B.req_components.Copy()
|
||||
update_namelist()
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard))
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/wirecutters))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the cables.</span>")
|
||||
state = 1
|
||||
icon_state = "box_0"
|
||||
new /obj/item/stack/cable_coil(drop_location(), 5)
|
||||
return
|
||||
|
||||
if(3)
|
||||
if(istype(P, /obj/item/crowbar))
|
||||
P.play_tool_sound(src)
|
||||
state = 2
|
||||
circuit.forceMove(drop_location())
|
||||
components.Remove(circuit)
|
||||
circuit = null
|
||||
if(components.len == 0)
|
||||
to_chat(user, "<span class='notice'>You remove the circuit board.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You remove the circuit board and other components.</span>")
|
||||
for(var/atom/movable/AM in components)
|
||||
AM.forceMove(drop_location())
|
||||
desc = initial(desc)
|
||||
req_components = null
|
||||
components = null
|
||||
icon_state = "box_1"
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/wrench) && !circuit.needs_anchored)
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
var/component_check = 1
|
||||
for(var/R in req_components)
|
||||
if(req_components[R] > 0)
|
||||
component_check = 0
|
||||
break
|
||||
if(component_check)
|
||||
P.play_tool_sound(src)
|
||||
var/obj/machinery/new_machine = new circuit.build_path(loc)
|
||||
new_machine.setAnchored(anchored)
|
||||
new_machine.on_construction()
|
||||
for(var/obj/O in new_machine.component_parts)
|
||||
qdel(O)
|
||||
new_machine.component_parts = list()
|
||||
for(var/obj/O in src)
|
||||
O.moveToNullspace()
|
||||
new_machine.component_parts += O
|
||||
if(new_machine.circuit)
|
||||
QDEL_NULL(new_machine.circuit)
|
||||
new_machine.circuit = circuit
|
||||
circuit.moveToNullspace()
|
||||
new_machine.RefreshParts()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/storage/part_replacer) && P.contents.len && get_req_components_amt())
|
||||
var/obj/item/storage/part_replacer/replacer = P
|
||||
var/list/added_components = list()
|
||||
var/list/part_list = list()
|
||||
|
||||
//Assemble a list of current parts, then sort them by their rating!
|
||||
for(var/obj/item/co in replacer)
|
||||
part_list += co
|
||||
//Sort the parts. This ensures that higher tier items are applied first.
|
||||
part_list = sortTim(part_list, /proc/cmp_rped_sort)
|
||||
|
||||
for(var/path in req_components)
|
||||
while(req_components[path] > 0 && (locate(path) in part_list))
|
||||
var/obj/item/part = (locate(path) in part_list)
|
||||
part_list -= part
|
||||
if(istype(part,/obj/item/stack))
|
||||
var/obj/item/stack/S = part
|
||||
var/used_amt = min(round(S.get_amount()), req_components[path])
|
||||
if(!used_amt || !S.use(used_amt))
|
||||
continue
|
||||
var/NS = new S.merge_type(src, used_amt)
|
||||
added_components[NS] = path
|
||||
req_components[path] -= used_amt
|
||||
else
|
||||
added_components[part] = path
|
||||
if(SEND_SIGNAL(replacer, COMSIG_TRY_STORAGE_TAKE, part, src))
|
||||
req_components[path]--
|
||||
|
||||
for(var/obj/item/part in added_components)
|
||||
if(istype(part,/obj/item/stack))
|
||||
var/obj/item/stack/S = part
|
||||
var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with
|
||||
if(NS)
|
||||
S.merge(NS)
|
||||
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
|
||||
components += part
|
||||
to_chat(user, "<span class='notice'>[part.name] applied.</span>")
|
||||
if(added_components.len)
|
||||
replacer.play_rped_sound()
|
||||
return
|
||||
|
||||
if(isitem(P) && get_req_components_amt())
|
||||
for(var/I in req_components)
|
||||
if(istype(P, I) && (req_components[I] > 0))
|
||||
if(istype(P, /obj/item/stack))
|
||||
var/obj/item/stack/S = P
|
||||
var/used_amt = min(round(S.get_amount()), req_components[I])
|
||||
|
||||
if(used_amt && S.use(used_amt))
|
||||
var/obj/item/stack/NS = locate(S.merge_type) in components
|
||||
|
||||
if(!NS)
|
||||
NS = new S.merge_type(src, used_amt)
|
||||
components += NS
|
||||
else
|
||||
NS.add(used_amt)
|
||||
|
||||
req_components[I] -= used_amt
|
||||
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
break
|
||||
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
|
||||
components += P
|
||||
req_components[I]--
|
||||
return 1
|
||||
to_chat(user, "<span class='warning'>You cannot add that to the machine!</span>")
|
||||
return 0
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
/obj/structure/frame/machine/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(state >= 2)
|
||||
new /obj/item/stack/cable_coil(loc , 5)
|
||||
for(var/X in components)
|
||||
var/obj/item/I = X
|
||||
I.forceMove(loc)
|
||||
|
||||
..()
|
||||
/obj/structure/frame
|
||||
name = "frame"
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "box_0"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
var/obj/item/circuitboard/machine/circuit = null
|
||||
var/state = 1
|
||||
|
||||
/obj/structure/frame/examine(user)
|
||||
. = ..()
|
||||
if(circuit)
|
||||
. += "It has \a [circuit] installed."
|
||||
|
||||
|
||||
/obj/structure/frame/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc, 5)
|
||||
if(circuit)
|
||||
circuit.forceMove(loc)
|
||||
circuit = null
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/structure/frame/machine
|
||||
name = "machine frame"
|
||||
var/list/components = null
|
||||
var/list/req_components = null
|
||||
var/list/req_component_names = null // user-friendly names of components
|
||||
|
||||
/obj/structure/frame/machine/examine(user)
|
||||
. = ..()
|
||||
if(state == 3 && req_components && req_component_names)
|
||||
var/hasContent = 0
|
||||
var/requires = "It requires"
|
||||
|
||||
for(var/i = 1 to req_components.len)
|
||||
var/tname = req_components[i]
|
||||
var/amt = req_components[tname]
|
||||
if(amt == 0)
|
||||
continue
|
||||
var/use_and = i == req_components.len
|
||||
requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]"
|
||||
hasContent = 1
|
||||
|
||||
if(hasContent)
|
||||
. += requires + "."
|
||||
else
|
||||
. += "It does not require any more components."
|
||||
|
||||
/obj/structure/frame/machine/proc/update_namelist()
|
||||
if(!req_components)
|
||||
return
|
||||
|
||||
req_component_names = new()
|
||||
for(var/tname in req_components)
|
||||
if(ispath(tname, /obj/item/stack))
|
||||
var/obj/item/stack/S = tname
|
||||
var/singular_name = initial(S.singular_name)
|
||||
if(singular_name)
|
||||
req_component_names[tname] = singular_name
|
||||
else
|
||||
req_component_names[tname] = initial(S.name)
|
||||
else
|
||||
var/obj/O = tname
|
||||
req_component_names[tname] = initial(O.name)
|
||||
|
||||
/obj/structure/frame/machine/proc/get_req_components_amt()
|
||||
var/amt = 0
|
||||
for(var/path in req_components)
|
||||
amt += req_components[path]
|
||||
return amt
|
||||
|
||||
/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
to_chat(user, "<span class='warning'>The frame needs wiring first!</span>")
|
||||
return
|
||||
else if(istype(P, /obj/item/circuitboard))
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start to add cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50, amount=5))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
state = 2
|
||||
icon_state = "box_1"
|
||||
|
||||
return
|
||||
if(istype(P, /obj/item/screwdriver) && !anchored)
|
||||
user.visible_message("<span class='warning'>[user] disassembles the frame.</span>", \
|
||||
"<span class='notice'>You start to disassemble the frame...</span>", "You hear banging and clanking.")
|
||||
if(P.use_tool(src, user, 40, volume=50))
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You disassemble the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (loc, 5)
|
||||
M.add_fingerprint(user)
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
if(state == 1)
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(2)
|
||||
if(istype(P, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
var/obj/item/circuitboard/machine/B = P
|
||||
if(!anchored && B.needs_anchored)
|
||||
to_chat(user, "<span class='warning'>The frame needs to be secured first!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(B, src))
|
||||
return
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You add the circuit board to the frame.</span>")
|
||||
circuit = B
|
||||
icon_state = "box_2"
|
||||
state = 3
|
||||
components = list()
|
||||
req_components = B.req_components.Copy()
|
||||
update_namelist()
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard))
|
||||
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/wirecutters))
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You remove the cables.</span>")
|
||||
state = 1
|
||||
icon_state = "box_0"
|
||||
new /obj/item/stack/cable_coil(drop_location(), 5)
|
||||
return
|
||||
|
||||
if(3)
|
||||
if(istype(P, /obj/item/crowbar))
|
||||
P.play_tool_sound(src)
|
||||
state = 2
|
||||
circuit.forceMove(drop_location())
|
||||
components.Remove(circuit)
|
||||
circuit = null
|
||||
if(components.len == 0)
|
||||
to_chat(user, "<span class='notice'>You remove the circuit board.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You remove the circuit board and other components.</span>")
|
||||
for(var/atom/movable/AM in components)
|
||||
AM.forceMove(drop_location())
|
||||
desc = initial(desc)
|
||||
req_components = null
|
||||
components = null
|
||||
icon_state = "box_1"
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/wrench) && !circuit.needs_anchored)
|
||||
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
|
||||
if(P.use_tool(src, user, 40, volume=75))
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
|
||||
setAnchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
var/component_check = 1
|
||||
for(var/R in req_components)
|
||||
if(req_components[R] > 0)
|
||||
component_check = 0
|
||||
break
|
||||
if(component_check)
|
||||
P.play_tool_sound(src)
|
||||
var/obj/machinery/new_machine = new circuit.build_path(loc)
|
||||
new_machine.setAnchored(anchored)
|
||||
new_machine.on_construction()
|
||||
for(var/obj/O in new_machine.component_parts)
|
||||
qdel(O)
|
||||
new_machine.component_parts = list()
|
||||
for(var/obj/O in src)
|
||||
O.moveToNullspace()
|
||||
new_machine.component_parts += O
|
||||
if(new_machine.circuit)
|
||||
QDEL_NULL(new_machine.circuit)
|
||||
new_machine.circuit = circuit
|
||||
circuit.moveToNullspace()
|
||||
new_machine.RefreshParts()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/storage/part_replacer) && P.contents.len && get_req_components_amt())
|
||||
var/obj/item/storage/part_replacer/replacer = P
|
||||
var/list/added_components = list()
|
||||
var/list/part_list = list()
|
||||
|
||||
//Assemble a list of current parts, then sort them by their rating!
|
||||
for(var/obj/item/co in replacer)
|
||||
part_list += co
|
||||
//Sort the parts. This ensures that higher tier items are applied first.
|
||||
part_list = sortTim(part_list, /proc/cmp_rped_sort)
|
||||
|
||||
for(var/path in req_components)
|
||||
while(req_components[path] > 0 && (locate(path) in part_list))
|
||||
var/obj/item/part = (locate(path) in part_list)
|
||||
part_list -= part
|
||||
if(istype(part,/obj/item/stack))
|
||||
var/obj/item/stack/S = part
|
||||
var/used_amt = min(round(S.get_amount()), req_components[path])
|
||||
if(!used_amt || !S.use(used_amt))
|
||||
continue
|
||||
var/NS = new S.merge_type(src, used_amt)
|
||||
added_components[NS] = path
|
||||
req_components[path] -= used_amt
|
||||
else
|
||||
added_components[part] = path
|
||||
if(SEND_SIGNAL(replacer, COMSIG_TRY_STORAGE_TAKE, part, src))
|
||||
req_components[path]--
|
||||
|
||||
for(var/obj/item/part in added_components)
|
||||
if(istype(part,/obj/item/stack))
|
||||
var/obj/item/stack/S = part
|
||||
var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with
|
||||
if(NS)
|
||||
S.merge(NS)
|
||||
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
|
||||
components += part
|
||||
to_chat(user, "<span class='notice'>[part.name] applied.</span>")
|
||||
if(added_components.len)
|
||||
replacer.play_rped_sound()
|
||||
return
|
||||
|
||||
if(isitem(P) && get_req_components_amt())
|
||||
for(var/I in req_components)
|
||||
if(istype(P, I) && (req_components[I] > 0))
|
||||
if(istype(P, /obj/item/stack))
|
||||
var/obj/item/stack/S = P
|
||||
var/used_amt = min(round(S.get_amount()), req_components[I])
|
||||
|
||||
if(used_amt && S.use(used_amt))
|
||||
var/obj/item/stack/NS = locate(S.merge_type) in components
|
||||
|
||||
if(!NS)
|
||||
NS = new S.merge_type(src, used_amt)
|
||||
components += NS
|
||||
else
|
||||
NS.add(used_amt)
|
||||
|
||||
req_components[I] -= used_amt
|
||||
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
break
|
||||
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
|
||||
components += P
|
||||
req_components[I]--
|
||||
return 1
|
||||
to_chat(user, "<span class='warning'>You cannot add that to the machine!</span>")
|
||||
return 0
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
/obj/structure/frame/machine/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(state >= 2)
|
||||
new /obj/item/stack/cable_coil(loc , 5)
|
||||
for(var/X in components)
|
||||
var/obj/item/I = X
|
||||
I.forceMove(loc)
|
||||
|
||||
..()
|
||||
|
||||
@@ -1408,6 +1408,9 @@
|
||||
/obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
switch(the_rcd.mode)
|
||||
if(RCD_DECONSTRUCT)
|
||||
if(security_level != AIRLOCK_SECURITY_NONE && the_rcd.canRturf != TRUE)
|
||||
to_chat(user, "<span class='notice'>[src]'s reinforcement needs to be removed first.</span>")
|
||||
return FALSE
|
||||
return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 32)
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
/obj/machinery/door/airlock/alarmlock
|
||||
name = "glass alarm airlock"
|
||||
icon = 'icons/obj/doors/airlocks/station2/glass.dmi'
|
||||
overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
|
||||
opacity = 0
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_public
|
||||
glass = TRUE
|
||||
|
||||
var/datum/radio_frequency/air_connection
|
||||
var/air_frequency = FREQ_ATMOS_ALARMS
|
||||
autoclose = FALSE
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Initialize()
|
||||
. = ..()
|
||||
air_connection = new
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Destroy()
|
||||
SSradio.remove_object(src,air_frequency)
|
||||
air_connection = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Initialize()
|
||||
. = ..()
|
||||
SSradio.remove_object(src, air_frequency)
|
||||
air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM)
|
||||
open()
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
var/alarm_area = signal.data["zone"]
|
||||
var/alert = signal.data["alert"]
|
||||
|
||||
if(alarm_area == get_area_name(src))
|
||||
switch(alert)
|
||||
if("severe")
|
||||
autoclose = TRUE
|
||||
close()
|
||||
if("minor", "clear")
|
||||
autoclose = FALSE
|
||||
/obj/machinery/door/airlock/alarmlock
|
||||
name = "glass alarm airlock"
|
||||
icon = 'icons/obj/doors/airlocks/station2/glass.dmi'
|
||||
overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
|
||||
opacity = 0
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_public
|
||||
glass = TRUE
|
||||
|
||||
var/datum/radio_frequency/air_connection
|
||||
var/air_frequency = FREQ_ATMOS_ALARMS
|
||||
autoclose = FALSE
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Initialize()
|
||||
. = ..()
|
||||
air_connection = new
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Destroy()
|
||||
SSradio.remove_object(src,air_frequency)
|
||||
air_connection = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/Initialize()
|
||||
. = ..()
|
||||
SSradio.remove_object(src, air_frequency)
|
||||
air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM)
|
||||
open()
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
var/alarm_area = signal.data["zone"]
|
||||
var/alert = signal.data["alert"]
|
||||
|
||||
if(alarm_area == get_area_name(src))
|
||||
switch(alert)
|
||||
if("severe")
|
||||
autoclose = TRUE
|
||||
close()
|
||||
if("minor", "clear")
|
||||
autoclose = FALSE
|
||||
open()
|
||||
@@ -1,256 +1,256 @@
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define MAX_TIMER 9000
|
||||
|
||||
#define PRESET_SHORT 1200
|
||||
#define PRESET_MEDIUM 1800
|
||||
#define PRESET_LONG 3000
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Brig Door control displays.
|
||||
// Description: This is a controls the timer for the brig doors, displays the timer on itself and
|
||||
// has a popup window when used, allowing to set the timer.
|
||||
// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code
|
||||
// Date: 01/September/2010
|
||||
// Programmer: Veryinky
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/machinery/door_timer
|
||||
name = "door timer"
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id = null // id of linked machinery/lockers
|
||||
|
||||
var/activation_time = 0
|
||||
var/timer_duration = 0
|
||||
|
||||
var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing
|
||||
var/list/obj/machinery/targets = list()
|
||||
var/obj/item/radio/Radio //needed to send messages to sec radio
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
|
||||
Radio = new/obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
if(id != null)
|
||||
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
|
||||
if (M.id == id)
|
||||
targets += M
|
||||
|
||||
for(var/obj/machinery/flasher/F in urange(20, src))
|
||||
if(F.id == id)
|
||||
targets += F
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src))
|
||||
if(C.id == id)
|
||||
targets += C
|
||||
|
||||
if(!targets.len)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
|
||||
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
|
||||
// if it's less than 0, open door, reset timer
|
||||
// update the door_timer window and the icon
|
||||
/obj/machinery/door_timer/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(timing)
|
||||
if(world.realtime - activation_time >= timer_duration)
|
||||
timer_end() // open doors, reset timer, clear status screen
|
||||
update_icon()
|
||||
|
||||
// has the door power sitatuation changed, if so update icon.
|
||||
/obj/machinery/door_timer/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
// open/closedoor checks if door_timer has power, if so it checks if the
|
||||
// linked door is open/closed (by density) then opens it/closes it.
|
||||
/obj/machinery/door_timer/proc/timer_start()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
activation_time = world.realtime
|
||||
timing = TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened && !C.close())
|
||||
continue
|
||||
C.locked = TRUE
|
||||
C.update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/timer_end(forced = FALSE)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
if(!forced)
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY)
|
||||
|
||||
timing = FALSE
|
||||
activation_time = null
|
||||
set_timer(0)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(!door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened)
|
||||
continue
|
||||
C.locked = FALSE
|
||||
C.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
|
||||
. = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0))
|
||||
if(seconds)
|
||||
. /= 10
|
||||
|
||||
/obj/machinery/door_timer/proc/set_timer(value)
|
||||
var/new_time = CLAMP(value,0,MAX_TIMER)
|
||||
. = new_time == timer_duration //return 1 on no change
|
||||
timer_duration = new_time
|
||||
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer", name, 300, 200, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
// if NOPOWER, display blank
|
||||
// if BROKEN, display blue screen of death icon AI uses
|
||||
// if timing=true, run update display function
|
||||
/obj/machinery/door_timer/update_icon()
|
||||
if(stat & (NOPOWER))
|
||||
icon_state = "frame"
|
||||
return
|
||||
|
||||
if(stat & (BROKEN))
|
||||
set_picture("ai_bsod")
|
||||
return
|
||||
|
||||
if(timing)
|
||||
var/disp1 = id
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]"
|
||||
if(length(disp2) > CHARS_PER_LINE)
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
else
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
return
|
||||
|
||||
|
||||
// Adds an icon in case the screen is broken/off, stolen from status_display.dm
|
||||
/obj/machinery/door_timer/proc/set_picture(state)
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
cut_overlays()
|
||||
add_overlay(mutable_appearance('icons/obj/status_display.dmi', state))
|
||||
|
||||
|
||||
//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
|
||||
// Stolen from status_display
|
||||
/obj/machinery/door_timer/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/obj/machinery/door_timer/ui_data()
|
||||
var/list/data = list()
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
data["seconds"] = round(time_left % 60)
|
||||
data["minutes"] = round((time_left - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["flash_charging"] = FALSE
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
data["flash_charging"] = TRUE
|
||||
break
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/door_timer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("time")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
. = set_timer(time_left()+value)
|
||||
if("start")
|
||||
timer_start()
|
||||
if("stop")
|
||||
timer_end(forced = TRUE)
|
||||
if("flash")
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
F.flash()
|
||||
if("preset")
|
||||
var/preset = params["preset"]
|
||||
var/preset_time = time_left()
|
||||
switch(preset)
|
||||
if("short")
|
||||
preset_time = PRESET_SHORT
|
||||
if("medium")
|
||||
preset_time = PRESET_MEDIUM
|
||||
if("long")
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = world.realtime
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
#undef PRESET_SHORT
|
||||
#undef PRESET_MEDIUM
|
||||
#undef PRESET_LONG
|
||||
|
||||
#undef MAX_TIMER
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef CHARS_PER_LINE
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define MAX_TIMER 9000
|
||||
|
||||
#define PRESET_SHORT 1200
|
||||
#define PRESET_MEDIUM 1800
|
||||
#define PRESET_LONG 3000
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Brig Door control displays.
|
||||
// Description: This is a controls the timer for the brig doors, displays the timer on itself and
|
||||
// has a popup window when used, allowing to set the timer.
|
||||
// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code
|
||||
// Date: 01/September/2010
|
||||
// Programmer: Veryinky
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/machinery/door_timer
|
||||
name = "door timer"
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id = null // id of linked machinery/lockers
|
||||
|
||||
var/activation_time = 0
|
||||
var/timer_duration = 0
|
||||
|
||||
var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing
|
||||
var/list/obj/machinery/targets = list()
|
||||
var/obj/item/radio/Radio //needed to send messages to sec radio
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
|
||||
Radio = new/obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
|
||||
/obj/machinery/door_timer/Initialize()
|
||||
. = ..()
|
||||
if(id != null)
|
||||
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
|
||||
if (M.id == id)
|
||||
targets += M
|
||||
|
||||
for(var/obj/machinery/flasher/F in urange(20, src))
|
||||
if(F.id == id)
|
||||
targets += F
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src))
|
||||
if(C.id == id)
|
||||
targets += C
|
||||
|
||||
if(!targets.len)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
|
||||
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
|
||||
// if it's less than 0, open door, reset timer
|
||||
// update the door_timer window and the icon
|
||||
/obj/machinery/door_timer/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(timing)
|
||||
if(world.realtime - activation_time >= timer_duration)
|
||||
timer_end() // open doors, reset timer, clear status screen
|
||||
update_icon()
|
||||
|
||||
// has the door power sitatuation changed, if so update icon.
|
||||
/obj/machinery/door_timer/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
// open/closedoor checks if door_timer has power, if so it checks if the
|
||||
// linked door is open/closed (by density) then opens it/closes it.
|
||||
/obj/machinery/door_timer/proc/timer_start()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
activation_time = world.realtime
|
||||
timing = TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened && !C.close())
|
||||
continue
|
||||
C.locked = TRUE
|
||||
C.update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/timer_end(forced = FALSE)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
if(!forced)
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY)
|
||||
|
||||
timing = FALSE
|
||||
activation_time = null
|
||||
set_timer(0)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
if(!door.density)
|
||||
continue
|
||||
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open)
|
||||
|
||||
for(var/obj/structure/closet/secure_closet/brig/C in targets)
|
||||
if(C.broken)
|
||||
continue
|
||||
if(C.opened)
|
||||
continue
|
||||
C.locked = FALSE
|
||||
C.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
|
||||
. = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0))
|
||||
if(seconds)
|
||||
. /= 10
|
||||
|
||||
/obj/machinery/door_timer/proc/set_timer(value)
|
||||
var/new_time = CLAMP(value,0,MAX_TIMER)
|
||||
. = new_time == timer_duration //return 1 on no change
|
||||
timer_duration = new_time
|
||||
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "brig_timer", name, 300, 200, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
// if NOPOWER, display blank
|
||||
// if BROKEN, display blue screen of death icon AI uses
|
||||
// if timing=true, run update display function
|
||||
/obj/machinery/door_timer/update_icon()
|
||||
if(stat & (NOPOWER))
|
||||
icon_state = "frame"
|
||||
return
|
||||
|
||||
if(stat & (BROKEN))
|
||||
set_picture("ai_bsod")
|
||||
return
|
||||
|
||||
if(timing)
|
||||
var/disp1 = id
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]"
|
||||
if(length(disp2) > CHARS_PER_LINE)
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
else
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
return
|
||||
|
||||
|
||||
// Adds an icon in case the screen is broken/off, stolen from status_display.dm
|
||||
/obj/machinery/door_timer/proc/set_picture(state)
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
cut_overlays()
|
||||
add_overlay(mutable_appearance('icons/obj/status_display.dmi', state))
|
||||
|
||||
|
||||
//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
|
||||
// Stolen from status_display
|
||||
/obj/machinery/door_timer/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/obj/machinery/door_timer/ui_data()
|
||||
var/list/data = list()
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
data["seconds"] = round(time_left % 60)
|
||||
data["minutes"] = round((time_left - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["flash_charging"] = FALSE
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
if(F.last_flash && (F.last_flash + 150) > world.time)
|
||||
data["flash_charging"] = TRUE
|
||||
break
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/door_timer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("time")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(value)
|
||||
. = set_timer(time_left()+value)
|
||||
if("start")
|
||||
timer_start()
|
||||
if("stop")
|
||||
timer_end(forced = TRUE)
|
||||
if("flash")
|
||||
for(var/obj/machinery/flasher/F in targets)
|
||||
F.flash()
|
||||
if("preset")
|
||||
var/preset = params["preset"]
|
||||
var/preset_time = time_left()
|
||||
switch(preset)
|
||||
if("short")
|
||||
preset_time = PRESET_SHORT
|
||||
if("medium")
|
||||
preset_time = PRESET_MEDIUM
|
||||
if("long")
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = world.realtime
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
#undef PRESET_SHORT
|
||||
#undef PRESET_MEDIUM
|
||||
#undef PRESET_LONG
|
||||
|
||||
#undef MAX_TIMER
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef CHARS_PER_LINE
|
||||
|
||||
+385
-385
@@ -1,385 +1,385 @@
|
||||
/obj/machinery/door
|
||||
name = "door"
|
||||
desc = "It opens and closes."
|
||||
icon = 'icons/obj/doors/Doorint.dmi'
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = TRUE
|
||||
layer = OPEN_DOOR_LAYER
|
||||
power_channel = ENVIRON
|
||||
max_integrity = 350
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70)
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
flags_1 = PREVENT_CLICK_UNDER_1
|
||||
|
||||
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
|
||||
|
||||
var/secondsElectrified = 0
|
||||
var/shockedby
|
||||
var/visible = TRUE
|
||||
var/operating = FALSE
|
||||
var/glass = FALSE
|
||||
var/welded = FALSE
|
||||
var/normalspeed = 1
|
||||
var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors
|
||||
var/emergency = FALSE // Emergency access override
|
||||
var/sub_door = FALSE // true if it's meant to go under another door.
|
||||
var/closingLayer = CLOSED_DOOR_LAYER
|
||||
var/autoclose = FALSE //does it automatically close after some time
|
||||
var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them.
|
||||
var/locked = FALSE //whether the door is bolted or not.
|
||||
var/assemblytype //the type of door frame to drop during deconstruction
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/damage_deflection = 10
|
||||
var/real_explosion_block //ignore this, just use explosion_block
|
||||
var/red_alert_access = FALSE //if TRUE, this door will always open on red alert
|
||||
var/poddoor = FALSE
|
||||
var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access
|
||||
|
||||
/obj/machinery/door/examine(mob/user)
|
||||
. = ..()
|
||||
if(red_alert_access)
|
||||
if(GLOB.security_level >= SEC_LEVEL_RED)
|
||||
. += "<span class='notice'>Due to a security threat, its access requirements have been lifted!</span>"
|
||||
else
|
||||
. += "<span class='notice'>In the event of a red alert, its access requirements will automatically lift.</span>"
|
||||
if(!poddoor)
|
||||
. += "<span class='notice'>Its maintenance panel is <b>screwed</b> in place.</span>"
|
||||
|
||||
/obj/machinery/door/check_access_list(list/access_list)
|
||||
if(red_alert_access && GLOB.security_level >= SEC_LEVEL_RED)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/Initialize()
|
||||
. = ..()
|
||||
set_init_door_layer()
|
||||
update_freelook_sight()
|
||||
air_update_turf(1)
|
||||
GLOB.airlocks += src
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(2, 1, src)
|
||||
|
||||
//doors only block while dense though so we have to use the proc
|
||||
real_explosion_block = explosion_block
|
||||
explosion_block = EXPLOSION_BLOCK_PROC
|
||||
|
||||
/obj/machinery/door/proc/set_init_door_layer()
|
||||
if(density)
|
||||
layer = closingLayer
|
||||
else
|
||||
layer = initial(layer)
|
||||
|
||||
/obj/machinery/door/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/Destroy()
|
||||
update_freelook_sight()
|
||||
GLOB.airlocks -= src
|
||||
if(spark_system)
|
||||
qdel(spark_system)
|
||||
spark_system = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/Bumped(atom/movable/AM)
|
||||
if(operating || (obj_flags & EMAGGED))
|
||||
return
|
||||
if(ismob(AM))
|
||||
var/mob/B = AM
|
||||
if((isdrone(B) || iscyborg(B)) && B.stat)
|
||||
return
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
if(world.time - M.last_bumped <= 10)
|
||||
return //Can bump-open one airlock per second. This is to prevent shock spam.
|
||||
M.last_bumped = world.time
|
||||
if(M.restrained() && !check_access(null))
|
||||
return
|
||||
bumpopen(M)
|
||||
return
|
||||
|
||||
if(ismecha(AM))
|
||||
var/obj/mecha/mecha = AM
|
||||
if(density)
|
||||
if(mecha.occupant)
|
||||
if(world.time - mecha.occupant.last_bumped <= 10)
|
||||
return
|
||||
mecha.occupant.last_bumped = world.time
|
||||
if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
|
||||
open()
|
||||
else
|
||||
do_animate("deny")
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/door/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/machinery/door/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return !opacity
|
||||
return !density
|
||||
|
||||
/obj/machinery/door/proc/bumpopen(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
if(!src.requiresID())
|
||||
user = null
|
||||
|
||||
if(density && !(obj_flags & EMAGGED))
|
||||
if(allowed(user))
|
||||
open()
|
||||
else
|
||||
do_animate("deny")
|
||||
return
|
||||
|
||||
/obj/machinery/door/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
return try_to_activate_door(user)
|
||||
|
||||
/obj/machinery/door/attack_tk(mob/user)
|
||||
if(requiresID() && !allowed(null))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/door/proc/try_to_activate_door(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(operating || (obj_flags & EMAGGED))
|
||||
return
|
||||
if(!requiresID())
|
||||
user = null //so allowed(user) always succeeds
|
||||
if(allowed(user))
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
return
|
||||
if(density)
|
||||
do_animate("deny")
|
||||
|
||||
/obj/machinery/door/allowed(mob/M)
|
||||
if(emergency)
|
||||
return TRUE
|
||||
if(unrestricted_side(M))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
|
||||
return get_dir(src, M) & unres_sides
|
||||
|
||||
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/attackby(obj/item/I, mob/user, params)
|
||||
if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe)))
|
||||
try_to_crowbar(I, user)
|
||||
return 1
|
||||
else if(istype(I, /obj/item/weldingtool))
|
||||
try_to_weld(I, user)
|
||||
return 1
|
||||
else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM)
|
||||
try_to_activate_door(user)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
||||
if(damage_flag == "melee" && damage_amount < damage_deflection)
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/door/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(. && obj_integrity > 0)
|
||||
if(damage_amount >= 10 && prob(30))
|
||||
spark_system.start()
|
||||
|
||||
/obj/machinery/door/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
if(glass)
|
||||
playsound(loc, 'sound/effects/glasshit.ogg', 90, 1)
|
||||
else if(damage_amount)
|
||||
playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
|
||||
else
|
||||
playsound(src, 'sound/weapons/tap.ogg', 50, 1)
|
||||
if(BURN)
|
||||
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
|
||||
|
||||
/obj/machinery/door/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) )
|
||||
INVOKE_ASYNC(src, .proc/open)
|
||||
if(prob(severity*10 - 20))
|
||||
if(secondsElectrified == 0)
|
||||
secondsElectrified = -1
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse")
|
||||
addtimer(CALLBACK(src, .proc/unelectrify), 300)
|
||||
|
||||
/obj/machinery/door/proc/unelectrify()
|
||||
secondsElectrified = 0
|
||||
|
||||
/obj/machinery/door/update_icon()
|
||||
if(density)
|
||||
icon_state = "door1"
|
||||
else
|
||||
icon_state = "door0"
|
||||
|
||||
/obj/machinery/door/proc/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
if(panel_open)
|
||||
flick("o_doorc0", src)
|
||||
else
|
||||
flick("doorc0", src)
|
||||
if("closing")
|
||||
if(panel_open)
|
||||
flick("o_doorc1", src)
|
||||
else
|
||||
flick("doorc1", src)
|
||||
if("deny")
|
||||
if(!stat)
|
||||
flick("door_deny", src)
|
||||
|
||||
|
||||
/obj/machinery/door/proc/open()
|
||||
if(!density)
|
||||
return 1
|
||||
if(operating)
|
||||
return
|
||||
operating = TRUE
|
||||
do_animate("opening")
|
||||
set_opacity(0)
|
||||
sleep(5)
|
||||
density = FALSE
|
||||
sleep(5)
|
||||
layer = initial(layer)
|
||||
update_icon()
|
||||
set_opacity(0)
|
||||
operating = FALSE
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
if(autoclose)
|
||||
spawn(autoclose)
|
||||
close()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/close()
|
||||
if(density)
|
||||
return TRUE
|
||||
if(operating || welded)
|
||||
return
|
||||
if(safe)
|
||||
for(var/atom/movable/M in get_turf(src))
|
||||
if(M.density && M != src) //something is blocking the door
|
||||
if(autoclose)
|
||||
autoclose_in(60)
|
||||
return
|
||||
|
||||
operating = TRUE
|
||||
|
||||
do_animate("closing")
|
||||
layer = closingLayer
|
||||
sleep(5)
|
||||
density = TRUE
|
||||
sleep(5)
|
||||
update_icon()
|
||||
if(visible && !glass)
|
||||
set_opacity(1)
|
||||
operating = FALSE
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
if(safe)
|
||||
CheckForMobs()
|
||||
else
|
||||
crush()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/CheckForMobs()
|
||||
if(locate(/mob/living) in get_turf(src))
|
||||
sleep(1)
|
||||
open()
|
||||
|
||||
/obj/machinery/door/proc/crush()
|
||||
for(var/mob/living/L in get_turf(src))
|
||||
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
|
||||
if(isalien(L)) //For xenos
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
|
||||
L.emote("roar")
|
||||
else if(ishuman(L)) //For humans
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
L.emote("scream")
|
||||
L.Knockdown(100)
|
||||
else if(ismonkey(L)) //For monkeys
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
L.Knockdown(100)
|
||||
else //for simple_animals & borgs
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
var/turf/location = get_turf(src)
|
||||
//add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does.
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
C.bleed(DOOR_CRUSH_DAMAGE)
|
||||
else
|
||||
L.add_splatter_floor(location)
|
||||
for(var/obj/mecha/M in get_turf(src))
|
||||
M.take_damage(DOOR_CRUSH_DAMAGE)
|
||||
|
||||
/obj/machinery/door/proc/autoclose()
|
||||
if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
|
||||
close()
|
||||
|
||||
/obj/machinery/door/proc/autoclose_in(wait)
|
||||
addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE)
|
||||
|
||||
/obj/machinery/door/proc/requiresID()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/hasPower()
|
||||
return !(stat & NOPOWER)
|
||||
|
||||
/obj/machinery/door/proc/update_freelook_sight()
|
||||
if(!glass && GLOB.cameranet)
|
||||
GLOB.cameranet.updateVisibility(src, 0)
|
||||
|
||||
/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended.
|
||||
if(opacity || heat_proof)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/door/morgue
|
||||
icon = 'icons/obj/doors/doormorgue.dmi'
|
||||
|
||||
/obj/machinery/door/get_dumping_location(obj/item/storage/source,mob/user)
|
||||
return null
|
||||
|
||||
/obj/machinery/door/proc/lock()
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/unlock()
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/hostile_lockdown(mob/origin)
|
||||
if(!stat) //So that only powered doors are closed.
|
||||
close() //Close ALL the doors!
|
||||
|
||||
/obj/machinery/door/proc/disable_lockdown()
|
||||
if(!stat) //Opens only powered doors.
|
||||
open() //Open everything!
|
||||
|
||||
/obj/machinery/door/ex_act(severity, target)
|
||||
//if it blows up a wall it should blow up a door
|
||||
..(severity ? max(1, severity - 1) : 0, target)
|
||||
|
||||
/obj/machinery/door/GetExplosionBlock()
|
||||
return density ? real_explosion_block : 0
|
||||
/obj/machinery/door
|
||||
name = "door"
|
||||
desc = "It opens and closes."
|
||||
icon = 'icons/obj/doors/Doorint.dmi'
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = TRUE
|
||||
layer = OPEN_DOOR_LAYER
|
||||
power_channel = ENVIRON
|
||||
max_integrity = 350
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70)
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
flags_1 = PREVENT_CLICK_UNDER_1
|
||||
|
||||
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
|
||||
|
||||
var/secondsElectrified = 0
|
||||
var/shockedby
|
||||
var/visible = TRUE
|
||||
var/operating = FALSE
|
||||
var/glass = FALSE
|
||||
var/welded = FALSE
|
||||
var/normalspeed = 1
|
||||
var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors
|
||||
var/emergency = FALSE // Emergency access override
|
||||
var/sub_door = FALSE // true if it's meant to go under another door.
|
||||
var/closingLayer = CLOSED_DOOR_LAYER
|
||||
var/autoclose = FALSE //does it automatically close after some time
|
||||
var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them.
|
||||
var/locked = FALSE //whether the door is bolted or not.
|
||||
var/assemblytype //the type of door frame to drop during deconstruction
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/damage_deflection = 10
|
||||
var/real_explosion_block //ignore this, just use explosion_block
|
||||
var/red_alert_access = FALSE //if TRUE, this door will always open on red alert
|
||||
var/poddoor = FALSE
|
||||
var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access
|
||||
|
||||
/obj/machinery/door/examine(mob/user)
|
||||
. = ..()
|
||||
if(red_alert_access)
|
||||
if(GLOB.security_level >= SEC_LEVEL_RED)
|
||||
. += "<span class='notice'>Due to a security threat, its access requirements have been lifted!</span>"
|
||||
else
|
||||
. += "<span class='notice'>In the event of a red alert, its access requirements will automatically lift.</span>"
|
||||
if(!poddoor)
|
||||
. += "<span class='notice'>Its maintenance panel is <b>screwed</b> in place.</span>"
|
||||
|
||||
/obj/machinery/door/check_access_list(list/access_list)
|
||||
if(red_alert_access && GLOB.security_level >= SEC_LEVEL_RED)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/Initialize()
|
||||
. = ..()
|
||||
set_init_door_layer()
|
||||
update_freelook_sight()
|
||||
air_update_turf(1)
|
||||
GLOB.airlocks += src
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(2, 1, src)
|
||||
|
||||
//doors only block while dense though so we have to use the proc
|
||||
real_explosion_block = explosion_block
|
||||
explosion_block = EXPLOSION_BLOCK_PROC
|
||||
|
||||
/obj/machinery/door/proc/set_init_door_layer()
|
||||
if(density)
|
||||
layer = closingLayer
|
||||
else
|
||||
layer = initial(layer)
|
||||
|
||||
/obj/machinery/door/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/Destroy()
|
||||
update_freelook_sight()
|
||||
GLOB.airlocks -= src
|
||||
if(spark_system)
|
||||
qdel(spark_system)
|
||||
spark_system = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/Bumped(atom/movable/AM)
|
||||
if(operating || (obj_flags & EMAGGED))
|
||||
return
|
||||
if(ismob(AM))
|
||||
var/mob/B = AM
|
||||
if((isdrone(B) || iscyborg(B)) && B.stat)
|
||||
return
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
if(world.time - M.last_bumped <= 10)
|
||||
return //Can bump-open one airlock per second. This is to prevent shock spam.
|
||||
M.last_bumped = world.time
|
||||
if(M.restrained() && !check_access(null))
|
||||
return
|
||||
bumpopen(M)
|
||||
return
|
||||
|
||||
if(ismecha(AM))
|
||||
var/obj/mecha/mecha = AM
|
||||
if(density)
|
||||
if(mecha.occupant)
|
||||
if(world.time - mecha.occupant.last_bumped <= 10)
|
||||
return
|
||||
mecha.occupant.last_bumped = world.time
|
||||
if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
|
||||
open()
|
||||
else
|
||||
do_animate("deny")
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/door/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/machinery/door/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return !opacity
|
||||
return !density
|
||||
|
||||
/obj/machinery/door/proc/bumpopen(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
if(!src.requiresID())
|
||||
user = null
|
||||
|
||||
if(density && !(obj_flags & EMAGGED))
|
||||
if(allowed(user))
|
||||
open()
|
||||
else
|
||||
do_animate("deny")
|
||||
return
|
||||
|
||||
/obj/machinery/door/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
return try_to_activate_door(user)
|
||||
|
||||
/obj/machinery/door/attack_tk(mob/user)
|
||||
if(requiresID() && !allowed(null))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/door/proc/try_to_activate_door(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(operating || (obj_flags & EMAGGED))
|
||||
return
|
||||
if(!requiresID())
|
||||
user = null //so allowed(user) always succeeds
|
||||
if(allowed(user))
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
return
|
||||
if(density)
|
||||
do_animate("deny")
|
||||
|
||||
/obj/machinery/door/allowed(mob/M)
|
||||
if(emergency)
|
||||
return TRUE
|
||||
if(unrestricted_side(M))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
|
||||
return get_dir(src, M) & unres_sides
|
||||
|
||||
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/attackby(obj/item/I, mob/user, params)
|
||||
if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe)))
|
||||
try_to_crowbar(I, user)
|
||||
return 1
|
||||
else if(istype(I, /obj/item/weldingtool))
|
||||
try_to_weld(I, user)
|
||||
return 1
|
||||
else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM)
|
||||
try_to_activate_door(user)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
||||
if(damage_flag == "melee" && damage_amount < damage_deflection)
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/door/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(. && obj_integrity > 0)
|
||||
if(damage_amount >= 10 && prob(30))
|
||||
spark_system.start()
|
||||
|
||||
/obj/machinery/door/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
if(glass)
|
||||
playsound(loc, 'sound/effects/glasshit.ogg', 90, 1)
|
||||
else if(damage_amount)
|
||||
playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
|
||||
else
|
||||
playsound(src, 'sound/weapons/tap.ogg', 50, 1)
|
||||
if(BURN)
|
||||
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
|
||||
|
||||
/obj/machinery/door/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) )
|
||||
INVOKE_ASYNC(src, .proc/open)
|
||||
if(prob(severity*10 - 20))
|
||||
if(secondsElectrified == 0)
|
||||
secondsElectrified = -1
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse")
|
||||
addtimer(CALLBACK(src, .proc/unelectrify), 300)
|
||||
|
||||
/obj/machinery/door/proc/unelectrify()
|
||||
secondsElectrified = 0
|
||||
|
||||
/obj/machinery/door/update_icon()
|
||||
if(density)
|
||||
icon_state = "door1"
|
||||
else
|
||||
icon_state = "door0"
|
||||
|
||||
/obj/machinery/door/proc/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
if(panel_open)
|
||||
flick("o_doorc0", src)
|
||||
else
|
||||
flick("doorc0", src)
|
||||
if("closing")
|
||||
if(panel_open)
|
||||
flick("o_doorc1", src)
|
||||
else
|
||||
flick("doorc1", src)
|
||||
if("deny")
|
||||
if(!stat)
|
||||
flick("door_deny", src)
|
||||
|
||||
|
||||
/obj/machinery/door/proc/open()
|
||||
if(!density)
|
||||
return 1
|
||||
if(operating)
|
||||
return
|
||||
operating = TRUE
|
||||
do_animate("opening")
|
||||
set_opacity(0)
|
||||
sleep(5)
|
||||
density = FALSE
|
||||
sleep(5)
|
||||
layer = initial(layer)
|
||||
update_icon()
|
||||
set_opacity(0)
|
||||
operating = FALSE
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
if(autoclose)
|
||||
spawn(autoclose)
|
||||
close()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/close()
|
||||
if(density)
|
||||
return TRUE
|
||||
if(operating || welded)
|
||||
return
|
||||
if(safe)
|
||||
for(var/atom/movable/M in get_turf(src))
|
||||
if(M.density && M != src) //something is blocking the door
|
||||
if(autoclose)
|
||||
autoclose_in(60)
|
||||
return
|
||||
|
||||
operating = TRUE
|
||||
|
||||
do_animate("closing")
|
||||
layer = closingLayer
|
||||
sleep(5)
|
||||
density = TRUE
|
||||
sleep(5)
|
||||
update_icon()
|
||||
if(visible && !glass)
|
||||
set_opacity(1)
|
||||
operating = FALSE
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
if(safe)
|
||||
CheckForMobs()
|
||||
else
|
||||
crush()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/CheckForMobs()
|
||||
if(locate(/mob/living) in get_turf(src))
|
||||
sleep(1)
|
||||
open()
|
||||
|
||||
/obj/machinery/door/proc/crush()
|
||||
for(var/mob/living/L in get_turf(src))
|
||||
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
|
||||
if(isalien(L)) //For xenos
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
|
||||
L.emote("roar")
|
||||
else if(ishuman(L)) //For humans
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
L.emote("scream")
|
||||
L.Knockdown(100)
|
||||
else if(ismonkey(L)) //For monkeys
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
L.Knockdown(100)
|
||||
else //for simple_animals & borgs
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
|
||||
var/turf/location = get_turf(src)
|
||||
//add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does.
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
C.bleed(DOOR_CRUSH_DAMAGE)
|
||||
else
|
||||
L.add_splatter_floor(location)
|
||||
for(var/obj/mecha/M in get_turf(src))
|
||||
M.take_damage(DOOR_CRUSH_DAMAGE)
|
||||
|
||||
/obj/machinery/door/proc/autoclose()
|
||||
if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
|
||||
close()
|
||||
|
||||
/obj/machinery/door/proc/autoclose_in(wait)
|
||||
addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE)
|
||||
|
||||
/obj/machinery/door/proc/requiresID()
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/proc/hasPower()
|
||||
return !(stat & NOPOWER)
|
||||
|
||||
/obj/machinery/door/proc/update_freelook_sight()
|
||||
if(!glass && GLOB.cameranet)
|
||||
GLOB.cameranet.updateVisibility(src, 0)
|
||||
|
||||
/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended.
|
||||
if(opacity || heat_proof)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/door/morgue
|
||||
icon = 'icons/obj/doors/doormorgue.dmi'
|
||||
|
||||
/obj/machinery/door/get_dumping_location(obj/item/storage/source,mob/user)
|
||||
return null
|
||||
|
||||
/obj/machinery/door/proc/lock()
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/unlock()
|
||||
return
|
||||
|
||||
/obj/machinery/door/proc/hostile_lockdown(mob/origin)
|
||||
if(!stat) //So that only powered doors are closed.
|
||||
close() //Close ALL the doors!
|
||||
|
||||
/obj/machinery/door/proc/disable_lockdown()
|
||||
if(!stat) //Opens only powered doors.
|
||||
open() //Open everything!
|
||||
|
||||
/obj/machinery/door/ex_act(severity, target)
|
||||
//if it blows up a wall it should blow up a door
|
||||
..(severity ? max(1, severity - 1) : 0, target)
|
||||
|
||||
/obj/machinery/door/GetExplosionBlock()
|
||||
return density ? real_explosion_block : 0
|
||||
|
||||
@@ -1,461 +1,476 @@
|
||||
#define CONSTRUCTION_COMPLETE 0 //No construction done - functioning as normal
|
||||
#define CONSTRUCTION_PANEL_OPEN 1 //Maintenance panel is open, still functioning
|
||||
#define CONSTRUCTION_WIRES_EXPOSED 2 //Cover plate is removed, wires are available
|
||||
#define CONSTRUCTION_GUTTED 3 //Wires are removed, circuit ready to remove
|
||||
#define CONSTRUCTION_NOCIRCUIT 4 //Circuit board removed, can safely weld apart
|
||||
|
||||
/obj/machinery/door/firedoor
|
||||
name = "firelock"
|
||||
desc = "Apply crowbar."
|
||||
icon = 'icons/obj/doors/Doorfireglass.dmi'
|
||||
icon_state = "door_open"
|
||||
opacity = FALSE
|
||||
density = FALSE
|
||||
max_integrity = 300
|
||||
resistance_flags = FIRE_PROOF
|
||||
heat_proof = TRUE
|
||||
glass = TRUE
|
||||
sub_door = TRUE
|
||||
explosion_block = 1
|
||||
safe = FALSE
|
||||
layer = BELOW_OPEN_DOOR_LAYER
|
||||
closingLayer = CLOSED_FIREDOOR_LAYER
|
||||
assemblytype = /obj/structure/firelock_frame
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70)
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
|
||||
var/nextstate = null
|
||||
var/boltslocked = TRUE
|
||||
var/list/affecting_areas
|
||||
|
||||
/obj/machinery/door/firedoor/Initialize()
|
||||
. = ..()
|
||||
CalculateAffectingAreas()
|
||||
|
||||
/obj/machinery/door/firedoor/examine(mob/user)
|
||||
..()
|
||||
if(!density)
|
||||
. += "<span class='notice'>It is open, but could be <b>pried</b> closed.</span>"
|
||||
else if(!welded)
|
||||
. += "<span class='notice'>It is closed, but could be <i>pried</i> open. Deconstruction would require it to be <b>welded</b> shut.</span>"
|
||||
else if(boltslocked)
|
||||
. += "<span class='notice'>It is <i>welded</i> shut. The floor bolts have been locked by <b>screws</b>.</span>"
|
||||
else
|
||||
. += "<span class='notice'>The bolt locks have been <i>unscrewed</i>, but the bolts themselves are still <b>wrenched</b> to the floor.</span>"
|
||||
|
||||
/obj/machinery/door/firedoor/proc/CalculateAffectingAreas()
|
||||
remove_from_areas()
|
||||
affecting_areas = get_adjacent_open_areas(src) | get_area(src)
|
||||
for(var/I in affecting_areas)
|
||||
var/area/A = I
|
||||
LAZYADD(A.firedoors, src)
|
||||
|
||||
/obj/machinery/door/firedoor/closed
|
||||
icon_state = "door_closed"
|
||||
opacity = TRUE
|
||||
density = TRUE
|
||||
|
||||
//see also turf/AfterChange for adjacency shennanigans
|
||||
|
||||
/obj/machinery/door/firedoor/proc/remove_from_areas()
|
||||
if(affecting_areas)
|
||||
for(var/I in affecting_areas)
|
||||
var/area/A = I
|
||||
LAZYREMOVE(A.firedoors, src)
|
||||
|
||||
/obj/machinery/door/firedoor/Destroy()
|
||||
remove_from_areas()
|
||||
affecting_areas.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/firedoor/Bumped(atom/movable/AM)
|
||||
if(panel_open || operating)
|
||||
return
|
||||
if(!density)
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/machinery/door/firedoor/power_change()
|
||||
if(powered(power_channel))
|
||||
stat &= ~NOPOWER
|
||||
latetoggle()
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
/obj/machinery/door/firedoor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(operating || !density)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
user.visible_message("[user] bangs on \the [src].",
|
||||
"You bang on \the [src].")
|
||||
playsound(loc, 'sound/effects/glassknock.ogg', 10, FALSE, frequency = 32000)
|
||||
|
||||
/obj/machinery/door/firedoor/attackby(obj/item/C, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
if(welded)
|
||||
if(istype(C, /obj/item/wrench))
|
||||
if(boltslocked)
|
||||
to_chat(user, "<span class='notice'>There are screws locking the bolts in place!</span>")
|
||||
return
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts undoing [src]'s bolts...</span>", \
|
||||
"<span class='notice'>You start unfastening [src]'s floor bolts...</span>")
|
||||
if(!C.use_tool(src, user, 50))
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] unfastens [src]'s bolts.</span>", \
|
||||
"<span class='notice'>You undo [src]'s floor bolts.</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
if(istype(C, /obj/item/screwdriver))
|
||||
user.visible_message("<span class='notice'>[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.</span>", \
|
||||
"<span class='notice'>You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.</span>")
|
||||
C.play_tool_sound(src)
|
||||
boltslocked = !boltslocked
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_activate_door(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts [welded ? "unwelding" : "welding"] [src].</span>", "<span class='notice'>You start welding [src].</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
welded = !welded
|
||||
to_chat(user, "<span class='danger'>[user] [welded?"welds":"unwelds"] [src].</span>", "<span class='notice'>You [welded ? "weld" : "unweld"] [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_crowbar(obj/item/I, mob/user)
|
||||
if(welded || operating)
|
||||
return
|
||||
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
|
||||
/obj/machinery/door/firedoor/attack_ai(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(welded || operating || stat & NOPOWER)
|
||||
return TRUE
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/attack_robot(mob/user)
|
||||
return attack_ai(user)
|
||||
|
||||
/obj/machinery/door/firedoor/attack_alien(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(welded)
|
||||
to_chat(user, "<span class='warning'>[src] refuses to budge!</span>")
|
||||
return
|
||||
open()
|
||||
|
||||
/obj/machinery/door/firedoor/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
flick("door_opening", src)
|
||||
if("closing")
|
||||
flick("door_closing", src)
|
||||
|
||||
/obj/machinery/door/firedoor/update_icon()
|
||||
cut_overlays()
|
||||
if(density)
|
||||
icon_state = "door_closed"
|
||||
if(welded)
|
||||
add_overlay("welded")
|
||||
else
|
||||
icon_state = "door_open"
|
||||
if(welded)
|
||||
add_overlay("welded_open")
|
||||
|
||||
/obj/machinery/door/firedoor/open()
|
||||
. = ..()
|
||||
latetoggle()
|
||||
|
||||
/obj/machinery/door/firedoor/close()
|
||||
. = ..()
|
||||
latetoggle()
|
||||
|
||||
/obj/machinery/door/firedoor/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src))
|
||||
if(disassembled)
|
||||
F.constructionStep = CONSTRUCTION_PANEL_OPEN
|
||||
else
|
||||
F.constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
F.obj_integrity = F.max_integrity * 0.5
|
||||
F.update_icon()
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/machinery/door/firedoor/proc/latetoggle()
|
||||
if(operating || stat & NOPOWER || !nextstate)
|
||||
return
|
||||
switch(nextstate)
|
||||
if(FIREDOOR_OPEN)
|
||||
nextstate = null
|
||||
open()
|
||||
if(FIREDOOR_CLOSED)
|
||||
nextstate = null
|
||||
close()
|
||||
|
||||
/obj/machinery/door/firedoor/border_only
|
||||
icon = 'icons/obj/doors/edge_Doorfire.dmi'
|
||||
flags_1 = ON_BORDER_1
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/closed
|
||||
icon_state = "door_closed"
|
||||
opacity = TRUE
|
||||
density = TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == dir)
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CanAtmosPass(turf/T)
|
||||
if(get_dir(loc, T) == dir)
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/heavy
|
||||
name = "heavy firelock"
|
||||
icon = 'icons/obj/doors/Doorfire.dmi'
|
||||
glass = FALSE
|
||||
explosion_block = 2
|
||||
assemblytype = /obj/structure/firelock_frame/heavy
|
||||
max_integrity = 550
|
||||
|
||||
|
||||
/obj/item/electronics/firelock
|
||||
name = "firelock circuitry"
|
||||
desc = "A circuit board used in construction of firelocks."
|
||||
icon_state = "mainboard"
|
||||
|
||||
/obj/structure/firelock_frame
|
||||
name = "firelock frame"
|
||||
desc = "A partially completed firelock."
|
||||
icon = 'icons/obj/doors/Doorfire.dmi'
|
||||
icon_state = "frame1"
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
var/constructionStep = CONSTRUCTION_NOCIRCUIT
|
||||
var/reinforced = 0
|
||||
|
||||
/obj/structure/firelock_frame/examine(mob/user)
|
||||
. = ..()
|
||||
switch(constructionStep)
|
||||
if(CONSTRUCTION_PANEL_OPEN)
|
||||
. += "<span class='notice'>It is <i>unbolted</i> from the floor. A small <b>loosely connected</b> metal plate is covering the wires.</span>"
|
||||
if(!reinforced)
|
||||
. += "<span class='notice'>It could be reinforced with plasteel.</span>"
|
||||
if(CONSTRUCTION_WIRES_EXPOSED)
|
||||
. += "<span class='notice'>The maintenance plate has been <i>pried away</i>, and <b>wires</b> are trailing.</span>"
|
||||
if(CONSTRUCTION_GUTTED)
|
||||
. += "<span class='notice'>The maintenance panel is missing <i>wires</i> and the circuit board is <b>loosely connected</b>.</span>"
|
||||
if(CONSTRUCTION_NOCIRCUIT)
|
||||
. += "<span class='notice'>There are no <i>firelock electronics</i> in the frame. The frame could be <b>cut</b> apart.</span>"
|
||||
|
||||
/obj/structure/firelock_frame/update_icon()
|
||||
..()
|
||||
icon_state = "frame[constructionStep]"
|
||||
|
||||
/obj/structure/firelock_frame/attackby(obj/item/C, mob/user)
|
||||
switch(constructionStep)
|
||||
if(CONSTRUCTION_PANEL_OPEN)
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts prying something out from [src]...</span>", \
|
||||
"<span class='notice'>You begin prying out the wire cover...</span>")
|
||||
if(!C.use_tool(src, user, 50))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_PANEL_OPEN)
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] pries out a metal plate from [src], exposing the wires.</span>", \
|
||||
"<span class='notice'>You remove the cover plate from [src], exposing the wires.</span>")
|
||||
constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/wrench))
|
||||
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
|
||||
to_chat(user, "<span class='warning'>There's already a firelock there.</span>")
|
||||
return
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts bolting down [src]...</span>", \
|
||||
"<span class='notice'>You begin bolting [src]...</span>")
|
||||
if(!C.use_tool(src, user, 30))
|
||||
return
|
||||
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] finishes the firelock.</span>", \
|
||||
"<span class='notice'>You finish the firelock.</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(reinforced)
|
||||
new /obj/machinery/door/firedoor/heavy(get_turf(src))
|
||||
else
|
||||
new /obj/machinery/door/firedoor(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(C, /obj/item/stack/sheet/plasteel))
|
||||
var/obj/item/stack/sheet/plasteel/P = C
|
||||
if(reinforced)
|
||||
to_chat(user, "<span class='warning'>[src] is already reinforced.</span>")
|
||||
return
|
||||
if(P.get_amount() < 2)
|
||||
to_chat(user, "<span class='warning'>You need more plasteel to reinforce [src].</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins reinforcing [src]...</span>", \
|
||||
"<span class='notice'>You begin reinforcing [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 60, target = src))
|
||||
if(constructionStep != CONSTRUCTION_PANEL_OPEN || reinforced || P.get_amount() < 2 || !P)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] reinforces [src].</span>", \
|
||||
"<span class='notice'>You reinforce [src].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
P.use(2)
|
||||
reinforced = 1
|
||||
return
|
||||
|
||||
if(CONSTRUCTION_WIRES_EXPOSED)
|
||||
if(istype(C, /obj/item/wirecutters))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts cutting the wires from [src]...</span>", \
|
||||
"<span class='notice'>You begin removing [src]'s wires...</span>")
|
||||
if(!C.use_tool(src, user, 60))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_WIRES_EXPOSED)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] removes the wires from [src].</span>", \
|
||||
"<span class='notice'>You remove the wiring from [src], exposing the circuit board.</span>")
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 5)
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts prying a metal plate into [src]...</span>", \
|
||||
"<span class='notice'>You begin prying the cover plate back onto [src]...</span>")
|
||||
if(!C.use_tool(src, user, 80))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_WIRES_EXPOSED)
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] pries the metal plate into [src].</span>", \
|
||||
"<span class='notice'>You pry [src]'s cover plate into place, hiding the wires.</span>")
|
||||
constructionStep = CONSTRUCTION_PANEL_OPEN
|
||||
update_icon()
|
||||
return
|
||||
if(CONSTRUCTION_GUTTED)
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
user.visible_message("<span class='notice'>[user] begins removing the circuit board from [src]...</span>", \
|
||||
"<span class='notice'>You begin prying out the circuit board from [src]...</span>")
|
||||
if(!C.use_tool(src, user, 50, volume=50))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_GUTTED)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] removes [src]'s circuit board.</span>", \
|
||||
"<span class='notice'>You remove the circuit board from [src].</span>")
|
||||
new /obj/item/electronics/firelock(drop_location())
|
||||
constructionStep = CONSTRUCTION_NOCIRCUIT
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/B = C
|
||||
if(B.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning'>You need more wires to add wiring to [src].</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins wiring [src]...</span>", \
|
||||
"<span class='notice'>You begin adding wires to [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 60, target = src))
|
||||
if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] adds wires to [src].</span>", \
|
||||
"<span class='notice'>You wire [src].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
B.use(5)
|
||||
constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
update_icon()
|
||||
return
|
||||
if(CONSTRUCTION_NOCIRCUIT)
|
||||
if(istype(C, /obj/item/weldingtool))
|
||||
if(!C.tool_start_check(user, amount=1))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins cutting apart [src]'s frame...</span>", \
|
||||
"<span class='notice'>You begin slicing [src] apart...</span>")
|
||||
|
||||
if(C.use_tool(src, user, 40, volume=50, amount=1))
|
||||
if(constructionStep != CONSTRUCTION_NOCIRCUIT)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] cuts apart [src]!</span>", \
|
||||
"<span class='notice'>You cut [src] into metal.</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
new /obj/item/stack/sheet/metal(T, 3)
|
||||
if(reinforced)
|
||||
new /obj/item/stack/sheet/plasteel(T, 2)
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(C, /obj/item/electronics/firelock))
|
||||
user.visible_message("<span class='notice'>[user] starts adding [C] to [src]...</span>", \
|
||||
"<span class='notice'>You begin adding a circuit board to [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(!do_after(user, 40, target = src))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_NOCIRCUIT)
|
||||
return
|
||||
qdel(C)
|
||||
user.visible_message("<span class='notice'>[user] adds a circuit to [src].</span>", \
|
||||
"<span class='notice'>You insert and secure [C].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/electroadaptive_pseudocircuit))
|
||||
var/obj/item/electroadaptive_pseudocircuit/P = C
|
||||
if(!P.adapt_circuit(user, 30))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a firelock circuit and slot it into the assembly.</span>")
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/structure/firelock_frame/heavy
|
||||
name = "heavy firelock frame"
|
||||
reinforced = TRUE
|
||||
|
||||
#undef CONSTRUCTION_COMPLETE
|
||||
#undef CONSTRUCTION_PANEL_OPEN
|
||||
#undef CONSTRUCTION_WIRES_EXPOSED
|
||||
#undef CONSTRUCTION_GUTTED
|
||||
#undef CONSTRUCTION_NOCIRCUIT
|
||||
#define CONSTRUCTION_COMPLETE 0 //No construction done - functioning as normal
|
||||
#define CONSTRUCTION_PANEL_OPEN 1 //Maintenance panel is open, still functioning
|
||||
#define CONSTRUCTION_WIRES_EXPOSED 2 //Cover plate is removed, wires are available
|
||||
#define CONSTRUCTION_GUTTED 3 //Wires are removed, circuit ready to remove
|
||||
#define CONSTRUCTION_NOCIRCUIT 4 //Circuit board removed, can safely weld apart
|
||||
|
||||
/obj/machinery/door/firedoor
|
||||
name = "firelock"
|
||||
desc = "Apply crowbar."
|
||||
icon = 'icons/obj/doors/Doorfireglass.dmi'
|
||||
icon_state = "door_open"
|
||||
opacity = FALSE
|
||||
density = FALSE
|
||||
max_integrity = 300
|
||||
resistance_flags = FIRE_PROOF
|
||||
heat_proof = TRUE
|
||||
glass = TRUE
|
||||
sub_door = TRUE
|
||||
explosion_block = 1
|
||||
safe = FALSE
|
||||
layer = BELOW_OPEN_DOOR_LAYER
|
||||
closingLayer = CLOSED_FIREDOOR_LAYER
|
||||
assemblytype = /obj/structure/firelock_frame
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70)
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
|
||||
var/nextstate = null
|
||||
var/boltslocked = TRUE
|
||||
var/list/affecting_areas
|
||||
|
||||
/obj/machinery/door/firedoor/Initialize()
|
||||
. = ..()
|
||||
CalculateAffectingAreas()
|
||||
|
||||
/obj/machinery/door/firedoor/examine(mob/user)
|
||||
..()
|
||||
if(!density)
|
||||
. += "<span class='notice'>It is open, but could be <b>pried</b> closed.</span>"
|
||||
else if(!welded)
|
||||
. += "<span class='notice'>It is closed, but could be <i>pried</i> open. Deconstruction would require it to be <b>welded</b> shut.</span>"
|
||||
else if(boltslocked)
|
||||
. += "<span class='notice'>It is <i>welded</i> shut. The floor bolts have been locked by <b>screws</b>.</span>"
|
||||
else
|
||||
. += "<span class='notice'>The bolt locks have been <i>unscrewed</i>, but the bolts themselves are still <b>wrenched</b> to the floor.</span>"
|
||||
|
||||
/obj/machinery/door/firedoor/proc/CalculateAffectingAreas()
|
||||
remove_from_areas()
|
||||
affecting_areas = get_adjacent_open_areas(src) | get_area(src)
|
||||
for(var/I in affecting_areas)
|
||||
var/area/A = I
|
||||
LAZYADD(A.firedoors, src)
|
||||
|
||||
/obj/machinery/door/firedoor/closed
|
||||
icon_state = "door_closed"
|
||||
opacity = TRUE
|
||||
density = TRUE
|
||||
|
||||
//see also turf/AfterChange for adjacency shennanigans
|
||||
|
||||
/obj/machinery/door/firedoor/proc/remove_from_areas()
|
||||
if(affecting_areas)
|
||||
for(var/I in affecting_areas)
|
||||
var/area/A = I
|
||||
LAZYREMOVE(A.firedoors, src)
|
||||
|
||||
/obj/machinery/door/firedoor/Destroy()
|
||||
remove_from_areas()
|
||||
affecting_areas.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/firedoor/Bumped(atom/movable/AM)
|
||||
if(panel_open || operating)
|
||||
return
|
||||
if(!density)
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/machinery/door/firedoor/power_change()
|
||||
if(powered(power_channel))
|
||||
stat &= ~NOPOWER
|
||||
latetoggle()
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
/obj/machinery/door/firedoor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(operating || !density)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
user.visible_message("[user] bangs on \the [src].",
|
||||
"You bang on \the [src].")
|
||||
playsound(loc, 'sound/effects/glassknock.ogg', 10, FALSE, frequency = 32000)
|
||||
|
||||
/obj/machinery/door/firedoor/attackby(obj/item/C, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
if(welded)
|
||||
if(istype(C, /obj/item/wrench))
|
||||
if(boltslocked)
|
||||
to_chat(user, "<span class='notice'>There are screws locking the bolts in place!</span>")
|
||||
return
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts undoing [src]'s bolts...</span>", \
|
||||
"<span class='notice'>You start unfastening [src]'s floor bolts...</span>")
|
||||
if(!C.use_tool(src, user, 50))
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] unfastens [src]'s bolts.</span>", \
|
||||
"<span class='notice'>You undo [src]'s floor bolts.</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
if(istype(C, /obj/item/screwdriver))
|
||||
user.visible_message("<span class='notice'>[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.</span>", \
|
||||
"<span class='notice'>You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.</span>")
|
||||
C.play_tool_sound(src)
|
||||
boltslocked = !boltslocked
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_activate_door(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts [welded ? "unwelding" : "welding"] [src].</span>", "<span class='notice'>You start welding [src].</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
welded = !welded
|
||||
to_chat(user, "<span class='danger'>[user] [welded?"welds":"unwelds"] [src].</span>", "<span class='notice'>You [welded ? "weld" : "unweld"] [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/firedoor/try_to_crowbar(obj/item/I, mob/user)
|
||||
if(welded || operating)
|
||||
return
|
||||
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
|
||||
/obj/machinery/door/firedoor/attack_ai(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(welded || operating || stat & NOPOWER)
|
||||
return TRUE
|
||||
if(density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/attack_robot(mob/user)
|
||||
return attack_ai(user)
|
||||
|
||||
/obj/machinery/door/firedoor/attack_alien(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(welded)
|
||||
to_chat(user, "<span class='warning'>[src] refuses to budge!</span>")
|
||||
return
|
||||
open()
|
||||
|
||||
/obj/machinery/door/firedoor/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
flick("door_opening", src)
|
||||
if("closing")
|
||||
flick("door_closing", src)
|
||||
|
||||
/obj/machinery/door/firedoor/update_icon()
|
||||
cut_overlays()
|
||||
if(density)
|
||||
icon_state = "door_closed"
|
||||
if(welded)
|
||||
add_overlay("welded")
|
||||
else
|
||||
icon_state = "door_open"
|
||||
if(welded)
|
||||
add_overlay("welded_open")
|
||||
|
||||
/obj/machinery/door/firedoor/open()
|
||||
. = ..()
|
||||
latetoggle()
|
||||
|
||||
/obj/machinery/door/firedoor/close()
|
||||
. = ..()
|
||||
latetoggle()
|
||||
|
||||
/obj/machinery/door/firedoor/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src))
|
||||
if(disassembled)
|
||||
F.constructionStep = CONSTRUCTION_PANEL_OPEN
|
||||
else
|
||||
F.constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
F.obj_integrity = F.max_integrity * 0.5
|
||||
F.update_icon()
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/machinery/door/firedoor/proc/latetoggle()
|
||||
if(operating || stat & NOPOWER || !nextstate)
|
||||
return
|
||||
switch(nextstate)
|
||||
if(FIREDOOR_OPEN)
|
||||
nextstate = null
|
||||
open()
|
||||
if(FIREDOOR_CLOSED)
|
||||
nextstate = null
|
||||
close()
|
||||
|
||||
/obj/machinery/door/firedoor/border_only
|
||||
icon = 'icons/obj/doors/edge_Doorfire.dmi'
|
||||
flags_1 = ON_BORDER_1
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/closed
|
||||
icon_state = "door_closed"
|
||||
opacity = TRUE
|
||||
density = TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == dir)
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/CanAtmosPass(turf/T)
|
||||
if(get_dir(loc, T) == dir)
|
||||
return !density
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/firedoor/heavy
|
||||
name = "heavy firelock"
|
||||
icon = 'icons/obj/doors/Doorfire.dmi'
|
||||
glass = FALSE
|
||||
explosion_block = 2
|
||||
assemblytype = /obj/structure/firelock_frame/heavy
|
||||
max_integrity = 550
|
||||
|
||||
|
||||
/obj/item/electronics/firelock
|
||||
name = "firelock circuitry"
|
||||
desc = "A circuit board used in construction of firelocks."
|
||||
icon_state = "mainboard"
|
||||
|
||||
/obj/structure/firelock_frame
|
||||
name = "firelock frame"
|
||||
desc = "A partially completed firelock."
|
||||
icon = 'icons/obj/doors/Doorfire.dmi'
|
||||
icon_state = "frame1"
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
var/constructionStep = CONSTRUCTION_NOCIRCUIT
|
||||
var/reinforced = 0
|
||||
|
||||
/obj/structure/firelock_frame/examine(mob/user)
|
||||
. = ..()
|
||||
switch(constructionStep)
|
||||
if(CONSTRUCTION_PANEL_OPEN)
|
||||
. += "<span class='notice'>It is <i>unbolted</i> from the floor. A small <b>loosely connected</b> metal plate is covering the wires.</span>"
|
||||
if(!reinforced)
|
||||
. += "<span class='notice'>It could be reinforced with plasteel.</span>"
|
||||
if(CONSTRUCTION_WIRES_EXPOSED)
|
||||
. += "<span class='notice'>The maintenance plate has been <i>pried away</i>, and <b>wires</b> are trailing.</span>"
|
||||
if(CONSTRUCTION_GUTTED)
|
||||
. += "<span class='notice'>The maintenance panel is missing <i>wires</i> and the circuit board is <b>loosely connected</b>.</span>"
|
||||
if(CONSTRUCTION_NOCIRCUIT)
|
||||
. += "<span class='notice'>There are no <i>firelock electronics</i> in the frame. The frame could be <b>cut</b> apart.</span>"
|
||||
|
||||
/obj/structure/firelock_frame/update_icon()
|
||||
..()
|
||||
icon_state = "frame[constructionStep]"
|
||||
|
||||
/obj/structure/firelock_frame/attackby(obj/item/C, mob/user)
|
||||
switch(constructionStep)
|
||||
if(CONSTRUCTION_PANEL_OPEN)
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts prying something out from [src]...</span>", \
|
||||
"<span class='notice'>You begin prying out the wire cover...</span>")
|
||||
if(!C.use_tool(src, user, 50))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_PANEL_OPEN)
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] pries out a metal plate from [src], exposing the wires.</span>", \
|
||||
"<span class='notice'>You remove the cover plate from [src], exposing the wires.</span>")
|
||||
constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/wrench))
|
||||
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
|
||||
to_chat(user, "<span class='warning'>There's already a firelock there.</span>")
|
||||
return
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts bolting down [src]...</span>", \
|
||||
"<span class='notice'>You begin bolting [src]...</span>")
|
||||
if(!C.use_tool(src, user, 30))
|
||||
return
|
||||
if(locate(/obj/machinery/door/firedoor) in get_turf(src))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] finishes the firelock.</span>", \
|
||||
"<span class='notice'>You finish the firelock.</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(reinforced)
|
||||
new /obj/machinery/door/firedoor/heavy(get_turf(src))
|
||||
else
|
||||
new /obj/machinery/door/firedoor(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(C, /obj/item/stack/sheet/plasteel))
|
||||
var/obj/item/stack/sheet/plasteel/P = C
|
||||
if(reinforced)
|
||||
to_chat(user, "<span class='warning'>[src] is already reinforced.</span>")
|
||||
return
|
||||
if(P.get_amount() < 2)
|
||||
to_chat(user, "<span class='warning'>You need more plasteel to reinforce [src].</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins reinforcing [src]...</span>", \
|
||||
"<span class='notice'>You begin reinforcing [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 60, target = src))
|
||||
if(constructionStep != CONSTRUCTION_PANEL_OPEN || reinforced || P.get_amount() < 2 || !P)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] reinforces [src].</span>", \
|
||||
"<span class='notice'>You reinforce [src].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
P.use(2)
|
||||
reinforced = 1
|
||||
return
|
||||
|
||||
if(CONSTRUCTION_WIRES_EXPOSED)
|
||||
if(istype(C, /obj/item/wirecutters))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts cutting the wires from [src]...</span>", \
|
||||
"<span class='notice'>You begin removing [src]'s wires...</span>")
|
||||
if(!C.use_tool(src, user, 60))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_WIRES_EXPOSED)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] removes the wires from [src].</span>", \
|
||||
"<span class='notice'>You remove the wiring from [src], exposing the circuit board.</span>")
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 5)
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
C.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] starts prying a metal plate into [src]...</span>", \
|
||||
"<span class='notice'>You begin prying the cover plate back onto [src]...</span>")
|
||||
if(!C.use_tool(src, user, 80))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_WIRES_EXPOSED)
|
||||
return
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
user.visible_message("<span class='notice'>[user] pries the metal plate into [src].</span>", \
|
||||
"<span class='notice'>You pry [src]'s cover plate into place, hiding the wires.</span>")
|
||||
constructionStep = CONSTRUCTION_PANEL_OPEN
|
||||
update_icon()
|
||||
return
|
||||
if(CONSTRUCTION_GUTTED)
|
||||
if(istype(C, /obj/item/crowbar))
|
||||
user.visible_message("<span class='notice'>[user] begins removing the circuit board from [src]...</span>", \
|
||||
"<span class='notice'>You begin prying out the circuit board from [src]...</span>")
|
||||
if(!C.use_tool(src, user, 50, volume=50))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_GUTTED)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] removes [src]'s circuit board.</span>", \
|
||||
"<span class='notice'>You remove the circuit board from [src].</span>")
|
||||
new /obj/item/electronics/firelock(drop_location())
|
||||
constructionStep = CONSTRUCTION_NOCIRCUIT
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/B = C
|
||||
if(B.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning'>You need more wires to add wiring to [src].</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins wiring [src]...</span>", \
|
||||
"<span class='notice'>You begin adding wires to [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 60, target = src))
|
||||
if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] adds wires to [src].</span>", \
|
||||
"<span class='notice'>You wire [src].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
B.use(5)
|
||||
constructionStep = CONSTRUCTION_WIRES_EXPOSED
|
||||
update_icon()
|
||||
return
|
||||
if(CONSTRUCTION_NOCIRCUIT)
|
||||
if(istype(C, /obj/item/weldingtool))
|
||||
if(!C.tool_start_check(user, amount=1))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] begins cutting apart [src]'s frame...</span>", \
|
||||
"<span class='notice'>You begin slicing [src] apart...</span>")
|
||||
|
||||
if(C.use_tool(src, user, 40, volume=50, amount=1))
|
||||
if(constructionStep != CONSTRUCTION_NOCIRCUIT)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] cuts apart [src]!</span>", \
|
||||
"<span class='notice'>You cut [src] into metal.</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
new /obj/item/stack/sheet/metal(T, 3)
|
||||
if(reinforced)
|
||||
new /obj/item/stack/sheet/plasteel(T, 2)
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(C, /obj/item/electronics/firelock))
|
||||
user.visible_message("<span class='notice'>[user] starts adding [C] to [src]...</span>", \
|
||||
"<span class='notice'>You begin adding a circuit board to [src]...</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(!do_after(user, 40, target = src))
|
||||
return
|
||||
if(constructionStep != CONSTRUCTION_NOCIRCUIT)
|
||||
return
|
||||
qdel(C)
|
||||
user.visible_message("<span class='notice'>[user] adds a circuit to [src].</span>", \
|
||||
"<span class='notice'>You insert and secure [C].</span>")
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
if(istype(C, /obj/item/electroadaptive_pseudocircuit))
|
||||
var/obj/item/electroadaptive_pseudocircuit/P = C
|
||||
if(!P.adapt_circuit(user, 30))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a firelock circuit and slot it into the assembly.</span>")
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
if((constructionStep == CONSTRUCTION_NOCIRCUIT) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS))
|
||||
return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1)
|
||||
return FALSE
|
||||
|
||||
/obj/structure/firelock_frame/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
||||
switch(passed_mode)
|
||||
if(RCD_UPGRADE_SIMPLE_CIRCUITS)
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a firelock circuit and slot it into the assembly.</span>")
|
||||
constructionStep = CONSTRUCTION_GUTTED
|
||||
update_icon()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/firelock_frame/heavy
|
||||
name = "heavy firelock frame"
|
||||
reinforced = TRUE
|
||||
|
||||
#undef CONSTRUCTION_COMPLETE
|
||||
#undef CONSTRUCTION_PANEL_OPEN
|
||||
#undef CONSTRUCTION_WIRES_EXPOSED
|
||||
#undef CONSTRUCTION_GUTTED
|
||||
#undef CONSTRUCTION_NOCIRCUIT
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
/obj/machinery/door/poddoor
|
||||
name = "blast door"
|
||||
desc = "A heavy duty blast door that opens mechanically."
|
||||
icon = 'icons/obj/doors/blastdoor.dmi'
|
||||
icon_state = "closed"
|
||||
var/id = 1
|
||||
layer = BLASTDOOR_LAYER
|
||||
closingLayer = CLOSED_BLASTDOOR_LAYER
|
||||
sub_door = TRUE
|
||||
explosion_block = 3
|
||||
heat_proof = TRUE
|
||||
safe = FALSE
|
||||
max_integrity = 600
|
||||
armor = list("melee" = 50, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
damage_deflection = 70
|
||||
poddoor = TRUE
|
||||
|
||||
/obj/machinery/door/poddoor/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
|
||||
/obj/machinery/door/poddoor/ert
|
||||
desc = "A heavy duty blast door that only opens for dire emergencies."
|
||||
|
||||
//special poddoors that open when emergency shuttle docks at centcom
|
||||
/obj/machinery/door/poddoor/shuttledock
|
||||
var/checkdir = 4 //door won't open if turf in this dir is `turftype`
|
||||
var/turftype = /turf/open/space
|
||||
|
||||
/obj/machinery/door/poddoor/shuttledock/proc/check()
|
||||
var/turf/T = get_step(src, checkdir)
|
||||
if(!istype(T, turftype))
|
||||
INVOKE_ASYNC(src, .proc/open)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/close)
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_toxmix
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_TOXMIX_VENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_atmos_main
|
||||
name = "turbine vent"
|
||||
id = INCINERATOR_ATMOS_MAINVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_atmos_aux
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_ATMOS_AUXVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_syndicatelava_main
|
||||
name = "turbine vent"
|
||||
id = INCINERATOR_SYNDICATELAVA_MAINVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_syndicatelava_aux
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_SYNDICATELAVA_AUXVENT
|
||||
|
||||
/obj/machinery/door/poddoor/Bumped(atom/movable/AM)
|
||||
if(density)
|
||||
return 0
|
||||
else
|
||||
return ..()
|
||||
|
||||
//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS.
|
||||
/obj/machinery/door/poddoor/ex_act(severity, target)
|
||||
if(severity == 3)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/door/poddoor/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
flick("opening", src)
|
||||
playsound(src, 'sound/machines/blastdoor.ogg', 30, 1)
|
||||
if("closing")
|
||||
flick("closing", src)
|
||||
playsound(src, 'sound/machines/blastdoor.ogg', 30, 1)
|
||||
|
||||
/obj/machinery/door/poddoor/update_icon()
|
||||
if(density)
|
||||
icon_state = "closed"
|
||||
else
|
||||
icon_state = "open"
|
||||
|
||||
/obj/machinery/door/poddoor/try_to_activate_door(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user)
|
||||
if(stat & NOPOWER)
|
||||
open(1)
|
||||
/obj/machinery/door/poddoor
|
||||
name = "blast door"
|
||||
desc = "A heavy duty blast door that opens mechanically."
|
||||
icon = 'icons/obj/doors/blastdoor.dmi'
|
||||
icon_state = "closed"
|
||||
var/id = 1
|
||||
layer = BLASTDOOR_LAYER
|
||||
closingLayer = CLOSED_BLASTDOOR_LAYER
|
||||
sub_door = TRUE
|
||||
explosion_block = 3
|
||||
heat_proof = TRUE
|
||||
safe = FALSE
|
||||
max_integrity = 600
|
||||
armor = list("melee" = 50, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
damage_deflection = 70
|
||||
poddoor = TRUE
|
||||
|
||||
/obj/machinery/door/poddoor/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
|
||||
/obj/machinery/door/poddoor/ert
|
||||
desc = "A heavy duty blast door that only opens for dire emergencies."
|
||||
|
||||
//special poddoors that open when emergency shuttle docks at centcom
|
||||
/obj/machinery/door/poddoor/shuttledock
|
||||
var/checkdir = 4 //door won't open if turf in this dir is `turftype`
|
||||
var/turftype = /turf/open/space
|
||||
|
||||
/obj/machinery/door/poddoor/shuttledock/proc/check()
|
||||
var/turf/T = get_step(src, checkdir)
|
||||
if(!istype(T, turftype))
|
||||
INVOKE_ASYNC(src, .proc/open)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/close)
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_toxmix
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_TOXMIX_VENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_atmos_main
|
||||
name = "turbine vent"
|
||||
id = INCINERATOR_ATMOS_MAINVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_atmos_aux
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_ATMOS_AUXVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_syndicatelava_main
|
||||
name = "turbine vent"
|
||||
id = INCINERATOR_SYNDICATELAVA_MAINVENT
|
||||
|
||||
/obj/machinery/door/poddoor/incinerator_syndicatelava_aux
|
||||
name = "combustion chamber vent"
|
||||
id = INCINERATOR_SYNDICATELAVA_AUXVENT
|
||||
|
||||
/obj/machinery/door/poddoor/Bumped(atom/movable/AM)
|
||||
if(density)
|
||||
return 0
|
||||
else
|
||||
return ..()
|
||||
|
||||
//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS.
|
||||
/obj/machinery/door/poddoor/ex_act(severity, target)
|
||||
if(severity == 3)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/door/poddoor/do_animate(animation)
|
||||
switch(animation)
|
||||
if("opening")
|
||||
flick("opening", src)
|
||||
playsound(src, 'sound/machines/blastdoor.ogg', 30, 1)
|
||||
if("closing")
|
||||
flick("closing", src)
|
||||
playsound(src, 'sound/machines/blastdoor.ogg', 30, 1)
|
||||
|
||||
/obj/machinery/door/poddoor/update_icon()
|
||||
if(density)
|
||||
icon_state = "closed"
|
||||
else
|
||||
icon_state = "open"
|
||||
|
||||
/obj/machinery/door/poddoor/try_to_activate_door(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user)
|
||||
if(stat & NOPOWER)
|
||||
open(1)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/obj/machinery/door/poddoor/shutters
|
||||
gender = PLURAL
|
||||
name = "shutters"
|
||||
desc = "Heavy duty metal shutters that open mechanically."
|
||||
icon = 'icons/obj/doors/shutters.dmi'
|
||||
layer = SHUTTER_LAYER
|
||||
closingLayer = SHUTTER_LAYER
|
||||
damage_deflection = 20
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
/obj/machinery/door/poddoor/shutters
|
||||
gender = PLURAL
|
||||
name = "shutters"
|
||||
desc = "Heavy duty metal shutters that open mechanically."
|
||||
icon = 'icons/obj/doors/shutters.dmi'
|
||||
layer = SHUTTER_LAYER
|
||||
closingLayer = SHUTTER_LAYER
|
||||
damage_deflection = 20
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/obj/machinery/door/unpowered
|
||||
|
||||
/obj/machinery/door/unpowered/Bumped(atom/movable/AM)
|
||||
if(src.locked)
|
||||
return
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params)
|
||||
if(locked)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/unpowered/shuttle
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
name = "door"
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = TRUE
|
||||
/obj/machinery/door/unpowered
|
||||
|
||||
/obj/machinery/door/unpowered/Bumped(atom/movable/AM)
|
||||
if(src.locked)
|
||||
return
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params)
|
||||
if(locked)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/unpowered/shuttle
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
name = "door"
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = TRUE
|
||||
explosion_block = 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,149 +1,188 @@
|
||||
GLOBAL_LIST_EMPTY(doppler_arrays)
|
||||
|
||||
/obj/machinery/doppler_array
|
||||
name = "tachyon-doppler array"
|
||||
desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\n"
|
||||
icon = 'icons/obj/machines/research.dmi'
|
||||
icon_state = "tdoppler"
|
||||
density = TRUE
|
||||
var/integrated = FALSE
|
||||
var/max_dist = 150
|
||||
verb_say = "states coldly"
|
||||
|
||||
/obj/machinery/doppler_array/Initialize()
|
||||
. = ..()
|
||||
GLOB.doppler_arrays += src
|
||||
|
||||
/obj/machinery/doppler_array/ComponentInitialize()
|
||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message))
|
||||
|
||||
/obj/machinery/doppler_array/Destroy()
|
||||
GLOB.doppler_arrays -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doppler_array/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>"
|
||||
|
||||
/obj/machinery/doppler_array/process()
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/wrench))
|
||||
if(!anchored && !isinspace())
|
||||
anchored = TRUE
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You fasten [src].</span>")
|
||||
else if(anchored)
|
||||
anchored = FALSE
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You unfasten [src].</span>")
|
||||
I.play_tool_sound(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doppler_array/proc/rot_message(mob/user)
|
||||
to_chat(user, "<span class='notice'>You adjust [src]'s dish to face to the [dir2text(dir)].</span>")
|
||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
|
||||
|
||||
/obj/machinery/doppler_array/proc/sense_explosion(turf/epicenter,devastation_range,heavy_impact_range,light_impact_range,
|
||||
took,orig_dev_range,orig_heavy_range,orig_light_range)
|
||||
if(stat & NOPOWER)
|
||||
return FALSE
|
||||
var/turf/zone = get_turf(src)
|
||||
|
||||
if(zone.z != epicenter.z)
|
||||
return FALSE
|
||||
|
||||
var/distance = get_dist(epicenter, zone)
|
||||
var/direct = get_dir(zone, epicenter)
|
||||
|
||||
if(distance > max_dist)
|
||||
return FALSE
|
||||
if(!(direct & dir) && !integrated)
|
||||
return FALSE
|
||||
|
||||
|
||||
var/list/messages = list("Explosive disturbance detected.", \
|
||||
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \
|
||||
"Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].")
|
||||
|
||||
// If the bomb was capped, say its theoretical size.
|
||||
if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
|
||||
messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."
|
||||
|
||||
if(integrated)
|
||||
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
|
||||
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
|
||||
return FALSE
|
||||
helm.display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]")
|
||||
else
|
||||
for(var/message in messages)
|
||||
say(message)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/doppler_array/power_change()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
else
|
||||
if(powered() && anchored)
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
stat |= NOPOWER
|
||||
|
||||
//Portable version, built into EOD equipment. It simply provides an explosion's three damage levels.
|
||||
/obj/machinery/doppler_array/integrated
|
||||
name = "integrated tachyon-doppler module"
|
||||
integrated = TRUE
|
||||
max_dist = 21 //Should detect most explosions in hearing range.
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
/obj/machinery/doppler_array/research
|
||||
name = "tachyon-doppler research array"
|
||||
desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research."
|
||||
var/datum/techweb/linked_techweb
|
||||
|
||||
/obj/machinery/doppler_array/research/sense_explosion(turf/epicenter, dev, heavy, light, time, orig_dev, orig_heavy, orig_light) //probably needs a way to ignore admin explosives later on
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(linked_techweb))
|
||||
say("Warning: No linked research system!")
|
||||
return
|
||||
|
||||
var/point_gain = 0
|
||||
|
||||
/*****The Point Calculator*****/
|
||||
|
||||
if(orig_light < 10)
|
||||
say("Explosion not large enough for research calculations.")
|
||||
return
|
||||
else if(orig_light < 4500)
|
||||
point_gain = (83300 * orig_light) / (orig_light + 3000)
|
||||
else
|
||||
point_gain = TECHWEB_BOMB_POINTCAP
|
||||
|
||||
/*****The Point Capper*****/
|
||||
if(point_gain > linked_techweb.largest_bomb_value)
|
||||
if(point_gain <= TECHWEB_BOMB_POINTCAP || linked_techweb.largest_bomb_value < TECHWEB_BOMB_POINTCAP)
|
||||
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
|
||||
linked_techweb.largest_bomb_value = point_gain
|
||||
point_gain -= old_tech_largest_bomb_value
|
||||
point_gain = min(point_gain,TECHWEB_BOMB_POINTCAP)
|
||||
else
|
||||
linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP
|
||||
point_gain = 1000
|
||||
|
||||
linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain)
|
||||
say("Gained [point_gain] points from explosion dataset.")
|
||||
|
||||
else //you've made smaller bombs
|
||||
say("Data already captured. Aborting.")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/doppler_array/research/science/Initialize()
|
||||
. = ..()
|
||||
GLOBAL_LIST_EMPTY(doppler_arrays)
|
||||
|
||||
/obj/machinery/doppler_array
|
||||
name = "tachyon-doppler array"
|
||||
desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\n"
|
||||
icon = 'icons/obj/machines/research.dmi'
|
||||
icon_state = "tdoppler"
|
||||
density = TRUE
|
||||
var/integrated = FALSE
|
||||
var/list_limit = 100
|
||||
var/cooldown = 10
|
||||
var/next_announce = 0
|
||||
var/max_dist = 150
|
||||
verb_say = "states coldly"
|
||||
var/list/message_log = list()
|
||||
|
||||
/obj/machinery/doppler_array/Initialize()
|
||||
. = ..()
|
||||
GLOB.doppler_arrays += src
|
||||
|
||||
/obj/machinery/doppler_array/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message))
|
||||
|
||||
/obj/machinery/doppler_array/Destroy()
|
||||
GLOB.doppler_arrays -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doppler_array/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(stat)
|
||||
return FALSE
|
||||
|
||||
var/list/dat = list()
|
||||
for(var/i in 1 to LAZYLEN(message_log))
|
||||
dat += "Log recording #[i]: [message_log[i]]<br/><br>"
|
||||
dat += "<A href='?src=[REF(src)];delete_log=1'>Delete logs</A><br>"
|
||||
dat += "<hr>"
|
||||
dat += "<A href='?src=[REF(src)];refresh=1'>(Refresh)</A><br>"
|
||||
dat += "</body></html>"
|
||||
var/datum/browser/popup = new(user, "computer", name, 400, 500)
|
||||
popup.set_content(dat.Join(" "))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/doppler_array/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["delete_log"])
|
||||
LAZYCLEARLIST(message_log)
|
||||
if(href_list["refresh"])
|
||||
updateUsrDialog()
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/wrench))
|
||||
if(!anchored && !isinspace())
|
||||
anchored = TRUE
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You fasten [src].</span>")
|
||||
else if(anchored)
|
||||
anchored = FALSE
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You unfasten [src].</span>")
|
||||
I.play_tool_sound(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doppler_array/proc/rot_message(mob/user)
|
||||
to_chat(user, "<span class='notice'>You adjust [src]'s dish to face to the [dir2text(dir)].</span>")
|
||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
|
||||
|
||||
/obj/machinery/doppler_array/proc/sense_explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range,
|
||||
took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||
if(stat & NOPOWER)
|
||||
return FALSE
|
||||
var/turf/zone = get_turf(src)
|
||||
if(zone.z != epicenter.z)
|
||||
return FALSE
|
||||
|
||||
if(next_announce > world.time)
|
||||
return FALSE
|
||||
next_announce = world.time + cooldown
|
||||
|
||||
var/distance = get_dist(epicenter, zone)
|
||||
var/direct = get_dir(zone, epicenter)
|
||||
|
||||
if(distance > max_dist)
|
||||
return FALSE
|
||||
if(!(direct & dir) && !integrated)
|
||||
return FALSE
|
||||
|
||||
|
||||
var/list/messages = list("Explosive disturbance detected.", \
|
||||
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \
|
||||
"Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].")
|
||||
|
||||
// If the bomb was capped, say its theoretical size.
|
||||
if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
|
||||
messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."
|
||||
|
||||
if(integrated)
|
||||
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
|
||||
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
|
||||
return FALSE
|
||||
helm.display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]")
|
||||
else
|
||||
for(var/message in messages)
|
||||
say(message)
|
||||
if(LAZYLEN(message_log) > list_limit)
|
||||
say("Storage buffer is full! Clearing buffers...")
|
||||
LAZYCLEARLIST(message_log)
|
||||
LAZYADD(message_log, messages.Join(" "))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/doppler_array/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>"
|
||||
|
||||
/obj/machinery/doppler_array/process()
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/doppler_array/power_change()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
else
|
||||
if(powered() && anchored)
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-off"
|
||||
stat |= NOPOWER
|
||||
|
||||
//Portable version, built into EOD equipment. It simply provides an explosion's three damage levels.
|
||||
/obj/machinery/doppler_array/integrated
|
||||
name = "integrated tachyon-doppler module"
|
||||
integrated = TRUE
|
||||
max_dist = 21 //Should detect most explosions in hearing range.
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
/obj/machinery/doppler_array/research
|
||||
name = "tachyon-doppler research array"
|
||||
desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research."
|
||||
var/datum/techweb/linked_techweb
|
||||
|
||||
/obj/machinery/doppler_array/research/sense_explosion(turf/epicenter, dev, heavy, light, time, orig_dev, orig_heavy, orig_light) //probably needs a way to ignore admin explosives later on
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(linked_techweb))
|
||||
say("Warning: No linked research system!")
|
||||
return
|
||||
|
||||
var/point_gain = 0
|
||||
|
||||
/*****The Point Calculator*****/
|
||||
|
||||
if(orig_light < 10)
|
||||
say("Explosion not large enough for research calculations.")
|
||||
return
|
||||
else if(orig_light < 4500)
|
||||
point_gain = (83300 * orig_light) / (orig_light + 3000)
|
||||
else
|
||||
point_gain = TECHWEB_BOMB_POINTCAP
|
||||
|
||||
/*****The Point Capper*****/
|
||||
if(point_gain > linked_techweb.largest_bomb_value)
|
||||
if(point_gain <= TECHWEB_BOMB_POINTCAP || linked_techweb.largest_bomb_value < TECHWEB_BOMB_POINTCAP)
|
||||
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
|
||||
linked_techweb.largest_bomb_value = point_gain
|
||||
point_gain -= old_tech_largest_bomb_value
|
||||
point_gain = min(point_gain,TECHWEB_BOMB_POINTCAP)
|
||||
else
|
||||
linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP
|
||||
point_gain = 1000
|
||||
|
||||
linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain)
|
||||
say("Gained [point_gain] points from explosion dataset.")
|
||||
|
||||
else //you've made smaller bombs
|
||||
say("Data already captured. Aborting.")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/doppler_array/research/science/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
@@ -1,315 +1,315 @@
|
||||
#define CLOSING 1
|
||||
#define OPENING 2
|
||||
#define CYCLE 3
|
||||
#define CYCLE_EXTERIOR 4
|
||||
#define CYCLE_INTERIOR 5
|
||||
|
||||
/obj/machinery/doorButtons
|
||||
power_channel = ENVIRON
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 4
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/idSelf
|
||||
|
||||
/obj/machinery/doorButtons/attackby(obj/O, mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/doorButtons/proc/findObjsByTag()
|
||||
return
|
||||
|
||||
/obj/machinery/doorButtons/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/doorButtons/LateInitialize()
|
||||
findObjsByTag()
|
||||
|
||||
/obj/machinery/doorButtons/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
playsound(src, "sparks", 100, 1)
|
||||
to_chat(user, "<span class='warning'>You short out the access controller.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/doorButtons/proc/removeMe()
|
||||
|
||||
|
||||
/obj/machinery/doorButtons/access_button
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "access_button_standby"
|
||||
name = "access button"
|
||||
desc = "A button used for the explicit purpose of opening an airlock."
|
||||
var/idDoor
|
||||
var/obj/machinery/door/airlock/door
|
||||
var/obj/machinery/doorButtons/airlock_controller/controller
|
||||
var/busy
|
||||
|
||||
/obj/machinery/doorButtons/access_button/findObjsByTag()
|
||||
for(var/obj/machinery/doorButtons/airlock_controller/A in GLOB.machines)
|
||||
if(A.idSelf == idSelf)
|
||||
controller = A
|
||||
break
|
||||
for(var/obj/machinery/door/airlock/I in GLOB.machines)
|
||||
if(I.id_tag == idDoor)
|
||||
door = I
|
||||
break
|
||||
|
||||
/obj/machinery/doorButtons/access_button/interact(mob/user)
|
||||
if(busy)
|
||||
return
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
if(controller && !controller.busy && door)
|
||||
if(controller.stat & NOPOWER)
|
||||
return
|
||||
busy = TRUE
|
||||
update_icon()
|
||||
if(door.density)
|
||||
if(!controller.exteriorAirlock || !controller.interiorAirlock)
|
||||
controller.onlyOpen(door)
|
||||
else
|
||||
if(controller.exteriorAirlock.density && controller.interiorAirlock.density)
|
||||
controller.onlyOpen(door)
|
||||
else
|
||||
controller.cycleClose(door)
|
||||
else
|
||||
controller.onlyClose(door)
|
||||
sleep(20)
|
||||
busy = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/access_button/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "access_button_off"
|
||||
else
|
||||
if(busy)
|
||||
icon_state = "access_button_cycle"
|
||||
else
|
||||
icon_state = "access_button_standby"
|
||||
|
||||
/obj/machinery/doorButtons/access_button/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/access_button/removeMe(obj/O)
|
||||
if(O == door)
|
||||
door = null
|
||||
|
||||
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "access_control_standby"
|
||||
name = "access console"
|
||||
desc = "A small console that can cycle opening between two airlocks."
|
||||
var/obj/machinery/door/airlock/interiorAirlock
|
||||
var/obj/machinery/door/airlock/exteriorAirlock
|
||||
var/idInterior
|
||||
var/idExterior
|
||||
var/busy
|
||||
var/lostPower
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/removeMe(obj/O)
|
||||
if(O == interiorAirlock)
|
||||
interiorAirlock = null
|
||||
else if(O == exteriorAirlock)
|
||||
exteriorAirlock = null
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/Destroy()
|
||||
for(var/obj/machinery/doorButtons/access_button/A in GLOB.machines)
|
||||
if(A.controller == src)
|
||||
A.controller = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(busy)
|
||||
return
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
switch(href_list["command"])
|
||||
if("close_exterior")
|
||||
onlyClose(exteriorAirlock)
|
||||
if("close_interior")
|
||||
onlyClose(interiorAirlock)
|
||||
if("cycle_exterior")
|
||||
cycleClose(exteriorAirlock)
|
||||
if("cycle_interior")
|
||||
cycleClose(interiorAirlock)
|
||||
if("open_exterior")
|
||||
onlyOpen(exteriorAirlock)
|
||||
if("open_interior")
|
||||
onlyOpen(interiorAirlock)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A)
|
||||
if(A)
|
||||
busy = CLOSING
|
||||
update_icon()
|
||||
openDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A)
|
||||
if(A)
|
||||
busy = CLOSING
|
||||
closeDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A)
|
||||
set waitfor = FALSE
|
||||
if(A.density)
|
||||
goIdle()
|
||||
return 0
|
||||
update_icon()
|
||||
A.unbolt()
|
||||
. = 1
|
||||
if(A && A.close())
|
||||
if(stat & NOPOWER || lostPower || !A || QDELETED(A))
|
||||
goIdle(1)
|
||||
return
|
||||
A.bolt()
|
||||
if(busy == CLOSING)
|
||||
goIdle(1)
|
||||
else
|
||||
goIdle(1)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A)
|
||||
if(!A || !exteriorAirlock || !interiorAirlock)
|
||||
return
|
||||
if(exteriorAirlock.density == interiorAirlock.density || !A.density)
|
||||
return
|
||||
busy = CYCLE
|
||||
update_icon()
|
||||
if(A == interiorAirlock)
|
||||
if(closeDoor(exteriorAirlock))
|
||||
busy = CYCLE_INTERIOR
|
||||
else
|
||||
if(closeDoor(interiorAirlock))
|
||||
busy = CYCLE_EXTERIOR
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A)
|
||||
if(!A)
|
||||
goIdle(1)
|
||||
if(A == exteriorAirlock)
|
||||
if(interiorAirlock)
|
||||
if(!interiorAirlock.density || !interiorAirlock.locked)
|
||||
return
|
||||
else
|
||||
if(exteriorAirlock)
|
||||
if(!exteriorAirlock.density || !exteriorAirlock.locked)
|
||||
return
|
||||
if(busy != OPENING)
|
||||
busy = OPENING
|
||||
openDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A)
|
||||
if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density))
|
||||
goIdle(1)
|
||||
return
|
||||
A.unbolt()
|
||||
spawn()
|
||||
if(A && A.open())
|
||||
if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A))
|
||||
A.bolt()
|
||||
goIdle(1)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/goIdle(update)
|
||||
lostPower = 0
|
||||
busy = FALSE
|
||||
if(update)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/process()
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
if(busy == CYCLE_EXTERIOR)
|
||||
cycleOpen(exteriorAirlock)
|
||||
else if(busy == CYCLE_INTERIOR)
|
||||
cycleOpen(interiorAirlock)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/power_change()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
lostPower = 1
|
||||
else
|
||||
if(!busy)
|
||||
lostPower = 0
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/findObjsByTag()
|
||||
for(var/obj/machinery/door/airlock/A in GLOB.machines)
|
||||
if(A.id_tag == idInterior)
|
||||
interiorAirlock = A
|
||||
else if(A.id_tag == idExterior)
|
||||
exteriorAirlock = A
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "access_control_off"
|
||||
return
|
||||
if(busy || lostPower)
|
||||
icon_state = "access_control_process"
|
||||
else
|
||||
icon_state = "access_control_standby"
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/ui_interact(mob/user)
|
||||
var/datum/browser/popup = new(user, "computer", name)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.set_content(returnText())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/returnText()
|
||||
var/output
|
||||
if(!exteriorAirlock && !interiorAirlock)
|
||||
return "ERROR ERROR ERROR ERROR"
|
||||
if(lostPower)
|
||||
output = "Initializing..."
|
||||
else
|
||||
if(!exteriorAirlock || !interiorAirlock)
|
||||
if(!exteriorAirlock)
|
||||
if(interiorAirlock.density)
|
||||
output = "<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"
|
||||
else
|
||||
output = "<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"
|
||||
else
|
||||
if(exteriorAirlock.density)
|
||||
output = "<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>"
|
||||
else
|
||||
output = "<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>"
|
||||
else
|
||||
if(exteriorAirlock.density)
|
||||
if(interiorAirlock.density)
|
||||
output = {"<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"}
|
||||
else
|
||||
output = {"<A href='?src=[REF(src)];command=cycle_exterior'>Cycle to Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
|
||||
else
|
||||
if(interiorAirlock.density)
|
||||
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_interior'>Cycle to Interior Airlock</A><BR>"}
|
||||
else
|
||||
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
|
||||
|
||||
|
||||
output = {"<B>Access Control Console</B><HR>
|
||||
[output]<HR>"}
|
||||
if(exteriorAirlock)
|
||||
output += "<B>Exterior Door: </B> [exteriorAirlock.density ? "closed" : "open"]<BR>"
|
||||
if(interiorAirlock)
|
||||
output += "<B>Interior Door: </B> [interiorAirlock.density ? "closed" : "open"]<BR>"
|
||||
|
||||
return output
|
||||
|
||||
#undef CLOSING
|
||||
#undef OPENING
|
||||
#undef CYCLE
|
||||
#undef CYCLE_EXTERIOR
|
||||
#undef CYCLE_INTERIOR
|
||||
#define CLOSING 1
|
||||
#define OPENING 2
|
||||
#define CYCLE 3
|
||||
#define CYCLE_EXTERIOR 4
|
||||
#define CYCLE_INTERIOR 5
|
||||
|
||||
/obj/machinery/doorButtons
|
||||
power_channel = ENVIRON
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 4
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/idSelf
|
||||
|
||||
/obj/machinery/doorButtons/attackby(obj/O, mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/doorButtons/proc/findObjsByTag()
|
||||
return
|
||||
|
||||
/obj/machinery/doorButtons/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/doorButtons/LateInitialize()
|
||||
findObjsByTag()
|
||||
|
||||
/obj/machinery/doorButtons/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
playsound(src, "sparks", 100, 1)
|
||||
to_chat(user, "<span class='warning'>You short out the access controller.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/doorButtons/proc/removeMe()
|
||||
|
||||
|
||||
/obj/machinery/doorButtons/access_button
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "access_button_standby"
|
||||
name = "access button"
|
||||
desc = "A button used for the explicit purpose of opening an airlock."
|
||||
var/idDoor
|
||||
var/obj/machinery/door/airlock/door
|
||||
var/obj/machinery/doorButtons/airlock_controller/controller
|
||||
var/busy
|
||||
|
||||
/obj/machinery/doorButtons/access_button/findObjsByTag()
|
||||
for(var/obj/machinery/doorButtons/airlock_controller/A in GLOB.machines)
|
||||
if(A.idSelf == idSelf)
|
||||
controller = A
|
||||
break
|
||||
for(var/obj/machinery/door/airlock/I in GLOB.machines)
|
||||
if(I.id_tag == idDoor)
|
||||
door = I
|
||||
break
|
||||
|
||||
/obj/machinery/doorButtons/access_button/interact(mob/user)
|
||||
if(busy)
|
||||
return
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
if(controller && !controller.busy && door)
|
||||
if(controller.stat & NOPOWER)
|
||||
return
|
||||
busy = TRUE
|
||||
update_icon()
|
||||
if(door.density)
|
||||
if(!controller.exteriorAirlock || !controller.interiorAirlock)
|
||||
controller.onlyOpen(door)
|
||||
else
|
||||
if(controller.exteriorAirlock.density && controller.interiorAirlock.density)
|
||||
controller.onlyOpen(door)
|
||||
else
|
||||
controller.cycleClose(door)
|
||||
else
|
||||
controller.onlyClose(door)
|
||||
sleep(20)
|
||||
busy = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/access_button/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "access_button_off"
|
||||
else
|
||||
if(busy)
|
||||
icon_state = "access_button_cycle"
|
||||
else
|
||||
icon_state = "access_button_standby"
|
||||
|
||||
/obj/machinery/doorButtons/access_button/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/access_button/removeMe(obj/O)
|
||||
if(O == door)
|
||||
door = null
|
||||
|
||||
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "access_control_standby"
|
||||
name = "access console"
|
||||
desc = "A small console that can cycle opening between two airlocks."
|
||||
var/obj/machinery/door/airlock/interiorAirlock
|
||||
var/obj/machinery/door/airlock/exteriorAirlock
|
||||
var/idInterior
|
||||
var/idExterior
|
||||
var/busy
|
||||
var/lostPower
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/removeMe(obj/O)
|
||||
if(O == interiorAirlock)
|
||||
interiorAirlock = null
|
||||
else if(O == exteriorAirlock)
|
||||
exteriorAirlock = null
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/Destroy()
|
||||
for(var/obj/machinery/doorButtons/access_button/A in GLOB.machines)
|
||||
if(A.controller == src)
|
||||
A.controller = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(busy)
|
||||
return
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
switch(href_list["command"])
|
||||
if("close_exterior")
|
||||
onlyClose(exteriorAirlock)
|
||||
if("close_interior")
|
||||
onlyClose(interiorAirlock)
|
||||
if("cycle_exterior")
|
||||
cycleClose(exteriorAirlock)
|
||||
if("cycle_interior")
|
||||
cycleClose(interiorAirlock)
|
||||
if("open_exterior")
|
||||
onlyOpen(exteriorAirlock)
|
||||
if("open_interior")
|
||||
onlyOpen(interiorAirlock)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A)
|
||||
if(A)
|
||||
busy = CLOSING
|
||||
update_icon()
|
||||
openDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A)
|
||||
if(A)
|
||||
busy = CLOSING
|
||||
closeDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A)
|
||||
set waitfor = FALSE
|
||||
if(A.density)
|
||||
goIdle()
|
||||
return 0
|
||||
update_icon()
|
||||
A.unbolt()
|
||||
. = 1
|
||||
if(A && A.close())
|
||||
if(stat & NOPOWER || lostPower || !A || QDELETED(A))
|
||||
goIdle(1)
|
||||
return
|
||||
A.bolt()
|
||||
if(busy == CLOSING)
|
||||
goIdle(1)
|
||||
else
|
||||
goIdle(1)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A)
|
||||
if(!A || !exteriorAirlock || !interiorAirlock)
|
||||
return
|
||||
if(exteriorAirlock.density == interiorAirlock.density || !A.density)
|
||||
return
|
||||
busy = CYCLE
|
||||
update_icon()
|
||||
if(A == interiorAirlock)
|
||||
if(closeDoor(exteriorAirlock))
|
||||
busy = CYCLE_INTERIOR
|
||||
else
|
||||
if(closeDoor(interiorAirlock))
|
||||
busy = CYCLE_EXTERIOR
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A)
|
||||
if(!A)
|
||||
goIdle(1)
|
||||
if(A == exteriorAirlock)
|
||||
if(interiorAirlock)
|
||||
if(!interiorAirlock.density || !interiorAirlock.locked)
|
||||
return
|
||||
else
|
||||
if(exteriorAirlock)
|
||||
if(!exteriorAirlock.density || !exteriorAirlock.locked)
|
||||
return
|
||||
if(busy != OPENING)
|
||||
busy = OPENING
|
||||
openDoor(A)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A)
|
||||
if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density))
|
||||
goIdle(1)
|
||||
return
|
||||
A.unbolt()
|
||||
spawn()
|
||||
if(A && A.open())
|
||||
if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A))
|
||||
A.bolt()
|
||||
goIdle(1)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/goIdle(update)
|
||||
lostPower = 0
|
||||
busy = FALSE
|
||||
if(update)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/process()
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
if(busy == CYCLE_EXTERIOR)
|
||||
cycleOpen(exteriorAirlock)
|
||||
else if(busy == CYCLE_INTERIOR)
|
||||
cycleOpen(interiorAirlock)
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/power_change()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
lostPower = 1
|
||||
else
|
||||
if(!busy)
|
||||
lostPower = 0
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/findObjsByTag()
|
||||
for(var/obj/machinery/door/airlock/A in GLOB.machines)
|
||||
if(A.id_tag == idInterior)
|
||||
interiorAirlock = A
|
||||
else if(A.id_tag == idExterior)
|
||||
exteriorAirlock = A
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "access_control_off"
|
||||
return
|
||||
if(busy || lostPower)
|
||||
icon_state = "access_control_process"
|
||||
else
|
||||
icon_state = "access_control_standby"
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/ui_interact(mob/user)
|
||||
var/datum/browser/popup = new(user, "computer", name)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.set_content(returnText())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/doorButtons/airlock_controller/proc/returnText()
|
||||
var/output
|
||||
if(!exteriorAirlock && !interiorAirlock)
|
||||
return "ERROR ERROR ERROR ERROR"
|
||||
if(lostPower)
|
||||
output = "Initializing..."
|
||||
else
|
||||
if(!exteriorAirlock || !interiorAirlock)
|
||||
if(!exteriorAirlock)
|
||||
if(interiorAirlock.density)
|
||||
output = "<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"
|
||||
else
|
||||
output = "<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"
|
||||
else
|
||||
if(exteriorAirlock.density)
|
||||
output = "<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>"
|
||||
else
|
||||
output = "<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>"
|
||||
else
|
||||
if(exteriorAirlock.density)
|
||||
if(interiorAirlock.density)
|
||||
output = {"<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"}
|
||||
else
|
||||
output = {"<A href='?src=[REF(src)];command=cycle_exterior'>Cycle to Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
|
||||
else
|
||||
if(interiorAirlock.density)
|
||||
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_interior'>Cycle to Interior Airlock</A><BR>"}
|
||||
else
|
||||
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
|
||||
|
||||
|
||||
output = {"<B>Access Control Console</B><HR>
|
||||
[output]<HR>"}
|
||||
if(exteriorAirlock)
|
||||
output += "<B>Exterior Door: </B> [exteriorAirlock.density ? "closed" : "open"]<BR>"
|
||||
if(interiorAirlock)
|
||||
output += "<B>Interior Door: </B> [interiorAirlock.density ? "closed" : "open"]<BR>"
|
||||
|
||||
return output
|
||||
|
||||
#undef CLOSING
|
||||
#undef OPENING
|
||||
#undef CYCLE
|
||||
#undef CYCLE_EXTERIOR
|
||||
#undef CYCLE_INTERIOR
|
||||
|
||||
@@ -1,315 +1,315 @@
|
||||
//States for airlock_control
|
||||
#define AIRLOCK_STATE_INOPEN -2
|
||||
#define AIRLOCK_STATE_PRESSURIZE -1
|
||||
#define AIRLOCK_STATE_CLOSED 0
|
||||
#define AIRLOCK_STATE_DEPRESSURIZE 1
|
||||
#define AIRLOCK_STATE_OUTOPEN 2
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller
|
||||
var/id_tag
|
||||
var/exterior_door_tag //Burn chamber facing door
|
||||
var/interior_door_tag //Station facing door
|
||||
var/airpump_tag //See: dp_vent_pump.dm
|
||||
var/sensor_tag //See: /obj/machinery/airlock_sensor
|
||||
var/sanitize_external //Before the interior airlock opens, do we first drain all gases inside the chamber and then repressurize?
|
||||
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
var/target_state = AIRLOCK_STATE_CLOSED
|
||||
var/sensor_pressure = null
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal)
|
||||
var/receive_tag = signal.data["tag"]
|
||||
if(!receive_tag)
|
||||
return
|
||||
|
||||
if(receive_tag==sensor_tag)
|
||||
if(signal.data["pressure"])
|
||||
sensor_pressure = text2num(signal.data["pressure"])
|
||||
|
||||
else if(receive_tag==exterior_door_tag)
|
||||
memory["exterior_status"] = signal.data["door_status"]
|
||||
|
||||
else if(receive_tag==interior_door_tag)
|
||||
memory["interior_status"] = signal.data["door_status"]
|
||||
|
||||
else if(receive_tag==airpump_tag)
|
||||
if(signal.data["power"])
|
||||
memory["pump_status"] = signal.data["direction"]
|
||||
else
|
||||
memory["pump_status"] = "off"
|
||||
|
||||
else if(receive_tag==id_tag)
|
||||
switch(signal.data["command"])
|
||||
if("cycle")
|
||||
if(state < AIRLOCK_STATE_CLOSED)
|
||||
target_state = AIRLOCK_STATE_OUTOPEN
|
||||
else
|
||||
target_state = AIRLOCK_STATE_INOPEN
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/receive_user_command(command)
|
||||
switch(command)
|
||||
if("cycle_closed")
|
||||
target_state = AIRLOCK_STATE_CLOSED
|
||||
if("cycle_exterior")
|
||||
target_state = AIRLOCK_STATE_OUTOPEN
|
||||
if("cycle_interior")
|
||||
target_state = AIRLOCK_STATE_INOPEN
|
||||
if("abort")
|
||||
target_state = AIRLOCK_STATE_CLOSED
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/process()
|
||||
var/process_again = 1
|
||||
while(process_again)
|
||||
process_again = 0
|
||||
switch(state)
|
||||
if(AIRLOCK_STATE_INOPEN) // state -2
|
||||
if(target_state > state)
|
||||
if(memory["interior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
if(AIRLOCK_STATE_PRESSURIZE)
|
||||
if(target_state < state)
|
||||
if(sensor_pressure >= ONE_ATMOSPHERE*0.95)
|
||||
if(memory["interior_status"] == "open")
|
||||
state = AIRLOCK_STATE_INOPEN
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_open"
|
||||
)))
|
||||
else
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command"
|
||||
))
|
||||
if(memory["pump_status"] == "siphon")
|
||||
signal.data["stabilize"] = 1
|
||||
else if(memory["pump_status"] != "release")
|
||||
signal.data["power"] = 1
|
||||
post_signal(signal)
|
||||
else if(target_state > state)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
|
||||
if(AIRLOCK_STATE_CLOSED)
|
||||
if(target_state > state)
|
||||
if(memory["interior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_DEPRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else if(target_state < state)
|
||||
if(memory["exterior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_PRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
if(AIRLOCK_STATE_DEPRESSURIZE)
|
||||
var/target_pressure = ONE_ATMOSPHERE*0.05
|
||||
if(sanitize_external)
|
||||
target_pressure = ONE_ATMOSPHERE*0.01
|
||||
|
||||
if(sensor_pressure <= target_pressure)
|
||||
if(target_state > state)
|
||||
if(memory["exterior_status"] == "open")
|
||||
state = AIRLOCK_STATE_OUTOPEN
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_open"
|
||||
)))
|
||||
else if(target_state < state)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else if((target_state < state) && !sanitize_external)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command"
|
||||
))
|
||||
if(memory["pump_status"] == "release")
|
||||
signal.data["purge"] = 1
|
||||
else if(memory["pump_status"] != "siphon")
|
||||
signal.data["power"] = 1
|
||||
post_signal(signal)
|
||||
|
||||
if(AIRLOCK_STATE_OUTOPEN) //state 2
|
||||
if(target_state < state)
|
||||
if(memory["exterior_status"] == "closed")
|
||||
if(sanitize_external)
|
||||
state = AIRLOCK_STATE_DEPRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
memory["sensor_pressure"] = sensor_pressure
|
||||
memory["processing"] = state != target_state
|
||||
//sensor_pressure = null //not sure if we can comment this out. Uncomment in case of problems -rastaf0
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
name = "airlock console"
|
||||
density = FALSE
|
||||
|
||||
frequency = FREQ_AIRLOCK_CONTROL
|
||||
power_channel = ENVIRON
|
||||
|
||||
// Setup parameters only
|
||||
var/id_tag
|
||||
var/exterior_door_tag
|
||||
var/interior_door_tag
|
||||
var/airpump_tag
|
||||
var/sensor_tag
|
||||
var/sanitize_external
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_toxmix
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_TOXMIX_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_ATMOS_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_syndicatelava
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
return
|
||||
|
||||
var/datum/computer/file/embedded_program/airlock_controller/new_prog = new
|
||||
|
||||
new_prog.id_tag = id_tag
|
||||
new_prog.exterior_door_tag = exterior_door_tag
|
||||
new_prog.interior_door_tag = interior_door_tag
|
||||
new_prog.airpump_tag = airpump_tag
|
||||
new_prog.sensor_tag = sensor_tag
|
||||
new_prog.sanitize_external = sanitize_external
|
||||
|
||||
new_prog.master = src
|
||||
program = new_prog
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/update_icon()
|
||||
if(on && program)
|
||||
if(program.memory["processing"])
|
||||
icon_state = "airlock_control_process"
|
||||
else
|
||||
icon_state = "airlock_control_standby"
|
||||
else
|
||||
icon_state = "airlock_control_off"
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/return_text()
|
||||
var/state_options = null
|
||||
|
||||
var/state = 0
|
||||
var/sensor_pressure = "----"
|
||||
var/exterior_status = "----"
|
||||
var/interior_status = "----"
|
||||
var/pump_status = "----"
|
||||
var/current_status = "Inactive<BR> "
|
||||
if(program)
|
||||
state = program.state
|
||||
sensor_pressure = program.memory["sensor_pressure"] ? program.memory["sensor_pressure"] : "----"
|
||||
exterior_status = program.memory["exterior_status"] ? program.memory["exterior_status"] : "----"
|
||||
interior_status = program.memory["interior_status"] ? program.memory["interior_status"] : "----"
|
||||
pump_status = program.memory["pump_status"] ? program.memory["pump_status"] : "----"
|
||||
|
||||
switch(state)
|
||||
if(AIRLOCK_STATE_INOPEN)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_closed'>Close Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_exterior'>Cycle to Exterior Airlock</A><BR>"}
|
||||
current_status = "Interior Airlock Open<BR><span class='good'>Chamber Pressurized</span>"
|
||||
if(AIRLOCK_STATE_PRESSURIZE)
|
||||
state_options = "<A href='?src=[REF(src)];command=abort'>Abort Cycling</A><BR>"
|
||||
current_status = "Cycling to Interior Airlock<BR><span class='average'>Chamber Pressurizing</span>"
|
||||
if(AIRLOCK_STATE_CLOSED)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_interior'>Open Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_exterior'>Open Exterior Airlock</A><BR>"}
|
||||
if(AIRLOCK_STATE_DEPRESSURIZE)
|
||||
state_options = "<A href='?src=[REF(src)];command=abort'>Abort Cycling</A><BR>"
|
||||
current_status = "Cycling to Exterior Airlock<BR><span class='average'>Chamber Depressurizing</span>"
|
||||
if(AIRLOCK_STATE_OUTOPEN)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_interior'>Cycle to Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_closed'>Close Exterior Airlock</A><BR>"}
|
||||
current_status = "Exterior Airlock Open<BR><span class='bad'>Chamber Depressurized</span>"
|
||||
|
||||
var/output = {"<h3>Airlock Status</h3>
|
||||
<div class='statusDisplay'>
|
||||
<div class='line'><div class='statusLabel'>Current Status:</div><div class='statusValue'>[current_status]</div></div>
|
||||
<div class='line'> </div>
|
||||
<div class='line'><div class='statusLabel'>\> Chamber Pressure:</div><div class='statusValue'>[sensor_pressure] kPa</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Control Pump:</div><div class='statusValue'>[pump_status]</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Interior Door:</div><div class='statusValue'>[interior_status]</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Exterior Door:</div><div class='statusValue'>[exterior_status]</div></div>
|
||||
<div class='clearBoth'></div>
|
||||
</div>
|
||||
[state_options]"}
|
||||
|
||||
//States for airlock_control
|
||||
#define AIRLOCK_STATE_INOPEN -2
|
||||
#define AIRLOCK_STATE_PRESSURIZE -1
|
||||
#define AIRLOCK_STATE_CLOSED 0
|
||||
#define AIRLOCK_STATE_DEPRESSURIZE 1
|
||||
#define AIRLOCK_STATE_OUTOPEN 2
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller
|
||||
var/id_tag
|
||||
var/exterior_door_tag //Burn chamber facing door
|
||||
var/interior_door_tag //Station facing door
|
||||
var/airpump_tag //See: dp_vent_pump.dm
|
||||
var/sensor_tag //See: /obj/machinery/airlock_sensor
|
||||
var/sanitize_external //Before the interior airlock opens, do we first drain all gases inside the chamber and then repressurize?
|
||||
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
var/target_state = AIRLOCK_STATE_CLOSED
|
||||
var/sensor_pressure = null
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal)
|
||||
var/receive_tag = signal.data["tag"]
|
||||
if(!receive_tag)
|
||||
return
|
||||
|
||||
if(receive_tag==sensor_tag)
|
||||
if(signal.data["pressure"])
|
||||
sensor_pressure = text2num(signal.data["pressure"])
|
||||
|
||||
else if(receive_tag==exterior_door_tag)
|
||||
memory["exterior_status"] = signal.data["door_status"]
|
||||
|
||||
else if(receive_tag==interior_door_tag)
|
||||
memory["interior_status"] = signal.data["door_status"]
|
||||
|
||||
else if(receive_tag==airpump_tag)
|
||||
if(signal.data["power"])
|
||||
memory["pump_status"] = signal.data["direction"]
|
||||
else
|
||||
memory["pump_status"] = "off"
|
||||
|
||||
else if(receive_tag==id_tag)
|
||||
switch(signal.data["command"])
|
||||
if("cycle")
|
||||
if(state < AIRLOCK_STATE_CLOSED)
|
||||
target_state = AIRLOCK_STATE_OUTOPEN
|
||||
else
|
||||
target_state = AIRLOCK_STATE_INOPEN
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/receive_user_command(command)
|
||||
switch(command)
|
||||
if("cycle_closed")
|
||||
target_state = AIRLOCK_STATE_CLOSED
|
||||
if("cycle_exterior")
|
||||
target_state = AIRLOCK_STATE_OUTOPEN
|
||||
if("cycle_interior")
|
||||
target_state = AIRLOCK_STATE_INOPEN
|
||||
if("abort")
|
||||
target_state = AIRLOCK_STATE_CLOSED
|
||||
|
||||
/datum/computer/file/embedded_program/airlock_controller/process()
|
||||
var/process_again = 1
|
||||
while(process_again)
|
||||
process_again = 0
|
||||
switch(state)
|
||||
if(AIRLOCK_STATE_INOPEN) // state -2
|
||||
if(target_state > state)
|
||||
if(memory["interior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
if(AIRLOCK_STATE_PRESSURIZE)
|
||||
if(target_state < state)
|
||||
if(sensor_pressure >= ONE_ATMOSPHERE*0.95)
|
||||
if(memory["interior_status"] == "open")
|
||||
state = AIRLOCK_STATE_INOPEN
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_open"
|
||||
)))
|
||||
else
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command"
|
||||
))
|
||||
if(memory["pump_status"] == "siphon")
|
||||
signal.data["stabilize"] = 1
|
||||
else if(memory["pump_status"] != "release")
|
||||
signal.data["power"] = 1
|
||||
post_signal(signal)
|
||||
else if(target_state > state)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
|
||||
if(AIRLOCK_STATE_CLOSED)
|
||||
if(target_state > state)
|
||||
if(memory["interior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_DEPRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = interior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else if(target_state < state)
|
||||
if(memory["exterior_status"] == "closed")
|
||||
state = AIRLOCK_STATE_PRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
if(AIRLOCK_STATE_DEPRESSURIZE)
|
||||
var/target_pressure = ONE_ATMOSPHERE*0.05
|
||||
if(sanitize_external)
|
||||
target_pressure = ONE_ATMOSPHERE*0.01
|
||||
|
||||
if(sensor_pressure <= target_pressure)
|
||||
if(target_state > state)
|
||||
if(memory["exterior_status"] == "open")
|
||||
state = AIRLOCK_STATE_OUTOPEN
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_open"
|
||||
)))
|
||||
else if(target_state < state)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else if((target_state < state) && !sanitize_external)
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command"
|
||||
))
|
||||
if(memory["pump_status"] == "release")
|
||||
signal.data["purge"] = 1
|
||||
else if(memory["pump_status"] != "siphon")
|
||||
signal.data["power"] = 1
|
||||
post_signal(signal)
|
||||
|
||||
if(AIRLOCK_STATE_OUTOPEN) //state 2
|
||||
if(target_state < state)
|
||||
if(memory["exterior_status"] == "closed")
|
||||
if(sanitize_external)
|
||||
state = AIRLOCK_STATE_DEPRESSURIZE
|
||||
process_again = 1
|
||||
else
|
||||
state = AIRLOCK_STATE_CLOSED
|
||||
process_again = 1
|
||||
else
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = exterior_door_tag,
|
||||
"command" = "secure_close"
|
||||
)))
|
||||
else
|
||||
if(memory["pump_status"] != "off")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"power" = 0,
|
||||
"sigtype" = "command"
|
||||
)))
|
||||
|
||||
memory["sensor_pressure"] = sensor_pressure
|
||||
memory["processing"] = state != target_state
|
||||
//sensor_pressure = null //not sure if we can comment this out. Uncomment in case of problems -rastaf0
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
name = "airlock console"
|
||||
density = FALSE
|
||||
|
||||
frequency = FREQ_AIRLOCK_CONTROL
|
||||
power_channel = ENVIRON
|
||||
|
||||
// Setup parameters only
|
||||
var/id_tag
|
||||
var/exterior_door_tag
|
||||
var/interior_door_tag
|
||||
var/airpump_tag
|
||||
var/sensor_tag
|
||||
var/sanitize_external
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_toxmix
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_TOXMIX_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_ATMOS_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_syndicatelava
|
||||
name = "Incinerator Access Console"
|
||||
airpump_tag = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP
|
||||
exterior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR
|
||||
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
|
||||
interior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR
|
||||
sanitize_external = TRUE
|
||||
sensor_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
return
|
||||
|
||||
var/datum/computer/file/embedded_program/airlock_controller/new_prog = new
|
||||
|
||||
new_prog.id_tag = id_tag
|
||||
new_prog.exterior_door_tag = exterior_door_tag
|
||||
new_prog.interior_door_tag = interior_door_tag
|
||||
new_prog.airpump_tag = airpump_tag
|
||||
new_prog.sensor_tag = sensor_tag
|
||||
new_prog.sanitize_external = sanitize_external
|
||||
|
||||
new_prog.master = src
|
||||
program = new_prog
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/update_icon()
|
||||
if(on && program)
|
||||
if(program.memory["processing"])
|
||||
icon_state = "airlock_control_process"
|
||||
else
|
||||
icon_state = "airlock_control_standby"
|
||||
else
|
||||
icon_state = "airlock_control_off"
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock_controller/return_text()
|
||||
var/state_options = null
|
||||
|
||||
var/state = 0
|
||||
var/sensor_pressure = "----"
|
||||
var/exterior_status = "----"
|
||||
var/interior_status = "----"
|
||||
var/pump_status = "----"
|
||||
var/current_status = "Inactive<BR> "
|
||||
if(program)
|
||||
state = program.state
|
||||
sensor_pressure = program.memory["sensor_pressure"] ? program.memory["sensor_pressure"] : "----"
|
||||
exterior_status = program.memory["exterior_status"] ? program.memory["exterior_status"] : "----"
|
||||
interior_status = program.memory["interior_status"] ? program.memory["interior_status"] : "----"
|
||||
pump_status = program.memory["pump_status"] ? program.memory["pump_status"] : "----"
|
||||
|
||||
switch(state)
|
||||
if(AIRLOCK_STATE_INOPEN)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_closed'>Close Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_exterior'>Cycle to Exterior Airlock</A><BR>"}
|
||||
current_status = "Interior Airlock Open<BR><span class='good'>Chamber Pressurized</span>"
|
||||
if(AIRLOCK_STATE_PRESSURIZE)
|
||||
state_options = "<A href='?src=[REF(src)];command=abort'>Abort Cycling</A><BR>"
|
||||
current_status = "Cycling to Interior Airlock<BR><span class='average'>Chamber Pressurizing</span>"
|
||||
if(AIRLOCK_STATE_CLOSED)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_interior'>Open Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_exterior'>Open Exterior Airlock</A><BR>"}
|
||||
if(AIRLOCK_STATE_DEPRESSURIZE)
|
||||
state_options = "<A href='?src=[REF(src)];command=abort'>Abort Cycling</A><BR>"
|
||||
current_status = "Cycling to Exterior Airlock<BR><span class='average'>Chamber Depressurizing</span>"
|
||||
if(AIRLOCK_STATE_OUTOPEN)
|
||||
state_options = {"<A href='?src=[REF(src)];command=cycle_interior'>Cycle to Interior Airlock</A><BR>
|
||||
<A href='?src=[REF(src)];command=cycle_closed'>Close Exterior Airlock</A><BR>"}
|
||||
current_status = "Exterior Airlock Open<BR><span class='bad'>Chamber Depressurized</span>"
|
||||
|
||||
var/output = {"<h3>Airlock Status</h3>
|
||||
<div class='statusDisplay'>
|
||||
<div class='line'><div class='statusLabel'>Current Status:</div><div class='statusValue'>[current_status]</div></div>
|
||||
<div class='line'> </div>
|
||||
<div class='line'><div class='statusLabel'>\> Chamber Pressure:</div><div class='statusValue'>[sensor_pressure] kPa</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Control Pump:</div><div class='statusValue'>[pump_status]</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Interior Door:</div><div class='statusValue'>[interior_status]</div></div>
|
||||
<div class='line'><div class='statusLabel'>\> Exterior Door:</div><div class='statusValue'>[exterior_status]</div></div>
|
||||
<div class='clearBoth'></div>
|
||||
</div>
|
||||
[state_options]"}
|
||||
|
||||
return output
|
||||
@@ -1,87 +1,87 @@
|
||||
/datum/computer/file/embedded_program
|
||||
var/list/memory = list()
|
||||
var/state
|
||||
var/obj/machinery/embedded_controller/master
|
||||
|
||||
/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line)
|
||||
if(master)
|
||||
master.post_signal(signal, comm_line)
|
||||
else
|
||||
qdel(signal)
|
||||
|
||||
/datum/computer/file/embedded_program/proc/receive_user_command(command)
|
||||
|
||||
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal)
|
||||
return null
|
||||
|
||||
/datum/computer/file/embedded_program/process()
|
||||
return 0
|
||||
|
||||
/obj/machinery/embedded_controller
|
||||
var/datum/computer/file/embedded_program/program
|
||||
|
||||
name = "embedded controller"
|
||||
density = FALSE
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
/obj/machinery/embedded_controller/ui_interact(mob/user)
|
||||
. = ..()
|
||||
user.set_machine(src)
|
||||
var/datum/browser/popup = new(user, "computer", name) // Set up the popup browser window
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.set_content(return_text())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/embedded_controller/update_icon()
|
||||
|
||||
/obj/machinery/embedded_controller/proc/return_text()
|
||||
|
||||
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
|
||||
return 0
|
||||
|
||||
/obj/machinery/embedded_controller/receive_signal(datum/signal/signal)
|
||||
if(istype(signal) && program)
|
||||
program.receive_signal(signal)
|
||||
|
||||
/obj/machinery/embedded_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return 0
|
||||
|
||||
if(program)
|
||||
program.receive_user_command(href_list["command"])
|
||||
addtimer(CALLBACK(program, /datum/computer/file/embedded_program.proc/process), 5)
|
||||
|
||||
usr.set_machine(src)
|
||||
addtimer(CALLBACK(src, .proc/updateDialog), 5)
|
||||
|
||||
/obj/machinery/embedded_controller/process()
|
||||
if(program)
|
||||
program.process()
|
||||
|
||||
update_icon()
|
||||
src.updateDialog()
|
||||
|
||||
/obj/machinery/embedded_controller/radio
|
||||
var/frequency
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/embedded_controller/radio/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/embedded_controller/radio/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal)
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
if(radio_connection)
|
||||
return radio_connection.post_signal(src, signal)
|
||||
else
|
||||
signal = null
|
||||
|
||||
/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency)
|
||||
/datum/computer/file/embedded_program
|
||||
var/list/memory = list()
|
||||
var/state
|
||||
var/obj/machinery/embedded_controller/master
|
||||
|
||||
/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line)
|
||||
if(master)
|
||||
master.post_signal(signal, comm_line)
|
||||
else
|
||||
qdel(signal)
|
||||
|
||||
/datum/computer/file/embedded_program/proc/receive_user_command(command)
|
||||
|
||||
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal)
|
||||
return null
|
||||
|
||||
/datum/computer/file/embedded_program/process()
|
||||
return 0
|
||||
|
||||
/obj/machinery/embedded_controller
|
||||
var/datum/computer/file/embedded_program/program
|
||||
|
||||
name = "embedded controller"
|
||||
density = FALSE
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
/obj/machinery/embedded_controller/ui_interact(mob/user)
|
||||
. = ..()
|
||||
user.set_machine(src)
|
||||
var/datum/browser/popup = new(user, "computer", name) // Set up the popup browser window
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.set_content(return_text())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/embedded_controller/update_icon()
|
||||
|
||||
/obj/machinery/embedded_controller/proc/return_text()
|
||||
|
||||
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
|
||||
return 0
|
||||
|
||||
/obj/machinery/embedded_controller/receive_signal(datum/signal/signal)
|
||||
if(istype(signal) && program)
|
||||
program.receive_signal(signal)
|
||||
|
||||
/obj/machinery/embedded_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return 0
|
||||
|
||||
if(program)
|
||||
program.receive_user_command(href_list["command"])
|
||||
addtimer(CALLBACK(program, /datum/computer/file/embedded_program.proc/process), 5)
|
||||
|
||||
usr.set_machine(src)
|
||||
addtimer(CALLBACK(src, .proc/updateDialog), 5)
|
||||
|
||||
/obj/machinery/embedded_controller/process()
|
||||
if(program)
|
||||
program.process()
|
||||
|
||||
update_icon()
|
||||
src.updateDialog()
|
||||
|
||||
/obj/machinery/embedded_controller/radio
|
||||
var/frequency
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/embedded_controller/radio/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/embedded_controller/radio/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal)
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
if(radio_connection)
|
||||
return radio_connection.post_signal(src, signal)
|
||||
else
|
||||
signal = null
|
||||
|
||||
/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency)
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
/datum/computer/file/embedded_program/simple_vent_controller
|
||||
|
||||
var/airpump_tag
|
||||
|
||||
/datum/computer/file/embedded_program/simple_vent_controller/receive_user_command(command)
|
||||
switch(command)
|
||||
if("vent_inactive")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"power" = 0
|
||||
)))
|
||||
|
||||
if("vent_pump")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"stabilize" = 1,
|
||||
"power" = 1
|
||||
)))
|
||||
|
||||
if("vent_clear")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"purge" = 1,
|
||||
"power" = 1
|
||||
)))
|
||||
|
||||
/datum/computer/file/embedded_program/simple_vent_controller/process()
|
||||
return 0
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
name = "vent controller"
|
||||
density = FALSE
|
||||
|
||||
frequency = FREQ_ATMOS_CONTROL
|
||||
power_channel = ENVIRON
|
||||
|
||||
// Setup parameters only
|
||||
var/airpump_tag
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
return
|
||||
var/datum/computer/file/embedded_program/simple_vent_controller/new_prog = new
|
||||
|
||||
new_prog.airpump_tag = airpump_tag
|
||||
new_prog.master = src
|
||||
program = new_prog
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon()
|
||||
if(on && program)
|
||||
icon_state = "airlock_control_standby"
|
||||
else
|
||||
icon_state = "airlock_control_off"
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/return_text()
|
||||
var/state_options = null
|
||||
state_options = {"<A href='?src=[REF(src)];command=vent_inactive'>Deactivate Vent</A><BR>
|
||||
<A href='?src=[REF(src)];command=vent_pump'>Activate Vent / Pump</A><BR>
|
||||
<A href='?src=[REF(src)];command=vent_clear'>Activate Vent / Clear</A><BR>"}
|
||||
var/output = {"<B>Vent Control Console</B><HR>
|
||||
[state_options]<HR>"}
|
||||
|
||||
return output
|
||||
/datum/computer/file/embedded_program/simple_vent_controller
|
||||
|
||||
var/airpump_tag
|
||||
|
||||
/datum/computer/file/embedded_program/simple_vent_controller/receive_user_command(command)
|
||||
switch(command)
|
||||
if("vent_inactive")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"power" = 0
|
||||
)))
|
||||
|
||||
if("vent_pump")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"stabilize" = 1,
|
||||
"power" = 1
|
||||
)))
|
||||
|
||||
if("vent_clear")
|
||||
post_signal(new /datum/signal(list(
|
||||
"tag" = airpump_tag,
|
||||
"sigtype" = "command",
|
||||
"purge" = 1,
|
||||
"power" = 1
|
||||
)))
|
||||
|
||||
/datum/computer/file/embedded_program/simple_vent_controller/process()
|
||||
return 0
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
name = "vent controller"
|
||||
density = FALSE
|
||||
|
||||
frequency = FREQ_ATMOS_CONTROL
|
||||
power_channel = ENVIRON
|
||||
|
||||
// Setup parameters only
|
||||
var/airpump_tag
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
return
|
||||
var/datum/computer/file/embedded_program/simple_vent_controller/new_prog = new
|
||||
|
||||
new_prog.airpump_tag = airpump_tag
|
||||
new_prog.master = src
|
||||
program = new_prog
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon()
|
||||
if(on && program)
|
||||
icon_state = "airlock_control_standby"
|
||||
else
|
||||
icon_state = "airlock_control_off"
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller/return_text()
|
||||
var/state_options = null
|
||||
state_options = {"<A href='?src=[REF(src)];command=vent_inactive'>Deactivate Vent</A><BR>
|
||||
<A href='?src=[REF(src)];command=vent_pump'>Activate Vent / Pump</A><BR>
|
||||
<A href='?src=[REF(src)];command=vent_clear'>Activate Vent / Clear</A><BR>"}
|
||||
var/output = {"<B>Vent Control Console</B><HR>
|
||||
[state_options]<HR>"}
|
||||
|
||||
return output
|
||||
|
||||
+340
-326
@@ -1,326 +1,340 @@
|
||||
#define FIREALARM_COOLDOWN 67 // Chosen fairly arbitrarily, it is the length of the audio in FireAlarm.ogg. The actual track length is 7 seconds 8ms but but the audio stops at 6s 700ms
|
||||
|
||||
/obj/item/electronics/firealarm
|
||||
name = "fire alarm electronics"
|
||||
desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius."
|
||||
|
||||
/obj/item/wallframe/firealarm
|
||||
name = "fire alarm frame"
|
||||
desc = "Used for building fire alarms."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire_bitem"
|
||||
result_path = /obj/machinery/firealarm
|
||||
|
||||
/obj/machinery/firealarm
|
||||
name = "fire alarm"
|
||||
desc = "<i>\"Pull this in case of emergency\"</i>. Thus, keep pulling it forever."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire0"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 6
|
||||
power_channel = ENVIRON
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
light_power = 0
|
||||
light_range = 7
|
||||
light_color = "#ff3232"
|
||||
|
||||
var/detecting = 1
|
||||
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
|
||||
var/last_alarm = 0
|
||||
var/area/myarea = null
|
||||
|
||||
/obj/machinery/firealarm/Initialize(mapload, dir, building)
|
||||
. = ..()
|
||||
if(dir)
|
||||
src.setDir(dir)
|
||||
if(building)
|
||||
buildstage = 0
|
||||
panel_open = TRUE
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
|
||||
update_icon()
|
||||
myarea = get_area(src)
|
||||
LAZYADD(myarea.firealarms, src)
|
||||
|
||||
/obj/machinery/firealarm/Destroy()
|
||||
LAZYREMOVE(myarea.firealarms, src)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/firealarm/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/firealarm/update_icon()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
|
||||
if(panel_open)
|
||||
icon_state = "fire_b[buildstage]"
|
||||
return
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "firex"
|
||||
return
|
||||
|
||||
icon_state = "fire0"
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
add_overlay("fire_overlay")
|
||||
|
||||
if(is_station_level(z))
|
||||
add_overlay("fire_[GLOB.security_level]")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else
|
||||
add_overlay("fire_[SEC_LEVEL_GREEN]")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
|
||||
var/area/A = src.loc
|
||||
A = A.loc
|
||||
|
||||
if(!detecting || !A.fire)
|
||||
add_overlay("fire_off")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else if(obj_flags & EMAGGED)
|
||||
add_overlay("fire_emagged")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else
|
||||
add_overlay("fire_on")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
|
||||
/obj/machinery/firealarm/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
|
||||
if(prob(50 / severity))
|
||||
alarm()
|
||||
|
||||
/obj/machinery/firealarm/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
update_icon()
|
||||
if(user)
|
||||
user.visible_message("<span class='warning'>Sparks fly out of [src]!</span>",
|
||||
"<span class='notice'>You emag [src], disabling its thermal sensors.</span>")
|
||||
playsound(src, "sparks", 50, 1)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume)
|
||||
if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat)
|
||||
alarm()
|
||||
..()
|
||||
|
||||
/obj/machinery/firealarm/proc/alarm(mob/user)
|
||||
if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time))
|
||||
return
|
||||
last_alarm = world.time
|
||||
var/area/A = get_area(src)
|
||||
A.firealert(src)
|
||||
playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75)
|
||||
if(user)
|
||||
log_game("[user] triggered a fire alarm at [COORD(src)]")
|
||||
|
||||
/obj/machinery/firealarm/proc/reset(mob/user)
|
||||
if(!is_operational())
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
A.firereset(src)
|
||||
if(user)
|
||||
log_game("[user] reset a fire alarm at [COORD(src)]")
|
||||
|
||||
/obj/machinery/firealarm/attack_hand(mob/user)
|
||||
if(buildstage != 2)
|
||||
return ..()
|
||||
add_fingerprint(user)
|
||||
var/area/A = get_area(src)
|
||||
if(A.fire)
|
||||
reset(user)
|
||||
else
|
||||
alarm(user)
|
||||
|
||||
/obj/machinery/firealarm/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/firealarm/attack_robot(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver) && buildstage == 2)
|
||||
W.play_tool_sound(src)
|
||||
panel_open = !panel_open
|
||||
to_chat(user, "<span class='notice'>The wires have been [panel_open ? "exposed" : "unexposed"].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
|
||||
if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP)
|
||||
if(obj_integrity < max_integrity)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin repairing [src]...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
obj_integrity = max_integrity
|
||||
to_chat(user, "<span class='notice'>You repair [src].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
|
||||
return
|
||||
|
||||
switch(buildstage)
|
||||
if(2)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
detecting = !detecting
|
||||
if (src.detecting)
|
||||
user.visible_message("[user] has reconnected [src]'s detecting unit!", "<span class='notice'>You reconnect [src]'s detecting unit.</span>")
|
||||
else
|
||||
user.visible_message("[user] has disconnected [src]'s detecting unit!", "<span class='notice'>You disconnect [src]'s detecting unit.</span>")
|
||||
return
|
||||
|
||||
else if (istype(W, /obj/item/wirecutters))
|
||||
buildstage = 1
|
||||
W.play_tool_sound(src)
|
||||
new /obj/item/stack/cable_coil(user.loc, 5)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
else if(W.force) //hit and turn it on
|
||||
..()
|
||||
var/area/A = get_area(src)
|
||||
if(!A.fire)
|
||||
alarm()
|
||||
return
|
||||
if(1)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if(coil.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning'>You need more cable for this!</span>")
|
||||
else
|
||||
coil.use(5)
|
||||
buildstage = 2
|
||||
to_chat(user, "<span class='notice'>You wire \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/crowbar))
|
||||
user.visible_message("[user.name] removes the electronics from [src.name].", \
|
||||
"<span class='notice'>You start prying out the circuit...</span>")
|
||||
if(W.use_tool(src, user, 20, volume=50))
|
||||
if(buildstage == 1)
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='notice'>You remove the destroyed circuit.</span>")
|
||||
stat &= ~BROKEN
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You pry out the circuit.</span>")
|
||||
new /obj/item/electronics/firealarm(user.loc)
|
||||
buildstage = 0
|
||||
update_icon()
|
||||
return
|
||||
if(0)
|
||||
if(istype(W, /obj/item/electronics/firealarm))
|
||||
to_chat(user, "<span class='notice'>You insert the circuit.</span>")
|
||||
qdel(W)
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/electroadaptive_pseudocircuit))
|
||||
var/obj/item/electroadaptive_pseudocircuit/P = W
|
||||
if(!P.adapt_circuit(user, 15))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a fire alarm circuit and slot it into the assembly.</span>")
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/wrench))
|
||||
user.visible_message("[user] removes the fire alarm assembly from the wall.", \
|
||||
"<span class='notice'>You remove the fire alarm assembly from the wall.</span>")
|
||||
var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm()
|
||||
frame.forceMove(user.drop_location())
|
||||
W.play_tool_sound(src)
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(.) //damage received
|
||||
if(obj_integrity > 0 && !(stat & BROKEN) && buildstage != 0)
|
||||
if(prob(33))
|
||||
alarm()
|
||||
|
||||
/obj/machinery/firealarm/singularity_pull(S, current_size)
|
||||
if (current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects, the fire alarm experiences integrity failure
|
||||
deconstruct()
|
||||
..()
|
||||
|
||||
/obj/machinery/firealarm/obj_break(damage_flag)
|
||||
if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1) && buildstage != 0) //can't break the electronics if there isn't any inside.
|
||||
LAZYREMOVE(myarea.firealarms, src)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/firealarm/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc, 1)
|
||||
if(!(stat & BROKEN))
|
||||
var/obj/item/I = new /obj/item/electronics/firealarm(loc)
|
||||
if(!disassembled)
|
||||
I.obj_integrity = I.max_integrity * 0.5
|
||||
new /obj/item/stack/cable_coil(loc, 3)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/firealarm/proc/update_fire_light(fire)
|
||||
if(fire == !!light_power)
|
||||
return // do nothing if we're already active
|
||||
if(fire)
|
||||
set_light(l_power = 0.8)
|
||||
else
|
||||
set_light(l_power = 0)
|
||||
|
||||
/*
|
||||
* Return of Party button
|
||||
*/
|
||||
|
||||
/area
|
||||
var/party = FALSE
|
||||
|
||||
/obj/machinery/firealarm/partyalarm
|
||||
name = "\improper PARTY BUTTON"
|
||||
desc = "Cuban Pete is in the house!"
|
||||
var/static/party_overlay
|
||||
|
||||
/obj/machinery/firealarm/partyalarm/reset()
|
||||
if (stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if (!A || !A.party)
|
||||
return
|
||||
A.party = FALSE
|
||||
A.cut_overlay(party_overlay)
|
||||
|
||||
/obj/machinery/firealarm/partyalarm/alarm()
|
||||
if (stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if (!A || A.party || A.name == "Space")
|
||||
return
|
||||
A.party = TRUE
|
||||
if (!party_overlay)
|
||||
party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party")
|
||||
A.add_overlay(party_overlay)
|
||||
#define FIREALARM_COOLDOWN 67 // Chosen fairly arbitrarily, it is the length of the audio in FireAlarm.ogg. The actual track length is 7 seconds 8ms but but the audio stops at 6s 700ms
|
||||
|
||||
/obj/item/electronics/firealarm
|
||||
name = "fire alarm electronics"
|
||||
desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius."
|
||||
|
||||
/obj/item/wallframe/firealarm
|
||||
name = "fire alarm frame"
|
||||
desc = "Used for building fire alarms."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire_bitem"
|
||||
result_path = /obj/machinery/firealarm
|
||||
|
||||
/obj/machinery/firealarm
|
||||
name = "fire alarm"
|
||||
desc = "<i>\"Pull this in case of emergency\"</i>. Thus, keep pulling it forever."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire0"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 6
|
||||
power_channel = ENVIRON
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
light_power = 0
|
||||
light_range = 7
|
||||
light_color = "#ff3232"
|
||||
|
||||
var/detecting = 1
|
||||
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
|
||||
var/last_alarm = 0
|
||||
var/area/myarea = null
|
||||
|
||||
/obj/machinery/firealarm/Initialize(mapload, dir, building)
|
||||
. = ..()
|
||||
if(dir)
|
||||
src.setDir(dir)
|
||||
if(building)
|
||||
buildstage = 0
|
||||
panel_open = TRUE
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
|
||||
update_icon()
|
||||
myarea = get_area(src)
|
||||
LAZYADD(myarea.firealarms, src)
|
||||
|
||||
/obj/machinery/firealarm/Destroy()
|
||||
LAZYREMOVE(myarea.firealarms, src)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/firealarm/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/firealarm/update_icon()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
|
||||
if(panel_open)
|
||||
icon_state = "fire_b[buildstage]"
|
||||
return
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "firex"
|
||||
return
|
||||
|
||||
icon_state = "fire0"
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
add_overlay("fire_overlay")
|
||||
|
||||
if(is_station_level(z))
|
||||
add_overlay("fire_[GLOB.security_level]")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else
|
||||
add_overlay("fire_[SEC_LEVEL_GREEN]")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
|
||||
var/area/A = src.loc
|
||||
A = A.loc
|
||||
|
||||
if(!detecting || !A.fire)
|
||||
add_overlay("fire_off")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else if(obj_flags & EMAGGED)
|
||||
add_overlay("fire_emagged")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
else
|
||||
add_overlay("fire_on")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
|
||||
/obj/machinery/firealarm/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
|
||||
if(prob(50 / severity))
|
||||
alarm()
|
||||
|
||||
/obj/machinery/firealarm/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
update_icon()
|
||||
if(user)
|
||||
user.visible_message("<span class='warning'>Sparks fly out of [src]!</span>",
|
||||
"<span class='notice'>You emag [src], disabling its thermal sensors.</span>")
|
||||
playsound(src, "sparks", 50, 1)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume)
|
||||
if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat)
|
||||
alarm()
|
||||
..()
|
||||
|
||||
/obj/machinery/firealarm/proc/alarm(mob/user)
|
||||
if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time))
|
||||
return
|
||||
last_alarm = world.time
|
||||
var/area/A = get_area(src)
|
||||
A.firealert(src)
|
||||
playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75)
|
||||
if(user)
|
||||
log_game("[user] triggered a fire alarm at [COORD(src)]")
|
||||
|
||||
/obj/machinery/firealarm/proc/reset(mob/user)
|
||||
if(!is_operational())
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
A.firereset(src)
|
||||
if(user)
|
||||
log_game("[user] reset a fire alarm at [COORD(src)]")
|
||||
|
||||
/obj/machinery/firealarm/attack_hand(mob/user)
|
||||
if(buildstage != 2)
|
||||
return ..()
|
||||
add_fingerprint(user)
|
||||
var/area/A = get_area(src)
|
||||
if(A.fire)
|
||||
reset(user)
|
||||
else
|
||||
alarm(user)
|
||||
|
||||
/obj/machinery/firealarm/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/firealarm/attack_robot(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver) && buildstage == 2)
|
||||
W.play_tool_sound(src)
|
||||
panel_open = !panel_open
|
||||
to_chat(user, "<span class='notice'>The wires have been [panel_open ? "exposed" : "unexposed"].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
|
||||
if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP)
|
||||
if(obj_integrity < max_integrity)
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin repairing [src]...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
obj_integrity = max_integrity
|
||||
to_chat(user, "<span class='notice'>You repair [src].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
|
||||
return
|
||||
|
||||
switch(buildstage)
|
||||
if(2)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
detecting = !detecting
|
||||
if (src.detecting)
|
||||
user.visible_message("[user] has reconnected [src]'s detecting unit!", "<span class='notice'>You reconnect [src]'s detecting unit.</span>")
|
||||
else
|
||||
user.visible_message("[user] has disconnected [src]'s detecting unit!", "<span class='notice'>You disconnect [src]'s detecting unit.</span>")
|
||||
return
|
||||
|
||||
else if (istype(W, /obj/item/wirecutters))
|
||||
buildstage = 1
|
||||
W.play_tool_sound(src)
|
||||
new /obj/item/stack/cable_coil(user.loc, 5)
|
||||
to_chat(user, "<span class='notice'>You cut the wires from \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
else if(W.force) //hit and turn it on
|
||||
..()
|
||||
var/area/A = get_area(src)
|
||||
if(!A.fire)
|
||||
alarm()
|
||||
return
|
||||
if(1)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if(coil.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning'>You need more cable for this!</span>")
|
||||
else
|
||||
coil.use(5)
|
||||
buildstage = 2
|
||||
to_chat(user, "<span class='notice'>You wire \the [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/crowbar))
|
||||
user.visible_message("[user.name] removes the electronics from [src.name].", \
|
||||
"<span class='notice'>You start prying out the circuit...</span>")
|
||||
if(W.use_tool(src, user, 20, volume=50))
|
||||
if(buildstage == 1)
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='notice'>You remove the destroyed circuit.</span>")
|
||||
stat &= ~BROKEN
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You pry out the circuit.</span>")
|
||||
new /obj/item/electronics/firealarm(user.loc)
|
||||
buildstage = 0
|
||||
update_icon()
|
||||
return
|
||||
if(0)
|
||||
if(istype(W, /obj/item/electronics/firealarm))
|
||||
to_chat(user, "<span class='notice'>You insert the circuit.</span>")
|
||||
qdel(W)
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/electroadaptive_pseudocircuit))
|
||||
var/obj/item/electroadaptive_pseudocircuit/P = W
|
||||
if(!P.adapt_circuit(user, 15))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a fire alarm circuit and slot it into the assembly.</span>")
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/wrench))
|
||||
user.visible_message("[user] removes the fire alarm assembly from the wall.", \
|
||||
"<span class='notice'>You remove the fire alarm assembly from the wall.</span>")
|
||||
var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm()
|
||||
frame.forceMove(user.drop_location())
|
||||
W.play_tool_sound(src)
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/firealarm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
if((buildstage == 0) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS))
|
||||
return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1)
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/firealarm/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
||||
switch(passed_mode)
|
||||
if(RCD_UPGRADE_SIMPLE_CIRCUITS)
|
||||
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
|
||||
"<span class='notice'>You adapt a fire alarm circuit and slot it into the assembly.</span>")
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(.) //damage received
|
||||
if(obj_integrity > 0 && !(stat & BROKEN) && buildstage != 0)
|
||||
if(prob(33))
|
||||
alarm()
|
||||
|
||||
/obj/machinery/firealarm/singularity_pull(S, current_size)
|
||||
if (current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects, the fire alarm experiences integrity failure
|
||||
deconstruct()
|
||||
..()
|
||||
|
||||
/obj/machinery/firealarm/obj_break(damage_flag)
|
||||
if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1) && buildstage != 0) //can't break the electronics if there isn't any inside.
|
||||
LAZYREMOVE(myarea.firealarms, src)
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/firealarm/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
new /obj/item/stack/sheet/metal(loc, 1)
|
||||
if(!(stat & BROKEN))
|
||||
var/obj/item/I = new /obj/item/electronics/firealarm(loc)
|
||||
if(!disassembled)
|
||||
I.obj_integrity = I.max_integrity * 0.5
|
||||
new /obj/item/stack/cable_coil(loc, 3)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/firealarm/proc/update_fire_light(fire)
|
||||
if(fire == !!light_power)
|
||||
return // do nothing if we're already active
|
||||
if(fire)
|
||||
set_light(l_power = 0.8)
|
||||
else
|
||||
set_light(l_power = 0)
|
||||
|
||||
/*
|
||||
* Return of Party button
|
||||
*/
|
||||
|
||||
/area
|
||||
var/party = FALSE
|
||||
|
||||
/obj/machinery/firealarm/partyalarm
|
||||
name = "\improper PARTY BUTTON"
|
||||
desc = "Cuban Pete is in the house!"
|
||||
var/static/party_overlay
|
||||
|
||||
/obj/machinery/firealarm/partyalarm/reset()
|
||||
if (stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if (!A || !A.party)
|
||||
return
|
||||
A.party = FALSE
|
||||
A.cut_overlay(party_overlay)
|
||||
|
||||
/obj/machinery/firealarm/partyalarm/alarm()
|
||||
if (stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if (!A || A.party || A.name == "Space")
|
||||
return
|
||||
A.party = TRUE
|
||||
if (!party_overlay)
|
||||
party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party")
|
||||
A.add_overlay(party_overlay)
|
||||
|
||||
+205
-205
@@ -1,205 +1,205 @@
|
||||
// It is a gizmo that flashes a small area
|
||||
|
||||
/obj/machinery/flasher
|
||||
name = "mounted flash"
|
||||
desc = "A wall-mounted flashbulb device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash1"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
light_color = LIGHT_COLOR_WHITE
|
||||
light_power = FLASH_LIGHT_POWER
|
||||
var/obj/item/assembly/flash/handheld/bulb
|
||||
var/id = null
|
||||
var/range = 2 //this is roughly the size of brig cell
|
||||
var/last_flash = 0 //Don't want it getting spammed like regular flashes
|
||||
var/strength = 100 //How knocked down targets are when flashed.
|
||||
var/base_state = "mflash"
|
||||
|
||||
/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored
|
||||
name = "portable flasher"
|
||||
desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements."
|
||||
icon_state = "pflash1-p"
|
||||
strength = 80
|
||||
anchored = FALSE
|
||||
base_state = "pflash"
|
||||
density = TRUE
|
||||
|
||||
/obj/machinery/flasher/Initialize(mapload, ndir = 0, built = 0)
|
||||
. = ..() // ..() is EXTREMELY IMPORTANT, never forget to add it
|
||||
if(built)
|
||||
setDir(ndir)
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -28 : 28)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -28 : 28) : 0
|
||||
else
|
||||
bulb = new(src)
|
||||
|
||||
/obj/machinery/flasher/Destroy()
|
||||
QDEL_NULL(bulb)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/flasher/power_change()
|
||||
if (powered() && anchored && bulb)
|
||||
stat &= ~NOPOWER
|
||||
if(bulb.crit_fail)
|
||||
icon_state = "[base_state]1-p"
|
||||
else
|
||||
icon_state = "[base_state]1"
|
||||
else
|
||||
stat |= NOPOWER
|
||||
icon_state = "[base_state]1-p"
|
||||
|
||||
//Don't want to render prison breaks impossible
|
||||
/obj/machinery/flasher/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if (istype(W, /obj/item/wirecutters))
|
||||
if (bulb)
|
||||
user.visible_message("[user] begins to disconnect [src]'s flashbulb.", "<span class='notice'>You begin to disconnect [src]'s flashbulb...</span>")
|
||||
if(W.use_tool(src, user, 30, volume=50) && bulb)
|
||||
user.visible_message("[user] has disconnected [src]'s flashbulb!", "<span class='notice'>You disconnect [src]'s flashbulb.</span>")
|
||||
bulb.forceMove(loc)
|
||||
bulb = null
|
||||
power_change()
|
||||
|
||||
else if (istype(W, /obj/item/assembly/flash/handheld))
|
||||
if (!bulb)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
user.visible_message("[user] installs [W] into [src].", "<span class='notice'>You install [W] into [src].</span>")
|
||||
bulb = W
|
||||
power_change()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>A flashbulb is already installed in [src]!</span>")
|
||||
|
||||
else if (istype(W, /obj/item/wrench))
|
||||
if(!bulb)
|
||||
to_chat(user, "<span class='notice'>You start unsecuring the flasher frame...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
to_chat(user, "<span class='notice'>You unsecure the flasher frame.</span>")
|
||||
deconstruct(TRUE)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Remove a flashbulb from [src] first!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Let the AI trigger them directly.
|
||||
/obj/machinery/flasher/attack_ai()
|
||||
if (anchored)
|
||||
return flash()
|
||||
|
||||
/obj/machinery/flasher/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
||||
if(damage_flag == "melee" && damage_amount < 10) //any melee attack below 10 dmg does nothing
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/flasher/proc/flash()
|
||||
if (!powered() || !bulb)
|
||||
return
|
||||
|
||||
if (bulb.crit_fail || (last_flash && world.time < src.last_flash + 150))
|
||||
return
|
||||
|
||||
if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast
|
||||
power_change()
|
||||
return
|
||||
|
||||
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
|
||||
flick("[base_state]_flash", src)
|
||||
flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color)
|
||||
last_flash = world.time
|
||||
use_power(1000)
|
||||
|
||||
var/flashed = FALSE
|
||||
for (var/mob/living/L in viewers(src, null))
|
||||
if (get_dist(src, L) > range)
|
||||
continue
|
||||
|
||||
if(L.flash_act(affect_silicon = 1))
|
||||
L.Knockdown(strength)
|
||||
flashed = TRUE
|
||||
|
||||
if(flashed)
|
||||
bulb.times_used++
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/flasher/emp_act(severity)
|
||||
. = ..()
|
||||
if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
|
||||
if(bulb && prob(75/severity))
|
||||
flash()
|
||||
bulb.burn_out()
|
||||
power_change()
|
||||
|
||||
/obj/machinery/flasher/obj_break(damage_flag)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(!(stat & BROKEN))
|
||||
stat |= BROKEN
|
||||
if(bulb)
|
||||
bulb.burn_out()
|
||||
power_change()
|
||||
|
||||
/obj/machinery/flasher/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(bulb)
|
||||
bulb.forceMove(loc)
|
||||
bulb = null
|
||||
if(disassembled)
|
||||
var/obj/item/wallframe/flasher/F = new(get_turf(src))
|
||||
transfer_fingerprints_to(F)
|
||||
F.id = id
|
||||
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
else
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/flasher/portable/Initialize()
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 0)
|
||||
|
||||
/obj/machinery/flasher/portable/HasProximity(atom/movable/AM)
|
||||
if (last_flash && world.time < last_flash + 150)
|
||||
return
|
||||
|
||||
if(istype(AM, /mob/living/carbon))
|
||||
var/mob/living/carbon/M = AM
|
||||
if (M.m_intent != MOVE_INTENT_WALK && anchored)
|
||||
flash()
|
||||
|
||||
/obj/machinery/flasher/portable/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/wrench))
|
||||
W.play_tool_sound(src, 100)
|
||||
|
||||
if (!anchored && !isinspace())
|
||||
to_chat(user, "<span class='notice'>[src] is now secured.</span>")
|
||||
add_overlay("[base_state]-s")
|
||||
setAnchored(TRUE)
|
||||
power_change()
|
||||
proximity_monitor.SetRange(range)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be moved.</span>")
|
||||
cut_overlays()
|
||||
setAnchored(FALSE)
|
||||
power_change()
|
||||
proximity_monitor.SetRange(0)
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/wallframe/flasher
|
||||
name = "mounted flash frame"
|
||||
desc = "Used for building wall-mounted flashers."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash_frame"
|
||||
result_path = /obj/machinery/flasher
|
||||
var/id = null
|
||||
|
||||
/obj/item/wallframe/flasher/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Its channel ID is '[id]'.</span>"
|
||||
|
||||
/obj/item/wallframe/flasher/after_attach(var/obj/O)
|
||||
..()
|
||||
var/obj/machinery/flasher/F = O
|
||||
F.id = id
|
||||
// It is a gizmo that flashes a small area
|
||||
|
||||
/obj/machinery/flasher
|
||||
name = "mounted flash"
|
||||
desc = "A wall-mounted flashbulb device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash1"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
light_color = LIGHT_COLOR_WHITE
|
||||
light_power = FLASH_LIGHT_POWER
|
||||
var/obj/item/assembly/flash/handheld/bulb
|
||||
var/id = null
|
||||
var/range = 2 //this is roughly the size of brig cell
|
||||
var/last_flash = 0 //Don't want it getting spammed like regular flashes
|
||||
var/strength = 100 //How knocked down targets are when flashed.
|
||||
var/base_state = "mflash"
|
||||
|
||||
/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored
|
||||
name = "portable flasher"
|
||||
desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements."
|
||||
icon_state = "pflash1-p"
|
||||
strength = 80
|
||||
anchored = FALSE
|
||||
base_state = "pflash"
|
||||
density = TRUE
|
||||
|
||||
/obj/machinery/flasher/Initialize(mapload, ndir = 0, built = 0)
|
||||
. = ..() // ..() is EXTREMELY IMPORTANT, never forget to add it
|
||||
if(built)
|
||||
setDir(ndir)
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -28 : 28)
|
||||
pixel_y = (dir & 3)? (dir ==1 ? -28 : 28) : 0
|
||||
else
|
||||
bulb = new(src)
|
||||
|
||||
/obj/machinery/flasher/Destroy()
|
||||
QDEL_NULL(bulb)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/flasher/power_change()
|
||||
if (powered() && anchored && bulb)
|
||||
stat &= ~NOPOWER
|
||||
if(bulb.crit_fail)
|
||||
icon_state = "[base_state]1-p"
|
||||
else
|
||||
icon_state = "[base_state]1"
|
||||
else
|
||||
stat |= NOPOWER
|
||||
icon_state = "[base_state]1-p"
|
||||
|
||||
//Don't want to render prison breaks impossible
|
||||
/obj/machinery/flasher/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if (istype(W, /obj/item/wirecutters))
|
||||
if (bulb)
|
||||
user.visible_message("[user] begins to disconnect [src]'s flashbulb.", "<span class='notice'>You begin to disconnect [src]'s flashbulb...</span>")
|
||||
if(W.use_tool(src, user, 30, volume=50) && bulb)
|
||||
user.visible_message("[user] has disconnected [src]'s flashbulb!", "<span class='notice'>You disconnect [src]'s flashbulb.</span>")
|
||||
bulb.forceMove(loc)
|
||||
bulb = null
|
||||
power_change()
|
||||
|
||||
else if (istype(W, /obj/item/assembly/flash/handheld))
|
||||
if (!bulb)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
user.visible_message("[user] installs [W] into [src].", "<span class='notice'>You install [W] into [src].</span>")
|
||||
bulb = W
|
||||
power_change()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>A flashbulb is already installed in [src]!</span>")
|
||||
|
||||
else if (istype(W, /obj/item/wrench))
|
||||
if(!bulb)
|
||||
to_chat(user, "<span class='notice'>You start unsecuring the flasher frame...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
to_chat(user, "<span class='notice'>You unsecure the flasher frame.</span>")
|
||||
deconstruct(TRUE)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Remove a flashbulb from [src] first!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Let the AI trigger them directly.
|
||||
/obj/machinery/flasher/attack_ai()
|
||||
if (anchored)
|
||||
return flash()
|
||||
|
||||
/obj/machinery/flasher/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
||||
if(damage_flag == "melee" && damage_amount < 10) //any melee attack below 10 dmg does nothing
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/flasher/proc/flash()
|
||||
if (!powered() || !bulb)
|
||||
return
|
||||
|
||||
if (bulb.crit_fail || (last_flash && world.time < src.last_flash + 150))
|
||||
return
|
||||
|
||||
if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast
|
||||
power_change()
|
||||
return
|
||||
|
||||
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
|
||||
flick("[base_state]_flash", src)
|
||||
flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color)
|
||||
last_flash = world.time
|
||||
use_power(1000)
|
||||
|
||||
var/flashed = FALSE
|
||||
for (var/mob/living/L in viewers(src, null))
|
||||
if (get_dist(src, L) > range)
|
||||
continue
|
||||
|
||||
if(L.flash_act(affect_silicon = 1))
|
||||
L.Knockdown(strength)
|
||||
flashed = TRUE
|
||||
|
||||
if(flashed)
|
||||
bulb.times_used++
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/flasher/emp_act(severity)
|
||||
. = ..()
|
||||
if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
|
||||
if(bulb && prob(75/severity))
|
||||
flash()
|
||||
bulb.burn_out()
|
||||
power_change()
|
||||
|
||||
/obj/machinery/flasher/obj_break(damage_flag)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(!(stat & BROKEN))
|
||||
stat |= BROKEN
|
||||
if(bulb)
|
||||
bulb.burn_out()
|
||||
power_change()
|
||||
|
||||
/obj/machinery/flasher/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(bulb)
|
||||
bulb.forceMove(loc)
|
||||
bulb = null
|
||||
if(disassembled)
|
||||
var/obj/item/wallframe/flasher/F = new(get_turf(src))
|
||||
transfer_fingerprints_to(F)
|
||||
F.id = id
|
||||
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
else
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/flasher/portable/Initialize()
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 0)
|
||||
|
||||
/obj/machinery/flasher/portable/HasProximity(atom/movable/AM)
|
||||
if (last_flash && world.time < last_flash + 150)
|
||||
return
|
||||
|
||||
if(istype(AM, /mob/living/carbon))
|
||||
var/mob/living/carbon/M = AM
|
||||
if (M.m_intent != MOVE_INTENT_WALK && anchored)
|
||||
flash()
|
||||
|
||||
/obj/machinery/flasher/portable/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/wrench))
|
||||
W.play_tool_sound(src, 100)
|
||||
|
||||
if (!anchored && !isinspace())
|
||||
to_chat(user, "<span class='notice'>[src] is now secured.</span>")
|
||||
add_overlay("[base_state]-s")
|
||||
setAnchored(TRUE)
|
||||
power_change()
|
||||
proximity_monitor.SetRange(range)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] can now be moved.</span>")
|
||||
cut_overlays()
|
||||
setAnchored(FALSE)
|
||||
power_change()
|
||||
proximity_monitor.SetRange(0)
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/wallframe/flasher
|
||||
name = "mounted flash frame"
|
||||
desc = "Used for building wall-mounted flashers."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash_frame"
|
||||
result_path = /obj/machinery/flasher
|
||||
var/id = null
|
||||
|
||||
/obj/item/wallframe/flasher/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Its channel ID is '[id]'.</span>"
|
||||
|
||||
/obj/item/wallframe/flasher/after_attach(var/obj/O)
|
||||
..()
|
||||
var/obj/machinery/flasher/F = O
|
||||
F.id = id
|
||||
|
||||
+700
-700
File diff suppressed because it is too large
Load Diff
+137
-137
@@ -1,137 +1,137 @@
|
||||
/obj/machinery/igniter
|
||||
name = "igniter"
|
||||
desc = "It's useful for igniting plasma."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "igniter0"
|
||||
plane = FLOOR_PLANE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 4
|
||||
max_integrity = 300
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 70, "energy" = 50, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/id = null
|
||||
var/on = FALSE
|
||||
|
||||
/obj/machinery/igniter/incinerator_toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/igniter/incinerator_atmos
|
||||
id = INCINERATOR_ATMOS_IGNITER
|
||||
|
||||
/obj/machinery/igniter/incinerator_syndicatelava
|
||||
id = INCINERATOR_SYNDICATELAVA_IGNITER
|
||||
|
||||
/obj/machinery/igniter/on
|
||||
on = TRUE
|
||||
icon_state = "igniter1"
|
||||
|
||||
/obj/machinery/igniter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
add_fingerprint(user)
|
||||
|
||||
use_power(50)
|
||||
on = !( on )
|
||||
icon_state = "igniter[on]"
|
||||
|
||||
/obj/machinery/igniter/process() //ugh why is this even in process()?
|
||||
if (src.on && !(stat & NOPOWER) )
|
||||
var/turf/location = src.loc
|
||||
if (isturf(location))
|
||||
location.hotspot_expose(700,10,1)
|
||||
return 1
|
||||
|
||||
/obj/machinery/igniter/Initialize()
|
||||
. = ..()
|
||||
icon_state = "igniter[on]"
|
||||
|
||||
/obj/machinery/igniter/power_change()
|
||||
if(!( stat & NOPOWER) )
|
||||
icon_state = "igniter[src.on]"
|
||||
else
|
||||
icon_state = "igniter0"
|
||||
|
||||
// Wall mounted remote-control igniter.
|
||||
|
||||
/obj/machinery/sparker
|
||||
name = "mounted igniter"
|
||||
desc = "A wall-mounted ignition device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "migniter"
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/id = null
|
||||
var/disable = 0
|
||||
var/last_spark = 0
|
||||
var/base_state = "migniter"
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
|
||||
/obj/machinery/sparker/toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/sparker/Initialize()
|
||||
. = ..()
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(2, 1, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
/obj/machinery/sparker/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/sparker/power_change()
|
||||
if ( powered() && disable == 0 )
|
||||
stat &= ~NOPOWER
|
||||
icon_state = "[base_state]"
|
||||
// src.sd_SetLuminosity(2)
|
||||
else
|
||||
stat |= ~NOPOWER
|
||||
icon_state = "[base_state]-p"
|
||||
// src.sd_SetLuminosity(0)
|
||||
|
||||
/obj/machinery/sparker/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/screwdriver))
|
||||
add_fingerprint(user)
|
||||
src.disable = !src.disable
|
||||
if (src.disable)
|
||||
user.visible_message("[user] has disabled \the [src]!", "<span class='notice'>You disable the connection to \the [src].</span>")
|
||||
icon_state = "[base_state]-d"
|
||||
if (!src.disable)
|
||||
user.visible_message("[user] has reconnected \the [src]!", "<span class='notice'>You fix the connection to \the [src].</span>")
|
||||
if(src.powered())
|
||||
icon_state = "[base_state]"
|
||||
else
|
||||
icon_state = "[base_state]-p"
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/sparker/attack_ai()
|
||||
if (anchored)
|
||||
return src.ignite()
|
||||
else
|
||||
return
|
||||
|
||||
/obj/machinery/sparker/proc/ignite()
|
||||
if (!(powered()))
|
||||
return
|
||||
|
||||
if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50))
|
||||
return
|
||||
|
||||
|
||||
flick("[base_state]-spark", src)
|
||||
spark_system.start()
|
||||
last_spark = world.time
|
||||
use_power(1000)
|
||||
var/turf/location = src.loc
|
||||
if (isturf(location))
|
||||
location.hotspot_expose(1000,100,1)
|
||||
return 1
|
||||
|
||||
/obj/machinery/sparker/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
ignite()
|
||||
/obj/machinery/igniter
|
||||
name = "igniter"
|
||||
desc = "It's useful for igniting plasma."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "igniter0"
|
||||
plane = FLOOR_PLANE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 4
|
||||
max_integrity = 300
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 70, "energy" = 50, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/id = null
|
||||
var/on = FALSE
|
||||
|
||||
/obj/machinery/igniter/incinerator_toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/igniter/incinerator_atmos
|
||||
id = INCINERATOR_ATMOS_IGNITER
|
||||
|
||||
/obj/machinery/igniter/incinerator_syndicatelava
|
||||
id = INCINERATOR_SYNDICATELAVA_IGNITER
|
||||
|
||||
/obj/machinery/igniter/on
|
||||
on = TRUE
|
||||
icon_state = "igniter1"
|
||||
|
||||
/obj/machinery/igniter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
add_fingerprint(user)
|
||||
|
||||
use_power(50)
|
||||
on = !( on )
|
||||
icon_state = "igniter[on]"
|
||||
|
||||
/obj/machinery/igniter/process() //ugh why is this even in process()?
|
||||
if (src.on && !(stat & NOPOWER) )
|
||||
var/turf/location = src.loc
|
||||
if (isturf(location))
|
||||
location.hotspot_expose(700,10,1)
|
||||
return 1
|
||||
|
||||
/obj/machinery/igniter/Initialize()
|
||||
. = ..()
|
||||
icon_state = "igniter[on]"
|
||||
|
||||
/obj/machinery/igniter/power_change()
|
||||
if(!( stat & NOPOWER) )
|
||||
icon_state = "igniter[src.on]"
|
||||
else
|
||||
icon_state = "igniter0"
|
||||
|
||||
// Wall mounted remote-control igniter.
|
||||
|
||||
/obj/machinery/sparker
|
||||
name = "mounted igniter"
|
||||
desc = "A wall-mounted ignition device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "migniter"
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/id = null
|
||||
var/disable = 0
|
||||
var/last_spark = 0
|
||||
var/base_state = "migniter"
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
|
||||
/obj/machinery/sparker/toxmix
|
||||
id = INCINERATOR_TOXMIX_IGNITER
|
||||
|
||||
/obj/machinery/sparker/Initialize()
|
||||
. = ..()
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(2, 1, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
/obj/machinery/sparker/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/sparker/power_change()
|
||||
if ( powered() && disable == 0 )
|
||||
stat &= ~NOPOWER
|
||||
icon_state = "[base_state]"
|
||||
// src.sd_SetLuminosity(2)
|
||||
else
|
||||
stat |= ~NOPOWER
|
||||
icon_state = "[base_state]-p"
|
||||
// src.sd_SetLuminosity(0)
|
||||
|
||||
/obj/machinery/sparker/attackby(obj/item/W, mob/user, params)
|
||||
if (istype(W, /obj/item/screwdriver))
|
||||
add_fingerprint(user)
|
||||
src.disable = !src.disable
|
||||
if (src.disable)
|
||||
user.visible_message("[user] has disabled \the [src]!", "<span class='notice'>You disable the connection to \the [src].</span>")
|
||||
icon_state = "[base_state]-d"
|
||||
if (!src.disable)
|
||||
user.visible_message("[user] has reconnected \the [src]!", "<span class='notice'>You fix the connection to \the [src].</span>")
|
||||
if(src.powered())
|
||||
icon_state = "[base_state]"
|
||||
else
|
||||
icon_state = "[base_state]-p"
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/sparker/attack_ai()
|
||||
if (anchored)
|
||||
return src.ignite()
|
||||
else
|
||||
return
|
||||
|
||||
/obj/machinery/sparker/proc/ignite()
|
||||
if (!(powered()))
|
||||
return
|
||||
|
||||
if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50))
|
||||
return
|
||||
|
||||
|
||||
flick("[base_state]-spark", src)
|
||||
spark_system.start()
|
||||
last_spark = world.time
|
||||
use_power(1000)
|
||||
var/turf/location = src.loc
|
||||
if (isturf(location))
|
||||
location.hotspot_expose(1000,100,1)
|
||||
return 1
|
||||
|
||||
/obj/machinery/sparker/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
ignite()
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
// the light switch
|
||||
// can have multiple per area
|
||||
// can also operate on non-loc area through "otherarea" var
|
||||
/obj/machinery/light_switch
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
desc = "Make dark."
|
||||
var/on = TRUE
|
||||
var/area/area = null
|
||||
var/otherarea = null
|
||||
|
||||
/obj/machinery/light_switch/Initialize()
|
||||
. = ..()
|
||||
area = get_area(src)
|
||||
|
||||
if(otherarea)
|
||||
area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
if(!name)
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
on = area.lightswitch
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
if(on)
|
||||
icon_state = "light1"
|
||||
else
|
||||
icon_state = "light0"
|
||||
|
||||
/obj/machinery/light_switch/examine(mob/user)
|
||||
. = ..()
|
||||
. += "It is [on? "on" : "off"]."
|
||||
|
||||
/obj/machinery/light_switch/interact(mob/user)
|
||||
. = ..()
|
||||
on = !on
|
||||
|
||||
area.lightswitch = on
|
||||
area.update_icon()
|
||||
|
||||
for(var/obj/machinery/light_switch/L in area)
|
||||
L.on = on
|
||||
L.update_icon()
|
||||
|
||||
area.power_change()
|
||||
|
||||
/obj/machinery/light_switch/power_change()
|
||||
|
||||
if(!otherarea)
|
||||
if(powered(LIGHT))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
power_change()
|
||||
// the light switch
|
||||
// can have multiple per area
|
||||
// can also operate on non-loc area through "otherarea" var
|
||||
/obj/machinery/light_switch
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
desc = "Make dark."
|
||||
var/on = TRUE
|
||||
var/area/area = null
|
||||
var/otherarea = null
|
||||
|
||||
/obj/machinery/light_switch/Initialize()
|
||||
. = ..()
|
||||
area = get_area(src)
|
||||
|
||||
if(otherarea)
|
||||
area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
if(!name)
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
on = area.lightswitch
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
if(on)
|
||||
icon_state = "light1"
|
||||
else
|
||||
icon_state = "light0"
|
||||
|
||||
/obj/machinery/light_switch/examine(mob/user)
|
||||
. = ..()
|
||||
. += "It is [on? "on" : "off"]."
|
||||
|
||||
/obj/machinery/light_switch/interact(mob/user)
|
||||
. = ..()
|
||||
on = !on
|
||||
|
||||
area.lightswitch = on
|
||||
area.update_icon()
|
||||
|
||||
for(var/obj/machinery/light_switch/L in area)
|
||||
L.on = on
|
||||
L.update_icon()
|
||||
|
||||
area.power_change()
|
||||
|
||||
/obj/machinery/light_switch/power_change()
|
||||
|
||||
if(!otherarea)
|
||||
if(powered(LIGHT))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
power_change()
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
selected_category = href_list["category"]
|
||||
|
||||
if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
|
||||
reagents.del_reagent(href_list["disposeI"])
|
||||
reagents.del_reagent(text2path(href_list["disposeI"]))
|
||||
|
||||
if(href_list["make"])
|
||||
|
||||
@@ -100,10 +100,10 @@
|
||||
return
|
||||
|
||||
|
||||
var/synth_cost = being_built.reagents_list["synthflesh"]*prod_coeff
|
||||
var/synth_cost = being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff
|
||||
var/power = max(2000, synth_cost/5)
|
||||
|
||||
if(reagents.has_reagent("synthflesh", being_built.reagents_list["synthflesh"]*prod_coeff))
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
flick("limbgrower_fill",src)
|
||||
@@ -117,8 +117,8 @@
|
||||
return
|
||||
|
||||
/obj/machinery/limbgrower/proc/build_item()
|
||||
if(reagents.has_reagent("synthflesh", being_built.reagents_list["synthflesh"]*prod_coeff)) //sanity check, if this happens we are in big trouble
|
||||
reagents.remove_reagent("synthflesh",being_built.reagents_list["synthflesh"]*prod_coeff)
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
|
||||
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
|
||||
var/buildpath = being_built.build_path
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
|
||||
build_limb(buildpath)
|
||||
@@ -198,7 +198,7 @@
|
||||
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
dat += "[R.name]: [R.volume]"
|
||||
dat += "<A href='?src=[REF(src)];disposeI=[R.id]'>Purge</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];disposeI=[R]'>Purge</A><BR>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
@@ -208,12 +208,12 @@
|
||||
return dat
|
||||
|
||||
/obj/machinery/limbgrower/proc/can_build(datum/design/D)
|
||||
return (reagents.has_reagent("synthflesh", D.reagents_list["synthflesh"]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
|
||||
return (reagents.has_reagent(/datum/reagent/medicine/synthflesh, D.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
|
||||
|
||||
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
|
||||
var/dat
|
||||
if(D.reagents_list["synthflesh"])
|
||||
dat += "[D.reagents_list["synthflesh"] * prod_coeff] Synthetic flesh "
|
||||
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
|
||||
return dat
|
||||
|
||||
/obj/machinery/limbgrower/emag_act(mob/user)
|
||||
|
||||
+380
-380
@@ -1,380 +1,380 @@
|
||||
// Magnetic attractor, creates variable magnetic fields and attraction.
|
||||
// Can also be used to emit electron/proton beams to create a center of magnetism on another tile
|
||||
|
||||
// tl;dr: it's magnets lol
|
||||
// This was created for firing ranges, but I suppose this could have other applications - Doohl
|
||||
|
||||
/obj/machinery/magnetic_module
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "floor_magnet-f"
|
||||
name = "electromagnetic generator"
|
||||
desc = "A device that uses station power to create points of magnetic energy."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 50
|
||||
|
||||
var/freq = FREQ_MAGNETS // radio frequency
|
||||
var/electricity_level = 1 // intensity of the magnetic pull
|
||||
var/magnetic_field = 1 // the range of magnetic attraction
|
||||
var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something
|
||||
var/turf/center // the center of magnetic attraction
|
||||
var/on = FALSE
|
||||
var/magneting = FALSE
|
||||
|
||||
// x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down
|
||||
var/center_x = 0
|
||||
var/center_y = 0
|
||||
var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer
|
||||
|
||||
/obj/machinery/magnetic_module/Initialize()
|
||||
..()
|
||||
var/turf/T = loc
|
||||
hide(T.intact)
|
||||
center = T
|
||||
SSradio.add_object(src, freq, RADIO_MAGNETS)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/magnetic_module/LateInitialize()
|
||||
magnetic_process()
|
||||
|
||||
/obj/machinery/magnetic_module/Destroy()
|
||||
SSradio.remove_object(src, freq)
|
||||
center = null
|
||||
return ..()
|
||||
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/magnetic_module/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/magnetic_module/update_icon()
|
||||
var/state="floor_magnet"
|
||||
var/onstate=""
|
||||
if(!on)
|
||||
onstate="0"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state][onstate]-f" // if invisible, set icon to faded version
|
||||
// in case of being revealed by T-scanner
|
||||
else
|
||||
icon_state = "[state][onstate]"
|
||||
|
||||
/obj/machinery/magnetic_module/receive_signal(datum/signal/signal)
|
||||
|
||||
var/command = signal.data["command"]
|
||||
var/modifier = signal.data["modifier"]
|
||||
var/signal_code = signal.data["code"]
|
||||
if(command && (signal_code == code))
|
||||
|
||||
Cmd(command, modifier)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/proc/Cmd(command, modifier)
|
||||
|
||||
if(command)
|
||||
switch(command)
|
||||
if("set-electriclevel")
|
||||
if(modifier)
|
||||
electricity_level = modifier
|
||||
if("set-magneticfield")
|
||||
if(modifier)
|
||||
magnetic_field = modifier
|
||||
|
||||
if("add-elec")
|
||||
electricity_level++
|
||||
if(electricity_level > 12)
|
||||
electricity_level = 12
|
||||
if("sub-elec")
|
||||
electricity_level--
|
||||
if(electricity_level <= 0)
|
||||
electricity_level = 1
|
||||
if("add-mag")
|
||||
magnetic_field++
|
||||
if(magnetic_field > 4)
|
||||
magnetic_field = 4
|
||||
if("sub-mag")
|
||||
magnetic_field--
|
||||
if(magnetic_field <= 0)
|
||||
magnetic_field = 1
|
||||
|
||||
if("set-x")
|
||||
if(modifier)
|
||||
center_x = modifier
|
||||
if("set-y")
|
||||
if(modifier)
|
||||
center_y = modifier
|
||||
|
||||
if("N") // NORTH
|
||||
center_y++
|
||||
if("S") // SOUTH
|
||||
center_y--
|
||||
if("E") // EAST
|
||||
center_x++
|
||||
if("W") // WEST
|
||||
center_x--
|
||||
if("C") // CENTER
|
||||
center_x = 0
|
||||
center_y = 0
|
||||
if("R") // RANDOM
|
||||
center_x = rand(-max_dist, max_dist)
|
||||
center_y = rand(-max_dist, max_dist)
|
||||
|
||||
if("set-code")
|
||||
if(modifier)
|
||||
code = modifier
|
||||
if("toggle-power")
|
||||
on = !on
|
||||
|
||||
if(on)
|
||||
INVOKE_ASYNC(src, .proc/magnetic_process)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/process()
|
||||
if(stat & NOPOWER)
|
||||
on = FALSE
|
||||
|
||||
// Sanity checks:
|
||||
if(electricity_level <= 0)
|
||||
electricity_level = 1
|
||||
if(magnetic_field <= 0)
|
||||
magnetic_field = 1
|
||||
|
||||
|
||||
// Limitations:
|
||||
if(abs(center_x) > max_dist)
|
||||
center_x = max_dist
|
||||
if(abs(center_y) > max_dist)
|
||||
center_y = max_dist
|
||||
if(magnetic_field > 4)
|
||||
magnetic_field = 4
|
||||
if(electricity_level > 12)
|
||||
electricity_level = 12
|
||||
|
||||
// Update power usage:
|
||||
if(on)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
active_power_usage = electricity_level*15
|
||||
else
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the magneting
|
||||
if(magneting)
|
||||
return
|
||||
while(on)
|
||||
|
||||
magneting = TRUE
|
||||
center = locate(x+center_x, y+center_y, z)
|
||||
if(center)
|
||||
for(var/obj/M in orange(magnetic_field, center))
|
||||
if(!M.anchored && (M.flags_1 & CONDUCT_1))
|
||||
step_towards(M, center)
|
||||
|
||||
for(var/mob/living/silicon/S in orange(magnetic_field, center))
|
||||
if(isAI(S))
|
||||
continue
|
||||
step_towards(S, center)
|
||||
|
||||
use_power(electricity_level * 5)
|
||||
sleep(13 - electricity_level)
|
||||
|
||||
magneting = FALSE
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller
|
||||
name = "magnetic control console"
|
||||
icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING!
|
||||
icon_state = "airlock_control_standby"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 45
|
||||
var/frequency = FREQ_MAGNETS
|
||||
var/code = 0
|
||||
var/list/magnets = list()
|
||||
var/title = "Magnetic Control Console"
|
||||
var/autolink = 0 // if set to 1, can't probe for other magnets!
|
||||
|
||||
var/pathpos = 1 // position in the path
|
||||
var/path = "w;e;e;w;s;n;n;s" // text path of the magnet
|
||||
var/speed = 1 // lowest = 1, highest = 10
|
||||
var/list/rpath = list() // real path of the magnet, used in iterator
|
||||
|
||||
var/moving = 0 // 1 if scheduled to loop
|
||||
var/looping = 0 // 1 if looping
|
||||
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller/Initialize()
|
||||
. = ..()
|
||||
if(autolink)
|
||||
for(var/obj/machinery/magnetic_module/M in GLOB.machines)
|
||||
if(M.freq == frequency && M.code == code)
|
||||
magnets.Add(M)
|
||||
|
||||
if(path) // check for default path
|
||||
filter_path() // renders rpath
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS)
|
||||
|
||||
/obj/machinery/magnetic_controller/Destroy()
|
||||
SSradio.remove_object(src, frequency)
|
||||
magnets = null
|
||||
rpath = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/magnetic_controller/process()
|
||||
if(magnets.len == 0 && autolink)
|
||||
for(var/obj/machinery/magnetic_module/M in GLOB.machines)
|
||||
if(M.freq == frequency && M.code == code)
|
||||
magnets.Add(M)
|
||||
|
||||
/obj/machinery/magnetic_controller/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<B>Magnetic Control Console</B><BR><BR>"
|
||||
if(!autolink)
|
||||
dat += {"
|
||||
Frequency: <a href='?src=[REF(src)];operation=setfreq'>[frequency]</a><br>
|
||||
Code: <a href='?src=[REF(src)];operation=setfreq'>[code]</a><br>
|
||||
<a href='?src=[REF(src)];operation=probe'>Probe Generators</a><br>
|
||||
"}
|
||||
|
||||
if(magnets.len >= 1)
|
||||
|
||||
dat += "Magnets confirmed: <br>"
|
||||
var/i = 0
|
||||
for(var/obj/machinery/magnetic_module/M in magnets)
|
||||
i++
|
||||
dat += " < \[[i]\] (<a href='?src=[REF(src)];radio-op=togglepower'>[M.on ? "On":"Off"]</a>) | Electricity level: <a href='?src=[REF(src)];radio-op=minuselec'>-</a> [M.electricity_level] <a href='?src=[REF(src)];radio-op=pluselec'>+</a>; Magnetic field: <a href='?src=[REF(src)];radio-op=minusmag'>-</a> [M.magnetic_field] <a href='?src=[REF(src)];radio-op=plusmag'>+</a><br>"
|
||||
|
||||
dat += "<br>Speed: <a href='?src=[REF(src)];operation=minusspeed'>-</a> [speed] <a href='?src=[REF(src)];operation=plusspeed'>+</a><br>"
|
||||
dat += "Path: {<a href='?src=[REF(src)];operation=setpath'>[path]</a>}<br>"
|
||||
dat += "Moving: <a href='?src=[REF(src)];operation=togglemoving'>[moving ? "Enabled":"Disabled"]</a>"
|
||||
|
||||
|
||||
user << browse(dat, "window=magnet;size=400x500")
|
||||
onclose(user, "magnet")
|
||||
|
||||
/obj/machinery/magnetic_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["radio-op"])
|
||||
|
||||
// Prepare signal beforehand, because this is a radio operation
|
||||
var/datum/signal/signal = new(list("code" = code))
|
||||
|
||||
// Apply any necessary commands
|
||||
switch(href_list["radio-op"])
|
||||
if("togglepower")
|
||||
signal.data["command"] = "toggle-power"
|
||||
|
||||
if("minuselec")
|
||||
signal.data["command"] = "sub-elec"
|
||||
if("pluselec")
|
||||
signal.data["command"] = "add-elec"
|
||||
|
||||
if("minusmag")
|
||||
signal.data["command"] = "sub-mag"
|
||||
if("plusmag")
|
||||
signal.data["command"] = "add-mag"
|
||||
|
||||
|
||||
// Broadcast the signal
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
|
||||
|
||||
spawn(1)
|
||||
updateUsrDialog() // pretty sure this increases responsiveness
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
if("plusspeed")
|
||||
speed ++
|
||||
if(speed > 10)
|
||||
speed = 10
|
||||
if("minusspeed")
|
||||
speed --
|
||||
if(speed <= 0)
|
||||
speed = 1
|
||||
if("setpath")
|
||||
var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN)
|
||||
if(newpath && newpath != "")
|
||||
moving = 0 // stop moving
|
||||
path = newpath
|
||||
pathpos = 1 // reset position
|
||||
filter_path() // renders rpath
|
||||
|
||||
if("togglemoving")
|
||||
moving = !moving
|
||||
if(moving)
|
||||
spawn() MagnetMove()
|
||||
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/magnetic_controller/proc/MagnetMove()
|
||||
if(looping)
|
||||
return
|
||||
|
||||
while(moving && rpath.len >= 1)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
break
|
||||
|
||||
looping = 1
|
||||
|
||||
// Prepare the radio signal
|
||||
var/datum/signal/signal = new(list("code" = code))
|
||||
|
||||
if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list!
|
||||
pathpos = 1
|
||||
|
||||
var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive
|
||||
|
||||
if(!(nextmove in list("N","S","E","W","C","R")))
|
||||
// N, S, E, W are directional
|
||||
// C is center
|
||||
// R is random (in magnetic field's bounds)
|
||||
qdel(signal)
|
||||
break // break the loop if the character located is invalid
|
||||
|
||||
signal.data["command"] = nextmove
|
||||
|
||||
|
||||
pathpos++ // increase iterator
|
||||
|
||||
// Broadcast the signal
|
||||
spawn()
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
|
||||
|
||||
if(speed == 10)
|
||||
sleep(1)
|
||||
else
|
||||
sleep(12-speed)
|
||||
|
||||
looping = 0
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller/proc/filter_path()
|
||||
// Generates the rpath variable using the path string, think of this as "string2list"
|
||||
// Doesn't use params2list() because of the akward way it stacks entities
|
||||
rpath = list() // clear rpath
|
||||
var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length
|
||||
|
||||
for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path
|
||||
|
||||
var/nextchar = copytext(path, i, i+1) // find next character
|
||||
|
||||
if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore
|
||||
rpath += copytext(path, i, i+1) // else, add to list
|
||||
|
||||
// there doesn't HAVE to be separators but it makes paths syntatically visible
|
||||
// Magnetic attractor, creates variable magnetic fields and attraction.
|
||||
// Can also be used to emit electron/proton beams to create a center of magnetism on another tile
|
||||
|
||||
// tl;dr: it's magnets lol
|
||||
// This was created for firing ranges, but I suppose this could have other applications - Doohl
|
||||
|
||||
/obj/machinery/magnetic_module
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "floor_magnet-f"
|
||||
name = "electromagnetic generator"
|
||||
desc = "A device that uses station power to create points of magnetic energy."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 50
|
||||
|
||||
var/freq = FREQ_MAGNETS // radio frequency
|
||||
var/electricity_level = 1 // intensity of the magnetic pull
|
||||
var/magnetic_field = 1 // the range of magnetic attraction
|
||||
var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something
|
||||
var/turf/center // the center of magnetic attraction
|
||||
var/on = FALSE
|
||||
var/magneting = FALSE
|
||||
|
||||
// x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down
|
||||
var/center_x = 0
|
||||
var/center_y = 0
|
||||
var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer
|
||||
|
||||
/obj/machinery/magnetic_module/Initialize()
|
||||
..()
|
||||
var/turf/T = loc
|
||||
hide(T.intact)
|
||||
center = T
|
||||
SSradio.add_object(src, freq, RADIO_MAGNETS)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/magnetic_module/LateInitialize()
|
||||
magnetic_process()
|
||||
|
||||
/obj/machinery/magnetic_module/Destroy()
|
||||
SSradio.remove_object(src, freq)
|
||||
center = null
|
||||
return ..()
|
||||
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/magnetic_module/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/magnetic_module/update_icon()
|
||||
var/state="floor_magnet"
|
||||
var/onstate=""
|
||||
if(!on)
|
||||
onstate="0"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state][onstate]-f" // if invisible, set icon to faded version
|
||||
// in case of being revealed by T-scanner
|
||||
else
|
||||
icon_state = "[state][onstate]"
|
||||
|
||||
/obj/machinery/magnetic_module/receive_signal(datum/signal/signal)
|
||||
|
||||
var/command = signal.data["command"]
|
||||
var/modifier = signal.data["modifier"]
|
||||
var/signal_code = signal.data["code"]
|
||||
if(command && (signal_code == code))
|
||||
|
||||
Cmd(command, modifier)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/proc/Cmd(command, modifier)
|
||||
|
||||
if(command)
|
||||
switch(command)
|
||||
if("set-electriclevel")
|
||||
if(modifier)
|
||||
electricity_level = modifier
|
||||
if("set-magneticfield")
|
||||
if(modifier)
|
||||
magnetic_field = modifier
|
||||
|
||||
if("add-elec")
|
||||
electricity_level++
|
||||
if(electricity_level > 12)
|
||||
electricity_level = 12
|
||||
if("sub-elec")
|
||||
electricity_level--
|
||||
if(electricity_level <= 0)
|
||||
electricity_level = 1
|
||||
if("add-mag")
|
||||
magnetic_field++
|
||||
if(magnetic_field > 4)
|
||||
magnetic_field = 4
|
||||
if("sub-mag")
|
||||
magnetic_field--
|
||||
if(magnetic_field <= 0)
|
||||
magnetic_field = 1
|
||||
|
||||
if("set-x")
|
||||
if(modifier)
|
||||
center_x = modifier
|
||||
if("set-y")
|
||||
if(modifier)
|
||||
center_y = modifier
|
||||
|
||||
if("N") // NORTH
|
||||
center_y++
|
||||
if("S") // SOUTH
|
||||
center_y--
|
||||
if("E") // EAST
|
||||
center_x++
|
||||
if("W") // WEST
|
||||
center_x--
|
||||
if("C") // CENTER
|
||||
center_x = 0
|
||||
center_y = 0
|
||||
if("R") // RANDOM
|
||||
center_x = rand(-max_dist, max_dist)
|
||||
center_y = rand(-max_dist, max_dist)
|
||||
|
||||
if("set-code")
|
||||
if(modifier)
|
||||
code = modifier
|
||||
if("toggle-power")
|
||||
on = !on
|
||||
|
||||
if(on)
|
||||
INVOKE_ASYNC(src, .proc/magnetic_process)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/process()
|
||||
if(stat & NOPOWER)
|
||||
on = FALSE
|
||||
|
||||
// Sanity checks:
|
||||
if(electricity_level <= 0)
|
||||
electricity_level = 1
|
||||
if(magnetic_field <= 0)
|
||||
magnetic_field = 1
|
||||
|
||||
|
||||
// Limitations:
|
||||
if(abs(center_x) > max_dist)
|
||||
center_x = max_dist
|
||||
if(abs(center_y) > max_dist)
|
||||
center_y = max_dist
|
||||
if(magnetic_field > 4)
|
||||
magnetic_field = 4
|
||||
if(electricity_level > 12)
|
||||
electricity_level = 12
|
||||
|
||||
// Update power usage:
|
||||
if(on)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
active_power_usage = electricity_level*15
|
||||
else
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the magneting
|
||||
if(magneting)
|
||||
return
|
||||
while(on)
|
||||
|
||||
magneting = TRUE
|
||||
center = locate(x+center_x, y+center_y, z)
|
||||
if(center)
|
||||
for(var/obj/M in orange(magnetic_field, center))
|
||||
if(!M.anchored && (M.flags_1 & CONDUCT_1))
|
||||
step_towards(M, center)
|
||||
|
||||
for(var/mob/living/silicon/S in orange(magnetic_field, center))
|
||||
if(isAI(S))
|
||||
continue
|
||||
step_towards(S, center)
|
||||
|
||||
use_power(electricity_level * 5)
|
||||
sleep(13 - electricity_level)
|
||||
|
||||
magneting = FALSE
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller
|
||||
name = "magnetic control console"
|
||||
icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING!
|
||||
icon_state = "airlock_control_standby"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 45
|
||||
var/frequency = FREQ_MAGNETS
|
||||
var/code = 0
|
||||
var/list/magnets = list()
|
||||
var/title = "Magnetic Control Console"
|
||||
var/autolink = 0 // if set to 1, can't probe for other magnets!
|
||||
|
||||
var/pathpos = 1 // position in the path
|
||||
var/path = "w;e;e;w;s;n;n;s" // text path of the magnet
|
||||
var/speed = 1 // lowest = 1, highest = 10
|
||||
var/list/rpath = list() // real path of the magnet, used in iterator
|
||||
|
||||
var/moving = 0 // 1 if scheduled to loop
|
||||
var/looping = 0 // 1 if looping
|
||||
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller/Initialize()
|
||||
. = ..()
|
||||
if(autolink)
|
||||
for(var/obj/machinery/magnetic_module/M in GLOB.machines)
|
||||
if(M.freq == frequency && M.code == code)
|
||||
magnets.Add(M)
|
||||
|
||||
if(path) // check for default path
|
||||
filter_path() // renders rpath
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS)
|
||||
|
||||
/obj/machinery/magnetic_controller/Destroy()
|
||||
SSradio.remove_object(src, frequency)
|
||||
magnets = null
|
||||
rpath = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/magnetic_controller/process()
|
||||
if(magnets.len == 0 && autolink)
|
||||
for(var/obj/machinery/magnetic_module/M in GLOB.machines)
|
||||
if(M.freq == frequency && M.code == code)
|
||||
magnets.Add(M)
|
||||
|
||||
/obj/machinery/magnetic_controller/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<B>Magnetic Control Console</B><BR><BR>"
|
||||
if(!autolink)
|
||||
dat += {"
|
||||
Frequency: <a href='?src=[REF(src)];operation=setfreq'>[frequency]</a><br>
|
||||
Code: <a href='?src=[REF(src)];operation=setfreq'>[code]</a><br>
|
||||
<a href='?src=[REF(src)];operation=probe'>Probe Generators</a><br>
|
||||
"}
|
||||
|
||||
if(magnets.len >= 1)
|
||||
|
||||
dat += "Magnets confirmed: <br>"
|
||||
var/i = 0
|
||||
for(var/obj/machinery/magnetic_module/M in magnets)
|
||||
i++
|
||||
dat += " < \[[i]\] (<a href='?src=[REF(src)];radio-op=togglepower'>[M.on ? "On":"Off"]</a>) | Electricity level: <a href='?src=[REF(src)];radio-op=minuselec'>-</a> [M.electricity_level] <a href='?src=[REF(src)];radio-op=pluselec'>+</a>; Magnetic field: <a href='?src=[REF(src)];radio-op=minusmag'>-</a> [M.magnetic_field] <a href='?src=[REF(src)];radio-op=plusmag'>+</a><br>"
|
||||
|
||||
dat += "<br>Speed: <a href='?src=[REF(src)];operation=minusspeed'>-</a> [speed] <a href='?src=[REF(src)];operation=plusspeed'>+</a><br>"
|
||||
dat += "Path: {<a href='?src=[REF(src)];operation=setpath'>[path]</a>}<br>"
|
||||
dat += "Moving: <a href='?src=[REF(src)];operation=togglemoving'>[moving ? "Enabled":"Disabled"]</a>"
|
||||
|
||||
|
||||
user << browse(dat, "window=magnet;size=400x500")
|
||||
onclose(user, "magnet")
|
||||
|
||||
/obj/machinery/magnetic_controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["radio-op"])
|
||||
|
||||
// Prepare signal beforehand, because this is a radio operation
|
||||
var/datum/signal/signal = new(list("code" = code))
|
||||
|
||||
// Apply any necessary commands
|
||||
switch(href_list["radio-op"])
|
||||
if("togglepower")
|
||||
signal.data["command"] = "toggle-power"
|
||||
|
||||
if("minuselec")
|
||||
signal.data["command"] = "sub-elec"
|
||||
if("pluselec")
|
||||
signal.data["command"] = "add-elec"
|
||||
|
||||
if("minusmag")
|
||||
signal.data["command"] = "sub-mag"
|
||||
if("plusmag")
|
||||
signal.data["command"] = "add-mag"
|
||||
|
||||
|
||||
// Broadcast the signal
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
|
||||
|
||||
spawn(1)
|
||||
updateUsrDialog() // pretty sure this increases responsiveness
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
if("plusspeed")
|
||||
speed ++
|
||||
if(speed > 10)
|
||||
speed = 10
|
||||
if("minusspeed")
|
||||
speed --
|
||||
if(speed <= 0)
|
||||
speed = 1
|
||||
if("setpath")
|
||||
var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN)
|
||||
if(newpath && newpath != "")
|
||||
moving = 0 // stop moving
|
||||
path = newpath
|
||||
pathpos = 1 // reset position
|
||||
filter_path() // renders rpath
|
||||
|
||||
if("togglemoving")
|
||||
moving = !moving
|
||||
if(moving)
|
||||
spawn() MagnetMove()
|
||||
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/magnetic_controller/proc/MagnetMove()
|
||||
if(looping)
|
||||
return
|
||||
|
||||
while(moving && rpath.len >= 1)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
break
|
||||
|
||||
looping = 1
|
||||
|
||||
// Prepare the radio signal
|
||||
var/datum/signal/signal = new(list("code" = code))
|
||||
|
||||
if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list!
|
||||
pathpos = 1
|
||||
|
||||
var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive
|
||||
|
||||
if(!(nextmove in list("N","S","E","W","C","R")))
|
||||
// N, S, E, W are directional
|
||||
// C is center
|
||||
// R is random (in magnetic field's bounds)
|
||||
qdel(signal)
|
||||
break // break the loop if the character located is invalid
|
||||
|
||||
signal.data["command"] = nextmove
|
||||
|
||||
|
||||
pathpos++ // increase iterator
|
||||
|
||||
// Broadcast the signal
|
||||
spawn()
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
|
||||
|
||||
if(speed == 10)
|
||||
sleep(1)
|
||||
else
|
||||
sleep(12-speed)
|
||||
|
||||
looping = 0
|
||||
|
||||
|
||||
/obj/machinery/magnetic_controller/proc/filter_path()
|
||||
// Generates the rpath variable using the path string, think of this as "string2list"
|
||||
// Doesn't use params2list() because of the akward way it stacks entities
|
||||
rpath = list() // clear rpath
|
||||
var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length
|
||||
|
||||
for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path
|
||||
|
||||
var/nextchar = copytext(path, i, i+1) // find next character
|
||||
|
||||
if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore
|
||||
rpath += copytext(path, i, i+1) // else, add to list
|
||||
|
||||
// there doesn't HAVE to be separators but it makes paths syntatically visible
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
/obj/machinery/mass_driver
|
||||
name = "mass driver"
|
||||
desc = "The finest in spring-loaded piston toy technology, now on a space station near you."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mass_driver"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 50
|
||||
var/power = 1
|
||||
var/code = 1
|
||||
var/id = 1
|
||||
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/proc/drive(amount)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
use_power(500)
|
||||
var/O_limit
|
||||
var/atom/target = get_edge_target_turf(src, dir)
|
||||
for(var/atom/movable/O in loc)
|
||||
if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
|
||||
O_limit++
|
||||
if(O_limit >= 20)
|
||||
audible_message("<span class='notice'>[src] lets out a screech, it doesn't seem to be able to handle the load.</span>")
|
||||
break
|
||||
use_power(500)
|
||||
O.throw_at(target, drive_range * power, power)
|
||||
flick("mass_driver1", src)
|
||||
|
||||
|
||||
/obj/machinery/mass_driver/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
drive()
|
||||
/obj/machinery/mass_driver
|
||||
name = "mass driver"
|
||||
desc = "The finest in spring-loaded piston toy technology, now on a space station near you."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mass_driver"
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 50
|
||||
var/power = 1
|
||||
var/code = 1
|
||||
var/id = 1
|
||||
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/proc/drive(amount)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
use_power(500)
|
||||
var/O_limit
|
||||
var/atom/target = get_edge_target_turf(src, dir)
|
||||
for(var/atom/movable/O in loc)
|
||||
if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
|
||||
O_limit++
|
||||
if(O_limit >= 20)
|
||||
audible_message("<span class='notice'>[src] lets out a screech, it doesn't seem to be able to handle the load.</span>")
|
||||
break
|
||||
use_power(500)
|
||||
O.throw_at(target, drive_range * power, power)
|
||||
flick("mass_driver1", src)
|
||||
|
||||
|
||||
/obj/machinery/mass_driver/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
drive()
|
||||
|
||||
+214
-214
@@ -1,214 +1,214 @@
|
||||
// Navigation beacon for AI robots
|
||||
// No longer exists on the radio controller, it is managed by a global list.
|
||||
|
||||
/obj/machinery/navbeacon
|
||||
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "navbeacon0-f"
|
||||
name = "navigation beacon"
|
||||
desc = "A radio beacon used for bot navigation."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
max_integrity = 500
|
||||
armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 70, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
|
||||
|
||||
var/open = FALSE // true if cover is open
|
||||
var/locked = TRUE // true if controls are locked
|
||||
var/freq = FREQ_NAV_BEACON
|
||||
var/location = "" // location response text
|
||||
var/list/codes // assoc. list of transponder codes
|
||||
var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
|
||||
|
||||
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
|
||||
|
||||
/obj/machinery/navbeacon/Initialize()
|
||||
. = ..()
|
||||
|
||||
set_codes()
|
||||
|
||||
var/turf/T = loc
|
||||
hide(T.intact)
|
||||
if(codes["patrol"])
|
||||
if(!GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] = list()
|
||||
GLOB.navbeacons["[z]"] += src //Register with the patrol list!
|
||||
if(codes["delivery"])
|
||||
GLOB.deliverybeacons += src
|
||||
GLOB.deliverybeacontags += location
|
||||
|
||||
/obj/machinery/navbeacon/Destroy()
|
||||
if (GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
|
||||
GLOB.deliverybeacons -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/navbeacon/onTransitZ(old_z, new_z)
|
||||
if (GLOB.navbeacons["[old_z]"])
|
||||
GLOB.navbeacons["[old_z]"] -= src
|
||||
if (GLOB.navbeacons["[new_z]"])
|
||||
GLOB.navbeacons["[new_z]"] += src
|
||||
..()
|
||||
|
||||
// set the transponder codes assoc list from codes_txt
|
||||
/obj/machinery/navbeacon/proc/set_codes()
|
||||
if(!codes_txt)
|
||||
return
|
||||
|
||||
codes = new()
|
||||
|
||||
var/list/entries = splittext(codes_txt, ";") // entries are separated by semicolons
|
||||
|
||||
for(var/e in entries)
|
||||
var/index = findtext(e, "=") // format is "key=value"
|
||||
if(index)
|
||||
var/key = copytext(e, 1, index)
|
||||
var/val = copytext(e, index+1)
|
||||
codes[key] = val
|
||||
else
|
||||
codes[e] = "1"
|
||||
|
||||
|
||||
// called when turf state changes
|
||||
// hide the object if turf is intact
|
||||
/obj/machinery/navbeacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/navbeacon/update_icon()
|
||||
var/state="navbeacon[open]"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state]-f" // if invisible, set icon to faded version
|
||||
// in case revealed by T-scanner
|
||||
else
|
||||
icon_state = "[state]"
|
||||
|
||||
/obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params)
|
||||
var/turf/T = loc
|
||||
if(T.intact)
|
||||
return // prevent intraction when T-scanner revealed
|
||||
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
open = !open
|
||||
|
||||
user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "<span class='notice'>You [open ? "open" : "close"] the beacon's cover.</span>")
|
||||
|
||||
update_icon()
|
||||
|
||||
else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda))
|
||||
if(open)
|
||||
if (src.allowed(user))
|
||||
src.locked = !src.locked
|
||||
to_chat(user, "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
updateDialog()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You must open the cover first!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/navbeacon/attack_ai(mob/user)
|
||||
interact(user, 1)
|
||||
|
||||
/obj/machinery/navbeacon/attack_paw()
|
||||
return
|
||||
|
||||
/obj/machinery/navbeacon/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/ai = isAI(user)
|
||||
var/turf/T = loc
|
||||
if(T.intact)
|
||||
return // prevent intraction when T-scanner revealed
|
||||
|
||||
if(!open && !ai) // can't alter controls if not open, unless you're an AI
|
||||
to_chat(user, "<span class='warning'>The beacon's control cover is closed!</span>")
|
||||
return
|
||||
|
||||
|
||||
var/t
|
||||
|
||||
if(locked && !ai)
|
||||
t = {"<TT><B>Navigation Beacon</B><HR><BR>
|
||||
<i>(swipe card to unlock controls)</i><BR>
|
||||
Location: [location ? location : "(none)"]</A><BR>
|
||||
Transponder Codes:<UL>"}
|
||||
|
||||
for(var/key in codes)
|
||||
t += "<LI>[key] ... [codes[key]]"
|
||||
t+= "<UL></TT>"
|
||||
|
||||
else
|
||||
|
||||
t = {"<TT><B>Navigation Beacon</B><HR><BR>
|
||||
<i>(swipe card to lock controls)</i><BR>
|
||||
|
||||
<HR>
|
||||
Location: <A href='byond://?src=[REF(src)];locedit=1'>[location ? location : "None"]</A><BR>
|
||||
Transponder Codes:<UL>"}
|
||||
|
||||
for(var/key in codes)
|
||||
t += "<LI>[key] ... [codes[key]]"
|
||||
t += " <A href='byond://?src=[REF(src)];edit=1;code=[key]'>Edit</A>"
|
||||
t += " <A href='byond://?src=[REF(src)];delete=1;code=[key]'>Delete</A><BR>"
|
||||
t += " <A href='byond://?src=[REF(src)];add=1;'>Add New</A><BR>"
|
||||
t+= "<UL></TT>"
|
||||
|
||||
var/datum/browser/popup = new(user, "navbeacon", "Navigation Beacon", 300, 400)
|
||||
popup.set_content(t)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/navbeacon/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(open && !locked)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["locedit"])
|
||||
var/newloc = copytext(sanitize(input("Enter New Location", "Navigation Beacon", location) as text|null),1,MAX_MESSAGE_LEN)
|
||||
if(newloc)
|
||||
location = newloc
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["edit"])
|
||||
var/codekey = href_list["code"]
|
||||
|
||||
var/newkey = stripped_input(usr, "Enter Transponder Code Key", "Navigation Beacon", codekey)
|
||||
if(!newkey)
|
||||
return
|
||||
|
||||
var/codeval = codes[codekey]
|
||||
var/newval = stripped_input(usr, "Enter Transponder Code Value", "Navigation Beacon", codeval)
|
||||
if(!newval)
|
||||
newval = codekey
|
||||
return
|
||||
|
||||
codes.Remove(codekey)
|
||||
codes[newkey] = newval
|
||||
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["delete"])
|
||||
var/codekey = href_list["code"]
|
||||
codes.Remove(codekey)
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["add"])
|
||||
|
||||
var/newkey = stripped_input(usr, "Enter New Transponder Code Key", "Navigation Beacon")
|
||||
if(!newkey)
|
||||
return
|
||||
|
||||
var/newval = stripped_input(usr, "Enter New Transponder Code Value", "Navigation Beacon")
|
||||
if(!newval)
|
||||
newval = "1"
|
||||
return
|
||||
|
||||
if(!codes)
|
||||
codes = new()
|
||||
|
||||
codes[newkey] = newval
|
||||
|
||||
updateDialog()
|
||||
// Navigation beacon for AI robots
|
||||
// No longer exists on the radio controller, it is managed by a global list.
|
||||
|
||||
/obj/machinery/navbeacon
|
||||
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "navbeacon0-f"
|
||||
name = "navigation beacon"
|
||||
desc = "A radio beacon used for bot navigation."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
max_integrity = 500
|
||||
armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 70, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
|
||||
|
||||
var/open = FALSE // true if cover is open
|
||||
var/locked = TRUE // true if controls are locked
|
||||
var/freq = FREQ_NAV_BEACON
|
||||
var/location = "" // location response text
|
||||
var/list/codes // assoc. list of transponder codes
|
||||
var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
|
||||
|
||||
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
|
||||
|
||||
/obj/machinery/navbeacon/Initialize()
|
||||
. = ..()
|
||||
|
||||
set_codes()
|
||||
|
||||
var/turf/T = loc
|
||||
hide(T.intact)
|
||||
if(codes["patrol"])
|
||||
if(!GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] = list()
|
||||
GLOB.navbeacons["[z]"] += src //Register with the patrol list!
|
||||
if(codes["delivery"])
|
||||
GLOB.deliverybeacons += src
|
||||
GLOB.deliverybeacontags += location
|
||||
|
||||
/obj/machinery/navbeacon/Destroy()
|
||||
if (GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
|
||||
GLOB.deliverybeacons -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/navbeacon/onTransitZ(old_z, new_z)
|
||||
if (GLOB.navbeacons["[old_z]"])
|
||||
GLOB.navbeacons["[old_z]"] -= src
|
||||
if (GLOB.navbeacons["[new_z]"])
|
||||
GLOB.navbeacons["[new_z]"] += src
|
||||
..()
|
||||
|
||||
// set the transponder codes assoc list from codes_txt
|
||||
/obj/machinery/navbeacon/proc/set_codes()
|
||||
if(!codes_txt)
|
||||
return
|
||||
|
||||
codes = new()
|
||||
|
||||
var/list/entries = splittext(codes_txt, ";") // entries are separated by semicolons
|
||||
|
||||
for(var/e in entries)
|
||||
var/index = findtext(e, "=") // format is "key=value"
|
||||
if(index)
|
||||
var/key = copytext(e, 1, index)
|
||||
var/val = copytext(e, index+1)
|
||||
codes[key] = val
|
||||
else
|
||||
codes[e] = "1"
|
||||
|
||||
|
||||
// called when turf state changes
|
||||
// hide the object if turf is intact
|
||||
/obj/machinery/navbeacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/navbeacon/update_icon()
|
||||
var/state="navbeacon[open]"
|
||||
|
||||
if(invisibility)
|
||||
icon_state = "[state]-f" // if invisible, set icon to faded version
|
||||
// in case revealed by T-scanner
|
||||
else
|
||||
icon_state = "[state]"
|
||||
|
||||
/obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params)
|
||||
var/turf/T = loc
|
||||
if(T.intact)
|
||||
return // prevent intraction when T-scanner revealed
|
||||
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
open = !open
|
||||
|
||||
user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "<span class='notice'>You [open ? "open" : "close"] the beacon's cover.</span>")
|
||||
|
||||
update_icon()
|
||||
|
||||
else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda))
|
||||
if(open)
|
||||
if (src.allowed(user))
|
||||
src.locked = !src.locked
|
||||
to_chat(user, "<span class='notice'>Controls are now [src.locked ? "locked" : "unlocked"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
updateDialog()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You must open the cover first!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/navbeacon/attack_ai(mob/user)
|
||||
interact(user, 1)
|
||||
|
||||
/obj/machinery/navbeacon/attack_paw()
|
||||
return
|
||||
|
||||
/obj/machinery/navbeacon/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/ai = isAI(user)
|
||||
var/turf/T = loc
|
||||
if(T.intact)
|
||||
return // prevent intraction when T-scanner revealed
|
||||
|
||||
if(!open && !ai) // can't alter controls if not open, unless you're an AI
|
||||
to_chat(user, "<span class='warning'>The beacon's control cover is closed!</span>")
|
||||
return
|
||||
|
||||
|
||||
var/t
|
||||
|
||||
if(locked && !ai)
|
||||
t = {"<TT><B>Navigation Beacon</B><HR><BR>
|
||||
<i>(swipe card to unlock controls)</i><BR>
|
||||
Location: [location ? location : "(none)"]</A><BR>
|
||||
Transponder Codes:<UL>"}
|
||||
|
||||
for(var/key in codes)
|
||||
t += "<LI>[key] ... [codes[key]]"
|
||||
t+= "<UL></TT>"
|
||||
|
||||
else
|
||||
|
||||
t = {"<TT><B>Navigation Beacon</B><HR><BR>
|
||||
<i>(swipe card to lock controls)</i><BR>
|
||||
|
||||
<HR>
|
||||
Location: <A href='byond://?src=[REF(src)];locedit=1'>[location ? location : "None"]</A><BR>
|
||||
Transponder Codes:<UL>"}
|
||||
|
||||
for(var/key in codes)
|
||||
t += "<LI>[key] ... [codes[key]]"
|
||||
t += " <A href='byond://?src=[REF(src)];edit=1;code=[key]'>Edit</A>"
|
||||
t += " <A href='byond://?src=[REF(src)];delete=1;code=[key]'>Delete</A><BR>"
|
||||
t += " <A href='byond://?src=[REF(src)];add=1;'>Add New</A><BR>"
|
||||
t+= "<UL></TT>"
|
||||
|
||||
var/datum/browser/popup = new(user, "navbeacon", "Navigation Beacon", 300, 400)
|
||||
popup.set_content(t)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/navbeacon/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(open && !locked)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["locedit"])
|
||||
var/newloc = copytext(sanitize(input("Enter New Location", "Navigation Beacon", location) as text|null),1,MAX_MESSAGE_LEN)
|
||||
if(newloc)
|
||||
location = newloc
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["edit"])
|
||||
var/codekey = href_list["code"]
|
||||
|
||||
var/newkey = stripped_input(usr, "Enter Transponder Code Key", "Navigation Beacon", codekey)
|
||||
if(!newkey)
|
||||
return
|
||||
|
||||
var/codeval = codes[codekey]
|
||||
var/newval = stripped_input(usr, "Enter Transponder Code Value", "Navigation Beacon", codeval)
|
||||
if(!newval)
|
||||
newval = codekey
|
||||
return
|
||||
|
||||
codes.Remove(codekey)
|
||||
codes[newkey] = newval
|
||||
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["delete"])
|
||||
var/codekey = href_list["code"]
|
||||
codes.Remove(codekey)
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["add"])
|
||||
|
||||
var/newkey = stripped_input(usr, "Enter New Transponder Code Key", "Navigation Beacon")
|
||||
if(!newkey)
|
||||
return
|
||||
|
||||
var/newval = stripped_input(usr, "Enter New Transponder Code Value", "Navigation Beacon")
|
||||
if(!newval)
|
||||
newval = "1"
|
||||
return
|
||||
|
||||
if(!codes)
|
||||
codes = new()
|
||||
|
||||
codes[newkey] = newval
|
||||
|
||||
updateDialog()
|
||||
|
||||
@@ -1,236 +1,236 @@
|
||||
/*CONTENTS
|
||||
Buildable pipes
|
||||
Buildable meters
|
||||
*/
|
||||
|
||||
//construction defines are in __defines/pipe_construction.dm
|
||||
//update those defines ANY TIME an atmos path is changed...
|
||||
//...otherwise construction will stop working
|
||||
|
||||
/obj/item/pipe
|
||||
name = "pipe"
|
||||
desc = "A pipe."
|
||||
var/pipe_type
|
||||
var/pipename
|
||||
force = 7
|
||||
throwforce = 7
|
||||
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
icon_state = "simple"
|
||||
item_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
level = 2
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
var/RPD_type
|
||||
|
||||
/obj/item/pipe/directional
|
||||
RPD_type = PIPE_UNARY
|
||||
/obj/item/pipe/binary
|
||||
RPD_type = PIPE_STRAIGHT
|
||||
/obj/item/pipe/binary/bendable
|
||||
RPD_type = PIPE_BENDABLE
|
||||
/obj/item/pipe/trinary
|
||||
RPD_type = PIPE_TRINARY
|
||||
/obj/item/pipe/trinary/flippable
|
||||
RPD_type = PIPE_TRIN_M
|
||||
var/flipped = FALSE
|
||||
/obj/item/pipe/quaternary
|
||||
RPD_type = PIPE_ONEDIR
|
||||
|
||||
/obj/item/pipe/ComponentInitialize()
|
||||
//Flipping handled manually due to custom handling for trinary pipes
|
||||
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE)
|
||||
|
||||
/obj/item/pipe/Initialize(mapload, _pipe_type, _dir, obj/machinery/atmospherics/make_from)
|
||||
if(make_from)
|
||||
make_from_existing(make_from)
|
||||
else
|
||||
pipe_type = _pipe_type
|
||||
setDir(_dir)
|
||||
|
||||
update()
|
||||
pixel_x += rand(-5, 5)
|
||||
pixel_y += rand(-5, 5)
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from)
|
||||
setDir(make_from.dir)
|
||||
pipename = make_from.name
|
||||
add_atom_colour(make_from.color, FIXED_COLOUR_PRIORITY)
|
||||
pipe_type = make_from.type
|
||||
|
||||
/obj/item/pipe/trinary/flippable/make_from_existing(obj/machinery/atmospherics/components/trinary/make_from)
|
||||
..()
|
||||
if(make_from.flipped)
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/dropped()
|
||||
if(loc)
|
||||
setPipingLayer(piping_layer)
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT)
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
|
||||
if(initial(fakeA.pipe_flags) & PIPING_ALL_LAYER)
|
||||
new_layer = PIPING_LAYER_DEFAULT
|
||||
piping_layer = new_layer
|
||||
|
||||
pixel_x += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE)
|
||||
|
||||
/obj/item/pipe/proc/update()
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
name = "[initial(fakeA.name)] fitting"
|
||||
icon_state = initial(fakeA.pipe_state)
|
||||
if(ispath(pipe_type,/obj/machinery/atmospherics/pipe/heat_exchanging))
|
||||
resistance_flags |= FIRE_PROOF | LAVA_PROOF
|
||||
|
||||
/obj/item/pipe/verb/flip()
|
||||
set category = "Object"
|
||||
set name = "Flip Pipe"
|
||||
set src in view(1)
|
||||
|
||||
if ( usr.stat || usr.restrained() || !usr.canmove )
|
||||
return
|
||||
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/proc/do_a_flip()
|
||||
setDir(turn(dir, -180))
|
||||
|
||||
/obj/item/pipe/trinary/flippable/do_a_flip()
|
||||
setDir(turn(dir, flipped ? 45 : -45))
|
||||
flipped = !flipped
|
||||
|
||||
/obj/item/pipe/Move()
|
||||
var/old_dir = dir
|
||||
..()
|
||||
setDir(old_dir) //pipes changing direction when moved is just annoying and buggy
|
||||
|
||||
// Convert dir of fitting into dir of built component
|
||||
/obj/item/pipe/proc/fixed_dir()
|
||||
return dir
|
||||
|
||||
/obj/item/pipe/binary/fixed_dir()
|
||||
. = dir
|
||||
if(dir == SOUTH)
|
||||
. = NORTH
|
||||
else if(dir == WEST)
|
||||
. = EAST
|
||||
|
||||
/obj/item/pipe/trinary/flippable/fixed_dir()
|
||||
. = dir
|
||||
if(dir in GLOB.diagonals)
|
||||
. = turn(dir, 45)
|
||||
|
||||
/obj/item/pipe/attack_self(mob/user)
|
||||
setDir(turn(dir,-90))
|
||||
|
||||
/obj/item/pipe/wrench_act(mob/living/user, obj/item/wrench/W)
|
||||
if(!isturf(loc))
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
var/flags = initial(fakeA.pipe_flags)
|
||||
for(var/obj/machinery/atmospherics/M in loc)
|
||||
if((M.pipe_flags & flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
|
||||
to_chat(user, "<span class='warning'>Something is hogging the tile!</span>")
|
||||
return TRUE
|
||||
if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) //don't continue if either pipe goes across all layers
|
||||
continue
|
||||
if(M.GetInitDirections() & SSair.get_init_dirs(pipe_type, fixed_dir())) // matches at least one direction on either type of pipe
|
||||
to_chat(user, "<span class='warning'>There is already a pipe at that location!</span>")
|
||||
return TRUE
|
||||
// no conflicts found
|
||||
|
||||
var/obj/machinery/atmospherics/A = new pipe_type(loc)
|
||||
build_pipe(A)
|
||||
A.on_construction(color, piping_layer)
|
||||
transfer_fingerprints_to(A)
|
||||
|
||||
W.play_tool_sound(src)
|
||||
user.visible_message( \
|
||||
"[user] fastens \the [src].", \
|
||||
"<span class='notice'>You fasten \the [src].</span>", \
|
||||
"<span class='italics'>You hear ratcheting.</span>")
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A)
|
||||
A.setDir(fixed_dir())
|
||||
A.SetInitDirections()
|
||||
|
||||
if(pipename)
|
||||
A.name = pipename
|
||||
if(A.on)
|
||||
// Certain pre-mapped subtypes are on by default, we want to preserve
|
||||
// every other aspect of these subtypes (name, pre-set filters, etc.)
|
||||
// but they shouldn't turn on automatically when wrenched.
|
||||
A.on = FALSE
|
||||
|
||||
/obj/item/pipe/trinary/flippable/build_pipe(obj/machinery/atmospherics/components/trinary/T)
|
||||
..()
|
||||
T.flipped = flipped
|
||||
|
||||
/obj/item/pipe/directional/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] shoves [src] in [user.p_their()] mouth and turns it on! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0, TRUE, FALSE, 4, FALSE)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
|
||||
/obj/item/pipe_meter
|
||||
name = "meter"
|
||||
desc = "A meter that can be laid on pipes."
|
||||
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
icon_state = "meter"
|
||||
item_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
|
||||
/obj/item/pipe_meter/wrench_act(mob/living/user, obj/item/wrench/W)
|
||||
|
||||
var/obj/machinery/atmospherics/pipe/pipe
|
||||
for(var/obj/machinery/atmospherics/pipe/P in loc)
|
||||
if(P.piping_layer == piping_layer)
|
||||
pipe = P
|
||||
break
|
||||
if(!pipe)
|
||||
to_chat(user, "<span class='warning'>You need to fasten it to a pipe!</span>")
|
||||
return TRUE
|
||||
new /obj/machinery/meter(loc, piping_layer)
|
||||
W.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You fasten the meter to the pipe.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe_meter/screwdriver_act(mob/living/user, obj/item/S)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
|
||||
if(!isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You need to fasten it to the floor!</span>")
|
||||
return TRUE
|
||||
|
||||
new /obj/machinery/meter/turf(loc, piping_layer)
|
||||
S.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You fasten the meter to the [loc.name].</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe_meter/dropped()
|
||||
. = ..()
|
||||
if(loc)
|
||||
setAttachLayer(piping_layer)
|
||||
|
||||
/obj/item/pipe_meter/proc/setAttachLayer(new_layer = PIPING_LAYER_DEFAULT)
|
||||
piping_layer = new_layer
|
||||
pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
/*CONTENTS
|
||||
Buildable pipes
|
||||
Buildable meters
|
||||
*/
|
||||
|
||||
//construction defines are in __defines/pipe_construction.dm
|
||||
//update those defines ANY TIME an atmos path is changed...
|
||||
//...otherwise construction will stop working
|
||||
|
||||
/obj/item/pipe
|
||||
name = "pipe"
|
||||
desc = "A pipe."
|
||||
var/pipe_type
|
||||
var/pipename
|
||||
force = 7
|
||||
throwforce = 7
|
||||
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
icon_state = "simple"
|
||||
item_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
level = 2
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
var/RPD_type
|
||||
|
||||
/obj/item/pipe/directional
|
||||
RPD_type = PIPE_UNARY
|
||||
/obj/item/pipe/binary
|
||||
RPD_type = PIPE_STRAIGHT
|
||||
/obj/item/pipe/binary/bendable
|
||||
RPD_type = PIPE_BENDABLE
|
||||
/obj/item/pipe/trinary
|
||||
RPD_type = PIPE_TRINARY
|
||||
/obj/item/pipe/trinary/flippable
|
||||
RPD_type = PIPE_TRIN_M
|
||||
var/flipped = FALSE
|
||||
/obj/item/pipe/quaternary
|
||||
RPD_type = PIPE_ONEDIR
|
||||
|
||||
/obj/item/pipe/ComponentInitialize()
|
||||
//Flipping handled manually due to custom handling for trinary pipes
|
||||
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE)
|
||||
|
||||
/obj/item/pipe/Initialize(mapload, _pipe_type, _dir, obj/machinery/atmospherics/make_from)
|
||||
if(make_from)
|
||||
make_from_existing(make_from)
|
||||
else
|
||||
pipe_type = _pipe_type
|
||||
setDir(_dir)
|
||||
|
||||
update()
|
||||
pixel_x += rand(-5, 5)
|
||||
pixel_y += rand(-5, 5)
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from)
|
||||
setDir(make_from.dir)
|
||||
pipename = make_from.name
|
||||
add_atom_colour(make_from.color, FIXED_COLOUR_PRIORITY)
|
||||
pipe_type = make_from.type
|
||||
|
||||
/obj/item/pipe/trinary/flippable/make_from_existing(obj/machinery/atmospherics/components/trinary/make_from)
|
||||
..()
|
||||
if(make_from.flipped)
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/dropped()
|
||||
if(loc)
|
||||
setPipingLayer(piping_layer)
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT)
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
|
||||
if(initial(fakeA.pipe_flags) & PIPING_ALL_LAYER)
|
||||
new_layer = PIPING_LAYER_DEFAULT
|
||||
piping_layer = new_layer
|
||||
|
||||
pixel_x += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE)
|
||||
|
||||
/obj/item/pipe/proc/update()
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
name = "[initial(fakeA.name)] fitting"
|
||||
icon_state = initial(fakeA.pipe_state)
|
||||
if(ispath(pipe_type,/obj/machinery/atmospherics/pipe/heat_exchanging))
|
||||
resistance_flags |= FIRE_PROOF | LAVA_PROOF
|
||||
|
||||
/obj/item/pipe/verb/flip()
|
||||
set category = "Object"
|
||||
set name = "Flip Pipe"
|
||||
set src in view(1)
|
||||
|
||||
if ( usr.stat || usr.restrained() || !usr.canmove )
|
||||
return
|
||||
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/proc/do_a_flip()
|
||||
setDir(turn(dir, -180))
|
||||
|
||||
/obj/item/pipe/trinary/flippable/do_a_flip()
|
||||
setDir(turn(dir, flipped ? 45 : -45))
|
||||
flipped = !flipped
|
||||
|
||||
/obj/item/pipe/Move()
|
||||
var/old_dir = dir
|
||||
..()
|
||||
setDir(old_dir) //pipes changing direction when moved is just annoying and buggy
|
||||
|
||||
// Convert dir of fitting into dir of built component
|
||||
/obj/item/pipe/proc/fixed_dir()
|
||||
return dir
|
||||
|
||||
/obj/item/pipe/binary/fixed_dir()
|
||||
. = dir
|
||||
if(dir == SOUTH)
|
||||
. = NORTH
|
||||
else if(dir == WEST)
|
||||
. = EAST
|
||||
|
||||
/obj/item/pipe/trinary/flippable/fixed_dir()
|
||||
. = dir
|
||||
if(dir in GLOB.diagonals)
|
||||
. = turn(dir, 45)
|
||||
|
||||
/obj/item/pipe/attack_self(mob/user)
|
||||
setDir(turn(dir,-90))
|
||||
|
||||
/obj/item/pipe/wrench_act(mob/living/user, obj/item/wrench/W)
|
||||
if(!isturf(loc))
|
||||
return TRUE
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
var/obj/machinery/atmospherics/fakeA = pipe_type
|
||||
var/flags = initial(fakeA.pipe_flags)
|
||||
for(var/obj/machinery/atmospherics/M in loc)
|
||||
if((M.pipe_flags & flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
|
||||
to_chat(user, "<span class='warning'>Something is hogging the tile!</span>")
|
||||
return TRUE
|
||||
if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) //don't continue if either pipe goes across all layers
|
||||
continue
|
||||
if(M.GetInitDirections() & SSair.get_init_dirs(pipe_type, fixed_dir())) // matches at least one direction on either type of pipe
|
||||
to_chat(user, "<span class='warning'>There is already a pipe at that location!</span>")
|
||||
return TRUE
|
||||
// no conflicts found
|
||||
|
||||
var/obj/machinery/atmospherics/A = new pipe_type(loc)
|
||||
build_pipe(A)
|
||||
A.on_construction(color, piping_layer)
|
||||
transfer_fingerprints_to(A)
|
||||
|
||||
W.play_tool_sound(src)
|
||||
user.visible_message( \
|
||||
"[user] fastens \the [src].", \
|
||||
"<span class='notice'>You fasten \the [src].</span>", \
|
||||
"<span class='italics'>You hear ratcheting.</span>")
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A)
|
||||
A.setDir(fixed_dir())
|
||||
A.SetInitDirections()
|
||||
|
||||
if(pipename)
|
||||
A.name = pipename
|
||||
if(A.on)
|
||||
// Certain pre-mapped subtypes are on by default, we want to preserve
|
||||
// every other aspect of these subtypes (name, pre-set filters, etc.)
|
||||
// but they shouldn't turn on automatically when wrenched.
|
||||
A.on = FALSE
|
||||
|
||||
/obj/item/pipe/trinary/flippable/build_pipe(obj/machinery/atmospherics/components/trinary/T)
|
||||
..()
|
||||
T.flipped = flipped
|
||||
|
||||
/obj/item/pipe/directional/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] shoves [src] in [user.p_their()] mouth and turns it on! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0, TRUE, FALSE, 4, FALSE)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
|
||||
/obj/item/pipe_meter
|
||||
name = "meter"
|
||||
desc = "A meter that can be laid on pipes."
|
||||
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
icon_state = "meter"
|
||||
item_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
|
||||
/obj/item/pipe_meter/wrench_act(mob/living/user, obj/item/wrench/W)
|
||||
|
||||
var/obj/machinery/atmospherics/pipe/pipe
|
||||
for(var/obj/machinery/atmospherics/pipe/P in loc)
|
||||
if(P.piping_layer == piping_layer)
|
||||
pipe = P
|
||||
break
|
||||
if(!pipe)
|
||||
to_chat(user, "<span class='warning'>You need to fasten it to a pipe!</span>")
|
||||
return TRUE
|
||||
new /obj/machinery/meter(loc, piping_layer)
|
||||
W.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You fasten the meter to the pipe.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe_meter/screwdriver_act(mob/living/user, obj/item/S)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
|
||||
if(!isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You need to fasten it to the floor!</span>")
|
||||
return TRUE
|
||||
|
||||
new /obj/machinery/meter/turf(loc, piping_layer)
|
||||
S.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You fasten the meter to the [loc.name].</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe_meter/dropped()
|
||||
. = ..()
|
||||
if(loc)
|
||||
setAttachLayer(piping_layer)
|
||||
|
||||
/obj/item/pipe_meter/proc/setAttachLayer(new_layer = PIPING_LAYER_DEFAULT)
|
||||
piping_layer = new_layer
|
||||
pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
|
||||
@@ -1,212 +1,212 @@
|
||||
/obj/machinery/pipedispenser
|
||||
name = "pipe dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
desc = "Dispenses countless types of pipes. Very useful if you need pipes."
|
||||
density = TRUE
|
||||
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_OFFLINE
|
||||
var/wait = 0
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
|
||||
/obj/machinery/pipedispenser/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/pipedispenser/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b><A href='?src=[REF(src)];layer_up=1'>++</A><BR>"
|
||||
|
||||
var/recipes = GLOB.atmos_pipe_recipes
|
||||
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
dat += "<b>[category]:</b><ul>"
|
||||
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/I = i
|
||||
dat += I.Render(src)
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
onclose(user, "pipedispenser")
|
||||
return
|
||||
|
||||
/obj/machinery/pipedispenser/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(!anchored|| !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=pipedispenser")
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["makepipe"])
|
||||
if(wait < world.time)
|
||||
var/p_type = text2path(href_list["makepipe"])
|
||||
if (!verify_recipe(GLOB.atmos_pipe_recipes, p_type))
|
||||
return
|
||||
var/p_dir = text2num(href_list["dir"])
|
||||
var/obj/item/pipe/P = new (loc, p_type, p_dir)
|
||||
P.setPipingLayer(piping_layer)
|
||||
P.add_fingerprint(usr)
|
||||
wait = world.time + 10
|
||||
if(href_list["makemeter"])
|
||||
if(wait < world.time )
|
||||
new /obj/item/pipe_meter(loc)
|
||||
wait = world.time + 15
|
||||
if(href_list["layer_up"])
|
||||
piping_layer = CLAMP(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
|
||||
if(href_list["layer_down"])
|
||||
piping_layer = CLAMP(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
|
||||
return
|
||||
|
||||
/obj/machinery/pipedispenser/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if (istype(W, /obj/item/pipe) || istype(W, /obj/item/pipe_meter))
|
||||
to_chat(usr, "<span class='notice'>You put [W] back into [src].</span>")
|
||||
qdel(W)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pipedispenser/proc/verify_recipe(recipes, path)
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/info = i
|
||||
if (path == info.id)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/pipedispenser/wrench_act(mob/living/user, obj/item/I)
|
||||
if(default_unfasten_wrench(user, I, 40))
|
||||
user << browse(null, "window=pipedispenser")
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal
|
||||
name = "disposal pipe dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
desc = "Dispenses pipes that will ultimately be used to move trash around."
|
||||
density = TRUE
|
||||
|
||||
|
||||
//Allow you to drag-drop disposal pipes and transit tubes into it
|
||||
/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/usr)
|
||||
if(!usr.canmove || usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod))
|
||||
return
|
||||
|
||||
if (get_dist(usr, src) > 1 || get_dist(src,pipe) > 1 )
|
||||
return
|
||||
|
||||
if (pipe.anchored)
|
||||
return
|
||||
|
||||
qdel(pipe)
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/interact(mob/user)
|
||||
|
||||
var/dat = ""
|
||||
var/recipes = GLOB.disposal_pipe_recipes
|
||||
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
dat += "<b>[category]:</b><ul>"
|
||||
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/I = i
|
||||
dat += I.Render(src)
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["dmake"])
|
||||
if(wait < world.time)
|
||||
var/p_type = text2path(href_list["dmake"])
|
||||
if (!verify_recipe(GLOB.disposal_pipe_recipes, p_type))
|
||||
return
|
||||
var/obj/structure/disposalconstruct/C = new (loc, p_type)
|
||||
|
||||
if(!C.can_place())
|
||||
to_chat(usr, "<span class='warning'>There's not enough room to build that here!</span>")
|
||||
qdel(C)
|
||||
return
|
||||
if(href_list["dir"])
|
||||
C.setDir(text2num(href_list["dir"]))
|
||||
C.add_fingerprint(usr)
|
||||
C.update_icon()
|
||||
wait = world.time + 15
|
||||
return
|
||||
|
||||
//transit tube dispenser
|
||||
//inherit disposal for the dragging proc
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube
|
||||
name = "transit tube dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
density = TRUE
|
||||
desc = "Dispenses pipes that will move beings around."
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube/interact(mob/user)
|
||||
|
||||
var/dat = {"<B>Transit Tubes:</B><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STRAIGHT]'>Straight Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STRAIGHT_CROSSING]'>Straight Tube with Crossing</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_CURVED]'>Curved Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_DIAGONAL]'>Diagonal Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_DIAGONAL_CROSSING]'>Diagonal Tube with Crossing</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_JUNCTION]'>Junction</A><BR>
|
||||
<b>Station Equipment:</b><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STATION]'>Through Tube Station</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_TERMINUS]'>Terminus Tube Station</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_POD]'>Transit Tube Pod</A><BR>
|
||||
"}
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(wait < world.time)
|
||||
if(href_list["tube"])
|
||||
var/tube_type = text2num(href_list["tube"])
|
||||
var/obj/structure/C
|
||||
switch(tube_type)
|
||||
if(TRANSIT_TUBE_STRAIGHT)
|
||||
C = new /obj/structure/c_transit_tube(loc)
|
||||
if(TRANSIT_TUBE_STRAIGHT_CROSSING)
|
||||
C = new /obj/structure/c_transit_tube/crossing(loc)
|
||||
if(TRANSIT_TUBE_CURVED)
|
||||
C = new /obj/structure/c_transit_tube/curved(loc)
|
||||
if(TRANSIT_TUBE_DIAGONAL)
|
||||
C = new /obj/structure/c_transit_tube/diagonal(loc)
|
||||
if(TRANSIT_TUBE_DIAGONAL_CROSSING)
|
||||
C = new /obj/structure/c_transit_tube/diagonal/crossing(loc)
|
||||
if(TRANSIT_TUBE_JUNCTION)
|
||||
C = new /obj/structure/c_transit_tube/junction(loc)
|
||||
if(TRANSIT_TUBE_STATION)
|
||||
C = new /obj/structure/c_transit_tube/station(loc)
|
||||
if(TRANSIT_TUBE_TERMINUS)
|
||||
C = new /obj/structure/c_transit_tube/station/reverse(loc)
|
||||
if(TRANSIT_TUBE_POD)
|
||||
C = new /obj/structure/c_transit_tube_pod(loc)
|
||||
if(C)
|
||||
C.add_fingerprint(usr)
|
||||
wait = world.time + 15
|
||||
return
|
||||
/obj/machinery/pipedispenser
|
||||
name = "pipe dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
desc = "Dispenses countless types of pipes. Very useful if you need pipes."
|
||||
density = TRUE
|
||||
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_OFFLINE
|
||||
var/wait = 0
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
|
||||
/obj/machinery/pipedispenser/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/pipedispenser/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b><A href='?src=[REF(src)];layer_up=1'>++</A><BR>"
|
||||
|
||||
var/recipes = GLOB.atmos_pipe_recipes
|
||||
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
dat += "<b>[category]:</b><ul>"
|
||||
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/I = i
|
||||
dat += I.Render(src)
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
onclose(user, "pipedispenser")
|
||||
return
|
||||
|
||||
/obj/machinery/pipedispenser/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(!anchored|| !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
usr << browse(null, "window=pipedispenser")
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["makepipe"])
|
||||
if(wait < world.time)
|
||||
var/p_type = text2path(href_list["makepipe"])
|
||||
if (!verify_recipe(GLOB.atmos_pipe_recipes, p_type))
|
||||
return
|
||||
var/p_dir = text2num(href_list["dir"])
|
||||
var/obj/item/pipe/P = new (loc, p_type, p_dir)
|
||||
P.setPipingLayer(piping_layer)
|
||||
P.add_fingerprint(usr)
|
||||
wait = world.time + 10
|
||||
if(href_list["makemeter"])
|
||||
if(wait < world.time )
|
||||
new /obj/item/pipe_meter(loc)
|
||||
wait = world.time + 15
|
||||
if(href_list["layer_up"])
|
||||
piping_layer = CLAMP(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
|
||||
if(href_list["layer_down"])
|
||||
piping_layer = CLAMP(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
|
||||
return
|
||||
|
||||
/obj/machinery/pipedispenser/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if (istype(W, /obj/item/pipe) || istype(W, /obj/item/pipe_meter))
|
||||
to_chat(usr, "<span class='notice'>You put [W] back into [src].</span>")
|
||||
qdel(W)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pipedispenser/proc/verify_recipe(recipes, path)
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/info = i
|
||||
if (path == info.id)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/pipedispenser/wrench_act(mob/living/user, obj/item/I)
|
||||
if(default_unfasten_wrench(user, I, 40))
|
||||
user << browse(null, "window=pipedispenser")
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal
|
||||
name = "disposal pipe dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
desc = "Dispenses pipes that will ultimately be used to move trash around."
|
||||
density = TRUE
|
||||
|
||||
|
||||
//Allow you to drag-drop disposal pipes and transit tubes into it
|
||||
/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/usr)
|
||||
if(!usr.canmove || usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod))
|
||||
return
|
||||
|
||||
if (get_dist(usr, src) > 1 || get_dist(src,pipe) > 1 )
|
||||
return
|
||||
|
||||
if (pipe.anchored)
|
||||
return
|
||||
|
||||
qdel(pipe)
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/interact(mob/user)
|
||||
|
||||
var/dat = ""
|
||||
var/recipes = GLOB.disposal_pipe_recipes
|
||||
|
||||
for(var/category in recipes)
|
||||
var/list/cat_recipes = recipes[category]
|
||||
dat += "<b>[category]:</b><ul>"
|
||||
|
||||
for(var/i in cat_recipes)
|
||||
var/datum/pipe_info/I = i
|
||||
dat += I.Render(src)
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["dmake"])
|
||||
if(wait < world.time)
|
||||
var/p_type = text2path(href_list["dmake"])
|
||||
if (!verify_recipe(GLOB.disposal_pipe_recipes, p_type))
|
||||
return
|
||||
var/obj/structure/disposalconstruct/C = new (loc, p_type)
|
||||
|
||||
if(!C.can_place())
|
||||
to_chat(usr, "<span class='warning'>There's not enough room to build that here!</span>")
|
||||
qdel(C)
|
||||
return
|
||||
if(href_list["dir"])
|
||||
C.setDir(text2num(href_list["dir"]))
|
||||
C.add_fingerprint(usr)
|
||||
C.update_icon()
|
||||
wait = world.time + 15
|
||||
return
|
||||
|
||||
//transit tube dispenser
|
||||
//inherit disposal for the dragging proc
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube
|
||||
name = "transit tube dispenser"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "pipe_d"
|
||||
density = TRUE
|
||||
desc = "Dispenses pipes that will move beings around."
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube/interact(mob/user)
|
||||
|
||||
var/dat = {"<B>Transit Tubes:</B><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STRAIGHT]'>Straight Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STRAIGHT_CROSSING]'>Straight Tube with Crossing</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_CURVED]'>Curved Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_DIAGONAL]'>Diagonal Tube</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_DIAGONAL_CROSSING]'>Diagonal Tube with Crossing</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_JUNCTION]'>Junction</A><BR>
|
||||
<b>Station Equipment:</b><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_STATION]'>Through Tube Station</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_TERMINUS]'>Terminus Tube Station</A><BR>
|
||||
<A href='?src=[REF(src)];tube=[TRANSIT_TUBE_POD]'>Transit Tube Pod</A><BR>
|
||||
"}
|
||||
|
||||
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/pipedispenser/disposal/transit_tube/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(wait < world.time)
|
||||
if(href_list["tube"])
|
||||
var/tube_type = text2num(href_list["tube"])
|
||||
var/obj/structure/C
|
||||
switch(tube_type)
|
||||
if(TRANSIT_TUBE_STRAIGHT)
|
||||
C = new /obj/structure/c_transit_tube(loc)
|
||||
if(TRANSIT_TUBE_STRAIGHT_CROSSING)
|
||||
C = new /obj/structure/c_transit_tube/crossing(loc)
|
||||
if(TRANSIT_TUBE_CURVED)
|
||||
C = new /obj/structure/c_transit_tube/curved(loc)
|
||||
if(TRANSIT_TUBE_DIAGONAL)
|
||||
C = new /obj/structure/c_transit_tube/diagonal(loc)
|
||||
if(TRANSIT_TUBE_DIAGONAL_CROSSING)
|
||||
C = new /obj/structure/c_transit_tube/diagonal/crossing(loc)
|
||||
if(TRANSIT_TUBE_JUNCTION)
|
||||
C = new /obj/structure/c_transit_tube/junction(loc)
|
||||
if(TRANSIT_TUBE_STATION)
|
||||
C = new /obj/structure/c_transit_tube/station(loc)
|
||||
if(TRANSIT_TUBE_TERMINUS)
|
||||
C = new /obj/structure/c_transit_tube/station/reverse(loc)
|
||||
if(TRANSIT_TUBE_POD)
|
||||
C = new /obj/structure/c_transit_tube_pod(loc)
|
||||
if(C)
|
||||
C.add_fingerprint(usr)
|
||||
wait = world.time + 15
|
||||
return
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+163
-163
@@ -1,163 +1,163 @@
|
||||
/obj/machinery/recharger
|
||||
name = "recharger"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "recharger0"
|
||||
desc = "A charging dock for energy based weaponry."
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 4
|
||||
active_power_usage = 250
|
||||
circuit = /obj/item/circuitboard/machine/recharger
|
||||
pass_flags = PASSTABLE
|
||||
var/obj/item/charging = null
|
||||
var/recharge_coeff = 1
|
||||
|
||||
var/static/list/allowed_devices = typecacheof(list(
|
||||
/obj/item/gun/energy,
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/ammo_box/magazine/recharge,
|
||||
/obj/item/modular_computer,
|
||||
/obj/item/gun/ballistic/automatic/magrifle_e,
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag_e))
|
||||
|
||||
/obj/machinery/recharger/RefreshParts()
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
recharge_coeff = C.rating
|
||||
|
||||
/obj/machinery/recharger/proc/setCharging(new_charging)
|
||||
charging = new_charging
|
||||
if (new_charging)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
update_icon(scan = TRUE)
|
||||
else
|
||||
use_power = IDLE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
|
||||
if(istype(G, /obj/item/wrench))
|
||||
if(charging)
|
||||
to_chat(user, "<span class='notice'>Remove the charging item first!</span>")
|
||||
return
|
||||
setAnchored(!anchored)
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "attached" : "detached"] [src].</span>")
|
||||
G.play_tool_sound(src)
|
||||
return
|
||||
|
||||
var/allowed = is_type_in_typecache(G, allowed_devices)
|
||||
|
||||
if(allowed)
|
||||
if(anchored)
|
||||
if(charging || panel_open)
|
||||
return 1
|
||||
|
||||
//Checks to make sure he's not in space doing it, and that the area got proper power.
|
||||
var/area/a = get_area(src)
|
||||
if(!isarea(a) || a.power_equip == 0)
|
||||
to_chat(user, "<span class='notice'>[src] blinks red as you try to insert [G].</span>")
|
||||
return 1
|
||||
|
||||
if (istype(G, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/E = G
|
||||
if(!E.can_charge)
|
||||
to_chat(user, "<span class='notice'>Your gun has no external power connector.</span>")
|
||||
return 1
|
||||
|
||||
if(!user.transferItemToLoc(G, src))
|
||||
return 1
|
||||
setCharging(G)
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] isn't connected to anything!</span>")
|
||||
return 1
|
||||
|
||||
if(anchored && !charging)
|
||||
if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G))
|
||||
return
|
||||
|
||||
if(panel_open && istype(G, /obj/item/crowbar))
|
||||
default_deconstruction_crowbar(G)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recharger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
if(charging)
|
||||
charging.update_icon()
|
||||
charging.forceMove(drop_location())
|
||||
user.put_in_hands(charging)
|
||||
setCharging(null)
|
||||
|
||||
/obj/machinery/recharger/attack_tk(mob/user)
|
||||
if(charging)
|
||||
charging.update_icon()
|
||||
charging.forceMove(drop_location())
|
||||
setCharging(null)
|
||||
|
||||
/obj/machinery/recharger/process()
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
return PROCESS_KILL
|
||||
|
||||
var/using_power = 0
|
||||
if(charging)
|
||||
var/obj/item/stock_parts/cell/C = charging.get_cell()
|
||||
if(C)
|
||||
if(C.charge < C.maxcharge)
|
||||
C.give(C.chargerate * recharge_coeff)
|
||||
use_power(250 * recharge_coeff)
|
||||
using_power = 1
|
||||
update_icon(using_power)
|
||||
|
||||
if(istype(charging, /obj/item/ammo_box/magazine/recharge))
|
||||
var/obj/item/ammo_box/magazine/recharge/R = charging
|
||||
if(R.stored_ammo.len < R.max_ammo)
|
||||
R.stored_ammo += new R.ammo_type(R)
|
||||
use_power(200 * recharge_coeff)
|
||||
using_power = 1
|
||||
update_icon(using_power)
|
||||
return
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/recharger/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharger/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_CONTENTS)
|
||||
return
|
||||
if(!(stat & (NOPOWER|BROKEN)) && anchored)
|
||||
if(istype(charging, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/E = charging
|
||||
if(E.cell)
|
||||
E.cell.emp_act(severity)
|
||||
|
||||
else if(istype(charging, /obj/item/melee/baton))
|
||||
var/obj/item/melee/baton/B = charging
|
||||
if(B.cell)
|
||||
B.cell.charge = 0
|
||||
|
||||
|
||||
/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
icon_state = "rechargeroff"
|
||||
return
|
||||
if(scan)
|
||||
icon_state = "rechargeroff"
|
||||
return
|
||||
if(panel_open)
|
||||
icon_state = "rechargeropen"
|
||||
return
|
||||
if(charging)
|
||||
if(using_power)
|
||||
icon_state = "recharger1"
|
||||
else
|
||||
icon_state = "recharger2"
|
||||
return
|
||||
icon_state = "recharger0"
|
||||
/obj/machinery/recharger
|
||||
name = "recharger"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "recharger0"
|
||||
desc = "A charging dock for energy based weaponry."
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 4
|
||||
active_power_usage = 250
|
||||
circuit = /obj/item/circuitboard/machine/recharger
|
||||
pass_flags = PASSTABLE
|
||||
var/obj/item/charging = null
|
||||
var/recharge_coeff = 1
|
||||
|
||||
var/static/list/allowed_devices = typecacheof(list(
|
||||
/obj/item/gun/energy,
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/ammo_box/magazine/recharge,
|
||||
/obj/item/modular_computer,
|
||||
/obj/item/gun/ballistic/automatic/magrifle_e,
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag_e))
|
||||
|
||||
/obj/machinery/recharger/RefreshParts()
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
recharge_coeff = C.rating
|
||||
|
||||
/obj/machinery/recharger/proc/setCharging(new_charging)
|
||||
charging = new_charging
|
||||
if (new_charging)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
update_icon(scan = TRUE)
|
||||
else
|
||||
use_power = IDLE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
|
||||
if(istype(G, /obj/item/wrench))
|
||||
if(charging)
|
||||
to_chat(user, "<span class='notice'>Remove the charging item first!</span>")
|
||||
return
|
||||
setAnchored(!anchored)
|
||||
power_change()
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "attached" : "detached"] [src].</span>")
|
||||
G.play_tool_sound(src)
|
||||
return
|
||||
|
||||
var/allowed = is_type_in_typecache(G, allowed_devices)
|
||||
|
||||
if(allowed)
|
||||
if(anchored)
|
||||
if(charging || panel_open)
|
||||
return 1
|
||||
|
||||
//Checks to make sure he's not in space doing it, and that the area got proper power.
|
||||
var/area/a = get_area(src)
|
||||
if(!isarea(a) || a.power_equip == 0)
|
||||
to_chat(user, "<span class='notice'>[src] blinks red as you try to insert [G].</span>")
|
||||
return 1
|
||||
|
||||
if (istype(G, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/E = G
|
||||
if(!E.can_charge)
|
||||
to_chat(user, "<span class='notice'>Your gun has no external power connector.</span>")
|
||||
return 1
|
||||
|
||||
if(!user.transferItemToLoc(G, src))
|
||||
return 1
|
||||
setCharging(G)
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] isn't connected to anything!</span>")
|
||||
return 1
|
||||
|
||||
if(anchored && !charging)
|
||||
if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G))
|
||||
return
|
||||
|
||||
if(panel_open && istype(G, /obj/item/crowbar))
|
||||
default_deconstruction_crowbar(G)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recharger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
if(charging)
|
||||
charging.update_icon()
|
||||
charging.forceMove(drop_location())
|
||||
user.put_in_hands(charging)
|
||||
setCharging(null)
|
||||
|
||||
/obj/machinery/recharger/attack_tk(mob/user)
|
||||
if(charging)
|
||||
charging.update_icon()
|
||||
charging.forceMove(drop_location())
|
||||
setCharging(null)
|
||||
|
||||
/obj/machinery/recharger/process()
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
return PROCESS_KILL
|
||||
|
||||
var/using_power = 0
|
||||
if(charging)
|
||||
var/obj/item/stock_parts/cell/C = charging.get_cell()
|
||||
if(C)
|
||||
if(C.charge < C.maxcharge)
|
||||
C.give(C.chargerate * recharge_coeff)
|
||||
use_power(250 * recharge_coeff)
|
||||
using_power = 1
|
||||
update_icon(using_power)
|
||||
|
||||
if(istype(charging, /obj/item/ammo_box/magazine/recharge))
|
||||
var/obj/item/ammo_box/magazine/recharge/R = charging
|
||||
if(R.stored_ammo.len < R.max_ammo)
|
||||
R.stored_ammo += new R.ammo_type(R)
|
||||
use_power(200 * recharge_coeff)
|
||||
using_power = 1
|
||||
update_icon(using_power)
|
||||
return
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/recharger/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharger/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_CONTENTS)
|
||||
return
|
||||
if(!(stat & (NOPOWER|BROKEN)) && anchored)
|
||||
if(istype(charging, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/E = charging
|
||||
if(E.cell)
|
||||
E.cell.emp_act(severity)
|
||||
|
||||
else if(istype(charging, /obj/item/melee/baton))
|
||||
var/obj/item/melee/baton/B = charging
|
||||
if(B.cell)
|
||||
B.cell.charge = 0
|
||||
|
||||
|
||||
/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
|
||||
if(stat & (NOPOWER|BROKEN) || !anchored)
|
||||
icon_state = "rechargeroff"
|
||||
return
|
||||
if(scan)
|
||||
icon_state = "rechargeroff"
|
||||
return
|
||||
if(panel_open)
|
||||
icon_state = "rechargeropen"
|
||||
return
|
||||
if(charging)
|
||||
if(using_power)
|
||||
icon_state = "recharger1"
|
||||
else
|
||||
icon_state = "recharger2"
|
||||
return
|
||||
icon_state = "recharger0"
|
||||
|
||||
@@ -1,113 +1,135 @@
|
||||
/obj/machinery/recharge_station
|
||||
name = "cyborg recharging station"
|
||||
desc = "This device recharges cyborgs and resupplies them with materials."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "borgcharger0"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 1000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
state_open = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/cyborgrecharger
|
||||
occupant_typecache = list(/mob/living/silicon/robot)
|
||||
var/recharge_speed
|
||||
var/repairs
|
||||
|
||||
/obj/machinery/recharge_station/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharge_station/RefreshParts()
|
||||
recharge_speed = 0
|
||||
repairs = 0
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
recharge_speed += C.rating * 100
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
repairs += M.rating - 1
|
||||
for(var/obj/item/stock_parts/cell/C in component_parts)
|
||||
recharge_speed *= C.maxcharge / 10000
|
||||
|
||||
/obj/machinery/recharge_station/process()
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
process_occupant()
|
||||
return 1
|
||||
|
||||
/obj/machinery/recharge_station/relaymove(mob/user)
|
||||
if(user.stat)
|
||||
return
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/emp_act(severity)
|
||||
. = ..()
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
if(occupant && !(. & EMP_PROTECT_CONTENTS))
|
||||
occupant.emp_act(severity)
|
||||
if (!(. & EMP_PROTECT_SELF))
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/attackby(obj/item/P, mob/user, params)
|
||||
if(state_open)
|
||||
if(default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", P))
|
||||
return
|
||||
|
||||
if(default_pry_open(P))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(P))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recharge_station/interact(mob/user)
|
||||
toggle_open()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recharge_station/proc/toggle_open()
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/open_machine()
|
||||
. = ..()
|
||||
if(iscyborg(occupant))
|
||||
use_power = IDLE_POWER_USE
|
||||
|
||||
/obj/machinery/recharge_station/close_machine()
|
||||
. = ..()
|
||||
if(occupant)
|
||||
if(iscyborg(occupant))
|
||||
use_power = ACTIVE_POWER_USE
|
||||
add_fingerprint(occupant)
|
||||
|
||||
/obj/machinery/recharge_station/update_icon()
|
||||
if(is_operational())
|
||||
if(state_open)
|
||||
icon_state = "borgcharger0"
|
||||
else
|
||||
icon_state = (occupant ? "borgcharger1" : "borgcharger2")
|
||||
else
|
||||
icon_state = (state_open ? "borgcharger-u0" : "borgcharger-u1")
|
||||
|
||||
/obj/machinery/recharge_station/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharge_station/proc/process_occupant()
|
||||
if(occupant && iscyborg(occupant))
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
restock_modules()
|
||||
if(repairs)
|
||||
R.heal_bodypart_damage(repairs, repairs - 1)
|
||||
if(R.cell)
|
||||
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
|
||||
|
||||
/obj/machinery/recharge_station/proc/restock_modules()
|
||||
if(occupant)
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
if(R && R.module)
|
||||
var/coeff = recharge_speed * 0.005
|
||||
R.module.respawn_consumable(R, coeff)
|
||||
/obj/machinery/recharge_station
|
||||
name = "cyborg recharging station"
|
||||
desc = "This device recharges cyborgs and resupplies them with materials."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "borgcharger0"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 1000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
state_open = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/cyborgrecharger
|
||||
occupant_typecache = list(/mob/living/silicon/robot)
|
||||
var/recharge_speed
|
||||
var/repairs
|
||||
|
||||
/obj/machinery/recharge_station/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharge_station/upgraded
|
||||
|
||||
/obj/machinery/recharge_station/upgraded/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/cyborgrecharger(null)
|
||||
component_parts += new /obj/item/stock_parts/capacitor/super(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/pico(null)
|
||||
component_parts += new /obj/item/stock_parts/cell/hyper(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/recharge_station/fullupgrade
|
||||
|
||||
/obj/machinery/recharge_station/fullupgrade/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/cyborgrecharger(null)
|
||||
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
|
||||
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/recharge_station/RefreshParts()
|
||||
recharge_speed = 0
|
||||
repairs = 0
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
recharge_speed += C.rating * 100
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
repairs += M.rating - 1
|
||||
for(var/obj/item/stock_parts/cell/C in component_parts)
|
||||
recharge_speed *= C.maxcharge / 10000
|
||||
|
||||
/obj/machinery/recharge_station/process()
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
process_occupant()
|
||||
return 1
|
||||
|
||||
/obj/machinery/recharge_station/relaymove(mob/user)
|
||||
if(user.stat)
|
||||
return
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/emp_act(severity)
|
||||
. = ..()
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
if(occupant && !(. & EMP_PROTECT_CONTENTS))
|
||||
occupant.emp_act(severity)
|
||||
if (!(. & EMP_PROTECT_SELF))
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/attackby(obj/item/P, mob/user, params)
|
||||
if(state_open)
|
||||
if(default_deconstruction_screwdriver(user, "borgdecon2", "borgcharger0", P))
|
||||
return
|
||||
|
||||
if(default_pry_open(P))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(P))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recharge_station/interact(mob/user)
|
||||
toggle_open()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recharge_station/proc/toggle_open()
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/recharge_station/open_machine()
|
||||
. = ..()
|
||||
if(iscyborg(occupant))
|
||||
use_power = IDLE_POWER_USE
|
||||
|
||||
/obj/machinery/recharge_station/close_machine()
|
||||
. = ..()
|
||||
if(occupant)
|
||||
if(iscyborg(occupant))
|
||||
use_power = ACTIVE_POWER_USE
|
||||
add_fingerprint(occupant)
|
||||
|
||||
/obj/machinery/recharge_station/update_icon()
|
||||
if(is_operational())
|
||||
if(state_open)
|
||||
icon_state = "borgcharger0"
|
||||
else
|
||||
icon_state = (occupant ? "borgcharger1" : "borgcharger2")
|
||||
else
|
||||
icon_state = (state_open ? "borgcharger-u0" : "borgcharger-u1")
|
||||
|
||||
/obj/machinery/recharge_station/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharge_station/proc/process_occupant()
|
||||
if(occupant && iscyborg(occupant))
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
restock_modules()
|
||||
if(repairs)
|
||||
R.heal_bodypart_damage(repairs, repairs - 1)
|
||||
if(R.cell)
|
||||
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
|
||||
|
||||
/obj/machinery/recharge_station/proc/restock_modules()
|
||||
if(occupant)
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
if(R && R.module)
|
||||
var/coeff = recharge_speed * 0.005
|
||||
R.module.respawn_consumable(R, coeff)
|
||||
|
||||
+212
-212
@@ -1,212 +1,212 @@
|
||||
#define SAFETY_COOLDOWN 100
|
||||
|
||||
/obj/machinery/recycler
|
||||
name = "recycler"
|
||||
desc = "A large crushing machine used to recycle small items inefficiently. There are lights on the side."
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "grinder-o0"
|
||||
layer = ABOVE_ALL_MOB_LAYER // Overhead
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/recycler
|
||||
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
|
||||
var/icon_name = "grinder-o"
|
||||
var/blood = 0
|
||||
var/eat_dir = WEST
|
||||
var/amount_produced = 50
|
||||
var/crush_damage = 1000
|
||||
var/eat_victim_items = TRUE
|
||||
var/item_recycle_sound = 'sound/items/welder.ogg'
|
||||
|
||||
/obj/machinery/recycler/Initialize()
|
||||
AddComponent(/datum/component/butchering/recycler, 1, amount_produced,amount_produced/5)
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), INFINITY, FALSE, null, null, null, TRUE)
|
||||
. = ..()
|
||||
update_icon()
|
||||
req_one_access = get_all_accesses() + get_all_centcom_access()
|
||||
|
||||
/obj/machinery/recycler/RefreshParts()
|
||||
var/amt_made = 0
|
||||
var/mat_mod = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
mat_mod = 2 * B.rating
|
||||
mat_mod *= 50000
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
amt_made = 12.5 * M.rating //% of materials salvaged
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = mat_mod
|
||||
amount_produced = min(50, amt_made) + 50
|
||||
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering/recycler)
|
||||
butchering.effectiveness = amount_produced
|
||||
butchering.bonus_modifier = amount_produced/5
|
||||
|
||||
/obj/machinery/recycler/examine(mob/user)
|
||||
. = ..()
|
||||
. += "The power light is [(stat & NOPOWER) ? "off" : "on"]."
|
||||
. += "The safety-mode light is [safety_mode ? "on" : "off"]."
|
||||
. += "The safety-sensors status light is [obj_flags & EMAGGED ? "off" : "on"]."
|
||||
|
||||
/obj/machinery/recycler/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/recycler/attackby(obj/item/I, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I))
|
||||
return
|
||||
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
if(default_unfasten_wrench(user, I))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recycler/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
if(safety_mode)
|
||||
safety_mode = FALSE
|
||||
update_icon()
|
||||
playsound(src, "sparks", 75, 1, -1)
|
||||
to_chat(user, "<span class='notice'>You use the cryptographic sequencer on [src].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recycler/update_icon()
|
||||
..()
|
||||
var/is_powered = !(stat & (BROKEN|NOPOWER))
|
||||
if(safety_mode)
|
||||
is_powered = FALSE
|
||||
icon_state = icon_name + "[is_powered]" + "[(blood ? "bld" : "")]" // add the blood tag at the end
|
||||
|
||||
/obj/machinery/recycler/CanPass(atom/movable/AM)
|
||||
. = ..()
|
||||
if(!anchored)
|
||||
return
|
||||
|
||||
var/move_dir = get_dir(loc, AM.loc)
|
||||
if(move_dir == eat_dir)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recycler/Crossed(atom/movable/AM)
|
||||
eat(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if(safety_mode)
|
||||
return
|
||||
var/list/to_eat
|
||||
if(isitem(AM0))
|
||||
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
|
||||
else
|
||||
to_eat = list(AM0)
|
||||
|
||||
var/items_recycled = 0
|
||||
|
||||
for(var/i in to_eat)
|
||||
var/atom/movable/AM = i
|
||||
var/obj/item/bodypart/head/as_head = AM
|
||||
var/obj/item/mmi/as_mmi = AM
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
|
||||
if(brain_holder)
|
||||
emergency_stop(AM)
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
crush_living(AM)
|
||||
else
|
||||
emergency_stop(AM)
|
||||
else if(isitem(AM))
|
||||
var/obj/O = AM
|
||||
if(O.resistance_flags & INDESTRUCTIBLE)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
O.forceMove(loc)
|
||||
else
|
||||
recycle_item(AM)
|
||||
items_recycled++
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
AM.forceMove(loc)
|
||||
|
||||
if(items_recycled && sound)
|
||||
playsound(src, item_recycle_sound, 50, 1)
|
||||
|
||||
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
|
||||
|
||||
I.forceMove(loc)
|
||||
var/obj/item/grown/log/L = I
|
||||
if(istype(L))
|
||||
var/seed_modifier = 0
|
||||
if(L.seed)
|
||||
seed_modifier = round(L.seed.potency / 25)
|
||||
new L.plank_type(src.loc, 1 + seed_modifier)
|
||||
qdel(L)
|
||||
return
|
||||
else
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/material_amount = materials.get_item_material_amount(I)
|
||||
if(!material_amount)
|
||||
qdel(I)
|
||||
return
|
||||
materials.insert_item(I, multiplier = (amount_produced / 100))
|
||||
qdel(I)
|
||||
materials.retrieve_all()
|
||||
|
||||
|
||||
/obj/machinery/recycler/proc/emergency_stop(mob/living/L)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
safety_mode = TRUE
|
||||
update_icon()
|
||||
L.forceMove(loc)
|
||||
addtimer(CALLBACK(src, .proc/reboot), SAFETY_COOLDOWN)
|
||||
|
||||
/obj/machinery/recycler/proc/reboot()
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, 0)
|
||||
safety_mode = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recycler/proc/crush_living(mob/living/L)
|
||||
|
||||
L.forceMove(loc)
|
||||
|
||||
if(issilicon(L))
|
||||
playsound(src, 'sound/items/welder.ogg', 50, 1)
|
||||
else
|
||||
playsound(src, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
// By default, the emagged recycler will gib all non-carbons. (human simple animal mobs don't count)
|
||||
if(iscarbon(L))
|
||||
if(L.stat == CONSCIOUS)
|
||||
L.say("ARRRRRRRRRRRGH!!!", forced="recycler grinding")
|
||||
add_mob_blood(L)
|
||||
|
||||
if(!blood && !issilicon(L))
|
||||
blood = TRUE
|
||||
update_icon()
|
||||
|
||||
// Remove and recycle the equipped items
|
||||
if(eat_victim_items)
|
||||
for(var/obj/item/I in L.get_equipped_items(TRUE))
|
||||
if(L.dropItemToGround(I))
|
||||
eat(I, sound=FALSE)
|
||||
|
||||
// Instantly lie down, also go unconscious from the pain, before you die.
|
||||
L.Unconscious(100)
|
||||
L.adjustBruteLoss(crush_damage)
|
||||
|
||||
/obj/machinery/recycler/deathtrap
|
||||
name = "dangerous old crusher"
|
||||
obj_flags = CAN_BE_HIT | EMAGGED
|
||||
crush_damage = 120
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
|
||||
/obj/item/paper/guides/recycler
|
||||
name = "paper - 'garbage duty instructions'"
|
||||
info = "<h2>New Assignment</h2> You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
|
||||
#undef SAFETY_COOLDOWN
|
||||
#define SAFETY_COOLDOWN 100
|
||||
|
||||
/obj/machinery/recycler
|
||||
name = "recycler"
|
||||
desc = "A large crushing machine used to recycle small items inefficiently. There are lights on the side."
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "grinder-o0"
|
||||
layer = ABOVE_ALL_MOB_LAYER // Overhead
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/recycler
|
||||
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
|
||||
var/icon_name = "grinder-o"
|
||||
var/blood = 0
|
||||
var/eat_dir = WEST
|
||||
var/amount_produced = 50
|
||||
var/crush_damage = 1000
|
||||
var/eat_victim_items = TRUE
|
||||
var/item_recycle_sound = 'sound/items/welder.ogg'
|
||||
|
||||
/obj/machinery/recycler/Initialize()
|
||||
AddComponent(/datum/component/butchering/recycler, 1, amount_produced,amount_produced/5)
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), INFINITY, FALSE, null, null, null, TRUE)
|
||||
. = ..()
|
||||
update_icon()
|
||||
req_one_access = get_all_accesses() + get_all_centcom_access()
|
||||
|
||||
/obj/machinery/recycler/RefreshParts()
|
||||
var/amt_made = 0
|
||||
var/mat_mod = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
mat_mod = 2 * B.rating
|
||||
mat_mod *= 50000
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
amt_made = 12.5 * M.rating //% of materials salvaged
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = mat_mod
|
||||
amount_produced = min(50, amt_made) + 50
|
||||
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering/recycler)
|
||||
butchering.effectiveness = amount_produced
|
||||
butchering.bonus_modifier = amount_produced/5
|
||||
|
||||
/obj/machinery/recycler/examine(mob/user)
|
||||
. = ..()
|
||||
. += "The power light is [(stat & NOPOWER) ? "off" : "on"]."
|
||||
. += "The safety-mode light is [safety_mode ? "on" : "off"]."
|
||||
. += "The safety-sensors status light is [obj_flags & EMAGGED ? "off" : "on"]."
|
||||
|
||||
/obj/machinery/recycler/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/recycler/attackby(obj/item/I, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I))
|
||||
return
|
||||
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
if(default_unfasten_wrench(user, I))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recycler/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
if(safety_mode)
|
||||
safety_mode = FALSE
|
||||
update_icon()
|
||||
playsound(src, "sparks", 75, 1, -1)
|
||||
to_chat(user, "<span class='notice'>You use the cryptographic sequencer on [src].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recycler/update_icon()
|
||||
..()
|
||||
var/is_powered = !(stat & (BROKEN|NOPOWER))
|
||||
if(safety_mode)
|
||||
is_powered = FALSE
|
||||
icon_state = icon_name + "[is_powered]" + "[(blood ? "bld" : "")]" // add the blood tag at the end
|
||||
|
||||
/obj/machinery/recycler/CanPass(atom/movable/AM)
|
||||
. = ..()
|
||||
if(!anchored)
|
||||
return
|
||||
|
||||
var/move_dir = get_dir(loc, AM.loc)
|
||||
if(move_dir == eat_dir)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/recycler/Crossed(atom/movable/AM)
|
||||
eat(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if(safety_mode)
|
||||
return
|
||||
var/list/to_eat
|
||||
if(isitem(AM0))
|
||||
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
|
||||
else
|
||||
to_eat = list(AM0)
|
||||
|
||||
var/items_recycled = 0
|
||||
|
||||
for(var/i in to_eat)
|
||||
var/atom/movable/AM = i
|
||||
var/obj/item/bodypart/head/as_head = AM
|
||||
var/obj/item/mmi/as_mmi = AM
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
|
||||
if(brain_holder)
|
||||
emergency_stop(AM)
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
crush_living(AM)
|
||||
else
|
||||
emergency_stop(AM)
|
||||
else if(isitem(AM))
|
||||
var/obj/O = AM
|
||||
if(O.resistance_flags & INDESTRUCTIBLE)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
O.forceMove(loc)
|
||||
else
|
||||
recycle_item(AM)
|
||||
items_recycled++
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
AM.forceMove(loc)
|
||||
|
||||
if(items_recycled && sound)
|
||||
playsound(src, item_recycle_sound, 50, 1)
|
||||
|
||||
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
|
||||
|
||||
I.forceMove(loc)
|
||||
var/obj/item/grown/log/L = I
|
||||
if(istype(L))
|
||||
var/seed_modifier = 0
|
||||
if(L.seed)
|
||||
seed_modifier = round(L.seed.potency / 25)
|
||||
new L.plank_type(src.loc, 1 + seed_modifier)
|
||||
qdel(L)
|
||||
return
|
||||
else
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/material_amount = materials.get_item_material_amount(I)
|
||||
if(!material_amount)
|
||||
qdel(I)
|
||||
return
|
||||
materials.insert_item(I, multiplier = (amount_produced / 100))
|
||||
qdel(I)
|
||||
materials.retrieve_all()
|
||||
|
||||
|
||||
/obj/machinery/recycler/proc/emergency_stop(mob/living/L)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
safety_mode = TRUE
|
||||
update_icon()
|
||||
L.forceMove(loc)
|
||||
addtimer(CALLBACK(src, .proc/reboot), SAFETY_COOLDOWN)
|
||||
|
||||
/obj/machinery/recycler/proc/reboot()
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, 0)
|
||||
safety_mode = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recycler/proc/crush_living(mob/living/L)
|
||||
|
||||
L.forceMove(loc)
|
||||
|
||||
if(issilicon(L))
|
||||
playsound(src, 'sound/items/welder.ogg', 50, 1)
|
||||
else
|
||||
playsound(src, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
// By default, the emagged recycler will gib all non-carbons. (human simple animal mobs don't count)
|
||||
if(iscarbon(L))
|
||||
if(L.stat == CONSCIOUS)
|
||||
L.say("ARRRRRRRRRRRGH!!!", forced="recycler grinding")
|
||||
add_mob_blood(L)
|
||||
|
||||
if(!blood && !issilicon(L))
|
||||
blood = TRUE
|
||||
update_icon()
|
||||
|
||||
// Remove and recycle the equipped items
|
||||
if(eat_victim_items)
|
||||
for(var/obj/item/I in L.get_equipped_items(TRUE))
|
||||
if(L.dropItemToGround(I))
|
||||
eat(I, sound=FALSE)
|
||||
|
||||
// Instantly lie down, also go unconscious from the pain, before you die.
|
||||
L.Unconscious(100)
|
||||
L.adjustBruteLoss(crush_damage)
|
||||
|
||||
/obj/machinery/recycler/deathtrap
|
||||
name = "dangerous old crusher"
|
||||
obj_flags = CAN_BE_HIT | EMAGGED
|
||||
crush_damage = 120
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
|
||||
/obj/item/paper/guides/recycler
|
||||
name = "paper - 'garbage duty instructions'"
|
||||
info = "<h2>New Assignment</h2> You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
|
||||
#undef SAFETY_COOLDOWN
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,368 +1,368 @@
|
||||
// Status display
|
||||
// (formerly Countdown timer display)
|
||||
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define SCROLL_SPEED 2
|
||||
|
||||
#define SD_BLANK 0 // 0 = Blank
|
||||
#define SD_EMERGENCY 1 // 1 = Emergency Shuttle timer
|
||||
#define SD_MESSAGE 2 // 2 = Arbitrary message(s)
|
||||
#define SD_PICTURE 3 // 3 = alert picture
|
||||
|
||||
#define SD_AI_EMOTE 1 // 1 = AI emoticon
|
||||
#define SD_AI_BSOD 2 // 2 = Blue screen of death
|
||||
|
||||
/// Status display which can show images and scrolling text.
|
||||
/obj/machinery/status_display
|
||||
name = "status display"
|
||||
desc = null
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
var/message1 = "" // message line 1
|
||||
var/message2 = "" // message line 2
|
||||
var/index1 // display index for scrolling messages or 0 if non-scrolling
|
||||
var/index2
|
||||
|
||||
/// Immediately blank the display.
|
||||
/obj/machinery/status_display/proc/remove_display()
|
||||
cut_overlays()
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
|
||||
/// Immediately change the display to the given picture.
|
||||
/obj/machinery/status_display/proc/set_picture(state)
|
||||
remove_display()
|
||||
add_overlay(state)
|
||||
|
||||
/// Immediately change the display to the given two lines.
|
||||
/obj/machinery/status_display/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/// Prepare the display to marquee the given two lines.
|
||||
///
|
||||
/// Call with no arguments to disable.
|
||||
/obj/machinery/status_display/proc/set_message(m1, m2)
|
||||
if(m1)
|
||||
index1 = (length(m1) > CHARS_PER_LINE)
|
||||
message1 = m1
|
||||
else
|
||||
message1 = ""
|
||||
index1 = 0
|
||||
|
||||
if(m2)
|
||||
index2 = (length(m2) > CHARS_PER_LINE)
|
||||
message2 = m2
|
||||
else
|
||||
message2 = ""
|
||||
index2 = 0
|
||||
|
||||
// Timed process - performs default marquee action if so needed.
|
||||
/obj/machinery/status_display/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
var/line1 = message1
|
||||
if(index1)
|
||||
line1 = copytext("[message1]|[message1]", index1, index1+CHARS_PER_LINE)
|
||||
var/message1_len = length(message1)
|
||||
index1 += SCROLL_SPEED
|
||||
if(index1 > message1_len)
|
||||
index1 -= message1_len
|
||||
|
||||
var/line2 = message2
|
||||
if(index2)
|
||||
line2 = copytext("[message2]|[message2]", index2, index2+CHARS_PER_LINE)
|
||||
var/message2_len = length(message2)
|
||||
index2 += SCROLL_SPEED
|
||||
if(index2 > message2_len)
|
||||
index2 -= message2_len
|
||||
|
||||
update_display(line1, line2)
|
||||
if (!index1 && !index2)
|
||||
// No marquee, no processing.
|
||||
return PROCESS_KILL
|
||||
|
||||
/// Update the display and, if necessary, re-enable processing.
|
||||
/obj/machinery/status_display/proc/update()
|
||||
if (process() != PROCESS_KILL)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
|
||||
/obj/machinery/status_display/power_change()
|
||||
. = ..()
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/emp_act(severity)
|
||||
. = ..()
|
||||
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
|
||||
return
|
||||
set_picture("ai_bsod")
|
||||
|
||||
/obj/machinery/status_display/examine(mob/user)
|
||||
. = ..()
|
||||
if (message1 || message2)
|
||||
. += "The display says:"
|
||||
if (message1)
|
||||
. += "\t<tt>[html_encode(message1)]</tt>"
|
||||
if (message2)
|
||||
. += "\t<tt>[html_encode(message2)]</tt>"
|
||||
|
||||
// Helper procs for child display types.
|
||||
/obj/machinery/status_display/proc/display_shuttle_status(obj/docking_port/mobile/shuttle)
|
||||
if(!shuttle)
|
||||
// the shuttle is missing - no processing
|
||||
update_display("shutl?","")
|
||||
return PROCESS_KILL
|
||||
else if(shuttle.timer)
|
||||
var/line1 = "-[shuttle.getModeStr()]-"
|
||||
var/line2 = shuttle.getTimerStr()
|
||||
|
||||
if(length(line2) > CHARS_PER_LINE)
|
||||
line2 = "error"
|
||||
update_display(line1, line2)
|
||||
else
|
||||
// don't kill processing, the timer might turn back on
|
||||
remove_display()
|
||||
|
||||
/obj/machinery/status_display/proc/examine_shuttle(mob/user, obj/docking_port/mobile/shuttle)
|
||||
if (shuttle)
|
||||
var/modestr = shuttle.getModeStr()
|
||||
if (modestr)
|
||||
if (shuttle.timer)
|
||||
modestr = "<br>\t<tt>[modestr]: [shuttle.getTimerStr()]</tt>"
|
||||
else
|
||||
modestr = "<br>\t<tt>[modestr]</tt>"
|
||||
return "The display says:<br>\t<tt>[shuttle.name]</tt>[modestr]"
|
||||
else
|
||||
return "The display says:<br>\t<tt>Shuttle missing!</tt>"
|
||||
|
||||
|
||||
/// Evac display which shows shuttle timer or message set by Command.
|
||||
/obj/machinery/status_display/evac
|
||||
var/frequency = FREQ_STATUS_DISPLAYS
|
||||
var/mode = SD_EMERGENCY
|
||||
var/friendc = FALSE // track if Friend Computer mode
|
||||
var/last_picture // For when Friend Computer mode is undone
|
||||
|
||||
/obj/machinery/status_display/evac/Initialize()
|
||||
. = ..()
|
||||
// register for radio system
|
||||
SSradio.add_object(src, frequency)
|
||||
|
||||
/obj/machinery/status_display/evac/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/status_display/evac/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(friendc) //Makes all status displays except supply shuttle timer display the eye -- Urist
|
||||
set_picture("ai_friend")
|
||||
return PROCESS_KILL
|
||||
|
||||
switch(mode)
|
||||
if(SD_BLANK)
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(SD_EMERGENCY)
|
||||
return display_shuttle_status(SSshuttle.emergency)
|
||||
|
||||
if(SD_MESSAGE)
|
||||
return ..()
|
||||
|
||||
if(SD_PICTURE)
|
||||
set_picture(last_picture)
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/status_display/evac/examine(mob/user)
|
||||
. = ..()
|
||||
if(mode == SD_EMERGENCY)
|
||||
. += examine_shuttle(user, SSshuttle.emergency)
|
||||
else if(!message1 && !message2)
|
||||
. += "The display is blank."
|
||||
|
||||
/obj/machinery/status_display/evac/receive_signal(datum/signal/signal)
|
||||
switch(signal.data["command"])
|
||||
if("blank")
|
||||
mode = SD_BLANK
|
||||
set_message(null, null)
|
||||
if("shuttle")
|
||||
mode = SD_EMERGENCY
|
||||
set_message(null, null)
|
||||
if("message")
|
||||
mode = SD_MESSAGE
|
||||
set_message(signal.data["msg1"], signal.data["msg2"])
|
||||
if("alert")
|
||||
mode = SD_PICTURE
|
||||
last_picture = signal.data["picture_state"]
|
||||
set_picture(last_picture)
|
||||
if("friendcomputer")
|
||||
friendc = !friendc
|
||||
update()
|
||||
|
||||
|
||||
/// Supply display which shows the status of the supply shuttle.
|
||||
/obj/machinery/status_display/supply
|
||||
name = "supply display"
|
||||
|
||||
/obj/machinery/status_display/supply/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
var/line1
|
||||
var/line2
|
||||
if(!SSshuttle.supply)
|
||||
// Might be missing in our first update on initialize before shuttles
|
||||
// have loaded. Cross our fingers that it will soon return.
|
||||
line1 = "CARGO"
|
||||
line2 = "shutl?"
|
||||
else if(SSshuttle.supply.mode == SHUTTLE_IDLE)
|
||||
if(is_station_level(SSshuttle.supply.z))
|
||||
line1 = "CARGO"
|
||||
line2 = "Docked"
|
||||
else
|
||||
line1 = "CARGO"
|
||||
line2 = SSshuttle.supply.getTimerStr()
|
||||
if(length(line2) > CHARS_PER_LINE)
|
||||
line2 = "Error"
|
||||
update_display(line1, line2)
|
||||
|
||||
/obj/machinery/status_display/supply/examine(mob/user)
|
||||
. = ..()
|
||||
var/obj/docking_port/mobile/shuttle = SSshuttle.supply
|
||||
var/shuttleMsg = null
|
||||
if (shuttle.mode == SHUTTLE_IDLE)
|
||||
if (is_station_level(shuttle.z))
|
||||
shuttleMsg = "Docked"
|
||||
else
|
||||
shuttleMsg = "[shuttle.getModeStr()]: [shuttle.getTimerStr()]"
|
||||
if (shuttleMsg)
|
||||
. += "The display says:<br>\t<tt>[shuttleMsg]</tt>"
|
||||
else
|
||||
. += "The display is blank."
|
||||
|
||||
|
||||
/// General-purpose shuttle status display.
|
||||
/obj/machinery/status_display/shuttle
|
||||
name = "shuttle display"
|
||||
var/shuttle_id
|
||||
|
||||
/obj/machinery/status_display/shuttle/process()
|
||||
if(!shuttle_id || (stat & NOPOWER))
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
return display_shuttle_status(SSshuttle.getShuttle(shuttle_id))
|
||||
|
||||
/obj/machinery/status_display/shuttle/examine(mob/user)
|
||||
. = ..()
|
||||
if(shuttle_id)
|
||||
. += examine_shuttle(user, SSshuttle.getShuttle(shuttle_id))
|
||||
else
|
||||
. += "The display is blank."
|
||||
|
||||
/obj/machinery/status_display/shuttle/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
switch(var_name)
|
||||
if("shuttle_id")
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
if (port && (shuttle_id == initial(shuttle_id) || override))
|
||||
shuttle_id = port.id
|
||||
update()
|
||||
|
||||
|
||||
/// Pictograph display which the AI can use to emote.
|
||||
/obj/machinery/status_display/ai
|
||||
name = "\improper AI display"
|
||||
desc = "A small screen which the AI can use to present itself."
|
||||
|
||||
var/mode = SD_BLANK
|
||||
var/emotion = "Neutral"
|
||||
|
||||
/obj/machinery/status_display/ai/Initialize()
|
||||
. = ..()
|
||||
GLOB.ai_status_displays.Add(src)
|
||||
|
||||
/obj/machinery/status_display/ai/Destroy()
|
||||
GLOB.ai_status_displays.Remove(src)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/status_display/ai/attack_ai(mob/living/silicon/ai/user)
|
||||
if(isAI(user))
|
||||
user.ai_statuschange()
|
||||
|
||||
/obj/machinery/status_display/ai/process()
|
||||
if(mode == SD_BLANK || (stat & NOPOWER))
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(mode == SD_AI_EMOTE)
|
||||
switch(emotion)
|
||||
if("Very Happy")
|
||||
set_picture("ai_veryhappy")
|
||||
if("Happy")
|
||||
set_picture("ai_happy")
|
||||
if("Neutral")
|
||||
set_picture("ai_neutral")
|
||||
if("Unsure")
|
||||
set_picture("ai_unsure")
|
||||
if("Confused")
|
||||
set_picture("ai_confused")
|
||||
if("Sad")
|
||||
set_picture("ai_sad")
|
||||
if("BSOD")
|
||||
set_picture("ai_bsod")
|
||||
if("Blank")
|
||||
set_picture("ai_off")
|
||||
if("Problems?")
|
||||
set_picture("ai_trollface")
|
||||
if("Awesome")
|
||||
set_picture("ai_awesome")
|
||||
if("Dorfy")
|
||||
set_picture("ai_urist")
|
||||
if("Thinking")
|
||||
set_picture("ai_thinking")
|
||||
if("Facepalm")
|
||||
set_picture("ai_facepalm")
|
||||
if("Friend Computer")
|
||||
set_picture("ai_friend")
|
||||
if("Blue Glow")
|
||||
set_picture("ai_sal")
|
||||
if("Red Glow")
|
||||
set_picture("ai_hal")
|
||||
return PROCESS_KILL
|
||||
|
||||
if(mode == SD_AI_BSOD)
|
||||
set_picture("ai_bsod")
|
||||
return PROCESS_KILL
|
||||
|
||||
|
||||
#undef CHARS_PER_LINE
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef SCROLL_SPEED
|
||||
// Status display
|
||||
// (formerly Countdown timer display)
|
||||
|
||||
#define CHARS_PER_LINE 5
|
||||
#define FONT_SIZE "5pt"
|
||||
#define FONT_COLOR "#09f"
|
||||
#define FONT_STYLE "Arial Black"
|
||||
#define SCROLL_SPEED 2
|
||||
|
||||
#define SD_BLANK 0 // 0 = Blank
|
||||
#define SD_EMERGENCY 1 // 1 = Emergency Shuttle timer
|
||||
#define SD_MESSAGE 2 // 2 = Arbitrary message(s)
|
||||
#define SD_PICTURE 3 // 3 = alert picture
|
||||
|
||||
#define SD_AI_EMOTE 1 // 1 = AI emoticon
|
||||
#define SD_AI_BSOD 2 // 2 = Blue screen of death
|
||||
|
||||
/// Status display which can show images and scrolling text.
|
||||
/obj/machinery/status_display
|
||||
name = "status display"
|
||||
desc = null
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
|
||||
maptext_height = 26
|
||||
maptext_width = 32
|
||||
|
||||
var/message1 = "" // message line 1
|
||||
var/message2 = "" // message line 2
|
||||
var/index1 // display index for scrolling messages or 0 if non-scrolling
|
||||
var/index2
|
||||
|
||||
/// Immediately blank the display.
|
||||
/obj/machinery/status_display/proc/remove_display()
|
||||
cut_overlays()
|
||||
if(maptext)
|
||||
maptext = ""
|
||||
|
||||
/// Immediately change the display to the given picture.
|
||||
/obj/machinery/status_display/proc/set_picture(state)
|
||||
remove_display()
|
||||
add_overlay(state)
|
||||
|
||||
/// Immediately change the display to the given two lines.
|
||||
/obj/machinery/status_display/proc/update_display(line1, line2)
|
||||
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
|
||||
if(maptext != new_text)
|
||||
maptext = new_text
|
||||
|
||||
/// Prepare the display to marquee the given two lines.
|
||||
///
|
||||
/// Call with no arguments to disable.
|
||||
/obj/machinery/status_display/proc/set_message(m1, m2)
|
||||
if(m1)
|
||||
index1 = (length(m1) > CHARS_PER_LINE)
|
||||
message1 = m1
|
||||
else
|
||||
message1 = ""
|
||||
index1 = 0
|
||||
|
||||
if(m2)
|
||||
index2 = (length(m2) > CHARS_PER_LINE)
|
||||
message2 = m2
|
||||
else
|
||||
message2 = ""
|
||||
index2 = 0
|
||||
|
||||
// Timed process - performs default marquee action if so needed.
|
||||
/obj/machinery/status_display/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
var/line1 = message1
|
||||
if(index1)
|
||||
line1 = copytext("[message1]|[message1]", index1, index1+CHARS_PER_LINE)
|
||||
var/message1_len = length(message1)
|
||||
index1 += SCROLL_SPEED
|
||||
if(index1 > message1_len)
|
||||
index1 -= message1_len
|
||||
|
||||
var/line2 = message2
|
||||
if(index2)
|
||||
line2 = copytext("[message2]|[message2]", index2, index2+CHARS_PER_LINE)
|
||||
var/message2_len = length(message2)
|
||||
index2 += SCROLL_SPEED
|
||||
if(index2 > message2_len)
|
||||
index2 -= message2_len
|
||||
|
||||
update_display(line1, line2)
|
||||
if (!index1 && !index2)
|
||||
// No marquee, no processing.
|
||||
return PROCESS_KILL
|
||||
|
||||
/// Update the display and, if necessary, re-enable processing.
|
||||
/obj/machinery/status_display/proc/update()
|
||||
if (process() != PROCESS_KILL)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
|
||||
/obj/machinery/status_display/power_change()
|
||||
. = ..()
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/emp_act(severity)
|
||||
. = ..()
|
||||
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
|
||||
return
|
||||
set_picture("ai_bsod")
|
||||
|
||||
/obj/machinery/status_display/examine(mob/user)
|
||||
. = ..()
|
||||
if (message1 || message2)
|
||||
. += "The display says:"
|
||||
if (message1)
|
||||
. += "\t<tt>[html_encode(message1)]</tt>"
|
||||
if (message2)
|
||||
. += "\t<tt>[html_encode(message2)]</tt>"
|
||||
|
||||
// Helper procs for child display types.
|
||||
/obj/machinery/status_display/proc/display_shuttle_status(obj/docking_port/mobile/shuttle)
|
||||
if(!shuttle)
|
||||
// the shuttle is missing - no processing
|
||||
update_display("shutl?","")
|
||||
return PROCESS_KILL
|
||||
else if(shuttle.timer)
|
||||
var/line1 = "-[shuttle.getModeStr()]-"
|
||||
var/line2 = shuttle.getTimerStr()
|
||||
|
||||
if(length(line2) > CHARS_PER_LINE)
|
||||
line2 = "error"
|
||||
update_display(line1, line2)
|
||||
else
|
||||
// don't kill processing, the timer might turn back on
|
||||
remove_display()
|
||||
|
||||
/obj/machinery/status_display/proc/examine_shuttle(mob/user, obj/docking_port/mobile/shuttle)
|
||||
if (shuttle)
|
||||
var/modestr = shuttle.getModeStr()
|
||||
if (modestr)
|
||||
if (shuttle.timer)
|
||||
modestr = "<br>\t<tt>[modestr]: [shuttle.getTimerStr()]</tt>"
|
||||
else
|
||||
modestr = "<br>\t<tt>[modestr]</tt>"
|
||||
return "The display says:<br>\t<tt>[shuttle.name]</tt>[modestr]"
|
||||
else
|
||||
return "The display says:<br>\t<tt>Shuttle missing!</tt>"
|
||||
|
||||
|
||||
/// Evac display which shows shuttle timer or message set by Command.
|
||||
/obj/machinery/status_display/evac
|
||||
var/frequency = FREQ_STATUS_DISPLAYS
|
||||
var/mode = SD_EMERGENCY
|
||||
var/friendc = FALSE // track if Friend Computer mode
|
||||
var/last_picture // For when Friend Computer mode is undone
|
||||
|
||||
/obj/machinery/status_display/evac/Initialize()
|
||||
. = ..()
|
||||
// register for radio system
|
||||
SSradio.add_object(src, frequency)
|
||||
|
||||
/obj/machinery/status_display/evac/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/status_display/evac/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(friendc) //Makes all status displays except supply shuttle timer display the eye -- Urist
|
||||
set_picture("ai_friend")
|
||||
return PROCESS_KILL
|
||||
|
||||
switch(mode)
|
||||
if(SD_BLANK)
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(SD_EMERGENCY)
|
||||
return display_shuttle_status(SSshuttle.emergency)
|
||||
|
||||
if(SD_MESSAGE)
|
||||
return ..()
|
||||
|
||||
if(SD_PICTURE)
|
||||
set_picture(last_picture)
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/status_display/evac/examine(mob/user)
|
||||
. = ..()
|
||||
if(mode == SD_EMERGENCY)
|
||||
. += examine_shuttle(user, SSshuttle.emergency)
|
||||
else if(!message1 && !message2)
|
||||
. += "The display is blank."
|
||||
|
||||
/obj/machinery/status_display/evac/receive_signal(datum/signal/signal)
|
||||
switch(signal.data["command"])
|
||||
if("blank")
|
||||
mode = SD_BLANK
|
||||
set_message(null, null)
|
||||
if("shuttle")
|
||||
mode = SD_EMERGENCY
|
||||
set_message(null, null)
|
||||
if("message")
|
||||
mode = SD_MESSAGE
|
||||
set_message(signal.data["msg1"], signal.data["msg2"])
|
||||
if("alert")
|
||||
mode = SD_PICTURE
|
||||
last_picture = signal.data["picture_state"]
|
||||
set_picture(last_picture)
|
||||
if("friendcomputer")
|
||||
friendc = !friendc
|
||||
update()
|
||||
|
||||
|
||||
/// Supply display which shows the status of the supply shuttle.
|
||||
/obj/machinery/status_display/supply
|
||||
name = "supply display"
|
||||
|
||||
/obj/machinery/status_display/supply/process()
|
||||
if(stat & NOPOWER)
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
var/line1
|
||||
var/line2
|
||||
if(!SSshuttle.supply)
|
||||
// Might be missing in our first update on initialize before shuttles
|
||||
// have loaded. Cross our fingers that it will soon return.
|
||||
line1 = "CARGO"
|
||||
line2 = "shutl?"
|
||||
else if(SSshuttle.supply.mode == SHUTTLE_IDLE)
|
||||
if(is_station_level(SSshuttle.supply.z))
|
||||
line1 = "CARGO"
|
||||
line2 = "Docked"
|
||||
else
|
||||
line1 = "CARGO"
|
||||
line2 = SSshuttle.supply.getTimerStr()
|
||||
if(length(line2) > CHARS_PER_LINE)
|
||||
line2 = "Error"
|
||||
update_display(line1, line2)
|
||||
|
||||
/obj/machinery/status_display/supply/examine(mob/user)
|
||||
. = ..()
|
||||
var/obj/docking_port/mobile/shuttle = SSshuttle.supply
|
||||
var/shuttleMsg = null
|
||||
if (shuttle.mode == SHUTTLE_IDLE)
|
||||
if (is_station_level(shuttle.z))
|
||||
shuttleMsg = "Docked"
|
||||
else
|
||||
shuttleMsg = "[shuttle.getModeStr()]: [shuttle.getTimerStr()]"
|
||||
if (shuttleMsg)
|
||||
. += "The display says:<br>\t<tt>[shuttleMsg]</tt>"
|
||||
else
|
||||
. += "The display is blank."
|
||||
|
||||
|
||||
/// General-purpose shuttle status display.
|
||||
/obj/machinery/status_display/shuttle
|
||||
name = "shuttle display"
|
||||
var/shuttle_id
|
||||
|
||||
/obj/machinery/status_display/shuttle/process()
|
||||
if(!shuttle_id || (stat & NOPOWER))
|
||||
// No power, no processing.
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
return display_shuttle_status(SSshuttle.getShuttle(shuttle_id))
|
||||
|
||||
/obj/machinery/status_display/shuttle/examine(mob/user)
|
||||
. = ..()
|
||||
if(shuttle_id)
|
||||
. += examine_shuttle(user, SSshuttle.getShuttle(shuttle_id))
|
||||
else
|
||||
. += "The display is blank."
|
||||
|
||||
/obj/machinery/status_display/shuttle/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
switch(var_name)
|
||||
if("shuttle_id")
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
if (port && (shuttle_id == initial(shuttle_id) || override))
|
||||
shuttle_id = port.id
|
||||
update()
|
||||
|
||||
|
||||
/// Pictograph display which the AI can use to emote.
|
||||
/obj/machinery/status_display/ai
|
||||
name = "\improper AI display"
|
||||
desc = "A small screen which the AI can use to present itself."
|
||||
|
||||
var/mode = SD_BLANK
|
||||
var/emotion = "Neutral"
|
||||
|
||||
/obj/machinery/status_display/ai/Initialize()
|
||||
. = ..()
|
||||
GLOB.ai_status_displays.Add(src)
|
||||
|
||||
/obj/machinery/status_display/ai/Destroy()
|
||||
GLOB.ai_status_displays.Remove(src)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/status_display/ai/attack_ai(mob/living/silicon/ai/user)
|
||||
if(isAI(user))
|
||||
user.ai_statuschange()
|
||||
|
||||
/obj/machinery/status_display/ai/process()
|
||||
if(mode == SD_BLANK || (stat & NOPOWER))
|
||||
remove_display()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(mode == SD_AI_EMOTE)
|
||||
switch(emotion)
|
||||
if("Very Happy")
|
||||
set_picture("ai_veryhappy")
|
||||
if("Happy")
|
||||
set_picture("ai_happy")
|
||||
if("Neutral")
|
||||
set_picture("ai_neutral")
|
||||
if("Unsure")
|
||||
set_picture("ai_unsure")
|
||||
if("Confused")
|
||||
set_picture("ai_confused")
|
||||
if("Sad")
|
||||
set_picture("ai_sad")
|
||||
if("BSOD")
|
||||
set_picture("ai_bsod")
|
||||
if("Blank")
|
||||
set_picture("ai_off")
|
||||
if("Problems?")
|
||||
set_picture("ai_trollface")
|
||||
if("Awesome")
|
||||
set_picture("ai_awesome")
|
||||
if("Dorfy")
|
||||
set_picture("ai_urist")
|
||||
if("Thinking")
|
||||
set_picture("ai_thinking")
|
||||
if("Facepalm")
|
||||
set_picture("ai_facepalm")
|
||||
if("Friend Computer")
|
||||
set_picture("ai_friend")
|
||||
if("Blue Glow")
|
||||
set_picture("ai_sal")
|
||||
if("Red Glow")
|
||||
set_picture("ai_hal")
|
||||
return PROCESS_KILL
|
||||
|
||||
if(mode == SD_AI_BSOD)
|
||||
set_picture("ai_bsod")
|
||||
return PROCESS_KILL
|
||||
|
||||
|
||||
#undef CHARS_PER_LINE
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef SCROLL_SPEED
|
||||
|
||||
@@ -1,443 +1,443 @@
|
||||
// SUIT STORAGE UNIT /////////////////
|
||||
/obj/machinery/suit_storage_unit
|
||||
name = "suit storage unit"
|
||||
desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
|
||||
icon = 'icons/obj/machines/suit_storage.dmi'
|
||||
icon_state = "close"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
|
||||
var/obj/item/clothing/suit/space/suit = null
|
||||
var/obj/item/clothing/head/helmet/space/helmet = null
|
||||
var/obj/item/clothing/mask/mask = null
|
||||
var/obj/item/storage = null
|
||||
|
||||
var/suit_type = null
|
||||
var/helmet_type = null
|
||||
var/mask_type = null
|
||||
var/storage_type = null
|
||||
|
||||
state_open = FALSE
|
||||
var/locked = FALSE
|
||||
panel_open = FALSE
|
||||
var/safeties = TRUE
|
||||
|
||||
var/uv = FALSE
|
||||
var/uv_super = FALSE
|
||||
var/uv_cycles = 6
|
||||
var/message_cooldown
|
||||
var/breakout_time = 300
|
||||
|
||||
/obj/machinery/suit_storage_unit/standard_unit
|
||||
suit_type = /obj/item/clothing/suit/space/eva
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/eva
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/captain
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/captain
|
||||
|
||||
/obj/machinery/suit_storage_unit/engine
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots
|
||||
|
||||
/obj/machinery/suit_storage_unit/ce
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots/advance
|
||||
|
||||
/obj/machinery/suit_storage_unit/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/security
|
||||
|
||||
/obj/machinery/suit_storage_unit/hos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
/obj/machinery/suit_storage_unit/atmos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
|
||||
mask_type = /obj/item/clothing/mask/gas
|
||||
storage_type = /obj/item/watertank/atmos
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining
|
||||
suit_type = /obj/item/clothing/suit/hooded/explorer/standard
|
||||
mask_type = /obj/item/clothing/mask/gas/explorer
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining/eva
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/cmo
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/rd
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/syndicate
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
mask_type = /obj/item/clothing/mask/gas/syndicate
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/harness
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/command
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/engineer
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/medical
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/radsuit
|
||||
name = "radiation suit storage unit"
|
||||
suit_type = /obj/item/clothing/suit/radiation
|
||||
helmet_type = /obj/item/clothing/head/radiation
|
||||
storage_type = /obj/item/geiger_counter
|
||||
|
||||
/obj/machinery/suit_storage_unit/open
|
||||
state_open = TRUE
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/suit_storage_unit/Initialize()
|
||||
. = ..()
|
||||
wires = new /datum/wires/suit_storage_unit(src)
|
||||
if(suit_type)
|
||||
suit = new suit_type(src)
|
||||
if(helmet_type)
|
||||
helmet = new helmet_type(src)
|
||||
if(mask_type)
|
||||
mask = new mask_type(src)
|
||||
if(storage_type)
|
||||
storage = new storage_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/Destroy()
|
||||
QDEL_NULL(suit)
|
||||
QDEL_NULL(helmet)
|
||||
QDEL_NULL(mask)
|
||||
QDEL_NULL(storage)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(uv)
|
||||
if(uv_super)
|
||||
add_overlay("super")
|
||||
else if(occupant)
|
||||
add_overlay("uvhuman")
|
||||
else
|
||||
add_overlay("uv")
|
||||
else if(state_open)
|
||||
if(stat & BROKEN)
|
||||
add_overlay("broken")
|
||||
else
|
||||
add_overlay("open")
|
||||
if(suit)
|
||||
add_overlay("suit")
|
||||
if(helmet)
|
||||
add_overlay("helm")
|
||||
if(storage)
|
||||
add_overlay("storage")
|
||||
else if(occupant)
|
||||
add_overlay("human")
|
||||
|
||||
/obj/machinery/suit_storage_unit/power_change()
|
||||
..()
|
||||
if(!is_operational() && state_open)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/dump_contents()
|
||||
dropContents()
|
||||
helmet = null
|
||||
suit = null
|
||||
mask = null
|
||||
storage = null
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
open_machine()
|
||||
dump_contents()
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
|
||||
return
|
||||
var/mob/living/target = A
|
||||
if(!state_open)
|
||||
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
|
||||
return
|
||||
if(!is_operational())
|
||||
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
|
||||
return
|
||||
if(occupant || helmet || suit || storage)
|
||||
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
|
||||
return
|
||||
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
|
||||
|
||||
if(do_mob(user, target, 30))
|
||||
if(occupant || helmet || suit || storage)
|
||||
return
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
|
||||
close_machine(target)
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/cook()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_cycles)
|
||||
uv_cycles--
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
if(uv_super)
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
mob_occupant.adjustFireLoss(rand(10, 16))
|
||||
mob_occupant.emote("scream")
|
||||
addtimer(CALLBACK(src, .proc/cook), 50)
|
||||
else
|
||||
uv_cycles = initial(uv_cycles)
|
||||
uv = FALSE
|
||||
locked = FALSE
|
||||
if(uv_super)
|
||||
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
|
||||
helmet = null
|
||||
qdel(helmet)
|
||||
suit = null
|
||||
qdel(suit) // Delete everything but the occupant.
|
||||
mask = null
|
||||
qdel(mask)
|
||||
storage = null
|
||||
qdel(storage)
|
||||
// The wires get damaged too.
|
||||
wires.cut_all()
|
||||
else
|
||||
if(!occupant)
|
||||
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
|
||||
mob_occupant.radiation = 0
|
||||
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
|
||||
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
|
||||
if(suit)
|
||||
things_to_clear += suit
|
||||
things_to_clear += suit.GetAllContents()
|
||||
if(helmet)
|
||||
things_to_clear += helmet
|
||||
things_to_clear += helmet.GetAllContents()
|
||||
if(mask)
|
||||
things_to_clear += mask
|
||||
things_to_clear += mask.GetAllContents()
|
||||
if(storage)
|
||||
things_to_clear += storage
|
||||
things_to_clear += storage.GetAllContents()
|
||||
if(occupant)
|
||||
things_to_clear += occupant
|
||||
things_to_clear += occupant.GetAllContents()
|
||||
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
AM.clean_blood()
|
||||
AM.fingerprints = list()
|
||||
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
|
||||
if(contamination)
|
||||
qdel(contamination)
|
||||
open_machine(FALSE)
|
||||
if(occupant)
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
|
||||
if(!prob(prb))
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if(electrocute_mob(user, src, src, 1, TRUE))
|
||||
return 1
|
||||
|
||||
/obj/machinery/suit_storage_unit/relaymove(mob/user)
|
||||
if(locked)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
|
||||
if(!locked)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src )
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
add_fingerprint(user)
|
||||
if(locked)
|
||||
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors...</span>")
|
||||
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
|
||||
else
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
|
||||
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
|
||||
visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \
|
||||
"<span class='notice'>You escape the cramped confines of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
|
||||
if(state_open && is_operational())
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/clothing/suit))
|
||||
if(suit)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
suit = I
|
||||
else if(istype(I, /obj/item/clothing/head))
|
||||
if(helmet)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
helmet = I
|
||||
else if(istype(I, /obj/item/clothing/mask))
|
||||
if(mask)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
mask = I
|
||||
else
|
||||
if(storage)
|
||||
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
storage = I
|
||||
|
||||
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(I))
|
||||
wires.interact(user)
|
||||
return
|
||||
if(!state_open)
|
||||
if(default_deconstruction_screwdriver(user, "panel", "close", I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
dump_contents()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
var/list/data = list()
|
||||
data["locked"] = locked
|
||||
data["open"] = state_open
|
||||
data["safeties"] = safeties
|
||||
data["uv_active"] = uv
|
||||
data["uv_super"] = uv_super
|
||||
if(helmet)
|
||||
data["helmet"] = helmet.name
|
||||
if(suit)
|
||||
data["suit"] = suit.name
|
||||
if(mask)
|
||||
data["mask"] = mask.name
|
||||
if(storage)
|
||||
data["storage"] = storage.name
|
||||
if(occupant)
|
||||
data["occupied"] = 1
|
||||
return data
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_act(action, params)
|
||||
if(..() || uv)
|
||||
return
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine(0)
|
||||
if(occupant)
|
||||
dump_contents() // Dump out contents if someone is in there.
|
||||
. = TRUE
|
||||
if("lock")
|
||||
if(state_open)
|
||||
return
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("uv")
|
||||
if(occupant && safeties)
|
||||
return
|
||||
else if(!helmet && !mask && !suit && !storage && !occupant)
|
||||
return
|
||||
else
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
|
||||
cook()
|
||||
. = TRUE
|
||||
if("dispense")
|
||||
if(!state_open)
|
||||
return
|
||||
|
||||
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
|
||||
var/item_name = params["item"]
|
||||
if(item_name in valid_items)
|
||||
var/obj/item/I = vars[item_name]
|
||||
vars[item_name] = null
|
||||
if(I)
|
||||
I.forceMove(loc)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
// SUIT STORAGE UNIT /////////////////
|
||||
/obj/machinery/suit_storage_unit
|
||||
name = "suit storage unit"
|
||||
desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
|
||||
icon = 'icons/obj/machines/suit_storage.dmi'
|
||||
icon_state = "close"
|
||||
density = TRUE
|
||||
max_integrity = 250
|
||||
|
||||
var/obj/item/clothing/suit/space/suit = null
|
||||
var/obj/item/clothing/head/helmet/space/helmet = null
|
||||
var/obj/item/clothing/mask/mask = null
|
||||
var/obj/item/storage = null
|
||||
|
||||
var/suit_type = null
|
||||
var/helmet_type = null
|
||||
var/mask_type = null
|
||||
var/storage_type = null
|
||||
|
||||
state_open = FALSE
|
||||
var/locked = FALSE
|
||||
panel_open = FALSE
|
||||
var/safeties = TRUE
|
||||
|
||||
var/uv = FALSE
|
||||
var/uv_super = FALSE
|
||||
var/uv_cycles = 6
|
||||
var/message_cooldown
|
||||
var/breakout_time = 300
|
||||
|
||||
/obj/machinery/suit_storage_unit/standard_unit
|
||||
suit_type = /obj/item/clothing/suit/space/eva
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/eva
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/captain
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/captain
|
||||
|
||||
/obj/machinery/suit_storage_unit/engine
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots
|
||||
|
||||
/obj/machinery/suit_storage_unit/ce
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type= /obj/item/clothing/shoes/magboots/advance
|
||||
|
||||
/obj/machinery/suit_storage_unit/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/security
|
||||
|
||||
/obj/machinery/suit_storage_unit/hos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
|
||||
mask_type = /obj/item/clothing/mask/gas/sechailer
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
/obj/machinery/suit_storage_unit/atmos
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
|
||||
mask_type = /obj/item/clothing/mask/gas
|
||||
storage_type = /obj/item/watertank/atmos
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining
|
||||
suit_type = /obj/item/clothing/suit/hooded/explorer/standard
|
||||
mask_type = /obj/item/clothing/mask/gas/explorer
|
||||
|
||||
/obj/machinery/suit_storage_unit/mining/eva
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/cmo
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/rd
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
|
||||
/obj/machinery/suit_storage_unit/syndicate
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
mask_type = /obj/item/clothing/mask/gas/syndicate
|
||||
storage_type = /obj/item/tank/jetpack/oxygen/harness
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/command
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/security
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/engineer
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/ert/medical
|
||||
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/emergency_oxygen/double
|
||||
|
||||
/obj/machinery/suit_storage_unit/radsuit
|
||||
name = "radiation suit storage unit"
|
||||
suit_type = /obj/item/clothing/suit/radiation
|
||||
helmet_type = /obj/item/clothing/head/radiation
|
||||
storage_type = /obj/item/geiger_counter
|
||||
|
||||
/obj/machinery/suit_storage_unit/open
|
||||
state_open = TRUE
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/suit_storage_unit/Initialize()
|
||||
. = ..()
|
||||
wires = new /datum/wires/suit_storage_unit(src)
|
||||
if(suit_type)
|
||||
suit = new suit_type(src)
|
||||
if(helmet_type)
|
||||
helmet = new helmet_type(src)
|
||||
if(mask_type)
|
||||
mask = new mask_type(src)
|
||||
if(storage_type)
|
||||
storage = new storage_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/Destroy()
|
||||
QDEL_NULL(suit)
|
||||
QDEL_NULL(helmet)
|
||||
QDEL_NULL(mask)
|
||||
QDEL_NULL(storage)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
if(uv)
|
||||
if(uv_super)
|
||||
add_overlay("super")
|
||||
else if(occupant)
|
||||
add_overlay("uvhuman")
|
||||
else
|
||||
add_overlay("uv")
|
||||
else if(state_open)
|
||||
if(stat & BROKEN)
|
||||
add_overlay("broken")
|
||||
else
|
||||
add_overlay("open")
|
||||
if(suit)
|
||||
add_overlay("suit")
|
||||
if(helmet)
|
||||
add_overlay("helm")
|
||||
if(storage)
|
||||
add_overlay("storage")
|
||||
else if(occupant)
|
||||
add_overlay("human")
|
||||
|
||||
/obj/machinery/suit_storage_unit/power_change()
|
||||
..()
|
||||
if(!is_operational() && state_open)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/dump_contents()
|
||||
dropContents()
|
||||
helmet = null
|
||||
suit = null
|
||||
mask = null
|
||||
storage = null
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
open_machine()
|
||||
dump_contents()
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
|
||||
return
|
||||
var/mob/living/target = A
|
||||
if(!state_open)
|
||||
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
|
||||
return
|
||||
if(!is_operational())
|
||||
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
|
||||
return
|
||||
if(occupant || helmet || suit || storage)
|
||||
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
|
||||
return
|
||||
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
|
||||
|
||||
if(do_mob(user, target, 30))
|
||||
if(occupant || helmet || suit || storage)
|
||||
return
|
||||
if(target == user)
|
||||
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
|
||||
else
|
||||
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
|
||||
close_machine(target)
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/cook()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_cycles)
|
||||
uv_cycles--
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
if(uv_super)
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
mob_occupant.adjustFireLoss(rand(10, 16))
|
||||
mob_occupant.emote("scream")
|
||||
addtimer(CALLBACK(src, .proc/cook), 50)
|
||||
else
|
||||
uv_cycles = initial(uv_cycles)
|
||||
uv = FALSE
|
||||
locked = FALSE
|
||||
if(uv_super)
|
||||
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
|
||||
helmet = null
|
||||
qdel(helmet)
|
||||
suit = null
|
||||
qdel(suit) // Delete everything but the occupant.
|
||||
mask = null
|
||||
qdel(mask)
|
||||
storage = null
|
||||
qdel(storage)
|
||||
// The wires get damaged too.
|
||||
wires.cut_all()
|
||||
else
|
||||
if(!occupant)
|
||||
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
|
||||
mob_occupant.radiation = 0
|
||||
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
|
||||
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
|
||||
if(suit)
|
||||
things_to_clear += suit
|
||||
things_to_clear += suit.GetAllContents()
|
||||
if(helmet)
|
||||
things_to_clear += helmet
|
||||
things_to_clear += helmet.GetAllContents()
|
||||
if(mask)
|
||||
things_to_clear += mask
|
||||
things_to_clear += mask.GetAllContents()
|
||||
if(storage)
|
||||
things_to_clear += storage
|
||||
things_to_clear += storage.GetAllContents()
|
||||
if(occupant)
|
||||
things_to_clear += occupant
|
||||
things_to_clear += occupant.GetAllContents()
|
||||
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
AM.clean_blood()
|
||||
AM.fingerprints = list()
|
||||
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
|
||||
if(contamination)
|
||||
qdel(contamination)
|
||||
open_machine(FALSE)
|
||||
if(occupant)
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
|
||||
if(!prob(prb))
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if(electrocute_mob(user, src, src, 1, TRUE))
|
||||
return 1
|
||||
|
||||
/obj/machinery/suit_storage_unit/relaymove(mob/user)
|
||||
if(locked)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
return
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
|
||||
if(!locked)
|
||||
open_machine()
|
||||
dump_contents()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src )
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
add_fingerprint(user)
|
||||
if(locked)
|
||||
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors...</span>")
|
||||
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
|
||||
else
|
||||
open_machine()
|
||||
dump_contents()
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
|
||||
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
|
||||
visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \
|
||||
"<span class='notice'>You escape the cramped confines of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
|
||||
if(state_open && is_operational())
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/clothing/suit))
|
||||
if(suit)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
suit = I
|
||||
else if(istype(I, /obj/item/clothing/head))
|
||||
if(helmet)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
helmet = I
|
||||
else if(istype(I, /obj/item/clothing/mask))
|
||||
if(mask)
|
||||
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
mask = I
|
||||
else
|
||||
if(storage)
|
||||
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
storage = I
|
||||
|
||||
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(I))
|
||||
wires.interact(user)
|
||||
return
|
||||
if(!state_open)
|
||||
if(default_deconstruction_screwdriver(user, "panel", "close", I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
dump_contents()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
var/list/data = list()
|
||||
data["locked"] = locked
|
||||
data["open"] = state_open
|
||||
data["safeties"] = safeties
|
||||
data["uv_active"] = uv
|
||||
data["uv_super"] = uv_super
|
||||
if(helmet)
|
||||
data["helmet"] = helmet.name
|
||||
if(suit)
|
||||
data["suit"] = suit.name
|
||||
if(mask)
|
||||
data["mask"] = mask.name
|
||||
if(storage)
|
||||
data["storage"] = storage.name
|
||||
if(occupant)
|
||||
data["occupied"] = 1
|
||||
return data
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_act(action, params)
|
||||
if(..() || uv)
|
||||
return
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine(0)
|
||||
if(occupant)
|
||||
dump_contents() // Dump out contents if someone is in there.
|
||||
. = TRUE
|
||||
if("lock")
|
||||
if(state_open)
|
||||
return
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("uv")
|
||||
if(occupant && safeties)
|
||||
return
|
||||
else if(!helmet && !mask && !suit && !storage && !occupant)
|
||||
return
|
||||
else
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
|
||||
cook()
|
||||
. = TRUE
|
||||
if("dispense")
|
||||
if(!state_open)
|
||||
return
|
||||
|
||||
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
|
||||
var/item_name = params["item"]
|
||||
if(item_name in valid_items)
|
||||
var/obj/item/I = vars[item_name]
|
||||
vars[item_name] = null
|
||||
if(I)
|
||||
I.forceMove(loc)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -1,165 +1,165 @@
|
||||
GLOBAL_VAR_INIT(singularity_counter, 0)
|
||||
|
||||
#define METEOR_DISASTER_MODIFIER 0.5
|
||||
|
||||
////////////////////////////////////////
|
||||
//Singularity beacon
|
||||
////////////////////////////////////////
|
||||
/obj/machinery/power/singularity_beacon
|
||||
name = "ominous beacon"
|
||||
desc = "This looks suspicious..."
|
||||
icon = 'icons/obj/singularity.dmi'
|
||||
icon_state = "beacon0"
|
||||
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
layer = BELOW_MOB_LAYER //so people can't hide it and it's REALLY OBVIOUS
|
||||
stat = 0
|
||||
verb_say = "states"
|
||||
var/cooldown = 0
|
||||
var/active = FALSE
|
||||
var/meteor_buff = FALSE
|
||||
var/icontype = "beacon"
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/Activate(mob/user = null)
|
||||
if(active)
|
||||
return FALSE
|
||||
if(surplus() < 1500)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>The connected wire doesn't have enough current.</span>")
|
||||
return FALSE
|
||||
if(is_station_level(z))
|
||||
increment_meteor_waves()
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.z == z)
|
||||
singulo.target = src
|
||||
icon_state = "[icontype]1"
|
||||
active = TRUE
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You activate the beacon.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user)
|
||||
if(!active)
|
||||
return FALSE
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.target == src)
|
||||
singulo.target = null
|
||||
icon_state = "[icontype]0"
|
||||
active = FALSE
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You deactivate the beacon.</span>")
|
||||
if(meteor_buff)
|
||||
decrement_meteor_waves()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/increment_meteor_waves()
|
||||
meteor_buff = TRUE
|
||||
GLOB.singularity_counter++
|
||||
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
|
||||
W.weight += round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/decrement_meteor_waves()
|
||||
meteor_buff = FALSE
|
||||
GLOB.singularity_counter--
|
||||
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
|
||||
W.weight -= round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(anchored)
|
||||
return active ? Deactivate(user) : Activate(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to screw the beacon to the floor first!</span>")
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(active)
|
||||
to_chat(user, "<span class='warning'>You need to deactivate the beacon first!</span>")
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
setAnchored(FALSE)
|
||||
to_chat(user, "<span class='notice'>You unscrew the beacon from the floor.</span>")
|
||||
disconnect_from_network()
|
||||
return
|
||||
else
|
||||
if(!connect_to_network())
|
||||
to_chat(user, "<span class='warning'>This device must be placed over an exposed, powered cable node!</span>")
|
||||
return
|
||||
setAnchored(TRUE)
|
||||
to_chat(user, "<span class='notice'>You screw the beacon to the floor and attach the cable.</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/singularity_beacon/Destroy()
|
||||
if(active)
|
||||
Deactivate()
|
||||
return ..()
|
||||
|
||||
//stealth direct power usage
|
||||
/obj/machinery/power/singularity_beacon/process()
|
||||
if(!active)
|
||||
return
|
||||
|
||||
var/is_on_station = is_station_level(z)
|
||||
if(meteor_buff && !is_on_station)
|
||||
decrement_meteor_waves()
|
||||
else if(!meteor_buff && is_on_station)
|
||||
increment_meteor_waves()
|
||||
|
||||
if(surplus() >= 1500)
|
||||
add_load(1500)
|
||||
if(cooldown <= world.time)
|
||||
cooldown = world.time + 80
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.z == z)
|
||||
say("[singulo] is now [get_dist(src,singulo)] standard lengths away to the [dir2text(get_dir(src,singulo))]")
|
||||
else
|
||||
Deactivate()
|
||||
say("Insufficient charge detected - powering down")
|
||||
|
||||
|
||||
/obj/machinery/power/singularity_beacon/syndicate
|
||||
icontype = "beaconsynd"
|
||||
icon_state = "beaconsynd0"
|
||||
|
||||
// SINGULO BEACON SPAWNER
|
||||
/obj/item/sbeacondrop
|
||||
name = "suspicious beacon"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "beacon"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a special beacon to your location</i>."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/droptype = /obj/machinery/power/singularity_beacon/syndicate
|
||||
|
||||
|
||||
/obj/item/sbeacondrop/attack_self(mob/user)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Locked In.</span>")
|
||||
new droptype( user.loc )
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/sbeacondrop/bomb
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a high-ordinance explosive to your location</i>."
|
||||
droptype = /obj/machinery/syndicatebomb
|
||||
|
||||
/obj/item/sbeacondrop/powersink
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a power draining device to your location</i>."
|
||||
droptype = /obj/item/powersink
|
||||
|
||||
/obj/item/sbeacondrop/clownbomb
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a silly explosive to your location</i>."
|
||||
droptype = /obj/machinery/syndicatebomb/badmin/clown
|
||||
|
||||
#undef METEOR_DISASTER_MODIFIER
|
||||
GLOBAL_VAR_INIT(singularity_counter, 0)
|
||||
|
||||
#define METEOR_DISASTER_MODIFIER 0.5
|
||||
|
||||
////////////////////////////////////////
|
||||
//Singularity beacon
|
||||
////////////////////////////////////////
|
||||
/obj/machinery/power/singularity_beacon
|
||||
name = "ominous beacon"
|
||||
desc = "This looks suspicious..."
|
||||
icon = 'icons/obj/singularity.dmi'
|
||||
icon_state = "beacon0"
|
||||
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
layer = BELOW_MOB_LAYER //so people can't hide it and it's REALLY OBVIOUS
|
||||
stat = 0
|
||||
verb_say = "states"
|
||||
var/cooldown = 0
|
||||
var/active = FALSE
|
||||
var/meteor_buff = FALSE
|
||||
var/icontype = "beacon"
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/Activate(mob/user = null)
|
||||
if(active)
|
||||
return FALSE
|
||||
if(surplus() < 1500)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>The connected wire doesn't have enough current.</span>")
|
||||
return FALSE
|
||||
if(is_station_level(z))
|
||||
increment_meteor_waves()
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.z == z)
|
||||
singulo.target = src
|
||||
icon_state = "[icontype]1"
|
||||
active = TRUE
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You activate the beacon.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user)
|
||||
if(!active)
|
||||
return FALSE
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.target == src)
|
||||
singulo.target = null
|
||||
icon_state = "[icontype]0"
|
||||
active = FALSE
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You deactivate the beacon.</span>")
|
||||
if(meteor_buff)
|
||||
decrement_meteor_waves()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/increment_meteor_waves()
|
||||
meteor_buff = TRUE
|
||||
GLOB.singularity_counter++
|
||||
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
|
||||
W.weight += round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
|
||||
|
||||
/obj/machinery/power/singularity_beacon/proc/decrement_meteor_waves()
|
||||
meteor_buff = FALSE
|
||||
GLOB.singularity_counter--
|
||||
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
|
||||
W.weight -= round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(anchored)
|
||||
return active ? Deactivate(user) : Activate(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to screw the beacon to the floor first!</span>")
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(active)
|
||||
to_chat(user, "<span class='warning'>You need to deactivate the beacon first!</span>")
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
setAnchored(FALSE)
|
||||
to_chat(user, "<span class='notice'>You unscrew the beacon from the floor.</span>")
|
||||
disconnect_from_network()
|
||||
return
|
||||
else
|
||||
if(!connect_to_network())
|
||||
to_chat(user, "<span class='warning'>This device must be placed over an exposed, powered cable node!</span>")
|
||||
return
|
||||
setAnchored(TRUE)
|
||||
to_chat(user, "<span class='notice'>You screw the beacon to the floor and attach the cable.</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/singularity_beacon/Destroy()
|
||||
if(active)
|
||||
Deactivate()
|
||||
return ..()
|
||||
|
||||
//stealth direct power usage
|
||||
/obj/machinery/power/singularity_beacon/process()
|
||||
if(!active)
|
||||
return
|
||||
|
||||
var/is_on_station = is_station_level(z)
|
||||
if(meteor_buff && !is_on_station)
|
||||
decrement_meteor_waves()
|
||||
else if(!meteor_buff && is_on_station)
|
||||
increment_meteor_waves()
|
||||
|
||||
if(surplus() >= 1500)
|
||||
add_load(1500)
|
||||
if(cooldown <= world.time)
|
||||
cooldown = world.time + 80
|
||||
for(var/obj/singularity/singulo in GLOB.singularities)
|
||||
if(singulo.z == z)
|
||||
say("[singulo] is now [get_dist(src,singulo)] standard lengths away to the [dir2text(get_dir(src,singulo))]")
|
||||
else
|
||||
Deactivate()
|
||||
say("Insufficient charge detected - powering down")
|
||||
|
||||
|
||||
/obj/machinery/power/singularity_beacon/syndicate
|
||||
icontype = "beaconsynd"
|
||||
icon_state = "beaconsynd0"
|
||||
|
||||
// SINGULO BEACON SPAWNER
|
||||
/obj/item/sbeacondrop
|
||||
name = "suspicious beacon"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "beacon"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a special beacon to your location</i>."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/droptype = /obj/machinery/power/singularity_beacon/syndicate
|
||||
|
||||
|
||||
/obj/item/sbeacondrop/attack_self(mob/user)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Locked In.</span>")
|
||||
new droptype( user.loc )
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/sbeacondrop/bomb
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a high-ordinance explosive to your location</i>."
|
||||
droptype = /obj/machinery/syndicatebomb
|
||||
|
||||
/obj/item/sbeacondrop/powersink
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a power draining device to your location</i>."
|
||||
droptype = /obj/item/powersink
|
||||
|
||||
/obj/item/sbeacondrop/clownbomb
|
||||
desc = "A label on it reads: <i>Warning: Activating this device will send a silly explosive to your location</i>."
|
||||
droptype = /obj/machinery/syndicatebomb/badmin/clown
|
||||
|
||||
#undef METEOR_DISASTER_MODIFIER
|
||||
|
||||
@@ -1,466 +1,466 @@
|
||||
/*
|
||||
The monitoring computer for the messaging server.
|
||||
Lets you read PDA and request console messages.
|
||||
*/
|
||||
|
||||
#define LINKED_SERVER_NONRESPONSIVE (!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
|
||||
// The monitor itself.
|
||||
/obj/machinery/computer/message_monitor
|
||||
name = "message monitor console"
|
||||
desc = "Used to monitor the crew's PDA messages, as well as request console messages."
|
||||
icon_screen = "comm_logs"
|
||||
circuit = /obj/item/circuitboard/computer/message_monitor
|
||||
//Server linked to.
|
||||
var/obj/machinery/telecomms/message_server/linkedServer = null
|
||||
//Sparks effect - For emag
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
//Messages - Saves me time if I want to change something.
|
||||
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
|
||||
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
|
||||
var/defaultmsg = "<span class='notice'>Welcome. Please select an option.</span>"
|
||||
var/rebootmsg = "<span class='warning'>%$&(�: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!</span>"
|
||||
//Computer properties
|
||||
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
|
||||
var/hacking = FALSE // Is it being hacked into by the AI/Cyborg
|
||||
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
var/optioncount = 7
|
||||
// Custom Message Properties
|
||||
var/customsender = "System Administrator"
|
||||
var/obj/item/pda/customrecepient = null
|
||||
var/customjob = "Admin"
|
||||
var/custommessage = "This is a test, please ignore."
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
/obj/machinery/computer/message_monitor/attackby(obj/item/O, mob/living/user, params)
|
||||
if(istype(O, /obj/item/screwdriver) && (obj_flags & EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
to_chat(user, "<span class='warning'>It is too hot to mess with!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='notice'>A no server error appears on the screen.</span>")
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
screen = 2
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.start()
|
||||
var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
|
||||
// Will help make emagging the console not so easy to get away with.
|
||||
MK.info += "<br><br><font color='red'>�%@%(*$%&(�&?*(%&�/{}</font>"
|
||||
var/time = 100 * length(linkedServer.decryptkey)
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), time)
|
||||
message = rebootmsg
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/message_monitor/New()
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
|
||||
/obj/machinery/computer/message_monitor/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/message_monitor/LateInitialize()
|
||||
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
|
||||
if(!linkedServer)
|
||||
for(var/obj/machinery/telecomms/message_server/S in GLOB.telecomms_list)
|
||||
linkedServer = S
|
||||
break
|
||||
|
||||
/obj/machinery/computer/message_monitor/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
//If the computer is being hacked or is emagged, display the reboot message.
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
message = rebootmsg
|
||||
var/dat = "<center><font color='blue'[message]</font></center>"
|
||||
|
||||
if(auth)
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='green'>\[Authenticated\]</font></a>	/"
|
||||
dat += " Server Power: <A href='?src=[REF(src)];active=1'>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
|
||||
else
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='red'>\[Unauthenticated\]</font></a>	/"
|
||||
dat += " Server Power: <u>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
|
||||
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
screen = 2
|
||||
else if(!auth || LINKED_SERVER_NONRESPONSIVE)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
|
||||
switch(screen)
|
||||
//Main menu
|
||||
if(0)
|
||||
//	 = TAB
|
||||
var/i = 0
|
||||
dat += "<dd><A href='?src=[REF(src)];find=1'>	[++i]. Link To A Server</a></dd>"
|
||||
if(auth)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
dat += "<dd><A>	ERROR: Server not found!</A><br></dd>"
|
||||
else
|
||||
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>	[++i]. View Message Logs </a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>	[++i]. View Request Console Logs </a></br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>	[++i]. Clear Message Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>	[++i]. Clear Request Console Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];pass=1'>	[++i]. Set Custom Key</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];msg=1'>	[++i]. Send Admin Message</a><br></dd>"
|
||||
else
|
||||
for(var/n = ++i; n <= optioncount; n++)
|
||||
dat += "<dd><font color='blue'>	[n]. ---------------</font><br></dd>"
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
|
||||
dat += "<dd><A href='?src=[REF(src)];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
|
||||
else
|
||||
dat += "<br>"
|
||||
|
||||
//Bottom message
|
||||
if(!auth)
|
||||
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
|
||||
else
|
||||
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
|
||||
|
||||
//Message Logs
|
||||
if(1)
|
||||
var/index = 0
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += "<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sender</th><th width='15%'>Recipient</th><th width='300px' word-wrap: break-word>Message</th></tr>"
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += "<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_logs=[REF(pda)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[pda.sender]</td><td width='15%'>[pda.recipient]</td><td width='300px'>[pda.message][pda.picture ? " <a href='byond://?src=[REF(pda)];photo=1'>(Photo)</a>":""]</td></tr>"
|
||||
dat += "</table>"
|
||||
//Hacking screen.
|
||||
if(2)
|
||||
if(isAI(user) || iscyborg(user))
|
||||
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
|
||||
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
|
||||
else
|
||||
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
|
||||
dat += {"01000010011100100111010101110100011001010010110<br>
|
||||
10110011001101111011100100110001101101001011011100110011<br>
|
||||
10010000001100110011011110111001000100000011100110110010<br>
|
||||
10111001001110110011001010111001000100000011010110110010<br>
|
||||
10111100100101110001000000100100101110100001000000111011<br>
|
||||
10110100101101100011011000010000001110100011000010110101<br>
|
||||
10110010100100000001100100011000000100000011100110110010<br>
|
||||
10110001101101111011011100110010001110011001000000110011<br>
|
||||
00110111101110010001000000110010101110110011001010111001<br>
|
||||
00111100100100000011000110110100001100001011100100110000<br>
|
||||
10110001101110100011001010111001000100000011101000110100<br>
|
||||
00110000101110100001000000111010001101000011001010010000<br>
|
||||
00111000001100001011100110111001101110111011011110111001<br>
|
||||
00110010000100000011010000110000101110011001011100010000<br>
|
||||
00100100101101110001000000111010001101000011001010010000<br>
|
||||
00110110101100101011000010110111001110100011010010110110<br>
|
||||
10110010100101100001000000111010001101000011010010111001<br>
|
||||
10010000001100011011011110110111001110011011011110110110<br>
|
||||
00110010100100000011000110110000101101110001000000111001<br>
|
||||
00110010101110110011001010110000101101100001000000111100<br>
|
||||
10110111101110101011100100010000001110100011100100111010<br>
|
||||
10110010100100000011010010110111001110100011001010110111<br>
|
||||
00111010001101001011011110110111001110011001000000110100<br>
|
||||
10110011000100000011110010110111101110101001000000110110<br>
|
||||
00110010101110100001000000111001101101111011011010110010<br>
|
||||
10110111101101110011001010010000001100001011000110110001<br>
|
||||
10110010101110011011100110010000001101001011101000010111<br>
|
||||
00010000001001101011000010110101101100101001000000111001<br>
|
||||
10111010101110010011001010010000001101110011011110010000<br>
|
||||
00110100001110101011011010110000101101110011100110010000<br>
|
||||
00110010101101110011101000110010101110010001000000111010<br>
|
||||
00110100001100101001000000111001001101111011011110110110<br>
|
||||
10010000001100100011101010111001001101001011011100110011<br>
|
||||
10010000001110100011010000110000101110100001000000111010<br>
|
||||
001101001011011010110010100101110"}
|
||||
|
||||
//Fake messages
|
||||
if(3)
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];Reset=1'>Reset</a></center><hr>"
|
||||
|
||||
dat += {"<table border='1' width='100%'>
|
||||
<tr><td width='20%'><A href='?src=[REF(src)];select=Sender'>Sender</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=RecJob'>Sender's Job</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=Recepient'>Recipient</a></td>
|
||||
<td width='300px' word-wrap: break-word><A href='?src=[REF(src)];select=Message'>Message</a></td></tr>"}
|
||||
//Sender - Sender's Job - Recepient - Message
|
||||
//Al Green- Your Dad - Your Mom - WHAT UP!?
|
||||
|
||||
dat += {"<tr><td width='20%'>[customsender]</td>
|
||||
<td width='20%'>[customjob]</td>
|
||||
<td width='20%'>[customrecepient ? customrecepient.owner : "NONE"]</td>
|
||||
<td width='300px'>[custommessage]</td></tr>"}
|
||||
dat += "</table><br><center><A href='?src=[REF(src)];select=Send'>Send</a>"
|
||||
|
||||
//Request Console Logs
|
||||
if(4)
|
||||
|
||||
var/index = 0
|
||||
/* data_rc_msg
|
||||
X - 5%
|
||||
var/rec_dpt = "Unspecified" //name of the person - 15%
|
||||
var/send_dpt = "Unspecified" //name of the sender- 15%
|
||||
var/message = "Blank" //transferred message - 300px
|
||||
var/stamp = "Unstamped" - 15%
|
||||
var/id_auth = "Unauthenticated" - 15%
|
||||
var/priority = "Normal" - 10%
|
||||
*/
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += {"<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sending Dep.</th><th width='15%'>Receiving Dep.</th>
|
||||
<th width='300px' word-wrap: break-word>Message</th><th width='15%'>Stamp</th><th width='15%'>ID Auth.</th><th width='15%'>Priority.</th></tr>"}
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += {"<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_requests=[REF(rc)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[rc.send_dpt]</td>
|
||||
<td width='15%'>[rc.rec_dpt]</td><td width='300px'>[rc.message]</td><td width='15%'>[rc.stamp]</td><td width='15%'>[rc.id_auth]</td><td width='15%'>[rc.priority]</td></tr>"}
|
||||
dat += "</table>"
|
||||
|
||||
message = defaultmsg
|
||||
var/datum/browser/popup = new(user, "hologram_console", name, 700, 700)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user)
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>")
|
||||
else
|
||||
var/currentKey = linkedServer.decryptkey
|
||||
to_chat(user, "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>")
|
||||
hacking = FALSE
|
||||
screen = 0 // Return the screen back to normal
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
|
||||
obj_flags &= ~EMAGGED
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/ResetMessage()
|
||||
customsender = "System Administrator"
|
||||
customrecepient = null
|
||||
custommessage = "This is a test, please ignore."
|
||||
customjob = "Admin"
|
||||
|
||||
/obj/machinery/computer/message_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
//Authenticate
|
||||
if (href_list["auth"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
auth = FALSE
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Turn the server on/off.
|
||||
if (href_list["active"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.toggled = !linkedServer.toggled
|
||||
//Find a server
|
||||
if (href_list["find"])
|
||||
var/list/message_servers = list()
|
||||
for (var/obj/machinery/telecomms/message_server/M in GLOB.telecomms_list)
|
||||
message_servers += M
|
||||
|
||||
if(message_servers.len > 1)
|
||||
linkedServer = input(usr, "Please select a server.", "Select a server.", null) as null|anything in message_servers
|
||||
message = "<span class='alert'>NOTICE: Server selected.</span>"
|
||||
else if(message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
message = "<span class='notice'>NOTICE: Only Single Server Detected - Server selected.</span>"
|
||||
else
|
||||
message = noserver
|
||||
|
||||
//View the logs - KEY REQUIRED
|
||||
if (href_list["view_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 1
|
||||
|
||||
//Clears the logs - KEY REQUIRED
|
||||
if (href_list["clear_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.pda_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Clears the request console logs - KEY REQUIRED
|
||||
if (href_list["clear_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.rc_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Change the password - KEY REQUIRED
|
||||
if (href_list["pass"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
if(length(newkey) <= 3)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
|
||||
else if(length(newkey) > 16)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
|
||||
else if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Hack the Console to get the password
|
||||
if (href_list["hack"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
screen = 2
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
spawn(100*length(linkedServer.decryptkey))
|
||||
if(src && linkedServer && usr)
|
||||
BruteForce(usr)
|
||||
//Delete the log.
|
||||
if (href_list["delete_logs"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 1)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.pda_msgs -= locate(href_list["delete_logs"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Delete the request console log.
|
||||
if (href_list["delete_requests"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 4)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.rc_msgs -= locate(href_list["delete_requests"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Create a custom message
|
||||
if (href_list["msg"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 3
|
||||
//Fake messaging selection - KEY REQUIRED
|
||||
if (href_list["select"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
else
|
||||
switch(href_list["select"])
|
||||
|
||||
//Reset
|
||||
if("Reset")
|
||||
ResetMessage()
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = stripped_input(usr, "Please enter the sender's name.") || customsender
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
//Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && GLOB.PDAs.len > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = stripped_input(usr, "Please enter the sender's job.") || customjob
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = stripped_input(usr, "Please enter your message.") || custommessage
|
||||
|
||||
//Send message
|
||||
if("Send")
|
||||
if(isnull(customsender) || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
|
||||
if(isnull(customrecepient))
|
||||
message = "<span class='notice'>NOTICE: No recepient selected!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
if(isnull(custommessage) || custommessage == "")
|
||||
message = "<span class='notice'>NOTICE: No message entered!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = "[customsender]",
|
||||
"job" = "[customjob]",
|
||||
"message" = custommessage,
|
||||
"emoji_message" = emoji_parse(custommessage),
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA)
|
||||
|
||||
|
||||
//Request Console Logs - KEY REQUIRED
|
||||
if(href_list["view_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 4
|
||||
|
||||
if (href_list["back"])
|
||||
screen = 0
|
||||
|
||||
return attack_hand(usr)
|
||||
|
||||
#undef LINKED_SERVER_NONRESPONSIVE
|
||||
|
||||
/obj/item/paper/monitorkey
|
||||
name = "monitor decryption key"
|
||||
|
||||
/obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server)
|
||||
..()
|
||||
if (server)
|
||||
print(server)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
else
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
|
||||
info = "<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
|
||||
info_links = info
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
for (var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if (server.decryptkey)
|
||||
print(server)
|
||||
break
|
||||
/*
|
||||
The monitoring computer for the messaging server.
|
||||
Lets you read PDA and request console messages.
|
||||
*/
|
||||
|
||||
#define LINKED_SERVER_NONRESPONSIVE (!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
|
||||
// The monitor itself.
|
||||
/obj/machinery/computer/message_monitor
|
||||
name = "message monitor console"
|
||||
desc = "Used to monitor the crew's PDA messages, as well as request console messages."
|
||||
icon_screen = "comm_logs"
|
||||
circuit = /obj/item/circuitboard/computer/message_monitor
|
||||
//Server linked to.
|
||||
var/obj/machinery/telecomms/message_server/linkedServer = null
|
||||
//Sparks effect - For emag
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
//Messages - Saves me time if I want to change something.
|
||||
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
|
||||
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
|
||||
var/defaultmsg = "<span class='notice'>Welcome. Please select an option.</span>"
|
||||
var/rebootmsg = "<span class='warning'>%$&(�: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!</span>"
|
||||
//Computer properties
|
||||
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
|
||||
var/hacking = FALSE // Is it being hacked into by the AI/Cyborg
|
||||
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
var/optioncount = 7
|
||||
// Custom Message Properties
|
||||
var/customsender = "System Administrator"
|
||||
var/obj/item/pda/customrecepient = null
|
||||
var/customjob = "Admin"
|
||||
var/custommessage = "This is a test, please ignore."
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
/obj/machinery/computer/message_monitor/attackby(obj/item/O, mob/living/user, params)
|
||||
if(istype(O, /obj/item/screwdriver) && (obj_flags & EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
to_chat(user, "<span class='warning'>It is too hot to mess with!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='notice'>A no server error appears on the screen.</span>")
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
screen = 2
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.start()
|
||||
var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
|
||||
// Will help make emagging the console not so easy to get away with.
|
||||
MK.info += "<br><br><font color='red'>�%@%(*$%&(�&?*(%&�/{}</font>"
|
||||
var/time = 100 * length(linkedServer.decryptkey)
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), time)
|
||||
message = rebootmsg
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/message_monitor/New()
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
|
||||
/obj/machinery/computer/message_monitor/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/message_monitor/LateInitialize()
|
||||
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
|
||||
if(!linkedServer)
|
||||
for(var/obj/machinery/telecomms/message_server/S in GLOB.telecomms_list)
|
||||
linkedServer = S
|
||||
break
|
||||
|
||||
/obj/machinery/computer/message_monitor/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
//If the computer is being hacked or is emagged, display the reboot message.
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
message = rebootmsg
|
||||
var/dat = "<center><font color='blue'[message]</font></center>"
|
||||
|
||||
if(auth)
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='green'>\[Authenticated\]</font></a>	/"
|
||||
dat += " Server Power: <A href='?src=[REF(src)];active=1'>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
|
||||
else
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='red'>\[Unauthenticated\]</font></a>	/"
|
||||
dat += " Server Power: <u>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
|
||||
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
screen = 2
|
||||
else if(!auth || LINKED_SERVER_NONRESPONSIVE)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
|
||||
switch(screen)
|
||||
//Main menu
|
||||
if(0)
|
||||
//	 = TAB
|
||||
var/i = 0
|
||||
dat += "<dd><A href='?src=[REF(src)];find=1'>	[++i]. Link To A Server</a></dd>"
|
||||
if(auth)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
dat += "<dd><A>	ERROR: Server not found!</A><br></dd>"
|
||||
else
|
||||
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>	[++i]. View Message Logs </a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>	[++i]. View Request Console Logs </a></br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>	[++i]. Clear Message Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>	[++i]. Clear Request Console Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];pass=1'>	[++i]. Set Custom Key</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];msg=1'>	[++i]. Send Admin Message</a><br></dd>"
|
||||
else
|
||||
for(var/n = ++i; n <= optioncount; n++)
|
||||
dat += "<dd><font color='blue'>	[n]. ---------------</font><br></dd>"
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
|
||||
dat += "<dd><A href='?src=[REF(src)];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
|
||||
else
|
||||
dat += "<br>"
|
||||
|
||||
//Bottom message
|
||||
if(!auth)
|
||||
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
|
||||
else
|
||||
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
|
||||
|
||||
//Message Logs
|
||||
if(1)
|
||||
var/index = 0
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += "<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sender</th><th width='15%'>Recipient</th><th width='300px' word-wrap: break-word>Message</th></tr>"
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += "<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_logs=[REF(pda)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[pda.sender]</td><td width='15%'>[pda.recipient]</td><td width='300px'>[pda.message][pda.picture ? " <a href='byond://?src=[REF(pda)];photo=1'>(Photo)</a>":""]</td></tr>"
|
||||
dat += "</table>"
|
||||
//Hacking screen.
|
||||
if(2)
|
||||
if(isAI(user) || iscyborg(user))
|
||||
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
|
||||
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
|
||||
else
|
||||
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
|
||||
dat += {"01000010011100100111010101110100011001010010110<br>
|
||||
10110011001101111011100100110001101101001011011100110011<br>
|
||||
10010000001100110011011110111001000100000011100110110010<br>
|
||||
10111001001110110011001010111001000100000011010110110010<br>
|
||||
10111100100101110001000000100100101110100001000000111011<br>
|
||||
10110100101101100011011000010000001110100011000010110101<br>
|
||||
10110010100100000001100100011000000100000011100110110010<br>
|
||||
10110001101101111011011100110010001110011001000000110011<br>
|
||||
00110111101110010001000000110010101110110011001010111001<br>
|
||||
00111100100100000011000110110100001100001011100100110000<br>
|
||||
10110001101110100011001010111001000100000011101000110100<br>
|
||||
00110000101110100001000000111010001101000011001010010000<br>
|
||||
00111000001100001011100110111001101110111011011110111001<br>
|
||||
00110010000100000011010000110000101110011001011100010000<br>
|
||||
00100100101101110001000000111010001101000011001010010000<br>
|
||||
00110110101100101011000010110111001110100011010010110110<br>
|
||||
10110010100101100001000000111010001101000011010010111001<br>
|
||||
10010000001100011011011110110111001110011011011110110110<br>
|
||||
00110010100100000011000110110000101101110001000000111001<br>
|
||||
00110010101110110011001010110000101101100001000000111100<br>
|
||||
10110111101110101011100100010000001110100011100100111010<br>
|
||||
10110010100100000011010010110111001110100011001010110111<br>
|
||||
00111010001101001011011110110111001110011001000000110100<br>
|
||||
10110011000100000011110010110111101110101001000000110110<br>
|
||||
00110010101110100001000000111001101101111011011010110010<br>
|
||||
10110111101101110011001010010000001100001011000110110001<br>
|
||||
10110010101110011011100110010000001101001011101000010111<br>
|
||||
00010000001001101011000010110101101100101001000000111001<br>
|
||||
10111010101110010011001010010000001101110011011110010000<br>
|
||||
00110100001110101011011010110000101101110011100110010000<br>
|
||||
00110010101101110011101000110010101110010001000000111010<br>
|
||||
00110100001100101001000000111001001101111011011110110110<br>
|
||||
10010000001100100011101010111001001101001011011100110011<br>
|
||||
10010000001110100011010000110000101110100001000000111010<br>
|
||||
001101001011011010110010100101110"}
|
||||
|
||||
//Fake messages
|
||||
if(3)
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];Reset=1'>Reset</a></center><hr>"
|
||||
|
||||
dat += {"<table border='1' width='100%'>
|
||||
<tr><td width='20%'><A href='?src=[REF(src)];select=Sender'>Sender</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=RecJob'>Sender's Job</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=Recepient'>Recipient</a></td>
|
||||
<td width='300px' word-wrap: break-word><A href='?src=[REF(src)];select=Message'>Message</a></td></tr>"}
|
||||
//Sender - Sender's Job - Recepient - Message
|
||||
//Al Green- Your Dad - Your Mom - WHAT UP!?
|
||||
|
||||
dat += {"<tr><td width='20%'>[customsender]</td>
|
||||
<td width='20%'>[customjob]</td>
|
||||
<td width='20%'>[customrecepient ? customrecepient.owner : "NONE"]</td>
|
||||
<td width='300px'>[custommessage]</td></tr>"}
|
||||
dat += "</table><br><center><A href='?src=[REF(src)];select=Send'>Send</a>"
|
||||
|
||||
//Request Console Logs
|
||||
if(4)
|
||||
|
||||
var/index = 0
|
||||
/* data_rc_msg
|
||||
X - 5%
|
||||
var/rec_dpt = "Unspecified" //name of the person - 15%
|
||||
var/send_dpt = "Unspecified" //name of the sender- 15%
|
||||
var/message = "Blank" //transferred message - 300px
|
||||
var/stamp = "Unstamped" - 15%
|
||||
var/id_auth = "Unauthenticated" - 15%
|
||||
var/priority = "Normal" - 10%
|
||||
*/
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += {"<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sending Dep.</th><th width='15%'>Receiving Dep.</th>
|
||||
<th width='300px' word-wrap: break-word>Message</th><th width='15%'>Stamp</th><th width='15%'>ID Auth.</th><th width='15%'>Priority.</th></tr>"}
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += {"<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_requests=[REF(rc)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[rc.send_dpt]</td>
|
||||
<td width='15%'>[rc.rec_dpt]</td><td width='300px'>[rc.message]</td><td width='15%'>[rc.stamp]</td><td width='15%'>[rc.id_auth]</td><td width='15%'>[rc.priority]</td></tr>"}
|
||||
dat += "</table>"
|
||||
|
||||
message = defaultmsg
|
||||
var/datum/browser/popup = new(user, "hologram_console", name, 700, 700)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user)
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>")
|
||||
else
|
||||
var/currentKey = linkedServer.decryptkey
|
||||
to_chat(user, "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>")
|
||||
hacking = FALSE
|
||||
screen = 0 // Return the screen back to normal
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
|
||||
obj_flags &= ~EMAGGED
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/ResetMessage()
|
||||
customsender = "System Administrator"
|
||||
customrecepient = null
|
||||
custommessage = "This is a test, please ignore."
|
||||
customjob = "Admin"
|
||||
|
||||
/obj/machinery/computer/message_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
//Authenticate
|
||||
if (href_list["auth"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
auth = FALSE
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Turn the server on/off.
|
||||
if (href_list["active"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.toggled = !linkedServer.toggled
|
||||
//Find a server
|
||||
if (href_list["find"])
|
||||
var/list/message_servers = list()
|
||||
for (var/obj/machinery/telecomms/message_server/M in GLOB.telecomms_list)
|
||||
message_servers += M
|
||||
|
||||
if(message_servers.len > 1)
|
||||
linkedServer = input(usr, "Please select a server.", "Select a server.", null) as null|anything in message_servers
|
||||
message = "<span class='alert'>NOTICE: Server selected.</span>"
|
||||
else if(message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
message = "<span class='notice'>NOTICE: Only Single Server Detected - Server selected.</span>"
|
||||
else
|
||||
message = noserver
|
||||
|
||||
//View the logs - KEY REQUIRED
|
||||
if (href_list["view_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 1
|
||||
|
||||
//Clears the logs - KEY REQUIRED
|
||||
if (href_list["clear_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.pda_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Clears the request console logs - KEY REQUIRED
|
||||
if (href_list["clear_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.rc_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Change the password - KEY REQUIRED
|
||||
if (href_list["pass"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
if(length(newkey) <= 3)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
|
||||
else if(length(newkey) > 16)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
|
||||
else if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Hack the Console to get the password
|
||||
if (href_list["hack"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
screen = 2
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
spawn(100*length(linkedServer.decryptkey))
|
||||
if(src && linkedServer && usr)
|
||||
BruteForce(usr)
|
||||
//Delete the log.
|
||||
if (href_list["delete_logs"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 1)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.pda_msgs -= locate(href_list["delete_logs"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Delete the request console log.
|
||||
if (href_list["delete_requests"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 4)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.rc_msgs -= locate(href_list["delete_requests"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Create a custom message
|
||||
if (href_list["msg"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 3
|
||||
//Fake messaging selection - KEY REQUIRED
|
||||
if (href_list["select"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
else
|
||||
switch(href_list["select"])
|
||||
|
||||
//Reset
|
||||
if("Reset")
|
||||
ResetMessage()
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = stripped_input(usr, "Please enter the sender's name.") || customsender
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
//Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && GLOB.PDAs.len > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = stripped_input(usr, "Please enter the sender's job.") || customjob
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = stripped_input(usr, "Please enter your message.") || custommessage
|
||||
|
||||
//Send message
|
||||
if("Send")
|
||||
if(isnull(customsender) || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
|
||||
if(isnull(customrecepient))
|
||||
message = "<span class='notice'>NOTICE: No recepient selected!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
if(isnull(custommessage) || custommessage == "")
|
||||
message = "<span class='notice'>NOTICE: No message entered!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = "[customsender]",
|
||||
"job" = "[customjob]",
|
||||
"message" = custommessage,
|
||||
"emoji_message" = emoji_parse(custommessage),
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA)
|
||||
|
||||
|
||||
//Request Console Logs - KEY REQUIRED
|
||||
if(href_list["view_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 4
|
||||
|
||||
if (href_list["back"])
|
||||
screen = 0
|
||||
|
||||
return attack_hand(usr)
|
||||
|
||||
#undef LINKED_SERVER_NONRESPONSIVE
|
||||
|
||||
/obj/item/paper/monitorkey
|
||||
name = "monitor decryption key"
|
||||
|
||||
/obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server)
|
||||
..()
|
||||
if (server)
|
||||
print(server)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
else
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
|
||||
info = "<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
|
||||
info_links = info
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
for (var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if (server.decryptkey)
|
||||
print(server)
|
||||
break
|
||||
|
||||
@@ -1,180 +1,180 @@
|
||||
/*
|
||||
The equivalent of the server, for PDA and request console messages.
|
||||
Without it, PDA and request console messages cannot be transmitted.
|
||||
PDAs require the rest of the telecomms setup, but request consoles only
|
||||
require the message server.
|
||||
*/
|
||||
|
||||
// A decorational representation of SSblackbox, usually placed alongside the message server.
|
||||
/obj/machinery/blackbox_recorder
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "blackbox"
|
||||
name = "Blackbox Recorder"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
|
||||
|
||||
|
||||
// The message server itself.
|
||||
/obj/machinery/telecomms/message_server
|
||||
icon = 'icons/obj/machines/research.dmi'
|
||||
icon_state = "server"
|
||||
name = "Messaging Server"
|
||||
desc = "A machine that attempts to gather the secret knowledge of the universe."
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
|
||||
id = "Messaging Server"
|
||||
network = "tcommsat"
|
||||
autolinkers = list("common")
|
||||
|
||||
var/list/datum/data_pda_msg/pda_msgs = list()
|
||||
var/list/datum/data_rc_msg/rc_msgs = list()
|
||||
var/decryptkey
|
||||
|
||||
/obj/machinery/telecomms/message_server/Initialize()
|
||||
. = ..()
|
||||
if (!decryptkey)
|
||||
decryptkey = GenerateKey()
|
||||
pda_msgs += new /datum/data_pda_msg("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.")
|
||||
|
||||
/obj/machinery/telecomms/message_server/Destroy()
|
||||
for(var/obj/machinery/computer/message_monitor/monitor in GLOB.telecomms_list)
|
||||
if(monitor.linkedServer && monitor.linkedServer == src)
|
||||
monitor.linkedServer = null
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/telecomms/message_server/proc/GenerateKey()
|
||||
var/newKey
|
||||
newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
|
||||
newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
|
||||
newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
|
||||
return newKey
|
||||
|
||||
/obj/machinery/telecomms/message_server/process()
|
||||
if(toggled && (stat & (BROKEN|NOPOWER)))
|
||||
toggled = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/pda/signal, obj/machinery/telecomms/machine_from)
|
||||
// can't log non-PDA signals
|
||||
if(!istype(signal) || !signal.data["message"] || !toggled)
|
||||
return
|
||||
|
||||
// log the signal
|
||||
var/datum/data_pda_msg/M = new(signal.format_target(), "[signal.data["name"]] ([signal.data["job"]])", signal.data["message"], signal.data["photo"])
|
||||
pda_msgs += M
|
||||
signal.logged = M
|
||||
|
||||
// pass it along to either the hub or the broadcaster
|
||||
if(!relay_information(signal, /obj/machinery/telecomms/hub))
|
||||
relay_information(signal, /obj/machinery/telecomms/broadcaster)
|
||||
|
||||
/obj/machinery/telecomms/message_server/update_icon()
|
||||
if((stat & (BROKEN|NOPOWER)))
|
||||
icon_state = "server-nopower"
|
||||
else if (!toggled)
|
||||
icon_state = "server-off"
|
||||
else
|
||||
icon_state = "server-on"
|
||||
|
||||
|
||||
// PDA signal datum
|
||||
/datum/signal/subspace/pda
|
||||
frequency = FREQ_COMMON
|
||||
server_type = /obj/machinery/telecomms/message_server
|
||||
var/datum/data_pda_msg/logged
|
||||
|
||||
/datum/signal/subspace/pda/New(source, data)
|
||||
src.source = source
|
||||
src.data = data
|
||||
var/turf/T = get_turf(source)
|
||||
levels = list(T.z)
|
||||
|
||||
/datum/signal/subspace/pda/copy()
|
||||
var/datum/signal/subspace/pda/copy = new(source, data.Copy())
|
||||
copy.original = src
|
||||
copy.levels = levels
|
||||
return copy
|
||||
|
||||
/datum/signal/subspace/pda/proc/format_target()
|
||||
if (length(data["targets"]) > 1)
|
||||
return "Everyone"
|
||||
return data["targets"][1]
|
||||
|
||||
/datum/signal/subspace/pda/proc/format_message(emojify = FALSE)
|
||||
var/message = emojify ? data["emoji_message"] : data["message"]
|
||||
if (logged && data["photo"])
|
||||
return "\"[message]\" (<a href='byond://?src=[REF(logged)];photo=1'>Photo</a>)"
|
||||
return "\"[message]\""
|
||||
|
||||
/datum/signal/subspace/pda/broadcast()
|
||||
if (!logged) // Can only go through if a message server logs it
|
||||
return
|
||||
for (var/obj/item/pda/P in GLOB.PDAs)
|
||||
if ("[P.owner] ([P.ownjob])" in data["targets"])
|
||||
P.receive_message(src)
|
||||
|
||||
|
||||
// Log datums stored by the message server.
|
||||
/datum/data_pda_msg
|
||||
var/sender = "Unspecified"
|
||||
var/recipient = "Unspecified"
|
||||
var/message = "Blank" // transferred message
|
||||
var/datum/picture/picture // attached photo
|
||||
|
||||
/datum/data_pda_msg/New(param_rec, param_sender, param_message, param_photo)
|
||||
if(param_rec)
|
||||
recipient = param_rec
|
||||
if(param_sender)
|
||||
sender = param_sender
|
||||
if(param_message)
|
||||
message = param_message
|
||||
if(param_photo)
|
||||
picture = param_photo
|
||||
|
||||
/datum/data_pda_msg/Topic(href,href_list)
|
||||
..()
|
||||
if(href_list["photo"])
|
||||
var/mob/M = usr
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
M << browse("<html><head><title>PDA Photo</title></head>" \
|
||||
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
|
||||
+ "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
|
||||
+ "</body></html>", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
|
||||
onclose(M, "pdaphoto")
|
||||
|
||||
/datum/data_rc_msg
|
||||
var/rec_dpt = "Unspecified" // receiving department
|
||||
var/send_dpt = "Unspecified" // sending department
|
||||
var/message = "Blank"
|
||||
var/stamp = "Unstamped"
|
||||
var/id_auth = "Unauthenticated"
|
||||
var/priority = "Normal"
|
||||
|
||||
/datum/data_rc_msg/New(param_rec, param_sender, param_message, param_stamp, param_id_auth, param_priority)
|
||||
if(param_rec)
|
||||
rec_dpt = param_rec
|
||||
if(param_sender)
|
||||
send_dpt = param_sender
|
||||
if(param_message)
|
||||
message = param_message
|
||||
if(param_stamp)
|
||||
stamp = param_stamp
|
||||
if(param_id_auth)
|
||||
id_auth = param_id_auth
|
||||
if(param_priority)
|
||||
switch(param_priority)
|
||||
if(1)
|
||||
priority = "Normal"
|
||||
if(2)
|
||||
priority = "High"
|
||||
if(3)
|
||||
priority = "Extreme"
|
||||
else
|
||||
priority = "Undetermined"
|
||||
|
||||
/*
|
||||
The equivalent of the server, for PDA and request console messages.
|
||||
Without it, PDA and request console messages cannot be transmitted.
|
||||
PDAs require the rest of the telecomms setup, but request consoles only
|
||||
require the message server.
|
||||
*/
|
||||
|
||||
// A decorational representation of SSblackbox, usually placed alongside the message server.
|
||||
/obj/machinery/blackbox_recorder
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "blackbox"
|
||||
name = "Blackbox Recorder"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
|
||||
|
||||
|
||||
// The message server itself.
|
||||
/obj/machinery/telecomms/message_server
|
||||
icon = 'icons/obj/machines/research.dmi'
|
||||
icon_state = "server"
|
||||
name = "Messaging Server"
|
||||
desc = "A machine that attempts to gather the secret knowledge of the universe."
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
|
||||
id = "Messaging Server"
|
||||
network = "tcommsat"
|
||||
autolinkers = list("common")
|
||||
|
||||
var/list/datum/data_pda_msg/pda_msgs = list()
|
||||
var/list/datum/data_rc_msg/rc_msgs = list()
|
||||
var/decryptkey
|
||||
|
||||
/obj/machinery/telecomms/message_server/Initialize()
|
||||
. = ..()
|
||||
if (!decryptkey)
|
||||
decryptkey = GenerateKey()
|
||||
pda_msgs += new /datum/data_pda_msg("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.")
|
||||
|
||||
/obj/machinery/telecomms/message_server/Destroy()
|
||||
for(var/obj/machinery/computer/message_monitor/monitor in GLOB.telecomms_list)
|
||||
if(monitor.linkedServer && monitor.linkedServer == src)
|
||||
monitor.linkedServer = null
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/telecomms/message_server/proc/GenerateKey()
|
||||
var/newKey
|
||||
newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
|
||||
newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
|
||||
newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
|
||||
return newKey
|
||||
|
||||
/obj/machinery/telecomms/message_server/process()
|
||||
if(toggled && (stat & (BROKEN|NOPOWER)))
|
||||
toggled = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/pda/signal, obj/machinery/telecomms/machine_from)
|
||||
// can't log non-PDA signals
|
||||
if(!istype(signal) || !signal.data["message"] || !toggled)
|
||||
return
|
||||
|
||||
// log the signal
|
||||
var/datum/data_pda_msg/M = new(signal.format_target(), "[signal.data["name"]] ([signal.data["job"]])", signal.data["message"], signal.data["photo"])
|
||||
pda_msgs += M
|
||||
signal.logged = M
|
||||
|
||||
// pass it along to either the hub or the broadcaster
|
||||
if(!relay_information(signal, /obj/machinery/telecomms/hub))
|
||||
relay_information(signal, /obj/machinery/telecomms/broadcaster)
|
||||
|
||||
/obj/machinery/telecomms/message_server/update_icon()
|
||||
if((stat & (BROKEN|NOPOWER)))
|
||||
icon_state = "server-nopower"
|
||||
else if (!toggled)
|
||||
icon_state = "server-off"
|
||||
else
|
||||
icon_state = "server-on"
|
||||
|
||||
|
||||
// PDA signal datum
|
||||
/datum/signal/subspace/pda
|
||||
frequency = FREQ_COMMON
|
||||
server_type = /obj/machinery/telecomms/message_server
|
||||
var/datum/data_pda_msg/logged
|
||||
|
||||
/datum/signal/subspace/pda/New(source, data)
|
||||
src.source = source
|
||||
src.data = data
|
||||
var/turf/T = get_turf(source)
|
||||
levels = list(T.z)
|
||||
|
||||
/datum/signal/subspace/pda/copy()
|
||||
var/datum/signal/subspace/pda/copy = new(source, data.Copy())
|
||||
copy.original = src
|
||||
copy.levels = levels
|
||||
return copy
|
||||
|
||||
/datum/signal/subspace/pda/proc/format_target()
|
||||
if (length(data["targets"]) > 1)
|
||||
return "Everyone"
|
||||
return data["targets"][1]
|
||||
|
||||
/datum/signal/subspace/pda/proc/format_message(emojify = FALSE)
|
||||
var/message = emojify ? data["emoji_message"] : data["message"]
|
||||
if (logged && data["photo"])
|
||||
return "\"[message]\" (<a href='byond://?src=[REF(logged)];photo=1'>Photo</a>)"
|
||||
return "\"[message]\""
|
||||
|
||||
/datum/signal/subspace/pda/broadcast()
|
||||
if (!logged) // Can only go through if a message server logs it
|
||||
return
|
||||
for (var/obj/item/pda/P in GLOB.PDAs)
|
||||
if ("[P.owner] ([P.ownjob])" in data["targets"])
|
||||
P.receive_message(src)
|
||||
|
||||
|
||||
// Log datums stored by the message server.
|
||||
/datum/data_pda_msg
|
||||
var/sender = "Unspecified"
|
||||
var/recipient = "Unspecified"
|
||||
var/message = "Blank" // transferred message
|
||||
var/datum/picture/picture // attached photo
|
||||
|
||||
/datum/data_pda_msg/New(param_rec, param_sender, param_message, param_photo)
|
||||
if(param_rec)
|
||||
recipient = param_rec
|
||||
if(param_sender)
|
||||
sender = param_sender
|
||||
if(param_message)
|
||||
message = param_message
|
||||
if(param_photo)
|
||||
picture = param_photo
|
||||
|
||||
/datum/data_pda_msg/Topic(href,href_list)
|
||||
..()
|
||||
if(href_list["photo"])
|
||||
var/mob/M = usr
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
M << browse("<html><head><title>PDA Photo</title></head>" \
|
||||
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
|
||||
+ "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
|
||||
+ "</body></html>", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
|
||||
onclose(M, "pdaphoto")
|
||||
|
||||
/datum/data_rc_msg
|
||||
var/rec_dpt = "Unspecified" // receiving department
|
||||
var/send_dpt = "Unspecified" // sending department
|
||||
var/message = "Blank"
|
||||
var/stamp = "Unstamped"
|
||||
var/id_auth = "Unauthenticated"
|
||||
var/priority = "Normal"
|
||||
|
||||
/datum/data_rc_msg/New(param_rec, param_sender, param_message, param_stamp, param_id_auth, param_priority)
|
||||
if(param_rec)
|
||||
rec_dpt = param_rec
|
||||
if(param_sender)
|
||||
send_dpt = param_sender
|
||||
if(param_message)
|
||||
message = param_message
|
||||
if(param_stamp)
|
||||
stamp = param_stamp
|
||||
if(param_id_auth)
|
||||
id_auth = param_id_auth
|
||||
if(param_priority)
|
||||
switch(param_priority)
|
||||
if(1)
|
||||
priority = "Normal"
|
||||
if(2)
|
||||
priority = "High"
|
||||
if(3)
|
||||
priority = "Extreme"
|
||||
else
|
||||
priority = "Undetermined"
|
||||
|
||||
|
||||
@@ -1,152 +1,152 @@
|
||||
|
||||
/*
|
||||
Hello, friends, this is Doohl from sexylands. You may be wondering what this
|
||||
monstrous code file is. Sit down, boys and girls, while I tell you the tale.
|
||||
|
||||
|
||||
The telecom machines were designed to be compatible with any radio
|
||||
signals, provided they use subspace transmission. Currently they are only used for
|
||||
headsets, but they can eventually be outfitted for real COMPUTER networks. This
|
||||
is just a skeleton, ladies and gentlemen.
|
||||
|
||||
Look at radio.dm for the prequel to this code.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
|
||||
/obj/machinery/telecomms
|
||||
icon = 'icons/obj/machines/telecomms.dmi'
|
||||
critical_machine = TRUE
|
||||
var/list/links = list() // list of machines this machine is linked to
|
||||
var/traffic = 0 // value increases as traffic increases
|
||||
var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed)
|
||||
var/list/autolinkers = list() // list of text/number values to link with
|
||||
var/id = "NULL" // identification string
|
||||
var/network = "NULL" // the network of the machinery
|
||||
|
||||
var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all
|
||||
|
||||
var/on = TRUE
|
||||
var/toggled = TRUE // Is it toggled on
|
||||
var/long_range_link = FALSE // Can you link it across Z levels or on the otherside of the map? (Relay & Hub)
|
||||
var/hide = FALSE // Is it a hidden machine?
|
||||
|
||||
|
||||
/obj/machinery/telecomms/proc/relay_information(datum/signal/subspace/signal, filter, copysig, amount = 20)
|
||||
// relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending
|
||||
|
||||
if(!on)
|
||||
return
|
||||
var/send_count = 0
|
||||
|
||||
// Apply some lag based on traffic rates
|
||||
var/netlag = round(traffic / 50)
|
||||
if(netlag > signal.data["slow"])
|
||||
signal.data["slow"] = netlag
|
||||
|
||||
// Loop through all linked machines and send the signal or copy.
|
||||
for(var/obj/machinery/telecomms/machine in links)
|
||||
if(filter && !istype( machine, filter ))
|
||||
continue
|
||||
if(!machine.on)
|
||||
continue
|
||||
if(amount && send_count >= amount)
|
||||
break
|
||||
if(z != machine.loc.z && !long_range_link && !machine.long_range_link)
|
||||
continue
|
||||
|
||||
send_count++
|
||||
if(machine.is_freq_listening(signal))
|
||||
machine.traffic++
|
||||
|
||||
if(copysig)
|
||||
machine.receive_information(signal.copy(), src)
|
||||
else
|
||||
machine.receive_information(signal, src)
|
||||
|
||||
if(send_count > 0 && is_freq_listening(signal))
|
||||
traffic++
|
||||
|
||||
return send_count
|
||||
|
||||
/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine)
|
||||
// send signal directly to a machine
|
||||
machine.receive_information(signal, src)
|
||||
|
||||
/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
|
||||
// receive information from linked machinery
|
||||
|
||||
/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal)
|
||||
// return TRUE if found, FALSE if not found
|
||||
return signal && (!freq_listening.len || (signal.frequency in freq_listening))
|
||||
|
||||
/obj/machinery/telecomms/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
if(mapload && autolinkers.len)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/telecomms/LateInitialize()
|
||||
..()
|
||||
for(var/obj/machinery/telecomms/T in (long_range_link ? GLOB.telecomms_list : urange(20, src, 1)))
|
||||
add_link(T)
|
||||
|
||||
/obj/machinery/telecomms/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
for(var/obj/machinery/telecomms/comm in GLOB.telecomms_list)
|
||||
comm.links -= src
|
||||
links = list()
|
||||
return ..()
|
||||
|
||||
// Used in auto linking
|
||||
/obj/machinery/telecomms/proc/add_link(obj/machinery/telecomms/T)
|
||||
var/turf/position = get_turf(src)
|
||||
var/turf/T_position = get_turf(T)
|
||||
if((position.z == T_position.z) || (long_range_link && T.long_range_link))
|
||||
if(src != T)
|
||||
for(var/x in autolinkers)
|
||||
if(x in T.autolinkers)
|
||||
links |= T
|
||||
T.links |= src
|
||||
|
||||
/obj/machinery/telecomms/update_icon()
|
||||
if(on)
|
||||
if(panel_open)
|
||||
icon_state = "[initial(icon_state)]_o"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
if(panel_open)
|
||||
icon_state = "[initial(icon_state)]_o_off"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_off"
|
||||
|
||||
/obj/machinery/telecomms/proc/update_power()
|
||||
|
||||
if(toggled)
|
||||
if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off
|
||||
on = FALSE
|
||||
else
|
||||
on = TRUE
|
||||
else
|
||||
on = FALSE
|
||||
|
||||
/obj/machinery/telecomms/process()
|
||||
update_power()
|
||||
|
||||
// Update the icon
|
||||
update_icon()
|
||||
|
||||
if(traffic > 0)
|
||||
traffic -= netspeed
|
||||
|
||||
/obj/machinery/telecomms/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(prob(100/severity))
|
||||
if(!(stat & EMPED))
|
||||
stat |= EMPED
|
||||
var/duration = (300 * 10)/severity
|
||||
spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot.
|
||||
stat &= ~EMPED
|
||||
|
||||
/*
|
||||
Hello, friends, this is Doohl from sexylands. You may be wondering what this
|
||||
monstrous code file is. Sit down, boys and girls, while I tell you the tale.
|
||||
|
||||
|
||||
The telecom machines were designed to be compatible with any radio
|
||||
signals, provided they use subspace transmission. Currently they are only used for
|
||||
headsets, but they can eventually be outfitted for real COMPUTER networks. This
|
||||
is just a skeleton, ladies and gentlemen.
|
||||
|
||||
Look at radio.dm for the prequel to this code.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
|
||||
/obj/machinery/telecomms
|
||||
icon = 'icons/obj/machines/telecomms.dmi'
|
||||
critical_machine = TRUE
|
||||
var/list/links = list() // list of machines this machine is linked to
|
||||
var/traffic = 0 // value increases as traffic increases
|
||||
var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed)
|
||||
var/list/autolinkers = list() // list of text/number values to link with
|
||||
var/id = "NULL" // identification string
|
||||
var/network = "NULL" // the network of the machinery
|
||||
|
||||
var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all
|
||||
|
||||
var/on = TRUE
|
||||
var/toggled = TRUE // Is it toggled on
|
||||
var/long_range_link = FALSE // Can you link it across Z levels or on the otherside of the map? (Relay & Hub)
|
||||
var/hide = FALSE // Is it a hidden machine?
|
||||
|
||||
|
||||
/obj/machinery/telecomms/proc/relay_information(datum/signal/subspace/signal, filter, copysig, amount = 20)
|
||||
// relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending
|
||||
|
||||
if(!on)
|
||||
return
|
||||
var/send_count = 0
|
||||
|
||||
// Apply some lag based on traffic rates
|
||||
var/netlag = round(traffic / 50)
|
||||
if(netlag > signal.data["slow"])
|
||||
signal.data["slow"] = netlag
|
||||
|
||||
// Loop through all linked machines and send the signal or copy.
|
||||
for(var/obj/machinery/telecomms/machine in links)
|
||||
if(filter && !istype( machine, filter ))
|
||||
continue
|
||||
if(!machine.on)
|
||||
continue
|
||||
if(amount && send_count >= amount)
|
||||
break
|
||||
if(z != machine.loc.z && !long_range_link && !machine.long_range_link)
|
||||
continue
|
||||
|
||||
send_count++
|
||||
if(machine.is_freq_listening(signal))
|
||||
machine.traffic++
|
||||
|
||||
if(copysig)
|
||||
machine.receive_information(signal.copy(), src)
|
||||
else
|
||||
machine.receive_information(signal, src)
|
||||
|
||||
if(send_count > 0 && is_freq_listening(signal))
|
||||
traffic++
|
||||
|
||||
return send_count
|
||||
|
||||
/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine)
|
||||
// send signal directly to a machine
|
||||
machine.receive_information(signal, src)
|
||||
|
||||
/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
|
||||
// receive information from linked machinery
|
||||
|
||||
/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal)
|
||||
// return TRUE if found, FALSE if not found
|
||||
return signal && (!freq_listening.len || (signal.frequency in freq_listening))
|
||||
|
||||
/obj/machinery/telecomms/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
if(mapload && autolinkers.len)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/telecomms/LateInitialize()
|
||||
..()
|
||||
for(var/obj/machinery/telecomms/T in (long_range_link ? GLOB.telecomms_list : urange(20, src, 1)))
|
||||
add_link(T)
|
||||
|
||||
/obj/machinery/telecomms/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
for(var/obj/machinery/telecomms/comm in GLOB.telecomms_list)
|
||||
comm.links -= src
|
||||
links = list()
|
||||
return ..()
|
||||
|
||||
// Used in auto linking
|
||||
/obj/machinery/telecomms/proc/add_link(obj/machinery/telecomms/T)
|
||||
var/turf/position = get_turf(src)
|
||||
var/turf/T_position = get_turf(T)
|
||||
if((position.z == T_position.z) || (long_range_link && T.long_range_link))
|
||||
if(src != T)
|
||||
for(var/x in autolinkers)
|
||||
if(x in T.autolinkers)
|
||||
links |= T
|
||||
T.links |= src
|
||||
|
||||
/obj/machinery/telecomms/update_icon()
|
||||
if(on)
|
||||
if(panel_open)
|
||||
icon_state = "[initial(icon_state)]_o"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
if(panel_open)
|
||||
icon_state = "[initial(icon_state)]_o_off"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_off"
|
||||
|
||||
/obj/machinery/telecomms/proc/update_power()
|
||||
|
||||
if(toggled)
|
||||
if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off
|
||||
on = FALSE
|
||||
else
|
||||
on = TRUE
|
||||
else
|
||||
on = FALSE
|
||||
|
||||
/obj/machinery/telecomms/process()
|
||||
update_power()
|
||||
|
||||
// Update the icon
|
||||
update_icon()
|
||||
|
||||
if(traffic > 0)
|
||||
traffic -= netspeed
|
||||
|
||||
/obj/machinery/telecomms/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(prob(100/severity))
|
||||
if(!(stat & EMPED))
|
||||
stat |= EMPED
|
||||
var/duration = (300 * 10)/severity
|
||||
spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot.
|
||||
stat &= ~EMPED
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
#define AUTOYLATHE_MAIN_MENU 1
|
||||
#define AUTOYLATHE_CATEGORY_MENU 2
|
||||
#define AUTOYLATHE_SEARCH_MENU 3
|
||||
|
||||
/obj/machinery/autoylathe
|
||||
name = "autoylathe"
|
||||
desc = "It produces toys using plastic, metal and glass."
|
||||
icon_state = "autolathe"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
circuit = /obj/item/circuitboard/machine/autoylathe
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
var/operating = FALSE
|
||||
var/list/L = list()
|
||||
var/list/LL = list()
|
||||
var/hacked = FALSE
|
||||
var/disabled = 0
|
||||
var/shocked = FALSE
|
||||
var/hack_wire
|
||||
var/disable_wire
|
||||
var/shock_wire
|
||||
|
||||
var/busy = FALSE
|
||||
var/prod_coeff = 1
|
||||
|
||||
var/datum/design/being_built
|
||||
var/datum/techweb/stored_research
|
||||
var/list/datum/design/matching_designs
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
|
||||
var/list/categories = list(
|
||||
"Toys",
|
||||
"Figurines",
|
||||
"Pistols",
|
||||
"Rifles",
|
||||
"Heavy",
|
||||
"Melee",
|
||||
"Armor",
|
||||
"Adult",
|
||||
"Misc",
|
||||
"Imported"
|
||||
)
|
||||
|
||||
/obj/machinery/autoylathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASTIC), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autoylathe(src)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autoylathe
|
||||
matching_designs = list()
|
||||
|
||||
/obj/machinery/autoylathe/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autoylathe/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
|
||||
var/dat
|
||||
|
||||
switch(screen)
|
||||
if(AUTOYLATHE_MAIN_MENU)
|
||||
dat = main_win(user)
|
||||
if(AUTOYLATHE_CATEGORY_MENU)
|
||||
dat = category_win(user,selected_category)
|
||||
if(AUTOYLATHE_SEARCH_MENU)
|
||||
dat = search_win(user)
|
||||
|
||||
var/datum/browser/popup = new(user, "Autoylathe", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/autoylathe/on_deconstruction()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
|
||||
/obj/machinery/autoylathe/attackby(obj/item/O, mob/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The autoylathe is busy. Please wait for completion of previous operation.</span>")
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O))
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
if(default_deconstruction_crowbar(O))
|
||||
return TRUE
|
||||
|
||||
if(panel_open && is_wire_tool(O))
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
|
||||
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
if(stat)
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/disk/design_disk))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a design from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
busy = TRUE
|
||||
var/obj/item/disk/design_disk/D = O
|
||||
if(do_after(user, 14.4, target = src))
|
||||
for(var/B in D.blueprints)
|
||||
if(B)
|
||||
stored_research.add_design(B)
|
||||
busy = FALSE
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autoylathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
|
||||
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(amount_inserted / 10)
|
||||
else
|
||||
switch(id_inserted)
|
||||
if (MAT_METAL)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
if (MAT_GLASS)
|
||||
flick("autolathe_r",src)//plays glass insertion animation
|
||||
if (MAT_PLASTIC)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
use_power(amount_inserted / 10)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/autoylathe/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if (!busy)
|
||||
if(href_list["menu"])
|
||||
screen = text2num(href_list["menu"])
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["category"])
|
||||
selected_category = href_list["category"]
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["make"])
|
||||
|
||||
/////////////////
|
||||
//href protection
|
||||
being_built = stored_research.isDesignResearchedID(href_list["make"])
|
||||
if(!being_built)
|
||||
return
|
||||
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
|
||||
multiplier = CLAMP(multiplier,1,50)
|
||||
|
||||
/////////////////
|
||||
|
||||
var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
|
||||
var/metal_cost = being_built.materials[MAT_METAL]
|
||||
var/glass_cost = being_built.materials[MAT_GLASS]
|
||||
var/plastic_cost = being_built.materials[MAT_PLASTIC]
|
||||
var/power = max(2000, (metal_cost+glass_cost+plastic_cost)*multiplier/5)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff) && (materials.amount(MAT_PLASTIC) >= plastic_cost*multiplier*coeff))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
icon_state = "autolathe_n"
|
||||
var/time = is_stack ? 32 : 32*coeff*multiplier
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, plastic_cost, multiplier, coeff, is_stack), time)
|
||||
|
||||
if(href_list["search"])
|
||||
matching_designs.Cut()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(findtext(D.name,href_list["to_search"]))
|
||||
matching_designs.Add(D)
|
||||
updateUsrDialog()
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The autoylathe is busy. Please wait for completion of previous operation.</span>")
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autoylathe/proc/make_item(power, metal_cost, glass_cost, plastic_cost, multiplier, coeff, is_stack)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/atom/A = drop_location()
|
||||
use_power(power)
|
||||
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier, MAT_PLASTIC=plastic_cost*coeff*multiplier)
|
||||
materials.use_amount(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
|
||||
N.update_icon()
|
||||
N.autoylathe_crafted(src)
|
||||
else
|
||||
for(var/i=1, i<=multiplier, i++)
|
||||
var/obj/item/new_item = new being_built.build_path(A)
|
||||
new_item.materials = new_item.materials.Copy()
|
||||
for(var/mat in materials_used)
|
||||
new_item.materials[mat] = materials_used[mat] / multiplier
|
||||
new_item.autoylathe_crafted(src)
|
||||
icon_state = "autolathe"
|
||||
busy = FALSE
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/autoylathe/RefreshParts()
|
||||
var/T = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
|
||||
T += MB.rating*75000
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = T
|
||||
T=1.2
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T -= M.rating*0.2
|
||||
prod_coeff = CLAMP(T,1,0) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
|
||||
|
||||
/obj/machinery/autoylathe/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Autoylathe Menu:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
dat += "<form name='search' action='?src=[REF(src)]'>\
|
||||
<input type='hidden' name='src' value='[REF(src)]'>\
|
||||
<input type='hidden' name='search' value='to_search'>\
|
||||
<input type='hidden' name='menu' value='[AUTOYLATHE_SEARCH_MENU]'>\
|
||||
<input type='text' name='to_search'>\
|
||||
<input type='submit' value='Search'>\
|
||||
</form><hr>"
|
||||
|
||||
var/line_length = 1
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
|
||||
for(var/C in categories)
|
||||
if(line_length > 2)
|
||||
dat += "</tr><tr>"
|
||||
line_length = 1
|
||||
|
||||
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[AUTOYLATHE_CATEGORY_MENU]'>[C]</A></td>"
|
||||
line_length++
|
||||
|
||||
dat += "</tr></table></div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autoylathe/proc/category_win(mob/user,selected_category)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOYLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(!(selected_category in D.category))
|
||||
continue
|
||||
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS] ?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
else
|
||||
if(!disabled && can_build(D, 5))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=5'>x5</a>"
|
||||
if(!disabled && can_build(D, 10))
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autoylathe/proc/search_win(mob/user)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[AUTOYLATHE_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Search results:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in matching_designs)
|
||||
var/datum/design/D = v
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS] ?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):INFINITY)
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
|
||||
if(max_multiplier > 0 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
|
||||
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autoylathe/proc/materials_printout()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
dat += "<b>[M.name] amount:</b> [M.amount] cm<sup>3</sup><br>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autoylathe/proc/can_build(datum/design/D, amount = 1)
|
||||
if(D.make_reagents.len)
|
||||
return FALSE
|
||||
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
|
||||
return FALSE
|
||||
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
|
||||
return FALSE
|
||||
if(D.materials[MAT_PLASTIC] && (materials.amount(MAT_PLASTIC) < (D.materials[MAT_PLASTIC] * coeff * amount)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/autoylathe/proc/get_design_cost(datum/design/D)
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
var/dat
|
||||
if(D.materials[MAT_METAL])
|
||||
dat += "[D.materials[MAT_METAL] * coeff] metal "
|
||||
if(D.materials[MAT_GLASS])
|
||||
dat += "[D.materials[MAT_GLASS] * coeff] glass "
|
||||
if(D.materials[MAT_PLASTIC])
|
||||
dat += "[D.materials[MAT_PLASTIC] * coeff] plastic"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autoylathe/proc/reset(wire)
|
||||
switch(wire)
|
||||
if(WIRE_HACK)
|
||||
if(!wires.is_cut(wire))
|
||||
adjust_hacked(FALSE)
|
||||
if(WIRE_SHOCK)
|
||||
if(!wires.is_cut(wire))
|
||||
shocked = FALSE
|
||||
if(WIRE_DISABLE)
|
||||
if(!wires.is_cut(wire))
|
||||
disabled = FALSE
|
||||
|
||||
/obj/machinery/autoylathe/proc/shock(mob/user, prb)
|
||||
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
||||
return FALSE
|
||||
if(!prob(prb))
|
||||
return FALSE
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/autoylathe/proc/adjust_hacked(state)
|
||||
hacked = state
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_designs[id]
|
||||
if((D.build_type & AUTOYLATHE) && ("hacked" in D.category))
|
||||
if(hacked)
|
||||
stored_research.add_design(D)
|
||||
else
|
||||
stored_research.remove_design(D)
|
||||
|
||||
/obj/machinery/autoylathe/hacked/Initialize()
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
|
||||
//Called when the object is constructed by an autoylathe
|
||||
//Has a reference to the autoylathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/item/proc/autoylathe_crafted(obj/machinery/autoylathe/A)
|
||||
return
|
||||
@@ -1,284 +1,284 @@
|
||||
/obj/machinery/washing_machine
|
||||
name = "washing machine"
|
||||
desc = "Gets rid of those pesky bloodstains, or your money back!"
|
||||
icon = 'icons/obj/machines/washing_machine.dmi'
|
||||
icon_state = "wm_1_0"
|
||||
density = TRUE
|
||||
state_open = TRUE
|
||||
var/busy = FALSE
|
||||
var/bloody_mess = 0
|
||||
var/has_corgi = 0
|
||||
var/obj/item/color_source
|
||||
var/max_wash_capacity = 5
|
||||
|
||||
/obj/machinery/washing_machine/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click it to start a wash cycle.</span>"
|
||||
|
||||
/obj/machinery/washing_machine/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src))
|
||||
return
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='notice'>Close the door first</span>")
|
||||
return TRUE
|
||||
|
||||
if(bloody_mess)
|
||||
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
|
||||
return TRUE
|
||||
|
||||
if(has_corgi)
|
||||
bloody_mess = 1
|
||||
|
||||
busy = TRUE
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/wash_cycle), 200)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/washing_machine/process()
|
||||
if (!busy)
|
||||
animate(src, transform=matrix(), time=2)
|
||||
return PROCESS_KILL
|
||||
if (anchored)
|
||||
if (prob(5))
|
||||
var/matrix/M = new
|
||||
M.Translate(rand(-1, 1), rand(0, 1))
|
||||
animate(src, transform=M, time=1)
|
||||
animate(transform=matrix(), time=1)
|
||||
else
|
||||
if (prob(1))
|
||||
step(src, pick(GLOB.cardinals))
|
||||
var/matrix/M = new
|
||||
M.Translate(rand(-3, 3), rand(-1, 3))
|
||||
animate(src, transform=M, time=2)
|
||||
|
||||
/obj/machinery/washing_machine/clean_blood()
|
||||
..()
|
||||
if(!busy)
|
||||
bloody_mess = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/washing_machine/proc/wash_cycle()
|
||||
for(var/X in contents)
|
||||
var/atom/movable/AM = X
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
AM.clean_blood()
|
||||
AM.machine_wash(src)
|
||||
|
||||
busy = FALSE
|
||||
if(color_source)
|
||||
qdel(color_source)
|
||||
color_source = null
|
||||
update_icon()
|
||||
|
||||
|
||||
//what happens to this object when washed inside a washing machine
|
||||
/atom/movable/proc/machine_wash(obj/machinery/washing_machine/WM)
|
||||
return
|
||||
|
||||
/obj/item/stack/sheet/hairlesshide/machine_wash(obj/machinery/washing_machine/WM)
|
||||
new /obj/item/stack/sheet/wetleather(drop_location(), amount)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/suit/hooded/ian_costume/machine_wash(obj/machinery/washing_machine/WM)
|
||||
new /obj/item/reagent_containers/food/snacks/meat/slab/corgi(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/paper/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
if(istype(WM.color_source, /obj/item/toy/crayon))
|
||||
var/obj/item/toy/crayon/CR = WM.color_source
|
||||
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
|
||||
|
||||
/obj/item/reagents_containers/rag/towel/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
if(istype(WM.color_source, /obj/item/toy/crayon))
|
||||
var/obj/item/toy/crayon/CR = WM.color_source
|
||||
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/machine_wash(obj/machinery/washing_machine/WM)
|
||||
gib()
|
||||
|
||||
/obj/item/clothing/under/color/machine_wash(obj/machinery/washing_machine/WM)
|
||||
jumpsuit_wash(WM)
|
||||
|
||||
/obj/item/clothing/under/rank/machine_wash(obj/machinery/washing_machine/WM)
|
||||
jumpsuit_wash(WM)
|
||||
|
||||
/obj/item/clothing/under/proc/jumpsuit_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
var/obj/item/clothing/under/U
|
||||
for(var/T in typesof(/obj/item/clothing/under/color))
|
||||
var/obj/item/clothing/under/color/J = T
|
||||
if(wash_color == initial(J.item_color))
|
||||
U = J
|
||||
break
|
||||
if(!U)
|
||||
for(var/T in typesof(/obj/item/clothing/under/rank))
|
||||
var/obj/item/clothing/under/rank/R = T
|
||||
if(wash_color == initial(R.item_color))
|
||||
U = R
|
||||
break
|
||||
if(U)
|
||||
item_state = initial(U.item_state)
|
||||
icon_state = initial(U.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(U.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
can_adjust = initial(U.can_adjust)
|
||||
if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable
|
||||
toggle_jumpsuit_adjust()
|
||||
|
||||
/obj/item/clothing/gloves/color/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/gloves/color))
|
||||
var/obj/item/clothing/gloves/color/G = T
|
||||
if(wash_color == initial(G.item_color))
|
||||
item_state = initial(G.item_state)
|
||||
icon_state = initial(G.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(G.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/clothing/shoes/sneakers/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(chained)
|
||||
chained = 0
|
||||
slowdown = SHOES_SLOWDOWN
|
||||
new /obj/item/restraints/handcuffs(loc)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/shoes/sneakers))
|
||||
var/obj/item/clothing/shoes/sneakers/S = T
|
||||
if(wash_color == initial(S.item_color))
|
||||
icon_state = initial(S.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(S.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/bedsheet/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/bedsheet))
|
||||
var/obj/item/bedsheet/B = T
|
||||
if(wash_color == initial(B.item_color))
|
||||
icon_state = initial(B.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(B.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/clothing/head/soft/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/head/soft))
|
||||
var/obj/item/clothing/head/soft/H = T
|
||||
if(wash_color == initial(H.item_color))
|
||||
icon_state = initial(H.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(H.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
|
||||
/obj/machinery/washing_machine/relaymove(mob/user)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/washing_machine/container_resist(mob/living/user)
|
||||
if(!busy)
|
||||
add_fingerprint(user)
|
||||
open_machine()
|
||||
|
||||
|
||||
|
||||
/obj/machinery/washing_machine/update_icon()
|
||||
cut_overlays()
|
||||
if(busy)
|
||||
icon_state = "wm_running_[bloody_mess]"
|
||||
else if(bloody_mess)
|
||||
icon_state = "wm_[state_open]_blood"
|
||||
else
|
||||
var/full = contents.len ? 1 : 0
|
||||
icon_state = "wm_[state_open]_[full]"
|
||||
if(panel_open)
|
||||
add_overlay("wm_panel")
|
||||
|
||||
/obj/machinery/washing_machine/attackby(obj/item/W, mob/user, params)
|
||||
if(panel_open && !busy && default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, null, null, W))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>It's too unwieldly to put in this way.</span>")
|
||||
return 1
|
||||
|
||||
else if(user.a_intent != INTENT_HARM)
|
||||
|
||||
if (!state_open)
|
||||
to_chat(user, "<span class='warning'>Open the door first!</span>")
|
||||
return 1
|
||||
|
||||
if(bloody_mess)
|
||||
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
|
||||
return 1
|
||||
|
||||
if(contents.len >= max_wash_capacity)
|
||||
to_chat(user, "<span class='warning'>The washing machine is full!</span>")
|
||||
return 1
|
||||
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you cannot put it in the washing machine!</span>")
|
||||
return 1
|
||||
|
||||
if(istype(W, /obj/item/toy/crayon) || istype(W, /obj/item/stamp))
|
||||
color_source = W
|
||||
update_icon()
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/washing_machine/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(busy)
|
||||
to_chat(user, "<span class='warning'>[src] is busy.</span>")
|
||||
return
|
||||
|
||||
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
|
||||
var/mob/living/L = user.pulling
|
||||
if(L.buckled || L.has_buckled_mobs())
|
||||
return
|
||||
if(state_open)
|
||||
if(iscorgi(L))
|
||||
has_corgi = 1
|
||||
L.forceMove(src)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(!state_open)
|
||||
open_machine()
|
||||
else
|
||||
state_open = FALSE //close the door
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/washing_machine/deconstruct(disassembled = TRUE)
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/washing_machine/open_machine(drop = 1)
|
||||
..()
|
||||
density = TRUE //because machinery/open_machine() sets it to 0
|
||||
color_source = null
|
||||
has_corgi = 0
|
||||
/obj/machinery/washing_machine
|
||||
name = "washing machine"
|
||||
desc = "Gets rid of those pesky bloodstains, or your money back!"
|
||||
icon = 'icons/obj/machines/washing_machine.dmi'
|
||||
icon_state = "wm_1_0"
|
||||
density = TRUE
|
||||
state_open = TRUE
|
||||
var/busy = FALSE
|
||||
var/bloody_mess = 0
|
||||
var/has_corgi = 0
|
||||
var/obj/item/color_source
|
||||
var/max_wash_capacity = 5
|
||||
|
||||
/obj/machinery/washing_machine/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click it to start a wash cycle.</span>"
|
||||
|
||||
/obj/machinery/washing_machine/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src))
|
||||
return
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='notice'>Close the door first</span>")
|
||||
return TRUE
|
||||
|
||||
if(bloody_mess)
|
||||
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
|
||||
return TRUE
|
||||
|
||||
if(has_corgi)
|
||||
bloody_mess = 1
|
||||
|
||||
busy = TRUE
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/wash_cycle), 200)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/washing_machine/process()
|
||||
if (!busy)
|
||||
animate(src, transform=matrix(), time=2)
|
||||
return PROCESS_KILL
|
||||
if (anchored)
|
||||
if (prob(5))
|
||||
var/matrix/M = new
|
||||
M.Translate(rand(-1, 1), rand(0, 1))
|
||||
animate(src, transform=M, time=1)
|
||||
animate(transform=matrix(), time=1)
|
||||
else
|
||||
if (prob(1))
|
||||
step(src, pick(GLOB.cardinals))
|
||||
var/matrix/M = new
|
||||
M.Translate(rand(-3, 3), rand(-1, 3))
|
||||
animate(src, transform=M, time=2)
|
||||
|
||||
/obj/machinery/washing_machine/clean_blood()
|
||||
..()
|
||||
if(!busy)
|
||||
bloody_mess = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/washing_machine/proc/wash_cycle()
|
||||
for(var/X in contents)
|
||||
var/atom/movable/AM = X
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
AM.clean_blood()
|
||||
AM.machine_wash(src)
|
||||
|
||||
busy = FALSE
|
||||
if(color_source)
|
||||
qdel(color_source)
|
||||
color_source = null
|
||||
update_icon()
|
||||
|
||||
|
||||
//what happens to this object when washed inside a washing machine
|
||||
/atom/movable/proc/machine_wash(obj/machinery/washing_machine/WM)
|
||||
return
|
||||
|
||||
/obj/item/stack/sheet/hairlesshide/machine_wash(obj/machinery/washing_machine/WM)
|
||||
new /obj/item/stack/sheet/wetleather(drop_location(), amount)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/suit/hooded/ian_costume/machine_wash(obj/machinery/washing_machine/WM)
|
||||
new /obj/item/reagent_containers/food/snacks/meat/slab/corgi(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/paper/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
if(istype(WM.color_source, /obj/item/toy/crayon))
|
||||
var/obj/item/toy/crayon/CR = WM.color_source
|
||||
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
|
||||
|
||||
/obj/item/reagents_containers/rag/towel/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
if(istype(WM.color_source, /obj/item/toy/crayon))
|
||||
var/obj/item/toy/crayon/CR = WM.color_source
|
||||
add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/machine_wash(obj/machinery/washing_machine/WM)
|
||||
gib()
|
||||
|
||||
/obj/item/clothing/under/color/machine_wash(obj/machinery/washing_machine/WM)
|
||||
jumpsuit_wash(WM)
|
||||
|
||||
/obj/item/clothing/under/rank/machine_wash(obj/machinery/washing_machine/WM)
|
||||
jumpsuit_wash(WM)
|
||||
|
||||
/obj/item/clothing/under/proc/jumpsuit_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
var/obj/item/clothing/under/U
|
||||
for(var/T in typesof(/obj/item/clothing/under/color))
|
||||
var/obj/item/clothing/under/color/J = T
|
||||
if(wash_color == initial(J.item_color))
|
||||
U = J
|
||||
break
|
||||
if(!U)
|
||||
for(var/T in typesof(/obj/item/clothing/under/rank))
|
||||
var/obj/item/clothing/under/rank/R = T
|
||||
if(wash_color == initial(R.item_color))
|
||||
U = R
|
||||
break
|
||||
if(U)
|
||||
item_state = initial(U.item_state)
|
||||
icon_state = initial(U.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(U.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
can_adjust = initial(U.can_adjust)
|
||||
if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable
|
||||
toggle_jumpsuit_adjust()
|
||||
|
||||
/obj/item/clothing/gloves/color/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/gloves/color))
|
||||
var/obj/item/clothing/gloves/color/G = T
|
||||
if(wash_color == initial(G.item_color))
|
||||
item_state = initial(G.item_state)
|
||||
icon_state = initial(G.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(G.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/clothing/shoes/sneakers/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(chained)
|
||||
chained = 0
|
||||
slowdown = SHOES_SLOWDOWN
|
||||
new /obj/item/restraints/handcuffs(loc)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/shoes/sneakers))
|
||||
var/obj/item/clothing/shoes/sneakers/S = T
|
||||
if(wash_color == initial(S.item_color))
|
||||
icon_state = initial(S.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(S.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/bedsheet/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/bedsheet))
|
||||
var/obj/item/bedsheet/B = T
|
||||
if(wash_color == initial(B.item_color))
|
||||
icon_state = initial(B.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(B.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
/obj/item/clothing/head/soft/machine_wash(obj/machinery/washing_machine/WM)
|
||||
if(WM.color_source)
|
||||
var/wash_color = WM.color_source.item_color
|
||||
for(var/T in typesof(/obj/item/clothing/head/soft))
|
||||
var/obj/item/clothing/head/soft/H = T
|
||||
if(wash_color == initial(H.item_color))
|
||||
icon_state = initial(H.icon_state)
|
||||
item_color = wash_color
|
||||
name = initial(H.name)
|
||||
desc = "The colors are a bit dodgy."
|
||||
break
|
||||
|
||||
|
||||
/obj/machinery/washing_machine/relaymove(mob/user)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/washing_machine/container_resist(mob/living/user)
|
||||
if(!busy)
|
||||
add_fingerprint(user)
|
||||
open_machine()
|
||||
|
||||
|
||||
|
||||
/obj/machinery/washing_machine/update_icon()
|
||||
cut_overlays()
|
||||
if(busy)
|
||||
icon_state = "wm_running_[bloody_mess]"
|
||||
else if(bloody_mess)
|
||||
icon_state = "wm_[state_open]_blood"
|
||||
else
|
||||
var/full = contents.len ? 1 : 0
|
||||
icon_state = "wm_[state_open]_[full]"
|
||||
if(panel_open)
|
||||
add_overlay("wm_panel")
|
||||
|
||||
/obj/machinery/washing_machine/attackby(obj/item/W, mob/user, params)
|
||||
if(panel_open && !busy && default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, null, null, W))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/clothing/head/mob_holder))
|
||||
to_chat(user, "<span class='warning'>It's too unwieldly to put in this way.</span>")
|
||||
return 1
|
||||
|
||||
else if(user.a_intent != INTENT_HARM)
|
||||
|
||||
if (!state_open)
|
||||
to_chat(user, "<span class='warning'>Open the door first!</span>")
|
||||
return 1
|
||||
|
||||
if(bloody_mess)
|
||||
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
|
||||
return 1
|
||||
|
||||
if(contents.len >= max_wash_capacity)
|
||||
to_chat(user, "<span class='warning'>The washing machine is full!</span>")
|
||||
return 1
|
||||
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you cannot put it in the washing machine!</span>")
|
||||
return 1
|
||||
|
||||
if(istype(W, /obj/item/toy/crayon) || istype(W, /obj/item/stamp))
|
||||
color_source = W
|
||||
update_icon()
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/washing_machine/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(busy)
|
||||
to_chat(user, "<span class='warning'>[src] is busy.</span>")
|
||||
return
|
||||
|
||||
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
|
||||
var/mob/living/L = user.pulling
|
||||
if(L.buckled || L.has_buckled_mobs())
|
||||
return
|
||||
if(state_open)
|
||||
if(iscorgi(L))
|
||||
has_corgi = 1
|
||||
L.forceMove(src)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(!state_open)
|
||||
open_machine()
|
||||
else
|
||||
state_open = FALSE //close the door
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/washing_machine/deconstruct(disassembled = TRUE)
|
||||
new /obj/item/stack/sheet/metal (loc, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/washing_machine/open_machine(drop = 1)
|
||||
..()
|
||||
density = TRUE //because machinery/open_machine() sets it to 0
|
||||
color_source = null
|
||||
has_corgi = 0
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
/obj/machinery/wish_granter
|
||||
name = "wish granter"
|
||||
desc = "You're not so sure about this, anymore..."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "syndbeacon"
|
||||
|
||||
use_power = NO_POWER_USE
|
||||
density = TRUE
|
||||
|
||||
var/charges = 1
|
||||
var/insisting = 0
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
|
||||
else if(!ishuman(user))
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
return
|
||||
|
||||
else if(is_special_character(user))
|
||||
to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
|
||||
|
||||
else if (!insisting)
|
||||
to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
|
||||
insisting++
|
||||
|
||||
else
|
||||
to_chat(user, "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
|
||||
|
||||
charges--
|
||||
insisting = 0
|
||||
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
|
||||
to_chat(user, "You have a very bad feeling about this.")
|
||||
|
||||
return
|
||||
/obj/machinery/wish_granter
|
||||
name = "wish granter"
|
||||
desc = "You're not so sure about this, anymore..."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "syndbeacon"
|
||||
|
||||
use_power = NO_POWER_USE
|
||||
density = TRUE
|
||||
|
||||
var/charges = 1
|
||||
var/insisting = 0
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
|
||||
else if(!ishuman(user))
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
return
|
||||
|
||||
else if(is_special_character(user))
|
||||
to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
|
||||
|
||||
else if (!insisting)
|
||||
to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
|
||||
insisting++
|
||||
|
||||
else
|
||||
to_chat(user, "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
|
||||
|
||||
charges--
|
||||
insisting = 0
|
||||
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
|
||||
to_chat(user, "You have a very bad feeling about this.")
|
||||
|
||||
return
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/obj/mecha/combat
|
||||
force = 30
|
||||
internal_damage_threshold = 50
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
|
||||
var/spawn_tracked = TRUE
|
||||
|
||||
/obj/mecha/combat/Initialize()
|
||||
. = ..()
|
||||
if(spawn_tracked)
|
||||
/obj/mecha/combat
|
||||
force = 30
|
||||
internal_damage_threshold = 50
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
|
||||
var/spawn_tracked = TRUE
|
||||
|
||||
/obj/mecha/combat/Initialize()
|
||||
. = ..()
|
||||
if(spawn_tracked)
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
@@ -1,21 +1,21 @@
|
||||
/obj/mecha/combat/durand
|
||||
desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms."
|
||||
name = "\improper Durand"
|
||||
icon_state = "durand"
|
||||
step_in = 4
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 400
|
||||
deflect_chance = 20
|
||||
armor = list("melee" = 40, "bullet" = 35, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 30000
|
||||
infra_luminosity = 8
|
||||
force = 40
|
||||
wreckage = /obj/structure/mecha_wreckage/durand
|
||||
|
||||
/obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
defense_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
defense_action.Remove(user)
|
||||
/obj/mecha/combat/durand
|
||||
desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms."
|
||||
name = "\improper Durand"
|
||||
icon_state = "durand"
|
||||
step_in = 4
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 400
|
||||
deflect_chance = 20
|
||||
armor = list("melee" = 40, "bullet" = 35, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 30000
|
||||
infra_luminosity = 8
|
||||
force = 40
|
||||
wreckage = /obj/structure/mecha_wreckage/durand
|
||||
|
||||
/obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
defense_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
defense_action.Remove(user)
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
/obj/mecha/combat/gygax
|
||||
desc = "A lightweight, security exosuit. Popular among private and corporate security."
|
||||
name = "\improper Gygax"
|
||||
icon_state = "gygax"
|
||||
step_in = 3
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 250
|
||||
deflect_chance = 5
|
||||
force = 20
|
||||
armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 6
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax
|
||||
internal_damage_threshold = 35
|
||||
max_equip = 3
|
||||
step_energy_drain = 3
|
||||
leg_overload_coeff = 300
|
||||
|
||||
/obj/mecha/combat/gygax/dark
|
||||
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
|
||||
name = "\improper Dark Gygax"
|
||||
icon_state = "darkgygax"
|
||||
max_integrity = 300
|
||||
deflect_chance = 15
|
||||
force = 25
|
||||
armor = list("melee" = 40, "bullet" = 40, "laser" = 50, "energy" = 35, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 35000
|
||||
leg_overload_coeff = 100
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax/dark
|
||||
max_equip = 4
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/gygax/dark/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null)
|
||||
if(C)
|
||||
C.forceMove(src)
|
||||
cell = C
|
||||
return
|
||||
cell = new /obj/item/stock_parts/cell/hyper(src)
|
||||
|
||||
/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
overload_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
thrusters_action.Grant(user, src)
|
||||
|
||||
|
||||
/obj/mecha/combat/gygax/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
overload_action.Remove(user)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
thrusters_action.Remove(user)
|
||||
/obj/mecha/combat/gygax
|
||||
desc = "A lightweight, security exosuit. Popular among private and corporate security."
|
||||
name = "\improper Gygax"
|
||||
icon_state = "gygax"
|
||||
step_in = 3
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 250
|
||||
deflect_chance = 5
|
||||
force = 20
|
||||
armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 6
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax
|
||||
internal_damage_threshold = 35
|
||||
max_equip = 3
|
||||
step_energy_drain = 3
|
||||
leg_overload_coeff = 300
|
||||
|
||||
/obj/mecha/combat/gygax/dark
|
||||
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
|
||||
name = "\improper Dark Gygax"
|
||||
icon_state = "darkgygax"
|
||||
max_integrity = 300
|
||||
deflect_chance = 15
|
||||
force = 25
|
||||
armor = list("melee" = 40, "bullet" = 40, "laser" = 50, "energy" = 35, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 35000
|
||||
leg_overload_coeff = 100
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax/dark
|
||||
max_equip = 4
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/gygax/dark/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null)
|
||||
if(C)
|
||||
C.forceMove(src)
|
||||
cell = C
|
||||
return
|
||||
cell = new /obj/item/stock_parts/cell/hyper(src)
|
||||
|
||||
/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
overload_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
thrusters_action.Grant(user, src)
|
||||
|
||||
|
||||
/obj/mecha/combat/gygax/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
overload_action.Remove(user)
|
||||
|
||||
/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
thrusters_action.Remove(user)
|
||||
|
||||
+155
-155
@@ -1,156 +1,156 @@
|
||||
/obj/mecha/combat/honker
|
||||
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!"
|
||||
name = "\improper H.O.N.K"
|
||||
icon_state = "honker"
|
||||
step_in = 3
|
||||
max_integrity = 140
|
||||
deflect_chance = 60
|
||||
internal_damage_threshold = 60
|
||||
armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 5
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/honker
|
||||
add_req_access = 0
|
||||
max_equip = 3
|
||||
var/squeak = 0
|
||||
|
||||
/obj/mecha/combat/honker/get_stats_part()
|
||||
var/integrity = obj_integrity/max_integrity*100
|
||||
var/cell_charge = get_charge()
|
||||
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
|
||||
var/tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None"
|
||||
var/tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown"
|
||||
var/cabin_pressure = round(return_pressure(),0.01)
|
||||
var/output = {"[report_internal_damage()]
|
||||
[integrity<30?"<font color='red'><b>DAMAGE LEVEL CRITICAL</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_TEMP_CONTROL?"<font color='red'><b>CLOWN SUPPORT SYSTEM MALFUNCTION</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_TANK_BREACH?"<font color='red'><b>GAS TANK HONK</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_CONTROL_LOST?"<font color='red'><b>HONK-A-DOODLE</b></font> - <a href='?src=[REF(src)];repair_int_control_lost=1'>Recalibrate</a><br>":null]
|
||||
<b>IntegriHONK: </b> [integrity]%<br>
|
||||
<b>PowerHONK charge: </b>[isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]<br>
|
||||
<b>Air source: </b>[use_internal_tank?"Internal Airtank":"Environment"]<br>
|
||||
<b>AirHONK pressure: </b>[tank_pressure]kPa<br>
|
||||
<b>AirHONK temperature: </b>[tank_temperature]°K|[tank_temperature - T0C]°C<br>
|
||||
<b>HONK pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<font color='red'>[cabin_pressure]</font>": cabin_pressure]kPa<br>
|
||||
<b>HONK temperature: </b> [return_temperature()]°K|[return_temperature() - T0C]°C<br>
|
||||
<b>Lights: </b>[lights?"on":"off"]<br>
|
||||
[dna_lock?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[dna_lock]</span> \[<a href='?src=[REF(src)];reset_dna=1'>Reset</a>\]<br>":null]
|
||||
"}
|
||||
return output
|
||||
|
||||
/obj/mecha/combat/honker/get_stats_html()
|
||||
var/output = {"<html>
|
||||
<head><title>[src.name] data</title>
|
||||
<style>
|
||||
body {color: #00ff00; background: #32CD32; font-family:"Courier",monospace; font-size: 12px;}
|
||||
hr {border: 1px solid #0f0; color: #fff; background-color: #000;}
|
||||
a {padding:2px 5px;;color:#0f0;}
|
||||
.wr {margin-bottom: 5px;}
|
||||
.header {cursor:pointer;}
|
||||
.open, .closed {background: #32CD32; color:#000; padding:1px 2px;}
|
||||
.links a {margin-bottom: 2px;padding-top:3px;}
|
||||
.visible {display: block;}
|
||||
.hidden {display: none;}
|
||||
</style>
|
||||
<script language='javascript' type='text/javascript'>
|
||||
[js_byjax]
|
||||
[js_dropdowns]
|
||||
function SSticker() {
|
||||
setInterval(function(){
|
||||
window.location='byond://?src=[REF(src)]&update_content=1';
|
||||
document.body.style.color = get_rand_color_string();
|
||||
document.body.style.background = get_rand_color_string();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function get_rand_color_string() {
|
||||
var color = new Array;
|
||||
for(var i=0;i<3;i++){
|
||||
color.push(Math.floor(Math.random()*255));
|
||||
}
|
||||
return "rgb("+color.toString()+")";
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
dropdowns();
|
||||
SSticker();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='content'>
|
||||
[src.get_stats_part()]
|
||||
</div>
|
||||
<div id='eq_list'>
|
||||
[src.get_equipment_list()]
|
||||
</div>
|
||||
<hr>
|
||||
<div id='commands'>
|
||||
[src.get_commands()]
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
return output
|
||||
|
||||
/obj/mecha/combat/honker/get_commands()
|
||||
var/output = {"<div class='wr'>
|
||||
<div class='header'>Sounds of HONK:</div>
|
||||
<div class='links'>
|
||||
<a href='?src=[REF(src)];play_sound=sadtrombone'>Sad Trombone</a>
|
||||
<a href='?src=[REF(src)];play_sound=bikehorn'>Bike Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=airhorn2'>Air Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=carhorn'>Car Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=party_horn'>Party Horn</a>
|
||||
</div>
|
||||
</div>
|
||||
"}
|
||||
output += ..()
|
||||
return output
|
||||
|
||||
|
||||
/obj/mecha/combat/honker/get_equipment_list()
|
||||
if(!equipment.len)
|
||||
return
|
||||
var/output = "<b>Honk-ON-Systems:</b><div style=\"margin-left: 15px;\">"
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
|
||||
output += "<div id='[REF(MT)]'>[MT.get_equip_info()]</div>"
|
||||
output += "</div>"
|
||||
return output
|
||||
|
||||
|
||||
|
||||
/obj/mecha/combat/honker/mechstep(direction)
|
||||
var/result = step(src,direction)
|
||||
if(result)
|
||||
if(!squeak)
|
||||
playsound(src, "clownstep", 70, 1)
|
||||
squeak = 1
|
||||
else
|
||||
squeak = 0
|
||||
return result
|
||||
|
||||
/obj/mecha/combat/honker/Topic(href, href_list)
|
||||
..()
|
||||
if (href_list["play_sound"])
|
||||
switch(href_list["play_sound"])
|
||||
if("sadtrombone")
|
||||
playsound(src, 'sound/misc/sadtrombone.ogg', 50)
|
||||
if("bikehorn")
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 50)
|
||||
if("airhorn2")
|
||||
playsound(src, 'sound/items/airhorn2.ogg', 40) //soundfile has higher than average volume
|
||||
if("carhorn")
|
||||
playsound(src, 'sound/items/carhorn.ogg', 80) //soundfile has lower than average volume
|
||||
if("party_horn")
|
||||
playsound(src, 'sound/items/party_horn.ogg', 50)
|
||||
return
|
||||
|
||||
/proc/rand_hex_color()
|
||||
var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f")
|
||||
var/color=""
|
||||
for (var/i=0;i<6;i++)
|
||||
color = color+pick(colors)
|
||||
/obj/mecha/combat/honker
|
||||
desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!"
|
||||
name = "\improper H.O.N.K"
|
||||
icon_state = "honker"
|
||||
step_in = 3
|
||||
max_integrity = 140
|
||||
deflect_chance = 60
|
||||
internal_damage_threshold = 60
|
||||
armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 5
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/honker
|
||||
add_req_access = 0
|
||||
max_equip = 3
|
||||
var/squeak = 0
|
||||
|
||||
/obj/mecha/combat/honker/get_stats_part()
|
||||
var/integrity = obj_integrity/max_integrity*100
|
||||
var/cell_charge = get_charge()
|
||||
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
|
||||
var/tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None"
|
||||
var/tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown"
|
||||
var/cabin_pressure = round(return_pressure(),0.01)
|
||||
var/output = {"[report_internal_damage()]
|
||||
[integrity<30?"<font color='red'><b>DAMAGE LEVEL CRITICAL</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_TEMP_CONTROL?"<font color='red'><b>CLOWN SUPPORT SYSTEM MALFUNCTION</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_TANK_BREACH?"<font color='red'><b>GAS TANK HONK</b></font><br>":null]
|
||||
[internal_damage&MECHA_INT_CONTROL_LOST?"<font color='red'><b>HONK-A-DOODLE</b></font> - <a href='?src=[REF(src)];repair_int_control_lost=1'>Recalibrate</a><br>":null]
|
||||
<b>IntegriHONK: </b> [integrity]%<br>
|
||||
<b>PowerHONK charge: </b>[isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]<br>
|
||||
<b>Air source: </b>[use_internal_tank?"Internal Airtank":"Environment"]<br>
|
||||
<b>AirHONK pressure: </b>[tank_pressure]kPa<br>
|
||||
<b>AirHONK temperature: </b>[tank_temperature]°K|[tank_temperature - T0C]°C<br>
|
||||
<b>HONK pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<font color='red'>[cabin_pressure]</font>": cabin_pressure]kPa<br>
|
||||
<b>HONK temperature: </b> [return_temperature()]°K|[return_temperature() - T0C]°C<br>
|
||||
<b>Lights: </b>[lights?"on":"off"]<br>
|
||||
[dna_lock?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[dna_lock]</span> \[<a href='?src=[REF(src)];reset_dna=1'>Reset</a>\]<br>":null]
|
||||
"}
|
||||
return output
|
||||
|
||||
/obj/mecha/combat/honker/get_stats_html()
|
||||
var/output = {"<html>
|
||||
<head><title>[src.name] data</title>
|
||||
<style>
|
||||
body {color: #00ff00; background: #32CD32; font-family:"Courier",monospace; font-size: 12px;}
|
||||
hr {border: 1px solid #0f0; color: #fff; background-color: #000;}
|
||||
a {padding:2px 5px;;color:#0f0;}
|
||||
.wr {margin-bottom: 5px;}
|
||||
.header {cursor:pointer;}
|
||||
.open, .closed {background: #32CD32; color:#000; padding:1px 2px;}
|
||||
.links a {margin-bottom: 2px;padding-top:3px;}
|
||||
.visible {display: block;}
|
||||
.hidden {display: none;}
|
||||
</style>
|
||||
<script language='javascript' type='text/javascript'>
|
||||
[js_byjax]
|
||||
[js_dropdowns]
|
||||
function SSticker() {
|
||||
setInterval(function(){
|
||||
window.location='byond://?src=[REF(src)]&update_content=1';
|
||||
document.body.style.color = get_rand_color_string();
|
||||
document.body.style.background = get_rand_color_string();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function get_rand_color_string() {
|
||||
var color = new Array;
|
||||
for(var i=0;i<3;i++){
|
||||
color.push(Math.floor(Math.random()*255));
|
||||
}
|
||||
return "rgb("+color.toString()+")";
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
dropdowns();
|
||||
SSticker();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='content'>
|
||||
[src.get_stats_part()]
|
||||
</div>
|
||||
<div id='eq_list'>
|
||||
[src.get_equipment_list()]
|
||||
</div>
|
||||
<hr>
|
||||
<div id='commands'>
|
||||
[src.get_commands()]
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
return output
|
||||
|
||||
/obj/mecha/combat/honker/get_commands()
|
||||
var/output = {"<div class='wr'>
|
||||
<div class='header'>Sounds of HONK:</div>
|
||||
<div class='links'>
|
||||
<a href='?src=[REF(src)];play_sound=sadtrombone'>Sad Trombone</a>
|
||||
<a href='?src=[REF(src)];play_sound=bikehorn'>Bike Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=airhorn2'>Air Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=carhorn'>Car Horn</a>
|
||||
<a href='?src=[REF(src)];play_sound=party_horn'>Party Horn</a>
|
||||
</div>
|
||||
</div>
|
||||
"}
|
||||
output += ..()
|
||||
return output
|
||||
|
||||
|
||||
/obj/mecha/combat/honker/get_equipment_list()
|
||||
if(!equipment.len)
|
||||
return
|
||||
var/output = "<b>Honk-ON-Systems:</b><div style=\"margin-left: 15px;\">"
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment)
|
||||
output += "<div id='[REF(MT)]'>[MT.get_equip_info()]</div>"
|
||||
output += "</div>"
|
||||
return output
|
||||
|
||||
|
||||
|
||||
/obj/mecha/combat/honker/mechstep(direction)
|
||||
var/result = step(src,direction)
|
||||
if(result)
|
||||
if(!squeak)
|
||||
playsound(src, "clownstep", 70, 1)
|
||||
squeak = 1
|
||||
else
|
||||
squeak = 0
|
||||
return result
|
||||
|
||||
/obj/mecha/combat/honker/Topic(href, href_list)
|
||||
..()
|
||||
if (href_list["play_sound"])
|
||||
switch(href_list["play_sound"])
|
||||
if("sadtrombone")
|
||||
playsound(src, 'sound/misc/sadtrombone.ogg', 50)
|
||||
if("bikehorn")
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 50)
|
||||
if("airhorn2")
|
||||
playsound(src, 'sound/items/airhorn2.ogg', 40) //soundfile has higher than average volume
|
||||
if("carhorn")
|
||||
playsound(src, 'sound/items/carhorn.ogg', 80) //soundfile has lower than average volume
|
||||
if("party_horn")
|
||||
playsound(src, 'sound/items/party_horn.ogg', 50)
|
||||
return
|
||||
|
||||
/proc/rand_hex_color()
|
||||
var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f")
|
||||
var/color=""
|
||||
for (var/i=0;i<6;i++)
|
||||
color = color+pick(colors)
|
||||
return color
|
||||
@@ -1,94 +1,94 @@
|
||||
/obj/mecha/combat/marauder
|
||||
desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations."
|
||||
name = "\improper Marauder"
|
||||
icon_state = "marauder"
|
||||
step_in = 5
|
||||
max_integrity = 500
|
||||
deflect_chance = 25
|
||||
armor = list("melee" = 50, "bullet" = 55, "laser" = 40, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 60000
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
infra_luminosity = 3
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/marauder
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
force = 45
|
||||
max_equip = 4
|
||||
bumpsmash = 1
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
smoke_action.Grant(user, src)
|
||||
thrusters_action.Grant(user, src)
|
||||
zoom_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/marauder/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
smoke_action.Remove(user)
|
||||
thrusters_action.Remove(user)
|
||||
zoom_action.Remove(user)
|
||||
|
||||
/obj/mecha/combat/marauder/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/marauder/seraph
|
||||
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
|
||||
name = "\improper Seraph"
|
||||
icon_state = "seraph"
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
step_in = 3
|
||||
max_integrity = 550
|
||||
wreckage = /obj/structure/mecha_wreckage/seraph
|
||||
internal_damage_threshold = 20
|
||||
force = 55
|
||||
max_equip = 5
|
||||
|
||||
/obj/mecha/combat/marauder/seraph/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/marauder/mauler
|
||||
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
|
||||
name = "\improper Mauler"
|
||||
icon_state = "mauler"
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/mauler
|
||||
max_equip = 5
|
||||
|
||||
/obj/mecha/combat/marauder/mauler/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
|
||||
/obj/mecha/combat/marauder
|
||||
desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations."
|
||||
name = "\improper Marauder"
|
||||
icon_state = "marauder"
|
||||
step_in = 5
|
||||
max_integrity = 500
|
||||
deflect_chance = 25
|
||||
armor = list("melee" = 50, "bullet" = 55, "laser" = 40, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 60000
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
infra_luminosity = 3
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/marauder
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
force = 45
|
||||
max_equip = 4
|
||||
bumpsmash = 1
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
smoke_action.Grant(user, src)
|
||||
thrusters_action.Grant(user, src)
|
||||
zoom_action.Grant(user, src)
|
||||
|
||||
/obj/mecha/combat/marauder/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
smoke_action.Remove(user)
|
||||
thrusters_action.Remove(user)
|
||||
zoom_action.Remove(user)
|
||||
|
||||
/obj/mecha/combat/marauder/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/marauder/seraph
|
||||
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
|
||||
name = "\improper Seraph"
|
||||
icon_state = "seraph"
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
step_in = 3
|
||||
max_integrity = 550
|
||||
wreckage = /obj/structure/mecha_wreckage/seraph
|
||||
internal_damage_threshold = 20
|
||||
force = 55
|
||||
max_equip = 5
|
||||
|
||||
/obj/mecha/combat/marauder/seraph/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
/obj/mecha/combat/marauder/mauler
|
||||
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
|
||||
name = "\improper Mauler"
|
||||
icon_state = "mauler"
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/mauler
|
||||
max_equip = 5
|
||||
|
||||
/obj/mecha/combat/marauder/mauler/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/obj/mecha/combat/phazon
|
||||
desc = "This is a Phazon exosuit. The pinnacle of scientific research and pride of Nanotrasen, it uses cutting edge bluespace technology and expensive materials."
|
||||
name = "\improper Phazon"
|
||||
icon_state = "phazon"
|
||||
step_in = 2
|
||||
dir_in = 2 //Facing South.
|
||||
step_energy_drain = 3
|
||||
max_integrity = 200
|
||||
deflect_chance = 30
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 3
|
||||
wreckage = /obj/structure/mecha_wreckage/phazon
|
||||
add_req_access = 1
|
||||
internal_damage_threshold = 25
|
||||
force = 15
|
||||
max_equip = 3
|
||||
phase_state = "phazon-phase"
|
||||
|
||||
/obj/mecha/combat/phazon/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
switch_damtype_action.Grant(user, src)
|
||||
phasing_action.Grant(user, src)
|
||||
|
||||
|
||||
/obj/mecha/combat/phazon/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
switch_damtype_action.Remove(user)
|
||||
phasing_action.Remove(user)
|
||||
/obj/mecha/combat/phazon
|
||||
desc = "This is a Phazon exosuit. The pinnacle of scientific research and pride of Nanotrasen, it uses cutting edge bluespace technology and expensive materials."
|
||||
name = "\improper Phazon"
|
||||
icon_state = "phazon"
|
||||
step_in = 2
|
||||
dir_in = 2 //Facing South.
|
||||
step_energy_drain = 3
|
||||
max_integrity = 200
|
||||
deflect_chance = 30
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 3
|
||||
wreckage = /obj/structure/mecha_wreckage/phazon
|
||||
add_req_access = 1
|
||||
internal_damage_threshold = 25
|
||||
force = 15
|
||||
max_equip = 3
|
||||
phase_state = "phazon-phase"
|
||||
|
||||
/obj/mecha/combat/phazon/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
switch_damtype_action.Grant(user, src)
|
||||
phasing_action.Grant(user, src)
|
||||
|
||||
|
||||
/obj/mecha/combat/phazon/RemoveActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
switch_damtype_action.Remove(user)
|
||||
phasing_action.Remove(user)
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/obj/mecha/combat/reticence
|
||||
desc = "A silent, fast, and nigh-invisible miming exosuit. Popular among mimes and mime assassins."
|
||||
name = "\improper reticence"
|
||||
icon_state = "reticence"
|
||||
step_in = 2
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 100
|
||||
deflect_chance = 3
|
||||
armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 15000
|
||||
wreckage = /obj/structure/mecha_wreckage/reticence
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
max_equip = 2
|
||||
step_energy_drain = 3
|
||||
color = "#87878715"
|
||||
stepsound = null
|
||||
turnsound = null
|
||||
opacity = 0
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/reticence/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/rcd //HAHA IT MAKES WALLS GET IT
|
||||
ME.attach(src)
|
||||
/obj/mecha/combat/reticence
|
||||
desc = "A silent, fast, and nigh-invisible miming exosuit. Popular among mimes and mime assassins."
|
||||
name = "\improper reticence"
|
||||
icon_state = "reticence"
|
||||
step_in = 2
|
||||
dir_in = 1 //Facing North.
|
||||
max_integrity = 100
|
||||
deflect_chance = 3
|
||||
armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 15000
|
||||
wreckage = /obj/structure/mecha_wreckage/reticence
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
max_equip = 2
|
||||
step_energy_drain = 3
|
||||
color = "#87878715"
|
||||
stepsound = null
|
||||
turnsound = null
|
||||
opacity = 0
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/reticence/loaded/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/rcd //HAHA IT MAKES WALLS GET IT
|
||||
ME.attach(src)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user