Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into DRAKEBORG
This commit is contained in:
@@ -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
|
||||
@@ -516,7 +518,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
used_environ += amount
|
||||
|
||||
|
||||
/area/Entered(atom/movable/M)
|
||||
/area/Entered(atom/movable/M, atom/OldLoc)
|
||||
set waitfor = FALSE
|
||||
SEND_SIGNAL(src, COMSIG_AREA_ENTERED, M)
|
||||
SEND_SIGNAL(M, COMSIG_ENTER_AREA, src) //The atom that enters the area
|
||||
@@ -524,6 +526,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
return
|
||||
|
||||
var/mob/living/L = M
|
||||
var/turf/oldTurf = get_turf(OldLoc)
|
||||
var/area/A = oldTurf?.loc
|
||||
if(A && (A.has_gravity != has_gravity))
|
||||
L.update_gravity(L.mob_has_gravity())
|
||||
|
||||
if(!L.ckey)
|
||||
return
|
||||
|
||||
@@ -567,6 +574,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
power_environ = FALSE
|
||||
always_unpowered = FALSE
|
||||
valid_territory = FALSE
|
||||
valid_malf_hack = FALSE
|
||||
blob_allowed = FALSE
|
||||
addSorted()
|
||||
|
||||
|
||||
+57
-11
@@ -70,6 +70,9 @@
|
||||
/// A luminescence-shifted value of the last color calculated for chatmessage overlays
|
||||
var/chat_color_darkened
|
||||
|
||||
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
|
||||
var/list/targeted_by
|
||||
|
||||
/atom/New(loc, ...)
|
||||
//atom creation method that preloads variables at creation
|
||||
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
|
||||
@@ -101,6 +104,8 @@
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
|
||||
if(loc)
|
||||
SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc`
|
||||
//atom color stuff
|
||||
if(color)
|
||||
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
@@ -142,6 +147,11 @@
|
||||
LAZYCLEARLIST(overlays)
|
||||
LAZYCLEARLIST(priority_overlays)
|
||||
|
||||
for(var/i in targeted_by)
|
||||
var/mob/M = i
|
||||
LAZYREMOVE(M.do_afters, src)
|
||||
targeted_by = null
|
||||
|
||||
QDEL_NULL(light)
|
||||
|
||||
return ..()
|
||||
@@ -217,7 +227,7 @@
|
||||
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
|
||||
if(does_attack_animation)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
log_combat(user, src, "punched", "hulk powers")
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_SMASH)
|
||||
|
||||
@@ -741,7 +751,7 @@
|
||||
flags_1 |= ADMIN_SPAWNED_1
|
||||
. = ..()
|
||||
switch(var_name)
|
||||
if("color")
|
||||
if(NAMEOF(src, color))
|
||||
add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
|
||||
|
||||
/atom/vv_get_dropdown()
|
||||
@@ -930,6 +940,8 @@
|
||||
log_game(log_text)
|
||||
if(LOG_GAME)
|
||||
log_game(log_text)
|
||||
if(LOG_SHUTTLE)
|
||||
log_shuttle(log_text)
|
||||
else
|
||||
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
|
||||
log_game(log_text)
|
||||
@@ -950,15 +962,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)
|
||||
@@ -982,6 +995,39 @@ Proc for attack log creation, because really why not
|
||||
var/reverse_message = "has been [what_done] by [ssource][postfix]"
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
|
||||
/**
|
||||
* log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over
|
||||
*
|
||||
* Note that this has no info on the attack that dealt the wound: information about where damage came from isn't passed to the bodypart's damaged proc. When in doubt, check the attack log for attacks at that same time
|
||||
* TODO later: Add logging for healed wounds, though that will require some rewriting of healing code to prevent admin heals from spamming the logs. Not high priority
|
||||
*
|
||||
* Arguments:
|
||||
* * victim- The guy who got wounded
|
||||
* * suffered_wound- The wound, already applied, that we're logging. It has to already be attached so we can get the limb from it
|
||||
* * dealt_damage- How much damage is associated with the attack that dealt with this wound.
|
||||
* * dealt_wound_bonus- The wound_bonus, if one was specified, of the wounding attack
|
||||
* * dealt_bare_wound_bonus- The bare_wound_bonus, if one was specified *and applied*, of the wounding attack. Not shown if armor was present
|
||||
* * base_roll- Base wounding ability of an attack is a random number from 1 to (dealt_damage ** WOUND_DAMAGE_EXPONENT). This is the number that was rolled in there, before mods
|
||||
*/
|
||||
/proc/log_wound(atom/victim, datum/wound/suffered_wound, dealt_damage, dealt_wound_bonus, dealt_bare_wound_bonus, base_roll)
|
||||
if(QDELETED(victim) || !suffered_wound)
|
||||
return
|
||||
var/message = "has suffered: [suffered_wound][suffered_wound.limb ? " to [suffered_wound.limb.name]" : null]"// maybe indicate if it's a promote/demote?
|
||||
|
||||
if(dealt_damage)
|
||||
message += " | Damage: [dealt_damage]"
|
||||
// The base roll is useful since it can show how lucky someone got with the given attack. For example, dealing a cut
|
||||
if(base_roll)
|
||||
message += " (rolled [base_roll]/[dealt_damage ** WOUND_DAMAGE_EXPONENT])"
|
||||
|
||||
if(dealt_wound_bonus)
|
||||
message += " | WB: [dealt_wound_bonus]"
|
||||
|
||||
if(dealt_bare_wound_bonus)
|
||||
message += " | BWB: [dealt_bare_wound_bonus]"
|
||||
|
||||
victim.log_message(message, LOG_ATTACK, color="blue")
|
||||
|
||||
// Filter stuff
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
|
||||
@@ -120,25 +120,25 @@
|
||||
if((var_name in careful_edits) && (var_value % world.icon_size) != 0)
|
||||
return FALSE
|
||||
switch(var_name)
|
||||
if("x")
|
||||
if(NAMEOF(src, x))
|
||||
var/turf/T = locate(var_value, y, z)
|
||||
if(T)
|
||||
forceMove(T)
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("y")
|
||||
if(NAMEOF(src, y))
|
||||
var/turf/T = locate(x, var_value, z)
|
||||
if(T)
|
||||
forceMove(T)
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("z")
|
||||
if(NAMEOF(src, z))
|
||||
var/turf/T = locate(x, y, var_value)
|
||||
if(T)
|
||||
forceMove(T)
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("loc")
|
||||
if(NAMEOF(src, loc))
|
||||
if(istype(var_value, /atom))
|
||||
forceMove(var_value)
|
||||
return TRUE
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// To be removed on step_ conversion
|
||||
// All this work to prevent a second bump
|
||||
/atom/movable/Move(atom/newloc, direct=0)
|
||||
set waitfor = FALSE //n o
|
||||
. = FALSE
|
||||
if(!newloc || newloc == loc)
|
||||
return
|
||||
@@ -52,6 +53,7 @@
|
||||
////////////////////////////////////////
|
||||
|
||||
/atom/movable/Move(atom/newloc, direct)
|
||||
set waitfor = FALSE //n o
|
||||
var/atom/movable/pullee = pulling
|
||||
var/turf/T = loc
|
||||
if(!moving_from_pull)
|
||||
|
||||
@@ -38,7 +38,8 @@ Credit where due:
|
||||
5. Xhuis from /tg/ for coding the first iteration of the mode, and the new, reworked version
|
||||
6. ChangelingRain from /tg/ for maintaining the gamemode for months after its release prior to its rework
|
||||
7. Clockwork cult code as of now, at least the one being pulled from Citadel Station's master branch, is being, or already is, fixed by Coolgat3 and Avunia.
|
||||
|
||||
8. Modern clockwork cult code mixed with original clockwork code, with various changes to make it less of a fustercluck, done by KeRSe. \
|
||||
Fixes and assistance done by TimothyTeakettle, Kevinz000, and Deltafire15. -Very glad for the help they gave.
|
||||
*/
|
||||
|
||||
///////////
|
||||
@@ -133,7 +134,7 @@ Credit where due:
|
||||
config_tag = "clockwork_cult"
|
||||
antag_flag = ROLE_SERVANT_OF_RATVAR
|
||||
false_report_weight = 10
|
||||
required_players = 35
|
||||
required_players = 24 //Fixing this directly for now since apparently config machine for forcing modes broke.
|
||||
required_enemies = 3
|
||||
recommended_enemies = 5
|
||||
enemy_minimum_age = 7
|
||||
@@ -143,13 +144,12 @@ Credit where due:
|
||||
announce_text = "Servants of Ratvar are trying to summon the Justiciar!\n\
|
||||
<span class='brass'>Servants</span>: Construct defenses to protect the Ark. Sabotage the station!\n\
|
||||
<span class='notice'>Crew</span>: Stop the servants before they can summon the Clockwork Justiciar."
|
||||
var/servants_to_serve = list()
|
||||
var/list/servants_to_serve = list() //Yes this list is made out of list
|
||||
var/roundstart_player_count
|
||||
var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.)
|
||||
|
||||
var/datum/team/clockcult/main_clockcult
|
||||
|
||||
/datum/game_mode/clockwork_cult/pre_setup()
|
||||
/datum/game_mode/clockwork_cult/pre_setup() //Gamemode and job code is pain. Have fun codediving all of that stuff, whoever works on this next - Delta
|
||||
var/list/errorList = list()
|
||||
var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
|
||||
if(errorList.len) // reebe failed to load
|
||||
@@ -162,38 +162,36 @@ Credit where due:
|
||||
restricted_jobs += protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
var/starter_servants = 4 //Guaranteed four servants
|
||||
var/starter_servants = 4 //Try to go for at least four
|
||||
var/number_players = num_players()
|
||||
roundstart_player_count = number_players
|
||||
if(number_players > 30) //plus one servant for every additional 10 players above 30
|
||||
number_players -= 30
|
||||
starter_servants += round(number_players / 10)
|
||||
starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players)
|
||||
GLOB.clockwork_vitality += 50 * starter_servants //some starter Vitality to help recover from initial fuck ups
|
||||
starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players)
|
||||
while(starter_servants)
|
||||
if(!antag_candidates.len)
|
||||
break //Skip setup, DO NOT RUNTIME
|
||||
var/datum/mind/servant = antag_pick(antag_candidates)
|
||||
servants_to_serve += servant
|
||||
antag_candidates -= servant
|
||||
servant.assigned_role = ROLE_SERVANT_OF_RATVAR
|
||||
servant.special_role = ROLE_SERVANT_OF_RATVAR
|
||||
servant.restricted_roles = restricted_jobs
|
||||
starter_servants--
|
||||
ark_time = 30 + round((roundstart_player_count / 5)) //In minutes, how long the Ark will wait before activation
|
||||
ark_time = min(ark_time, 35) //35 minute maximum for the activation timer
|
||||
return 1
|
||||
if(!servants_to_serve.len) //Uh oh, something went wrong
|
||||
setup_error = "There are no clockcult candidates! (Or something went very wrong)"
|
||||
return FALSE
|
||||
GLOB.clockwork_vitality += 50 * servants_to_serve.len //some starter Vitality to help recover from initial fuck ups
|
||||
return TRUE //Haha yes it works time to not touch it any more than that.
|
||||
|
||||
/datum/game_mode/clockwork_cult/post_setup()
|
||||
for(var/S in servants_to_serve)
|
||||
var/datum/mind/servant = S
|
||||
log_game("[key_name(servant)] was made an initial servant of Ratvar")
|
||||
var/mob/living/L = servant.current
|
||||
var/turf/T = pick(GLOB.servant_spawns)
|
||||
L.forceMove(T)
|
||||
GLOB.servant_spawns -= T
|
||||
greet_servant(L)
|
||||
equip_servant(L)
|
||||
add_servant_of_ratvar(L, TRUE)
|
||||
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful
|
||||
G.final_countdown(ark_time)
|
||||
..()
|
||||
return 1
|
||||
|
||||
@@ -201,22 +199,23 @@ Credit where due:
|
||||
if(!M)
|
||||
return 0
|
||||
to_chat(M, "<span class='bold large_brass'>You are a servant of Ratvar, the Clockwork Justiciar!</span>")
|
||||
to_chat(M, "<span class='brass'>You have approximately <b>[ark_time]</b> minutes until the Ark activates.</span>")
|
||||
to_chat(M, "<span class='brass'>Unlock <b>Script</b> scripture by converting a new servant.</span>")
|
||||
to_chat(M, "<span class='brass'><b>Application</b> scripture will be unlocked halfway until the Ark's activation.</span>")
|
||||
to_chat(M, "<span class='brass'>Unlock <b>Script</b> scripture by converting a new servant or when 35kw of power is reached.</span>")
|
||||
to_chat(M, "<span class='brass'><b>Application</b> scripture will be unlocked when 50kw of power is reached.</span>")
|
||||
M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
return 1
|
||||
|
||||
/datum/game_mode/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob, with one of each component
|
||||
/datum/game_mode/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob
|
||||
if(!M || !ishuman(M))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/L = M
|
||||
L.equipOutfit(/datum/outfit/servant_of_ratvar)
|
||||
var/obj/item/clockwork/slab/S = new
|
||||
var/slot = "At your feet"
|
||||
var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK, "On your belt" = SLOT_BELT)
|
||||
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]"
|
||||
@@ -224,7 +223,6 @@ Credit where due:
|
||||
if(!S.forceMove(get_turf(L)))
|
||||
qdel(S)
|
||||
if(S && !QDELETED(S))
|
||||
to_chat(L, "<span class='bold large_brass'>There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.</span>")
|
||||
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>")
|
||||
@@ -278,7 +276,7 @@ Credit where due:
|
||||
gloves = /obj/item/clothing/gloves/color/yellow
|
||||
belt = /obj/item/storage/belt/utility/servant
|
||||
backpack_contents = list(/obj/item/storage/box/engineer = 1, \
|
||||
/obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1, /obj/item/reagent_containers/food/drinks/bottle/holyoil = 1)
|
||||
/obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/reagent_containers/food/drinks/bottle/holyoil = 1)
|
||||
id = /obj/item/pda
|
||||
var/plasmaman //We use this to determine if we should activate internals in post_equip()
|
||||
|
||||
@@ -305,53 +303,3 @@ Credit where due:
|
||||
PDA.update_label()
|
||||
PDA.id_check(H, W)
|
||||
H.sec_hud_set_ID()
|
||||
|
||||
|
||||
//This paper serves as a quick run-down to the cult as well as a changelog to refer to.
|
||||
//Check strings/clockwork_cult_changelog.txt for the changelog, and update it when you can!
|
||||
/obj/item/paper/servant_primer
|
||||
name = "The Ark And You: A Primer On Servitude"
|
||||
color = "#DAAA18"
|
||||
info = "<b>DON'T PANIC.</b><br><br>\
|
||||
Here's a quick primer on what you should know here.\
|
||||
<ol>\
|
||||
<li>You're in a place called Reebe right now. The crew can't get here normally.</li>\
|
||||
<li>In the north is your base camp, with supplies, consoles, and the Ark. In the south is an inaccessible area that the crew can walk between \
|
||||
once they arrive (more on that later.) Everything between that space is an open area.</li>\
|
||||
<li>Your job as a servant is to build fortifications and defenses to protect the Ark and your base once the Ark activates. You can do this \
|
||||
however you like, but work with your allies and coordinate your efforts.</li>\
|
||||
<li>Once the Ark activates, the station will be alerted. Portals to Reebe will open up in nearly every room. When they take these portals, \
|
||||
the crewmembers will arrive in the area that you can't access, but can get through it freely - whereas you can't. Treat this as the \"spawn\" of the \
|
||||
crew and defend it accordingly.</li>\
|
||||
</ol>\
|
||||
<hr>\
|
||||
Here is the layout of Reebe, from left to right:\
|
||||
<ul>\
|
||||
<li><b>Dressing Room:</b> Contains clothing, a dresser, and a mirror. There are spare slabs and absconders here.</li>\
|
||||
<li><b>Listening Station:</b> Contains intercoms, a telecomms relay, and a list of frequencies.</li>\
|
||||
<li><b>Ark Chamber:</b> Houses the Ark.</li>\
|
||||
<li><b>Observation Room:</b> Contains five camera observers. These can be used to watch the station through its cameras, as well as to teleport down \
|
||||
to most areas. To do this, use the Warp action while hovering over the tile you want to warp to.</li>\
|
||||
<li><b>Infirmary:</b> Contains sleepers and basic medical supplies for superficial wounds. The sleepers can consume Vitality to heal any occupants. \
|
||||
This room is generally more useful during the preparation phase; when defending the Ark, scripture is more useful.</li>\
|
||||
</ul>\
|
||||
<hr>\
|
||||
<h2>Things that have changed:</h2>\
|
||||
<ul>\
|
||||
CLOCKCULTCHANGELOG\
|
||||
</ul>\
|
||||
<hr>\
|
||||
<b>Good luck!</b>"
|
||||
|
||||
/obj/item/paper/servant_primer/Initialize()
|
||||
. = ..()
|
||||
var/changelog = world.file2list("strings/clockwork_cult_changelog.txt")
|
||||
var/changelog_contents = ""
|
||||
for(var/entry in changelog)
|
||||
changelog_contents += "<li>[entry]</li>"
|
||||
info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents)
|
||||
|
||||
/obj/item/paper/servant_primer/oui_getcontent(mob/target)
|
||||
if(!is_servant_of_ratvar(target) && !isobserver(target))
|
||||
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
|
||||
return ..()
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
if(visualsOnly)
|
||||
return
|
||||
H.dna.add_mutation(SMILE)
|
||||
H.faction |= "clown"
|
||||
|
||||
/datum/outfit/syndicate/clownop/leader
|
||||
name = "Clown Operative Leader - Basic"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -543,6 +543,8 @@
|
||||
/datum/game_mode/proc/get_remaining_days(client/C)
|
||||
if(!C)
|
||||
return 0
|
||||
if(C.prefs?.db_flags & DB_FLAG_EXEMPT)
|
||||
return 0
|
||||
if(!CONFIG_GET(flag/use_age_restriction_for_jobs))
|
||||
return 0
|
||||
if(!isnum(C.player_age))
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
add_fingerprint(user)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/dominator/attack_hand(mob/user)
|
||||
/obj/machinery/dominator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(operating || (stat & BROKEN))
|
||||
examine(user)
|
||||
return
|
||||
|
||||
@@ -845,6 +845,37 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
/datum/objective/destroy/internal
|
||||
var/stolen = FALSE //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/steal_five_of_type
|
||||
name = "steal five of"
|
||||
explanation_text = "Steal at least five items!"
|
||||
var/list/wanted_items = list(/obj/item)
|
||||
|
||||
/datum/objective/steal_five_of_type/New()
|
||||
..()
|
||||
wanted_items = typecacheof(wanted_items)
|
||||
|
||||
/datum/objective/steal_five_of_type/summon_guns
|
||||
name = "steal guns"
|
||||
explanation_text = "Steal at least five guns!"
|
||||
wanted_items = list(/obj/item/gun)
|
||||
|
||||
/datum/objective/steal_five_of_type/summon_magic
|
||||
name = "steal magic"
|
||||
explanation_text = "Steal at least five magical artefacts!"
|
||||
wanted_items = list(/obj/item/spellbook, /obj/item/gun/magic, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/scrying, /obj/item/antag_spawner/contract, /obj/item/necromantic_stone)
|
||||
|
||||
/datum/objective/steal_five_of_type/check_completion()
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
var/stolen_count = 0
|
||||
for(var/datum/mind/M in owners)
|
||||
if(!isliving(M.current))
|
||||
continue
|
||||
var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
|
||||
for(var/obj/I in all_items) //Check for wanted items
|
||||
if(is_type_in_typecache(I, wanted_items))
|
||||
stolen_count++
|
||||
return stolen_count >= 5
|
||||
|
||||
//Created by admin tools
|
||||
/datum/objective/custom
|
||||
name = "custom"
|
||||
|
||||
@@ -94,6 +94,11 @@
|
||||
targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/steal/blackbox
|
||||
name = "the black box from the onboard blackbox recording device. Take care to wear the proper safety equipment when extracting the black box as the telecommunications array is likely to be under inhospitable conditions."
|
||||
targetitem = /obj/item/blackbox //steal the forbidden ssblackbox
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/steal/nuke_core
|
||||
name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!"
|
||||
targetitem = /obj/item/nuke_core
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/obj/structure/door_assembly
|
||||
var/datum/airlock_maker/maker = null
|
||||
|
||||
/obj/structure/door_assembly/attack_hand()
|
||||
/obj/structure/door_assembly/on_attack_hand()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -107,10 +107,7 @@
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pdapainter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/pdapainter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
|
||||
if(!storedpda)
|
||||
to_chat(user, "<span class='notice'>[src] is empty.</span>")
|
||||
|
||||
+58
-173
@@ -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,22 +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("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol"))
|
||||
|
||||
/obj/machinery/sleeper/clockwork/process()
|
||||
if(occupant && isliving(occupant))
|
||||
var/mob/living/L = occupant
|
||||
if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing
|
||||
GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1)
|
||||
L.adjustBruteLoss(-1)
|
||||
L.adjustFireLoss(-1)
|
||||
L.adjustOxyLoss(-5)
|
||||
|
||||
/obj/machinery/sleeper/old
|
||||
icon_state = "oldpod"
|
||||
|
||||
@@ -442,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(
|
||||
@@ -476,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
|
||||
|
||||
@@ -121,7 +122,7 @@ Class Procs:
|
||||
var/ui_style // ID of custom TGUI style (optional)
|
||||
var/ui_x
|
||||
var/ui_y
|
||||
|
||||
var/init_process = TRUE //Stop processing from starting on init
|
||||
var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
|
||||
|
||||
var/fair_market_price = 69
|
||||
@@ -138,7 +139,7 @@ Class Procs:
|
||||
circuit = new circuit
|
||||
circuit.apply_default_parts(src)
|
||||
|
||||
if(!speed_process)
|
||||
if(!speed_process && init_process)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
else
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
@@ -313,7 +314,7 @@ Class Procs:
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
return attack_hand(user)
|
||||
else
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
user.visible_message("<span class='danger'>[user.name] smashes against \the [src.name] with its paws.</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
take_damage(4, BRUTE, "melee", 1)
|
||||
|
||||
@@ -122,10 +122,7 @@
|
||||
else
|
||||
icon_state = "airlock_sensor_off"
|
||||
|
||||
/obj/machinery/airlock_sensor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/airlock_sensor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = master_tag,
|
||||
"command" = "cycle"
|
||||
@@ -161,4 +158,4 @@
|
||||
|
||||
/obj/machinery/airlock_sensor/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -39,7 +39,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
icon_state = (panel_open ? "AAS_Off_Open" : "AAS_Off")
|
||||
|
||||
/obj/machinery/announcement_system/update_overlays()
|
||||
. =..()
|
||||
. = ..()
|
||||
if(arrivalToggle)
|
||||
. += greenlight
|
||||
|
||||
@@ -54,19 +54,15 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
GLOB.announcement_systems -= src //"OH GOD WHY ARE THERE 100,000 LISTED ANNOUNCEMENT SYSTEMS?!!"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/announcement_system/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/announcement_system/attackby(obj/item/P, mob/user, params)
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
if(P.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
P.play_tool_sound(src)
|
||||
panel_open = !panel_open
|
||||
to_chat(user, "<span class='notice'>You [panel_open ? "open" : "close"] the maintenance hatch of [src].</span>")
|
||||
update_icon()
|
||||
else if(default_deconstruction_crowbar(P))
|
||||
return
|
||||
else if(istype(P, /obj/item/multitool) && panel_open && (stat & BROKEN))
|
||||
else if(P.tool_behaviour == TOOL_MULTITOOL && panel_open && (stat & BROKEN))
|
||||
to_chat(user, "<span class='notice'>You reset [src]'s firmware.</span>")
|
||||
stat &= ~BROKEN
|
||||
update_icon()
|
||||
@@ -88,10 +84,6 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
message = CompileText(arrival, user, rank)
|
||||
else if(message_type == "NEWHEAD" && newheadToggle)
|
||||
message = CompileText(newhead, user, rank)
|
||||
//CITADEL EDIT for cryopods
|
||||
else if(message_type == "CRYOSTORAGE")
|
||||
message = CompileText("%PERSON, %RANK has been moved to cryo storage.", user, rank)
|
||||
//END EDIT
|
||||
else if(message_type == "ARRIVALS_BROKEN")
|
||||
message = "The arrivals shuttle has been damaged. Docking for repairs..."
|
||||
|
||||
@@ -101,63 +93,58 @@ 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, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "AutomatedAnnouncement")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/announcement_system/ui_interact(mob/user)
|
||||
/obj/machinery/announcement_system/ui_data()
|
||||
var/list/data = list()
|
||||
data["arrival"] = arrival
|
||||
data["arrivalToggle"] = arrivalToggle
|
||||
data["newhead"] = newhead
|
||||
data["newheadToggle"] = newheadToggle
|
||||
return data
|
||||
|
||||
/obj/machinery/announcement_system/ui_act(action, param)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
if(.)
|
||||
return
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
|
||||
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
|
||||
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='hear'>You hear a faint buzz.</span>")
|
||||
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, TRUE)
|
||||
return
|
||||
|
||||
|
||||
var/contents = "Arrival Announcement: <A href='?src=[REF(src)];ArrivalT-Topic=1'>([(arrivalToggle ? "On" : "Off")])</a><br>\n<A href='?src=[REF(src)];ArrivalTopic=1'>[arrival]</a><br><br>\n"
|
||||
contents += "Departmental Head Announcement: <A href='?src=[REF(src)];NewheadT-Topic=1'>([(newheadToggle ? "On" : "Off")])</a><br>\n<A href='?src=[REF(src)];NewheadTopic=1'>[newhead]</a><br><br>\n"
|
||||
|
||||
var/datum/browser/popup = new(user, "announcement_config", "Automated Announcement Configuration", 370, 220)
|
||||
popup.set_content(contents)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/announcement_system/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
|
||||
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1)
|
||||
return
|
||||
|
||||
if(href_list["ArrivalTopic"])
|
||||
var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival)
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
arrival = NewMessage
|
||||
else if(href_list["NewheadTopic"])
|
||||
var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead)
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
newhead = NewMessage
|
||||
|
||||
else if(href_list["NewheadT-Topic"])
|
||||
newheadToggle = !newheadToggle
|
||||
update_icon()
|
||||
else if(href_list["ArrivalT-Topic"])
|
||||
arrivalToggle = !arrivalToggle
|
||||
update_icon()
|
||||
|
||||
switch(action)
|
||||
if("ArrivalText")
|
||||
var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN)
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
arrival = NewMessage
|
||||
log_game("The arrivals announcement was updated: [NewMessage] by:[key_name(usr)]")
|
||||
if("NewheadText")
|
||||
var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN)
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
newhead = NewMessage
|
||||
log_game("The head announcement was updated: [NewMessage] by:[key_name(usr)]")
|
||||
if("NewheadToggle")
|
||||
newheadToggle = !newheadToggle
|
||||
update_icon()
|
||||
if("ArrivalToggle")
|
||||
arrivalToggle = !arrivalToggle
|
||||
update_icon()
|
||||
add_fingerprint(usr)
|
||||
interact(usr)
|
||||
|
||||
/obj/machinery/announcement_system/attack_robot(mob/living/silicon/user)
|
||||
. = attack_ai(user)
|
||||
|
||||
/obj/machinery/announcement_system/attack_ai(mob/user)
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='warning'>[src]'s firmware appears to be malfunctioning!</span>")
|
||||
@@ -165,8 +152,8 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/announcement_system/proc/act_up() //does funny breakage stuff
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
if(!obj_break()) // if badmins flag this unbreakable or its already broken
|
||||
return
|
||||
|
||||
arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!")
|
||||
newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.")
|
||||
@@ -177,9 +164,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
act_up()
|
||||
|
||||
/obj/machinery/announcement_system/emag_act()
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
act_up()
|
||||
return TRUE
|
||||
|
||||
@@ -100,10 +100,7 @@
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/aug_manipulator/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/aug_manipulator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(storedpart)
|
||||
|
||||
@@ -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, "bank_machine", 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,7 +43,11 @@
|
||||
board.one_access = 1
|
||||
board.accesses = req_one_access
|
||||
|
||||
/obj/machinery/button/update_icon_state()
|
||||
setup_device()
|
||||
|
||||
|
||||
/obj/machinery/button/update_icon()
|
||||
cut_overlays()
|
||||
if(panel_open)
|
||||
icon_state = "button-open"
|
||||
else if(stat & (NOPOWER|BROKEN))
|
||||
@@ -129,7 +133,12 @@
|
||||
A.id = id
|
||||
initialized_button = 1
|
||||
|
||||
/obj/machinery/button/attack_hand(mob/user)
|
||||
/obj/machinery/button/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
if(id && istype(device, /obj/item/assembly/control))
|
||||
var/obj/item/assembly/control/A = device
|
||||
A.id = "[idnum][id]"
|
||||
|
||||
/obj/machinery/button/on_attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -72,6 +72,11 @@
|
||||
if(mapload && is_station_level(z) && prob(3) && !start_active)
|
||||
toggle_cam()
|
||||
|
||||
/obj/machinery/camera/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
if(can_use())
|
||||
toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
|
||||
@@ -230,7 +235,7 @@
|
||||
itemname = P.name
|
||||
info = P.notehtml
|
||||
to_chat(U, "<span class='notice'>You hold \the [itemname] up to the camera...</span>")
|
||||
U.changeNext_move(CLICK_CD_MELEE)
|
||||
U.DelayNextAction(CLICK_CD_MELEE)
|
||||
for(var/mob/O in GLOB.player_list)
|
||||
if(isAI(O))
|
||||
var/mob/living/silicon/ai/AI = O
|
||||
|
||||
@@ -79,10 +79,7 @@
|
||||
charging = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/cell_charger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/cell_charger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
@@ -103,8 +100,18 @@
|
||||
removecell()
|
||||
|
||||
/obj/machinery/cell_charger/attack_ai(mob/user)
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
charging.forceMove(loc)
|
||||
to_chat(user, "<span class='notice'>You remotely disconnect the battery port and eject [charging] from [src].</span>")
|
||||
|
||||
removecell()
|
||||
return
|
||||
|
||||
/obj/machinery/cell_charger/attack_robot(mob/user)
|
||||
attack_ai(user)
|
||||
|
||||
/obj/machinery/cell_charger/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -75,31 +75,6 @@
|
||||
speed_coeff = max(1, speed_coeff)
|
||||
heal_level = clamp((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100)
|
||||
|
||||
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
|
||||
//TO-DO: Make the genetics machine accept them.
|
||||
/obj/item/disk/data
|
||||
name = "cloning data disk"
|
||||
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
||||
var/list/fields = list()
|
||||
var/list/mutations = list()
|
||||
var/max_mutations = 6
|
||||
var/read_only = 0 //Well,it's still a floppy disk
|
||||
|
||||
//Disk stuff.
|
||||
/obj/item/disk/data/Initialize()
|
||||
. = ..()
|
||||
icon_state = "datadisk[rand(0,6)]"
|
||||
add_overlay("datadisk_gene")
|
||||
|
||||
/obj/item/disk/data/attack_self(mob/user)
|
||||
read_only = !read_only
|
||||
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
|
||||
|
||||
/obj/item/disk/data/examine(mob/user)
|
||||
. = ..()
|
||||
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
|
||||
|
||||
|
||||
//Clonepod
|
||||
|
||||
/obj/machinery/clonepod/examine(mob/user)
|
||||
|
||||
@@ -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, "operating_computer", name, 350, 470, master_ui, state)
|
||||
ui = new(user, src, "OperatingComputer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
@@ -108,8 +111,53 @@
|
||||
))
|
||||
else
|
||||
data["patient"] = null
|
||||
return data
|
||||
switch(patient.stat)
|
||||
if(CONSCIOUS)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "good"
|
||||
if(SOFT_CRIT)
|
||||
data["patient"]["stat"] = "Conscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(UNCONSCIOUS)
|
||||
data["patient"]["stat"] = "Unconscious"
|
||||
data["patient"]["statstate"] = "average"
|
||||
if(DEAD)
|
||||
data["patient"]["stat"] = "Dead"
|
||||
data["patient"]["statstate"] = "bad"
|
||||
data["patient"]["health"] = patient.health
|
||||
data["patient"]["blood_type"] = patient.dna.blood_type
|
||||
data["patient"]["maxHealth"] = patient.maxHealth
|
||||
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
||||
data["patient"]["bruteLoss"] = patient.getBruteLoss()
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
data["procedures"] = list()
|
||||
if(patient.surgeries.len)
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
var/chems_needed = surgery_step.get_chem_list()
|
||||
var/alternative_step
|
||||
var/alt_chems_needed = ""
|
||||
if(surgery_step.repeatable)
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
alternative_step = capitalize(next_step.name)
|
||||
alt_chems_needed = next_step.get_chem_list()
|
||||
else
|
||||
alternative_step = "Finish operation"
|
||||
data["procedures"] += list(list(
|
||||
"name" = capitalize("[parse_zone(procedure.location)] [procedure.name]"),
|
||||
"next_step" = capitalize(surgery_step.name),
|
||||
"chems_needed" = chems_needed,
|
||||
"alternative_step" = alternative_step,
|
||||
"alt_chems_needed" = alt_chems_needed
|
||||
))
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -2,12 +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
|
||||
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))
|
||||
@@ -18,60 +19,45 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
var/dat = ""
|
||||
/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, "AiRestorer", name)
|
||||
ui.open()
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
/obj/machinery/computer/aifixer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<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)
|
||||
|
||||
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>"
|
||||
return data
|
||||
|
||||
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>"
|
||||
/obj/machinery/computer/aifixer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!occupier)
|
||||
active = FALSE
|
||||
|
||||
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)
|
||||
@@ -91,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))
|
||||
|
||||
@@ -136,3 +136,17 @@
|
||||
empprize = pickweight(prizes)
|
||||
new empprize(loc)
|
||||
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
|
||||
|
||||
/obj/machinery/computer/arcade/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/stack/arcadeticket))
|
||||
var/obj/item/stack/arcadeticket/T = O
|
||||
var/amount = T.get_amount()
|
||||
if(amount <2)
|
||||
to_chat(user, "<span class='warning'>You need 2 tickets to claim a prize!</span>")
|
||||
return
|
||||
prizevend(user)
|
||||
T.pay_tickets()
|
||||
T.update_icon()
|
||||
O = T
|
||||
to_chat(user, "<span class='notice'>You turn in 2 tickets to the [src] and claim a prize!</span>")
|
||||
return
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon_state = "arcade"
|
||||
circuit = /obj/item/circuitboard/computer/arcade/amputation
|
||||
|
||||
/obj/machinery/computer/arcade/amputation/attack_hand(mob/user)
|
||||
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
var/mob/living/carbon/c_user = user
|
||||
@@ -28,4 +28,4 @@
|
||||
for(var/i=1; i<=rand(3,5); i++)
|
||||
prizevend(user)
|
||||
else
|
||||
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")
|
||||
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")
|
||||
|
||||
@@ -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, "atmos_alert", 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, "atmos_control", 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, "atmos_control", 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
|
||||
|
||||
@@ -4,109 +4,163 @@
|
||||
icon_screen = "cameras"
|
||||
icon_keyboard = "security_key"
|
||||
circuit = /obj/item/circuitboard/computer/security
|
||||
var/last_pic = 1
|
||||
var/list/network = list("ss13")
|
||||
var/list/watchers = list() //who's using the console, associated with the camera they're on.
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/active_camera
|
||||
var/list/concurrent_users = list()
|
||||
|
||||
// Stuff needed to render the map
|
||||
var/map_name
|
||||
var/const/default_map_size = 15
|
||||
var/obj/screen/cam_screen
|
||||
var/obj/screen/plane_master/lighting/cam_plane_master
|
||||
var/obj/screen/background/cam_background
|
||||
|
||||
/obj/machinery/computer/security/Initialize()
|
||||
. = ..()
|
||||
// Map name has to start and end with an A-Z character,
|
||||
// and definitely NOT with a square bracket or even a number.
|
||||
// I wasted 6 hours on this. :agony:
|
||||
map_name = "camera_console_[REF(src)]_map"
|
||||
// Convert networks to lowercase
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += lowertext(i)
|
||||
|
||||
/obj/machinery/computer/security/check_eye(mob/user)
|
||||
if(!can_interact(user) || !(user in watchers) || !watchers[user])
|
||||
user.unset_machine()
|
||||
return
|
||||
var/obj/machinery/camera/C = watchers[user]
|
||||
if(!C.can_use())
|
||||
user.unset_machine()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/on_unset_machine(mob/user)
|
||||
watchers.Remove(user)
|
||||
user.reset_perspective(null)
|
||||
// Initialize map objects
|
||||
cam_screen = new
|
||||
cam_screen.name = "screen"
|
||||
cam_screen.assigned_map = map_name
|
||||
cam_screen.del_on_map_removal = FALSE
|
||||
cam_screen.screen_loc = "[map_name]:1,1"
|
||||
cam_plane_master = new
|
||||
cam_plane_master.name = "plane_master"
|
||||
cam_plane_master.assigned_map = map_name
|
||||
cam_plane_master.del_on_map_removal = FALSE
|
||||
cam_plane_master.screen_loc = "[map_name]:CENTER"
|
||||
cam_background = new
|
||||
cam_background.assigned_map = map_name
|
||||
cam_background.del_on_map_removal = FALSE
|
||||
|
||||
/obj/machinery/computer/security/Destroy()
|
||||
if(watchers.len)
|
||||
for(var/mob/M in watchers)
|
||||
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
||||
qdel(cam_screen)
|
||||
qdel(cam_plane_master)
|
||||
qdel(cam_background)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/can_interact(mob/user)
|
||||
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
return FALSE
|
||||
return ..()
|
||||
/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
/obj/machinery/computer/security/interact(mob/user, special_state)
|
||||
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
|
||||
// Update UI
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
if(!ui)
|
||||
var/user_ref = REF(user)
|
||||
var/is_living = isliving(user)
|
||||
// Ghosts shouldn't count towards concurrent users, which produces
|
||||
// an audible terminal_on click.
|
||||
if(is_living)
|
||||
concurrent_users += user_ref
|
||||
// Turn on the console
|
||||
if(length(concurrent_users) == 1 && is_living)
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE)
|
||||
use_power(active_power_usage)
|
||||
// Register map objects
|
||||
user.client.register_map_obj(cam_screen)
|
||||
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, "CameraConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/security/ui_data()
|
||||
var/list/data = list()
|
||||
data["network"] = network
|
||||
data["activeCamera"] = null
|
||||
if(active_camera)
|
||||
data["activeCamera"] = list(
|
||||
name = active_camera.c_tag,
|
||||
status = active_camera.status,
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/security/ui_static_data()
|
||||
var/list/data = list()
|
||||
data["mapRef"] = map_name
|
||||
var/list/cameras = get_available_cameras()
|
||||
data["cameras"] = list()
|
||||
for(var/i in cameras)
|
||||
var/obj/machinery/camera/C = cameras[i]
|
||||
data["cameras"] += list(list(
|
||||
name = C.c_tag,
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/security/ui_act(action, params)
|
||||
. = ..()
|
||||
if (ismob(user) && !isliving(user)) // ghosts don't need cameras
|
||||
return
|
||||
if (!network)
|
||||
stack_trace("No camera network")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
if (!(islist(network)))
|
||||
stack_trace("Camera network is not a list")
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
|
||||
var/list/camera_list = get_available_cameras()
|
||||
if(!(user in watchers))
|
||||
for(var/Num in camera_list)
|
||||
var/obj/machinery/camera/CAM = camera_list[Num]
|
||||
if(istype(CAM) && CAM.can_use())
|
||||
watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
|
||||
break
|
||||
if(!(user in watchers))
|
||||
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
|
||||
return FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
|
||||
use_camera_console(user)
|
||||
|
||||
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
|
||||
var/list/camera_list = get_available_cameras()
|
||||
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
|
||||
if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
|
||||
return
|
||||
if(!t || t == "Cancel")
|
||||
user.unset_machine()
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/obj/machinery/camera/C = camera_list[t]
|
||||
if(action == "switch_camera")
|
||||
var/c_tag = params["name"]
|
||||
var/list/cameras = get_available_cameras()
|
||||
var/obj/machinery/camera/C = cameras[c_tag]
|
||||
active_camera = C
|
||||
playsound(src, get_sfx("terminal_type"), 25, FALSE)
|
||||
|
||||
if(!C || !C.can_use() || !can_interact(user))
|
||||
user.unset_machine()
|
||||
return FALSE
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
return TRUE
|
||||
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
|
||||
if(isAI(user))
|
||||
var/mob/living/silicon/ai/A = user
|
||||
A.eyeobj.setLoc(get_turf(C))
|
||||
A.client.eye = A.eyeobj
|
||||
else
|
||||
user.reset_perspective(C)
|
||||
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
||||
user.clear_fullscreen("flash", 5)
|
||||
watchers[user] = C
|
||||
use_power(50)
|
||||
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
|
||||
var/list/visible_turfs = list()
|
||||
for(var/turf/T in (C.isXRay() \
|
||||
? range(C.view_range, C) \
|
||||
: view(C.view_range, C)))
|
||||
visible_turfs += T
|
||||
|
||||
//returns the list of cameras accessible from this computer
|
||||
var/list/bbox = get_bbox_of_atoms(visible_turfs)
|
||||
var/size_x = bbox[3] - bbox[1] + 1
|
||||
var/size_y = bbox[4] - bbox[2] + 1
|
||||
|
||||
cam_screen.vis_contents = visible_turfs
|
||||
cam_background.icon_state = "clear"
|
||||
cam_background.fill_rect(1, 1, size_x, size_y)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/security/ui_close(mob/user)
|
||||
var/user_ref = REF(user)
|
||||
var/is_living = isliving(user)
|
||||
// Living creature or not, we remove you anyway.
|
||||
concurrent_users -= user_ref
|
||||
// Unregister map objects
|
||||
user.client.clear_map(map_name)
|
||||
// Turn off the console
|
||||
if(length(concurrent_users) == 0 && is_living)
|
||||
active_camera = null
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE)
|
||||
use_power(0)
|
||||
|
||||
/obj/machinery/computer/security/proc/show_camera_static()
|
||||
cam_screen.vis_contents.Cut()
|
||||
cam_background.icon_state = "scanline2"
|
||||
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
|
||||
|
||||
// Returns the list of cameras accessible from this computer
|
||||
/obj/machinery/computer/security/proc/get_available_cameras()
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras
|
||||
continue
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
|
||||
var/list/D = list()
|
||||
D["Cancel"] = "Cancel"
|
||||
for(var/obj/machinery/camera/C in L)
|
||||
if(!C.network)
|
||||
stack_trace("Camera in a cameranet has no camera network")
|
||||
@@ -114,9 +168,9 @@
|
||||
if(!(islist(C.network)))
|
||||
stack_trace("Camera in a cameranet has a non-list camera network")
|
||||
continue
|
||||
var/list/tempnetwork = C.network&network
|
||||
var/list/tempnetwork = C.network & network
|
||||
if(tempnetwork.len)
|
||||
D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C
|
||||
D["[C.c_tag]"] = C
|
||||
return D
|
||||
|
||||
// SECURITY MONITORS
|
||||
@@ -127,7 +181,6 @@
|
||||
icon_state = "television"
|
||||
icon_keyboard = null
|
||||
icon_screen = "detective_tv"
|
||||
clockwork = TRUE //it'd look weird
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
/obj/machinery/computer/security/mining
|
||||
@@ -145,7 +198,7 @@
|
||||
circuit = /obj/item/circuitboard/computer/research
|
||||
|
||||
/obj/machinery/computer/security/hos
|
||||
name = "Head of Security's camera console"
|
||||
name = "\improper Head of Security's camera console"
|
||||
desc = "A custom security console with added access to the labor camp network."
|
||||
network = list("ss13", "labor")
|
||||
circuit = null
|
||||
@@ -157,7 +210,7 @@
|
||||
circuit = null
|
||||
|
||||
/obj/machinery/computer/security/qm
|
||||
name = "Quartermaster's camera console"
|
||||
name = "\improper Quartermaster's camera console"
|
||||
desc = "A console with access to the mining, auxillary base and vault camera networks."
|
||||
network = list("mine", "auxbase", "vault")
|
||||
circuit = null
|
||||
@@ -172,7 +225,6 @@
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
clockwork = TRUE //it'd look very weird
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/Initialize()
|
||||
@@ -190,11 +242,35 @@
|
||||
name = "entertainment monitor"
|
||||
desc = "Damn, they better have the /tg/ channel on these things."
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "entertainment"
|
||||
icon_state = "entertainment_blank"
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
interaction_flags_atom = NONE // interact() is called by BigClick()
|
||||
var/icon_state_off = "entertainment_blank"
|
||||
var/icon_state_on = "entertainment"
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
|
||||
|
||||
// Bypass clickchain to allow humans to use the telescreen from a distance
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
|
||||
interact(usr)
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
|
||||
if(on && icon_state == icon_state_off)
|
||||
say(pick(
|
||||
"Feats of bravery live now at the thunderdome!",
|
||||
"Two enter, one leaves! Tune in now!",
|
||||
"Violence like you've never seen it before!",
|
||||
"Spears! Camera! Action! LIVE NOW!"))
|
||||
icon_state = icon_state_on
|
||||
else
|
||||
icon_state = icon_state_off
|
||||
|
||||
/obj/machinery/computer/security/telescreen/rd
|
||||
name = "Research Director's telescreen"
|
||||
name = "\improper Research Director's telescreen"
|
||||
desc = "Used for watching the AI and the RD's goons from the safety of his office."
|
||||
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
|
||||
|
||||
@@ -202,26 +278,26 @@
|
||||
name = "circuitry telescreen"
|
||||
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
|
||||
network = list("rd")
|
||||
|
||||
|
||||
/obj/machinery/computer/security/telescreen/ce
|
||||
name = "Chief Engineer's telescreen"
|
||||
name = "\improper Chief Engineer's telescreen"
|
||||
desc = "Used for watching the engine, telecommunications and the minisat."
|
||||
network = list("engine", "singularity", "tcomms", "minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/cmo
|
||||
name = "Chief Medical Officer's telescreen"
|
||||
name = "\improper Chief Medical Officer's telescreen"
|
||||
desc = "A telescreen with access to the medbay's camera network."
|
||||
network = list("medbay")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/vault
|
||||
name = "Vault monitor"
|
||||
name = "vault monitor"
|
||||
desc = "A telescreen that connects to the vault's camera network."
|
||||
network = list("vault")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/toxins
|
||||
name = "Bomb test site monitor"
|
||||
name = "bomb test site monitor"
|
||||
desc = "A telescreen that connects to the bomb test site's camera."
|
||||
network = list("toxin")
|
||||
network = list("toxins")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/engine
|
||||
name = "engine monitor"
|
||||
@@ -254,7 +330,7 @@
|
||||
network = list("minisat")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/aiupload
|
||||
name = "AI upload monitor"
|
||||
name = "\improper AI upload monitor"
|
||||
desc = "A telescreen that connects to the AI upload's camera network."
|
||||
network = list("aiupload")
|
||||
|
||||
|
||||
@@ -29,9 +29,17 @@
|
||||
if(lock_override & CAMERA_LOCK_REEBE)
|
||||
z_lock |= SSmapping.levels_by_trait(ZTRAIT_REEBE)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
for(var/i in networks)
|
||||
networks -= i
|
||||
networks += "[idnum][i]"
|
||||
|
||||
/obj/machinery/computer/camera_advanced/syndie
|
||||
icon_keyboard = "syndie_key"
|
||||
|
||||
/obj/machinery/computer/camera_advanced/syndie/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
return //For syndie nuke shuttle, to spy for station.
|
||||
|
||||
/obj/machinery/computer/camera_advanced/proc/CreateEye()
|
||||
eyeobj = new()
|
||||
eyeobj.origin = src
|
||||
@@ -95,10 +103,7 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/computer/camera_advanced/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(current_user)
|
||||
to_chat(user, "The console is already in use!")
|
||||
return
|
||||
@@ -268,112 +273,4 @@
|
||||
C.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
||||
C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
|
||||
else
|
||||
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
|
||||
|
||||
|
||||
//Used by servants of Ratvar! They let you beam to the station.
|
||||
/obj/machinery/computer/camera_advanced/ratvar
|
||||
name = "ratvarian camera observer"
|
||||
desc = "A console used to snoop on the station's goings-on. A jet of steam occasionally whooshes out from slats on its sides."
|
||||
use_power = FALSE
|
||||
networks = list("ss13", "minisat") //:eye:
|
||||
var/datum/action/innate/servant_warp/warp_action = new
|
||||
|
||||
/obj/machinery/computer/camera_advanced/ratvar/Initialize()
|
||||
. = ..()
|
||||
ratvar_act()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/ratvar/process()
|
||||
if(prob(1))
|
||||
playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 25, TRUE)
|
||||
new/obj/effect/temp_visual/steam_release(get_turf(src))
|
||||
|
||||
/obj/machinery/computer/camera_advanced/ratvar/CreateEye()
|
||||
..()
|
||||
eyeobj.visible_icon = TRUE
|
||||
eyeobj.icon = 'icons/mob/cameramob.dmi' //in case you still had any doubts
|
||||
eyeobj.icon_state = "generic_camera"
|
||||
|
||||
/obj/machinery/computer/camera_advanced/ratvar/GrantActions(mob/living/carbon/user)
|
||||
..()
|
||||
if(warp_action)
|
||||
warp_action.Grant(user)
|
||||
warp_action.target = src
|
||||
actions += warp_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/ratvar/can_use(mob/living/user)
|
||||
if(!is_servant_of_ratvar(user))
|
||||
to_chat(user, "<span class='warning'>[src]'s keys are in a language foreign to you, and you don't understand anything on its screen.</span>")
|
||||
return
|
||||
if(clockwork_ark_active())
|
||||
to_chat(user, "<span class='warning'>The Ark is active, and [src] has shut down.</span>")
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/datum/action/innate/servant_warp
|
||||
name = "Warp"
|
||||
desc = "Warps to the tile you're viewing. You can use the Abscond scripture to return. Clicking this button again cancels the warp."
|
||||
icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
|
||||
button_icon_state = "warp_down"
|
||||
background_icon_state = "bg_clock"
|
||||
buttontooltipstyle = "clockcult"
|
||||
var/cancel = FALSE //if TRUE, an active warp will be canceled
|
||||
var/obj/effect/temp_visual/ratvar/warp_marker/warping
|
||||
|
||||
/datum/action/innate/servant_warp/Activate()
|
||||
if(QDELETED(target) || !(ishuman(owner) || iscyborg(owner)) || !owner.canUseTopic(target))
|
||||
return
|
||||
if(!GLOB.servants_active) //No leaving unless there's servants from the get-go
|
||||
return
|
||||
if(warping)
|
||||
cancel = TRUE
|
||||
return
|
||||
var/mob/living/carbon/human/user = owner
|
||||
var/mob/camera/aiEye/remote/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/ratvar/R = target
|
||||
var/turf/T = get_turf(remote_eye)
|
||||
if(!is_reebe(user.z) || !is_station_level(T.z))
|
||||
return
|
||||
if(isclosedturf(T))
|
||||
to_chat(user, "<span class='sevtug_small'>You can't teleport into a wall.</span>")
|
||||
return
|
||||
else if(isspaceturf(T))
|
||||
to_chat(user, "<span class='sevtug_small'>[prob(1) ? "Servant cannot into space." : "You can't teleport into space."]</span>")
|
||||
return
|
||||
else if(T.flags_1 & NOJAUNT_1)
|
||||
to_chat(user, "<span class='sevtug_small'>This tile is blessed by holy water and deflects the warp.</span>")
|
||||
return
|
||||
var/area/AR = get_area(T)
|
||||
if(!AR.clockwork_warp_allowed)
|
||||
to_chat(user, "<span class='sevtug_small'>[AR.clockwork_warp_fail]</span>")
|
||||
return
|
||||
if(alert(user, "Are you sure you want to warp to [AR]?", target.name, "Warp", "Cancel") == "Cancel" || QDELETED(R) || !user.canUseTopic(R))
|
||||
return
|
||||
do_sparks(5, TRUE, user)
|
||||
do_sparks(5, TRUE, T)
|
||||
warping = new(T)
|
||||
user.visible_message("<span class='warning'>[user]'s [target.name] flares!</span>", "<span class='bold sevtug_small'>You begin warping to [AR]...</span>")
|
||||
button_icon_state = "warp_cancel"
|
||||
owner.update_action_buttons()
|
||||
if(!do_after(user, 50, target = warping, extra_checks = CALLBACK(src, .proc/is_canceled)))
|
||||
to_chat(user, "<span class='bold sevtug_small'>Warp interrupted.</span>")
|
||||
QDEL_NULL(warping)
|
||||
button_icon_state = "warp_down"
|
||||
owner.update_action_buttons()
|
||||
cancel = FALSE
|
||||
return
|
||||
button_icon_state = "warp_down"
|
||||
owner.update_action_buttons()
|
||||
QDEL_NULL(warping)
|
||||
if(!do_teleport(user, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE))
|
||||
to_chat(user, "<span class='bold sevtug_small'>Warp Failed. Something deflected our attempt to warp to [AR].</span>")
|
||||
return
|
||||
T.visible_message("<span class='warning'>[user] warps in!</span>")
|
||||
playsound(user, 'sound/magic/magic_missile.ogg', 50, TRUE)
|
||||
playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE)
|
||||
user.setDir(SOUTH)
|
||||
flash_color(user, flash_color = "#AF0AAF", flash_time = 5)
|
||||
R.remove_eye_control(user)
|
||||
|
||||
/datum/action/innate/servant_warp/proc/is_canceled()
|
||||
return !cancel
|
||||
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
|
||||
@@ -61,7 +61,7 @@
|
||||
// main interface
|
||||
if("main")
|
||||
state = STATE_DEFAULT
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
if("login")
|
||||
var/mob/M = usr
|
||||
|
||||
@@ -73,19 +73,19 @@
|
||||
auth_id = "[I.registered_name] ([I.assignment])"
|
||||
if((ACCESS_CAPTAIN in I.access))
|
||||
authenticated = 2
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
if(obj_flags & EMAGGED)
|
||||
authenticated = 2
|
||||
auth_id = "Unknown"
|
||||
to_chat(M, "<span class='warning'>[src] lets out a quiet alarm as its login is overridden.</span>")
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0)
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 25, FALSE)
|
||||
if(prob(25))
|
||||
for(var/mob/living/silicon/ai/AI in active_ais())
|
||||
SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons
|
||||
if("logout")
|
||||
authenticated = 0
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
|
||||
|
||||
if("swipeidseclevel")
|
||||
var/mob/M = usr
|
||||
@@ -109,7 +109,7 @@
|
||||
security_level_cd = world.time + 15 SECONDS
|
||||
if(GLOB.security_level != old_level)
|
||||
to_chat(usr, "<span class='notice'>Authorization confirmed. Modifying security level.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
//Only notify people if an actual change happened
|
||||
var/security_level = NUM2SECLEVEL(GLOB.security_level)
|
||||
log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
|
||||
@@ -118,28 +118,28 @@
|
||||
tmp_alertlevel = 0
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You are not authorized to do this!</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
tmp_alertlevel = 0
|
||||
state = STATE_DEFAULT
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You need to swipe your ID!</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
|
||||
|
||||
if("announce")
|
||||
if(authenticated==2)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
|
||||
make_announcement(usr)
|
||||
|
||||
if("crossserver")
|
||||
if(authenticated==2)
|
||||
if(!checkCCcooldown())
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
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.", "")
|
||||
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)
|
||||
send2otherserver("[station_name()]", input,"Comms_Console")
|
||||
minor_announce(input, title = "Outgoing message to allied station")
|
||||
usr.log_talk(input, LOG_SAY, tag="message to the other server")
|
||||
@@ -168,22 +168,18 @@
|
||||
if(D)
|
||||
points_to_check = D.account_balance
|
||||
if(points_to_check >= S.credit_cost)
|
||||
var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines
|
||||
if(M)
|
||||
SSshuttle.shuttle_purchased = TRUE
|
||||
D.adjust_money(-S.credit_cost)
|
||||
minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
|
||||
SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
|
||||
M.unload_preview()
|
||||
M.load_template(S)
|
||||
M.existing_shuttle = SSshuttle.emergency
|
||||
M.action_load(S)
|
||||
message_admins("[S.name] loaded, purchased by [usr]")
|
||||
else
|
||||
to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.")
|
||||
SSshuttle.shuttle_purchased = TRUE
|
||||
SSshuttle.unload_preview()
|
||||
SSshuttle.load_template(S)
|
||||
SSshuttle.existing_shuttle = SSshuttle.emergency
|
||||
SSshuttle.action_load(S)
|
||||
D.adjust_money(-S.credit_cost)
|
||||
minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
|
||||
log_shuttle("[key_name(usr)] has purchased [S.name].")
|
||||
SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
|
||||
else
|
||||
to_chat(usr, "Not enough credits.")
|
||||
to_chat(usr, "<span class='alert'>Insufficient credits.</span>")
|
||||
|
||||
if("callshuttle")
|
||||
state = STATE_DEFAULT
|
||||
@@ -268,7 +264,7 @@
|
||||
|
||||
// Status display stuff
|
||||
if("setstat")
|
||||
playsound(src, "terminal_type", 50, 0)
|
||||
playsound(src, "terminal_type", 50, FALSE)
|
||||
switch(href_list["statdisp"])
|
||||
if("message")
|
||||
post_status("message", stat_msg1, stat_msg2)
|
||||
@@ -308,13 +304,13 @@
|
||||
if("MessageSyndicate")
|
||||
if((authenticated==2) && (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, 0)
|
||||
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_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] 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 /??????/.", "")
|
||||
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)
|
||||
Syndicate_announce(input, usr)
|
||||
to_chat(usr, "<span class='danger'>SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.</span>")
|
||||
for(var/client/X in GLOB.admins)
|
||||
@@ -327,7 +323,7 @@
|
||||
|
||||
if("RestoreBackup")
|
||||
to_chat(usr, "<span class='notice'>Backup routing data restored!</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
obj_flags &= ~EMAGGED
|
||||
updateDialog()
|
||||
|
||||
@@ -341,7 +337,7 @@
|
||||
return
|
||||
Nuke_request(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Request sent.</span>")
|
||||
usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY)
|
||||
usr.log_message("has requested the nuclear codes from CentCom with reason \"[input]\"", LOG_SAY)
|
||||
priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
|
||||
CM.lastTimeUsed = world.time
|
||||
|
||||
@@ -448,7 +444,7 @@
|
||||
if(authenticated == 1)
|
||||
authenticated = 2
|
||||
to_chat(user, "<span class='danger'>You scramble the communication routing circuits!</span>")
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/communications/ui_interact(mob/user)
|
||||
@@ -514,16 +510,16 @@
|
||||
dat += "<BR>\[ <A HREF='?src=[REF(src)];operation=login'>Log In</A> \]"
|
||||
if(STATE_CALLSHUTTLE)
|
||||
dat += get_call_shuttle_form()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
|
||||
if(STATE_CANCELSHUTTLE)
|
||||
dat += get_cancel_shuttle_form()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
|
||||
if(STATE_MESSAGELIST)
|
||||
dat += "Messages:"
|
||||
for(var/i in 1 to messages.len)
|
||||
var/datum/comm_message/M = messages[i]
|
||||
dat += "<BR><A HREF='?src=[REF(src)];operation=viewmessage;message-num=[i]'>[M.title]</A>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
if(STATE_VIEWMESSAGE)
|
||||
if (currmsg)
|
||||
dat += "<B>[currmsg.title]</B><BR><BR>[currmsg.content]"
|
||||
@@ -557,7 +553,7 @@
|
||||
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=redalert'>Red Alert</A> |"
|
||||
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=lockdown'>Lockdown</A> |"
|
||||
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR><HR>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
if(STATE_ALERT_LEVEL)
|
||||
dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]<BR>"
|
||||
if(GLOB.security_level == SEC_LEVEL_DELTA)
|
||||
@@ -571,7 +567,7 @@
|
||||
dat += "Confirm the change to: [NUM2SECLEVEL(tmp_alertlevel)]<BR>"
|
||||
dat += "<A HREF='?src=[REF(src)];operation=swipeidseclevel'>Swipe ID</A> to confirm change.<BR>"
|
||||
if(STATE_TOGGLE_EMERGENCY)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
|
||||
if(GLOB.emergency_access == 1)
|
||||
dat += "<b>Emergency Maintenance Access is currently <font color='red'>ENABLED</font></b>"
|
||||
dat += "<BR>Restore maintenance access restrictions? <BR>\[ <A HREF='?src=[REF(src)];operation=disableemergency'>OK</A> | <A HREF='?src=[REF(src)];operation=viewmessage'>Cancel</A> \]"
|
||||
@@ -722,7 +718,7 @@
|
||||
|
||||
/obj/machinery/computer/communications/proc/make_announcement(mob/living/user, is_silicon)
|
||||
if(!SScommunications.can_announce(user, is_silicon))
|
||||
to_chat(user, "Intercomms recharging. Please stand by.")
|
||||
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))
|
||||
|
||||
@@ -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, "crew", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui = new(user, src, "CrewConsole")
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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, "launchpad_console", 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
|
||||
|
||||
@@ -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, "gulag_console", 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)
|
||||
|
||||
@@ -5,163 +5,122 @@
|
||||
icon_keyboard = "rd_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/computer/robotics
|
||||
var/temp = null
|
||||
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
ui_x = 500
|
||||
ui_y = 460
|
||||
|
||||
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
|
||||
. = FALSE
|
||||
if(!istype(R))
|
||||
return FALSE
|
||||
return
|
||||
if(isAI(user))
|
||||
if (R.connected_ai != user)
|
||||
return FALSE
|
||||
if(R.connected_ai != user)
|
||||
return
|
||||
if(iscyborg(user))
|
||||
if (R != user)
|
||||
return FALSE
|
||||
if(R != user)
|
||||
return
|
||||
if(R.scrambledcodes)
|
||||
return FALSE
|
||||
if (hasSiliconAccessInArea(user) && !issilicon(user))
|
||||
if (!Adjacent(user))
|
||||
return FALSE
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if (src.z > 6)
|
||||
to_chat(user, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
var/robots = 0
|
||||
/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, "RoboticsControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/robotics/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["can_hack"] = FALSE
|
||||
if(issilicon(user))
|
||||
var/mob/living/silicon/S = user
|
||||
if(S.hack_software)
|
||||
data["can_hack"] = TRUE
|
||||
else if(IsAdminGhost(user))
|
||||
data["can_hack"] = TRUE
|
||||
|
||||
data["cyborgs"] = list()
|
||||
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
|
||||
if(!can_control(user, R))
|
||||
continue
|
||||
robots++
|
||||
dat += "[R.name] |"
|
||||
if(R.stat)
|
||||
dat += " Not Responding |"
|
||||
else if(R.locked_down)
|
||||
dat += " Locked Down |"
|
||||
else
|
||||
dat += " Operating Normally |"
|
||||
if(R.cell)
|
||||
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
|
||||
else
|
||||
dat += " No Cell Installed |"
|
||||
if(R.module)
|
||||
dat += " Module Installed ([R.module.name]) |"
|
||||
else
|
||||
dat += " No Module Installed |"
|
||||
if(R.connected_ai)
|
||||
dat += " Slaved to [R.connected_ai.name] |"
|
||||
else
|
||||
dat += " Independent from AI |"
|
||||
if(issilicon(user) && user != R)
|
||||
var/mob/living/silicon/S = user
|
||||
if(is_servant_of_ratvar(S))
|
||||
dat += "<A href='?src=[REF(src)];convert=[REF(R)]'>(<font color=#BE8700><i>Convert</i></font>)</A> "
|
||||
else if(S.hack_software && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
else if(IsAdminGhost(user) && !R.emagged)
|
||||
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.locked_down? "Lockdown" : "Release"]</i></font>)</A> "
|
||||
dat += "<A href='?src=[REF(src)];killbot=[REF(R)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
if(z != (get_turf(R)).z)
|
||||
continue
|
||||
var/list/cyborg_data = list(
|
||||
name = R.name,
|
||||
locked_down = R.locked_down,
|
||||
status = R.stat,
|
||||
charge = R.cell ? round(R.cell.percent()) : null,
|
||||
module = R.module ? "[R.module.name] Module" : "No Module Detected",
|
||||
synchronization = R.connected_ai,
|
||||
emagged = R.emagged,
|
||||
ref = REF(R)
|
||||
)
|
||||
data["cyborgs"] += list(cyborg_data)
|
||||
|
||||
if(!robots)
|
||||
dat += "No Cyborg Units detected within access parameters."
|
||||
dat += "<BR>"
|
||||
|
||||
var/drones = 0
|
||||
data["drones"] = list()
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
|
||||
if(D.hacked)
|
||||
continue
|
||||
drones++
|
||||
dat += "[D.name] |"
|
||||
if(D.stat)
|
||||
dat += " Not Responding |"
|
||||
dat += "<A href='?src=[REF(src)];killdrone=[REF(D)]'>(<font color=red><i>Destroy</i></font>)</A>"
|
||||
dat += "<BR>"
|
||||
if(z != (get_turf(D)).z)
|
||||
continue
|
||||
var/list/drone_data = list(
|
||||
name = D.name,
|
||||
status = D.stat,
|
||||
ref = REF(D)
|
||||
)
|
||||
data["drones"] += list(drone_data)
|
||||
|
||||
if(!drones)
|
||||
dat += "No Drone Units detected within access parameters."
|
||||
return data
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/robotics/Topic(href, href_list)
|
||||
/obj/machinery/computer/robotics/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
else if (href_list["killbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
switch(action)
|
||||
if("killbot")
|
||||
if(allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R) && !..())
|
||||
var/turf/T = get_turf(R)
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!</span>")
|
||||
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
|
||||
R.self_destruct()
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["stopbot"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R))
|
||||
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm" && can_control(usr, R) && !..())
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
if("stopbot")
|
||||
if(allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
if(can_control(usr, R) && !..())
|
||||
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!</span>")
|
||||
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
|
||||
R.SetLockdown(!R.locked_down)
|
||||
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "[!R.locked_down ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
|
||||
else if (href_list["magbot"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
|
||||
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
|
||||
R.SetEmagged(1)
|
||||
|
||||
else if(href_list["convert"])
|
||||
if(isAI(usr) && is_servant_of_ratvar(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
|
||||
log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
|
||||
add_servant_of_ratvar(R)
|
||||
|
||||
else if (href_list["killdrone"])
|
||||
if(src.allowed(usr))
|
||||
var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list
|
||||
if(D.hacked)
|
||||
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
|
||||
else
|
||||
var/turf/T = get_turf(D)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
|
||||
log_game("[key_name(usr)] detonated [key_name(D)]!")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, D)
|
||||
s.start()
|
||||
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
|
||||
D.gib()
|
||||
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
to_chat(usr, "<span class='danger'>Access Denied.</span>")
|
||||
if("magbot")
|
||||
var/mob/living/silicon/S = usr
|
||||
if((istype(S) && S.hack_software) || IsAdminGhost(usr))
|
||||
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
|
||||
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
|
||||
R.SetEmagged(TRUE)
|
||||
if("killdrone")
|
||||
if(allowed(usr))
|
||||
var/mob/living/simple_animal/drone/D = locate(params["ref"]) in GLOB.mob_list
|
||||
if(D.hacked)
|
||||
to_chat(usr, "<span class='danger'>ERROR: [D] is not responding to external commands.</span>")
|
||||
else
|
||||
var/turf/T = get_turf(D)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!")
|
||||
log_game("[key_name(usr)] detonated [key_name(D)]!")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, TRUE, D)
|
||||
s.start()
|
||||
D.visible_message("<span class='danger'>\the [D] self-destructs!</span>")
|
||||
D.gib()
|
||||
|
||||
@@ -662,7 +662,7 @@ What a mess.*/
|
||||
GLOB.data_core.removeMajorCrime(active1.fields["id"], href_list["cdataid"])
|
||||
if("notes")
|
||||
if(istype(active2, /datum/data/record))
|
||||
var/t1 = stripped_input(usr, "Please summarize notes:", "Secure. records", active2.fields["notes"], null)
|
||||
var/t1 = stripped_multiline_input(usr, "Please summarize notes:", "Secure records", active2.fields["notes"], 8192)
|
||||
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
|
||||
return
|
||||
active2.fields["notes"] = t1
|
||||
|
||||
@@ -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, "station_alert", 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
return defib.get_cell()
|
||||
|
||||
//defib interaction
|
||||
/obj/machinery/defibrillator_mount/attack_hand(mob/living/user)
|
||||
/obj/machinery/defibrillator_mount/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!defib)
|
||||
to_chat(user, "<span class='warning'>There's no defibrillator unit loaded!</span>")
|
||||
return
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
if(user.Adjacent(src))
|
||||
. += "<span class='notice'>Alt-click it to beam its contents to any nearby disposal bins.</span>"
|
||||
|
||||
/obj/machinery/dish_drive/attack_hand(mob/living/user)
|
||||
/obj/machinery/dish_drive/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!contents.len)
|
||||
to_chat(user, "<span class='warning'>There's nothing in [src]!</span>")
|
||||
return
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
var/precision_coeff
|
||||
var/message_cooldown
|
||||
var/breakout_time = 1200
|
||||
var/obj/machinery/computer/scan_consolenew/linked_console = null
|
||||
|
||||
/obj/machinery/dna_scannernew/RefreshParts()
|
||||
scan_level = 0
|
||||
@@ -22,8 +23,8 @@
|
||||
precision_coeff = 0
|
||||
for(var/obj/item/stock_parts/scanning_module/P in component_parts)
|
||||
scan_level += P.rating
|
||||
for(var/obj/item/stock_parts/matter_bin/P in component_parts)
|
||||
precision_coeff = P.rating
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
precision_coeff = M.rating
|
||||
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
|
||||
damage_coeff = P.rating
|
||||
|
||||
@@ -31,11 +32,8 @@
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Radiation pulse accuracy increased by factor <b>[precision_coeff**2]</b>.<br>Radiation pulse damage decreased by factor <b>[damage_coeff**2]</b>.</span>"
|
||||
if(scan_level >= 3)
|
||||
. += "<span class='notice'>Scanner has been upgraded to support autoprocessing.<span>"
|
||||
|
||||
/obj/machinery/dna_scannernew/update_icon_state()
|
||||
|
||||
//no power or maintenance
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered"
|
||||
@@ -53,10 +51,6 @@
|
||||
//running
|
||||
icon_state = initial(icon_state)+ (state_open ? "_open" : "")
|
||||
|
||||
/obj/machinery/dna_scannernew/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/dna_scannernew/proc/toggle_open(mob/user)
|
||||
if(panel_open)
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
@@ -76,11 +70,9 @@
|
||||
if(!locked)
|
||||
open_machine()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
"<span class='hear'>You hear a metallic creaking from [src].</span>")
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
|
||||
return
|
||||
@@ -96,33 +88,28 @@
|
||||
return C
|
||||
return null
|
||||
|
||||
/obj/machinery/dna_scannernew/close_machine(atom/movable/target)
|
||||
/obj/machinery/dna_scannernew/close_machine(mob/living/carbon/user)
|
||||
if(!state_open)
|
||||
return FALSE
|
||||
|
||||
..(target)
|
||||
|
||||
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
if(istype(mob_occupant))
|
||||
if(locate_computer(/obj/machinery/computer/cloning))
|
||||
if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound)
|
||||
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
|
||||
..(user)
|
||||
|
||||
// DNA manipulators cannot operate on severed heads or brains
|
||||
if(isliving(occupant))
|
||||
var/obj/machinery/computer/scan_consolenew/console = locate_computer(/obj/machinery/computer/scan_consolenew)
|
||||
if(console)
|
||||
console.on_scanner_close()
|
||||
if(iscarbon(occupant))
|
||||
if(linked_console)
|
||||
linked_console.on_scanner_close()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/open_machine()
|
||||
if(state_open || panel_open)
|
||||
if(state_open)
|
||||
return FALSE
|
||||
|
||||
..()
|
||||
|
||||
if(linked_console)
|
||||
linked_console.on_scanner_open()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
|
||||
@@ -133,51 +120,49 @@
|
||||
return
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/dna_scannernew/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(..())
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) //sent icon_state is irrelevant...
|
||||
update_icon() //..since we're updating the icon here, since the scanner can be unpowered when opened/closed
|
||||
return
|
||||
return FALSE
|
||||
/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
/obj/machinery/dna_scannernew/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return TRUE
|
||||
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
|
||||
update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scannernew/crowbar_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_pry_open(I))
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return TRUE
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scannernew/default_pry_open(obj/item/I) //wew
|
||||
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
|
||||
if(.)
|
||||
I.play_tool_sound(src, 50)
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/dna_scannernew/interact(mob/user)
|
||||
toggle_open(user)
|
||||
|
||||
/obj/machinery/dna_scannernew/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
var/mob/living/L = user
|
||||
if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
|
||||
//Just for transferring between genetics machines.
|
||||
/obj/item/disk/data
|
||||
name = "DNA data disk"
|
||||
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
||||
var/list/genetic_makeup_buffer = list()
|
||||
var/list/fields = list()
|
||||
var/list/mutations = list()
|
||||
var/max_mutations = 6
|
||||
var/read_only = FALSE //Well,it's still a floppy disk
|
||||
|
||||
/obj/item/disk/data/Initialize()
|
||||
. = ..()
|
||||
icon_state = "datadisk[rand(0,6)]"
|
||||
add_overlay("datadisk_gene")
|
||||
|
||||
/obj/item/disk/data/attack_self(mob/user)
|
||||
read_only = !read_only
|
||||
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
|
||||
|
||||
/obj/item/disk/data/examine(mob/user)
|
||||
. = ..()
|
||||
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
|
||||
|
||||
@@ -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
|
||||
@@ -157,6 +157,10 @@
|
||||
. = ..()
|
||||
AddComponent(/datum/component/ntnet_interface)
|
||||
|
||||
/obj/machinery/door/airlock/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
if(id_tag)
|
||||
id_tag = "[idnum][id_tag]"
|
||||
|
||||
/obj/machinery/door/airlock/proc/update_other_id()
|
||||
for(var/obj/machinery/door/airlock/A in GLOB.airlocks)
|
||||
if(A.closeOtherId == closeOtherId && A != src)
|
||||
@@ -188,7 +192,7 @@
|
||||
/obj/machinery/door/airlock/vv_edit_var(var_name)
|
||||
. = ..()
|
||||
switch (var_name)
|
||||
if ("cyclelinkeddir")
|
||||
if (NAMEOF(src, cyclelinkeddir))
|
||||
cyclelinkairlock()
|
||||
|
||||
/obj/machinery/door/airlock/check_access_ntnet(datum/netdata/data)
|
||||
@@ -294,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
|
||||
@@ -305,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 ..()
|
||||
@@ -759,13 +763,10 @@
|
||||
/obj/machinery/door/airlock/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/door/airlock/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/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)
|
||||
@@ -779,6 +780,8 @@
|
||||
H.apply_damage(10, BRUTE, BODY_ZONE_HEAD)
|
||||
else
|
||||
visible_message("<span class='danger'>[user] headbutts the airlock. Good thing [user.p_theyre()] wearing a helmet.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/airlock/attempt_wire_interaction(mob/user)
|
||||
if(security_level)
|
||||
@@ -787,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)
|
||||
@@ -822,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)
|
||||
|
||||
@@ -836,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>",
|
||||
@@ -1067,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
|
||||
|
||||
@@ -1087,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 )
|
||||
@@ -1109,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)
|
||||
@@ -1357,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))
|
||||
@@ -1436,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, "ai_airlock", name, 500, 390, master_ui, state)
|
||||
ui = new(user, src, "AiAirlock", name)
|
||||
ui.open()
|
||||
return TRUE
|
||||
|
||||
@@ -1448,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
|
||||
@@ -1491,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)
|
||||
@@ -1527,7 +1540,6 @@
|
||||
. = TRUE
|
||||
if("speed-toggle")
|
||||
normalspeed = !normalspeed
|
||||
|
||||
. = TRUE
|
||||
if("open-close")
|
||||
user_toggle_open(usr)
|
||||
|
||||
@@ -2,42 +2,54 @@
|
||||
name = "airlock electronics"
|
||||
req_access = list(ACCESS_MAINT_TUNNELS)
|
||||
custom_price = PRICE_CHEAP
|
||||
|
||||
/// A list of all granted accesses
|
||||
var/list/accesses = list()
|
||||
/// If the airlock should require ALL or only ONE of the listed accesses
|
||||
var/one_access = 0
|
||||
var/unres_sides = 0 //unrestricted sides, or sides of the airlock that will open regardless of access
|
||||
/// Unrestricted sides, or sides of the airlock that will open regardless of access
|
||||
var/unres_sides = 0
|
||||
/// A holder of the electronics, in case of them working as an integrated part
|
||||
var/holder
|
||||
|
||||
/obj/item/electronics/airlock/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<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)
|
||||
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, "airlock_electronics", name, 420, 485, master_ui, state)
|
||||
ui = new(user, src, "AirlockElectronics", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/electronics/airlock/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/regions = list()
|
||||
for(var/i in 1 to 7)
|
||||
var/list/accesses = list()
|
||||
for(var/access in get_region_accesses(i))
|
||||
if (get_access_desc(access))
|
||||
accesses += list(list(
|
||||
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||
"ref" = access,
|
||||
))
|
||||
|
||||
regions += list(list(
|
||||
"name" = get_region_accesses_name(i),
|
||||
"regid" = i,
|
||||
"accesses" = accesses
|
||||
))
|
||||
|
||||
data["regions"] = regions
|
||||
return data
|
||||
|
||||
/obj/item/electronics/airlock/ui_data()
|
||||
var/list/data = list()
|
||||
var/list/regions = list()
|
||||
|
||||
for(var/i in 1 to 7)
|
||||
var/list/region = list()
|
||||
var/list/accesses = list()
|
||||
for(var/j in get_region_accesses(i))
|
||||
var/list/access = list()
|
||||
access["name"] = get_access_desc(j)
|
||||
access["id"] = j
|
||||
access["req"] = (j in src.accesses)
|
||||
accesses[++accesses.len] = access
|
||||
region["name"] = get_region_accesses_name(i)
|
||||
region["accesses"] = accesses
|
||||
regions[++regions.len] = region
|
||||
data["regions"] = regions
|
||||
data["accesses"] = accesses
|
||||
data["oneAccess"] = one_access
|
||||
data["unres_direction"] = unres_sides
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/electronics/airlock/ui_act(action, params)
|
||||
@@ -48,12 +60,12 @@
|
||||
accesses = list()
|
||||
one_access = 0
|
||||
. = TRUE
|
||||
if("one_access")
|
||||
one_access = !one_access
|
||||
. = TRUE
|
||||
if("grant_all")
|
||||
accesses = get_all_accesses()
|
||||
. = TRUE
|
||||
if("one_access")
|
||||
one_access = !one_access
|
||||
. = TRUE
|
||||
if("set")
|
||||
var/access = text2num(params["access"])
|
||||
if (!(access in accesses))
|
||||
@@ -65,3 +77,20 @@
|
||||
var/unres_direction = text2num(params["unres_direction"])
|
||||
unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked
|
||||
. = TRUE
|
||||
if("grant_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
accesses |= get_region_accesses(region)
|
||||
. = TRUE
|
||||
if("deny_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region))
|
||||
return
|
||||
accesses -= get_region_accesses(region)
|
||||
. = TRUE
|
||||
|
||||
/obj/item/electronics/airlock/ui_host()
|
||||
if(holder)
|
||||
return holder
|
||||
return src
|
||||
|
||||
@@ -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, "brig_timer", 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
|
||||
@@ -140,10 +140,7 @@
|
||||
do_animate("deny")
|
||||
return
|
||||
|
||||
/obj/machinery/door/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/door/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
return try_to_activate_door(user)
|
||||
|
||||
/obj/machinery/door/attack_tk(mob/user)
|
||||
@@ -343,6 +340,11 @@
|
||||
/obj/machinery/door/proc/crush()
|
||||
for(var/mob/living/L in get_turf(src))
|
||||
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
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.
|
||||
L.emote("roar")
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70)
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
|
||||
air_tight = TRUE
|
||||
attack_hand_is_action = TRUE
|
||||
attack_hand_speed = CLICK_CD_MELEE
|
||||
var/emergency_close_timer = 0
|
||||
var/nextstate = null
|
||||
var/boltslocked = TRUE
|
||||
@@ -80,7 +82,6 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/machinery/door/firedoor/power_change()
|
||||
if(powered(power_channel))
|
||||
stat &= ~NOPOWER
|
||||
@@ -88,11 +89,7 @@
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
/obj/machinery/door/firedoor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
/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)
|
||||
@@ -103,7 +100,6 @@
|
||||
return TRUE
|
||||
if(operating || !density)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
user.visible_message("[user] bangs on \the [src].",
|
||||
"You bang on \the [src].")
|
||||
@@ -302,7 +298,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
|
||||
@@ -324,7 +320,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
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
damage_deflection = 70
|
||||
poddoor = TRUE
|
||||
|
||||
/obj/machinery/door/poddoor/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
id = "[idnum][id]"
|
||||
|
||||
/obj/machinery/door/poddoor/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
if(user)
|
||||
log_game("[user] reset a fire alarm at [COORD(src)]")
|
||||
|
||||
/obj/machinery/firealarm/attack_hand(mob/user)
|
||||
/obj/machinery/firealarm/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(buildstage != 2)
|
||||
return ..()
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
else
|
||||
bulb = new(src)
|
||||
|
||||
/obj/machinery/flasher/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
id = "[idnum][id]"
|
||||
|
||||
/obj/machinery/flasher/Destroy()
|
||||
QDEL_NULL(bulb)
|
||||
return ..()
|
||||
|
||||
@@ -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, "gulag_item_reclaimer", 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])
|
||||
|
||||
@@ -101,8 +101,6 @@ The console is located at computer/gulag_teleporter.dm
|
||||
if(!locked)
|
||||
open_machine()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
harvesting = FALSE
|
||||
warming_up = FALSE
|
||||
|
||||
/obj/machinery/harvester/attack_hand(mob/user)
|
||||
/obj/machinery/harvester/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else if(!harvesting)
|
||||
|
||||
+183
-188
@@ -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
|
||||
@@ -78,7 +107,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
new_disk.forceMove(src)
|
||||
disk = new_disk
|
||||
|
||||
/obj/machinery/holopad/tutorial/attack_hand(mob/user)
|
||||
/obj/machinery/holopad/tutorial/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.incapacitated() || !is_operational())
|
||||
@@ -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
|
||||
|
||||
@@ -178,8 +176,6 @@
|
||||
icon_state += "_occupied"
|
||||
|
||||
/obj/machinery/hypnochair/container_resist(mob/living/user)
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(600)].)</span>", \
|
||||
"<span class='hear'>You hear a metallic creaking from [src].</span>")
|
||||
@@ -203,3 +199,4 @@
|
||||
if(!(L.mobility_flags & MOBILITY_STAND))
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
on = TRUE
|
||||
icon_state = "igniter1"
|
||||
|
||||
/obj/machinery/igniter/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/igniter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
add_fingerprint(user)
|
||||
|
||||
use_power(50)
|
||||
@@ -53,6 +50,9 @@
|
||||
else
|
||||
icon_state = "igniter0"
|
||||
|
||||
/obj/machinery/igniter/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
id = "[idnum][id]"
|
||||
|
||||
// Wall mounted remote-control igniter.
|
||||
|
||||
/obj/machinery/sparker
|
||||
|
||||
@@ -158,12 +158,7 @@
|
||||
attached.transfer_blood_to(beaker, amount)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/iv_drip/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!ishuman(user))
|
||||
return
|
||||
/obj/machinery/iv_drip/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(attached)
|
||||
visible_message("[attached] is detached from [src]")
|
||||
attached = null
|
||||
@@ -174,7 +169,11 @@
|
||||
else
|
||||
toggle_mode()
|
||||
|
||||
/obj/machinery/iv_drip/verb/eject_beaker()
|
||||
/obj/machinery/iv_drip/attack_robot(mob/user)
|
||||
if(Adjacent(user))
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/iv_drip/verb/eject_beaker(mob/user)
|
||||
set category = "Object"
|
||||
set name = "Remove IV Container"
|
||||
set src in view(1)
|
||||
@@ -189,6 +188,8 @@
|
||||
if(usr && Adjacent(usr) && usr.can_hold_items())
|
||||
if(!usr.put_in_hands(beaker))
|
||||
beaker.forceMove(drop_location())
|
||||
if(iscyborg(user))
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -282,13 +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, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
|
||||
ui.set_style("syndicate")
|
||||
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)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
var/id = 1
|
||||
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
|
||||
|
||||
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
id = "[idnum][id]"
|
||||
|
||||
/obj/machinery/mass_driver/proc/drive(amount)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
|
||||
@@ -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,69 +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
|
||||
|
||||
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/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()
|
||||
. = ..()
|
||||
@@ -99,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"
|
||||
@@ -118,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)
|
||||
@@ -159,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)
|
||||
@@ -283,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>")
|
||||
@@ -292,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)
|
||||
. = ..()
|
||||
@@ -313,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
|
||||
@@ -381,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
|
||||
@@ -418,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
|
||||
@@ -431,11 +462,18 @@
|
||||
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)
|
||||
popDown() // no valid targets, close the cover
|
||||
|
||||
/obj/machinery/porta_turret/proc/randomize_shot_stagger()
|
||||
shot_stagger = rand(0, min(2 SECONDS, round(shot_delay/3, world.tick_lag)))
|
||||
|
||||
/obj/machinery/porta_turret/proc/tryToShootAt(list/atom/movable/targets)
|
||||
while(targets.len > 0)
|
||||
var/atom/movable/M = pick(targets)
|
||||
@@ -443,7 +481,6 @@
|
||||
if(target(M))
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/proc/popUp() //pops the turret up
|
||||
if(!anchored)
|
||||
return
|
||||
@@ -485,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)
|
||||
@@ -525,18 +563,21 @@
|
||||
if(target)
|
||||
popUp() //pop the turret up if it's not already up.
|
||||
setDir(get_dir(base, target))//even if you can't shoot, follow the target
|
||||
shootAt(target)
|
||||
INVOKE_ASYNC(src, .proc/shootAt, target)
|
||||
return 1
|
||||
return
|
||||
|
||||
/obj/machinery/porta_turret/proc/shootAt(atom/movable/target)
|
||||
/obj/machinery/porta_turret/proc/shootAt(atom/movable/target, stagger_enabled = FALSE)
|
||||
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)
|
||||
@@ -557,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)
|
||||
@@ -576,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:
|
||||
@@ -586,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'
|
||||
@@ -679,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"
|
||||
@@ -692,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"
|
||||
@@ -709,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
|
||||
@@ -743,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
|
||||
@@ -798,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
|
||||
@@ -811,7 +858,6 @@
|
||||
stun_projectile_sound = 'sound/weapons/gunshot.ogg'
|
||||
desc = "A ballistic machine gun auto-turret."
|
||||
|
||||
|
||||
////////////////////////
|
||||
//Turret Control Panel//
|
||||
////////////////////////
|
||||
@@ -822,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)
|
||||
. = ..()
|
||||
@@ -862,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()
|
||||
@@ -1045,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)
|
||||
@@ -1077,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
|
||||
@@ -1106,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)
|
||||
|
||||
@@ -79,6 +79,9 @@
|
||||
if(PTURRET_INTERNAL_ARMOUR_ON)
|
||||
if(istype(I, /obj/item/gun/energy)) //the gun installation part
|
||||
var/obj/item/gun/energy/E = I
|
||||
if(!E.can_turret)
|
||||
to_chat(user, "<span class='warning'>[src] can't be fit into turrets.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(E, src))
|
||||
return
|
||||
installed_gun = E
|
||||
@@ -168,10 +171,7 @@
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/porta_turret_construct/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/porta_turret_construct/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
switch(build_step)
|
||||
if(PTURRET_GUN_EQUIPPED)
|
||||
build_step = PTURRET_INTERNAL_ARMOUR_ON
|
||||
|
||||
@@ -31,10 +31,7 @@
|
||||
return parent_turret.attack_ai(user)
|
||||
|
||||
|
||||
/obj/machinery/porta_turret_cover/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/porta_turret_cover/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
|
||||
return parent_turret.attack_hand(user)
|
||||
|
||||
|
||||
@@ -108,10 +108,7 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/recharger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/recharger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
|
||||
add_fingerprint(user)
|
||||
if(charging)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -225,6 +225,6 @@
|
||||
|
||||
/obj/item/paper/guides/recycler
|
||||
name = "paper - 'garbage duty instructions'"
|
||||
info = "<h2>New Assignment</h2> You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
info = "_New Assignment_\n\n You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
|
||||
#undef SAFETY_COOLDOWN
|
||||
|
||||
@@ -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, "space_heater", 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(.)
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
if(!.)
|
||||
return
|
||||
switch(var_name)
|
||||
if("shuttle_id")
|
||||
if(NAMEOF(src, shuttle_id))
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
|
||||
@@ -301,8 +301,6 @@
|
||||
open_machine()
|
||||
dump_contents()
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
@@ -379,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, "suit_storage_unit", name, 400, 305, master_ui, state)
|
||||
ui = new(user, src, "SuitStorageUnit", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
|
||||
@@ -68,10 +68,7 @@ GLOBAL_VAR_INIT(singularity_counter, 0)
|
||||
/obj/machinery/power/singularity_beacon/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/power/singularity_beacon/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/power/singularity_beacon/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(anchored)
|
||||
return active ? Deactivate(user) : Activate(user)
|
||||
else
|
||||
|
||||
@@ -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, "tcommsserver", "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, "telepdalog", name, 727, 510, master_ui, state)
|
||||
ui = new(user, src, "TelecommsPDALog", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
|
||||
@@ -389,7 +388,6 @@
|
||||
|
||||
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
|
||||
info = "<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
|
||||
info_links = info
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
|
||||
@@ -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, "telemonitor", 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, "teleinteract", "[name] Access", 520, 500, master_ui, state)
|
||||
ui = new(user, src, "TelecommsInteraction", "[name] Access")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/telecomms/ui_data(mob/user)
|
||||
|
||||
@@ -5,16 +5,73 @@
|
||||
require the message server.
|
||||
*/
|
||||
|
||||
// A decorational representation of SSblackbox, usually placed alongside the message server.
|
||||
// A decorational representation of SSblackbox, usually placed alongside the message server. Also contains a traitor theft item.
|
||||
/obj/machinery/blackbox_recorder
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "blackbox"
|
||||
name = "Blackbox Recorder"
|
||||
name = "blackbox recorder"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
|
||||
var/obj/item/stored
|
||||
|
||||
/obj/machinery/blackbox_recorder/Initialize()
|
||||
. = ..()
|
||||
stored = new /obj/item/blackbox(src)
|
||||
|
||||
/obj/machinery/blackbox_recorder/on_attack_hand(mob/living/user, act_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(stored)
|
||||
to_chat(user, "<span class='notice'>You start struggling to pry the [stored] from the [src]...</span>")
|
||||
if(!do_after(user, 30 SECONDS, TRUE, src))
|
||||
to_chat(user, "<span class='warning'>Your fingers slip as you fail to pry the [stored] from the [src], clicking it right back into the slot!</span>")
|
||||
return
|
||||
if(user.put_in_hands(stored))
|
||||
stored.forceMove(user.drop_location())
|
||||
stored = null
|
||||
to_chat(user, "<span class='warning'>You successfully pry the [stored] from the [src], and send its overwhelming weight tumbling onto the ground! The tapes on the [src] stop spinning...</span>")
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>It seems that the blackbox is missing...</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/blackbox_recorder/attackby(obj/item/I, mob/living/user, params)
|
||||
. = ..()
|
||||
if(istype(I, /obj/item/blackbox))
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to your hand!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] clicks the [I] into the [src]!</span>", \
|
||||
"<span class='notice'>You press [I] into [src], and it clicks into place. The tapes on the [src] begin spinning again...</span>")
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
stored = I
|
||||
update_icon()
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/blackbox_recorder/Destroy()
|
||||
if(stored)
|
||||
stored.forceMove(loc)
|
||||
new /obj/effect/decal/cleanable/oil(loc)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/blackbox_recorder/update_icon()
|
||||
. = ..()
|
||||
if(!stored)
|
||||
icon_state = "blackbox_b"
|
||||
else
|
||||
icon_state = "blackbox"
|
||||
|
||||
/obj/item/blackbox
|
||||
name = "the blackbox"
|
||||
desc = "A strange relic, capable of recording data on extradimensional vertices. It lives inside the blackbox recorder for safe keeping."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "blackcube"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
|
||||
|
||||
// The message server itself.
|
||||
@@ -140,9 +197,9 @@
|
||||
..()
|
||||
if(href_list["photo"])
|
||||
var/mob/M = usr
|
||||
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
|
||||
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
|
||||
var/dat = "<div style='overflow: hidden; margin :0; text-align: center'>"
|
||||
dat += "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />"
|
||||
dat += "</div>"
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
/obj/machinery/turnstile/CanAtmosPass(turf/T)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/turnstile/bullet_act(obj/item/projectile/P, def_zone)
|
||||
return BULLET_ACT_FORCE_PIERCE //Pass through!
|
||||
|
||||
/obj/machinery/turnstile/proc/allowed_access(var/mob/B)
|
||||
if(B.pulledby && ismob(B.pulledby))
|
||||
return allowed(B.pulledby) | allowed(B)
|
||||
@@ -28,6 +25,8 @@
|
||||
return allowed(B)
|
||||
|
||||
/obj/machinery/turnstile/CanPass(atom/movable/AM, turf/T)
|
||||
if(istype(AM, /obj/item/projectile))
|
||||
return TRUE
|
||||
if(ismob(AM))
|
||||
var/mob/B = AM
|
||||
if(isliving(AM))
|
||||
@@ -60,6 +59,8 @@
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/turnstile/CheckExit(atom/movable/AM as mob|obj, target)
|
||||
if(istype(AM, /obj/item/projectile))
|
||||
return TRUE
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
var/outdir = dir
|
||||
@@ -81,4 +82,4 @@
|
||||
M.last_bumped = world.time
|
||||
return canexit
|
||||
else
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -297,10 +297,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/washing_machine/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/machinery/washing_machine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(busy)
|
||||
to_chat(user, "<span class='warning'>[src] is busy.</span>")
|
||||
return
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/charges = 1
|
||||
var/insisting = 0
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
/obj/machinery/wish_granter/on_attack_hand(mob/living/carbon/user)
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
@@ -31,7 +31,7 @@
|
||||
user.dna.add_mutation(XRAY)
|
||||
user.dna.add_mutation(SPACEMUT)
|
||||
user.dna.add_mutation(TK)
|
||||
user.next_move_modifier *= 0.5 //half the delay between attacks!
|
||||
user.action_cooldown_mod *= 0.5
|
||||
to_chat(user, "Things around you feel slower!")
|
||||
charges--
|
||||
insisting = FALSE
|
||||
@@ -101,7 +101,7 @@
|
||||
to_chat(user, "[killreward] materializes into your hands!")
|
||||
else
|
||||
to_chat(user, "[killreward] materializes onto the floor.")
|
||||
user.next_move_modifier *= 0.8 //20% less delay between attacks!
|
||||
user.action_cooldown_mod *= 0.8
|
||||
to_chat(user, "Things around you feel slightly slower!")
|
||||
var/mob/living/simple_animal/hostile/venus_human_trap/killwish = new /mob/living/simple_animal/hostile/venus_human_trap(loc)
|
||||
killwish.maxHealth = 1500
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
internals_req_access = list()
|
||||
add_req_access = 0
|
||||
wreckage = /obj/structure/mecha_wreckage/durand/neovgre
|
||||
stepsound = 'sound/mecha/neostep2.ogg'
|
||||
turnsound = 'sound/mecha/powerloader_step.ogg'
|
||||
|
||||
/obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar!
|
||||
internals_action.Grant(user, src)
|
||||
@@ -32,7 +34,7 @@
|
||||
|
||||
/obj/mecha/combat/neovgre/MouseDrop_T(mob/M, mob/user)
|
||||
if(!is_servant_of_ratvar(user))
|
||||
to_chat(user, "<span class='brass'>BEGONE HERETIC!</span>")
|
||||
to_chat(user, "<span class='neovgre'>BEGONE HEATHEN!</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
@@ -91,7 +93,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre
|
||||
equip_cooldown = 8 //Rapid fire heavy laser cannon, simple yet elegant
|
||||
energy_drain = 30
|
||||
name = "Aribter Laser Cannon"
|
||||
name = "Arbiter Laser Cannon"
|
||||
desc = "Please re-attach this to neovgre and stop asking questions about why it looks like a normal Nanotrasen issue Solaris laser cannon - Nezbere"
|
||||
fire_sound = 'sound/weapons/neovgre_laser.ogg'
|
||||
|
||||
|
||||
@@ -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, "mech_bay_power_console", "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
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
infra_luminosity = 15 //byond implementation is bugged.
|
||||
force = 5
|
||||
flags_1 = HEAR_1|BLOCK_FACE_ATOM_1
|
||||
attack_hand_speed = CLICK_CD_MELEE
|
||||
attack_hand_is_action = TRUE
|
||||
var/can_move = 0 //time of next allowed movement
|
||||
var/mob/living/occupant = null
|
||||
var/step_in = 10 //make a step in step_in/10 sec.
|
||||
|
||||
@@ -5,62 +5,71 @@
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/computer/mecha_control
|
||||
var/list/located = list()
|
||||
var/screen = 0
|
||||
var/stored_data
|
||||
|
||||
/obj/machinery/computer/mecha/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
|
||||
if(screen == 0)
|
||||
dat += "<h3>Tracking beacons data</h3>"
|
||||
var/list/trackerlist = list()
|
||||
for(var/obj/mecha/MC in GLOB.mechas_list)
|
||||
trackerlist += MC.trackers
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/TR in trackerlist)
|
||||
var/answer = TR.get_mecha_info()
|
||||
if(answer)
|
||||
dat += {"<hr>[answer]<br/>
|
||||
<a href='?src=[REF(src)];send_message=[REF(TR)]'>Send message</a><br/>
|
||||
<a href='?src=[REF(src)];get_log=[REF(TR)]'>Show exosuit log</a><br/>
|
||||
[TR.recharging?"Recharging EMP Pulse...<br>":"<a style='color: #f00;' href='?src=[REF(src)];shock=[REF(TR)]'>(EMP Pulse)</a><br>"]"}
|
||||
/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, "ExosuitControlConsole", name)
|
||||
ui.open()
|
||||
|
||||
if(screen==1)
|
||||
dat += "<h3>Log contents</h3>"
|
||||
dat += "<a href='?src=[REF(src)];return=1'>Return</a><hr>"
|
||||
dat += "[stored_data]"
|
||||
/obj/machinery/computer/mecha/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
dat += "<A href='?src=[REF(src)];refresh=1'>(Refresh)</A><BR>"
|
||||
dat += "</body></html>"
|
||||
var/list/trackerlist = list()
|
||||
for(var/obj/mecha/MC in GLOB.mechas_list)
|
||||
trackerlist += MC.trackers
|
||||
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
onclose(user, "computer")
|
||||
data["mechs"] = list()
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/MT in trackerlist)
|
||||
if(!MT.chassis)
|
||||
continue
|
||||
var/obj/mecha/M = MT.chassis
|
||||
var/list/mech_data = list(
|
||||
name = M.name,
|
||||
integrity = round((M.obj_integrity / M.max_integrity) * 100),
|
||||
charge = M.cell ? round(M.cell.percent()) : null,
|
||||
airtank = M.internal_tank ? M.return_pressure() : null,
|
||||
pilot = M.occupant,
|
||||
location = get_area_name(M, TRUE),
|
||||
active_equipment = M.selected,
|
||||
emp_recharging = MT.recharging,
|
||||
tracker_ref = REF(MT)
|
||||
)
|
||||
if(istype(M, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = M
|
||||
mech_data += list(
|
||||
cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100)
|
||||
)
|
||||
|
||||
/obj/machinery/computer/mecha/Topic(href, href_list)
|
||||
data["mechs"] += list(mech_data)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/mecha/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["send_message"])
|
||||
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["send_message"])
|
||||
if (!istype(MT))
|
||||
return
|
||||
var/message = stripped_input(usr,"Input message","Transmit message")
|
||||
var/obj/mecha/M = MT.in_mecha()
|
||||
if(trim(message) && M)
|
||||
M.occupant_message(message)
|
||||
return
|
||||
if(href_list["shock"])
|
||||
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["shock"])
|
||||
if (istype(MT))
|
||||
MT.shock()
|
||||
if(href_list["get_log"])
|
||||
var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["get_log"])
|
||||
if(istype(MT))
|
||||
stored_data = MT.get_mecha_log()
|
||||
screen = 1
|
||||
if(href_list["return"])
|
||||
screen = 0
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("send_message")
|
||||
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"])
|
||||
if(!istype(MT))
|
||||
return
|
||||
var/message = stripped_input(usr, "Input message", "Transmit message")
|
||||
var/obj/mecha/M = MT.chassis
|
||||
if(trim(message) && M)
|
||||
M.occupant_message(message)
|
||||
to_chat(usr, "<span class='notice'>Message sent.</span>")
|
||||
. = TRUE
|
||||
if("shock")
|
||||
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"])
|
||||
if(!istype(MT))
|
||||
return
|
||||
var/obj/mecha/M = MT.chassis
|
||||
if(M)
|
||||
MT.shock()
|
||||
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which is currently [M.occupant? "being piloted by [key_name(M.occupant)]." : "without a pilot."] ")
|
||||
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "being piloted by [key_name_admin(M.occupant)][ADMIN_FLW(M.occupant)]." : "without a pilot."] ")
|
||||
. = TRUE
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking
|
||||
name = "exosuit tracking beacon"
|
||||
@@ -68,24 +77,31 @@
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "motion2"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/ai_beacon = FALSE //If this beacon allows for AI control. Exists to avoid using istype() on checking.
|
||||
var/recharging = 0
|
||||
/// If this beacon allows for AI control. Exists to avoid using istype() on checking
|
||||
var/ai_beacon = FALSE
|
||||
/// Cooldown variable for EMP pulsing
|
||||
var/recharging = FALSE
|
||||
/// The Mecha that this tracking beacon is attached to
|
||||
var/obj/mecha/chassis
|
||||
|
||||
/**
|
||||
* Returns a html formatted string describing attached mech status
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
|
||||
if(!in_mecha())
|
||||
return 0
|
||||
var/obj/mecha/M = src.loc
|
||||
var/cell_charge = M.get_charge()
|
||||
var/answer = {"<b>Name:</b> [M.name]
|
||||
<b>Integrity:</b> [M.obj_integrity/M.max_integrity*100]%
|
||||
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
|
||||
<b>Airtank:</b> [M.return_pressure()]kPa
|
||||
<b>Pilot:</b> [M.occupant||"None"]
|
||||
<b>Location:</b> [get_area(M)||"Unknown"]
|
||||
<b>Active equipment:</b> [M.selected||"None"] "}
|
||||
if(istype(M, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = M
|
||||
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
|
||||
if(!chassis)
|
||||
return FALSE
|
||||
|
||||
var/cell_charge = chassis.get_charge()
|
||||
var/answer = {"<b>Name:</b> [chassis.name]<br>
|
||||
<b>Integrity:</b> [round((chassis.obj_integrity/chassis.max_integrity * 100), 0.01)]%<br>
|
||||
<b>Cell Charge:</b> [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]<br>
|
||||
<b>Airtank:</b> [chassis.internal_tank ? "[round(chassis.return_pressure(), 0.01)]" : "Not Equipped"] kPa<br>
|
||||
<b>Pilot:</b> [chassis.occupant || "None"]<br>
|
||||
<b>Location:</b> [get_area_name(chassis, TRUE) || "Unknown"]<br>
|
||||
<b>Active Equipment:</b> [chassis.selected || "None"]"}
|
||||
if(istype(chassis, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = chassis
|
||||
answer += "<br><b>Used Cargo Space:</b> [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%"
|
||||
|
||||
return answer
|
||||
|
||||
@@ -95,42 +111,41 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/Destroy()
|
||||
if(ismecha(loc))
|
||||
var/obj/mecha/M = loc
|
||||
if(src in M.trackers)
|
||||
M.trackers -= src
|
||||
if(chassis)
|
||||
if(src in chassis.trackers)
|
||||
chassis.trackers -= src
|
||||
chassis = null
|
||||
return ..()
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
|
||||
if(ismecha(loc))
|
||||
return loc
|
||||
return 0
|
||||
/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/mecha/M)
|
||||
if(!..())
|
||||
return
|
||||
M.trackers += src
|
||||
M.diag_hud_set_mechtracking()
|
||||
chassis = M
|
||||
|
||||
/**
|
||||
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/shock()
|
||||
if(recharging)
|
||||
return
|
||||
var/obj/mecha/M = in_mecha()
|
||||
if(M)
|
||||
M.emp_act(EMP_HEAVY)
|
||||
addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 15 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
recharging = 1
|
||||
if(chassis)
|
||||
chassis.emp_act(EMP_HEAVY)
|
||||
addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
recharging = TRUE
|
||||
|
||||
/**
|
||||
* Resets recharge variable, allowing tracker to be EMP pulsed again
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
|
||||
recharging = 0
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
|
||||
if(!ismecha(loc))
|
||||
return 0
|
||||
var/obj/mecha/M = src.loc
|
||||
return M.get_log_html()
|
||||
|
||||
recharging = FALSE
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/ai_control
|
||||
name = "exosuit AI control beacon"
|
||||
desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit."
|
||||
ai_beacon = TRUE
|
||||
|
||||
|
||||
/obj/item/storage/box/mechabeacons
|
||||
name = "exosuit tracking beacons"
|
||||
|
||||
|
||||
@@ -54,11 +54,7 @@
|
||||
. *= booster_damage_modifier
|
||||
|
||||
|
||||
/obj/mecha/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code.
|
||||
/obj/mecha/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', 40, 1, -1)
|
||||
user.visible_message("<span class='danger'>[user] hits [name]. Nothing happens</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
@@ -255,7 +251,7 @@
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
if(obj_integrity < max_integrity)
|
||||
if(W.use_tool(src, user, 0, volume=50, amount=1))
|
||||
if (internal_damage & MECHA_INT_TANK_BREACH)
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
w_class = WEIGHT_CLASS_GIGANTIC
|
||||
flags_1 = CONDUCT_1
|
||||
|
||||
/obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/mecha/M) //For attaching parts to a finished mech
|
||||
if(!user.transferItemToLoc(src, M))
|
||||
to_chat(user, "<span class='warning'>\The [src] is stuck to your hand, you cannot put it in \the [M]!</span>")
|
||||
return FALSE
|
||||
user.visible_message("<span class='notice'>[user] attaches [src] to [M].</span>", "<span class='notice'>You attach [src] to [M].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/mecha_parts/chassis
|
||||
name = "Mecha Chassis"
|
||||
icon_state = "backbone"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
var/buckle_prevents_pull = FALSE
|
||||
|
||||
//Interaction
|
||||
/atom/movable/attack_hand(mob/living/user)
|
||||
/atom/movable/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
@@ -145,3 +145,13 @@
|
||||
var/mob/living/L = M.pulledby
|
||||
L.set_pull_offsets(M, L.grab_state)
|
||||
return M
|
||||
|
||||
/atom/movable/proc/precise_user_unbuckle_mob(mob/user)
|
||||
if(!buckled_mobs)
|
||||
return
|
||||
else if(length(buckled_mobs) == 1)
|
||||
return user_unbuckle_mob(buckled_mobs[1], user)
|
||||
else
|
||||
var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs
|
||||
return user_unbuckle_mob(unbuckled, user)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -23,8 +23,10 @@
|
||||
START_PROCESSING(SSobj, src)
|
||||
impact_area = get_area(src)
|
||||
|
||||
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
|
||||
|
||||
@@ -75,7 +77,7 @@
|
||||
|
||||
|
||||
/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 +87,7 @@
|
||||
icon_state = "shield2"
|
||||
density = FALSE
|
||||
var/boing = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/grav
|
||||
|
||||
/obj/effect/anomaly/grav/anomalyEffect()
|
||||
..()
|
||||
@@ -95,17 +98,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 +147,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 +158,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 +171,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 +187,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 +199,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 +236,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 +260,7 @@
|
||||
name = "pyroclastic anomaly"
|
||||
icon_state = "mustard"
|
||||
var/ticks = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/pyro
|
||||
|
||||
/obj/effect/anomaly/pyro/anomalyEffect()
|
||||
..()
|
||||
@@ -278,6 +293,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()
|
||||
..()
|
||||
|
||||
@@ -101,10 +101,7 @@
|
||||
to_chat(user, "<span class='notice'>You carefully remove the poster from the wall.</span>")
|
||||
roll_and_drop(user.loc)
|
||||
|
||||
/obj/structure/sign/poster/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/structure/sign/poster/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(ruined)
|
||||
return
|
||||
visible_message("[user] rips [src] in a single, decisive motion!" )
|
||||
|
||||
@@ -137,10 +137,7 @@
|
||||
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
|
||||
beauty = -150
|
||||
|
||||
/obj/effect/decal/cleanable/vomit/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(isflyperson(H))
|
||||
|
||||
@@ -268,6 +268,8 @@
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
attack_hand_speed = CLICK_CD_MELEE
|
||||
attack_hand_is_action = TRUE
|
||||
|
||||
/obj/structure/foamedmetal/Initialize()
|
||||
. = ..()
|
||||
@@ -284,11 +286,7 @@
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
/obj/structure/foamedmetal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, "<span class='warning'>You hit [src] but bounce off it!</span>")
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
@@ -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)))
|
||||
@@ -60,16 +62,13 @@
|
||||
/obj/effect/portal/attack_tk(mob/user)
|
||||
return
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
/obj/effect/portal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(get_turf(user) == get_turf(src))
|
||||
teleport(user)
|
||||
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)
|
||||
@@ -81,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
|
||||
|
||||
@@ -132,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))
|
||||
@@ -156,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
|
||||
|
||||
@@ -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
|
||||
@@ -466,7 +464,7 @@
|
||||
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 2,
|
||||
/obj/effect/spawner/lootdrop/space_cash/no_turf = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
|
||||
/obj/item/storage/pill_bottle/dice = 5,
|
||||
/obj/item/storage/box/dice = 5,
|
||||
/obj/item/toy/cards/deck = 5,
|
||||
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5
|
||||
)
|
||||
@@ -485,7 +483,7 @@
|
||||
/obj/effect/spawner/lootdrop/cig_packs/no_turf = 10,
|
||||
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
|
||||
/obj/item/storage/pill_bottle/dice = 5,
|
||||
/obj/item/storage/box/dice = 5,
|
||||
/obj/item/toy/cards/deck = 5,
|
||||
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5,
|
||||
/obj/item/kitchen/knife = 5,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user