Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into one-more-dojo-tweak

This commit is contained in:
Putnam
2020-01-12 17:40:26 -08:00
1386 changed files with 200260 additions and 202018 deletions
File diff suppressed because it is too large Load Diff
+30 -30
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+874 -874
View File
File diff suppressed because it is too large Load Diff
+199 -199
View File
@@ -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"
+72 -72
View File
@@ -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)
+127 -127
View File
@@ -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()
+84 -84
View File
@@ -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?"
+82 -82
View File
@@ -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()
+32 -32
View File
@@ -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")
File diff suppressed because it is too large Load Diff
+59 -59
View File
@@ -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."
+265 -265
View File
@@ -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
+141 -141
View File
@@ -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()
+303 -303
View File
@@ -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")
+21 -21
View File
@@ -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."
+82 -82
View File
@@ -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."
+99 -99
View File
@@ -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."
+73 -73
View File
@@ -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)
+48 -48
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+48 -48
View File
@@ -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)
+163 -163
View File
@@ -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
View File
@@ -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
+3 -3
View File
@@ -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
View File
@@ -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)
+148 -148
View File
@@ -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)
+77 -77
View File
@@ -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)
+89 -89
View File
@@ -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
+151 -151
View File
@@ -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
View File
@@ -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()
File diff suppressed because it is too large Load Diff
+128 -128
View File
@@ -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
+150 -150
View File
@@ -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.")
+100 -100
View File
@@ -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)
+305 -305
View File
@@ -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)
+145 -145
View File
@@ -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
+254 -254
View File
@@ -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
+209 -209
View File
@@ -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
+3 -3
View File
@@ -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)
+71 -71
View File
@@ -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
View File
@@ -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."
+165 -165
View File
@@ -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
+98 -98
View File
@@ -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
+279 -279
View File
@@ -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)
..()
+3
View File
@@ -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
+42 -42
View File
@@ -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()
+256 -256
View File
@@ -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
View File
@@ -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
+476 -461
View File
@@ -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
+91 -91
View File
@@ -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)
+13 -13
View File
@@ -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
+21 -21
View File
@@ -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
+187 -148
View File
@@ -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>&nbsp;"
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'>&nbsp;</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>&nbsp;"
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'>&nbsp;</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
View File
@@ -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
View File
@@ -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
File diff suppressed because it is too large Load Diff
+137 -137
View File
@@ -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()
+67 -67
View File
@@ -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()
+8 -8
View File
@@ -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
View File
@@ -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 += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;< \[[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 += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;< \[[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
+38 -38
View File
@@ -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
View File
@@ -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()
+236 -236
View File
@@ -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
+212 -212
View File
@@ -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
View File
@@ -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"
+135 -113
View File
@@ -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
View File
@@ -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
+368 -368
View File
@@ -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
+443 -443
View File
@@ -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()
+165 -165
View File
@@ -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
+466 -466
View File
@@ -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'>&#09;<font color='green'>\[Authenticated\]</font></a>&#09;/"
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'>&#09;<font color='red'>\[Unauthenticated\]</font></a>&#09;/"
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)
//&#09; = TAB
var/i = 0
dat += "<dd><A href='?src=[REF(src)];find=1'>&#09;[++i]. Link To A Server</a></dd>"
if(auth)
if(LINKED_SERVER_NONRESPONSIVE)
dat += "<dd><A>&#09;ERROR: Server not found!</A><br></dd>"
else
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>&#09;[++i]. View Message Logs </a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>&#09;[++i]. View Request Console Logs </a></br></dd>"
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>&#09;[++i]. Clear Message Logs</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>&#09;[++i]. Clear Request Console Logs</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];pass=1'>&#09;[++i]. Set Custom Key</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];msg=1'>&#09;[++i]. Send Admin Message</a><br></dd>"
else
for(var/n = ++i; n <= optioncount; n++)
dat += "<dd><font color='blue'>&#09;[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'>&#09;<font color='green'>\[Authenticated\]</font></a>&#09;/"
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'>&#09;<font color='red'>\[Unauthenticated\]</font></a>&#09;/"
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)
//&#09; = TAB
var/i = 0
dat += "<dd><A href='?src=[REF(src)];find=1'>&#09;[++i]. Link To A Server</a></dd>"
if(auth)
if(LINKED_SERVER_NONRESPONSIVE)
dat += "<dd><A>&#09;ERROR: Server not found!</A><br></dd>"
else
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>&#09;[++i]. View Message Logs </a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>&#09;[++i]. View Request Console Logs </a></br></dd>"
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>&#09;[++i]. Clear Message Logs</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>&#09;[++i]. Clear Request Console Logs</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];pass=1'>&#09;[++i]. Set Custom Key</a><br></dd>"
dat += "<dd><A href='?src=[REF(src)];msg=1'>&#09;[++i]. Send Admin Message</a><br></dd>"
else
for(var/n = ++i; n <= optioncount; n++)
dat += "<dd><font color='blue'>&#09;[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"
+152 -152
View File
@@ -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
+389
View File
@@ -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
+284 -284
View File
@@ -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
+43 -43
View File
@@ -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
+10 -10
View File
@@ -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)
+21 -21
View File
@@ -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)
+68 -68
View File
@@ -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
View File
@@ -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]&deg;K|[tank_temperature - T0C]&deg;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()]&deg;K|[return_temperature() - T0C]&deg;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]&deg;K|[tank_temperature - T0C]&deg;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()]&deg;K|[return_temperature() - T0C]&deg;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
+94 -94
View File
@@ -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)
+29 -29
View File
@@ -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)
+29 -29
View File
@@ -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