Merge remote-tracking branch 'citadel/master' into combat_rework_experimental
This commit is contained in:
@@ -43,6 +43,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //Eating up space doesn't count for victory as a blob.
|
||||
considered_hull_exterior = TRUE
|
||||
|
||||
/area/space/nearstation
|
||||
icon_state = "space_near"
|
||||
@@ -1592,4 +1593,4 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
/// If it's valid territory for gangs/cults to summon
|
||||
var/valid_territory = TRUE
|
||||
/// malf ais can hack this
|
||||
var/valid_malf_hack = TRUE
|
||||
/// if blobs can spawn there and if it counts towards their score.
|
||||
var/blob_allowed = TRUE
|
||||
/// whether servants can warp into this area from Reebe
|
||||
@@ -32,6 +34,9 @@
|
||||
/// If megafauna can be spawned by natural random generation
|
||||
var/megafauna_spawn_allowed = FALSE
|
||||
|
||||
/// Considered space for hull shielding
|
||||
var/considered_hull_exterior = FALSE
|
||||
|
||||
var/fire = null
|
||||
var/atmos = TRUE
|
||||
var/atmosalm = FALSE
|
||||
@@ -572,6 +577,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
power_environ = FALSE
|
||||
always_unpowered = FALSE
|
||||
valid_territory = FALSE
|
||||
valid_malf_hack = FALSE
|
||||
blob_allowed = FALSE
|
||||
addSorted()
|
||||
|
||||
|
||||
+18
-11
@@ -26,7 +26,6 @@
|
||||
var/list/atom_colours //used to store the different colors on an atom
|
||||
//its inherent color, the colored paint applied on it, special color effect etc...
|
||||
|
||||
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
|
||||
var/list/remove_overlays // a very temporary list of overlays to remove
|
||||
var/list/add_overlays // a very temporary list of overlays to add
|
||||
|
||||
@@ -145,7 +144,6 @@
|
||||
qdel(reagents)
|
||||
|
||||
LAZYCLEARLIST(overlays)
|
||||
LAZYCLEARLIST(priority_overlays)
|
||||
|
||||
for(var/i in targeted_by)
|
||||
var/mob/M = i
|
||||
@@ -962,15 +960,16 @@
|
||||
if(source != target)
|
||||
target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE)
|
||||
|
||||
/*
|
||||
Proc for attack log creation, because really why not
|
||||
1 argument is the actor performing the action
|
||||
2 argument is the target of the action
|
||||
3 is a verb describing the action (e.g. punched, throwed, kicked, etc.)
|
||||
4 is a tool with which the action was made (usually an item)
|
||||
5 is any additional text, which will be appended to the rest of the log line
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log a combat message in the attack log
|
||||
*
|
||||
* Arguments:
|
||||
* * atom/user - argument is the actor performing the action
|
||||
* * atom/target - argument is the target of the action
|
||||
* * what_done - is a verb describing the action (e.g. punched, throwed, kicked, etc.)
|
||||
* * atom/object - is a tool with which the action was made (usually an item)
|
||||
* * addition - is any additional text, which will be appended to the rest of the log line
|
||||
*/
|
||||
/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null)
|
||||
var/ssource = key_name(user)
|
||||
var/starget = key_name(target)
|
||||
@@ -1120,3 +1119,11 @@ Proc for attack log creation, because really why not
|
||||
max_grav = max(G.setting,max_grav)
|
||||
return max_grav
|
||||
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
|
||||
|
||||
/**
|
||||
* Causes effects when the atom gets hit by a rust effect from heretics
|
||||
*
|
||||
* Override this if you want custom behaviour in whatever gets hit by the rust
|
||||
*/
|
||||
/atom/proc/rust_heretic_act()
|
||||
return
|
||||
|
||||
@@ -646,3 +646,10 @@
|
||||
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
|
||||
sleep(1)
|
||||
animate(I, alpha = 0, transform = matrix(), time = 1)
|
||||
|
||||
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(anchored == anchorvalue)
|
||||
return
|
||||
. = anchored
|
||||
anchored = anchorvalue
|
||||
|
||||
@@ -213,6 +213,9 @@ Credit where due:
|
||||
var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/obj/item/clockwork/replica_fabricator/F = new
|
||||
if(H.equip_to_slot_or_del(F, SLOT_IN_BACKPACK))
|
||||
to_chat(H, "<span class='brass'>You have been equipped with a replica fabricator, an advanced tool that can convert objects like doors, tables or even coats into clockwork equivalents.</span>")
|
||||
slot = H.equip_in_one_of_slots(S, slots)
|
||||
if(slot == "In your backpack")
|
||||
slot = "In your [H.back.name]"
|
||||
@@ -221,8 +224,7 @@ Credit where due:
|
||||
qdel(S)
|
||||
if(S && !QDELETED(S))
|
||||
to_chat(L, "<span class='alloy'>[slot] is a <b>clockwork slab</b>, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
|
||||
as a servant, you can find a concise tutorial in the Recollection category of its interface.</span>")
|
||||
to_chat(L, "<span class='alloy italics'>If you want more information, you can read <a href=\"https://tgstation13.org/wiki/Clockwork_Cult\">the wiki page</a> to learn more.</span>")
|
||||
as a servant, you can read <a href=\"https://citadel-station.net/wikimain/index.php?title=Clockwork_Cult\">the wiki page</a> to learn more.</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
hitsound = null
|
||||
attack_verb_on = list("slipped")
|
||||
clumsy_check = FALSE
|
||||
sharpness = IS_BLUNT
|
||||
sharpness = SHARP_NONE
|
||||
sword_color = "yellow"
|
||||
heat = 0
|
||||
light_color = "#ffff00"
|
||||
|
||||
@@ -6,10 +6,6 @@ GLOBAL_VAR_INIT(dynamic_latejoin_delay_max, (30 MINUTES))
|
||||
GLOBAL_VAR_INIT(dynamic_midround_delay_min, (10 MINUTES))
|
||||
GLOBAL_VAR_INIT(dynamic_midround_delay_max, (30 MINUTES))
|
||||
|
||||
GLOBAL_VAR_INIT(dynamic_event_delay_min, (10 MINUTES))
|
||||
GLOBAL_VAR_INIT(dynamic_event_delay_max, (30 MINUTES)) // this is on top of regular events, so can't be quite as often
|
||||
|
||||
|
||||
// -- Roundstart injection delays
|
||||
GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_min, (2 MINUTES))
|
||||
GLOBAL_VAR_INIT(dynamic_first_latejoin_delay_max, (30 MINUTES))
|
||||
@@ -58,7 +54,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
// Threat logging vars
|
||||
/// Starting threat level, for things that increase it but can bring it back down.
|
||||
var/initial_threat_level = 0
|
||||
/// Target threat level right now. Events and antags will try to keep the round at this level.
|
||||
/// Target threat level right now. Antags will try to keep the round at this level.
|
||||
var/threat_level = 0
|
||||
/// The current antag threat. Recalculated every time a ruletype starts or ends.
|
||||
var/threat = 0
|
||||
@@ -80,8 +76,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/list/latejoin_rules = list()
|
||||
/// List of midround rules used for selecting the rules.
|
||||
var/list/midround_rules = list()
|
||||
/// List of events used for reducing threat without causing antag injection (necessarily).
|
||||
var/list/events = list()
|
||||
/** # Pop range per requirement.
|
||||
* If the value is five the range is:
|
||||
* 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+
|
||||
@@ -119,8 +113,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/latejoin_injection_cooldown = 0
|
||||
/// When world.time is over this number the mode tries to inject a midround ruleset.
|
||||
var/midround_injection_cooldown = 0
|
||||
/// When wor.dtime is over this number the mode tries to do an event.
|
||||
var/event_injection_cooldown = 0
|
||||
/// When TRUE GetInjectionChance returns 100.
|
||||
var/forced_injection = FALSE
|
||||
/// Forced ruleset to be executed for the next latejoin.
|
||||
@@ -184,7 +176,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
dat += "<br>Injection Timers: (<b>[storyteller.get_injection_chance(TRUE)]%</b> chance)<BR>"
|
||||
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
|
||||
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
|
||||
dat += "Event: [(event_injection_cooldown-world.time)>60*10 ? "[round((event_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(event_injection_cooldown-world.time)/10] seconds"] <a href='?src=\ref[src];[HrefToken()];forceevent=1'>\[Now!\]</a><BR>"
|
||||
usr << browse(dat.Join(), "window=gamemode_panel;size=500x500")
|
||||
|
||||
/datum/game_mode/dynamic/Topic(href, href_list)
|
||||
@@ -204,10 +195,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/threatadd = input("Specify how much threat to add (negative to subtract). This can inflate the threat level.", "Adjust Threat", 0) as null|num
|
||||
if(!threatadd)
|
||||
return
|
||||
if(threatadd > 0)
|
||||
create_threat(threatadd)
|
||||
else
|
||||
remove_threat(threatadd)
|
||||
create_threat(threatadd)
|
||||
else if (href_list["injectlate"])
|
||||
latejoin_injection_cooldown = 0
|
||||
forced_injection = TRUE
|
||||
@@ -216,10 +204,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
midround_injection_cooldown = 0
|
||||
forced_injection = TRUE
|
||||
message_admins("[key_name(usr)] forced a midround injection.", 1)
|
||||
else if (href_list["forceevent"])
|
||||
event_injection_cooldown = 0
|
||||
// events always happen anyway
|
||||
message_admins("[key_name(usr)] forced an event.", 1)
|
||||
else if (href_list["threatlog"])
|
||||
show_threatlog(usr)
|
||||
else if (href_list["stacking_limit"])
|
||||
@@ -377,8 +361,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
generate_threat()
|
||||
|
||||
storyteller.start_injection_cooldowns()
|
||||
SSevents.frequency_lower = storyteller.event_frequency_lower // 6 minutes by default
|
||||
SSevents.frequency_upper = storyteller.event_frequency_upper // 20 minutes by default
|
||||
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
|
||||
initial_threat_level = threat_level
|
||||
return TRUE
|
||||
@@ -397,9 +379,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
if ("Midround")
|
||||
if (ruleset.weight)
|
||||
midround_rules += ruleset
|
||||
if("Event")
|
||||
if(ruleset.weight)
|
||||
events += ruleset
|
||||
for(var/mob/dead/new_player/player in GLOB.player_list)
|
||||
if(player.ready == PLAYER_READY_TO_PLAY && player.mind)
|
||||
roundstart_pop_ready++
|
||||
@@ -596,8 +575,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
latejoin_rules = remove_from_list(latejoin_rules, rule.type)
|
||||
else if(rule.ruletype == "Midround")
|
||||
midround_rules = remove_from_list(midround_rules, rule.type)
|
||||
else if(rule.ruletype == "Event")
|
||||
events = remove_from_list(events,rule.type)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_midround_latejoin_rule, rule), rule.delay)
|
||||
return TRUE
|
||||
|
||||
@@ -706,17 +683,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
picking_midround_latejoin_rule(drafted_rules)
|
||||
// get_injection_chance can do things on fail
|
||||
|
||||
if(event_injection_cooldown < world.time)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Attempted event injections")
|
||||
event_injection_cooldown = storyteller.get_event_cooldown() + world.time
|
||||
message_admins("DYNAMIC: Doing event injection.")
|
||||
log_game("DYNAMIC: Doing event injection.")
|
||||
update_playercounts()
|
||||
var/list/drafted_rules = storyteller.event_draft()
|
||||
if(drafted_rules.len > 0)
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Successful event injections")
|
||||
picking_midround_latejoin_rule(drafted_rules)
|
||||
|
||||
/// Updates current_players.
|
||||
/datum/game_mode/dynamic/proc/update_playercounts()
|
||||
current_players[CURRENT_LIVING_PLAYERS] = list()
|
||||
|
||||
@@ -1,454 +0,0 @@
|
||||
/datum/dynamic_ruleset/event
|
||||
ruletype = "Event"
|
||||
var/typepath // typepath of the event
|
||||
var/triggering
|
||||
var/earliest_start = 20 MINUTES
|
||||
|
||||
/datum/dynamic_ruleset/event/get_blackbox_info()
|
||||
var/list/ruleset_data = list()
|
||||
ruleset_data["name"] = name
|
||||
ruleset_data["rule_type"] = ruletype
|
||||
ruleset_data["cost"] = total_cost
|
||||
ruleset_data["weight"] = weight
|
||||
ruleset_data["scaled_times"] = scaled_times
|
||||
ruleset_data["event_type"] = typepath
|
||||
ruleset_data["population_tier"] = indice_pop
|
||||
return ruleset_data
|
||||
|
||||
/datum/dynamic_ruleset/event/execute()
|
||||
var/datum/round_event/E = new typepath()
|
||||
E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
|
||||
// E.control = src // can't be done! we just don't use events that require these, those can be from_ghost almost always
|
||||
|
||||
testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
|
||||
deadchat_broadcast("<span class='deadsay'><b>[name]</b> has just been triggered by dynamic!</span>")
|
||||
log_game("Random Event triggering: [name] ([typepath])")
|
||||
|
||||
return E
|
||||
|
||||
/datum/dynamic_ruleset/event/ready(forced = FALSE)
|
||||
if (!forced)
|
||||
if(earliest_start >= world.time-SSticker.round_start_time)
|
||||
return FALSE
|
||||
var/job_check = 0
|
||||
if (enemy_roles.len > 0)
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
if (M.stat == DEAD)
|
||||
continue // Dead players cannot count as opponents
|
||||
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles))
|
||||
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
|
||||
|
||||
var/threat = round(mode.threat_level/10)
|
||||
if (job_check < required_enemies[threat])
|
||||
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// PIRATES //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/pirates
|
||||
name = "Space Pirates"
|
||||
config_tag = "pirates"
|
||||
typepath = /datum/round_event/pirates
|
||||
antag_flag = ROLE_TRAITOR
|
||||
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
|
||||
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
|
||||
weight = 5
|
||||
cost = 10
|
||||
earliest_start = 30 MINUTES
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
|
||||
requirements = list(70,60,50,50,40,40,40,30,20,15)
|
||||
property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1)
|
||||
high_population_requirement = 15
|
||||
|
||||
/datum/dynamic_ruleset/event/pirates/ready(forced = FALSE)
|
||||
if (!SSmapping.empty_space)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// SPIDERS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/spiders
|
||||
name = "Spider Infestation"
|
||||
config_tag = "spiders"
|
||||
typepath = /datum/round_event/spider_infestation
|
||||
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
|
||||
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
|
||||
weight = 5
|
||||
cost = 10
|
||||
requirements = list(70,60,50,50,40,40,40,30,20,15)
|
||||
high_population_requirement = 15
|
||||
property_weights = list("chaos" = 1, "valid" = 1)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// CLOGGED VENTS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/ventclog
|
||||
name = "Clogged Vents"
|
||||
config_tag = "ventclog"
|
||||
typepath = /datum/round_event/vent_clog
|
||||
enemy_roles = list("Chemist","Medical Doctor","Chief Medical Officer")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
cost = 2
|
||||
weight = 4
|
||||
repeatable_weight_decrease = 3
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5) // yes, can happen on fake-extended
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("chaos" = 1, "extended" = 2)
|
||||
|
||||
/datum/dynamic_ruleset/event/ventclog/ready()
|
||||
if(mode.threat_level > 30 && mode.threat >= 5 && prob(20))
|
||||
name = "Clogged Vents: Threatening"
|
||||
cost = 5
|
||||
required_enemies = list(3,3,3,2,2,2,1,1,1,1)
|
||||
typepath = /datum/round_event/vent_clog/threatening
|
||||
else if(mode.threat_level > 15 && mode.threat > 15 && prob(30))
|
||||
name = "Clogged Vents: Catastrophic"
|
||||
cost = 15
|
||||
required_enemies = list(2,2,1,1,1,1,0,0,0,0)
|
||||
typepath = /datum/round_event/vent_clog/catastrophic
|
||||
else
|
||||
cost = 2
|
||||
name = "Clogged Vents: Normal"
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
typepath = /datum/round_event/vent_clog
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// ION STORM //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/ion_storm
|
||||
name = "Ion Storm"
|
||||
config_tag = "ion_storm"
|
||||
typepath = /datum/round_event/ion_storm
|
||||
enemy_roles = list("Research Director","Captain","Chief Engineer")
|
||||
required_enemies = list(1,1,0,0,0,0,0,0,0,0)
|
||||
weight = 4
|
||||
// no repeatable weight decrease. too variable to be unfun multiple times in one round
|
||||
cost = 1
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("story_potential" = 1, "extended" = 1)
|
||||
always_max_weight = TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// METEORS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/meteor_wave
|
||||
name = "Meteor Wave"
|
||||
config_tag = "meteor_wave"
|
||||
typepath = /datum/round_event/meteor_wave
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Captain","Cyborg")
|
||||
required_enemies = list(3,3,3,3,3,3,3,3,3,3)
|
||||
cost = 15
|
||||
weight = 3
|
||||
earliest_start = 25 MINUTES
|
||||
repeatable_weight_decrease = 2
|
||||
requirements = list(60,50,40,30,30,30,30,30,30,30)
|
||||
high_population_requirement = 30
|
||||
property_weights = list("extended" = -2)
|
||||
|
||||
/datum/dynamic_ruleset/event/meteor_wave/ready()
|
||||
if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30))
|
||||
name = "Meteor Wave: Threatening"
|
||||
cost = 25
|
||||
typepath = /datum/round_event/meteor_wave/threatening
|
||||
else if(world.time-SSticker.round_start_time > 45 MINUTES && mode.threat_level > 50 && mode.threat >= 40 && prob(30))
|
||||
name = "Meteor Wave: Catastrophic"
|
||||
cost = 40
|
||||
typepath = /datum/round_event/meteor_wave/catastrophic
|
||||
else
|
||||
name = "Meteor Wave: Normal"
|
||||
cost = 15
|
||||
typepath = /datum/round_event/meteor_wave
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// ANOMALIES //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/anomaly_bluespace
|
||||
name = "Anomaly: Bluespace"
|
||||
config_tag = "anomaly_bluespace"
|
||||
typepath = /datum/round_event/anomaly/anomaly_bluespace
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 3
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/anomaly_flux
|
||||
name = "Anomaly: Hyper-Energetic Flux"
|
||||
config_tag = "anomaly_flux"
|
||||
typepath = /datum/round_event/anomaly/anomaly_flux
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 5
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 10
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/anomaly_gravitational
|
||||
name = "Anomaly: Gravitational"
|
||||
config_tag = "anomaly_gravitational"
|
||||
typepath = /datum/round_event/anomaly/anomaly_grav
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 3
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/anomaly_pyroclastic
|
||||
name = "Anomaly: Pyroclastic"
|
||||
config_tag = "anomaly_pyroclastic"
|
||||
typepath = /datum/round_event/anomaly/anomaly_pyro
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 5
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
|
||||
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/anomaly_vortex
|
||||
name = "Anomaly: Vortex"
|
||||
config_tag = "anomaly_vortex"
|
||||
typepath = /datum/round_event/anomaly/anomaly_vortex
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 5
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
|
||||
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// WOW THAT'S A LOT OF EVENTS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/event/brand_intelligence
|
||||
name = "Brand Intelligence"
|
||||
config_tag = "brand_intelligence"
|
||||
typepath = /datum/round_event/brand_intelligence
|
||||
weight = 1
|
||||
repeatable_weight_decrease = 1
|
||||
cost = 2
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
|
||||
required_enemies = list(1,1,1,1,0,0,0,0,0,0)
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = -1, "chaos" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/carp_migration
|
||||
name = "Carp Migration"
|
||||
config_tag = "carp_migration"
|
||||
typepath = /datum/round_event/carp_migration
|
||||
weight = 7
|
||||
repeatable_weight_decrease = 3
|
||||
cost = 4
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
earliest_start = 10 MINUTES
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/communications_blackout
|
||||
name = "Communications Blackout"
|
||||
config_tag = "communications_blackout"
|
||||
typepath = /datum/round_event/communications_blackout
|
||||
cost = 4
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 3
|
||||
enemy_roles = list("Chief Engineer","Station Engineer")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1, "chaos" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/processor_overload
|
||||
name = "Processor Overload"
|
||||
config_tag = "processor_overload"
|
||||
typepath = /datum/round_event/processor_overload
|
||||
cost = 4
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 3
|
||||
enemy_roles = list("Chief Engineer","Station Engineer")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1, "chaos" = 1)
|
||||
always_max_weight = TRUE
|
||||
|
||||
/datum/dynamic_ruleset/event/space_dust
|
||||
name = "Minor Space Dust"
|
||||
config_tag = "space_dust"
|
||||
typepath = /datum/round_event/space_dust
|
||||
cost = 2
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
enemy_roles = list("Chief Engineer","Station Engineer")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
earliest_start = 0 MINUTES
|
||||
property_weights = list("extended" = 1)
|
||||
always_max_weight = TRUE
|
||||
|
||||
/datum/dynamic_ruleset/event/major_dust
|
||||
name = "Major Space Dust"
|
||||
config_tag = "major_dust"
|
||||
typepath = /datum/round_event/meteor_wave/major_dust
|
||||
cost = 4
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
enemy_roles = list("Chief Engineer","Station Engineer")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/electrical_storm
|
||||
name = "Electrical Storm"
|
||||
config_tag = "electrical_storm"
|
||||
typepath = /datum/round_event/electrical_storm
|
||||
cost = 1
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
enemy_roles = list("Chief Engineer","Station Engineer")
|
||||
required_enemies = list(1,1,1,0,0,0,0,0,0,0)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/heart_attack
|
||||
name = "Random Heart Attack"
|
||||
config_tag = "heart_attack"
|
||||
typepath = /datum/round_event/heart_attack
|
||||
cost = 3
|
||||
weight = 2
|
||||
repeatable_weight_decrease = 1
|
||||
enemy_roles = list("Medical Doctor","Chief Medical Officer")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(101,101,101,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
always_max_weight = TRUE
|
||||
|
||||
/datum/dynamic_ruleset/event/radiation_storm
|
||||
name = "Radiation Storm"
|
||||
config_tag = "radiation_storm"
|
||||
typepath = /datum/round_event/radiation_storm
|
||||
cost = 3
|
||||
weight = 1
|
||||
enemy_roles = list("Chemist","Chief Medical Officer","Geneticist","Medical Doctor","AI","Captain")
|
||||
required_enemies = list(1,1,1,1,1,1,1,1,1,1)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = 1,"chaos" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/portal_storm_syndicate
|
||||
name = "Portal Storm"
|
||||
config_tag = "portal_storm"
|
||||
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
|
||||
cost = 10
|
||||
weight = 1
|
||||
enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(101,101,101,30,30,30,30,30,30,30)
|
||||
high_population_requirement = 30
|
||||
earliest_start = 30 MINUTES
|
||||
property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1)
|
||||
|
||||
/datum/dynamic_ruleset/event/wormholes
|
||||
name = "Wormholes"
|
||||
config_tag = "wormhole"
|
||||
typepath = /datum/round_event/wormholes
|
||||
cost = 3
|
||||
weight = 4
|
||||
enemy_roles = list("AI","Medical Doctor","Station Engineer","Head of Personnel","Captain")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/swarmers
|
||||
name = "Swarmers"
|
||||
config_tag = "swarmer"
|
||||
typepath = /datum/round_event/spawn_swarmer
|
||||
cost = 10
|
||||
weight = 1
|
||||
earliest_start = 30 MINUTES
|
||||
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer")
|
||||
required_enemies = list(4,4,4,4,3,3,2,2,1,1)
|
||||
requirements = list(101,101,101,101,101,101,101,101,101,101)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = -2)
|
||||
|
||||
/datum/dynamic_ruleset/event/sentient_disease
|
||||
name = "Sentient Disease"
|
||||
config_tag = "sentient_disease"
|
||||
typepath = /datum/round_event/ghost_role/sentient_disease
|
||||
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
|
||||
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
|
||||
high_population_requirement = 5
|
||||
|
||||
/datum/dynamic_ruleset/event/revenant
|
||||
name = "Revenant"
|
||||
config_tag = "revenant"
|
||||
typepath = /datum/round_event/ghost_role/revenant
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,30,30,20,15,15,15,15,15)
|
||||
high_population_requirement = 15
|
||||
property_weights = list("story_potential" = -2, "extended" = -1)
|
||||
@@ -191,6 +191,26 @@
|
||||
SSticker.mode_result = "loss - rev heads killed"
|
||||
SSticker.news_report = REVS_LOSE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// HERETIC SMUGGLER //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/latejoin/heretic_smuggler
|
||||
name = "Heretic Smuggler"
|
||||
antag_datum = /datum/antagonist/heretic
|
||||
antag_flag = "latejoin_heretic"
|
||||
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
restricted_roles = list("AI","Cyborg")
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 25
|
||||
requirements = list(60,60,60,55,50,50,50,50,50,50)
|
||||
high_population_requirement = 50
|
||||
property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2)
|
||||
repeatable = TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// BLOODSUCKERS //
|
||||
|
||||
@@ -538,7 +538,7 @@
|
||||
name = "Slaughter Demon"
|
||||
config_tag = "slaughter_demon"
|
||||
antag_flag = ROLE_ALIEN
|
||||
enemy_roles = list("Security Officer","Shaft Miner","Head of Security","Captain","Janitor","AI","Cyborg")
|
||||
enemy_roles = list("Security Officer","Shaft Miner","Head of Security","Captain","Janitor","AI","Cyborg","Bartender")
|
||||
required_enemies = list(3,2,2,2,2,1,1,1,1,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
|
||||
@@ -143,6 +143,48 @@
|
||||
changeling.add_antag_datum(new_antag)
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// ELDRITCH CULT //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/heretics
|
||||
name = "Heretics"
|
||||
antag_flag = "heretic"
|
||||
antag_datum = /datum/antagonist/heretic
|
||||
protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain")
|
||||
restricted_roles = list("AI", "Cyborg")
|
||||
required_candidates = 1
|
||||
weight = 3
|
||||
cost = 25
|
||||
scaling_cost = 15
|
||||
requirements = list(60,60,60,55,50,50,50,50,50,50)
|
||||
property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2)
|
||||
antag_cap = list(1,1,1,1,2,2,2,2,3,3)
|
||||
high_population_requirement = 50
|
||||
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/heretics/pre_execute()
|
||||
. = ..()
|
||||
var/num_ecult = antag_cap[indice_pop] * (scaled_times + 1)
|
||||
|
||||
for (var/i = 1 to num_ecult)
|
||||
var/mob/picked_candidate = pick_n_take(candidates)
|
||||
assigned += picked_candidate.mind
|
||||
picked_candidate.mind.restricted_roles = restricted_roles
|
||||
picked_candidate.mind.special_role = ROLE_HERETIC
|
||||
return TRUE
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/heretics/execute()
|
||||
|
||||
for(var/c in assigned)
|
||||
var/datum/mind/cultie = c
|
||||
var/datum/antagonist/heretic/new_antag = new antag_datum()
|
||||
cultie.add_antag_datum(new_antag)
|
||||
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// WIZARDS //
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
|
||||
|
||||
/**
|
||||
Property weights are:
|
||||
Property weights are added to the config weight of the ruleset. They are:
|
||||
"story_potential" -- essentially how many different ways the antag can be played.
|
||||
"trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this.
|
||||
"chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended".
|
||||
"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to
|
||||
let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights.
|
||||
"extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on.
|
||||
"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason.
|
||||
"conversion" -- Basically a bool. Conversion antags, well, convert. It's in its own class 'cause people kinda hate conversion.
|
||||
*/
|
||||
|
||||
/datum/dynamic_storyteller/proc/start_injection_cooldowns()
|
||||
@@ -39,9 +39,6 @@ Property weights are:
|
||||
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
|
||||
mode.midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
|
||||
|
||||
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
|
||||
mode.event_injection_cooldown = (round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
|
||||
|
||||
/datum/dynamic_storyteller/proc/calculate_threat()
|
||||
var/threat = 0
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
@@ -50,10 +47,6 @@ Property weights are:
|
||||
for(var/r in SSevents.running)
|
||||
var/datum/round_event/R = r
|
||||
threat += R.threat()
|
||||
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
|
||||
var/turf/T = get_turf(H)
|
||||
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
|
||||
threat += H.threat()
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list)
|
||||
threat += 25 // can't be giving them too much of a break
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
@@ -91,6 +84,8 @@ Property weights are:
|
||||
mean += 2.5
|
||||
if(CHAOS_MAX)
|
||||
mean += 5
|
||||
else
|
||||
voters += 0.5
|
||||
if(voters)
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
if(flags & USE_PREV_ROUND_WEIGHTS)
|
||||
@@ -101,10 +96,6 @@ Property weights are:
|
||||
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
|
||||
return round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max))
|
||||
|
||||
/datum/dynamic_storyteller/proc/get_event_cooldown()
|
||||
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
|
||||
return round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max))
|
||||
|
||||
/datum/dynamic_storyteller/proc/get_latejoin_cooldown()
|
||||
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min)
|
||||
return round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max))
|
||||
@@ -128,7 +119,9 @@ Property weights are:
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
|
||||
var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult
|
||||
if(calced_weight > 0) // negatives in the list might cause problems
|
||||
drafted_rules[rule] = calced_weight
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/midround_draft()
|
||||
@@ -140,25 +133,29 @@ Property weights are:
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
rule.trim_candidates()
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
|
||||
pick this particular ruleset.
|
||||
Let's use a toy example: there's 60 threat level and 10 threat spent.
|
||||
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
|
||||
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
|
||||
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
|
||||
is 2.26 times as likely to be picked, all other things considered.
|
||||
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
|
||||
*/
|
||||
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
|
||||
var/cost_difference = rule.cost-(mode.threat_level-mode.threat)
|
||||
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
|
||||
pick this particular ruleset.
|
||||
Let's use a toy example: there's 60 threat level and 10 threat spent.
|
||||
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
|
||||
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
|
||||
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
|
||||
is 2.26 times as likely to be picked, all other things considered.
|
||||
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
|
||||
*/
|
||||
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,abs(cost_difference),0)))
|
||||
if(cost_difference > 0)
|
||||
threat_weight /= (1+(cost_difference*0.1))
|
||||
var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult * threat_weight
|
||||
if(calced_weight > 0)
|
||||
drafted_rules[rule] = calced_weight
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
|
||||
@@ -175,31 +172,22 @@ Property weights are:
|
||||
|
||||
rule.candidates = list(newPlayer)
|
||||
rule.trim_candidates()
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & MINOR_RULESET))
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))
|
||||
var/cost_difference = rule.cost-(mode.threat_level-mode.threat)
|
||||
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,abs(cost_difference),0)))
|
||||
if(cost_difference > 0)
|
||||
threat_weight /= (1+(cost_difference*0.1))
|
||||
var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult * threat_weight
|
||||
if(calced_weight > 0)
|
||||
drafted_rules[rule] = calced_weight
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
|
||||
if(rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
return drafted_rules
|
||||
|
||||
|
||||
/datum/dynamic_storyteller/chaotic
|
||||
name = "Chaotic"
|
||||
config_tag = "chaotic"
|
||||
@@ -262,9 +250,6 @@ Property weights are:
|
||||
/datum/dynamic_storyteller/random/get_midround_cooldown()
|
||||
return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2)
|
||||
|
||||
/datum/dynamic_storyteller/random/get_event_cooldown()
|
||||
return rand(GLOB.dynamic_event_delay_min/2, GLOB.dynamic_event_delay_max*2)
|
||||
|
||||
/datum/dynamic_storyteller/random/get_latejoin_cooldown()
|
||||
return rand(GLOB.dynamic_latejoin_delay_min/2, GLOB.dynamic_latejoin_delay_max*2)
|
||||
|
||||
@@ -310,14 +295,6 @@ Property weights are:
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/random/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
if(rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/story
|
||||
name = "Story"
|
||||
config_tag = "story"
|
||||
@@ -327,12 +304,6 @@ Property weights are:
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("story_potential" = 2)
|
||||
|
||||
|
||||
/datum/dynamic_storyteller/story/calculate_threat()
|
||||
var/current_time = (world.time / SSautotransfer.targettime)*180
|
||||
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_storyteller/classic
|
||||
name = "Classic"
|
||||
config_tag = "classic"
|
||||
@@ -363,7 +334,7 @@ Property weights are:
|
||||
/datum/dynamic_storyteller/no_antag
|
||||
name = "Extended"
|
||||
config_tag = "semiextended"
|
||||
desc = "No standard antags. Threatening events may still spawn."
|
||||
desc = "No standard antags."
|
||||
curve_centre = -5
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN | FORCE_IF_WON
|
||||
@@ -375,15 +346,3 @@ Property weights are:
|
||||
|
||||
/datum/dynamic_storyteller/no_antag/get_injection_chance(dry_run)
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/extended
|
||||
name = "Super Extended"
|
||||
config_tag = "extended"
|
||||
desc = "No antags. No dangerous events."
|
||||
curve_centre = -20
|
||||
weight = 0
|
||||
curve_width = 0.5
|
||||
|
||||
/datum/dynamic_storyteller/extended/on_start()
|
||||
..()
|
||||
GLOB.dynamic_forced_extended = TRUE
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/datum/game_mode/heretics
|
||||
name = "heresy"
|
||||
config_tag = "heresy"
|
||||
antag_flag = ROLE_HERETIC
|
||||
false_report_weight = 5
|
||||
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 heretic role blacklist
|
||||
required_players = 15
|
||||
required_enemies = 1
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = 1
|
||||
enemy_minimum_age = 0
|
||||
round_ends_with_antag_death = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "Heretics have been spotted on the station!\n\
|
||||
<span class='danger'>Heretics</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the madman succeed!"
|
||||
|
||||
var/ecult_possible = 4 //hard limit on culties if scaling is turned off
|
||||
var/num_ecult = 1
|
||||
var/list/culties = list()
|
||||
|
||||
/datum/game_mode/heretics/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/esc = CONFIG_GET(number/ecult_scaling_coeff)
|
||||
if(esc)
|
||||
num_ecult = min(max(1, min(round(num_players() / (esc * 2)) + 2, round(num_players() / esc))),4)
|
||||
else
|
||||
num_ecult = max(1, min(num_players(), ecult_possible))
|
||||
|
||||
for(var/i in 1 to num_ecult)
|
||||
if(!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/cultie = antag_pick(antag_candidates)
|
||||
antag_candidates -= cultie
|
||||
cultie.special_role = ROLE_HERETIC
|
||||
cultie.restricted_roles = restricted_jobs
|
||||
culties += cultie
|
||||
|
||||
var/enough_heretics = culties.len > 0
|
||||
|
||||
if(!enough_heretics)
|
||||
setup_error = "Not enough heretic candidates"
|
||||
return FALSE
|
||||
else
|
||||
for(var/antag in culties)
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/heretics/post_setup()
|
||||
for(var/c in culties)
|
||||
var/datum/mind/cultie = c
|
||||
log_game("[key_name(cultie)] has been selected as a heretic!")
|
||||
var/datum/antagonist/heretic/new_antag = new()
|
||||
cultie.add_antag_datum(new_antag)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/heretics/generate_report()
|
||||
return "Cybersun Industries has announced that they have successfully raided a high-security library. The library contained a very dangerous book that was \
|
||||
shown to posses anomalous properties. We suspect that the book has been copied over, Stay vigilant!"
|
||||
@@ -112,7 +112,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/turf/T = get_turf(loc)
|
||||
ram_turf(T)
|
||||
|
||||
if(prob(10) && !isspaceturf(T))//randomly takes a 'hit' from ramming
|
||||
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming
|
||||
get_hit()
|
||||
|
||||
/obj/effect/meteor/Destroy()
|
||||
@@ -136,7 +136,8 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
if(A)
|
||||
ram_turf(get_turf(A))
|
||||
playsound(src.loc, meteorsound, 40, 1)
|
||||
get_hit()
|
||||
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid))
|
||||
get_hit()
|
||||
|
||||
/obj/effect/meteor/proc/ram_turf(turf/T)
|
||||
//first bust whatever is in the turf
|
||||
|
||||
+58
-174
@@ -12,9 +12,9 @@
|
||||
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/min_health = -25
|
||||
var/list/available_chems
|
||||
var/controls_inside = FALSE
|
||||
var/list/possible_chems = list(
|
||||
@@ -31,32 +31,13 @@
|
||||
|
||||
/obj/machinery/sleeper/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500, NO_REACT)
|
||||
// if(mapload)
|
||||
// component_parts -= circuit
|
||||
// QDEL_NULL(circuit)
|
||||
occupant_typecache = GLOB.typecache_living
|
||||
update_icon()
|
||||
reset_chem_buttons()
|
||||
RefreshParts()
|
||||
add_inital_chems()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/sleeper/setDir(newdir)
|
||||
. = ..()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/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
|
||||
@@ -73,15 +54,11 @@
|
||||
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_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(state_open)
|
||||
icon_state += "-open"
|
||||
icon_state = "[initial(icon_state)]-open"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/machinery/sleeper/container_resist(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
@@ -98,10 +75,12 @@
|
||||
|
||||
/obj/machinery/sleeper/open_machine()
|
||||
if(!state_open && !panel_open)
|
||||
// flick("[initial(icon_state)]-anim", src)
|
||||
..()
|
||||
|
||||
/obj/machinery/sleeper/close_machine(mob/user)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
// flick("[initial(icon_state)]-anim", src)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
@@ -112,46 +91,23 @@
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(is_operational() && occupant)
|
||||
var/datum/reagent/R = pick(reagents.reagent_list)
|
||||
var/datum/reagent/R = pick(reagents.reagent_list) //cit specific
|
||||
inject_chem(R.type, occupant)
|
||||
open_machine()
|
||||
//Is this too much?
|
||||
//Is this too much? Cit specific
|
||||
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())
|
||||
if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(!(L.mobility_flags & MOBILITY_STAND))
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
|
||||
@@ -187,31 +143,29 @@
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/ui_state(mob/user)
|
||||
if(controls_inside)
|
||||
return GLOB.contained_state
|
||||
return GLOB.default_state
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Sleeper", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(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/process()
|
||||
..()
|
||||
check_nap_violations()
|
||||
@@ -221,22 +175,13 @@
|
||||
|
||||
/obj/machinery/sleeper/ui_data()
|
||||
var/list/data = list()
|
||||
var/chemical_list = list()
|
||||
var/blood_percent = 0
|
||||
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["blood_levels"] = blood_percent
|
||||
data["blood_status"] = "Patient either has no blood, or does not require it to function."
|
||||
data["chemical_list"] = chemical_list
|
||||
|
||||
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)))
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[chem]
|
||||
data["chems"] += list(list("name" = R.name, "id" = R.type, "allowed" = chem_allowed(chem)))
|
||||
|
||||
data["occupant"] = list()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
@@ -264,40 +209,10 @@
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
|
||||
if(mob_occupant.reagents.reagent_list.len)
|
||||
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)
|
||||
chemical_list += list(list("name" = R.name, "volume" = R.volume))
|
||||
else
|
||||
chemical_list = "Patient has no reagents."
|
||||
|
||||
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(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks
|
||||
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
|
||||
blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
|
||||
var/blood_id = C.get_blood_id()
|
||||
var/blood_warning = ""
|
||||
if(blood_percent < 80)
|
||||
blood_warning = "Patient has low blood levels."
|
||||
if(blood_percent < 60)
|
||||
blood_warning = "Patient has DANGEROUSLY low blood levels."
|
||||
if(blood_id)
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(!(blood_id in GLOB.blood_reagent_types)) // 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["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]"
|
||||
data["blood_levels"] = blood_percent
|
||||
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/ui_act(action, params)
|
||||
@@ -314,37 +229,14 @@
|
||||
. = 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))
|
||||
if(inject_chem(chem, usr))
|
||||
. = 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, 1000)
|
||||
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, 1000)
|
||||
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)
|
||||
. = ..()
|
||||
@@ -353,10 +245,9 @@
|
||||
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
|
||||
/obj/machinery/sleeper/proc/inject_chem(chem, mob/user)
|
||||
if((chem in available_chems) && chem_allowed(chem))
|
||||
occupant.reagents.add_reagent(chem_buttons[chem], 10) //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
|
||||
@@ -369,14 +260,6 @@
|
||||
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)
|
||||
@@ -416,23 +299,6 @@
|
||||
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(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine,
|
||||
/datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/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"
|
||||
|
||||
@@ -443,8 +309,6 @@
|
||||
idle_power_usage = 3000
|
||||
circuit = /obj/item/circuitboard/machine/sleeper/party
|
||||
var/leddit = FALSE //Get it like reddit and lead alright fine
|
||||
ui_x = 310
|
||||
ui_y = 400
|
||||
|
||||
controls_inside = TRUE
|
||||
possible_chems = list(
|
||||
@@ -477,3 +341,23 @@
|
||||
/obj/machinery/sleeper/party/emag_act(mob/user)
|
||||
..()
|
||||
leddit = TRUE
|
||||
|
||||
/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(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol)
|
||||
) //everything is available at start
|
||||
fair_market_price = 0 //it's free
|
||||
|
||||
/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)
|
||||
|
||||
@@ -92,6 +92,7 @@ Class Procs:
|
||||
pressure_resistance = 15
|
||||
max_integrity = 200
|
||||
layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it.
|
||||
flags_1 = DEFAULT_RICOCHET_1
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
ricochet_chance_mod = 0.3
|
||||
|
||||
@@ -116,6 +117,7 @@ Class Procs:
|
||||
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
|
||||
var/speed_process = FALSE // Process as fast as possible?
|
||||
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
|
||||
var/wire_compatible = FALSE
|
||||
// For storing and overriding ui id and dimensions
|
||||
var/tgui_id // ID of TGUI interface
|
||||
var/ui_style // ID of custom TGUI style (optional)
|
||||
@@ -432,6 +434,7 @@ Class Procs:
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
setAnchored(!anchored)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
|
||||
return SUCCESSFUL_UNFASTEN
|
||||
return FAILED_UNFASTEN
|
||||
return CANT_UNFASTEN
|
||||
@@ -546,3 +549,6 @@ Class Procs:
|
||||
. = . % 9
|
||||
AM.pixel_x = -8 + ((.%3)*8)
|
||||
AM.pixel_y = -8 + (round( . / 3)*8)
|
||||
|
||||
/obj/machinery/rust_heretic_act()
|
||||
take_damage(500, BRUTE, "melee", 1)
|
||||
|
||||
@@ -93,13 +93,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
for(var/channel in channels)
|
||||
radio.talk_into(src, message, channel)
|
||||
|
||||
//config stuff
|
||||
|
||||
/obj/machinery/announcement_system/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)
|
||||
/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AutomatedAnnouncement", "Automated Announcement System", 500, 225, master_ui, state)
|
||||
ui = new(user, src, "AutomatedAnnouncement")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/announcement_system/ui_data()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "A machine used to deposit and withdraw station funds."
|
||||
icon = 'goon/icons/obj/goon_terminals.dmi'
|
||||
idle_power_usage = 100
|
||||
|
||||
var/siphoning = FALSE
|
||||
var/next_warning = 0
|
||||
var/obj/item/radio/radio
|
||||
@@ -38,7 +39,6 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/computer/bank_machine/process()
|
||||
..()
|
||||
if(siphoning)
|
||||
@@ -51,7 +51,7 @@
|
||||
end_syphon()
|
||||
return
|
||||
|
||||
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
|
||||
playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE)
|
||||
syphoning_credits += 200
|
||||
D.adjust_money(-200)
|
||||
if(next_warning < world.time && prob(15))
|
||||
@@ -60,17 +60,20 @@
|
||||
radio.talk_into(src, message, radio_channel)
|
||||
next_warning = world.time + minimum_time_between_warnings
|
||||
|
||||
/obj/machinery/computer/bank_machine/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)
|
||||
/obj/machinery/computer/bank_machine/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state)
|
||||
ui = new(user, src, "BankMachine", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/bank_machine/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
data["current_balance"] = D.account_balance
|
||||
|
||||
if(D)
|
||||
data["current_balance"] = D.account_balance
|
||||
else
|
||||
data["current_balance"] = 0
|
||||
data["siphoning"] = siphoning
|
||||
data["station_name"] = station_name()
|
||||
|
||||
|
||||
@@ -43,10 +43,13 @@
|
||||
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)
|
||||
/obj/machinery/computer/operating/ui_state(mob/user)
|
||||
return GLOB.not_incapacitated_state
|
||||
|
||||
/obj/machinery/computer/operating/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state)
|
||||
ui = new(user, src, "OperatingComputer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
@@ -153,6 +156,8 @@
|
||||
))
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
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
|
||||
ui_x = 370
|
||||
ui_y = 360
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = FALSE
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
@@ -20,64 +19,45 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/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)
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user, datum/tgui/ui) //artur didn't port this correctly
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AiRestorer", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "AiRestorer", name)
|
||||
ui.open()
|
||||
|
||||
var/dat = ""
|
||||
/obj/machinery/computer/aifixer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
data["ejectable"] = FALSE
|
||||
data["AI_present"] = FALSE
|
||||
data["error"] = null
|
||||
if(!occupier)
|
||||
data["error"] = "Please transfer an AI unit."
|
||||
else
|
||||
data["AI_present"] = TRUE
|
||||
data["name"] = occupier.name
|
||||
data["restoring"] = active
|
||||
data["health"] = (occupier.health + 100) / 2
|
||||
data["isDead"] = occupier.stat == DEAD
|
||||
data["laws"] = occupier.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
return data
|
||||
|
||||
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>"
|
||||
/obj/machinery/computer/aifixer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!occupier)
|
||||
active = FALSE
|
||||
|
||||
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
|
||||
switch(action)
|
||||
if("PRG_beginReconstruction")
|
||||
if(occupier?.health < 100)
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
active = TRUE
|
||||
occupier.notify_ghost_cloning("Your core files are being restored!", source = src)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
@@ -97,17 +77,6 @@
|
||||
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_overlays()
|
||||
. = ..()
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
desc = "Used to remotely control the flow of power to different parts of the station."
|
||||
icon_screen = "solar"
|
||||
icon_keyboard = "power_key"
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
req_access = list(ACCESS_CE)
|
||||
circuit = /obj/item/circuitboard/computer/apc_control
|
||||
light_color = LIGHT_COLOR_YELLOW
|
||||
var/mob/living/operator //Who's operating the computer right now
|
||||
var/obj/machinery/power/apc/active_apc //The APC we're using right now
|
||||
var/list/result_filters //For sorting the results
|
||||
var/checking_logs = 0
|
||||
var/should_log = TRUE
|
||||
var/restoring = FALSE
|
||||
var/list/logs
|
||||
var/auth_id = "\[NULL\]"
|
||||
var/auth_id = "\[NULL\]:"
|
||||
|
||||
/obj/machinery/computer/apc_control/Initialize()
|
||||
/obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C)
|
||||
. = ..()
|
||||
result_filters = list("Name" = null, "Charge Above" = null, "Charge Below" = null, "Responsive" = null)
|
||||
logs = list()
|
||||
|
||||
/obj/machinery/computer/apc_control/process()
|
||||
if(operator && (!operator.Adjacent(src) || stat))
|
||||
@@ -23,8 +23,8 @@
|
||||
if(active_apc)
|
||||
if(!active_apc.locked)
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
@@ -34,171 +34,163 @@
|
||||
if(!IsAdminGhost(user))
|
||||
to_chat(user,"<span class='warning'>[src] does not support AI control.</span>") //You already have APC access, cheater!
|
||||
return
|
||||
..(user)
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC)
|
||||
return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.stat && !istype(APC.area, /area/ai_monitored) && !APC.area.outdoors
|
||||
|
||||
/obj/machinery/computer/apc_control/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
var/dat
|
||||
if(authenticated)
|
||||
if(!checking_logs)
|
||||
dat += "Logged in as [auth_id].<br><br>"
|
||||
dat += "<i>Filters</i><br>"
|
||||
dat += "<b>Name:</b> <a href='?src=[REF(src)];name_filter=1'>[result_filters["Name"] ? result_filters["Name"] : "None set"]</a><br>"
|
||||
dat += "<b>Charge:</b> <a href='?src=[REF(src)];above_filter=1'>\>[result_filters["Charge Above"] ? result_filters["Charge Above"] : "NaN"]%</a> and <a href='?src=[REF(src)];below_filter=1'>\<[result_filters["Charge Below"] ? result_filters["Charge Below"] : "NaN"]%</a><br>"
|
||||
dat += "<b>Accessible:</b> <a href='?src=[REF(src)];access_filter=1'>[result_filters["Responsive"] ? "Non-Responsive Only" : "All"]</a><br><br>"
|
||||
for(var/A in GLOB.apcs_list)
|
||||
if(check_apc(A))
|
||||
var/obj/machinery/power/apc/APC = A
|
||||
if(result_filters["Name"] && !findtext(APC.name, result_filters["Name"]) && !findtext(APC.area.name, result_filters["Name"]))
|
||||
continue
|
||||
if(result_filters["Charge Above"] && (!APC.cell || (APC.cell && (APC.cell.charge / APC.cell.maxcharge) < result_filters["Charge Above"] / 100)))
|
||||
continue
|
||||
if(result_filters["Charge Below"] && APC.cell && (APC.cell.charge / APC.cell.maxcharge) > result_filters["Charge Below"] / 100)
|
||||
continue
|
||||
if(result_filters["Responsive"] && !APC.aidisabled)
|
||||
continue
|
||||
dat += "<a href='?src=[REF(src)];access_apc=[REF(APC)]'>[A]</a><br>\
|
||||
<b>Charge:</b> [APC.cell ? "[DisplayEnergy(APC.cell.charge)] / [DisplayEnergy(APC.cell.maxcharge)] ([round((APC.cell.charge / APC.cell.maxcharge) * 100)]%)" : "No Powercell Installed"]<br>\
|
||||
<b>Area:</b> [APC.area]<br>\
|
||||
[APC.aidisabled || APC.panel_open ? "<font color='#FF0000'>APC does not respond to interface query.</font>" : "<font color='#00FF00'>APC responds to interface query.</font>"]<br><br>"
|
||||
dat += "<a href='?src=[REF(src)];check_logs=1'>Check Logs</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];log_out=1'>Log Out</a><br>"
|
||||
if(obj_flags & EMAGGED)
|
||||
dat += "<font color='#FF0000'>WARNING: Logging functionality partially disabled from outside source.</font><br>"
|
||||
dat += "<a href='?src=[REF(src)];restore_logging=1'>Restore logging functionality?</a><br>"
|
||||
else
|
||||
if(logs.len)
|
||||
for(var/entry in logs)
|
||||
dat += "[entry]<br>"
|
||||
else
|
||||
dat += "<i>No activity has been recorded at this time.</i><br>"
|
||||
if(obj_flags & EMAGGED)
|
||||
dat += "<a href='?src=[REF(src)];clear_logs=1'><font color='#FF0000'>@#%! CLEAR LOGS</a>"
|
||||
dat += "<a href='?src=[REF(src)];check_apcs=1'>Return</a>"
|
||||
operator = user
|
||||
else
|
||||
dat = "<a href='?src=[REF(src)];authenticate=1'>Please swipe a valid ID to log in...</a>"
|
||||
var/datum/browser/popup = new(user, "apc_control", name, 600, 400)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
/obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui)
|
||||
operator = user
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ApcControl")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/apc_control/Topic(href, href_list)
|
||||
/obj/machinery/computer/apc_control/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["auth_id"] = auth_id
|
||||
data["authenticated"] = authenticated
|
||||
data["emagged"] = obj_flags & EMAGGED
|
||||
data["logging"] = should_log
|
||||
data["restoring"] = restoring
|
||||
data["logs"] = list()
|
||||
data["apcs"] = list()
|
||||
|
||||
for(var/entry in logs)
|
||||
data["logs"] += list(list("entry" = entry))
|
||||
|
||||
for(var/apc in GLOB.apcs_list)
|
||||
if(check_apc(apc))
|
||||
var/obj/machinery/power/apc/A = apc
|
||||
var/has_cell = (A.cell) ? TRUE : FALSE
|
||||
data["apcs"] += list(list(
|
||||
"name" = A.area.name,
|
||||
"operating" = A.operating,
|
||||
"charge" = (has_cell) ? A.cell.percent() : "NOCELL",
|
||||
"load" = DisplayPower(A.lastused_total),
|
||||
"charging" = A.charging,
|
||||
"chargeMode" = A.chargemode,
|
||||
"eqp" = A.equipment,
|
||||
"lgt" = A.lighting,
|
||||
"env" = A.environ,
|
||||
"responds" = A.aidisabled || A.panel_open,
|
||||
"ref" = REF(A)
|
||||
)
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/apc_control/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
if(href_list["authenticate"])
|
||||
var/obj/item/card/id/ID = usr.get_idcard(TRUE)
|
||||
if(ID && istype(ID))
|
||||
if(check_access(ID))
|
||||
switch(action)
|
||||
if("log-in")
|
||||
if(obj_flags & EMAGGED)
|
||||
authenticated = TRUE
|
||||
auth_id = "[ID.registered_name] ([ID.assignment])"
|
||||
log_activity("logged in")
|
||||
if(href_list["log_out"])
|
||||
log_activity("logged out")
|
||||
authenticated = FALSE
|
||||
auth_id = "\[NULL\]"
|
||||
if(href_list["restore_logging"])
|
||||
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Logging functionality restored from backup data.</span>")
|
||||
obj_flags &= ~EMAGGED
|
||||
LAZYADD(logs, "<b>-=- Logging restored to full functionality at this point -=-</b>")
|
||||
if(href_list["access_apc"])
|
||||
playsound(src, "terminal_type", 50, 0)
|
||||
var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list
|
||||
if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC))
|
||||
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.</span>")
|
||||
return
|
||||
if(active_apc)
|
||||
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] Disconnected from [active_apc].</span>")
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
active_apc = null
|
||||
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.</span>")
|
||||
log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]")
|
||||
APC.remote_control = src
|
||||
APC.ui_interact(usr)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
if(APC.locked)
|
||||
APC.say("Remote access detected. Interface unlocked.")
|
||||
playsound(APC, 'sound/machines/boltsup.ogg', 25, 0)
|
||||
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
APC.locked = FALSE
|
||||
APC.update_icon()
|
||||
active_apc = APC
|
||||
if(href_list["name_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = stripped_input(usr, "What name are you looking for?", name)
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed name filter to \"[new_filter]\"")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Name"] = new_filter
|
||||
if(href_list["above_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed greater than charge filter to \"[new_filter]\"")
|
||||
if(new_filter)
|
||||
new_filter = clamp(new_filter, 0, 100)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Charge Above"] = new_filter
|
||||
if(href_list["below_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed lesser than charge filter to \"[new_filter]\"")
|
||||
if(new_filter)
|
||||
new_filter = clamp(new_filter, 0, 100)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Charge Below"] = new_filter
|
||||
if(href_list["access_filter"])
|
||||
if(isnull(result_filters["Responsive"]))
|
||||
result_filters["Responsive"] = 1
|
||||
log_activity("sorted by non-responsive APCs only")
|
||||
else
|
||||
result_filters["Responsive"] = !result_filters["Responsive"]
|
||||
log_activity("sorted by all APCs")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
if(href_list["check_logs"])
|
||||
checking_logs = TRUE
|
||||
log_activity("checked logs")
|
||||
if(href_list["check_apcs"])
|
||||
checking_logs = FALSE
|
||||
log_activity("checked APCs")
|
||||
if(href_list["clear_logs"])
|
||||
logs = list()
|
||||
ui_interact(usr) //Refresh the UI after a filter changes
|
||||
auth_id = "Unknown (Unknown):"
|
||||
log_activity("[auth_id] logged in to the terminal")
|
||||
return
|
||||
var/obj/item/card/id/ID = operator.get_idcard(TRUE)
|
||||
if(ID && istype(ID))
|
||||
if(check_access(ID))
|
||||
authenticated = TRUE
|
||||
auth_id = "[ID.registered_name] ([ID.assignment]):"
|
||||
log_activity("[auth_id] logged in to the terminal")
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
else
|
||||
auth_id = "[ID.registered_name] ([ID.assignment]):"
|
||||
log_activity("[auth_id] attempted to log into the terminal")
|
||||
return
|
||||
auth_id = "Unknown (Unknown):"
|
||||
log_activity("[auth_id] attempted to log into the terminal")
|
||||
if("log-out")
|
||||
log_activity("[auth_id] logged out of the terminal")
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
|
||||
authenticated = FALSE
|
||||
auth_id = "\[NULL\]"
|
||||
if("toggle-logs")
|
||||
should_log = !should_log
|
||||
log_game("[key_name(operator)] set the logs of [src] in [AREACOORD(src)] [should_log ? "On" : "Off"]")
|
||||
if("restore-console")
|
||||
restoring = TRUE
|
||||
addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9)
|
||||
if("access-apc")
|
||||
var/ref = params["ref"]
|
||||
playsound(src, "terminal_type", 50, FALSE)
|
||||
var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list
|
||||
if(!APC)
|
||||
return
|
||||
if(active_apc)
|
||||
to_chat(operator, "<span class='robot danger'>[icon2html(src, auth_id)] Disconnected from [active_apc].</span>")
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
active_apc = null
|
||||
APC.remote_control = src
|
||||
APC.ui_interact(operator)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
log_game("[key_name(operator)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]")
|
||||
if(APC.locked)
|
||||
APC.say("Remote access detected. Interface unlocked.")
|
||||
playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE)
|
||||
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
APC.locked = FALSE
|
||||
APC.update_icon()
|
||||
active_apc = APC
|
||||
if("check-logs")
|
||||
log_activity("Checked Logs")
|
||||
if("check-apcs")
|
||||
log_activity("Checked APCs")
|
||||
if("toggle-minor")
|
||||
var/ref = params["ref"]
|
||||
var/type = params["type"]
|
||||
var/value = params["value"]
|
||||
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
|
||||
if(!target)
|
||||
return
|
||||
target.vars[type] = target.setsubsystem(text2num(value))
|
||||
target.update_icon()
|
||||
target.update()
|
||||
var/setTo = ""
|
||||
switch(target.vars[type])
|
||||
if(0)
|
||||
setTo = "Off"
|
||||
if(1)
|
||||
setTo = "Auto Off"
|
||||
if(2)
|
||||
setTo = "On"
|
||||
if(3)
|
||||
setTo = "Auto On"
|
||||
log_activity("Set APC [target.area.name] [type] to [setTo]")
|
||||
log_game("[key_name(operator)] Set APC [target.area.name] [type] to [setTo]]")
|
||||
if("breaker")
|
||||
var/ref = params["ref"]
|
||||
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
|
||||
target.toggle_breaker()
|
||||
var/setTo = target.operating ? "On" : "Off"
|
||||
log_activity("Turned APC [target.area.name]'s breaker [setTo]")
|
||||
|
||||
/obj/machinery/computer/apc_control/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(!authenticated)
|
||||
to_chat(user, "<span class='warning'>You bypass [src]'s access requirements using your emag.</span>")
|
||||
authenticated = TRUE
|
||||
log_activity("logged in")
|
||||
else
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
user.visible_message("<span class='warning'>You emag [src], disabling precise logging and allowing you to clear logs.</span>")
|
||||
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], disabling operator tracking.")
|
||||
obj_flags |= EMAGGED
|
||||
playsound(src, "sparks", 50, 1)
|
||||
return TRUE
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]")
|
||||
playsound(src, "sparks", 50, TRUE)
|
||||
|
||||
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
|
||||
var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]"
|
||||
LAZYADD(logs, "<b>([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)])</b> [op_string] [log_text]")
|
||||
if(!should_log)
|
||||
return
|
||||
LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]): [auth_id] [log_text]")
|
||||
|
||||
/obj/machinery/computer/apc_control/proc/restore_comp()
|
||||
obj_flags &= ~EMAGGED
|
||||
should_log = TRUE
|
||||
log_game("[key_name(operator)] restored the logs of [src] in [AREACOORD(src)]")
|
||||
log_activity("-=- Logging restored to full functionality at this point -=-")
|
||||
restoring = FALSE
|
||||
|
||||
/mob/proc/using_power_flow_console()
|
||||
for(var/obj/machinery/computer/apc_control/A in range(1, src))
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
dat += "</b></center>"
|
||||
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/arcade/battle/Topic(href, href_list)
|
||||
|
||||
@@ -178,9 +178,12 @@
|
||||
table[y1][x1] += 10
|
||||
if(href_list["same_board"]) //Reset the board... kinda
|
||||
if(game_status != MINESWEEPER_GAME_PLAYING)
|
||||
mine_sound = TRUE
|
||||
game_status = MINESWEEPER_GAME_PLAYING
|
||||
if(table[y1][x1] >= 10) //If revealed, become unrevealed!
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
|
||||
if(mine_sound)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
|
||||
mine_sound = FALSE
|
||||
table[y1][x1] -= 10
|
||||
if(table[y1][x1] > 10 && !reset_board)
|
||||
safe_squares_revealed += 1
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
|
||||
var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
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)
|
||||
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state)
|
||||
ui = new(user, src, "AtmosAlertConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
|
||||
@@ -45,11 +44,11 @@
|
||||
if("clear")
|
||||
var/zone = params["zone"]
|
||||
if(zone in priority_alarms)
|
||||
to_chat(usr, "Priority alarm for [zone] cleared.")
|
||||
to_chat(usr, "<span class='notice'>Priority alarm for [zone] cleared.</span>")
|
||||
priority_alarms -= zone
|
||||
. = TRUE
|
||||
if(zone in minor_alarms)
|
||||
to_chat(usr, "Minor alarm for [zone] cleared.")
|
||||
to_chat(usr, "<span class='notice'>Minor alarm for [zone] cleared.</span>")
|
||||
minor_alarms -= zone
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -91,8 +91,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
ui_x = 400
|
||||
ui_y = 925
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
@@ -123,11 +121,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
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)
|
||||
/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "AtmosControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/ui_data(mob/user)
|
||||
@@ -265,13 +262,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
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, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
data["tank"] = TRUE
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
icon_keyboard = "security_key"
|
||||
circuit = /obj/item/circuitboard/computer/security
|
||||
light_color = LIGHT_COLOR_RED
|
||||
ui_x = 870
|
||||
ui_y = 708
|
||||
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/active_camera
|
||||
@@ -55,11 +53,9 @@
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
/obj/machinery/computer/security/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)
|
||||
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
|
||||
// Update UI
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
@@ -76,10 +72,11 @@
|
||||
use_power(active_power_usage)
|
||||
// Register map objects
|
||||
user.client.register_map_obj(cam_screen)
|
||||
user.client.register_map_obj(cam_plane_master)
|
||||
for(var/plane in cam_plane_master)
|
||||
user.client.register_map_obj(plane)
|
||||
user.client.register_map_obj(cam_background)
|
||||
// Open UI
|
||||
ui = new(user, src, ui_key, "CameraConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "CameraConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/security/ui_data()
|
||||
|
||||
@@ -353,7 +353,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
dat = list("<tt>", header.Join(), body, "<br></tt>")
|
||||
var/datum/browser/popup = new(user, "id_com", src.name, 900, 620)
|
||||
popup.set_content(dat.Join())
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/card/Topic(href, href_list)
|
||||
|
||||
@@ -276,7 +276,6 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "cloning", "Cloning System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cloning/Topic(href, href_list)
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
#define STATE_DEFAULT 1
|
||||
#define STATE_CALLSHUTTLE 2
|
||||
#define STATE_CANCELSHUTTLE 3
|
||||
#define STATE_MESSAGELIST 4
|
||||
#define STATE_VIEWMESSAGE 5
|
||||
#define STATE_DELMESSAGE 6
|
||||
#define STATE_STATUSDISPLAY 7
|
||||
#define STATE_ALERT_LEVEL 8
|
||||
#define STATE_CONFIRM_LEVEL 9
|
||||
#define STATE_TOGGLE_EMERGENCY 10
|
||||
#define STATE_PURCHASE 11
|
||||
|
||||
// The communications computer
|
||||
/obj/machinery/computer/communications
|
||||
name = "communications console"
|
||||
@@ -6,6 +18,7 @@
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list(ACCESS_HEADS)
|
||||
circuit = /obj/item/circuitboard/computer/communications
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
var/auth_id = "Unknown" //Who is currently logged in?
|
||||
var/list/datum/comm_message/messages = list()
|
||||
var/datum/comm_message/currmsg
|
||||
@@ -16,22 +29,10 @@
|
||||
var/ai_message_cooldown = 0
|
||||
var/tmp_alertlevel = 0
|
||||
var/static/security_level_cd // used to stop mass spam.
|
||||
var/const/STATE_DEFAULT = 1
|
||||
var/const/STATE_CALLSHUTTLE = 2
|
||||
var/const/STATE_CANCELSHUTTLE = 3
|
||||
var/const/STATE_MESSAGELIST = 4
|
||||
var/const/STATE_VIEWMESSAGE = 5
|
||||
var/const/STATE_DELMESSAGE = 6
|
||||
var/const/STATE_STATUSDISPLAY = 7
|
||||
var/const/STATE_ALERT_LEVEL = 8
|
||||
var/const/STATE_CONFIRM_LEVEL = 9
|
||||
var/const/STATE_TOGGLE_EMERGENCY = 10
|
||||
var/const/STATE_PURCHASE = 11
|
||||
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/communications/proc/checkCCcooldown()
|
||||
var/obj/item/circuitboard/computer/communications/CM = circuit
|
||||
@@ -46,7 +47,7 @@
|
||||
/obj/machinery/computer/communications/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src))
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13
|
||||
to_chat(usr, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
|
||||
@@ -132,15 +133,20 @@
|
||||
|
||||
if("crossserver")
|
||||
if(authenticated==2)
|
||||
var/dest = href_list["cross_dest"]
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
return
|
||||
var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
|
||||
var/warning = dest == "all" ? "Please choose a message to transmit to allied stations." : "Please choose a message to transmit to [dest] sector station."
|
||||
var/input = stripped_multiline_input(usr, "[warning] Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
send2otherserver("[station_name()]", input,"Comms_Console")
|
||||
if(dest == "all")
|
||||
send2otherserver("[station_name()]", input,"Comms_Console")
|
||||
else
|
||||
send2otherserver("[station_name()]", input,"Comms_Console", list(dest))
|
||||
minor_announce(input, title = "Outgoing message to allied station")
|
||||
usr.log_talk(input, LOG_SAY, tag="message to the other server")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.")
|
||||
@@ -156,12 +162,12 @@
|
||||
var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles
|
||||
if(S && istype(S))
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE)
|
||||
to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?")
|
||||
to_chat(usr, "<span class='alert'>It's a bit late to buy a new shuttle, don't you think?</span>")
|
||||
return
|
||||
if(SSshuttle.shuttle_purchased)
|
||||
to_chat(usr, "A replacement shuttle has already been purchased.")
|
||||
to_chat(usr, "<span class='alert'>A replacement shuttle has already been purchased.</span>")
|
||||
else if(!S.prerequisites_met())
|
||||
to_chat(usr, "You have not met the requirements for purchasing this shuttle.")
|
||||
to_chat(usr, "<span class='alert'>You have not met the requirements for purchasing this shuttle.</span>")
|
||||
else
|
||||
var/points_to_check
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
||||
@@ -183,7 +189,7 @@
|
||||
|
||||
if("callshuttle")
|
||||
state = STATE_DEFAULT
|
||||
if(authenticated)
|
||||
if(authenticated && SSshuttle.canEvac(usr))
|
||||
state = STATE_CALLSHUTTLE
|
||||
if("callshuttle2")
|
||||
if(authenticated)
|
||||
@@ -284,12 +290,12 @@
|
||||
if("MessageCentCom")
|
||||
if(authenticated)
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
CentCom_announce(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Message transmitted to Central Command.</span>")
|
||||
for(var/client/X in GLOB.admins)
|
||||
@@ -302,7 +308,7 @@
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate")
|
||||
if((authenticated==2) && (obj_flags & EMAGGED))
|
||||
if((authenticated) && (obj_flags & EMAGGED))
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
@@ -332,7 +338,7 @@
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","")
|
||||
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self-Destruct Code Request.","")
|
||||
if(!input || !(usr in view(1,src)) || !checkCCcooldown())
|
||||
return
|
||||
Nuke_request(input, usr)
|
||||
@@ -347,7 +353,9 @@
|
||||
aicurrmsg = null
|
||||
aistate = STATE_DEFAULT
|
||||
if("ai-callshuttle")
|
||||
aistate = STATE_CALLSHUTTLE
|
||||
aistate = STATE_DEFAULT
|
||||
if(SSshuttle.canEvac(usr))
|
||||
aistate = STATE_CALLSHUTTLE
|
||||
if("ai-callshuttle2")
|
||||
SSshuttle.requestEvac(usr, href_list["call"])
|
||||
aistate = STATE_DEFAULT
|
||||
@@ -460,9 +468,8 @@
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
|
||||
if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src)))
|
||||
if(issilicon(user))
|
||||
var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access
|
||||
if(dat2)
|
||||
dat += dat2
|
||||
@@ -493,9 +500,15 @@
|
||||
if (authenticated==2)
|
||||
dat += "<BR><BR><B>Captain Functions</B>"
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=announce'>Make a Captain's Announcement</A> \]"
|
||||
var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server))
|
||||
if(cross_servers_count)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver'>Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""]</A> \]"
|
||||
var/list/cross_servers = CONFIG_GET(keyed_list/cross_server)
|
||||
var/our_id = CONFIG_GET(string/cross_comms_name)
|
||||
if(cross_servers.len)
|
||||
for(var/server in cross_servers)
|
||||
if(server == our_id)
|
||||
continue
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver=all;cross_dest=[server]'>Send a message to station in [server] sector.</A> \]"
|
||||
if(cross_servers.len > 2)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=crossserver;cross_dest=all'>Send a message to all allied stations</A> \]"
|
||||
if(SSmapping.config.allow_custom_shuttles)
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=purchase_menu'>Purchase Shuttle</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=changeseclevel'>Change Alert Level</A> \]"
|
||||
@@ -721,8 +734,13 @@
|
||||
to_chat(user, "<span class='alert'>Intercomms recharging. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?")
|
||||
if(!input || !user.canUseTopic(src))
|
||||
if(!input || !user.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(!(user.can_speak())) //No more cheating, mime/random mute guy!
|
||||
input = "..."
|
||||
to_chat(user, "<span class='warning'>You find yourself unable to speak.</span>")
|
||||
else
|
||||
input = user.treat_message(input) //Adds slurs and so on. Someone should make this use languages too.
|
||||
SScommunications.make_announcement(user, is_silicon, input)
|
||||
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> made an priority announcement from <span class='name'>[get_area_name(usr, TRUE)]</span>.</span>", user)
|
||||
|
||||
@@ -771,3 +789,15 @@
|
||||
content = new_content
|
||||
if(new_possible_answers)
|
||||
possible_answers = new_possible_answers
|
||||
|
||||
#undef STATE_DEFAULT
|
||||
#undef STATE_CALLSHUTTLE
|
||||
#undef STATE_CANCELSHUTTLE
|
||||
#undef STATE_MESSAGELIST
|
||||
#undef STATE_VIEWMESSAGE
|
||||
#undef STATE_DELMESSAGE
|
||||
#undef STATE_STATUSDISPLAY
|
||||
#undef STATE_ALERT_LEVEL
|
||||
#undef STATE_CONFIRM_LEVEL
|
||||
#undef STATE_TOGGLE_EMERGENCY
|
||||
#undef STATE_PURCHASE
|
||||
|
||||
@@ -76,11 +76,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
/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)
|
||||
/datum/crewmonitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui = new(user, src, "CrewConsole")
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
|
||||
@@ -217,12 +217,7 @@
|
||||
// already discovered mutations
|
||||
stored_research = SSresearch.science_tech
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui)
|
||||
// Most of ui_interact is spent setting variables for passing to the tgui
|
||||
// interface.
|
||||
// We can also do some general state processing here too as it's a good
|
||||
@@ -264,11 +259,14 @@
|
||||
time_to_pulse = round((rad_pulse_timer - world.time)/10)
|
||||
|
||||
// Attempt to update tgui ui, open and update if needed.
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "DnaConsole", name, 539, 710, master_ui, state)
|
||||
ui = new(user, src, "DnaConsole")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_assets()
|
||||
. = ..() || list()
|
||||
. += get_asset_datum(/datum/asset/simple/genetics)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
@@ -360,7 +358,7 @@
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_act(action, var/list/params)
|
||||
/obj/machinery/computer/scan_consolenew/ui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
@@ -485,6 +483,7 @@
|
||||
// Resolve mutation's BYOND path from the alias
|
||||
var/alias = params["alias"]
|
||||
var/path = GET_MUTATION_TYPE_FROM_ALIAS(alias)
|
||||
|
||||
// Make sure the occupant still has this mutation
|
||||
if(!(path in scanner_occupant.dna.mutation_index))
|
||||
return
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
var/obj/machinery/launchpad/pad = launchpads[number]
|
||||
return pad
|
||||
|
||||
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/launchpad/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "LaunchpadConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/launchpad/ui_data(mob/user)
|
||||
@@ -128,4 +128,4 @@
|
||||
if("pull")
|
||||
teleport(usr, current_pad, FALSE)
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
@@ -178,7 +178,6 @@
|
||||
dat += "<A href='?src=[REF(src)];login=1'>{Log In}</A>"
|
||||
var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/med_data/Topic(href, href_list)
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
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()
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
icon_keyboard = "security_key"
|
||||
req_access = list(ACCESS_ARMORY)
|
||||
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
|
||||
ui_x = 350
|
||||
ui_y = 295
|
||||
|
||||
var/default_goal = 200
|
||||
var/obj/machinery/gulag_teleporter/teleporter = null
|
||||
@@ -21,11 +19,10 @@
|
||||
. = ..()
|
||||
scan_machinery()
|
||||
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/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)
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "GulagTeleporterConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "GulagTeleporterConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
dat += "<HR><A href='?src=[REF(src)];lock=1'>{Log Out}</A>"
|
||||
var/datum/browser/popup = new(user, "computer", "Prisoner Management Console", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/robotics/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)
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "RoboticsControlConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "RoboticsControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/robotics/ui_data(mob/user)
|
||||
@@ -123,5 +122,5 @@
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, TRUE, D)
|
||||
s.start()
|
||||
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
|
||||
D.visible_message("<span class='danger'>\the [D] self-destructs!</span>")
|
||||
D.gib()
|
||||
|
||||
@@ -250,7 +250,6 @@
|
||||
dat += "<A href='?src=[REF(src)];choice=Log In'>{Log In}</A>"
|
||||
var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
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)
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state)
|
||||
ui = new(user, src, "StationAlertConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
@@ -31,6 +30,7 @@
|
||||
data["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
data["alarms"][class] += area
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
|
||||
@@ -103,7 +103,6 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
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)
|
||||
@@ -185,7 +184,6 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
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)
|
||||
|
||||
@@ -34,11 +34,10 @@
|
||||
break
|
||||
return power_station
|
||||
|
||||
obj/machinery/computer/teleporter/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)
|
||||
/obj/machinery/computer/teleporter/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Teleporter", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "Teleporter", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/teleporter/ui_data(mob/user)
|
||||
@@ -56,7 +55,6 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/obj/machinery/computer/teleporter/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
@@ -92,16 +90,18 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
|
||||
say("Processing hub calibration to target...")
|
||||
calibrating = TRUE
|
||||
power_station.update_icon()
|
||||
spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
|
||||
calibrating = FALSE
|
||||
if(check_hub_connection())
|
||||
power_station.teleporter_hub.calibrated = TRUE
|
||||
say("Calibration complete.")
|
||||
else
|
||||
say("Error: Unable to detect hub.")
|
||||
power_station.update_icon()
|
||||
addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/teleporter/proc/finish_calibration()
|
||||
calibrating = FALSE
|
||||
if(check_hub_connection())
|
||||
power_station.teleporter_hub.calibrated = TRUE
|
||||
say("Calibration complete.")
|
||||
else
|
||||
say("Error: Unable to detect hub.")
|
||||
power_station.update_icon()
|
||||
|
||||
/obj/machinery/computer/teleporter/proc/check_hub_connection()
|
||||
if(!power_station)
|
||||
return FALSE
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cryopod/Topic(href, href_list)
|
||||
@@ -308,7 +307,7 @@
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
|
||||
investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
|
||||
//Handle Borg stuff first
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/active = FALSE
|
||||
var/list/rangers = list()
|
||||
var/stop = 0
|
||||
var/volume = 70
|
||||
var/datum/track/selection = null
|
||||
|
||||
/obj/machinery/jukebox/disco
|
||||
@@ -51,74 +52,91 @@
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/machinery/jukebox/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if (!anchored)
|
||||
/obj/machinery/jukebox/ui_status(mob/user)
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
|
||||
return
|
||||
if(!allowed(user))
|
||||
return UI_CLOSE
|
||||
if(!allowed(user) && !isobserver(user))
|
||||
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
|
||||
user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1)
|
||||
return
|
||||
if(!SSjukeboxes.songs.len)
|
||||
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
if(!SSjukeboxes.songs.len && !isobserver(user))
|
||||
to_chat(user,"<span class='warning'>Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.</span>")
|
||||
playsound(src,'sound/misc/compiler-failure.ogg', 25, 1)
|
||||
return
|
||||
var/list/dat = list()
|
||||
dat +="<div class='statusDisplay' style='text-align:center'>"
|
||||
dat += "<b><A href='?src=[REF(src)];action=toggle'>[!active ? "BREAK IT DOWN" : "SHUT IT DOWN"]<b></A><br>"
|
||||
dat += "</div><br>"
|
||||
dat += "<A href='?src=[REF(src)];action=select'> Select Track</A><br>"
|
||||
if(istype(selection))
|
||||
dat += "Track Selected: [selection.song_name]<br>"
|
||||
dat += "Track Length: [DisplayTimeText(selection.song_length)]<br><br>"
|
||||
else
|
||||
dat += "Track Selected: None!<br><br>"
|
||||
var/datum/browser/popup = new(user, "vending", "[name]", 400, 350)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/jukebox/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Jukebox", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/jukebox/Topic(href, href_list)
|
||||
if(..())
|
||||
/obj/machinery/jukebox/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["active"] = active
|
||||
data["songs"] = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
var/list/track_data = list(
|
||||
name = S.song_name
|
||||
)
|
||||
data["songs"] += list(track_data)
|
||||
data["track_selected"] = null
|
||||
data["track_length"] = null
|
||||
data["track_beat"] = null
|
||||
if(selection)
|
||||
data["track_selected"] = selection.song_name
|
||||
data["track_length"] = DisplayTimeText(selection.song_length)
|
||||
data["track_beat"] = selection.song_beat
|
||||
data["volume"] = volume
|
||||
return data
|
||||
|
||||
/obj/machinery/jukebox/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
switch(href_list["action"])
|
||||
|
||||
switch(action)
|
||||
if("toggle")
|
||||
if (QDELETED(src))
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!active)
|
||||
if(stop > world.time)
|
||||
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
|
||||
return
|
||||
if(!istype(selection))
|
||||
to_chat(usr, "<span class='warning'>Error: Severe user incompetence detected.</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
return
|
||||
if(!activate_music())
|
||||
to_chat(usr, "<span class='warning'>Error: Generic hardware failure.</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
return
|
||||
updateUsrDialog()
|
||||
else if(active)
|
||||
activate_music()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return TRUE
|
||||
else
|
||||
stop = 0
|
||||
updateUsrDialog()
|
||||
if("select")
|
||||
return TRUE
|
||||
if("select_track")
|
||||
if(active)
|
||||
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
|
||||
return
|
||||
|
||||
var/list/available = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
available[S.song_name] = S
|
||||
var/selected = input(usr, "Choose your song", "Track:") as null|anything in available
|
||||
var/selected = params["track"]
|
||||
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
|
||||
return
|
||||
selection = available[selected]
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
if("set_volume")
|
||||
var/new_volume = params["volume"]
|
||||
if(new_volume == "reset")
|
||||
volume = initial(volume)
|
||||
return TRUE
|
||||
else if(new_volume == "min")
|
||||
volume = 0
|
||||
return TRUE
|
||||
else if(new_volume == "max")
|
||||
volume = 100
|
||||
return TRUE
|
||||
else if(text2num(new_volume) != null)
|
||||
volume = text2num(new_volume)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/jukebox/proc/activate_music()
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
integrity_failure = 0.25
|
||||
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
|
||||
autoclose = TRUE
|
||||
secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
|
||||
secondsElectrified = NOT_ELECTRIFIED //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
|
||||
assemblytype = /obj/structure/door_assembly
|
||||
normalspeed = 1
|
||||
explosion_block = 1
|
||||
@@ -298,10 +298,10 @@
|
||||
|
||||
/obj/machinery/door/airlock/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(electronics)
|
||||
if(charge)
|
||||
qdel(charge)
|
||||
charge = null
|
||||
QDEL_NULL(electronics)
|
||||
if (cyclelinkedairlock)
|
||||
if (cyclelinkedairlock.cyclelinkedairlock == src)
|
||||
cyclelinkedairlock.cyclelinkedairlock = null
|
||||
@@ -309,7 +309,7 @@
|
||||
if(id_tag)
|
||||
for(var/obj/machinery/doorButtons/D in GLOB.machines)
|
||||
D.removeMe(src)
|
||||
qdel(note)
|
||||
QDEL_NULL(note)
|
||||
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
|
||||
diag_hud.remove_from_hud(src)
|
||||
return ..()
|
||||
@@ -765,8 +765,8 @@
|
||||
|
||||
/obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!(issilicon(user) || IsAdminGhost(user)))
|
||||
if(src.isElectrified())
|
||||
if(src.shock(user, 100))
|
||||
if(isElectrified())
|
||||
if(shock(user, 100))
|
||||
return
|
||||
|
||||
if(ishuman(user) && prob(40) && src.density)
|
||||
@@ -790,15 +790,15 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/airlock/proc/electrified_loop()
|
||||
while (secondsElectrified > 0)
|
||||
while (secondsElectrified > NOT_ELECTRIFIED)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
secondsElectrified -= 1
|
||||
secondsElectrified--
|
||||
updateDialog()
|
||||
// This is to protect against changing to permanent, mid loop.
|
||||
if(secondsElectrified==0)
|
||||
if(secondsElectrified == NOT_ELECTRIFIED)
|
||||
set_electrified(NOT_ELECTRIFIED)
|
||||
else
|
||||
set_electrified(ELECTRIFIED_PERMANENT)
|
||||
@@ -825,8 +825,8 @@
|
||||
|
||||
/obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params)
|
||||
if(!issilicon(user) && !IsAdminGhost(user))
|
||||
if(src.isElectrified())
|
||||
if(src.shock(user, 75))
|
||||
if(isElectrified())
|
||||
if(shock(user, 75))
|
||||
return
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -839,7 +839,7 @@
|
||||
to_chat(user, "<span class='warning'>You need at least 2 metal sheets to reinforce [src].</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start reinforcing [src].</span>")
|
||||
if(do_after(user, 20, 1, target = src))
|
||||
if(do_after(user, 20, TRUE, target = src))
|
||||
if(!panel_open || !S.use(2))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] reinforces \the [src] with metal.</span>",
|
||||
@@ -1070,7 +1070,7 @@
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
|
||||
if(istype(I, /obj/item/crowbar/power))
|
||||
if(isElectrified())
|
||||
if(hasPower() && isElectrified())
|
||||
shock(user,100)//it's like sticking a forck in a power socket
|
||||
return
|
||||
|
||||
@@ -1090,12 +1090,11 @@
|
||||
time_to_open = 50
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick?
|
||||
prying_so_hard = TRUE
|
||||
var/result = do_after(user, time_to_open,target = src)
|
||||
prying_so_hard = FALSE
|
||||
if(result)
|
||||
if(do_after(user, time_to_open,target = src))
|
||||
open(2)
|
||||
if(density && !open(2))
|
||||
to_chat(user, "<span class='warning'>Despite your attempts, [src] refuses to open.</span>")
|
||||
prying_so_hard = FALSE
|
||||
|
||||
/obj/machinery/door/airlock/open(forced=0)
|
||||
if( operating || welded || locked )
|
||||
@@ -1112,7 +1111,6 @@
|
||||
detonated = 1
|
||||
charge = null
|
||||
for(var/mob/living/carbon/human/H in orange(2,src))
|
||||
H.Unconscious(160)
|
||||
H.adjust_fire_stacks(20)
|
||||
H.IgniteMob() //Guaranteed knockout and ignition for nearby people
|
||||
H.apply_damage(40, BRUTE, BODY_ZONE_CHEST)
|
||||
@@ -1360,12 +1358,25 @@
|
||||
wires.cut_all()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/proc/set_electrified(seconds)
|
||||
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
|
||||
secondsElectrified = seconds
|
||||
diag_hud_set_electrified()
|
||||
if(secondsElectrified > 0)
|
||||
if(secondsElectrified > NOT_ELECTRIFIED)
|
||||
INVOKE_ASYNC(src, .proc/electrified_loop)
|
||||
|
||||
if(user)
|
||||
var/message
|
||||
switch(secondsElectrified)
|
||||
if(ELECTRIFIED_PERMANENT)
|
||||
message = "permanently shocked"
|
||||
if(NOT_ELECTRIFIED)
|
||||
message = "unshocked"
|
||||
else
|
||||
message = "temp shocked for [secondsElectrified] seconds"
|
||||
LAZYADD(shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)] - ([uppertext(message)])"))
|
||||
log_combat(user, src, message)
|
||||
//add_hiddenprint(user)
|
||||
|
||||
/obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(obj_integrity < (0.75 * max_integrity))
|
||||
@@ -1439,11 +1450,10 @@
|
||||
else if(istype(note, /obj/item/photo))
|
||||
return "photo"
|
||||
|
||||
/obj/machinery/door/airlock/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)
|
||||
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/door/airlock/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state)
|
||||
ui = new(user, src, "AiAirlock", name)
|
||||
ui.open()
|
||||
return TRUE
|
||||
|
||||
@@ -1451,13 +1461,13 @@
|
||||
var/list/data = list()
|
||||
|
||||
var/list/power = list()
|
||||
power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean
|
||||
power["main_timeleft"] = src.secondsMainPowerLost
|
||||
power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean
|
||||
power["backup_timeleft"] = src.secondsBackupPowerLost
|
||||
power["main"] = secondsMainPowerLost ? 0 : 2 // boolean
|
||||
power["main_timeleft"] = secondsMainPowerLost
|
||||
power["backup"] = secondsBackupPowerLost ? 0 : 2 // boolean
|
||||
power["backup_timeleft"] = secondsBackupPowerLost
|
||||
data["power"] = power
|
||||
|
||||
data["shock"] = secondsElectrified == 0 ? 2 : 0
|
||||
data["shock"] = secondsElectrified == NOT_ELECTRIFIED ? 2 : 0
|
||||
data["shock_timeleft"] = secondsElectrified
|
||||
data["id_scanner"] = !aiDisabledIdScanner
|
||||
data["emergency"] = emergency // access
|
||||
@@ -1494,14 +1504,14 @@
|
||||
loseMainPower()
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "Main power is already offline.")
|
||||
to_chat(usr, "<span class='warning'>Main power is already offline.</span>")
|
||||
. = TRUE
|
||||
if("disrupt-backup")
|
||||
if(!secondsBackupPowerLost)
|
||||
loseBackupPower()
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "Backup power is already offline.")
|
||||
to_chat(usr, "<span class='warning'>Backup power is already offline.</span>")
|
||||
. = TRUE
|
||||
if("shock-restore")
|
||||
shock_restore(usr)
|
||||
@@ -1530,7 +1540,6 @@
|
||||
. = TRUE
|
||||
if("speed-toggle")
|
||||
normalspeed = !normalspeed
|
||||
|
||||
. = TRUE
|
||||
if("open-close")
|
||||
user_toggle_open(usr)
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
. = ..()
|
||||
. += "<span class='notice'>Has a neat <i>selection menu</i> for modifying airlock access levels.</span>"
|
||||
|
||||
/obj/item/electronics/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/electronics/airlock/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/electronics/airlock/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state)
|
||||
ui = new(user, src, "AirlockElectronics", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/electronics/airlock/ui_static_data(mob/user)
|
||||
|
||||
@@ -310,6 +310,17 @@
|
||||
opacity = 0
|
||||
glass = TRUE
|
||||
|
||||
/obj/machinery/door/airlock/bronze
|
||||
name = "bronze airlock"
|
||||
icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
|
||||
overlays_file = 'icons/obj/doors/airlocks/clockwork/overlays.dmi'
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_bronze
|
||||
|
||||
/obj/machinery/door/airlock/bronze/seethru
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_bronze/seethru
|
||||
opacity = 0
|
||||
glass = TRUE
|
||||
|
||||
//////////////////////////////////
|
||||
/*
|
||||
Station2 Airlocks
|
||||
|
||||
@@ -140,11 +140,10 @@
|
||||
. = 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)
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state)
|
||||
ui = new(user, src, "BrigTimer", name)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
@@ -235,7 +234,7 @@
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = REALTIMEOFDAY
|
||||
activation_time = world.time
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
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
|
||||
flags_1 = PREVENT_CLICK_UNDER_1|DEFAULT_RICOCHET_1
|
||||
ricochet_chance_mod = 0.8
|
||||
|
||||
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
|
||||
@@ -342,7 +342,8 @@
|
||||
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(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
for(var/datum/wound/W in C.all_wounds)
|
||||
for(var/i in C.all_wounds) // should probably replace with signal
|
||||
var/datum/wound/W = i
|
||||
W.crush(DOOR_CRUSH_DAMAGE)
|
||||
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.
|
||||
|
||||
@@ -74,12 +74,6 @@
|
||||
/obj/machinery/door/firedoor/Bumped(atom/movable/AM)
|
||||
if(panel_open || operating || welded)
|
||||
return
|
||||
if(ismob(AM))
|
||||
var/mob/user = AM
|
||||
if(density && !welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user)))
|
||||
add_fingerprint(user)
|
||||
open()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/door/firedoor/power_change()
|
||||
@@ -90,14 +84,6 @@
|
||||
stat |= NOPOWER
|
||||
|
||||
/obj/machinery/door/firedoor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user)))
|
||||
add_fingerprint(user)
|
||||
if(density)
|
||||
emergency_close_timer = world.time + 30 // prevent it from instaclosing again if in space
|
||||
open()
|
||||
else
|
||||
close()
|
||||
return TRUE
|
||||
if(operating || !density)
|
||||
return
|
||||
|
||||
@@ -298,7 +284,7 @@
|
||||
|
||||
/obj/machinery/door/firedoor/border_only
|
||||
icon = 'icons/obj/doors/edge_Doorfire.dmi'
|
||||
flags_1 = ON_BORDER_1
|
||||
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/closed
|
||||
@@ -320,7 +306,7 @@
|
||||
to_chat(M, "<span class='notice'>You pull [M.pulling] through [src] right as it closes</span>")
|
||||
M.pulling.forceMove(T1)
|
||||
M.start_pulling(M2)
|
||||
|
||||
|
||||
for(var/mob/living/M in T2)
|
||||
if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T1 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force)
|
||||
var/mob/living/M2 = M.pulling
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
integrity_failure = 0
|
||||
armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100)
|
||||
visible = FALSE
|
||||
flags_1 = ON_BORDER_1
|
||||
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
|
||||
opacity = 0
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
|
||||
|
||||
@@ -260,7 +260,6 @@
|
||||
|
||||
/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()
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
. = ..()
|
||||
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()
|
||||
|
||||
|
||||
@@ -20,18 +20,15 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
|
||||
return
|
||||
req_access = list()
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/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)
|
||||
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state)
|
||||
ui = new(user, src, "GulagItemReclaimer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
|
||||
@@ -60,20 +57,22 @@
|
||||
mobs += list(mob_info)
|
||||
|
||||
data["mobs"] = mobs
|
||||
|
||||
|
||||
data["can_reclaim"] = can_reclaim
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/ui_act(action, list/params)
|
||||
/obj/machinery/gulag_item_reclaimer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("release_items")
|
||||
var/mob/M = locate(params["mobref"])
|
||||
if(M == usr || allowed(usr))
|
||||
drop_items(M)
|
||||
else
|
||||
to_chat(usr, "Access denied.")
|
||||
var/mob/living/carbon/human/H = locate(params["mobref"]) in stored_items
|
||||
if(H != usr && !allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
drop_items(H)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user)
|
||||
if(!stored_items[user])
|
||||
|
||||
+182
-187
@@ -25,7 +25,6 @@ Possible to do for anyone motivated enough:
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#define HOLOGRAM_POWER_USAGE 2
|
||||
|
||||
@@ -34,34 +33,64 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
plane = ABOVE_WALL_PLANE
|
||||
plane = FLOOR_PLANE
|
||||
flags_1 = HEAR_1
|
||||
req_access = list(ACCESS_KEYCARD_AUTH) //Used to allow for forced connecting to other (not secure) holopads. Anyone can make a call, though.
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 100
|
||||
max_integrity = 300
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
|
||||
circuit = /obj/item/circuitboard/machine/holopad
|
||||
var/list/masters //List of living mobs that use the holopad
|
||||
var/list/holorays //Holoray-mob link.
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
var/temp = ""
|
||||
var/list/holo_calls //array of /datum/holocalls
|
||||
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
var/obj/item/disk/holodisk/disk //Record disk
|
||||
var/replay_mode = FALSE //currently replaying a recording
|
||||
var/loop_mode = FALSE //currently looping a recording
|
||||
var/record_mode = FALSE //currently recording
|
||||
var/record_start = 0 //recording start time
|
||||
var/record_user //user that inititiated the recording
|
||||
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
|
||||
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
/// List of living mobs that use the holopad
|
||||
var/list/masters
|
||||
/// Holoray-mob link
|
||||
var/list/holorays
|
||||
/// To prevent request spam. ~Carn
|
||||
var/last_request = 0
|
||||
/// Change to change how far the AI can move away from the holopad before deactivating
|
||||
var/holo_range = 5
|
||||
/// Array of /datum/holocalls
|
||||
var/list/holo_calls
|
||||
/// Currently outgoing holocall, do not modify the datums only check and call the public procs
|
||||
var/datum/holocall/outgoing_call
|
||||
/// Record disk
|
||||
var/obj/item/disk/holodisk/disk
|
||||
/// Currently replaying a recording
|
||||
var/replay_mode = FALSE
|
||||
/// Currently looping a recording
|
||||
var/loop_mode = FALSE
|
||||
/// Currently recording
|
||||
var/record_mode = FALSE
|
||||
/// Recording start time
|
||||
var/record_start = 0
|
||||
/// User that inititiated the recording
|
||||
var/record_user
|
||||
/// Replay hologram
|
||||
var/obj/effect/overlay/holo_pad_hologram/replay_holo
|
||||
/// Calls will be automatically answered after a couple rings, here for debugging
|
||||
var/static/force_answer_call = FALSE
|
||||
// var/static/list/holopads = list()
|
||||
var/obj/effect/overlay/holoray/ray
|
||||
var/ringing = FALSE
|
||||
var/offset = FALSE
|
||||
var/on_network = TRUE
|
||||
/// For pads in secure areas; do not allow forced connecting
|
||||
var/secure = FALSE
|
||||
/// If we are currently calling another holopad
|
||||
var/calling = FALSE
|
||||
/*
|
||||
/obj/machinery/holopad/secure
|
||||
name = "secure holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls."
|
||||
secure = TRUE
|
||||
|
||||
/obj/machinery/holopad/secure/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/circuitboard/machine/holopad/board = circuit
|
||||
board.secure = TRUE
|
||||
board.build_path = /obj/machinery/holopad/secure
|
||||
*/
|
||||
/obj/machinery/holopad/tutorial
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
@@ -121,10 +150,8 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/power_change()
|
||||
if (powered())
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
. = ..()
|
||||
if (!powered())
|
||||
if(replay_mode)
|
||||
replay_stop()
|
||||
if(record_mode)
|
||||
@@ -163,171 +190,150 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
if(istype(P,/obj/item/disk/holodisk))
|
||||
if(disk)
|
||||
to_chat(user,"<span class='notice'>There's already a disk inside [src]</span>")
|
||||
to_chat(user,"<span class='warning'>There's already a disk inside [src]!</span>")
|
||||
return
|
||||
if (!user.transferItemToLoc(P,src))
|
||||
return
|
||||
to_chat(user,"<span class='notice'>You insert [P] into [src]</span>")
|
||||
to_chat(user,"<span class='notice'>You insert [P] into [src].</span>")
|
||||
disk = P
|
||||
updateDialog()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/ui_status(mob/user)
|
||||
if(!is_operational())
|
||||
return UI_CLOSE
|
||||
if(outgoing_call && !calling)
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests.
|
||||
/obj/machinery/holopad/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Holopad", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/holopad/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["calling"] = calling
|
||||
data["on_network"] = on_network
|
||||
data["on_cooldown"] = last_request + 200 < world.time ? FALSE : TRUE
|
||||
data["allowed"] = allowed(user)
|
||||
data["disk"] = disk ? TRUE : FALSE
|
||||
data["disk_record"] = disk?.record ? TRUE : FALSE
|
||||
data["replay_mode"] = replay_mode
|
||||
data["loop_mode"] = loop_mode
|
||||
data["record_mode"] = record_mode
|
||||
data["holo_calls"] = list()
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
var/list/call_data = list(
|
||||
caller = HC.user,
|
||||
connected = HC.connected_holopad == src ? TRUE : FALSE,
|
||||
ref = REF(HC)
|
||||
)
|
||||
data["holo_calls"] += list(call_data)
|
||||
return data
|
||||
|
||||
/obj/machinery/holopad/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(!istype(user))
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(outgoing_call || user.incapacitated() || !is_operational())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = temp
|
||||
else
|
||||
if(on_network)
|
||||
dat += "<a href='?src=[REF(src)];AIrequest=1'>Request an AI's presence</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];Holocall=1'>Call another holopad</a><br>"
|
||||
if(disk)
|
||||
if(disk.record)
|
||||
//Replay
|
||||
dat += "<a href='?src=[REF(src)];replay_start=1'>Replay disk recording</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];loop_start=1'>Loop disk recording</a><br>"
|
||||
//Clear
|
||||
dat += "<a href='?src=[REF(src)];record_clear=1'>Clear disk recording</a><br>"
|
||||
switch(action)
|
||||
if("AIrequest")
|
||||
if(last_request + 200 < world.time)
|
||||
last_request = world.time
|
||||
to_chat(usr, "<span class='info'>You requested an AI's presence.</span>")
|
||||
var/area/area = get_area(src)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
|
||||
if(!AI.client)
|
||||
continue
|
||||
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
|
||||
return TRUE
|
||||
else
|
||||
//Record
|
||||
dat += "<a href='?src=[REF(src)];record_start=1'>Start new recording</a><br>"
|
||||
//Eject
|
||||
dat += "<a href='?src=[REF(src)];disk_eject=1'>Eject disk</a><br>"
|
||||
to_chat(usr, "<span class='info'>A request for AI presence was already sent recently.</span>")
|
||||
return
|
||||
if("holocall")
|
||||
if(outgoing_call)
|
||||
return
|
||||
if(usr.loc == loc)
|
||||
var/list/callnames = list()
|
||||
for(var/I in GLOB.network_holopads)
|
||||
var/area/A = get_area(I)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in sortNames(callnames)
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
if(usr.loc == loc)
|
||||
var/input = text2num(params["headcall"])
|
||||
var/headcall = input == 1 ? TRUE : FALSE
|
||||
new /datum/holocall(usr, src, callnames[result], headcall)
|
||||
calling = TRUE
|
||||
return TRUE
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You must stand on the holopad to make a call!</span>")
|
||||
if("connectcall")
|
||||
var/datum/holocall/call_to_connect = locate(params["holopad"]) in holo_calls
|
||||
if(!QDELETED(call_to_connect))
|
||||
call_to_connect.Answer(src)
|
||||
return TRUE
|
||||
if("disconnectcall")
|
||||
var/datum/holocall/call_to_disconnect = locate(params["holopad"]) in holo_calls
|
||||
if(!QDELETED(call_to_disconnect))
|
||||
call_to_disconnect.Disconnect(src)
|
||||
return TRUE
|
||||
if("disk_eject")
|
||||
if(disk && !replay_mode)
|
||||
disk.forceMove(drop_location())
|
||||
disk = null
|
||||
return TRUE
|
||||
if("replay_mode")
|
||||
if(replay_mode)
|
||||
replay_stop()
|
||||
return TRUE
|
||||
else
|
||||
replay_start()
|
||||
return TRUE
|
||||
if("loop_mode")
|
||||
loop_mode = !loop_mode
|
||||
return TRUE
|
||||
if("record_mode")
|
||||
if(record_mode)
|
||||
record_stop()
|
||||
return TRUE
|
||||
else
|
||||
record_start(usr)
|
||||
return TRUE
|
||||
if("record_clear")
|
||||
record_clear()
|
||||
return TRUE
|
||||
if("offset")
|
||||
offset++
|
||||
if(offset > 4)
|
||||
offset = FALSE
|
||||
var/turf/new_turf
|
||||
if(!offset)
|
||||
new_turf = get_turf(src)
|
||||
else
|
||||
new_turf = get_step(src, GLOB.cardinals[offset])
|
||||
replay_holo.forceMove(new_turf)
|
||||
return TRUE
|
||||
if("hang_up")
|
||||
if(outgoing_call)
|
||||
outgoing_call.Disconnect(src)
|
||||
return TRUE
|
||||
|
||||
if(LAZYLEN(holo_calls))
|
||||
dat += "=====================================================<br>"
|
||||
|
||||
if(on_network)
|
||||
var/one_answered_call = FALSE
|
||||
var/one_unanswered_call = FALSE
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
dat += "<a href='?src=[REF(src)];connectcall=[REF(HC)]'>Answer call from [get_area(HC.calling_holopad)]</a><br>"
|
||||
one_unanswered_call = TRUE
|
||||
else
|
||||
one_answered_call = TRUE
|
||||
|
||||
if(one_answered_call && one_unanswered_call)
|
||||
dat += "=====================================================<br>"
|
||||
//we loop twice for formatting
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src)
|
||||
dat += "<a href='?src=[REF(src)];disconnectcall=[REF(HC)]'>Disconnect call from [HC.user]</a><br>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "holopad", name, 300, 175)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
//Stop ringing the AI!!
|
||||
/**
|
||||
* hangup_all_calls: Disconnects all current holocalls from the holopad
|
||||
*/
|
||||
/obj/machinery/holopad/proc/hangup_all_calls()
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
HC.Disconnect(src)
|
||||
|
||||
/obj/machinery/holopad/Topic(href, href_list)
|
||||
if(..() || isAI(usr))
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
if(!is_operational())
|
||||
return
|
||||
if (href_list["AIrequest"])
|
||||
if(last_request + 200 < world.time)
|
||||
last_request = world.time
|
||||
temp = "You requested an AI's presence.<BR>"
|
||||
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
|
||||
var/area/area = get_area(src)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
|
||||
if(!AI.client)
|
||||
continue
|
||||
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
|
||||
else
|
||||
temp = "A request for AI presence was already sent recently.<BR>"
|
||||
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
|
||||
|
||||
else if(href_list["Holocall"])
|
||||
if(outgoing_call)
|
||||
return
|
||||
|
||||
temp = "You must stand on the holopad to make a call!<br>"
|
||||
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
|
||||
if(usr.loc == loc)
|
||||
var/list/callnames = list()
|
||||
for(var/I in GLOB.network_holopads)
|
||||
var/area/A = get_area(I)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
|
||||
if(usr.loc == loc)
|
||||
temp = "Dialing...<br>"
|
||||
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
|
||||
new /datum/holocall(usr, src, callnames[result])
|
||||
|
||||
else if(href_list["connectcall"])
|
||||
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
|
||||
if(!QDELETED(call_to_connect))
|
||||
call_to_connect.Answer(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["disconnectcall"])
|
||||
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
|
||||
if(!QDELETED(call_to_disconnect))
|
||||
call_to_disconnect.Disconnect(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
temp = ""
|
||||
if(outgoing_call)
|
||||
outgoing_call.Disconnect()
|
||||
|
||||
else if(href_list["disk_eject"])
|
||||
if(disk && !replay_mode)
|
||||
disk.forceMove(drop_location())
|
||||
disk = null
|
||||
|
||||
else if(href_list["replay_stop"])
|
||||
replay_stop()
|
||||
else if(href_list["replay_start"])
|
||||
replay_start()
|
||||
else if(href_list["loop_start"])
|
||||
loop_mode = TRUE
|
||||
replay_start()
|
||||
else if(href_list["record_start"])
|
||||
record_start(usr)
|
||||
else if(href_list["record_stop"])
|
||||
record_stop()
|
||||
else if(href_list["record_clear"])
|
||||
record_clear()
|
||||
else if(href_list["offset"])
|
||||
offset++
|
||||
if (offset > 4)
|
||||
offset = FALSE
|
||||
var/turf/new_turf
|
||||
if (!offset)
|
||||
new_turf = get_turf(src)
|
||||
else
|
||||
new_turf = get_step(src, GLOB.cardinals[offset])
|
||||
replay_holo.forceMove(new_turf)
|
||||
updateDialog()
|
||||
|
||||
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
|
||||
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
@@ -366,6 +372,9 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(!secure) //HC.head_call &&
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
HC.Disconnect(src)//can't answer calls while calling
|
||||
else
|
||||
@@ -412,17 +421,17 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
|
||||
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
|
||||
. = ..()
|
||||
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
@@ -449,7 +458,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
else
|
||||
icon_state = "holopad0"
|
||||
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h)
|
||||
LAZYSET(masters, user, h)
|
||||
LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
@@ -504,7 +513,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction)
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
|
||||
if(LAZYLEN(masters) && masters[user])
|
||||
var/obj/effect/overlay/holo_pad_hologram/holo = masters[user]
|
||||
var/transfered = FALSE
|
||||
@@ -516,8 +525,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
transfered = TRUE
|
||||
//All is good.
|
||||
holo.forceMove(new_turf)
|
||||
if(direction)
|
||||
holo.setDir(direction)
|
||||
if(!transfered)
|
||||
update_holoray(user,new_turf)
|
||||
return TRUE
|
||||
@@ -568,22 +575,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(!replay_mode)
|
||||
replay_mode = TRUE
|
||||
replay_holo = setup_replay_holo(disk.record)
|
||||
temp = "Replaying...<br>"
|
||||
temp += "<A href='?src=[REF(src)];offset=1'>Change offset</A><br>"
|
||||
temp += "<A href='?src=[REF(src)];replay_stop=1'>End replay</A>"
|
||||
SetLightsAndPower()
|
||||
replay_entry(1)
|
||||
return
|
||||
|
||||
/obj/machinery/holopad/proc/replay_stop()
|
||||
if(replay_mode)
|
||||
replay_mode = FALSE
|
||||
loop_mode = FALSE
|
||||
offset = FALSE
|
||||
temp = null
|
||||
QDEL_NULL(replay_holo)
|
||||
SetLightsAndPower()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/holopad/proc/record_start(mob/living/user)
|
||||
if(!user || !disk || disk.record)
|
||||
@@ -593,8 +593,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
record_start = world.time
|
||||
record_user = user
|
||||
disk.record.set_caller_image(user)
|
||||
temp = "Recording...<br>"
|
||||
temp += "<A href='?src=[REF(src)];record_stop=1'>End recording.</A>"
|
||||
|
||||
/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language)
|
||||
if(!record_mode)
|
||||
@@ -641,7 +639,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(replay_holo)
|
||||
replay_holo.say(message)
|
||||
if(HOLORECORD_SOUND)
|
||||
playsound(src,entry[2],50,1)
|
||||
playsound(src,entry[2],50,TRUE)
|
||||
if(HOLORECORD_DELAY)
|
||||
addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2])
|
||||
return
|
||||
@@ -660,14 +658,11 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
/obj/machinery/holopad/proc/record_stop()
|
||||
if(record_mode)
|
||||
record_mode = FALSE
|
||||
temp = null
|
||||
record_user = null
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/holopad/proc/record_clear()
|
||||
if(disk && disk.record)
|
||||
QDEL_NULL(disk.record)
|
||||
updateDialog()
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram
|
||||
initial_language_holder = /datum/language_holder/universal
|
||||
|
||||
@@ -6,14 +6,12 @@
|
||||
circuit = /obj/item/circuitboard/machine/hypnochair
|
||||
density = TRUE
|
||||
opacity = 0
|
||||
ui_x = 375
|
||||
ui_y = 480
|
||||
|
||||
var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away
|
||||
var/interrogating = FALSE ///Is the device currently interrogating someone?
|
||||
var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption
|
||||
var/trigger_phrase = "" ///Trigger phrase to implant
|
||||
var/timerid = 0 ///Timer ID for interrogations
|
||||
|
||||
var/message_cooldown = 0 ///Cooldown for breakout message
|
||||
|
||||
/obj/machinery/hypnochair/Initialize()
|
||||
@@ -25,24 +23,24 @@
|
||||
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/hypnochair/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)
|
||||
/obj/machinery/hypnochair/ui_state(mob/user)
|
||||
return GLOB.notcontained_state
|
||||
|
||||
/obj/machinery/hypnochair/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "HypnoChair", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "HypnoChair", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/hypnochair/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? TRUE : FALSE
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["interrogating"] = interrogating
|
||||
|
||||
@@ -201,3 +199,4 @@
|
||||
if(!(L.mobility_flags & MOBILITY_STAND))
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
/obj/machinery/iv_drip
|
||||
name = "\improper IV drip"
|
||||
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate."
|
||||
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. Alt-Click to change the transfer rate."
|
||||
icon = 'icons/obj/iv_drip.dmi'
|
||||
icon_state = "iv_drip"
|
||||
anchored = FALSE
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
|
||||
var/mob/living/carbon/attached
|
||||
var/mode = IV_INJECTING
|
||||
var/dripfeed = FALSE
|
||||
var/obj/item/reagent_containers/beaker
|
||||
var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood,
|
||||
/obj/item/reagent_containers/food,
|
||||
@@ -132,9 +133,11 @@
|
||||
if(mode)
|
||||
if(beaker.reagents.total_volume)
|
||||
var/transfer_amount = 5
|
||||
if (dripfeed)
|
||||
transfer_amount = 1
|
||||
if(istype(beaker, /obj/item/reagent_containers/blood))
|
||||
// speed up transfer on blood packs
|
||||
transfer_amount = 10
|
||||
transfer_amount *= 2
|
||||
var/fraction = min(transfer_amount/beaker.reagents.total_volume, 1) //the fraction that is transfered of the total volume
|
||||
beaker.reagents.reaction(attached, INJECT, fraction, FALSE) //make reagents reacts, but don't spam messages
|
||||
beaker.reagents.trans_to(attached, transfer_amount)
|
||||
@@ -169,6 +172,16 @@
|
||||
else
|
||||
toggle_mode()
|
||||
|
||||
/obj/machinery/iv_drip/AltClick(mob/living/user)
|
||||
if(!user.canUseTopic(src, be_close=TRUE))
|
||||
return
|
||||
if(dripfeed)
|
||||
dripfeed = FALSE
|
||||
to_chat(usr, "<span class='notice'>You loosen the valve to speed up the [src].</span>")
|
||||
else
|
||||
dripfeed = TRUE
|
||||
to_chat(usr, "<span class='notice'>You tighten the valve to slowly drip-feed the contents of [src].</span>")
|
||||
|
||||
/obj/machinery/iv_drip/attack_robot(mob/user)
|
||||
if(Adjacent(user))
|
||||
attack_hand(user)
|
||||
@@ -227,7 +240,7 @@
|
||||
|
||||
/obj/machinery/iv_drip/telescopic
|
||||
name = "telescopic IV drip"
|
||||
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down."
|
||||
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down.Alt-Click with a beaker attached to change the transfer rate."
|
||||
icon_state = "iv_drip"
|
||||
|
||||
/obj/machinery/iv_drip/telescopic/update_icon_state()
|
||||
|
||||
@@ -282,12 +282,14 @@
|
||||
ui_interact(user)
|
||||
to_chat(user, "<span class='notice'>[src] projects a display onto your retina.</span>")
|
||||
|
||||
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", 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, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
|
||||
ui.open()
|
||||
/obj/item/launchpad_remote/ui_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/obj/item/launchpad_remote/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "LaunchpadRemote")
|
||||
ui.open()
|
||||
ui.set_autoupdate(TRUE)
|
||||
|
||||
/obj/item/launchpad_remote/ui_data(mob/user)
|
||||
|
||||
@@ -38,3 +38,14 @@
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
drive()
|
||||
|
||||
/obj/machinery/mass_driver/pressure_plate
|
||||
name = "pressure plated mass driver"
|
||||
var/drive_delay = 10
|
||||
|
||||
/obj/machinery/mass_driver/pressure_plate/Crossed(atom/movable/O)
|
||||
. = ..()
|
||||
if(isliving(O))
|
||||
var/mob/living/L = O
|
||||
to_chat(L, "<span class='warning'>You feel something click beneath you!</span>")
|
||||
addtimer(CALLBACK(src, .proc/drive), drive_delay)
|
||||
@@ -4,6 +4,15 @@
|
||||
#define POPUP_ANIM_TIME 5
|
||||
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
|
||||
|
||||
#define TURRET_FLAG_SHOOT_ALL_REACT (1<<0) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
#define TURRET_FLAG_AUTH_WEAPONS (1<<1) // Checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
#define TURRET_FLAG_SHOOT_CRIMINALS (1<<2) // Checks if it can shoot people that are wanted
|
||||
#define TURRET_FLAG_SHOOT_ALL (1<<3) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
#define TURRET_FLAG_SHOOT_ANOMALOUS (1<<4) // Checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
#define TURRET_FLAG_SHOOT_UNSHIELDED (1<<5) // Checks if it can shoot people that aren't mindshielded and who arent heads
|
||||
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
|
||||
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
|
||||
|
||||
/obj/machinery/porta_turret
|
||||
name = "turret"
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
@@ -15,70 +24,79 @@
|
||||
use_power = IDLE_POWER_USE //this turret uses and requires power
|
||||
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
|
||||
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
|
||||
req_access = list(ACCESS_SEC_DOORS)
|
||||
req_access = list(ACCESS_SECURITY) /// Only people with Security access
|
||||
power_channel = EQUIP //drains power from the EQUIPMENT channel
|
||||
speed_process = TRUE
|
||||
|
||||
var/base_icon_state = "standard"
|
||||
var/scan_range = 7
|
||||
var/atom/base = null //for turrets inside other objects
|
||||
|
||||
var/raised = 0 //if the turret cover is "open" and the turret is raised
|
||||
var/raising= 0 //if the turret is currently opening or closing its cover
|
||||
|
||||
max_integrity = 160 //the turret's health
|
||||
integrity_failure = 0.5
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
var/locked = TRUE //if the turret's behaviour control access is locked
|
||||
var/controllock = FALSE //if the turret responds to control panels
|
||||
|
||||
var/installation = /obj/item/gun/energy/e_gun/turret //the type of weapon installed by default
|
||||
/// Base turret icon state
|
||||
var/base_icon_state = "standard"
|
||||
/// Scan range of the turret for locating targets
|
||||
var/scan_range = 7
|
||||
/// For turrets inside other objects
|
||||
var/atom/base = null
|
||||
/// If the turret cover is "open" and the turret is raised
|
||||
var/raised = FALSE
|
||||
/// If the turret is currently opening or closing its cover
|
||||
var/raising = FALSE
|
||||
/// If the turret's behaviour control access is locked
|
||||
var/locked = TRUE
|
||||
/// If the turret responds to control panels
|
||||
var/controllock = FALSE
|
||||
/// The type of weapon installed by default
|
||||
var/installation = /obj/item/gun/energy/e_gun/turret
|
||||
/// What stored gun is in the turret
|
||||
var/obj/item/gun/stored_gun = null
|
||||
var/gun_charge = 0 //the charge of the gun when retrieved from wreckage
|
||||
|
||||
/// The charge of the gun when retrieved from wreckage
|
||||
var/gun_charge = 0
|
||||
/// In which mode is turret in, stun or lethal
|
||||
var/mode = TURRET_STUN
|
||||
|
||||
var/stun_projectile = null //stun mode projectile type
|
||||
/// Stun mode projectile type
|
||||
var/stun_projectile = null
|
||||
/// Sound of stun projectile
|
||||
var/stun_projectile_sound
|
||||
var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any
|
||||
/// Projectile to use in stun mode when the target is resting, if any
|
||||
var/nonlethal_projectile
|
||||
/// Sound of stun projectile wen the target is resting, optional
|
||||
var/nonlethal_projectile_sound
|
||||
var/lethal_projectile = null //lethal mode projectile type
|
||||
/// Lethal mode projectile type
|
||||
var/lethal_projectile = null
|
||||
/// Sound of lethal projectile
|
||||
var/lethal_projectile_sound
|
||||
|
||||
var/reqpower = 500 //power needed per shot
|
||||
var/always_up = 0 //Will stay active
|
||||
var/has_cover = 1 //Hides the cover
|
||||
|
||||
var/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret
|
||||
|
||||
var/last_fired = 0 //world.time the turret last fired
|
||||
var/shot_delay = 15 //ticks until next shot (1.5 ?)
|
||||
var/shot_stagger = 0 // sleep() shots to stagger attacks
|
||||
|
||||
var/check_records = 1 //checks if it can use the security records
|
||||
var/criminals = 1 //checks if it can shoot people on arrest
|
||||
var/auth_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/stun_all = 0 //if this is active, the turret shoots everything that isn't security or head of staff
|
||||
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/shoot_unloyal = 0 //checks if it can shoot people that aren't loyalty implantd
|
||||
|
||||
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
|
||||
var/on = TRUE //determines if the turret is on
|
||||
|
||||
var/list/faction = list("turret") // Same faction mobs will never be shot at, no matter the other settings
|
||||
|
||||
var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks?
|
||||
|
||||
/// Power needed per shot
|
||||
var/reqpower = 500
|
||||
/// Will stay active
|
||||
var/always_up = FALSE
|
||||
/// Hides the cover
|
||||
var/has_cover = TRUE
|
||||
/// The cover that is covering this turret
|
||||
var/obj/machinery/porta_turret_cover/cover = null
|
||||
/// World.time the turret last fired
|
||||
var/last_fired = 0
|
||||
/// Ticks until next shot (1.5 ?)
|
||||
var/shot_delay = 15
|
||||
/// Turret flags about who is turret allowed to shoot
|
||||
var/turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS
|
||||
/// Determines if the turret is on
|
||||
var/on = TRUE
|
||||
/// Same faction mobs will never be shot at, no matter the other settings
|
||||
var/list/faction = list("turret")
|
||||
/// The spark system, used for generating... sparks?
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
/// Linked turret control panel of the turret
|
||||
var/obj/machinery/turretid/cp = null
|
||||
|
||||
var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall
|
||||
|
||||
var/manual_control = FALSE //
|
||||
/// The turret will try to shoot from a turf in that direction when in a wall
|
||||
var/wall_turret_direction
|
||||
/// If the turret is manually controlled
|
||||
var/manual_control = FALSE
|
||||
/// Action button holder for quitting manual control
|
||||
var/datum/action/turret_quit/quit_action
|
||||
/// Action button holder for switching between turret modes when manually controlling
|
||||
var/datum/action/turret_toggle/toggle_action
|
||||
/// Mob that is remotely controlling the turret
|
||||
var/mob/remote_controller
|
||||
/// MISSING:
|
||||
var/shot_stagger = 0
|
||||
|
||||
/obj/machinery/porta_turret/Initialize()
|
||||
. = ..()
|
||||
@@ -100,6 +118,27 @@
|
||||
if(!has_cover)
|
||||
INVOKE_ASYNC(src, .proc/popUp)
|
||||
|
||||
/obj/machinery/porta_turret/proc/toggle_on(var/set_to)
|
||||
var/current = on
|
||||
if (!isnull(set_to))
|
||||
on = set_to
|
||||
else
|
||||
on = !on
|
||||
if (current != on)
|
||||
check_should_process()
|
||||
if (!on)
|
||||
popDown()
|
||||
|
||||
/obj/machinery/porta_turret/proc/check_should_process()
|
||||
if (datum_flags & DF_ISPROCESSING)
|
||||
if (!on || !anchored || (stat & BROKEN) || !powered())
|
||||
//end_processing()
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
else
|
||||
if (on && anchored && !(stat & BROKEN) && powered())
|
||||
START_PROCESSING(SSmachines, src)
|
||||
//begin_processing()
|
||||
|
||||
/obj/machinery/porta_turret/update_icon_state()
|
||||
if(!anchored)
|
||||
icon_state = "turretCover"
|
||||
@@ -119,7 +158,6 @@
|
||||
else
|
||||
icon_state = "[base_icon_state]_unpowered"
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun)
|
||||
if(stored_gun)
|
||||
qdel(stored_gun)
|
||||
@@ -160,83 +198,88 @@
|
||||
remove_control()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat
|
||||
dat += "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a><br>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<br>"
|
||||
/obj/machinery/porta_turret/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PortableTurret", name)
|
||||
ui.open()
|
||||
|
||||
if(!locked)
|
||||
dat += "Check for Weapon Authorization: <A href='?src=[REF(src)];operation=authweapon'>[auth_weapons ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Check Security Records: <A href='?src=[REF(src)];operation=checkrecords'>[check_records ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize Identified Criminals: <A href='?src=[REF(src)];operation=shootcrooks'>[criminals ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Non-Security and Non-Command Personnel: <A href='?src=[REF(src)];operation=shootall'>[stun_all ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Unidentified Life Signs: <A href='?src=[REF(src)];operation=checkxenos'>[check_anomalies ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Non-Loyalty Implanted Personnel: <A href='?src=[REF(src)];operation=checkloyal'>[shoot_unloyal ? "Yes" : "No"]</A><BR>"
|
||||
/obj/machinery/porta_turret/ui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"locked" = locked,
|
||||
"on" = on,
|
||||
"check_weapons" = turret_flags & TURRET_FLAG_AUTH_WEAPONS,
|
||||
"neutralize_criminals" = turret_flags & TURRET_FLAG_SHOOT_CRIMINALS,
|
||||
"neutralize_all" = turret_flags & TURRET_FLAG_SHOOT_ALL,
|
||||
"neutralize_unidentified" = turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS,
|
||||
"neutralize_nonmindshielded" = turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED,
|
||||
"neutralize_cyborgs" = turret_flags & TURRET_FLAG_SHOOT_BORGS,
|
||||
"ignore_heads" = turret_flags & TURRET_FLAG_SHOOT_HEADS,
|
||||
"manual_control" = manual_control,
|
||||
"silicon_user" = FALSE,
|
||||
"allow_manual_control" = FALSE,
|
||||
"lasertag_turret" = istype(src, /obj/machinery/porta_turret/lasertag),
|
||||
)
|
||||
if(issilicon(user))
|
||||
data["silicon_user"] = TRUE
|
||||
if(!manual_control)
|
||||
var/mob/living/silicon/S = user
|
||||
if(S.hack_software)
|
||||
dat += "Assume direct control : <a href='?src=[REF(src)];operation=manual'>Manual Control</a><br>"
|
||||
else
|
||||
dat += "Warning! Remote control protocol enabled.<br>"
|
||||
data["allow_manual_control"] = TRUE
|
||||
return data
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/porta_turret/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["power"] && !locked)
|
||||
if(anchored) //you can't turn a turret on/off if it's not anchored/secured
|
||||
on = !on //toggle on/off
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>It has to be secured first!</span>")
|
||||
interact(usr)
|
||||
/obj/machinery/porta_turret/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"]) //toggles customizable behavioural protocols
|
||||
if("authweapon")
|
||||
auth_weapons = !auth_weapons
|
||||
if("checkrecords")
|
||||
check_records = !check_records
|
||||
if("shootcrooks")
|
||||
criminals = !criminals
|
||||
if("shootall")
|
||||
stun_all = !stun_all
|
||||
if("checkxenos")
|
||||
check_anomalies = !check_anomalies
|
||||
if("checkloyal")
|
||||
shoot_unloyal = !shoot_unloyal
|
||||
if("manual")
|
||||
if(issilicon(usr) && !manual_control)
|
||||
give_control(usr)
|
||||
interact(usr)
|
||||
switch(action)
|
||||
if("power")
|
||||
if(anchored)
|
||||
toggle_on()
|
||||
return TRUE
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>It has to be secured first!</span>")
|
||||
if("authweapon")
|
||||
turret_flags ^= TURRET_FLAG_AUTH_WEAPONS
|
||||
return TRUE
|
||||
if("shootcriminals")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_CRIMINALS
|
||||
return TRUE
|
||||
if("shootall")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_ALL
|
||||
return TRUE
|
||||
if("checkxenos")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_ANOMALOUS
|
||||
return TRUE
|
||||
if("checkloyal")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_UNSHIELDED
|
||||
return TRUE
|
||||
if("shootborgs")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_BORGS
|
||||
return TRUE
|
||||
if("shootheads")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_HEADS
|
||||
return TRUE
|
||||
if("manual")
|
||||
if(!issilicon(usr))
|
||||
return
|
||||
give_control(usr)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/porta_turret/ui_host(mob/user)
|
||||
if(has_cover && cover)
|
||||
return cover
|
||||
if(base)
|
||||
return base
|
||||
return src
|
||||
|
||||
/obj/machinery/porta_turret/power_change()
|
||||
if(!anchored)
|
||||
. = ..()
|
||||
if(!anchored || (stat & BROKEN) || !powered())
|
||||
update_icon()
|
||||
remove_control()
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
update_icon()
|
||||
remove_control()
|
||||
else
|
||||
if( powered() )
|
||||
stat &= ~NOPOWER
|
||||
update_icon()
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
stat |= NOPOWER
|
||||
remove_control()
|
||||
update_icon()
|
||||
|
||||
check_should_process()
|
||||
|
||||
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
|
||||
if(stat & BROKEN)
|
||||
@@ -284,8 +327,10 @@
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
to_chat(user, "<span class='alert'>Access denied.</span>")
|
||||
else if(istype(I, /obj/item/multitool) && !locked)
|
||||
if(!multitool_check_buffer(user, I))
|
||||
return
|
||||
var/obj/item/multitool/M = I
|
||||
M.buffer = src
|
||||
to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>")
|
||||
@@ -293,19 +338,17 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>")
|
||||
visible_message("[src] hums oddly...")
|
||||
audible_message("<span class='hear'>[src] hums oddly...</span>")
|
||||
obj_flags |= EMAGGED
|
||||
controllock = TRUE
|
||||
on = FALSE //turns off the turret temporarily
|
||||
toggle_on(FALSE) //turns off the turret temporarily
|
||||
update_icon()
|
||||
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
|
||||
on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
|
||||
return TRUE
|
||||
|
||||
//6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 6 SECONDS)
|
||||
//turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
|
||||
|
||||
/obj/machinery/porta_turret/emp_act(severity)
|
||||
. = ..()
|
||||
@@ -314,63 +357,41 @@
|
||||
if(on)
|
||||
//if the turret is on, the EMP no matter how severe disables the turret for a while
|
||||
//and scrambles its settings, with a slight chance of having an emag effect
|
||||
check_records = pick(0, 1)
|
||||
criminals = pick(0, 1)
|
||||
auth_weapons = pick(0, 1)
|
||||
stun_all = pick(0, 0, 0, 0, 1) //stun_all is a pretty big deal, so it's least likely to get turned on
|
||||
if(prob(50))
|
||||
turret_flags |= TURRET_FLAG_SHOOT_CRIMINALS
|
||||
if(prob(50))
|
||||
turret_flags |= TURRET_FLAG_AUTH_WEAPONS
|
||||
if(prob(20))
|
||||
turret_flags |= TURRET_FLAG_SHOOT_ALL // Shooting everyone is a pretty big deal, so it's least likely to get turned on
|
||||
|
||||
on = FALSE
|
||||
toggle_on(FALSE)
|
||||
remove_control()
|
||||
|
||||
spawn(rand(60,600))
|
||||
if(!on)
|
||||
on = TRUE
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), rand(60,600))
|
||||
|
||||
/obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
|
||||
. = ..()
|
||||
if(.) //damage received
|
||||
if(. && obj_integrity > 0) //damage received
|
||||
if(prob(30))
|
||||
spark_system.start()
|
||||
if(on && !attacked && !(obj_flags & EMAGGED))
|
||||
attacked = TRUE
|
||||
if(on && !(turret_flags & TURRET_FLAG_SHOOT_ALL_REACT) && !(obj_flags & EMAGGED))
|
||||
turret_flags |= TURRET_FLAG_SHOOT_ALL_REACT
|
||||
addtimer(CALLBACK(src, .proc/reset_attacked), 60)
|
||||
|
||||
/obj/machinery/porta_turret/proc/reset_attacked()
|
||||
attacked = FALSE
|
||||
turret_flags &= ~TURRET_FLAG_SHOOT_ALL_REACT
|
||||
|
||||
/obj/machinery/porta_turret/deconstruct(disassembled = TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/porta_turret/obj_break(damage_flag)
|
||||
if(!(flags_1 & NODECONSTRUCT_1) && !(stat & BROKEN))
|
||||
stat |= BROKEN //enables the BROKEN bit
|
||||
. = ..()
|
||||
if(.)
|
||||
power_change()
|
||||
invisibility = 0
|
||||
spark_system.start() //creates some sparks because they look cool
|
||||
qdel(cover) //deletes the cover - no need on keeping it there!
|
||||
|
||||
//turret healing
|
||||
/obj/machinery/porta_turret/examine(mob/user)
|
||||
. = ..()
|
||||
if(obj_integrity < max_integrity)
|
||||
. += "<span class='notice'>Use a welder to fix it.</span>"
|
||||
|
||||
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(obj_integrity < max_integrity)
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return
|
||||
user.visible_message("[user] is welding the turret.", \
|
||||
"<span class='notice'>You begin repairing the turret...</span>", \
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
if(I.use_tool(src, user, 40, volume=50))
|
||||
obj_integrity = max_integrity
|
||||
user.visible_message("[user.name] has repaired [src].", \
|
||||
"<span class='notice'>You finish repairing the turret.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/process()
|
||||
//the main machinery process
|
||||
if(cover == null && anchored) //if it has no cover and is anchored
|
||||
@@ -382,35 +403,43 @@
|
||||
cover.parent_turret = src //assign the cover its parent_turret, which would be this (src)
|
||||
|
||||
if(!on || (stat & (NOPOWER|BROKEN)) || manual_control)
|
||||
return
|
||||
return PROCESS_KILL
|
||||
|
||||
var/list/targets = list()
|
||||
for(var/mob/A in view(scan_range, base))
|
||||
if(A.invisibility > SEE_INVISIBLE_LIVING)
|
||||
continue
|
||||
|
||||
if(check_anomalies)//if it's set to check for simple animals
|
||||
if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS)//if it's set to check for simple animals
|
||||
if(isanimal(A))
|
||||
var/mob/living/simple_animal/SA = A
|
||||
if(SA.stat || in_faction(SA)) //don't target if dead or in faction
|
||||
continue
|
||||
targets += SA
|
||||
if(issilicon(A))
|
||||
var/mob/living/silicon/sillycone = A
|
||||
if(sillycone.stat || in_faction(sillycone))
|
||||
continue
|
||||
|
||||
if(issilicon(A))
|
||||
var/mob/living/silicon/sillycone = A
|
||||
|
||||
if(ispAI(A))
|
||||
continue
|
||||
|
||||
if((turret_flags & TURRET_FLAG_SHOOT_BORGS) && sillycone.stat != DEAD && iscyborg(sillycone))
|
||||
targets += sillycone
|
||||
continue
|
||||
|
||||
if(sillycone.stat || in_faction(sillycone))
|
||||
continue
|
||||
|
||||
if(iscyborg(sillycone))
|
||||
var/mob/living/silicon/robot/sillyconerobot = A
|
||||
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
|
||||
continue
|
||||
|
||||
if(iscyborg(sillycone))
|
||||
var/mob/living/silicon/robot/sillyconerobot = A
|
||||
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
|
||||
continue
|
||||
|
||||
targets += sillycone
|
||||
|
||||
if(iscarbon(A))
|
||||
else if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
//If not emagged, only target non downed carbons
|
||||
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam
|
||||
//If not emagged, only target carbons that can use items
|
||||
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE)))
|
||||
continue
|
||||
|
||||
//If emagged, target all but dead carbons
|
||||
@@ -419,12 +448,13 @@
|
||||
|
||||
//if the target is a human and not in our faction, analyze threat level
|
||||
if(ishuman(C) && !in_faction(C))
|
||||
|
||||
if(assess_perp(C) >= 4)
|
||||
targets += C
|
||||
|
||||
else if(check_anomalies) //non humans who are not simple animals (xenos etc)
|
||||
else if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) //non humans who are not simple animals (xenos etc)
|
||||
if(!in_faction(C))
|
||||
targets += C
|
||||
|
||||
for(var/A in GLOB.mechas_list)
|
||||
if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range))
|
||||
var/obj/mecha/Mech = A
|
||||
@@ -432,6 +462,10 @@
|
||||
if(assess_perp(Mech.occupant) >= 4)
|
||||
targets += Mech
|
||||
|
||||
if((turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) && GLOB.blobs.len && (mode == TURRET_LETHAL))
|
||||
for(var/obj/structure/blob/B in view(scan_range, base))
|
||||
targets += B
|
||||
|
||||
if(targets.len)
|
||||
tryToShootAt(targets)
|
||||
else if(!always_up)
|
||||
@@ -488,36 +522,37 @@
|
||||
if(obj_flags & EMAGGED)
|
||||
return 10 //if emagged, always return 10.
|
||||
|
||||
if((stun_all || attacked) && !allowed(perp))
|
||||
if((turret_flags & (TURRET_FLAG_SHOOT_ALL | TURRET_FLAG_SHOOT_ALL_REACT)) && !allowed(perp))
|
||||
//if the turret has been attacked or is angry, target all non-sec people
|
||||
if(!allowed(perp))
|
||||
return 10
|
||||
|
||||
if(auth_weapons) //check for weapon authorization
|
||||
if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization
|
||||
if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/card/id/syndicate))
|
||||
|
||||
if(allowed(perp)) //if the perp has security access, return 0
|
||||
return 0
|
||||
|
||||
if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton))
|
||||
threatcount += 4
|
||||
|
||||
if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton))
|
||||
threatcount += 2
|
||||
|
||||
if(check_records) //if the turret can check the records, check if they are set to *Arrest* on records
|
||||
if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records
|
||||
var/perpname = perp.get_face_name(perp.get_id_name())
|
||||
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
|
||||
if(!R || (R.fields["criminal"] == "*Arrest*"))
|
||||
threatcount += 4
|
||||
|
||||
if(shoot_unloyal)
|
||||
if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD))
|
||||
threatcount += 4
|
||||
if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
|
||||
threatcount += 4
|
||||
|
||||
// If we aren't shooting heads then return a threatcount of 0
|
||||
if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS) && (perp.get_assignment() in GLOB.command_positions))
|
||||
return 0
|
||||
|
||||
return threatcount
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/proc/in_faction(mob/target)
|
||||
for(var/faction1 in faction)
|
||||
if(faction1 in target.faction)
|
||||
@@ -533,16 +568,16 @@
|
||||
return
|
||||
|
||||
/obj/machinery/porta_turret/proc/shootAt(atom/movable/target, stagger_enabled = FALSE)
|
||||
if(stagger_enabled)
|
||||
randomize_shot_stagger()
|
||||
sleep(shot_stagger)
|
||||
if(!raised) //the turret has to be raised in order to fire - makes sense, right?
|
||||
return
|
||||
|
||||
if(!(obj_flags & EMAGGED)) //if it hasn't been emagged, cooldown before shooting again
|
||||
if(last_fired + shot_delay > world.time)
|
||||
return
|
||||
last_fired = world.time
|
||||
if(last_fired + shot_delay > world.time)
|
||||
return
|
||||
last_fired = world.time
|
||||
|
||||
if(stagger_enabled)
|
||||
randomize_shot_stagger()
|
||||
sleep(shot_stagger)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/U = get_turf(target)
|
||||
@@ -563,15 +598,14 @@
|
||||
T = closer
|
||||
break
|
||||
|
||||
var/mob/living/carbon/C
|
||||
if(iscarbon(target))
|
||||
C = target
|
||||
|
||||
update_icon()
|
||||
var/obj/item/projectile/A
|
||||
//any emagged turrets drains 2x power and uses a different projectile?
|
||||
if(mode == TURRET_STUN)
|
||||
if(nonlethal_projectile && C && C.resting)
|
||||
var/mob/living/carbon/C = null
|
||||
if(iscarbon(target))
|
||||
C = target
|
||||
if(nonlethal_projectile && C?.resting)
|
||||
use_power(reqpower*0.5)
|
||||
A = new nonlethal_projectile(T)
|
||||
playsound(loc, nonlethal_projectile_sound, 75, 1)
|
||||
@@ -582,7 +616,7 @@
|
||||
else
|
||||
use_power(reqpower * 2)
|
||||
A = new lethal_projectile(T)
|
||||
playsound(loc, lethal_projectile_sound, 75, 1)
|
||||
playsound(loc, lethal_projectile_sound, 75, TRUE)
|
||||
|
||||
|
||||
//Shooting Code:
|
||||
@@ -592,16 +626,15 @@
|
||||
A.fire()
|
||||
return A
|
||||
|
||||
/obj/machinery/porta_turret/proc/setState(on, mode)
|
||||
/obj/machinery/porta_turret/proc/setState(on, mode, shoot_cyborgs)
|
||||
if(controllock)
|
||||
return
|
||||
src.on = on
|
||||
if(!on)
|
||||
popDown()
|
||||
|
||||
shoot_cyborgs ? (turret_flags |= TURRET_FLAG_SHOOT_BORGS) : (turret_flags &= ~TURRET_FLAG_SHOOT_BORGS)
|
||||
toggle_on(on)
|
||||
src.mode = mode
|
||||
power_change()
|
||||
|
||||
|
||||
/datum/action/turret_toggle
|
||||
name = "Toggle Mode"
|
||||
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
|
||||
@@ -685,7 +718,15 @@
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
// AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) //this one or ^ one?
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/setup()
|
||||
return
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
|
||||
return 10 //Syndicate turrets shoot everything not in their faction
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/energy
|
||||
icon_state = "standard_stun"
|
||||
@@ -698,7 +739,6 @@
|
||||
lethal_projectile_sound = 'sound/weapons/laser.ogg'
|
||||
desc = "An energy blaster auto-turret."
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/energy/heavy
|
||||
icon_state = "standard_stun"
|
||||
base_icon_state = "standard"
|
||||
@@ -715,14 +755,13 @@
|
||||
integrity_failure = 0.08
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/setup()
|
||||
return
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
|
||||
return 10 //Syndicate turrets shoot everything not in their faction
|
||||
/obj/machinery/porta_turret/syndicate/energy/raven
|
||||
stun_projectile = /obj/item/projectile/beam/laser
|
||||
stun_projectile_sound = 'sound/weapons/laser.ogg'
|
||||
faction = list("neutral","silicon","turret")
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/pod
|
||||
integrity_failure = 0.5
|
||||
max_integrity = 40
|
||||
stun_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
@@ -749,6 +788,7 @@
|
||||
faction = list("silicon")
|
||||
nonlethal_projectile = /obj/item/projectile/beam/disabler
|
||||
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
|
||||
turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS | TURRET_FLAG_SHOOT_HEADS
|
||||
|
||||
/obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp)
|
||||
return 10 //AI turrets shoot at everything not in their faction
|
||||
@@ -804,6 +844,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/weak
|
||||
max_integrity = 120
|
||||
integrity_failure = 0.5
|
||||
name = "Old Laser Turret"
|
||||
desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else."
|
||||
stun_projectile = /obj/item/projectile/beam/weak/penetrator
|
||||
@@ -817,7 +858,6 @@
|
||||
stun_projectile_sound = 'sound/weapons/gunshot.ogg'
|
||||
desc = "A ballistic machine gun auto-turret."
|
||||
|
||||
|
||||
////////////////////////
|
||||
//Turret Control Panel//
|
||||
////////////////////////
|
||||
@@ -828,14 +868,22 @@
|
||||
icon = 'icons/obj/machines/turret_control.dmi'
|
||||
icon_state = "control_standby"
|
||||
density = FALSE
|
||||
var/enabled = 1
|
||||
var/lethal = 0
|
||||
var/locked = TRUE
|
||||
var/control_area = null //can be area name, path or nothing.
|
||||
var/ailock = 0 // AI cannot use this
|
||||
req_access = list(ACCESS_AI_UPLOAD)
|
||||
var/list/obj/machinery/porta_turret/turrets = list()
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
/// Variable dictating if linked turrets are active and will shoot targets
|
||||
var/enabled = TRUE
|
||||
/// Variable dictating if linked turrets will shoot lethal projectiles
|
||||
var/lethal = FALSE
|
||||
/// Variable dictating if the panel is locked, preventing changes to turret settings
|
||||
var/locked = TRUE
|
||||
/// An area in which linked turrets are located, it can be an area name, path or nothing
|
||||
var/control_area = null
|
||||
/// AI is unable to use this machine if set to TRUE
|
||||
var/ailock = FALSE
|
||||
/// Variable dictating if linked turrets will shoot cyborgs
|
||||
var/shoot_cyborgs = FALSE
|
||||
/// List of all linked turrets
|
||||
var/list/turrets = list()
|
||||
|
||||
/obj/machinery/turretid/Initialize(mapload, ndir = 0, built = 0)
|
||||
. = ..()
|
||||
@@ -868,112 +916,111 @@
|
||||
T.cp = src
|
||||
|
||||
/obj/machinery/turretid/examine(mob/user)
|
||||
. = ..()
|
||||
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
|
||||
. += "<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>"
|
||||
. += "<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"
|
||||
. += ..()
|
||||
if(issilicon(user) && !(stat & BROKEN))
|
||||
. += {"<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>
|
||||
<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"}
|
||||
|
||||
/obj/machinery/turretid/attackby(obj/item/I, mob/user, params)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if (istype(I, /obj/item/multitool))
|
||||
if(!multitool_check_buffer(user, I))
|
||||
return
|
||||
var/obj/item/multitool/M = I
|
||||
if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret))
|
||||
turrets |= M.buffer
|
||||
to_chat(user, "You link \the [M.buffer] with \the [src]")
|
||||
to_chat(user, "<span class='notice'>You link \the [M.buffer] with \the [src].</span>")
|
||||
return
|
||||
|
||||
if (hasSiliconAccessInArea(user))
|
||||
if (issilicon(user))
|
||||
return attack_hand(user)
|
||||
|
||||
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
|
||||
if (allowed(usr))
|
||||
if(obj_flags & EMAGGED)
|
||||
to_chat(user, "<span class='notice'>The turret control is unresponsive.</span>")
|
||||
to_chat(user, "<span class='warning'>The turret control is unresponsive!</span>")
|
||||
return
|
||||
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the panel.</span>")
|
||||
if (locked)
|
||||
if (user.machine==src)
|
||||
user.unset_machine()
|
||||
user << browse(null, "window=turretid")
|
||||
else
|
||||
if (user.machine==src)
|
||||
attack_hand(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
to_chat(user, "<span class='alert'>Access denied.</span>")
|
||||
|
||||
/obj/machinery/turretid/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
to_chat(user, "<span class='danger'>You short out the turret controls' access analysis module.</span>")
|
||||
to_chat(user, "<span class='notice'>You short out the turret controls' access analysis module.</span>")
|
||||
obj_flags |= EMAGGED
|
||||
locked = FALSE
|
||||
if(user && user.machine == src)
|
||||
attack_hand(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/turretid/attack_ai(mob/user)
|
||||
if(!ailock || IsAdminGhost(user))
|
||||
return attack_hand(user)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
|
||||
to_chat(user, "<span class='warning'>There seems to be a firewall preventing you from accessing this device!</span>")
|
||||
|
||||
/obj/machinery/turretid/ui_interact(mob/user)
|
||||
/obj/machinery/turretid/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "TurretControl", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/turretid/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["locked"] = locked
|
||||
data["siliconUser"] = hasSiliconAccessInArea(user) || IsAdminGhost(user)
|
||||
data["enabled"] = enabled
|
||||
data["lethal"] = lethal
|
||||
data["shootCyborgs"] = shoot_cyborgs
|
||||
return data
|
||||
|
||||
/obj/machinery/turretid/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if ( get_dist(src, user) > 0 )
|
||||
if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) )
|
||||
to_chat(user, "<span class='notice'>You are too far away.</span>")
|
||||
user.unset_machine()
|
||||
user << browse(null, "window=turretid")
|
||||
return
|
||||
|
||||
var/t = ""
|
||||
|
||||
if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user)))
|
||||
t += "<div class='notice icon'>Swipe ID card to unlock interface</div>"
|
||||
else
|
||||
if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user))
|
||||
t += "<div class='notice icon'>Swipe ID card to lock interface</div>"
|
||||
t += "Turrets [enabled?"activated":"deactivated"] - <A href='?src=[REF(src)];toggleOn=1'>[enabled?"Disable":"Enable"]?</a><br>"
|
||||
t += "Currently set for [lethal?"lethal":"stun repeatedly"] - <A href='?src=[REF(src)];toggleLethal=1'>Change to [lethal?"Stun repeatedly":"Lethal"]?</a><br>"
|
||||
|
||||
var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([get_area_name(src, TRUE)])")
|
||||
popup.set_content(t)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/turretid/Topic(href, href_list)
|
||||
if(..())
|
||||
if(.)
|
||||
return
|
||||
if (locked)
|
||||
if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
|
||||
to_chat(usr, "Control panel is locked!")
|
||||
return
|
||||
if (href_list["toggleOn"])
|
||||
toggle_on()
|
||||
else if (href_list["toggleLethal"])
|
||||
toggle_lethal()
|
||||
attack_hand(usr)
|
||||
|
||||
/obj/machinery/turretid/proc/toggle_lethal()
|
||||
switch(action)
|
||||
if("lock")
|
||||
if(!hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
|
||||
return
|
||||
if((obj_flags & EMAGGED) || (stat & BROKEN))
|
||||
to_chat(usr, "<span class='warning'>The turret control is unresponsive!</span>")
|
||||
return
|
||||
locked = !locked
|
||||
return TRUE
|
||||
if("power")
|
||||
toggle_on(usr)
|
||||
return TRUE
|
||||
if("mode")
|
||||
toggle_lethal(usr)
|
||||
return TRUE
|
||||
if("shoot_silicons")
|
||||
shoot_silicons(usr)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/turretid/proc/toggle_lethal(mob/user)
|
||||
lethal = !lethal
|
||||
add_hiddenprint(user)
|
||||
log_combat(user, src, "[lethal ? "enabled" : "disabled"] lethals on")
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/proc/toggle_on()
|
||||
/obj/machinery/turretid/proc/toggle_on(mob/user)
|
||||
enabled = !enabled
|
||||
add_hiddenprint(user)
|
||||
log_combat(user, src, "[enabled ? "enabled" : "disabled"]")
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/proc/shoot_silicons(mob/user)
|
||||
shoot_cyborgs = !shoot_cyborgs
|
||||
add_hiddenprint(user)
|
||||
log_combat(user, src, "[shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs"]")
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/proc/updateTurrets()
|
||||
for (var/obj/machinery/porta_turret/aTurret in turrets)
|
||||
aTurret.setState(enabled, lethal)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/turretid/power_change()
|
||||
..()
|
||||
aTurret.setState(enabled, lethal, shoot_cyborgs)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/turretid/update_icon_state()
|
||||
@@ -1051,11 +1098,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/lasertag
|
||||
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
|
||||
check_records = 0
|
||||
criminals = 0
|
||||
auth_weapons = 1
|
||||
stun_all = 0
|
||||
check_anomalies = 0
|
||||
turret_flags = TURRET_FLAG_AUTH_WEAPONS
|
||||
var/team_color
|
||||
|
||||
/obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp)
|
||||
@@ -1083,20 +1126,14 @@
|
||||
if(properties["team_color"])
|
||||
team_color = properties["team_color"]
|
||||
|
||||
/obj/machinery/porta_turret/lasertag/ui_interact(mob/user)
|
||||
. = ..()
|
||||
/obj/machinery/porta_turret/lasertag/ui_status(mob/user)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(team_color == "blue" && istype(H.wear_suit, /obj/item/clothing/suit/redtag))
|
||||
return
|
||||
return UI_CLOSE
|
||||
if(team_color == "red" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
|
||||
return
|
||||
|
||||
var/dat = "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
//lasertag presets
|
||||
/obj/machinery/porta_turret/lasertag/red
|
||||
@@ -1112,11 +1149,9 @@
|
||||
if(on)
|
||||
if(team_color == "blue")
|
||||
if(istype(P, /obj/item/projectile/beam/lasertag/redtag))
|
||||
on = FALSE
|
||||
spawn(100)
|
||||
on = TRUE
|
||||
toggle_on(FALSE)
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
|
||||
else if(team_color == "red")
|
||||
if(istype(P, /obj/item/projectile/beam/lasertag/bluetag))
|
||||
on = FALSE
|
||||
spawn(100)
|
||||
on = TRUE
|
||||
toggle_on(FALSE)
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
|
||||
|
||||
@@ -126,17 +126,6 @@
|
||||
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)
|
||||
if(!occupant)
|
||||
return
|
||||
SEND_SIGNAL(occupant, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, recharge_speed, repairs)
|
||||
|
||||
@@ -218,10 +218,10 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
dat += "<b>Message Authentication</b> <br><br>"
|
||||
dat += "<b>Message for [dpt]:</b> [message] <br><br>"
|
||||
dat += "<div class='notice'>You may authenticate your message now by scanning your ID or your stamp</div> <br>"
|
||||
|
||||
|
||||
dat += "<b>Validated by:</b> [msgVerified ? "<span class='good'><b>[msgVerified]</b></span>" : "<i>Not Validated</i>"] <br>"
|
||||
dat += "<b>Stamped by:</b> [msgStamped ? "<span class='boldnotice'>[msgStamped]</span>" : "<i>Not Stamped</i>"] <br><br>"
|
||||
|
||||
|
||||
dat += "<a href='?src=[REF(src)];department=[dpt]'>Send Message</a> <br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'><< Discard Message</a> <br>"
|
||||
|
||||
@@ -271,7 +271,6 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
|
||||
var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/requests_console/Topic(href, href_list)
|
||||
@@ -279,7 +278,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
if(href_list["write"])
|
||||
dpt = ckey(reject_bad_text(href_list["write"])) //write contains the string of the receiving department's name
|
||||
var/new_message = stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN)
|
||||
@@ -358,7 +357,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
workingServer = TRUE
|
||||
|
||||
if(!workingServer)
|
||||
screen = 7
|
||||
screen = 7
|
||||
say("NOTICE: No server detected! Please contact your local engineering team.")
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -539,7 +538,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
to_chat(user, "<span class='warning'>You are not authorized to send announcements!</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
if(istype(O, /obj/item/stamp))
|
||||
if(screen == 9)
|
||||
var/obj/item/stamp/T = O
|
||||
|
||||
@@ -132,7 +132,6 @@
|
||||
|
||||
var/datum/browser/popup = new(user, "slotmachine", "Slot Machine")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/slot_machine/Topic(href, href_list)
|
||||
|
||||
@@ -170,12 +170,10 @@
|
||||
..()
|
||||
default_unfasten_wrench(user, I, 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state)
|
||||
ui = new(user, src, "SpaceHeater", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/space_heater/ui_data()
|
||||
@@ -210,7 +208,7 @@
|
||||
if("power")
|
||||
on = !on
|
||||
mode = HEATER_MODE_STANDBY
|
||||
usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
|
||||
usr.visible_message("<span class='notice'>[usr] switches [on ? "on" : "off"] \the [src].</span>", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
|
||||
update_icon()
|
||||
if (on)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
@@ -222,16 +220,7 @@
|
||||
if(!panel_open)
|
||||
return
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(target == "input")
|
||||
target = input("New target temperature:", name, round(targetTemperature - T0C, 1)) as num|null
|
||||
if(!isnull(target) && !..())
|
||||
target += T0C
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
target = targetTemperature + adjust
|
||||
. = TRUE
|
||||
else if(text2num(target) != null)
|
||||
if(text2num(target) != null)
|
||||
target= text2num(target) + T0C
|
||||
. = TRUE
|
||||
if(.)
|
||||
|
||||
@@ -377,11 +377,13 @@
|
||||
|
||||
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)
|
||||
/obj/machinery/suit_storage_unit/ui_state(mob/user)
|
||||
return GLOB.notcontained_state
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state)
|
||||
ui = new(user, src, "SuitStorageUnit", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
var/notice = ""
|
||||
var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech
|
||||
|
||||
/obj/machinery/computer/telecomms/server/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)
|
||||
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsLogBrowser", "Telecomms Server Monitor", 575, 400, master_ui, state)
|
||||
ui = new(user, src, "TelecommsLogBrowser", "Telecomms Server Monitor")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
|
||||
|
||||
@@ -36,12 +36,11 @@
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
/obj/machinery/computer/message_monitor/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)
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsPDALog", name, 727, 510, master_ui, state)
|
||||
ui = new(user, src, "TelecommsPDALog", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
|
||||
circuit = /obj/item/circuitboard/computer/comm_monitor
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/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)
|
||||
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsMonitor", name, 575, 400, master_ui, state)
|
||||
ui = new(user, src, "TelecommsMonitor", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
|
||||
|
||||
@@ -27,16 +27,15 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/telecomms/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)
|
||||
/obj/machinery/telecomms/ui_interact(mob/user, datum/tgui/ui)
|
||||
if(!canInteract(user))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsInteraction", "[name] Access", 520, 500, master_ui, state)
|
||||
ui = new(user, src, "TelecommsInteraction", "[name] Access")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/telecomms/ui_data(mob/user)
|
||||
|
||||
@@ -11,10 +11,15 @@
|
||||
var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff)
|
||||
var/energy_drain = 0
|
||||
var/obj/mecha/chassis = null
|
||||
var/range = MELEE //bitFflags
|
||||
/// Bitflag. Determines the range of the equipment.
|
||||
var/range = MELEE
|
||||
/// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
|
||||
var/mech_flags = NONE
|
||||
var/salvageable = 1
|
||||
//var/detachable = TRUE // Set to FALSE for built-in equipment that cannot be removed
|
||||
var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates
|
||||
var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist.
|
||||
//var/destroy_sound = 'sound/mecha/critdestr.ogg'
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page()
|
||||
if(chassis)
|
||||
@@ -35,9 +40,14 @@
|
||||
if(chassis.selected == src)
|
||||
chassis.selected = null
|
||||
src.update_chassis_page()
|
||||
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>")
|
||||
//log_message("[src] is destroyed.", LOG_MECHA)
|
||||
chassis.log_append_to_last("[src] is destroyed.",1)
|
||||
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
|
||||
if(chassis.occupant)
|
||||
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>")
|
||||
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
|
||||
//chassis.occupant.playsound_local(chassis, destroy_sound, 50)
|
||||
//if(!detachable) //If we're a built-in nondetachable equipment, let's lock up the slot that we were in.
|
||||
// chassis.max_equip--
|
||||
chassis = null
|
||||
return ..()
|
||||
|
||||
@@ -59,7 +69,7 @@
|
||||
return txt
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not?
|
||||
return range&RANGED
|
||||
return range&RANGED //rename to MECHA_RANGE and MECHA_MELEE
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/is_melee()
|
||||
return range&MELEE
|
||||
@@ -72,10 +82,10 @@
|
||||
return 0
|
||||
if(!equip_ready)
|
||||
return 0
|
||||
if(crit_fail)
|
||||
return 0
|
||||
if(energy_drain && !chassis.has_charge(energy_drain))
|
||||
return 0
|
||||
if(crit_fail)
|
||||
return 0
|
||||
if(chassis.equipment_disabled)
|
||||
to_chat(chassis.occupant, "<span=warn>Error -- Equipment control unit is unresponsive.</span>")
|
||||
return 0
|
||||
@@ -117,8 +127,6 @@
|
||||
chassis = M
|
||||
forceMove(M)
|
||||
M.mecha_log_message("[src] initialized.")
|
||||
if(!M.selected && selectable)
|
||||
M.selected = src
|
||||
src.update_chassis_page()
|
||||
return
|
||||
|
||||
@@ -150,7 +158,7 @@
|
||||
chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
|
||||
return
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color)
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) //on tg this just overrides log_message
|
||||
log_message(message, LOG_GAME, color) //pass to default admin logging too
|
||||
if(chassis)
|
||||
chassis.mecha_log_message(message, color) //and pass to our chassis
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Sleeper, Medical Beam, and Syringe gun
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical
|
||||
mech_flags = EXOSUIT_MODULE_MEDICAL
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
toolspeed = 0.9
|
||||
var/drill_delay = 7
|
||||
var/drill_level = DRILL_BASIC
|
||||
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/drill/Initialize()
|
||||
. = ..()
|
||||
@@ -153,6 +154,7 @@
|
||||
selectable = 0
|
||||
equip_cooldown = 15
|
||||
var/scanning_time = 0
|
||||
mech_flags = EXOSUIT_MODULE_WORKING
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
icon_state = "mecha_clamp"
|
||||
equip_cooldown = 15
|
||||
energy_drain = 10
|
||||
tool_behaviour = TOOL_RETRACTOR
|
||||
toolspeed = 0.8
|
||||
var/dam_force = 20
|
||||
var/obj/mecha/working/ripley/cargo_holder
|
||||
harmful = TRUE
|
||||
tool_behaviour = TOOL_RETRACTOR
|
||||
toolspeed = 0.8
|
||||
mech_flags = EXOSUIT_MODULE_RIPLEY
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
|
||||
if(..())
|
||||
@@ -180,6 +181,7 @@
|
||||
equip_cooldown = 5
|
||||
energy_drain = 0
|
||||
range = MELEE|RANGED
|
||||
mech_flags = EXOSUIT_MODULE_WORKING
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/projectile_delay = 0
|
||||
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired.
|
||||
var/kickback = TRUE //Will using this weapon in no grav push mecha back.
|
||||
mech_flags = EXOSUIT_MODULE_COMBAT
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M)
|
||||
if(..())
|
||||
|
||||
@@ -81,10 +81,10 @@
|
||||
var/obj/machinery/mech_bay_recharge_port/recharge_port
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/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)
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "MechBayPowerConsole", "Mech Bay Power Control Console", 400, 200, master_ui, state)
|
||||
ui = new(user, src, "MechBayPowerConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
|
||||
@@ -104,7 +104,6 @@
|
||||
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,)
|
||||
if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell))
|
||||
data["recharge_port"]["mech"]["cell"] = list(
|
||||
"critfail" = recharge_port.recharging_mech.cell.crit_fail,
|
||||
"charge" = recharge_port.recharging_mech.cell.charge,
|
||||
"maxcharge" = recharge_port.recharging_mech.cell.maxcharge
|
||||
)
|
||||
|
||||
+546
-335
@@ -9,17 +9,41 @@
|
||||
active_power_usage = 5000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/machine/mechfab
|
||||
var/time_coeff = 1
|
||||
var/component_coeff = 1
|
||||
var/datum/techweb/specialized/autounlocking/exofab/stored_research
|
||||
var/sync = 0
|
||||
var/part_set
|
||||
var/datum/design/being_built
|
||||
// processing_flags = START_PROCESSING_MANUALLY
|
||||
|
||||
// subsystem_type = /datum/controller/subsystem/processing/fastprocess
|
||||
|
||||
/// Current items in the build queue.
|
||||
var/list/queue = list()
|
||||
var/processing_queue = 0
|
||||
var/screen = "main"
|
||||
var/temp
|
||||
var/offstation_security_levels = TRUE
|
||||
/// Whether or not the machine is building the entire queue automagically.
|
||||
var/process_queue = FALSE
|
||||
|
||||
/// The current design datum that the machine is building.
|
||||
var/datum/design/being_built
|
||||
/// World time when the build will finish.
|
||||
var/build_finish = 0
|
||||
/// World time when the build started.
|
||||
var/build_start = 0
|
||||
/// Reference to all materials used in the creation of the item being_built.
|
||||
var/list/build_materials
|
||||
/// Part currently stored in the Exofab.
|
||||
var/obj/item/stored_part
|
||||
|
||||
/// Coefficient for the speed of item building. Based on the installed parts.
|
||||
var/time_coeff = 1
|
||||
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
|
||||
var/component_coeff = 1
|
||||
|
||||
/// Copy of the currently synced techweb.
|
||||
var/datum/techweb/specialized/autounlocking/exofab/stored_research
|
||||
|
||||
/// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE.
|
||||
var/link_on_init = TRUE
|
||||
|
||||
/// Reference to a remote material inventory, such as an ore silo.
|
||||
var/datum/component/remote_materials/rmat
|
||||
|
||||
/// A list of categories that valid MECHFAB design datums will broadly categorise themselves under.
|
||||
var/list/part_sets = list(
|
||||
"Cyborg",
|
||||
"Ripley",
|
||||
@@ -33,25 +57,17 @@
|
||||
"Exosuit Equipment",
|
||||
"Exosuit Ammunition",
|
||||
"Cyborg Upgrade Modules",
|
||||
"Cybernetics",
|
||||
"Implants",
|
||||
"Control Interfaces",
|
||||
"Misc"
|
||||
)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Initialize()
|
||||
var/static/list/allowed_types = list(
|
||||
/datum/material/iron,
|
||||
/datum/material/glass,
|
||||
/datum/material/silver,
|
||||
/datum/material/gold,
|
||||
/datum/material/diamond,
|
||||
/datum/material/plasma,
|
||||
/datum/material/uranium,
|
||||
/datum/material/bananium,
|
||||
/datum/material/titanium,
|
||||
/datum/material/bluespace
|
||||
)
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
materials.precise_insertion = TRUE
|
||||
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
|
||||
stored_research = new
|
||||
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init)
|
||||
|
||||
RefreshParts() //Recalculating local material sizes if the fab isn't linked
|
||||
return ..()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/RefreshParts()
|
||||
@@ -60,8 +76,7 @@
|
||||
//maximum stocking amount (default 300000, 600000 at T4)
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
T += M.rating
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = (200000 + (T*50000))
|
||||
rmat.set_local_size((200000 + (T*50000)))
|
||||
|
||||
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
|
||||
T = 1.15
|
||||
@@ -74,89 +89,157 @@
|
||||
for(var/obj/item/stock_parts/manipulator/Ml in component_parts)
|
||||
T += Ml.rating
|
||||
time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01)
|
||||
var/obj/item/circuitboard/machine/mechfab/C = circuit
|
||||
offstation_security_levels = C.offstation_security_levels
|
||||
|
||||
// Adjust the build time of any item currently being built.
|
||||
if(being_built)
|
||||
var/last_const_time = build_finish - build_start
|
||||
var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time))
|
||||
var/const_time_left = build_finish - world.time
|
||||
var/new_build_time = (new_const_time / last_const_time) * const_time_left
|
||||
build_finish = world.time + new_build_time
|
||||
|
||||
update_static_data(usr)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/examine(mob/user)
|
||||
. = ..()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[materials.max_amount]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>"
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[rmat.local_size]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>"
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/emag_act()
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
req_access = list()
|
||||
INVOKE_ASYNC(src, .proc/error_action_sucessful)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful()
|
||||
say("DB error \[Code 0x00F1\]")
|
||||
sleep(10)
|
||||
say("Attempting auto-repair...")
|
||||
sleep(15)
|
||||
say("User DB corrupted \[Code 0x00FA\]. Truncating data structure...")
|
||||
sleep(30)
|
||||
say("User DB truncated. Please contact your Nanotrasen system operator for future assistance.")
|
||||
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
|
||||
var/output = ""
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
if(!(set_name in D.category))
|
||||
continue
|
||||
output += "<div class='part'>[output_part_info(D)]<br>\["
|
||||
if(check_clearance(D) && check_resources(D))
|
||||
output += "<a href='?src=[REF(src)];part=[D.id]'>Build</a> | "
|
||||
output += "<a href='?src=[REF(src)];add_to_queue=[D.id]'>Add to queue</a>\]\[<a href='?src=[REF(src)];part_desc=[D.id]'>?</a>\]</div>"
|
||||
return output
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/check_clearance(datum/design/D)
|
||||
if(!(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) && !ISINRANGE(GLOB.security_level, D.min_security_level, D.max_security_level))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D)
|
||||
var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z))
|
||||
var/sec_text = ""
|
||||
if(clearance && (D.min_security_level > SEC_LEVEL_GREEN || D.max_security_level < SEC_LEVEL_DELTA))
|
||||
sec_text = " (Allowed security levels: "
|
||||
for(var/n in D.min_security_level to D.max_security_level)
|
||||
sec_text += NUM2SECLEVEL(n)
|
||||
if(n + 1 <= D.max_security_level)
|
||||
sec_text += ", "
|
||||
sec_text += ") "
|
||||
var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [sec_text][get_construction_time_w_coeff(D)/10]sec"
|
||||
return output
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D)
|
||||
var/i = 0
|
||||
var/output
|
||||
/**
|
||||
* Generates an info list for a given part.
|
||||
*
|
||||
* Returns a list of part information.
|
||||
* * D - Design datum to get information on.
|
||||
* * categories - Boolean, whether or not to parse snowflake categories into the part information list.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, categories = FALSE)
|
||||
var/cost = list()
|
||||
for(var/c in D.materials)
|
||||
var/datum/material/M = c
|
||||
output += "[i?" | ":null][get_resource_cost_w_coeff(D, M)] [M.name]"
|
||||
i++
|
||||
return output
|
||||
cost[M.name] = get_resource_cost_w_coeff(D, M)
|
||||
|
||||
var/obj/built_item = D.build_path
|
||||
|
||||
var/list/category_override = null
|
||||
var/list/sub_category = null
|
||||
|
||||
if(categories)
|
||||
// Handle some special cases to build up sub-categories for the fab interface.
|
||||
// Start with checking if this design builds a cyborg module.
|
||||
if(built_item in typesof(/obj/item/borg/upgrade))
|
||||
var/obj/item/borg/upgrade/U = built_item
|
||||
var/module_types = initial(U.module_flags)
|
||||
sub_category = list()
|
||||
if(module_types)
|
||||
if(module_types & BORG_MODULE_SECURITY)
|
||||
sub_category += "Security"
|
||||
if(module_types & BORG_MODULE_MINER)
|
||||
sub_category += "Mining"
|
||||
if(module_types & BORG_MODULE_JANITOR)
|
||||
sub_category += "Janitor"
|
||||
if(module_types & BORG_MODULE_MEDICAL)
|
||||
sub_category += "Medical"
|
||||
if(module_types & BORG_MODULE_ENGINEERING)
|
||||
sub_category += "Engineering"
|
||||
else
|
||||
sub_category += "All Cyborgs"
|
||||
// Else check if this design builds a piece of exosuit equipment.
|
||||
else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment))
|
||||
var/obj/item/mecha_parts/mecha_equipment/E = built_item
|
||||
var/mech_types = initial(E.mech_flags)
|
||||
sub_category = "Equipment"
|
||||
if(mech_types)
|
||||
category_override = list()
|
||||
if(mech_types & EXOSUIT_MODULE_RIPLEY)
|
||||
category_override += "Ripley"
|
||||
if(mech_types & EXOSUIT_MODULE_FIREFIGHTER)
|
||||
category_override += "Firefighter"
|
||||
if(mech_types & EXOSUIT_MODULE_ODYSSEUS)
|
||||
category_override += "Odysseus"
|
||||
// if(mech_types & EXOSUIT_MODULE_CLARKE)
|
||||
// category_override += "Clarke"
|
||||
if(mech_types & EXOSUIT_MODULE_GYGAX_MED)
|
||||
category_override += "Medical-Spec Gygax"
|
||||
if(mech_types & EXOSUIT_MODULE_GYGAX)
|
||||
category_override += "Gygax"
|
||||
if(mech_types & EXOSUIT_MODULE_DURAND)
|
||||
category_override += "Durand"
|
||||
if(mech_types & EXOSUIT_MODULE_HONK)
|
||||
category_override += "H.O.N.K"
|
||||
if(mech_types & EXOSUIT_MODULE_PHAZON)
|
||||
category_override += "Phazon"
|
||||
|
||||
|
||||
var/list/part = list(
|
||||
"name" = D.name,
|
||||
"desc" = initial(built_item.desc),
|
||||
"printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10,
|
||||
"cost" = cost,
|
||||
"id" = D.id,
|
||||
"subCategory" = sub_category,
|
||||
"categoryOverride" = category_override,
|
||||
"searchMeta" = "UNKNOWN"//D.search_metadata
|
||||
)
|
||||
|
||||
return part
|
||||
|
||||
/**
|
||||
* Generates a list of resources / materials available to this Exosuit Fab
|
||||
*
|
||||
* Returns null if there is no material container available.
|
||||
* List format is list(material_name = list(amount = ..., ref = ..., etc.))
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
|
||||
var/output
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = mat_id
|
||||
var/amount = materials.materials[mat_id]
|
||||
output += "<span class=\"res_name\">[M.name]: </span>[amount] cm³"
|
||||
if(amount >= MINERAL_MATERIAL_AMOUNT)
|
||||
output += "<span style='font-size:80%;'>- Remove \[<a href='?src=[REF(src)];remove_mat=1;material=[REF(mat_id)]'>1</a>\]"
|
||||
if(amount >= (MINERAL_MATERIAL_AMOUNT * 10))
|
||||
output += " | \[<a href='?src=[REF(src)];remove_mat=10;material=[REF(M)]'>10</a>\]"
|
||||
output += " | \[<a href='?src=[REF(src)];remove_mat=50;material=[REF(M)]'>All</a>\]</span>"
|
||||
output += "<br/>"
|
||||
return output
|
||||
var/datum/component/material_container/materials = rmat.mat_container
|
||||
|
||||
var/list/material_data = list()
|
||||
|
||||
if(materials)
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = mat_id
|
||||
var/list/material_info = list()
|
||||
var/amount = materials.materials[mat_id]
|
||||
|
||||
material_info = list(
|
||||
"name" = M.name,
|
||||
"ref" = REF(M),
|
||||
"amount" = amount,
|
||||
"sheets" = round(amount / MINERAL_MATERIAL_AMOUNT),
|
||||
"removable" = amount >= MINERAL_MATERIAL_AMOUNT
|
||||
)
|
||||
|
||||
material_data += list(material_info)
|
||||
|
||||
return material_data
|
||||
|
||||
return null
|
||||
|
||||
/**
|
||||
* Intended to be called when an item starts printing.
|
||||
*
|
||||
* Adds the overlay to show the fab working and sets active power usage settings.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/on_start_printing()
|
||||
add_overlay("fab-active")
|
||||
use_power = ACTIVE_POWER_USE
|
||||
|
||||
/**
|
||||
* Intended to be called when the exofab has stopped working and is no longer printing items.
|
||||
*
|
||||
* Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/on_finish_printing()
|
||||
cut_overlay("fab-active")
|
||||
use_power = IDLE_POWER_USE
|
||||
desc = initial(desc)
|
||||
process_queue = FALSE
|
||||
|
||||
/**
|
||||
* Calculates resource/material costs for printing an item based on the machine's resource coefficient.
|
||||
*
|
||||
* Returns a list of k,v resources with their amounts.
|
||||
* * D - Design datum to calculate the modified resource cost of.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
|
||||
var/list/resources = list()
|
||||
for(var/R in D.materials)
|
||||
@@ -164,294 +247,419 @@
|
||||
resources[M] = get_resource_cost_w_coeff(D, M)
|
||||
return resources
|
||||
|
||||
/**
|
||||
* Checks if the Exofab has enough resources to print a given item.
|
||||
*
|
||||
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
|
||||
* Returns TRUE if there are sufficient resources to print the item.
|
||||
* * D - Design datum to calculate the modified resource cost of.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
|
||||
if(D.reagents_list.len) // No reagents storage - no reagent designs.
|
||||
if(length(D.reagents_list)) // No reagents storage - no reagent designs.
|
||||
return FALSE
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/datum/component/material_container/materials = rmat.mat_container
|
||||
if(materials.has_materials(get_resources_w_coeff(D)))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D)
|
||||
/**
|
||||
* Attempts to build the next item in the build queue.
|
||||
*
|
||||
* Returns FALSE if either there are no more parts to build or the next part is not buildable.
|
||||
* Returns TRUE if the next part has started building.
|
||||
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE)
|
||||
if(!length(queue))
|
||||
return FALSE
|
||||
|
||||
var/datum/design/D = queue[1]
|
||||
if(build_part(D, verbose))
|
||||
remove_from_queue(1)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Starts the build process for a given design datum.
|
||||
*
|
||||
* Returns FALSE if the procedure fails. Returns TRUE when being_built is set.
|
||||
* Uses materials.
|
||||
* * D - Design datum to attempt to print.
|
||||
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE)
|
||||
if(!D)
|
||||
return FALSE
|
||||
|
||||
var/datum/component/material_container/materials = rmat.mat_container
|
||||
if (!materials)
|
||||
if(verbose)
|
||||
say("No access to material storage, please contact the quartermaster.")
|
||||
return FALSE
|
||||
if (rmat.on_hold())
|
||||
if(verbose)
|
||||
say("Mineral access is on hold, please contact the quartermaster.")
|
||||
return FALSE
|
||||
if(!check_resources(D))
|
||||
if(verbose)
|
||||
say("Not enough resources. Processing stopped.")
|
||||
return FALSE
|
||||
|
||||
build_materials = get_resources_w_coeff(D)
|
||||
|
||||
materials.use_materials(build_materials)
|
||||
being_built = D
|
||||
desc = "It's building \a [initial(D.name)]."
|
||||
var/list/res_coef = get_resources_w_coeff(D)
|
||||
build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time))
|
||||
build_start = world.time
|
||||
desc = "It's building \a [D.name]."
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.use_materials(res_coef)
|
||||
add_overlay("fab-active")
|
||||
use_power = ACTIVE_POWER_USE
|
||||
updateUsrDialog()
|
||||
sleep(get_construction_time_w_coeff(D))
|
||||
use_power = IDLE_POWER_USE
|
||||
cut_overlay("fab-active")
|
||||
desc = initial(desc)
|
||||
rmat.silo_log(src, "built", -1, "[D.name]", build_materials)
|
||||
|
||||
var/location = get_step(src,(dir))
|
||||
var/obj/item/I = new D.build_path(location)
|
||||
I.set_custom_materials(res_coef)
|
||||
say("\The [I] is complete.")
|
||||
being_built = null
|
||||
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page()
|
||||
send_byjax(usr,"mecha_fabricator.browser","queue",list_queue())
|
||||
return
|
||||
/obj/machinery/mecha_part_fabricator/process()
|
||||
// If there's a stored part to dispense due to an obstruction, try to dispense it.
|
||||
if(stored_part)
|
||||
var/turf/exit = get_step(src,(dir))
|
||||
if(exit.density)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
|
||||
if(set_name in part_sets)
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
if(set_name in D.category)
|
||||
add_to_queue(D)
|
||||
say("Obstruction cleared. \The [stored_part] is complete.")
|
||||
stored_part.forceMove(exit)
|
||||
stored_part = null
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D)
|
||||
// If there's nothing being built, try to build something
|
||||
if(!being_built)
|
||||
// If we're not processing the queue anymore or there's nothing to build, end processing.
|
||||
if(!process_queue || !build_next_in_queue())
|
||||
on_finish_printing()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
//end_processing()
|
||||
return TRUE
|
||||
on_start_printing()
|
||||
|
||||
// If there's an item being built, check if it is complete.
|
||||
if(being_built && (build_finish < world.time))
|
||||
// Then attempt to dispense it and if appropriate build the next item.
|
||||
dispense_built_part(being_built)
|
||||
if(process_queue)
|
||||
build_next_in_queue(FALSE)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Dispenses a part to the tile infront of the Exosuit Fab.
|
||||
*
|
||||
* Returns FALSE is the machine cannot dispense the part on the appropriate turf.
|
||||
* Return TRUE if the part was successfully dispensed.
|
||||
* * D - Design datum to attempt to dispense.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D)
|
||||
var/obj/item/I = new D.build_path(src)
|
||||
// I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
|
||||
I.set_custom_materials(build_materials)
|
||||
|
||||
being_built = null
|
||||
|
||||
var/turf/exit = get_step(src,(dir))
|
||||
if(exit.density)
|
||||
say("Error! Part outlet is obstructed.")
|
||||
desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed."
|
||||
stored_part = I
|
||||
return FALSE
|
||||
|
||||
say("\The [I] is complete.")
|
||||
I.forceMove(exit)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Adds a list of datum designs to the build queue.
|
||||
*
|
||||
* Will only add designs that are in this machine's stored techweb.
|
||||
* Does final checks for datum IDs and makes sure this machine can build the designs.
|
||||
* * part_list - List of datum design ids for designs to add to the queue.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list)
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if((D.build_type & MECHFAB) && (D.id in part_list))
|
||||
add_to_queue(D)
|
||||
|
||||
/**
|
||||
* Adds a datum design to the build queue.
|
||||
*
|
||||
* Returns TRUE if successful and FALSE if the design was not added to the queue.
|
||||
* * D - Datum design to add to the queue.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D)
|
||||
if(!istype(queue))
|
||||
queue = list()
|
||||
if(D)
|
||||
queue[++queue.len] = D
|
||||
return queue.len
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Removes datum design from the build queue based on index.
|
||||
*
|
||||
* Returns TRUE if successful and FALSE if a design was not removed from the queue.
|
||||
* * index - Index in the build queue of the element to remove.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
|
||||
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>queue.len))
|
||||
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue)))
|
||||
return FALSE
|
||||
queue.Cut(index,++index)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/process_queue()
|
||||
var/datum/design/D = queue[1]
|
||||
if(!D)
|
||||
remove_from_queue(1)
|
||||
if(queue.len)
|
||||
return process_queue()
|
||||
else
|
||||
return
|
||||
temp = null
|
||||
while(D)
|
||||
if(stat&(NOPOWER|BROKEN))
|
||||
return FALSE
|
||||
if(!check_clearance(D))
|
||||
say("Security level not met. Queue processing stopped.")
|
||||
temp = {"<span class='alert'>Security level not met to build next part.</span><br>
|
||||
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
|
||||
return FALSE
|
||||
if(!check_resources(D))
|
||||
say("Not enough resources. Queue processing stopped.")
|
||||
temp = {"<span class='alert'>Not enough resources to build next part.</span><br>
|
||||
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
|
||||
return FALSE
|
||||
remove_from_queue(1)
|
||||
build_part(D)
|
||||
D = listgetindex(queue, 1)
|
||||
say("Queue processing finished successfully.")
|
||||
|
||||
/**
|
||||
* Generates a list of parts formatted for tgui based on the current build queue.
|
||||
*
|
||||
* Returns a formatted list of lists containing formatted part information for every part in the build queue.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/list_queue()
|
||||
var/output = "<b>Queue contains:</b>"
|
||||
if(!istype(queue) || !queue.len)
|
||||
output += "<br>Nothing"
|
||||
else
|
||||
output += "<ol>"
|
||||
var/i = 0
|
||||
for(var/datum/design/D in queue)
|
||||
i++
|
||||
var/obj/part = D.build_path
|
||||
output += "<li[(!check_clearance(D) ||!check_resources(D))?" style='color: #f00;'":null]>"
|
||||
output += initial(part.name) + " - "
|
||||
output += "[i>1?"<a href='?src=[REF(src)];queue_move=-1;index=[i]' class='arrow'>↑</a>":null] "
|
||||
output += "[i<queue.len?"<a href='?src=[REF(src)];queue_move=+1;index=[i]' class='arrow'>↓</a>":null] "
|
||||
output += "<a href='?src=[REF(src)];remove_from_queue=[i]'>Remove</a></li>"
|
||||
if(!istype(queue) || !length(queue))
|
||||
return null
|
||||
|
||||
output += "</ol>"
|
||||
output += "\[<a href='?src=[REF(src)];process_queue=1'>Process queue</a> | <a href='?src=[REF(src)];clear_queue=1'>Clear queue</a>\]"
|
||||
return output
|
||||
var/list/queued_parts = list()
|
||||
for(var/datum/design/D in queue)
|
||||
var/list/part = output_part_info(D)
|
||||
queued_parts += list(part)
|
||||
return queued_parts
|
||||
|
||||
/**
|
||||
* Syncs machine with R&D servers.
|
||||
*
|
||||
* Requires an R&D Console visible within 7 tiles. Copies techweb research. Updates tgui's state data.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/sync()
|
||||
temp = "Updating local R&D database..."
|
||||
updateUsrDialog()
|
||||
sleep(30) //only sleep if called by user
|
||||
|
||||
for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src))
|
||||
for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src))
|
||||
RDC.stored_research.copy_research_to(stored_research)
|
||||
temp = "Processed equipment designs.<br>"
|
||||
//check if the tech coefficients have changed
|
||||
temp += "<a href='?src=[REF(src)];clear_temp=1'>Return</a>"
|
||||
|
||||
updateUsrDialog()
|
||||
update_static_data(usr)
|
||||
say("Successfully synchronized with R&D server.")
|
||||
return
|
||||
|
||||
temp = "Unable to connect to local R&D Database.<br>Please check your connections and try again.<br><a href='?src=[REF(src)];clear_temp=1'>Return</a>"
|
||||
updateUsrDialog()
|
||||
say("Unable to connect to local R&D server.")
|
||||
return
|
||||
|
||||
/**
|
||||
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
|
||||
*
|
||||
* Returns coefficient-modified resource cost for the given material component.
|
||||
* * D - Design datum to pull the resource cost from.
|
||||
* * resource - Material datum reference to the resource to calculate the cost of.
|
||||
* * roundto - Rounding value for round() proc
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1)
|
||||
return round(D.materials[resource]*component_coeff, roundto)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran
|
||||
return round(initial(D.construction_time)*time_coeff, roundto)
|
||||
/**
|
||||
* Calculates the coefficient-modified build time of a design.
|
||||
*
|
||||
* Returns coefficient-modified build time of a given design.
|
||||
* * D - Design datum to calculate the modified build time of.
|
||||
* * roundto - Rounding value for round() proc
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran
|
||||
return round(construction_time*time_coeff, roundto)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user as mob)
|
||||
. = ..()
|
||||
var/dat, left_part
|
||||
user.set_machine(src)
|
||||
var/turf/exit = get_step(src,(dir))
|
||||
if(exit.density)
|
||||
say("Error! Part outlet is obstructed.")
|
||||
return
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(being_built)
|
||||
var/obj/I = being_built.build_path
|
||||
left_part = {"<TT>Building [initial(I.name)].<BR>
|
||||
Please wait until completion...</TT>"}
|
||||
/obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
|
||||
)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ExosuitFabricator")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/final_sets = list()
|
||||
var/list/buildable_parts = list()
|
||||
|
||||
for(var/part_set in part_sets)
|
||||
final_sets += part_set
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
// This is for us.
|
||||
var/list/part = output_part_info(D, TRUE)
|
||||
|
||||
if(part["category_override"])
|
||||
for(var/cat in part["category_override"])
|
||||
buildable_parts[cat] += list(part)
|
||||
if(!(cat in part_sets))
|
||||
final_sets += cat
|
||||
continue
|
||||
|
||||
for(var/cat in part_sets)
|
||||
// Find all matching categories.
|
||||
if(!(cat in D.category))
|
||||
continue
|
||||
|
||||
buildable_parts[cat] += list(part)
|
||||
|
||||
data["partSets"] = final_sets
|
||||
data["buildableParts"] = buildable_parts
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["materials"] = output_available_resources()
|
||||
|
||||
if(being_built)
|
||||
var/list/part = list(
|
||||
"name" = being_built.name,
|
||||
"duration" = build_finish - world.time,
|
||||
"printTime" = get_construction_time_w_coeff(initial(being_built.construction_time))
|
||||
)
|
||||
data["buildingPart"] = part
|
||||
else
|
||||
switch(screen)
|
||||
if("main")
|
||||
left_part = output_available_resources()+"<hr>"
|
||||
left_part += "<a href='?src=[REF(src)];sync=1'>Sync with R&D servers</a><hr>"
|
||||
for(var/part_set in part_sets)
|
||||
left_part += "<a href='?src=[REF(src)];part_set=[part_set]'>[part_set]</a> - \[<a href='?src=[REF(src)];partset_to_queue=[part_set]'>Add all parts to queue</a>\]<br>"
|
||||
if("parts")
|
||||
left_part += output_parts_list(part_set)
|
||||
left_part += "<hr><a href='?src=[REF(src)];screen=main'>Return</a>"
|
||||
dat = {"<html>
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
|
||||
<title>[name] data</title>
|
||||
<style>
|
||||
.res_name {font-weight: bold; text-transform: capitalize;}
|
||||
.red {color: #f00;}
|
||||
.part {margin-bottom: 10px;}
|
||||
.arrow {text-decoration: none; font-size: 10px;}
|
||||
body, table {height: 100%;}
|
||||
td {vertical-align: top; padding: 5px;}
|
||||
html, body {padding: 0px; margin: 0px;}
|
||||
h1 {font-size: 18px; margin: 5px 0px;}
|
||||
</style>
|
||||
<script language='javascript' type='text/javascript'>
|
||||
[js_byjax]
|
||||
</script>
|
||||
</head><body>
|
||||
<body>
|
||||
<table style='width: 100%;'>
|
||||
<tr>
|
||||
<td style='width: 65%; padding-right: 10px;'>
|
||||
[left_part]
|
||||
</td>
|
||||
<td style='width: 35%; background: #ccc;' id='queue'>
|
||||
[list_queue()]
|
||||
</td>
|
||||
<tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>"}
|
||||
user << browse(dat, "window=mecha_fabricator;size=1000x430")
|
||||
onclose(user, "mecha_fabricator")
|
||||
return
|
||||
data["buildingPart"] = null
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
|
||||
data["queue"] = list_queue()
|
||||
|
||||
if(stored_part)
|
||||
data["storedPart"] = stored_part.name
|
||||
else
|
||||
data["storedPart"] = null
|
||||
|
||||
data["isProcessingQueue"] = process_queue
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_act(action, var/list/params)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["part_set"])
|
||||
var/tpart_set = href_list["part_set"]
|
||||
if(tpart_set)
|
||||
if(tpart_set=="clear")
|
||||
part_set = null
|
||||
else
|
||||
part_set = tpart_set
|
||||
screen = "parts"
|
||||
if(href_list["part"])
|
||||
var/T = href_list["part"]
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
if(D.id == T)
|
||||
if(!processing_queue)
|
||||
build_part(D)
|
||||
else
|
||||
add_to_queue(D)
|
||||
break
|
||||
if(href_list["add_to_queue"])
|
||||
var/T = href_list["add_to_queue"]
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
if(D.id == T)
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
switch(action)
|
||||
if("sync_rnd")
|
||||
// Sync with R&D Servers
|
||||
sync()
|
||||
return
|
||||
if("add_queue_set")
|
||||
// Add all parts of a set to queue
|
||||
var/part_list = params["part_list"]
|
||||
add_part_set_to_queue(part_list)
|
||||
return
|
||||
if("add_queue_part")
|
||||
// Add a specific part to queue
|
||||
var/T = params["id"]
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if((D.build_type & MECHFAB) && (D.id == T))
|
||||
add_to_queue(D)
|
||||
break
|
||||
return update_queue_on_page()
|
||||
if(href_list["remove_from_queue"])
|
||||
remove_from_queue(text2num(href_list["remove_from_queue"]))
|
||||
return update_queue_on_page()
|
||||
if(href_list["partset_to_queue"])
|
||||
add_part_set_to_queue(href_list["partset_to_queue"])
|
||||
return update_queue_on_page()
|
||||
if(href_list["process_queue"])
|
||||
spawn(0)
|
||||
if(processing_queue || being_built)
|
||||
return FALSE
|
||||
processing_queue = 1
|
||||
process_queue()
|
||||
processing_queue = 0
|
||||
if(href_list["clear_temp"])
|
||||
temp = null
|
||||
if(href_list["screen"])
|
||||
screen = href_list["screen"]
|
||||
if(href_list["queue_move"] && href_list["index"])
|
||||
var/index = text2num(href_list["index"])
|
||||
var/new_index = index + text2num(href_list["queue_move"])
|
||||
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
|
||||
if(ISINRANGE(new_index,1,queue.len))
|
||||
queue.Swap(index,new_index)
|
||||
return update_queue_on_page()
|
||||
if(href_list["clear_queue"])
|
||||
queue = list()
|
||||
return update_queue_on_page()
|
||||
if(href_list["sync"])
|
||||
sync()
|
||||
if(href_list["part_desc"])
|
||||
var/T = href_list["part_desc"]
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(D.build_type & MECHFAB)
|
||||
if(D.id == T)
|
||||
var/obj/part = D.build_path
|
||||
temp = {"<h1>[initial(part.name)] description:</h1>
|
||||
[initial(part.desc)]<br>
|
||||
<a href='?src=[REF(src)];clear_temp=1'>Return</a>
|
||||
"}
|
||||
break
|
||||
return
|
||||
if("del_queue_part")
|
||||
// Delete a specific from from the queue
|
||||
var/index = text2num(params["index"])
|
||||
remove_from_queue(index)
|
||||
return
|
||||
if("clear_queue")
|
||||
// Delete everything from queue
|
||||
queue.Cut()
|
||||
return
|
||||
if("build_queue")
|
||||
// Build everything in queue
|
||||
if(process_queue)
|
||||
return
|
||||
process_queue = TRUE
|
||||
|
||||
if(href_list["remove_mat"] && href_list["material"])
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/datum/material/Mat = locate(href_list["material"])
|
||||
materials.retrieve_sheets(text2num(href_list["remove_mat"]), Mat)
|
||||
if(!being_built)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
//begin_processing()
|
||||
return
|
||||
if("stop_queue")
|
||||
// Pause queue building. Also known as stop.
|
||||
process_queue = FALSE
|
||||
return
|
||||
if("build_part")
|
||||
// Build a single part
|
||||
if(being_built || process_queue)
|
||||
return
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
var/id = params["id"]
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/on_deconstruction()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
..()
|
||||
if(!(D.build_type & MECHFAB) || !(D.id == id))
|
||||
return
|
||||
|
||||
if(build_part(D))
|
||||
on_start_printing()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
//begin_processing() teege has this as a helper proc. please port it!
|
||||
|
||||
return
|
||||
if("move_queue_part")
|
||||
// Moves a part up or down in the queue.
|
||||
var/index = text2num(params["index"])
|
||||
var/new_index = index + text2num(params["newindex"])
|
||||
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
|
||||
if(ISINRANGE(new_index,1,length(queue)))
|
||||
queue.Swap(index,new_index)
|
||||
return
|
||||
if("remove_mat")
|
||||
// Remove a material from the fab
|
||||
var/mat_ref = params["ref"]
|
||||
var/amount = text2num(params["amount"])
|
||||
var/datum/material/mat = locate(mat_ref)
|
||||
eject_sheets(mat, amount)
|
||||
return
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Eject material sheets.
|
||||
*
|
||||
* Returns the number of sheets successfully ejected.
|
||||
* eject_sheet - Byond REF of the material to eject.
|
||||
* eject_amt - Number of sheets to attempt to eject.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt)
|
||||
var/datum/component/material_container/mat_container = rmat.mat_container
|
||||
if (!mat_container)
|
||||
say("No access to material storage, please contact the quartermaster.")
|
||||
return 0
|
||||
if (rmat.on_hold())
|
||||
say("Mineral access is on hold, please contact the quartermaster.")
|
||||
return 0
|
||||
var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location())
|
||||
var/list/matlist = list()
|
||||
matlist[eject_sheet] = text2num(eject_amt)
|
||||
rmat.silo_log(src, "ejected", -count, "sheets", matlist)
|
||||
return count
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
|
||||
var/datum/material/M = id_inserted
|
||||
add_overlay("fab-load-[M.name]")
|
||||
addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W))
|
||||
/obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(being_built)
|
||||
to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
|
||||
return FALSE
|
||||
return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I)
|
||||
|
||||
if(default_deconstruction_crowbar(W))
|
||||
/obj/machinery/mecha_part_fabricator/crowbar_act(mob/living/user, obj/item/I)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
if(being_built)
|
||||
to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
|
||||
return FALSE
|
||||
return default_deconstruction_crowbar(I)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user)
|
||||
if(panel_open)
|
||||
@@ -463,6 +671,9 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/maint
|
||||
link_on_init = FALSE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/offstation
|
||||
offstation_security_levels = FALSE
|
||||
link_on_init = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/mechfab/offstation
|
||||
|
||||
@@ -153,6 +153,9 @@
|
||||
/obj/mecha/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/mecha/rust_heretic_act()
|
||||
take_damage(500, BRUTE)
|
||||
|
||||
/obj/mecha/Destroy()
|
||||
go_out()
|
||||
var/mob/living/silicon/ai/AI
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/computer/mecha_control
|
||||
ui_x = 500
|
||||
ui_y = 500
|
||||
|
||||
/obj/machinery/computer/mecha/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)
|
||||
/obj/machinery/computer/mecha/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ExosuitControlConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "ExosuitControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/mecha/ui_data(mob/user)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/obj/mecha/proc/get_armour_facing(relative_dir)
|
||||
switch(relative_dir)
|
||||
if(0) // BACKSTAB!
|
||||
if(180) // BACKSTAB!
|
||||
return facing_modifiers[BACK_ARMOUR]
|
||||
if(45, 90, 270, 315)
|
||||
return facing_modifiers[SIDE_ARMOUR]
|
||||
if(225, 180, 135)
|
||||
if(0, 45) // direct or 45 degrees off
|
||||
return facing_modifiers[FRONT_ARMOUR]
|
||||
return 1 //always return non-0
|
||||
return facing_modifiers[SIDE_ARMOUR] //if its not a front hit or back hit then assume its from the side
|
||||
|
||||
/obj/mecha/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
@@ -43,7 +41,7 @@
|
||||
break
|
||||
|
||||
if(attack_dir)
|
||||
var/facing_modifier = get_armour_facing(dir2angle(attack_dir) - dir2angle(src))
|
||||
var/facing_modifier = get_armour_facing(abs(dir2angle(dir) - dir2angle(attack_dir)))
|
||||
booster_damage_modifier /= facing_modifier
|
||||
booster_deflection_modifier *= facing_modifier
|
||||
if(prob(deflect_chance * booster_deflection_modifier))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
anchored = TRUE
|
||||
light_range = 3
|
||||
var/movechance = 70
|
||||
var/obj/item/assembly/signaler/anomaly/aSignal
|
||||
var/obj/item/assembly/signaler/anomaly/aSignal = /obj/item/assembly/signaler/anomaly
|
||||
var/area/impact_area
|
||||
|
||||
var/lifespan = 990
|
||||
@@ -17,14 +17,20 @@
|
||||
var/countdown_colour
|
||||
var/obj/effect/countdown/anomaly/countdown
|
||||
|
||||
/obj/effect/anomaly/Initialize(mapload, new_lifespan)
|
||||
/// chance we drop a core when neutralized
|
||||
var/core_drop_chance = 100
|
||||
|
||||
/obj/effect/anomaly/Initialize(mapload, new_lifespan, core_drop_chance = 100)
|
||||
. = ..()
|
||||
GLOB.poi_list |= src
|
||||
START_PROCESSING(SSobj, src)
|
||||
impact_area = get_area(src)
|
||||
src.core_drop_chance = core_drop_chance
|
||||
|
||||
aSignal = new(src)
|
||||
aSignal.name = "[name] core"
|
||||
if (!impact_area)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
aSignal = new aSignal(src)
|
||||
aSignal.code = rand(1,100)
|
||||
aSignal.anomaly_type = type
|
||||
|
||||
@@ -52,6 +58,8 @@
|
||||
GLOB.poi_list.Remove(src)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel(countdown)
|
||||
if(aSignal)
|
||||
QDEL_NULL(aSignal)
|
||||
return ..()
|
||||
|
||||
/obj/effect/anomaly/proc/anomalyEffect()
|
||||
@@ -68,14 +76,14 @@
|
||||
/obj/effect/anomaly/proc/anomalyNeutralize()
|
||||
new /obj/effect/particle_effect/smoke/bad(loc)
|
||||
|
||||
for(var/atom/movable/O in src)
|
||||
O.forceMove(drop_location())
|
||||
if(prob(core_drop_chance))
|
||||
aSignal.forceMove(drop_location())
|
||||
aSignal = null
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/analyzer))
|
||||
if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed
|
||||
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>")
|
||||
|
||||
///////////////////////
|
||||
@@ -85,6 +93,7 @@
|
||||
icon_state = "shield2"
|
||||
density = FALSE
|
||||
var/boing = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/grav
|
||||
|
||||
/obj/effect/anomaly/grav/anomalyEffect()
|
||||
..()
|
||||
@@ -95,17 +104,23 @@
|
||||
for(var/mob/living/M in range(0, src))
|
||||
gravShock(M)
|
||||
for(var/mob/living/M in orange(4, src))
|
||||
step_towards(M,src)
|
||||
if(!M.mob_negates_gravity()) //delete when runtimed
|
||||
step_towards(M,src)
|
||||
for(var/obj/O in range(0,src))
|
||||
if(!O.anchored)
|
||||
//if(isturf(O.loc))
|
||||
// var/turf/T = O.loc
|
||||
// if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
|
||||
// continue
|
||||
var/mob/living/target = locate() in view(4,src)
|
||||
if(target && !target.stat)
|
||||
O.throw_at(target, 5, 10)
|
||||
|
||||
/obj/effect/anomaly/grav/Crossed(mob/A)
|
||||
gravShock(A)
|
||||
/obj/effect/anomaly/grav/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
gravShock(AM)
|
||||
|
||||
/obj/effect/anomaly/grav/Bump(mob/A)
|
||||
/obj/effect/anomaly/grav/Bump(atom/A)
|
||||
gravShock(A)
|
||||
|
||||
/obj/effect/anomaly/grav/Bumped(atom/movable/AM)
|
||||
@@ -138,6 +153,7 @@
|
||||
name = "flux wave anomaly"
|
||||
icon_state = "electricity2"
|
||||
density = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/flux
|
||||
var/canshock = FALSE
|
||||
var/shockdamage = 20
|
||||
var/explosive = TRUE
|
||||
@@ -148,11 +164,12 @@
|
||||
for(var/mob/living/M in range(0, src))
|
||||
mobShock(M)
|
||||
|
||||
/obj/effect/anomaly/flux/Crossed(mob/living/M)
|
||||
mobShock(M)
|
||||
/obj/effect/anomaly/flux/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
mobShock(AM)
|
||||
|
||||
/obj/effect/anomaly/flux/Bump(mob/living/M)
|
||||
mobShock(M)
|
||||
/obj/effect/anomaly/flux/Bump(atom/A)
|
||||
mobShock(A)
|
||||
|
||||
/obj/effect/anomaly/flux/Bumped(atom/movable/AM)
|
||||
mobShock(AM)
|
||||
@@ -160,7 +177,7 @@
|
||||
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
|
||||
if(canshock && istype(M))
|
||||
canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
|
||||
M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES)
|
||||
M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES)
|
||||
|
||||
/obj/effect/anomaly/flux/detonate()
|
||||
if(explosive)
|
||||
@@ -176,6 +193,7 @@
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "bluespace"
|
||||
density = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
|
||||
|
||||
/obj/effect/anomaly/bluespace/anomalyEffect()
|
||||
..()
|
||||
@@ -187,7 +205,7 @@
|
||||
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
|
||||
/obj/effect/anomaly/bluespace/detonate()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
var/turf/T = pick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
// Calculate new position (searches through beacons in world)
|
||||
var/obj/item/beacon/chosen
|
||||
@@ -224,21 +242,23 @@
|
||||
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
|
||||
A.forceMove(newloc)
|
||||
|
||||
spawn()
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.plane = FULLSCREEN_PLANE
|
||||
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
INVOKE_ASYNC(src, .proc/blue_effect, M)
|
||||
|
||||
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.plane = FULLSCREEN_PLANE
|
||||
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
|
||||
/////////////////////
|
||||
|
||||
@@ -246,6 +266,7 @@
|
||||
name = "pyroclastic anomaly"
|
||||
icon_state = "mustard"
|
||||
var/ticks = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/pyro
|
||||
|
||||
/obj/effect/anomaly/pyro/anomalyEffect()
|
||||
..()
|
||||
@@ -270,7 +291,7 @@
|
||||
S.rabid = TRUE
|
||||
S.amount_grown = SLIME_EVOLUTION_THRESHOLD
|
||||
S.Evolve()
|
||||
offer_control(S)
|
||||
offer_control(S,POLL_IGNORE_SENTIENCE_POTION)
|
||||
|
||||
/////////////////////
|
||||
|
||||
@@ -278,6 +299,7 @@
|
||||
name = "vortex anomaly"
|
||||
icon_state = "bhole3"
|
||||
desc = "That's a nice station you have there. It'd be a shame if something happened to it."
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/vortex
|
||||
|
||||
/obj/effect/anomaly/bhole/anomalyEffect()
|
||||
..()
|
||||
|
||||
@@ -46,4 +46,5 @@
|
||||
var/turf/T = loc
|
||||
if(!istype(T)) //you know this will happen somehow
|
||||
CRASH("Turf decal initialized in an object/nullspace")
|
||||
T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha)
|
||||
var/turn_dir = 180 - dir2angle(T.dir) //Turning a dir by 0 results in a roulette of random dirs.
|
||||
T.AddElement(/datum/element/decal, icon, icon_state, turn_dir ? turn(dir, turn_dir) : dir, CLEAN_GOD, color, null, null, alpha)
|
||||
|
||||
@@ -63,3 +63,23 @@
|
||||
|
||||
/datum/effect_system/lightning_spread
|
||||
effect_type = /obj/effect/particle_effect/sparks/electricity
|
||||
|
||||
//fake sparks, not subtyped because we don't want light/heat, nor checks inside an often used proc for a rare subcase for saving like 10 lines of code
|
||||
/obj/effect/particle_effect/fake_sparks
|
||||
name = "lightning"
|
||||
icon_state = "electricity"
|
||||
|
||||
/obj/effect/particle_effect/fake_sparks/Initialize()
|
||||
. = ..()
|
||||
flick(icon_state, src) // replay the animation
|
||||
playsound(src, "sparks", 100, TRUE)
|
||||
QDEL_IN(src, 20)
|
||||
|
||||
/datum/effect_system/fake_spark_spread
|
||||
effect_type = /obj/effect/particle_effect/fake_sparks
|
||||
|
||||
/proc/do_fake_sparks(n, c, source)
|
||||
var/datum/effect_system/fake_spark_spread/sparks = new
|
||||
sparks.set_up(n, c, source)
|
||||
sparks.autocleanup = TRUE
|
||||
sparks.start()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
|
||||
/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
|
||||
if(!istype(source) || !istype(destination))
|
||||
return
|
||||
var/turf/actual_destination = get_teleport_turf(destination, accuracy)
|
||||
var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override)
|
||||
var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override)
|
||||
var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override)
|
||||
var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override)
|
||||
if(!istype(P1)||!istype(P2))
|
||||
return
|
||||
P1.link_portal(P2)
|
||||
@@ -21,7 +21,6 @@
|
||||
var/obj/effect/portal/linked
|
||||
var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
|
||||
var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE
|
||||
var/creator
|
||||
var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
|
||||
var/atmos_link = FALSE //Link source/destination atmos.
|
||||
var/turf/open/atmos_source //Atmos link source
|
||||
@@ -35,6 +34,7 @@
|
||||
name = "wormhole"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "anom"
|
||||
layer = RIPPLE_LAYER
|
||||
mech_sized = TRUE
|
||||
teleport_channel = TELEPORT_CHANNEL_WORMHOLE
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
user.forceMove(get_turf(src))
|
||||
return TRUE
|
||||
|
||||
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
|
||||
/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0)
|
||||
if(force_stop)
|
||||
return ..()
|
||||
if(isobserver(AM))
|
||||
return ..()
|
||||
if(linked && (get_turf(oldloc) == get_turf(linked)))
|
||||
@@ -66,7 +68,7 @@
|
||||
if(Adjacent(user))
|
||||
user.forceMove(get_turf(src))
|
||||
|
||||
/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
|
||||
/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
|
||||
. = ..()
|
||||
GLOB.portals += src
|
||||
if(!istype(_linked) && automatic_link)
|
||||
@@ -78,7 +80,6 @@
|
||||
atmos_link = atmos_link_override
|
||||
link_portal(_linked)
|
||||
hardlinked = automatic_link
|
||||
creator = _creator
|
||||
if(isturf(hard_target_override))
|
||||
hard_target = hard_target_override
|
||||
|
||||
@@ -129,10 +130,7 @@
|
||||
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
|
||||
atmos_destination = null
|
||||
|
||||
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
|
||||
if(creator && hascall(creator, "on_portal_destroy"))
|
||||
call(creator, "on_portal_destroy")(src, src.loc)
|
||||
creator = null
|
||||
/obj/effect/portal/Destroy()
|
||||
GLOB.portals -= src
|
||||
unlink_atmos()
|
||||
if(hardlinked && !QDELETED(linked))
|
||||
@@ -153,8 +151,6 @@
|
||||
return FALSE
|
||||
if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored))
|
||||
return
|
||||
if(ismegafauna(M))
|
||||
message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].")
|
||||
var/no_effect = FALSE
|
||||
if(last_effect == world.time)
|
||||
no_effect = TRUE
|
||||
|
||||
@@ -168,3 +168,26 @@
|
||||
items = list(
|
||||
/obj/item/clothing/mask/gas/sexymime,
|
||||
/obj/item/clothing/under/rank/civilian/mime/sexy)
|
||||
|
||||
/obj/effect/spawner/bundle/crate/Initialize(mapload)
|
||||
if(items && items.len)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/closet/LC = locate(/obj/structure/closet) in T
|
||||
if(LC)
|
||||
for(var/path in items)
|
||||
new path(LC)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/spawner/bundle/crate/mosin
|
||||
name = "Mosin-Nagant spawner"
|
||||
items = list(
|
||||
/obj/item/gun/ballistic/shotgun/boltaction,
|
||||
/obj/item/ammo_box/a762
|
||||
)
|
||||
|
||||
/obj/effect/spawner/bundle/crate/surplusrifle
|
||||
name = "surplus rifle spawner"
|
||||
items = list(
|
||||
/obj/item/gun/ballistic/automatic/surplus,
|
||||
/obj/item/ammo_box/magazine/m10mm/rifle
|
||||
)
|
||||
|
||||
@@ -380,8 +380,6 @@
|
||||
name = "random keg spawner"
|
||||
lootcount = 1
|
||||
loot = list(/obj/structure/reagent_dispensers/keg/mead = 5,
|
||||
/obj/structure/reagent_dispensers/keg/aphro = 2,
|
||||
/obj/structure/reagent_dispensers/keg/aphro/strong = 2,
|
||||
/obj/structure/reagent_dispensers/keg/gargle = 1)
|
||||
|
||||
/obj/effect/spawner/lootdrop/coin
|
||||
|
||||
@@ -139,6 +139,23 @@
|
||||
/obj/effect/temp_visual/dir_setting/curse/hand
|
||||
icon_state = "cursehand"
|
||||
|
||||
/obj/effect/temp_visual/bsa_splash
|
||||
name = "\improper Bluespace energy wave"
|
||||
desc = "A massive, rippling wave of bluepace energy, all rapidly exhausting itself the moment it leaves the concentrated beam of light."
|
||||
icon = 'icons/effects/beam_splash.dmi'
|
||||
icon_state = "beam_splash_l"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
pixel_y = -16
|
||||
duration = 50
|
||||
|
||||
/obj/effect/temp_visual/bsa_splash/Initialize(mapload, dir)
|
||||
. = ..()
|
||||
switch(dir)
|
||||
if(WEST)
|
||||
icon_state = "beam_splash_w"
|
||||
if(EAST)
|
||||
icon_state = "beam_splash_e"
|
||||
|
||||
/obj/effect/temp_visual/wizard
|
||||
name = "water"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
|
||||
@@ -103,12 +103,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
|
||||
|
||||
var/list/embedding = NONE
|
||||
var/list/embedding
|
||||
|
||||
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
|
||||
var/heat = 0
|
||||
///All items with sharpness of IS_SHARP or higher will automatically get the butchering component.
|
||||
var/sharpness = IS_BLUNT
|
||||
///All items with sharpness of SHARP_EDGED or higher will automatically get the butchering component.
|
||||
var/sharpness = SHARP_NONE
|
||||
|
||||
var/tool_behaviour = NONE
|
||||
var/toolspeed = 1
|
||||
@@ -206,7 +206,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
if(GLOB.rpg_loot_items)
|
||||
AddComponent(/datum/component/fantasy)
|
||||
|
||||
if(sharpness) //give sharp objects butchering functionality, for consistency
|
||||
if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency
|
||||
AddComponent(/datum/component/butchering, 80 * toolspeed)
|
||||
|
||||
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
|
||||
@@ -1088,7 +1088,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
|
||||
|
||||
/obj/item/proc/updateEmbedding()
|
||||
if(!islist(embedding) || !LAZYLEN(embedding))
|
||||
if(!LAZYLEN(embedding))
|
||||
return
|
||||
|
||||
AddElement(/datum/element/embed,\
|
||||
|
||||
@@ -135,6 +135,14 @@ RLD
|
||||
flick("[icon_state]_empty", src) //somewhat hacky thing to make RCDs with ammo counters actually have a blinking yellow light
|
||||
return .
|
||||
|
||||
|
||||
/obj/item/construction/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/proc/range_check(atom/A, mob/user)
|
||||
if(!(A in range(custom_range, get_turf(user))))
|
||||
to_chat(user, "<span class='warning'>The \'Out of Range\' light on [src] blinks red.</span>")
|
||||
@@ -234,7 +242,6 @@ RLD
|
||||
|
||||
var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500, src)
|
||||
popup.set_content(t1)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/item/construction/rcd/Topic(href, href_list)
|
||||
@@ -276,13 +283,6 @@ RLD
|
||||
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
|
||||
return MA
|
||||
|
||||
/obj/item/construction/rcd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
@@ -856,6 +856,82 @@ RLD
|
||||
desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells."
|
||||
upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS
|
||||
|
||||
/obj/item/construction/plumbing
|
||||
name = "Plumbing Constructor"
|
||||
desc = "An expertly modified RCD outfitted to construct plumbing machinery. Reload with compressed matter cartridges."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "arcd"
|
||||
item_state = "oldrcd"
|
||||
has_ammobar = FALSE
|
||||
matter = 200
|
||||
max_matter = 200
|
||||
|
||||
///type of the plumbing machine
|
||||
var/blueprint = null
|
||||
///index, used in the attack self to get the type. stored here since it doesnt change
|
||||
var/list/choices = list()
|
||||
///index, used in the attack self to get the type. stored here since it doesnt change
|
||||
var/list/name_to_type = list()
|
||||
///
|
||||
var/list/machinery_data = list("cost" = list(), "delay" = list())
|
||||
|
||||
/obj/item/construction/plumbing/attack_self(mob/user)
|
||||
..()
|
||||
if(!choices.len)
|
||||
for(var/A in subtypesof(/obj/machinery/plumbing))
|
||||
var/obj/machinery/plumbing/M = A
|
||||
if(initial(M.rcd_constructable))
|
||||
choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state)))
|
||||
name_to_type[initial(M.name)] = M
|
||||
machinery_data["cost"][A] = initial(M.rcd_cost)
|
||||
machinery_data["delay"][A] = initial(M.rcd_delay)
|
||||
|
||||
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
|
||||
blueprint = name_to_type[choice]
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
|
||||
to_chat(user, "<span class='notice'>You change [name]s blueprint to '[choice]'.</span>")
|
||||
|
||||
///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type
|
||||
/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user)
|
||||
if(!machinery_data || !isopenturf(A))
|
||||
return FALSE
|
||||
|
||||
if(checkResource(machinery_data["cost"][blueprint], user) && blueprint)
|
||||
if(do_after(user, machinery_data["delay"][blueprint], target = A))
|
||||
if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A))
|
||||
useResource(machinery_data["cost"][blueprint], user)
|
||||
activate()
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
|
||||
new blueprint (A, FALSE, FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/plumbing/proc/canPlace(turf/T)
|
||||
if(!isopenturf(T))
|
||||
return FALSE
|
||||
. = TRUE
|
||||
for(var/obj/O in T.contents)
|
||||
if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion
|
||||
return FALSE
|
||||
|
||||
/obj/item/construction/plumbing/afterattack(atom/A, mob/user)
|
||||
. = ..()
|
||||
if(!range_check(A, user))
|
||||
return
|
||||
if(istype(A, /obj/machinery/plumbing))
|
||||
var/obj/machinery/plumbing/P = A
|
||||
if(P.anchored)
|
||||
to_chat(user, "<span class='warning'>The [P.name] needs to be unanchored!</span>")
|
||||
return
|
||||
if(do_after(user, 20, target = P))
|
||||
P.deconstruct() //Let's not substract matter
|
||||
playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
|
||||
else
|
||||
create_machine(A, user)
|
||||
|
||||
|
||||
#undef GLOW_MODE
|
||||
#undef LIGHT_MODE
|
||||
#undef REMOVE_MODE
|
||||
|
||||
@@ -6,6 +6,7 @@ RPD
|
||||
#define ATMOS_CATEGORY 0
|
||||
#define DISPOSALS_CATEGORY 1
|
||||
#define TRANSIT_CATEGORY 2
|
||||
#define PLUMBING_CATEGORY 3
|
||||
|
||||
#define BUILD_MODE (1<<0)
|
||||
#define WRENCH_MODE (1<<1)
|
||||
@@ -75,6 +76,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
)
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(fluid_duct_recipes, list(
|
||||
"Fluid Ducts" = list(
|
||||
new /datum/pipe_info/plumbing("Duct", /obj/machinery/duct, PIPE_ONEDIR),
|
||||
new /datum/pipe_info/plumbing/multilayer("Duct Layer-Manifold",/obj/machinery/duct/multilayered, PIPE_STRAIGHT)
|
||||
)
|
||||
))
|
||||
|
||||
/datum/pipe_info
|
||||
var/name
|
||||
var/icon_state
|
||||
@@ -175,6 +183,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
if(dt == PIPE_UNARY_FLIPPABLE)
|
||||
icon_state = "[icon_state]_preview"
|
||||
|
||||
/datum/pipe_info/plumbing/New(label, obj/path, dt=PIPE_UNARY)
|
||||
name = label
|
||||
id = path
|
||||
icon_state = initial(path.icon_state)
|
||||
dirtype = dt
|
||||
|
||||
/datum/pipe_info/plumbing/multilayer //exists as identifier so we can see the difference between multi_layer and just ducts properly later on
|
||||
|
||||
|
||||
/obj/item/pipe_dispenser
|
||||
name = "Rapid Piping Device (RPD)"
|
||||
desc = "A device used to rapidly pipe things."
|
||||
@@ -200,15 +217,19 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
var/atmos_build_speed = 5 //deciseconds (500ms)
|
||||
var/disposal_build_speed = 5
|
||||
var/transit_build_speed = 5
|
||||
var/plumbing_build_speed = 5
|
||||
var/destroy_speed = 5
|
||||
var/paint_speed = 5
|
||||
var/category = ATMOS_CATEGORY
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
var/ducting_layer = DUCT_LAYER_DEFAULT
|
||||
var/datum/pipe_info/recipe
|
||||
var/static/datum/pipe_info/first_atmos
|
||||
var/static/datum/pipe_info/first_disposal
|
||||
var/static/datum/pipe_info/first_transit
|
||||
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
|
||||
var/static/datum/pipe_info/first_plumbing
|
||||
var/locked = FALSE //wheter we can change categories. Useful for the plumber
|
||||
|
||||
/obj/item/pipe_dispenser/New()
|
||||
. = ..()
|
||||
@@ -238,29 +259,30 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/pipe_dispenser/ui_base_html(html)
|
||||
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
|
||||
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
|
||||
/obj/item/pipe_dispenser/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/pipes),
|
||||
)
|
||||
|
||||
/obj/item/pipe_dispenser/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)
|
||||
/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
|
||||
assets.send(user)
|
||||
|
||||
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
|
||||
ui = new(user, src, "RapidPipeDispenser", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/pipe_dispenser/ui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"category" = category,
|
||||
"piping_layer" = piping_layer,
|
||||
|
||||
"ducting_layer" = ducting_layer,
|
||||
|
||||
"preview_rows" = recipe.get_preview(p_dir),
|
||||
"categories" = list(),
|
||||
"selected_color" = paint_color,
|
||||
"paint_colors" = GLOB.pipe_paint_colors,
|
||||
"mode" = mode
|
||||
"mode" = mode,
|
||||
"locked" = locked
|
||||
)
|
||||
|
||||
var/list/recipes
|
||||
@@ -271,6 +293,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
recipes = GLOB.disposal_pipe_recipes
|
||||
if(TRANSIT_CATEGORY)
|
||||
recipes = GLOB.transit_tube_recipes
|
||||
if(PLUMBING_CATEGORY)
|
||||
recipes = GLOB.fluid_duct_recipes
|
||||
for(var/c in recipes)
|
||||
var/list/cat = recipes[c]
|
||||
var/list/r = list()
|
||||
@@ -284,7 +308,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
/obj/item/pipe_dispenser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src))
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
var/playeffect = TRUE
|
||||
switch(action)
|
||||
@@ -299,11 +323,16 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
recipe = first_atmos
|
||||
if(TRANSIT_CATEGORY)
|
||||
recipe = first_transit
|
||||
if(PLUMBING_CATEGORY)
|
||||
recipe = first_plumbing
|
||||
p_dir = NORTH
|
||||
playeffect = FALSE
|
||||
if("piping_layer")
|
||||
piping_layer = text2num(params["piping_layer"])
|
||||
playeffect = FALSE
|
||||
// if("ducting_layer")
|
||||
// ducting_layer = text2num(params["ducting_layer"])
|
||||
// playeffect = FALSE
|
||||
if("pipe_type")
|
||||
var/static/list/recipes
|
||||
if(!recipes)
|
||||
@@ -320,11 +349,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
mode &= ~n
|
||||
else
|
||||
mode |= n
|
||||
|
||||
if(playeffect && world.time >= effectcooldown)
|
||||
if(playeffect)
|
||||
spark_system.start()
|
||||
effectcooldown = world.time + 100
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
|
||||
@@ -469,16 +496,56 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
if(mode & WRENCH_MODE)
|
||||
tube.wrench_act(user, src)
|
||||
return
|
||||
|
||||
if(PLUMBING_CATEGORY) //Plumbing.
|
||||
if(!can_make_pipe)
|
||||
return ..()
|
||||
A = get_turf(A)
|
||||
if(isclosedturf(A))
|
||||
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start building a fluid duct...</span>")
|
||||
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
|
||||
if(do_after(user, plumbing_build_speed, target = A))
|
||||
var/obj/machinery/duct/D
|
||||
if(recipe.type == /datum/pipe_info/plumbing/multilayer)
|
||||
var/temp_connects = NORTH + SOUTH
|
||||
if(queued_p_dir == EAST)
|
||||
temp_connects = EAST + WEST
|
||||
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer, temp_connects)
|
||||
else
|
||||
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer)
|
||||
D.add_fingerprint(usr)
|
||||
if(mode & WRENCH_MODE)
|
||||
D.wrench_act(user, src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe_dispenser/proc/activate()
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
/* unneeded, you can craft ducts from plastic
|
||||
/obj/item/pipe_dispenser/plumbing
|
||||
name = "Plumberinator"
|
||||
desc = "A crude device to rapidly plumb things."
|
||||
icon_state = "plumberer"
|
||||
category = PLUMBING_CATEGORY
|
||||
locked = TRUE
|
||||
|
||||
/obj/item/pipe_dispenser/plumbing/Initialize()
|
||||
. = ..()
|
||||
spark_system = new
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
if(!first_plumbing)
|
||||
first_plumbing = GLOB.fluid_duct_recipes[GLOB.fluid_duct_recipes[1]][1]
|
||||
|
||||
recipe = first_plumbing
|
||||
|
||||
*/
|
||||
|
||||
#undef ATMOS_CATEGORY
|
||||
#undef DISPOSALS_CATEGORY
|
||||
#undef TRANSIT_CATEGORY
|
||||
#undef PLUMBING_CATEGORY
|
||||
|
||||
#undef BUILD_MODE
|
||||
#undef DESTROY_MODE
|
||||
|
||||
@@ -180,10 +180,10 @@
|
||||
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
|
||||
return
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "DecalPainter", name, 500, 400, master_ui, state)
|
||||
ui = new(user, src, "DecalPainter", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_data(mob/user)
|
||||
|
||||
@@ -28,39 +28,37 @@
|
||||
/// triggered on wield of two handed item
|
||||
/obj/item/broom/proc/on_wield(obj/item/source, mob/user)
|
||||
to_chat(user, "<span class='notice'>You brace the [src] against the ground in a firm sweeping stance.</span>")
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/sweep)
|
||||
RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, .proc/sweep)
|
||||
|
||||
/// triggered on unwield of two handed item
|
||||
/obj/item/broom/proc/on_unwield(obj/item/source, mob/user)
|
||||
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
|
||||
UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE)
|
||||
|
||||
/obj/item/broom/afterattack(atom/A, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
sweep(user, A, FALSE)
|
||||
sweep(user, A)
|
||||
|
||||
/obj/item/broom/proc/sweep(mob/user, atom/A, moving = TRUE)
|
||||
var/turf/target
|
||||
if (!moving)
|
||||
if (isturf(A))
|
||||
target = A
|
||||
else
|
||||
target = A.loc
|
||||
else
|
||||
target = user.loc
|
||||
if (!isturf(target))
|
||||
/obj/item/broom/proc/sweep(datum/source, atom/newLoc)
|
||||
if(!ismob(source) || !isturf(newLoc) || (get_dist(source, newLoc) > 1))
|
||||
return
|
||||
if (locate(/obj/structure/table) in target.contents)
|
||||
var/turf/target = newLoc
|
||||
var/atom/movable/AM
|
||||
var/sweep_dir = get_dir(source, target)
|
||||
if(!sweep_dir)
|
||||
return
|
||||
for(var/i in target.contents)
|
||||
AM = i
|
||||
if(AM.density) // eh good enough heuristic check
|
||||
return
|
||||
var/i = 0
|
||||
for(var/obj/item/garbage in target.contents)
|
||||
if(!garbage.anchored)
|
||||
garbage.Move(get_step(target, user.dir), user.dir)
|
||||
i++
|
||||
if(i >= 20)
|
||||
step(garbage, sweep_dir)
|
||||
if(++i > 20)
|
||||
break
|
||||
if(i >= 1)
|
||||
if(i)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 30, TRUE, -1)
|
||||
|
||||
/obj/item/broom/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) //bless you whoever fixes this copypasta
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
custom_materials = list(/datum/material/iron=13000)
|
||||
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
|
||||
hitsound = "swing_hit"
|
||||
sharpness = IS_SHARP
|
||||
sharpness = SHARP_EDGED
|
||||
actions_types = list(/datum/action/item_action/startchainsaw)
|
||||
tool_behaviour = TOOL_SAW
|
||||
toolspeed = 0.5
|
||||
@@ -71,10 +71,6 @@
|
||||
/obj/item/chainsaw/update_icon_state()
|
||||
icon_state = "chainsaw_[on ? "on" : "off"]"
|
||||
|
||||
/obj/item/chainsaw/get_dismemberment_chance()
|
||||
if(wielded)
|
||||
. = ..()
|
||||
|
||||
/obj/item/chainsaw/doomslayer
|
||||
name = "THE GREAT COMMUNICATOR"
|
||||
desc = "<span class='warning'>VRRRRRRR!!!</span>"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/ignores_timeout = FALSE
|
||||
var/response_timer_id = null
|
||||
var/approval_time = 600
|
||||
var/allow_unicode = FALSE
|
||||
|
||||
var/static/regex/standard_station_regex
|
||||
|
||||
@@ -48,6 +49,9 @@
|
||||
|
||||
if(!new_name)
|
||||
return
|
||||
if(!allow_unicode && (length(new_name) != length_char(new_name)))
|
||||
to_chat(user, "Unicode is not allowed. Adminhelp if you want to use it so badly.")
|
||||
return
|
||||
log_game("[key_name(user)] has proposed to name the station as \
|
||||
[new_name]")
|
||||
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/medipen_refiller
|
||||
name = "Medipen Refiller (Machine Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/medipen_refiller
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/clonepod
|
||||
name = "Clone Pod (Machine Board)"
|
||||
build_path = /obj/machinery/clonepod
|
||||
@@ -383,7 +390,7 @@
|
||||
|
||||
/obj/item/circuitboard/machine/thermomachine/examine()
|
||||
. = ..()
|
||||
. += "<span class='notice'>It is set to layer [pipe_layer].</span>"
|
||||
. += "<span class='notice'>It is set to layer [pipe_layer]. Use a Multitool on the circuit to change this.</span>"
|
||||
|
||||
/obj/item/circuitboard/machine/thermomachine/heater
|
||||
name = "Heater (Machine Board)"
|
||||
@@ -512,6 +519,10 @@
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/hydroponics/automagic
|
||||
name = "Automatic Hydroponics Tray (Machine Board)"
|
||||
build_path = /obj/machinery/hydroponics/constructable/automagic
|
||||
|
||||
/obj/item/circuitboard/machine/seed_extractor
|
||||
name = "Seed Extractor (Machine Board)"
|
||||
build_path = /obj/machinery/seed_extractor
|
||||
@@ -1135,3 +1146,8 @@
|
||||
build_path = /obj/machinery/atmospherics/components/unary/shuttle/heater
|
||||
req_components = list(/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stock_parts/matter_bin = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/explosive_compressor
|
||||
name = "Explosive Compressor (Machine Board)"
|
||||
build_path = /obj/machinery/research/explosive_compressor
|
||||
req_components = list(/obj/item/stock_parts/matter_bin = 3)
|
||||
|
||||
@@ -147,23 +147,23 @@
|
||||
to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>")
|
||||
. = TRUE
|
||||
|
||||
/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
// tgui is a plague upon this codebase
|
||||
/obj/item/toy/crayon/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui)
|
||||
// tgui is a plague upon this codebase
|
||||
// no u
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Crayon", name, 600, 600,
|
||||
master_ui, state)
|
||||
ui = new(user, src, "Crayon", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
if(has_cap)
|
||||
is_capped = !is_capped
|
||||
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/crayon/CtrlClick(mob/user)
|
||||
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
@@ -735,7 +735,11 @@
|
||||
if(isobj(target))
|
||||
if(actually_paints)
|
||||
var/list/hsl = rgb2hsl(hex2num(copytext(paint_color,2,4)),hex2num(copytext(paint_color,4,6)),hex2num(copytext(paint_color,6,8)))
|
||||
if(hsl[3] < 0.25 && !istype(target, /obj/structure/window) && !istype(target, /obj/effect/decal/cleanable/crayon)) //Colors too dark are rejected
|
||||
var/static/whitelisted = typecacheof(list(/obj/structure/window,
|
||||
/obj/effect/decal/cleanable/crayon,
|
||||
/obj/machinery/door/window)
|
||||
)
|
||||
if(hsl[3] < 0.25 && !whitelisted[target]) //Colors too dark are rejected
|
||||
to_chat(usr, "<span class='warning'>A color that dark on an object like this? Surely not...</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -394,8 +394,6 @@
|
||||
to_chat(user, "<span class='warning'>[src] are recharging!</span>")
|
||||
return
|
||||
|
||||
user.stop_pulling() //User has hands full, and we don't care about anyone else pulling on it, their problem. CLEAR!!
|
||||
|
||||
if(user.a_intent == INTENT_DISARM)
|
||||
do_disarm(M, user)
|
||||
return
|
||||
@@ -447,8 +445,7 @@
|
||||
if(do_after(user, isnull(defib?.disarm_shock_time)? disarm_shock_time : defib.disarm_shock_time, target = M))
|
||||
M.visible_message("<span class='danger'>[user] zaps [M] with [src]!</span>", \
|
||||
"<span class='userdanger'>[user] zaps [M] with [src]!</span>")
|
||||
M.adjustStaminaLoss(50)
|
||||
M.DefaultCombatKnockdown(100)
|
||||
M.DefaultCombatKnockdown(140)
|
||||
M.updatehealth() //forces health update before next life tick
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
M.emote("gasp")
|
||||
|
||||
@@ -266,7 +266,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
|
||||
assets.send(user)
|
||||
|
||||
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/goonchat)
|
||||
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/chat)
|
||||
emoji_s.send(user) //Already sent by chat but no harm doing this
|
||||
|
||||
user.set_machine(src)
|
||||
@@ -1027,6 +1027,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
else if(is_type_in_list(C, contained_item)) //Checks if there is a pen
|
||||
if(inserted_item)
|
||||
to_chat(user, "<span class='warning'>There is already \a [inserted_item] in \the [src]!</span>")
|
||||
return ..()
|
||||
else
|
||||
if(!user.transferItemToLoc(C, src))
|
||||
return
|
||||
|
||||
@@ -590,7 +590,7 @@ Code:
|
||||
var/static/list/emoji_icon_states
|
||||
var/static/emoji_table
|
||||
if(!emoji_table)
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat)
|
||||
var/list/collate = list("<br><table>")
|
||||
for(var/emoji in sortList(icon_states(icon('icons/emoji.dmi'))))
|
||||
var/tag = sheet.icon_tag("emoji-[emoji]")
|
||||
|
||||
@@ -54,18 +54,20 @@
|
||||
name = initial(name)
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/aicard/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state)
|
||||
ui = new(user, src, "Intellicard", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/aicard/ui_data()
|
||||
var/list/data = list()
|
||||
if(AI)
|
||||
data["name"] = AI.name
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
|
||||
data["health"] = (AI.health + 100) / 2
|
||||
data["wireless"] = !AI.control_disabled //todo disabled->enabled
|
||||
data["radio"] = AI.radio_enabled
|
||||
@@ -86,19 +88,19 @@
|
||||
if(confirm == "Yes" && !..())
|
||||
flush = TRUE
|
||||
if(AI && AI.loc == src)
|
||||
to_chat(AI, "Your core files are being wiped!")
|
||||
to_chat(AI, "<span class='userdanger'>Your core files are being wiped!</span>")
|
||||
while(AI.stat != DEAD && flush)
|
||||
AI.adjustOxyLoss(1)
|
||||
AI.adjustOxyLoss(5)
|
||||
AI.updatehealth()
|
||||
sleep(5)
|
||||
flush = FALSE
|
||||
. = TRUE
|
||||
if("wireless")
|
||||
AI.control_disabled = !AI.control_disabled
|
||||
to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!")
|
||||
to_chat(AI, "<span class='warning'>[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!</span>")
|
||||
. = TRUE
|
||||
if("radio")
|
||||
AI.radio_enabled = !AI.radio_enabled
|
||||
to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!")
|
||||
to_chat(AI, "<span class='warning'>Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!</span>")
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -163,12 +163,13 @@
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/dogborg/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)
|
||||
/obj/item/dogborg/sleeper/ui_state(mob/user)
|
||||
return GLOB.notcontained_state
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/dogborg/sleeper/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state)
|
||||
ui = new(user, src, "dogborg_sleeper", name, 375, 550) //UI DOES NOT EXIST
|
||||
ui.open()
|
||||
|
||||
/obj/item/dogborg/sleeper/ui_data()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user