Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into putnamos-for-real
This commit is contained in:
+16
-1
@@ -38,6 +38,10 @@
|
||||
var/poweralm = TRUE
|
||||
var/lightswitch = TRUE
|
||||
|
||||
var/totalbeauty = 0 //All beauty in this area combined, only includes indoor area.
|
||||
var/beauty = 0 // Beauty average per open turf in the area
|
||||
var/beauty_threshold = 150 //If a room is too big it doesn't have beauty.
|
||||
|
||||
var/requires_power = TRUE
|
||||
/// This gets overridden to 1 for space in area/Initialize().
|
||||
var/always_unpowered = FALSE
|
||||
@@ -65,7 +69,7 @@
|
||||
/// Hides area from player Teleport function.
|
||||
var/hidden = FALSE
|
||||
/// Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
|
||||
var/safe = FALSE
|
||||
var/safe = FALSE
|
||||
/// If false, loading multiple maps with this area type will create multiple instances.
|
||||
var/unique = TRUE
|
||||
|
||||
@@ -192,6 +196,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
/area/LateInitialize()
|
||||
if(!base_area) //we don't want to run it twice.
|
||||
power_change() // all machines set to current power level, also updates icon
|
||||
update_beauty()
|
||||
|
||||
/area/proc/reg_in_areas_in_z()
|
||||
if(contents.len)
|
||||
@@ -538,6 +543,16 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
L.client.played = TRUE
|
||||
addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600)
|
||||
|
||||
///Divides total beauty in the room by roomsize to allow us to get an average beauty per tile.
|
||||
/area/proc/update_beauty()
|
||||
if(!areasize)
|
||||
beauty = 0
|
||||
return FALSE
|
||||
if(areasize >= beauty_threshold)
|
||||
beauty = 0
|
||||
return FALSE //Too big
|
||||
beauty = totalbeauty / areasize
|
||||
|
||||
/area/Exited(atom/movable/M)
|
||||
SEND_SIGNAL(src, COMSIG_AREA_EXITED, M)
|
||||
SEND_SIGNAL(M, COMSIG_EXIT_AREA, src) //The atom that exits the area
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
/area/centcom/vip
|
||||
name = "VIP Zone"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
/area/centcom/winterball
|
||||
|
||||
/area/centcom/winterball
|
||||
name = "winterball Zone"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@
|
||||
/area/ruin/powered/seedvault
|
||||
icon_state = "dk_yellow"
|
||||
|
||||
/area/ruin/unpowered/elephant_graveyard
|
||||
name = "Elephant Graveyard"
|
||||
icon_state = "dk_yellow"
|
||||
|
||||
/area/ruin/powered/graveyard_shuttle
|
||||
name = "Elephant Graveyard"
|
||||
icon_state = "green"
|
||||
|
||||
/area/ruin/unpowered/syndicate_lava_base
|
||||
name = "Secret Base"
|
||||
icon_state = "dk_yellow"
|
||||
|
||||
@@ -129,7 +129,26 @@
|
||||
icon_state = "crew_quarters"
|
||||
|
||||
|
||||
//Ruin of Space Diner
|
||||
|
||||
/area/ruin/space/diner
|
||||
name = "Space Diner"
|
||||
|
||||
/area/ruin/space/diner/interior
|
||||
name = "Space Diner"
|
||||
icon_state = "maintbar"
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
blob_allowed = FALSE //Nope, no winning in the diner as a blob. Gotta eat the main station.
|
||||
|
||||
/area/ruin/space/diner/solars
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
|
||||
valid_territory = FALSE
|
||||
blob_allowed = FALSE
|
||||
flags_1 = NONE
|
||||
ambientsounds = ENGINEERING
|
||||
name = "Space Diner Solar Array"
|
||||
icon_state = "yellow"
|
||||
|
||||
//Ruin of Derelict Oupost
|
||||
|
||||
|
||||
@@ -93,6 +93,13 @@
|
||||
/area/shuttle/abandoned/pod
|
||||
name = "Abandoned Ship Pod"
|
||||
|
||||
////////////////////////////Bounty Hunter Shuttles////////////////////////////
|
||||
/area/shuttle/hunter
|
||||
name = "Hunter Shuttle"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
blob_allowed = FALSE
|
||||
canSmoothWithAreas = /area/shuttle/hunter
|
||||
|
||||
////////////////////////////Single-area shuttles////////////////////////////
|
||||
|
||||
/area/shuttle/transit
|
||||
@@ -103,6 +110,10 @@
|
||||
/area/shuttle/custom
|
||||
name = "Custom player shuttle"
|
||||
|
||||
/area/shuttle/custom/powered
|
||||
name = "Custom Powered player shuttle"
|
||||
requires_power = FALSE
|
||||
|
||||
/area/shuttle/arrival
|
||||
name = "Arrival Shuttle"
|
||||
unique = TRUE // SSjob refers to this area for latejoiners
|
||||
@@ -200,4 +211,7 @@
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/caravan/freighter3
|
||||
name = "Tiny Freighter"
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/snowtaxi
|
||||
name = "Snow Taxi"
|
||||
|
||||
+86
-49
@@ -8,6 +8,13 @@
|
||||
var/interaction_flags_atom = NONE
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
var/flags_ricochet = NONE
|
||||
|
||||
///When a projectile tries to ricochet off this atom, the projectile ricochet chance is multiplied by this
|
||||
var/ricochet_chance_mod = 1
|
||||
///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom
|
||||
var/ricochet_damage_mod = 0.33
|
||||
|
||||
//This atom's HUD (med/sec, etc) images. Associative list.
|
||||
var/list/image/hud_list = null
|
||||
//HUD images that this atom can provide.
|
||||
@@ -41,12 +48,15 @@
|
||||
var/rad_insulation = RAD_NO_INSULATION
|
||||
|
||||
///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.)
|
||||
///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials].
|
||||
var/list/custom_materials
|
||||
///Bitfield for how the atom handles materials.
|
||||
var/material_flags = NONE
|
||||
///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines.
|
||||
var/material_modifier = 1
|
||||
|
||||
var/datum/wires/wires = null
|
||||
|
||||
var/icon/blood_splatter_icon
|
||||
var/list/fingerprints
|
||||
var/list/fingerprintshidden
|
||||
@@ -105,11 +115,8 @@
|
||||
if (canSmoothWith)
|
||||
canSmoothWith = typelist("canSmoothWith", canSmoothWith)
|
||||
|
||||
var/temp_list = list()
|
||||
for(var/i in custom_materials)
|
||||
temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version
|
||||
custom_materials = null //Null the list to prepare for applying the materials properly
|
||||
set_custom_materials(temp_list)
|
||||
// apply materials properly from the default custom_materials value
|
||||
set_custom_materials(custom_materials)
|
||||
|
||||
ComponentInitialize()
|
||||
|
||||
@@ -139,8 +146,27 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Checks if a projectile should ricochet off of us. Projectiles get final say.
|
||||
* [__DEFINES/projectiles.dm] for return values.
|
||||
*/
|
||||
/atom/proc/check_projectile_ricochet(obj/item/projectile/P)
|
||||
return (flags_1 & DEFAULT_RICOCHET_1)? PROJECTILE_RICOCHET_YES : PROJECTILE_RICOCHET_NO
|
||||
|
||||
/atom/proc/handle_ricochet(obj/item/projectile/P)
|
||||
return
|
||||
var/turf/p_turf = get_turf(P)
|
||||
var/face_direction = get_dir(src, p_turf)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
|
||||
var/a_incidence_s = abs(incidence_s)
|
||||
if(a_incidence_s > 90 && a_incidence_s < 270)
|
||||
return FALSE
|
||||
if((P.flag in list("bullet", "bomb")) && P.ricochet_incidence_leeway)
|
||||
if((a_incidence_s < 90 && a_incidence_s < 90 - P.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > P.ricochet_incidence_leeway))
|
||||
return
|
||||
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
|
||||
P.setAngle(new_angle_s)
|
||||
return TRUE
|
||||
|
||||
/atom/proc/CanPass(atom/movable/mover, turf/target)
|
||||
return !density
|
||||
@@ -313,10 +339,11 @@
|
||||
. += desc
|
||||
|
||||
if(custom_materials)
|
||||
var/list/materials_list = list()
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/M = i
|
||||
. += "<u>It is made out of [M.name]</u>."
|
||||
|
||||
materials_list += "[M.name]"
|
||||
. += "<u>It is made out of [english_list(materials_list)]</u>."
|
||||
if(reagents)
|
||||
if(reagents.reagents_holder_flags & TRANSPARENT)
|
||||
. += "It contains:"
|
||||
@@ -409,7 +436,7 @@
|
||||
var/blood_id = get_blood_id()
|
||||
if(!(blood_id in GLOB.blood_reagent_types))
|
||||
return
|
||||
return list("ANIMAL DNA" = "Y-")
|
||||
return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
|
||||
|
||||
/mob/living/carbon/get_blood_dna_list()
|
||||
var/blood_id = get_blood_id()
|
||||
@@ -417,13 +444,15 @@
|
||||
return
|
||||
var/list/blood_dna = list()
|
||||
if(dna)
|
||||
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
|
||||
blood_dna[dna.unique_enzymes] = dna.blood_type
|
||||
else
|
||||
blood_dna["color"] = BLOOD_COLOR_HUMAN
|
||||
blood_dna["UNKNOWN DNA"] = "X*"
|
||||
return blood_dna
|
||||
|
||||
/mob/living/carbon/alien/get_blood_dna_list()
|
||||
return list("UNKNOWN DNA" = "X*")
|
||||
return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
|
||||
|
||||
//to add a mob's dna info into an object's blood_DNA list.
|
||||
/atom/proc/transfer_mob_blood_dna(mob/living/L)
|
||||
@@ -434,18 +463,33 @@
|
||||
LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
|
||||
var/old_length = blood_DNA.len
|
||||
blood_DNA |= new_blood_dna
|
||||
var/changed = FALSE
|
||||
if(!blood_DNA["color"])
|
||||
blood_DNA["color"] = new_blood_dna["color"]
|
||||
changed = TRUE
|
||||
else
|
||||
var/old = blood_DNA["color"]
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
|
||||
changed = old != blood_DNA["color"]
|
||||
if(blood_DNA.len == old_length)
|
||||
return FALSE
|
||||
return TRUE
|
||||
return changed
|
||||
|
||||
//to add blood dna info to the object's blood_DNA list
|
||||
/atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases)
|
||||
LAZYINITLIST(blood_DNA)
|
||||
|
||||
var/old_length = blood_DNA.len
|
||||
blood_DNA |= blood_dna
|
||||
if(blood_DNA.len > old_length)
|
||||
return TRUE
|
||||
. = TRUE
|
||||
//some new blood DNA was added
|
||||
if(!blood_dna["color"])
|
||||
return
|
||||
if(!blood_DNA["color"])
|
||||
blood_DNA["color"] = blood_dna["color"]
|
||||
else
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
|
||||
|
||||
//to add blood from a mob onto something, and transfer their dna info
|
||||
/atom/proc/add_mob_blood(mob/living/M)
|
||||
@@ -514,28 +558,7 @@
|
||||
return TRUE
|
||||
|
||||
/atom/proc/blood_DNA_to_color()
|
||||
var/list/colors = list()//first we make a list of all bloodtypes present
|
||||
for(var/bloop in blood_DNA)
|
||||
if(colors[blood_DNA[bloop]])
|
||||
colors[blood_DNA[bloop]]++
|
||||
else
|
||||
colors[blood_DNA[bloop]] = 1
|
||||
|
||||
var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up
|
||||
|
||||
if(colors.len)
|
||||
var/sum = 0 //this is all shitcode, but it works; trust me
|
||||
final_rgb = bloodtype_to_color(colors[1])
|
||||
sum = colors[colors[1]]
|
||||
if(colors.len > 1)
|
||||
var/i = 2
|
||||
while(i <= colors.len)
|
||||
var/tmp = colors[colors[i]]
|
||||
final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum))
|
||||
sum += tmp
|
||||
i++
|
||||
|
||||
return final_rgb
|
||||
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
|
||||
|
||||
/atom/proc/clean_blood()
|
||||
. = blood_DNA? TRUE : FALSE
|
||||
@@ -581,6 +604,14 @@
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Respond to a electric bolt action on our item
|
||||
*
|
||||
* Default behaviour is to return, we define here to allow for cleaner code later on
|
||||
*/
|
||||
/atom/proc/zap_act(power, zap_flags, shocked_targets)
|
||||
return
|
||||
|
||||
/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user)
|
||||
if(GetComponent(/datum/component/storage))
|
||||
return component_storage_contents_dump_act(src_object, user)
|
||||
@@ -835,6 +866,17 @@
|
||||
/atom/proc/GenerateTag()
|
||||
return
|
||||
|
||||
/**
|
||||
* Called after a shuttle is loaded **from map template initially**.
|
||||
*
|
||||
* @params
|
||||
* * port - Mobile port/shuttle
|
||||
* * dock - Stationary dock the shuttle's at
|
||||
* * idnum - ID number of the shuttle
|
||||
*/
|
||||
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
return
|
||||
|
||||
// Generic logging helper
|
||||
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
|
||||
if(!log_globally)
|
||||
@@ -927,14 +969,14 @@ Proc for attack log creation, because really why not
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
|
||||
// Filter stuff
|
||||
/atom/movable/proc/add_filter(name,priority,list/params)
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
var/list/p = params.Copy()
|
||||
p["priority"] = priority
|
||||
filter_data[name] = p
|
||||
update_filters()
|
||||
|
||||
/atom/movable/proc/update_filters()
|
||||
/atom/proc/update_filters()
|
||||
filters = null
|
||||
filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE)
|
||||
for(var/f in filter_data)
|
||||
@@ -943,11 +985,11 @@ Proc for attack log creation, because really why not
|
||||
arguments -= "priority"
|
||||
filters += filter(arglist(arguments))
|
||||
|
||||
/atom/movable/proc/get_filter(name)
|
||||
/atom/proc/get_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
return filters[filter_data.Find(name)]
|
||||
|
||||
/atom/movable/proc/remove_filter(name)
|
||||
/atom/proc/remove_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
filter_data -= name
|
||||
update_filters()
|
||||
@@ -958,26 +1000,21 @@ Proc for attack log creation, because really why not
|
||||
|
||||
///Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(var/list/materials, multiplier = 1)
|
||||
|
||||
if(!materials)
|
||||
materials = custom_materials
|
||||
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
|
||||
custom_material.on_removed(src, material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
custom_materials = null
|
||||
return
|
||||
|
||||
custom_materials = list() //Reset the list
|
||||
if(material_flags)
|
||||
for(var/x in materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
|
||||
custom_material.on_applied(src, materials[x] * multiplier * material_modifier, material_flags)
|
||||
|
||||
for(var/x in materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
|
||||
|
||||
if(material_flags & MATERIAL_EFFECTS)
|
||||
custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags)
|
||||
custom_materials[custom_material] += materials[x] * multiplier
|
||||
custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier)
|
||||
|
||||
/**
|
||||
* Returns true if this atom has gravity for the passed in turf
|
||||
|
||||
+18
-16
@@ -37,6 +37,8 @@
|
||||
var/throwforce = 0
|
||||
var/datum/component/orbiter/orbiting
|
||||
var/can_be_z_moved = TRUE
|
||||
///If we were without gravity and another animation happened, the bouncing will stop, and we need to restart it in next life().
|
||||
var/floating_need_update = FALSE
|
||||
|
||||
var/zfalling = FALSE
|
||||
|
||||
@@ -56,10 +58,6 @@
|
||||
em_block = new(src, render_target)
|
||||
vis_contents += em_block
|
||||
|
||||
/atom/movable/Destroy()
|
||||
QDEL_NULL(em_block)
|
||||
return ..()
|
||||
|
||||
/atom/movable/proc/update_emissive_block()
|
||||
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
|
||||
return
|
||||
@@ -183,14 +181,15 @@
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/stop_pulling()
|
||||
if(pulling)
|
||||
pulling.pulledby = null
|
||||
var/mob/living/ex_pulled = pulling
|
||||
pulling = null
|
||||
setGrabState(0)
|
||||
if(isliving(ex_pulled))
|
||||
var/mob/living/L = ex_pulled
|
||||
L.update_mobility()// mob gets up if it was lyng down in a chokehold
|
||||
if(!pulling)
|
||||
return
|
||||
pulling.pulledby = null
|
||||
var/mob/living/ex_pulled = pulling
|
||||
pulling = null
|
||||
setGrabState(0)
|
||||
if(isliving(ex_pulled))
|
||||
var/mob/living/L = ex_pulled
|
||||
L.update_mobility()// mob gets up if it was lyng down in a chokehold
|
||||
|
||||
/atom/movable/proc/Move_Pulled(atom/A)
|
||||
if(!pulling)
|
||||
@@ -232,10 +231,12 @@
|
||||
/atom/movable/Destroy(force)
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
QDEL_NULL(em_block)
|
||||
|
||||
unbuckle_all_mobs(force=1)
|
||||
|
||||
. = ..()
|
||||
|
||||
if(loc)
|
||||
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
|
||||
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
|
||||
@@ -493,15 +494,16 @@
|
||||
/atom/movable/proc/float(on)
|
||||
if(throwing)
|
||||
return
|
||||
if(on && !(movement_type & FLOATING))
|
||||
if(on && (!(movement_type & FLOATING) || floating_need_update))
|
||||
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
|
||||
sleep(10)
|
||||
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && (movement_type & FLOATING))
|
||||
if(!(movement_type & FLOATING))
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && movement_type & FLOATING)
|
||||
animate(src, pixel_y = initial(pixel_y), time = 10)
|
||||
setMovetype(movement_type & ~FLOATING)
|
||||
|
||||
floating_need_update = FALSE
|
||||
|
||||
/* Language procs
|
||||
* Unless you are doing something very specific, these are the ones you want to use.
|
||||
|
||||
@@ -51,4 +51,4 @@
|
||||
|
||||
H.dna.add_mutation(CLOWNMUT)
|
||||
H.dna.add_mutation(SMILE)
|
||||
H.gain_trauma(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_LOBOTOMY, "clowns") //MWA HA HA
|
||||
H.gain_trauma(/datum/brain_trauma/mild/phobia/clowns, TRAUMA_RESILIENCE_LOBOTOMY) //MWA HA HA
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
icon_state = "moustacheg"
|
||||
clumsy_check = GRENADE_NONCLUMSY_FUMBLE
|
||||
|
||||
/obj/item/grenade/chem_grenade/teargas/moustache/prime()
|
||||
/obj/item/grenade/chem_grenade/teargas/moustache/prime(mob/living/lanced_by)
|
||||
var/list/check_later = list()
|
||||
for(var/mob/living/carbon/C in get_turf(src))
|
||||
check_later += C
|
||||
|
||||
@@ -48,9 +48,6 @@
|
||||
/obj/machinery/dominator/hulk_damage()
|
||||
return (max_integrity - integrity_failure) / DOM_HULK_HITS_REQUIRED
|
||||
|
||||
/obj/machinery/dominator/tesla_act()
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/dominator/update_icon()
|
||||
cut_overlays()
|
||||
if(stat & BROKEN)
|
||||
@@ -148,9 +145,9 @@
|
||||
new /obj/item/stack/sheet/plasteel(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/dominator/attacked_by(obj/item/I, mob/living/user)
|
||||
/obj/machinery/dominator/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/dominator/attack_hand(mob/user)
|
||||
if(operating || (stat & BROKEN))
|
||||
@@ -243,4 +240,4 @@
|
||||
|
||||
#undef DOM_BLOCKED_SPAM_CAP
|
||||
#undef DOM_REQUIRED_TURFS
|
||||
#undef DOM_HULK_HITS_REQUIRED
|
||||
#undef DOM_HULK_HITS_REQUIRED
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/obj/effect/decal/cleanable/crayon/gang
|
||||
icon = 'icons/effects/crayondecal.dmi'
|
||||
layer = ABOVE_NORMAL_TURF_LAYER //Harder to hide
|
||||
plane = GAME_PLANE
|
||||
plane = ABOVE_WALL_PLANE
|
||||
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
|
||||
var/datum/team/gang/gang
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
|
||||
name = "Fragmentation Grenade"
|
||||
id = "frag nade"
|
||||
cost = 5
|
||||
item_path = /obj/item/grenade/syndieminibomb/concussion/frag
|
||||
item_path = /obj/item/grenade/frag
|
||||
|
||||
/datum/gang_item/equipment/implant_breaker
|
||||
name = "Implant Breaker"
|
||||
|
||||
@@ -201,10 +201,13 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
return won || ..()
|
||||
|
||||
/datum/objective/assassinate/once/process()
|
||||
won = check_completion()
|
||||
won = check_midround_completion()
|
||||
if(won)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
|
||||
/datum/objective/assassinate/once/proc/check_midround_completion()
|
||||
return won || !considered_alive(target) //The target afking / logging off for a bit during the round doesn't complete it, but them being afk at roundend does.
|
||||
|
||||
/datum/objective/assassinate/internal
|
||||
var/stolen = 0 //Have we already eliminated this target?
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
targetitem = /obj/item/gun/energy/e_gun/hos
|
||||
difficulty = 10
|
||||
excludefromjob = list("Head Of Security")
|
||||
altitems = list(/obj/item/gun/ballistic/revolver/mws, /obj/item/choice_beacon/hosgun) //We now look for either the alt verson of the hos gun or the beacon picker.
|
||||
|
||||
/datum/objective_item/steal/handtele
|
||||
name = "a hand teleporter."
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
|
||||
/mob
|
||||
var/datum/hSB/sandbox = null
|
||||
|
||||
/mob/proc/CanBuild()
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
|
||||
/datum/game_mode/wizard/are_special_antags_dead()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
for(var/datum/mind/wizard in wizards | apprentices)
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
return FALSE
|
||||
|
||||
@@ -58,6 +58,14 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/wizard/check_finished()
|
||||
. = ..()
|
||||
if(.)
|
||||
finished = TRUE
|
||||
else if(gamemode_ready && are_special_antags_dead() && !CONFIG_GET(keyed_list/continuous)[config_tag])
|
||||
finished = TRUE
|
||||
. = TRUE
|
||||
|
||||
/datum/game_mode/wizard/set_round_result()
|
||||
..()
|
||||
if(finished)
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
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)
|
||||
@@ -429,3 +434,45 @@
|
||||
|
||||
/obj/machinery/sleeper/old
|
||||
icon_state = "oldpod"
|
||||
|
||||
/obj/machinery/sleeper/party
|
||||
name = "party pod"
|
||||
desc = "'Sleeper' units were once known for their healing properties, until a lengthy investigation revealed they were also dosing patients with deadly lead acetate. This appears to be one of those old 'sleeper' units repurposed as a 'Party Pod'. It’s probably not a good idea to use it."
|
||||
icon_state = "partypod"
|
||||
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(
|
||||
list(/datum/reagent/consumable/ethanol/beer, /datum/reagent/consumable/laughter),
|
||||
list(/datum/reagent/spraytan,/datum/reagent/barbers_aid),
|
||||
list(/datum/reagent/colorful_reagent,/datum/reagent/hair_dye),
|
||||
list(/datum/reagent/drug/space_drugs,/datum/reagent/baldium)
|
||||
)//Exclusively uses non-lethal, "fun" chems. At an obvious downside.
|
||||
var/spray_chems = list(
|
||||
/datum/reagent/spraytan, /datum/reagent/hair_dye, /datum/reagent/baldium, /datum/reagent/barbers_aid
|
||||
)//Chemicals that need to have a touch or vapor reaction to be applied, not the standard chamber reaction.
|
||||
enter_message = "<span class='notice'><b>You're surrounded by some funky music inside the chamber. You zone out as you feel waves of krunk vibe within you.</b></span>"
|
||||
|
||||
/obj/machinery/sleeper/party/inject_chem(chem, mob/user)
|
||||
if(leddit)
|
||||
occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, 4) //You're injecting chemicals into yourself from a recalled, decrepit medical machine. What did you expect?
|
||||
else if (prob(20))
|
||||
occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, rand(1,3))
|
||||
if(chem in spray_chems)
|
||||
var/datum/reagents/holder = new()
|
||||
holder.add_reagent(chem_buttons[chem], 10) //I hope this is the correct way to do this.
|
||||
holder.reaction(occupant, VAPOR, 0)
|
||||
holder.trans_to(occupant, 10)
|
||||
playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6)
|
||||
if(user)
|
||||
log_combat(user, occupant, "sprayed [chem] into", addition = "via [src]")
|
||||
return TRUE
|
||||
..()
|
||||
|
||||
/obj/machinery/sleeper/party/emag_act(mob/user)
|
||||
..()
|
||||
leddit = TRUE
|
||||
|
||||
@@ -92,6 +92,8 @@ 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_ricochet = RICOCHET_HARD
|
||||
ricochet_chance_mod = 0.3
|
||||
|
||||
anchored = TRUE
|
||||
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
|
||||
@@ -110,7 +112,8 @@ Class Procs:
|
||||
var/state_open = FALSE
|
||||
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
|
||||
var/list/occupant_typecache //if set, turned into typecache in Initialize, other wise, defaults to mob/living typecache
|
||||
var/atom/movable/occupant = null
|
||||
var/atom/movable/occupant
|
||||
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
|
||||
var/speed_process = FALSE // Process as fast as possible?
|
||||
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
|
||||
// For storing and overriding ui id and dimensions
|
||||
@@ -217,6 +220,7 @@ Class Procs:
|
||||
if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled))
|
||||
occupant = target
|
||||
target.forceMove(src)
|
||||
target.setDir(new_occupant_dir)
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
|
||||
@@ -520,11 +524,11 @@ Class Procs:
|
||||
/obj/machinery/proc/can_be_overridden()
|
||||
. = 1
|
||||
|
||||
/obj/machinery/tesla_act(power, tesla_flags, shocked_objects)
|
||||
..()
|
||||
if(prob(85) && (tesla_flags & TESLA_MACHINE_EXPLOSIVE))
|
||||
/obj/machinery/zap_act(power, zap_flags, shocked_objects)
|
||||
. = ..()
|
||||
if(prob(85) && (zap_flags & ZAP_MACHINE_EXPLOSIVE))
|
||||
explosion(src, 1, 2, 4, flame_range = 2, adminlog = FALSE, smoke = FALSE)
|
||||
if(tesla_flags & TESLA_OBJ_DAMAGE)
|
||||
else if(zap_flags & ZAP_OBJ_DAMAGE)
|
||||
take_damage(power/2000, BURN, "energy")
|
||||
if(prob(40))
|
||||
emp_act(EMP_LIGHT)
|
||||
|
||||
@@ -46,28 +46,16 @@
|
||||
"Dinnerware",
|
||||
"Imported"
|
||||
)
|
||||
var/list/allowed_materials = list(
|
||||
/datum/material/iron,
|
||||
/datum/material/glass,
|
||||
/datum/material/gold,
|
||||
/datum/material/silver,
|
||||
/datum/material/diamond,
|
||||
/datum/material/uranium,
|
||||
/datum/material/plasma,
|
||||
/datum/material/bluespace,
|
||||
/datum/material/bananium,
|
||||
/datum/material/titanium,
|
||||
/datum/material/runite,
|
||||
/datum/material/plastic,
|
||||
/datum/material/adamantine,
|
||||
/datum/material/mythril
|
||||
)
|
||||
var/list/allowed_materials
|
||||
|
||||
/// Base print speed
|
||||
var/base_print_speed = 10
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, allowed_materials, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
var/list/mats = allowed_materials
|
||||
if(!mats)
|
||||
mats = SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID]
|
||||
AddComponent(/datum/component/material_container, mats, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
stored_research = new stored_research
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
|
||||
if(istext(id) && mapload)
|
||||
if(copytext(id, 1, 2) == "!")
|
||||
id = SSmapping.get_obfuscated_id(id)
|
||||
if(istext(id) && mapload && id[1] == "!")
|
||||
id = SSmapping.get_obfuscated_id(id)
|
||||
. = ..()
|
||||
var/turf/T = get_turf_pixel(src)
|
||||
if(iswallturf(T))
|
||||
plane = ABOVE_WALL_PLANE
|
||||
|
||||
if(built)
|
||||
setDir(ndir)
|
||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
|
||||
@@ -27,7 +30,6 @@
|
||||
panel_open = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
if(!built && !device && device_type)
|
||||
device = new device_type(src)
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
// UPGRADE PROCS
|
||||
|
||||
/obj/machinery/camera/proc/upgradeEmpProof()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS)
|
||||
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly))
|
||||
upgrades |= CAMERA_UPGRADE_EMP_PROOF
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
var/efficiency
|
||||
|
||||
var/datum/mind/clonemind
|
||||
var/get_clone_mind = CLONEPOD_GET_MIND
|
||||
var/grab_ghost_when = CLONER_MATURE_CLONE
|
||||
|
||||
var/internal_radio = TRUE
|
||||
@@ -134,43 +135,44 @@
|
||||
return examine(user)
|
||||
|
||||
//Start growing a human clone in the pod!
|
||||
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance)
|
||||
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
|
||||
if(panel_open)
|
||||
return FALSE
|
||||
if(mess || attempting)
|
||||
return FALSE
|
||||
clonemind = locate(mindref) in SSticker.minds
|
||||
if(!istype(clonemind)) //not a mind
|
||||
return FALSE
|
||||
if(!QDELETED(clonemind.current))
|
||||
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
|
||||
if(get_clone_mind == CLONEPOD_GET_MIND)
|
||||
clonemind = locate(mindref) in SSticker.minds
|
||||
if(!istype(clonemind)) //not a mind
|
||||
return FALSE
|
||||
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
|
||||
if(!QDELETED(clonemind.current))
|
||||
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
|
||||
return FALSE
|
||||
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
|
||||
return FALSE
|
||||
if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
|
||||
return FALSE
|
||||
if(clonemind.active) //somebody is using that mind
|
||||
if( ckey(clonemind.key)!=ckey )
|
||||
return FALSE
|
||||
else
|
||||
// get_ghost() will fail if they're unable to reenter their body
|
||||
var/mob/dead/observer/G = clonemind.get_ghost()
|
||||
if(!G)
|
||||
return FALSE
|
||||
if(G.suiciding) // The ghost came from a body that is suiciding.
|
||||
return FALSE
|
||||
if(clonemind.damnation_type) //Can't clone the damned.
|
||||
INVOKE_ASYNC(src, .proc/horrifyingsound)
|
||||
mess = TRUE
|
||||
update_icon()
|
||||
return FALSE
|
||||
if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
|
||||
return FALSE
|
||||
if(clonemind.active) //somebody is using that mind
|
||||
if( ckey(clonemind.key)!=ckey )
|
||||
return FALSE
|
||||
else
|
||||
// get_ghost() will fail if they're unable to reenter their body
|
||||
var/mob/dead/observer/G = clonemind.get_ghost()
|
||||
if(!G)
|
||||
return FALSE
|
||||
if(G.suiciding) // The ghost came from a body that is suiciding.
|
||||
return FALSE
|
||||
if(clonemind.damnation_type) //Can't clone the damned.
|
||||
INVOKE_ASYNC(src, .proc/horrifyingsound)
|
||||
mess = TRUE
|
||||
update_icon()
|
||||
return FALSE
|
||||
current_insurance = insurance
|
||||
attempting = TRUE //One at a time!!
|
||||
countdown.start()
|
||||
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
||||
|
||||
H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
|
||||
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
|
||||
|
||||
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
|
||||
|
||||
@@ -192,7 +194,14 @@
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
|
||||
H.Unconscious(80)
|
||||
|
||||
clonemind.transfer_to(H)
|
||||
if(clonemind)
|
||||
clonemind.transfer_to(H)
|
||||
|
||||
else if(get_clone_mind == CLONEPOD_POLL_MIND)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/C = pick(candidates)
|
||||
H.key = C.key
|
||||
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
@@ -209,6 +218,12 @@
|
||||
var/datum/quirk/Q = new V(H)
|
||||
Q.on_clone(quirks[V])
|
||||
|
||||
for(var/t in traumas)
|
||||
var/datum/brain_trauma/BT = t
|
||||
var/datum/brain_trauma/cloned_trauma = BT.on_clone()
|
||||
if(cloned_trauma)
|
||||
H.gain_trauma(cloned_trauma, BT.resilience)
|
||||
|
||||
H.set_cloned_appearance()
|
||||
H.give_genitals(TRUE)
|
||||
|
||||
@@ -271,9 +286,6 @@
|
||||
var/obj/item/bodypart/BP = I
|
||||
BP.attach_limb(mob_occupant)
|
||||
|
||||
//Premature clones may have brain damage.
|
||||
mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult))
|
||||
|
||||
use_power(7500) //This might need tweaking.
|
||||
|
||||
else if((mob_occupant && mob_occupant.cloneloss <= (100 - heal_level)))
|
||||
@@ -399,6 +411,8 @@
|
||||
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
|
||||
mob_occupant.flash_act()
|
||||
|
||||
mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, mob_occupant.getCloneLoss())
|
||||
|
||||
occupant.forceMove(T)
|
||||
update_icon()
|
||||
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
|
||||
@@ -474,10 +488,9 @@
|
||||
unattached_flesh.Cut()
|
||||
|
||||
H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
|
||||
//H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE)
|
||||
// In addition to being cellularly damaged and having barely any
|
||||
|
||||
// brain function, they also have no limbs or internal organs.
|
||||
// In addition to being cellularly damaged, they also have no limbs or internal organs.
|
||||
// Applying brainloss is done when the clone leaves the pod, so application of traumas can happen.
|
||||
// based on the level of damage sustained.
|
||||
|
||||
if(!HAS_TRAIT(H, TRAIT_NODISMEMBER))
|
||||
var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
@@ -545,6 +558,17 @@
|
||||
. += "cover-on"
|
||||
. += "panel"
|
||||
|
||||
//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
|
||||
/obj/machinery/clonepod/experimental
|
||||
name = "experimental cloning pod"
|
||||
desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
|
||||
icon = 'icons/obj/machines/cloning.dmi'
|
||||
icon_state = "pod_0"
|
||||
req_access = null
|
||||
circuit = /obj/item/circuitboard/machine/clonepod/experimental
|
||||
internal_radio = FALSE
|
||||
get_clone_mind = CLONEPOD_POLL_MIND
|
||||
|
||||
/*
|
||||
* Manual -- A big ol' manual.
|
||||
*/
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
/obj/item/clothing/mask/facehugger/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/gun/ballistic/automatic/toy/pistol/unrestricted = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/hot_potato/harmless/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/dualsaber/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/dualsaber/hypereutactic/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/dualsaber/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE,
|
||||
|
||||
/obj/item/storage/box/snappops = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/under/syndicate/tacticool = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
@@ -175,6 +175,12 @@
|
||||
clockwork = TRUE //it'd look very weird
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/Initialize()
|
||||
. = ..()
|
||||
var/turf/T = get_turf_pixel(src)
|
||||
if(iswallturf(T))
|
||||
plane = ABOVE_WALL_PLANE
|
||||
|
||||
/obj/machinery/computer/security/telescreen/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(stat & BROKEN)
|
||||
@@ -251,3 +257,12 @@
|
||||
name = "AI upload monitor"
|
||||
desc = "A telescreen that connects to the AI upload's camera network."
|
||||
network = list("aiupload")
|
||||
|
||||
// Subtype that connects to shuttles.
|
||||
/obj/machinery/computer/security/shuttle
|
||||
circuit = /obj/item/circuitboard/computer/security/shuttle
|
||||
|
||||
/obj/machinery/computer/security/shuttle/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]"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
circuit = /obj/item/circuitboard/computer/cloning
|
||||
req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW.
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/clonepod_type = /obj/machinery/clonepod
|
||||
var/list/pods //Linked cloning pods
|
||||
var/temp = "Inactive"
|
||||
var/scantemp_ckey
|
||||
@@ -17,6 +18,7 @@
|
||||
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
|
||||
var/loading = 0 // Nice loading text
|
||||
var/autoprocess = 0
|
||||
var/use_records = TRUE // Old experimental cloner.
|
||||
var/list/records = list()
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
@@ -36,29 +38,32 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return null
|
||||
if(pod.is_operational() && !(pod.occupant || pod.mess))
|
||||
return pod
|
||||
if(!pods)
|
||||
return
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind)
|
||||
return null
|
||||
if(pod.is_operational() && !(pod.occupant || pod.mess))
|
||||
return pod
|
||||
|
||||
/obj/machinery/computer/cloning/proc/HasEfficientPod()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.is_operational() && pod.efficiency > 5)
|
||||
return TRUE
|
||||
if(!pods)
|
||||
return
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.is_operational() && pod.efficiency > 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return pod
|
||||
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
|
||||
. = pod
|
||||
if(!pods)
|
||||
return
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/pod = P
|
||||
if(pod.occupant && pod.clonemind == mind)
|
||||
return pod
|
||||
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
|
||||
. = pod
|
||||
|
||||
/obj/machinery/computer/cloning/process()
|
||||
if(!(scanner && LAZYLEN(pods) && autoprocess))
|
||||
@@ -73,7 +78,7 @@
|
||||
if(pod.occupant)
|
||||
continue //how though?
|
||||
|
||||
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"]))
|
||||
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
|
||||
temp = "[R.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
|
||||
records -= R
|
||||
|
||||
@@ -103,12 +108,10 @@
|
||||
return null
|
||||
|
||||
/obj/machinery/computer/cloning/proc/findcloner()
|
||||
var/obj/machinery/clonepod/podf = null
|
||||
|
||||
var/obj/machinery/clonepod/podf
|
||||
for(var/direction in GLOB.cardinals)
|
||||
|
||||
podf = locate(/obj/machinery/clonepod, get_step(src, direction))
|
||||
if (!isnull(podf) && podf.is_operational())
|
||||
podf = locate(clonepod_type, get_step(src, direction))
|
||||
if(podf?.is_operational())
|
||||
AttachCloner(podf)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
|
||||
@@ -132,7 +135,7 @@
|
||||
else if(istype(W, /obj/item/multitool))
|
||||
var/obj/item/multitool/P = W
|
||||
|
||||
if(istype(P.buffer, /obj/machinery/clonepod))
|
||||
if(istype(P.buffer, clonepod_type))
|
||||
if(get_area(P.buffer) != get_area(src))
|
||||
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
|
||||
P.buffer = null
|
||||
@@ -157,13 +160,14 @@
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
|
||||
|
||||
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
|
||||
if(!autoprocess)
|
||||
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
|
||||
if(use_records)
|
||||
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
|
||||
if(!autoprocess)
|
||||
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
|
||||
else
|
||||
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
|
||||
else
|
||||
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Autoclone</span>"
|
||||
dat += "<span class='linkOff'>Autoclone</span>"
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
@@ -190,26 +194,29 @@
|
||||
else if(loading)
|
||||
dat += "[scanner_occupant] => Scanning..."
|
||||
else
|
||||
if(scanner_occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = scanner_occupant.ckey
|
||||
if(use_records)
|
||||
if(scanner_occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = scanner_occupant.ckey
|
||||
else
|
||||
scantemp = "Ready to Clone"
|
||||
dat += "[scanner_occupant] => [scantemp]"
|
||||
dat += "</div>"
|
||||
|
||||
if(scanner_occupant)
|
||||
dat += "<a href='byond://?src=[REF(src)];scan=1'>Start Scan</a>"
|
||||
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
dat += "<a href='byond://?src=[REF(src)];scan=1'>[use_records ? "Start Scan" : "Clone"]</a>"
|
||||
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Start Scan</span>"
|
||||
|
||||
// Database
|
||||
dat += "<h3>Database Functions</h3>"
|
||||
if (src.records.len && src.records.len > 0)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>View Records (0)</span><br>"
|
||||
if (src.diskette)
|
||||
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
|
||||
dat += "<span class='linkOff'>[use_records ? "Start Scan" : "Clone"]</span>"
|
||||
if(use_records)
|
||||
// Database
|
||||
dat += "<h3>Database Functions</h3>"
|
||||
if (src.records.len && src.records.len > 0)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>View Records (0)</span><br>"
|
||||
if (src.diskette)
|
||||
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
|
||||
|
||||
|
||||
|
||||
@@ -290,24 +297,19 @@
|
||||
autoprocess = FALSE
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
. = TRUE
|
||||
|
||||
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
|
||||
scantemp = ""
|
||||
|
||||
loading = 1
|
||||
loading = TRUE
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
say("Initiating scan...")
|
||||
var/prev_locked = scanner.locked
|
||||
scanner.locked = TRUE
|
||||
spawn(20)
|
||||
src.scan_occupant(scanner.occupant)
|
||||
|
||||
loading = 0
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
scanner.locked = prev_locked
|
||||
|
||||
addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
|
||||
. = TRUE
|
||||
|
||||
//No locking an open scanner.
|
||||
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
|
||||
@@ -317,8 +319,17 @@
|
||||
else
|
||||
scanner.locked = FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
. = TRUE
|
||||
|
||||
else if(href_list["view_rec"])
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateUsrDialog()
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
. = TRUE
|
||||
|
||||
if(. || !use_records)
|
||||
return
|
||||
if(href_list["view_rec"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
src.active_record = find_record("id", href_list["view_rec"], records)
|
||||
if(active_record)
|
||||
@@ -330,6 +341,7 @@
|
||||
src.menu = 3
|
||||
else
|
||||
src.temp = "Record missing."
|
||||
. = TRUE
|
||||
|
||||
else if (href_list["del_rec"])
|
||||
if ((!src.active_record) || (src.menu < 3))
|
||||
@@ -353,8 +365,9 @@
|
||||
else
|
||||
src.temp = "<font class='bad'>Access Denied.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
. = TRUE
|
||||
|
||||
else if (href_list["disk"]) //Load or eject.
|
||||
else if (href_list["disk"] && use_records) //Load or eject.
|
||||
switch(href_list["disk"])
|
||||
if("load")
|
||||
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
|
||||
@@ -392,10 +405,7 @@
|
||||
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
|
||||
src.temp = "Save successful."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateUsrDialog()
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
. = TRUE
|
||||
|
||||
else if (href_list["clone"])
|
||||
var/datum/data/record/C = find_record("id", href_list["clone"], records)
|
||||
@@ -415,7 +425,7 @@
|
||||
else if(pod.occupant)
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"]))
|
||||
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
|
||||
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
records.Remove(C)
|
||||
@@ -429,53 +439,49 @@
|
||||
else
|
||||
temp = "<font class='bad'>Data corruption.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
. = TRUE
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
else if (href_list["menu"] && use_records)
|
||||
menu = text2num(href_list["menu"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
|
||||
if(!scanner || !L)
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
if(use_records)
|
||||
scan_occupant(L)
|
||||
else
|
||||
clone_occupant(L)
|
||||
|
||||
loading = FALSE
|
||||
src.updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
scanner.locked = prev_locked
|
||||
|
||||
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
var/datum/dna/dna
|
||||
var/datum/bank_account/has_bank_account
|
||||
|
||||
// Do not use unless you know what they are.
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
|
||||
if(ishuman(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
dna = C.has_dna()
|
||||
var/obj/item/card/id/I = C.get_idcard()
|
||||
if(I)
|
||||
has_bank_account = I.registered_account
|
||||
if(isbrain(mob_occupant))
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
dna = B.stored_dna
|
||||
|
||||
if(!istype(dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(mob_occupant.suiciding || mob_occupant.hellbound)
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
if ((!mob_occupant.ckey) || (!mob_occupant.client))
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (find_record("ckey", mob_occupant.ckey, records))
|
||||
scantemp = "<font class='average'>Subject already in database.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(SSeconomy.full_ancap && !has_bank_account)
|
||||
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
if(!can_scan(dna, mob_occupant, FALSE, has_bank_account))
|
||||
return
|
||||
|
||||
var/datum/data/record/R = new()
|
||||
if(dna.species)
|
||||
// We store the instance rather than the path, because some
|
||||
@@ -497,11 +503,17 @@
|
||||
R.fields["features"] = dna.features
|
||||
R.fields["factions"] = mob_occupant.faction
|
||||
R.fields["quirks"] = list()
|
||||
R.fields["bank_account"] = has_bank_account
|
||||
for(var/V in mob_occupant.roundstart_quirks)
|
||||
var/datum/quirk/T = V
|
||||
R.fields["quirks"][T.type] = T.clone_data()
|
||||
|
||||
R.fields["traumas"] = list()
|
||||
if(ishuman(mob_occupant))
|
||||
R.fields["traumas"] = C.get_traumas()
|
||||
if(isbrain(mob_occupant))
|
||||
R.fields["traumas"] = B.get_traumas()
|
||||
|
||||
R.fields["bank_account"] = has_bank_account
|
||||
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
|
||||
R.fields["mind"] = "[REF(mob_occupant.mind)]"
|
||||
|
||||
@@ -520,3 +532,78 @@
|
||||
board.records = records
|
||||
scantemp = "Subject successfully scanned."
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
//Used by the experimental cloning computer.
|
||||
/obj/machinery/computer/cloning/proc/clone_occupant(occupant)
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
var/datum/dna/dna
|
||||
if(ishuman(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
dna = C.has_dna()
|
||||
if(isbrain(mob_occupant))
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
dna = B.stored_dna
|
||||
|
||||
if(!can_scan(dna, mob_occupant, TRUE))
|
||||
return
|
||||
|
||||
var/clone_species
|
||||
if(dna.species)
|
||||
clone_species = dna.species
|
||||
else
|
||||
var/datum/species/rando_race = pick(GLOB.roundstart_races)
|
||||
clone_species = rando_race.type
|
||||
|
||||
var/obj/machinery/clonepod/pod = GetAvailablePod()
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!LAZYLEN(pods))
|
||||
temp = "<font class='bad'>No Clonepods detected.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!pod)
|
||||
temp = "<font class='bad'>No Clonepods available.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.occupant)
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
|
||||
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
|
||||
if(!istype(dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(!experimental)
|
||||
if(mob_occupant.suiciding || mob_occupant.hellbound)
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
if (!experimental)
|
||||
if(!mob_occupant.ckey || !mob_occupant.client)
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if (find_record("ckey", mob_occupant.ckey, records))
|
||||
scantemp = "<font class='average'>Subject already in database.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if(SSeconomy.full_ancap && !account)
|
||||
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
|
||||
/obj/machinery/computer/cloning/prototype
|
||||
name = "prototype cloning console"
|
||||
desc = "Used to operate an experimental cloner."
|
||||
icon_screen = "dna"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/cloning/prototype
|
||||
clonepod_type = /obj/machinery/clonepod/experimental
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
investigate_log("Cryogenics machine closed with occupant [key_name(occupant)] by user [key_name(user)].", INVESTIGATE_CRYOGENICS)
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
if(mob_occupant.client)//if they're logged in
|
||||
@@ -251,12 +252,15 @@
|
||||
icon_state = "cryopod"
|
||||
|
||||
/obj/machinery/cryopod/open_machine()
|
||||
if(occupant)
|
||||
investigate_log("Cryogenics machine opened with occupant [key_name(occupant)] inside.", INVESTIGATE_CRYOGENICS)
|
||||
..()
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/container_resist(mob/living/user)
|
||||
investigate_log("Cryogenics machine container resisted by [key_name(user)] with occupant [key_name(occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
@@ -304,6 +308,8 @@
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
|
||||
//Handle Borg stuff first
|
||||
if(iscyborg(mob_occupant))
|
||||
|
||||
@@ -70,14 +70,13 @@
|
||||
if(W.amount < 5)
|
||||
to_chat(user, "<span class='warning'>You need at least five wooden planks to make a wall!</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start adding [I] to [src]...</span>")
|
||||
if(do_after(user, 50, target=src))
|
||||
W.use(5)
|
||||
var/turf/T = get_turf(src)
|
||||
T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal)
|
||||
qdel(src)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding [I] to [src]...</span>")
|
||||
if(do_after(user, 50, target=src))
|
||||
W.use(5)
|
||||
var/turf/T = get_turf(src)
|
||||
T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal)
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -170,7 +169,8 @@
|
||||
|
||||
to_chat(user, "[src] is now in [mode] mode.")
|
||||
|
||||
/obj/item/grenade/barrier/prime()
|
||||
/obj/item/grenade/barrier/prime(mob/living/lanced_by)
|
||||
. = ..()
|
||||
new /obj/structure/barricade/security(get_turf(src.loc))
|
||||
switch(mode)
|
||||
if(VERTICAL)
|
||||
|
||||
@@ -413,8 +413,8 @@
|
||||
// shock user with probability prb (if all connections & power are working)
|
||||
// returns TRUE if shocked, FALSE otherwise
|
||||
// The preceding comment was borrowed from the grille's shock script
|
||||
/obj/machinery/door/airlock/proc/shock(mob/user, prb)
|
||||
if(!hasPower()) // unpowered, no shock
|
||||
/obj/machinery/door/airlock/proc/shock(mob/living/user, prb)
|
||||
if(!istype(user) || !hasPower()) // unpowered, no shock
|
||||
return FALSE
|
||||
if(shockCooldown > world.time)
|
||||
return FALSE //Already shocked someone recently?
|
||||
@@ -577,11 +577,17 @@
|
||||
cut_overlays()
|
||||
add_overlay(frame_overlay)
|
||||
add_overlay(filling_overlay)
|
||||
add_overlay(lights_overlay)
|
||||
if(lights_overlay)
|
||||
add_overlay(lights_overlay)
|
||||
var/mutable_appearance/lights_vis = mutable_appearance(lights_overlay.icon, lights_overlay.icon_state)
|
||||
add_overlay(lights_vis)
|
||||
add_overlay(panel_overlay)
|
||||
add_overlay(weld_overlay)
|
||||
add_overlay(sparks_overlay)
|
||||
add_overlay(damag_overlay)
|
||||
if(damag_overlay)
|
||||
add_overlay(damag_overlay)
|
||||
var/mutable_appearance/damage_vis = mutable_appearance(damag_overlay.icon, damag_overlay.icon_state)
|
||||
add_overlay(damage_vis)
|
||||
add_overlay(note_overlay)
|
||||
check_unres()
|
||||
|
||||
@@ -1052,11 +1058,11 @@
|
||||
to_chat(user, "<span class='warning'>The airlock's bolts prevent it from being forced!</span>")
|
||||
else if( !welded && !operating)
|
||||
if(!beingcrowbarred) //being fireaxe'd
|
||||
var/obj/item/twohanded/fireaxe/F = I
|
||||
if(F.wielded)
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to be wielding the fire axe to do that!</span>")
|
||||
var/obj/item/fireaxe/axe = I
|
||||
if(!axe.wielded)
|
||||
to_chat(user, "<span class='warning'>You need to be wielding \the [axe] to do that!</span>")
|
||||
return
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
else
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/electronics/airlock
|
||||
name = "airlock electronics"
|
||||
req_access = list(ACCESS_MAINT_TUNNELS)
|
||||
custom_price = 50
|
||||
custom_price = PRICE_CHEAP
|
||||
|
||||
var/list/accesses = list()
|
||||
var/one_access = 0
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
plane = ABOVE_WALL_PLANE
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id // id of linked machinery/lockers
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
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
|
||||
ricochet_chance_mod = 0.8
|
||||
|
||||
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
|
||||
|
||||
var/secondsElectrified = 0
|
||||
var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
|
||||
var/shockedby
|
||||
var/visible = TRUE
|
||||
var/visible = TRUE // To explain: Whether the door can block line of sight when closed or not.
|
||||
var/operating = FALSE
|
||||
var/glass = FALSE
|
||||
var/welded = FALSE
|
||||
@@ -207,7 +208,7 @@
|
||||
return max_moles - min_moles > 20
|
||||
|
||||
/obj/machinery/door/attackby(obj/item/I, mob/user, params)
|
||||
if(user.a_intent != INTENT_HARM && (I.tool_behaviour == TOOL_CROWBAR || istype(I, /obj/item/twohanded/fireaxe)))
|
||||
if(user.a_intent != INTENT_HARM && (I.tool_behaviour == TOOL_CROWBAR || istype(I, /obj/item/fireaxe)))
|
||||
try_to_crowbar(I, user)
|
||||
return 1
|
||||
else if(I.tool_behaviour == TOOL_WELDER)
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
|
||||
/obj/item/electronics/firelock
|
||||
name = "firelock circuitry"
|
||||
custom_price = 50
|
||||
custom_price = PRICE_CHEAP
|
||||
desc = "A circuit board used in construction of firelocks."
|
||||
icon_state = "mainboard"
|
||||
|
||||
|
||||
@@ -53,7 +53,9 @@
|
||||
if("opening")
|
||||
rad_insulation = 1
|
||||
if("closing")
|
||||
rad_insulation = 0.2
|
||||
rad_insulation = -0.5
|
||||
|
||||
// A 3x3 N2 SM setup won't irradiate you if you're behind the shutter at -0.9 insulation. If it starts to delam, it'll start irradiating you slowly. Keep the value between -0.1 to -0.9
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/window
|
||||
name = "windowed shutters"
|
||||
|
||||
@@ -54,6 +54,15 @@
|
||||
else
|
||||
icon_state = "[src.base_state]open"
|
||||
|
||||
/obj/machinery/door/window/update_atom_colour()
|
||||
if((color && (color_hex2num(color) < 255)))
|
||||
visible = TRUE
|
||||
if(density)
|
||||
set_opacity(TRUE)
|
||||
else
|
||||
visible = FALSE
|
||||
set_opacity(density && visible)
|
||||
|
||||
/obj/machinery/door/window/proc/open_and_close()
|
||||
open()
|
||||
if(src.check_access(null))
|
||||
@@ -143,16 +152,18 @@
|
||||
do_animate("opening")
|
||||
playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
|
||||
src.icon_state ="[src.base_state]open"
|
||||
sleep(10)
|
||||
addtimer(CALLBACK(src, .proc/finish_opening), 10)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/window/proc/finish_opening()
|
||||
operating = FALSE
|
||||
density = FALSE
|
||||
// src.sd_set_opacity(0) //TODO: why is this here? Opaque windoors? ~Carn
|
||||
if(visible)
|
||||
set_opacity(FALSE)
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
|
||||
if(operating == 1) //emag again
|
||||
operating = FALSE
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/window/close(forced=0)
|
||||
if (src.operating)
|
||||
@@ -171,10 +182,13 @@
|
||||
density = TRUE
|
||||
air_update_turf(1)
|
||||
update_freelook_sight()
|
||||
sleep(10)
|
||||
addtimer(CALLBACK(src, .proc/finish_closing), 10)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/door/window/proc/finish_closing()
|
||||
if(visible)
|
||||
set_opacity(TRUE)
|
||||
operating = FALSE
|
||||
return 1
|
||||
|
||||
/obj/machinery/door/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
switch(damage_type)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
plane = ABOVE_WALL_PLANE
|
||||
name = "vent controller"
|
||||
density = FALSE
|
||||
|
||||
|
||||
@@ -1,298 +0,0 @@
|
||||
//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
|
||||
/obj/machinery/clonepod/experimental
|
||||
name = "experimental cloning pod"
|
||||
desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
|
||||
icon = 'icons/obj/machines/cloning.dmi'
|
||||
icon_state = "pod_0"
|
||||
req_access = null
|
||||
circuit = /obj/item/circuitboard/machine/clonepod/experimental
|
||||
internal_radio = FALSE
|
||||
|
||||
//Start growing a human clone in the pod!
|
||||
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
|
||||
if(panel_open)
|
||||
return FALSE
|
||||
if(mess || attempting)
|
||||
return FALSE
|
||||
|
||||
attempting = TRUE //One at a time!!
|
||||
countdown.start()
|
||||
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
||||
|
||||
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
|
||||
|
||||
if(efficiency > 2)
|
||||
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
|
||||
H.dna.remove_mutation_group(unclean_mutations)
|
||||
if(efficiency > 5 && prob(20))
|
||||
H.easy_randmut(POSITIVE)
|
||||
if(efficiency < 3 && prob(50))
|
||||
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
if(ismob(M))
|
||||
H = M
|
||||
|
||||
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
|
||||
occupant = H
|
||||
|
||||
if(!clonename) //to prevent null names
|
||||
clonename = "clone ([rand(1,999)])"
|
||||
H.real_name = clonename
|
||||
|
||||
icon_state = "pod_1"
|
||||
//Get the clone body ready
|
||||
maim_clone(H)
|
||||
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
|
||||
H.Unconscious(80)
|
||||
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/C = pick(candidates)
|
||||
H.key = C.key
|
||||
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
|
||||
|
||||
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
||||
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
|
||||
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
|
||||
|
||||
if(H)
|
||||
H.faction |= factions
|
||||
|
||||
H.set_cloned_appearance()
|
||||
|
||||
H.suiciding = FALSE
|
||||
attempting = FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
|
||||
/obj/machinery/computer/prototype_cloning
|
||||
name = "prototype cloning console"
|
||||
desc = "Used to operate an experimental cloner."
|
||||
icon_screen = "dna"
|
||||
icon_keyboard = "med_key"
|
||||
circuit = /obj/item/circuitboard/computer/prototype_cloning
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/list/pods //Linked experimental cloning pods
|
||||
var/temp = "Inactive"
|
||||
var/scantemp = "Ready to Scan"
|
||||
var/loading = FALSE // Nice loading text
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/Initialize()
|
||||
. = ..()
|
||||
updatemodules(TRUE)
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/Destroy()
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
DetachCloner(P)
|
||||
pods = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null)
|
||||
if(pods)
|
||||
for(var/P in pods)
|
||||
var/obj/machinery/clonepod/experimental/pod = P
|
||||
if(pod.is_operational() && !(pod.occupant || pod.mess))
|
||||
return pod
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner)
|
||||
scanner = findscanner()
|
||||
if(findfirstcloner && !LAZYLEN(pods))
|
||||
findcloner()
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/findscanner()
|
||||
var/obj/machinery/dna_scannernew/scannerf = null
|
||||
|
||||
// Loop through every direction
|
||||
for(var/direction in GLOB.cardinals)
|
||||
// Try to find a scanner in that direction
|
||||
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
|
||||
// If found and operational, return the scanner
|
||||
if (!isnull(scannerf) && scannerf.is_operational())
|
||||
return scannerf
|
||||
|
||||
// If no scanner was found, it will return null
|
||||
return null
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/findcloner()
|
||||
var/obj/machinery/clonepod/experimental/podf = null
|
||||
for(var/direction in GLOB.cardinals)
|
||||
podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction))
|
||||
if (!isnull(podf) && podf.is_operational())
|
||||
AttachCloner(podf)
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod)
|
||||
if(!pod.connected)
|
||||
pod.connected = src
|
||||
LAZYADD(pods, pod)
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod)
|
||||
pod.connected = null
|
||||
LAZYREMOVE(pods, pod)
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
var/obj/item/multitool/P = W
|
||||
|
||||
if(istype(P.buffer, /obj/machinery/clonepod/experimental))
|
||||
if(get_area(P.buffer) != get_area(src))
|
||||
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
|
||||
P.buffer = null
|
||||
return
|
||||
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
|
||||
var/obj/machinery/clonepod/experimental/pod = P.buffer
|
||||
if(pod.connected)
|
||||
pod.connected.DetachCloner(pod)
|
||||
AttachCloner(pod)
|
||||
else
|
||||
P.buffer = src
|
||||
to_chat(user, "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/interact(mob/user)
|
||||
user.set_machine(src)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
updatemodules(TRUE)
|
||||
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
|
||||
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
if (isnull(src.scanner) || !LAZYLEN(pods))
|
||||
dat += "<h3>Modules</h3>"
|
||||
//dat += "<a href='byond://?src=[REF(src)];relmodules=1'>Reload Modules</a>"
|
||||
if (isnull(src.scanner))
|
||||
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
|
||||
if (!LAZYLEN(pods))
|
||||
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
|
||||
|
||||
// Scan-n-Clone
|
||||
if (!isnull(src.scanner))
|
||||
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
|
||||
|
||||
dat += "<h3>Cloning</h3>"
|
||||
|
||||
dat += "<div class='statusDisplay'>"
|
||||
if(!scanner_occupant)
|
||||
dat += "Scanner Unoccupied"
|
||||
else if(loading)
|
||||
dat += "[scanner_occupant] => Scanning..."
|
||||
else
|
||||
scantemp = "Ready to Clone"
|
||||
dat += "[scanner_occupant] => [scantemp]"
|
||||
dat += "</div>"
|
||||
|
||||
if(scanner_occupant)
|
||||
dat += "<a href='byond://?src=[REF(src)];clone=1'>Clone</a>"
|
||||
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Clone</span>"
|
||||
|
||||
var/datum/browser/popup = new(user, "cloning", "Prototype Cloning System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(loading)
|
||||
return
|
||||
|
||||
else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational())
|
||||
scantemp = ""
|
||||
|
||||
loading = TRUE
|
||||
updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
say("Initiating scan...")
|
||||
|
||||
spawn(20)
|
||||
clone_occupant(scanner.occupant)
|
||||
loading = FALSE
|
||||
updateUsrDialog()
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
//No locking an open scanner.
|
||||
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
|
||||
if ((!scanner.locked) && (scanner.occupant))
|
||||
scanner.locked = TRUE
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
scanner.locked = FALSE
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
else if (href_list["refresh"])
|
||||
updateUsrDialog()
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant)
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
var/datum/dna/dna
|
||||
if(ishuman(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
dna = C.has_dna()
|
||||
if(isbrain(mob_occupant))
|
||||
var/mob/living/brain/B = mob_occupant
|
||||
dna = B.stored_dna
|
||||
|
||||
if(!istype(dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
|
||||
var/clone_species
|
||||
if(dna.species)
|
||||
clone_species = dna.species
|
||||
else
|
||||
var/datum/species/rando_race = pick(GLOB.roundstart_races)
|
||||
clone_species = rando_race.type
|
||||
|
||||
var/obj/machinery/clonepod/pod = GetAvailablePod()
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!LAZYLEN(pods))
|
||||
temp = "<font class='bad'>No Clonepods detected.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(!pod)
|
||||
temp = "<font class='bad'>No Clonepods available.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else if(pod.occupant)
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
|
||||
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/obj/item/electronics/firealarm
|
||||
name = "fire alarm electronics"
|
||||
custom_price = 50
|
||||
custom_price = PRICE_CHEAP
|
||||
desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius."
|
||||
|
||||
/obj/item/wallframe/firealarm
|
||||
@@ -17,6 +17,7 @@
|
||||
desc = "<i>\"Pull this in case of emergency\"</i>. Thus, keep pulling it forever."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire0"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
max_integrity = 250
|
||||
integrity_failure = 0.4
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
desc = "A wall-mounted flashbulb device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash1"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
max_integrity = 250
|
||||
integrity_failure = 0.4
|
||||
light_color = LIGHT_COLOR_WHITE
|
||||
@@ -20,6 +21,7 @@
|
||||
name = "portable flasher"
|
||||
desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements."
|
||||
icon_state = "pflash1-p"
|
||||
plane = GAME_PLANE
|
||||
strength = 80
|
||||
anchored = FALSE
|
||||
base_state = "pflash"
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
name = "auto-autopsy"
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/harvester/setDir(newdir)
|
||||
. = ..()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/harvester/RefreshParts()
|
||||
interval = 0
|
||||
|
||||
@@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
plane = FLOOR_PLANE
|
||||
plane = ABOVE_WALL_PLANE
|
||||
flags_1 = HEAR_1
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
/obj/machinery/hypnochair
|
||||
name = "enhanced interrogation chamber"
|
||||
desc = "A device used to perform \"enhanced interrogation\" through invasive mental conditioning."
|
||||
icon = 'icons/obj/machines/implantchair.dmi'
|
||||
icon_state = "hypnochair"
|
||||
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()
|
||||
. = ..()
|
||||
open_machine()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/hypnochair/attackby(obj/item/I, mob/user, params)
|
||||
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)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "hypnochair", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/hypnochair/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? TRUE : FALSE
|
||||
data["open"] = state_open
|
||||
data["interrogating"] = interrogating
|
||||
|
||||
data["occupant"] = list()
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
data["occupant"]["name"] = mob_occupant.name
|
||||
data["occupant"]["stat"] = mob_occupant.stat
|
||||
|
||||
data["trigger"] = trigger_phrase
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/hypnochair/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
if(!interrogating)
|
||||
open_machine()
|
||||
. = TRUE
|
||||
if("set_phrase")
|
||||
set_phrase(params["phrase"])
|
||||
. = TRUE
|
||||
if("interrogate")
|
||||
if(!interrogating)
|
||||
interrogate()
|
||||
else
|
||||
interrupt_interrogation()
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/hypnochair/proc/set_phrase(phrase)
|
||||
trigger_phrase = phrase
|
||||
|
||||
/obj/machinery/hypnochair/proc/interrogate()
|
||||
if(!trigger_phrase)
|
||||
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE)
|
||||
return
|
||||
var/mob/living/carbon/C = occupant
|
||||
if(!istype(C))
|
||||
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE)
|
||||
return
|
||||
victim = C
|
||||
if(!(C.get_eye_protection() > 0))
|
||||
to_chat(C, "<span class='warning'>Strobing coloured lights assault you relentlessly! You're losing your ability to think straight!</span>")
|
||||
C.become_blind("hypnochair")
|
||||
ADD_TRAIT(C, TRAIT_DEAF, "hypnochair")
|
||||
interrogating = TRUE
|
||||
START_PROCESSING(SSobj, src)
|
||||
start_time = world.time
|
||||
update_icon()
|
||||
timerid = addtimer(CALLBACK(src, .proc/finish_interrogation), 450, TIMER_STOPPABLE)
|
||||
|
||||
/obj/machinery/hypnochair/process()
|
||||
var/mob/living/carbon/C = occupant
|
||||
if(!istype(C) || C != victim)
|
||||
interrupt_interrogation()
|
||||
return
|
||||
if(prob(10) && !(C.get_eye_protection() > 0))
|
||||
to_chat(C, "<span class='hypnophrase'>[pick(\
|
||||
"...blue... red... green... blue, red, green, blueredgreen<span class='small'>blueredgreen</span>",\
|
||||
"...pretty colors...",\
|
||||
"...you keep hearing words, but you can't seem to understand them...",\
|
||||
"...so peaceful...",\
|
||||
"...an annoying buzz in your ears..."\
|
||||
)]</span>")
|
||||
|
||||
/obj/machinery/hypnochair/proc/finish_interrogation()
|
||||
interrogating = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
var/temp_trigger = trigger_phrase
|
||||
trigger_phrase = "" //Erase evidence, in case the subject is able to look at the panel afterwards
|
||||
audible_message("<span class='notice'>[src] pings!</span>")
|
||||
playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
|
||||
|
||||
if(QDELETED(victim) || victim != occupant)
|
||||
victim = null
|
||||
return
|
||||
victim.cure_blind("hypnochair")
|
||||
REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair")
|
||||
if(!(victim.get_eye_protection() > 0))
|
||||
victim.cure_trauma_type(/datum/brain_trauma/severe/hypnotic_trigger, TRAUMA_RESILIENCE_SURGERY)
|
||||
if(prob(90))
|
||||
victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_trigger(temp_trigger), TRAUMA_RESILIENCE_SURGERY)
|
||||
else
|
||||
victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_stupor(), TRAUMA_RESILIENCE_SURGERY)
|
||||
victim = null
|
||||
|
||||
/obj/machinery/hypnochair/proc/interrupt_interrogation()
|
||||
deltimer(timerid)
|
||||
interrogating = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
if(QDELETED(victim))
|
||||
victim = null
|
||||
return
|
||||
victim.cure_blind("hypnochair")
|
||||
REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair")
|
||||
if(!(victim.get_eye_protection() > 0))
|
||||
var/time_diff = world.time - start_time
|
||||
switch(time_diff)
|
||||
if(0 to 100)
|
||||
victim.confused += 10
|
||||
victim.Dizzy(100)
|
||||
victim.blur_eyes(5)
|
||||
if(101 to 200)
|
||||
victim.confused += 15
|
||||
victim.Dizzy(200)
|
||||
victim.blur_eyes(10)
|
||||
if(prob(25))
|
||||
victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE)
|
||||
if(201 to INFINITY)
|
||||
victim.confused += 20
|
||||
victim.Dizzy(300)
|
||||
victim.blur_eyes(15)
|
||||
if(prob(65))
|
||||
victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE)
|
||||
victim = null
|
||||
|
||||
/obj/machinery/hypnochair/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(state_open)
|
||||
icon_state += "_open"
|
||||
if(occupant)
|
||||
if(interrogating)
|
||||
icon_state += "_active"
|
||||
else
|
||||
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>")
|
||||
if(do_after(user,(600), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/hypnochair/relaymove(mob/user)
|
||||
if(message_cooldown <= world.time)
|
||||
message_cooldown = world.time + 50
|
||||
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
|
||||
|
||||
/obj/machinery/hypnochair/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(!(L.mobility_flags & MOBILITY_STAND))
|
||||
return
|
||||
close_machine(target)
|
||||
@@ -13,7 +13,8 @@
|
||||
var/obj/item/reagent_containers/beaker
|
||||
var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood,
|
||||
/obj/item/reagent_containers/food,
|
||||
/obj/item/reagent_containers/glass))
|
||||
/obj/item/reagent_containers/glass,
|
||||
/obj/item/reagent_containers/chem_pack))
|
||||
|
||||
/obj/machinery/iv_drip/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
desc = "Make dark."
|
||||
var/on = TRUE
|
||||
var/area/area = null
|
||||
|
||||
@@ -679,7 +679,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/energy
|
||||
icon_state = "standard_stun"
|
||||
@@ -788,7 +788,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/assess_perp(mob/living/carbon/human/perp)
|
||||
return 0
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret_cover/attacked_by(obj/item/I, mob/user)
|
||||
parent_turret.attacked_by(I, user)
|
||||
/obj/machinery/porta_turret_cover/attacked_by(obj/item/I, mob/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
return parent_turret.attacked_by(I, user)
|
||||
|
||||
/obj/machinery/porta_turret_cover/attack_alien(mob/living/carbon/alien/humanoid/user)
|
||||
parent_turret.attack_alien(user)
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/ammo_box/magazine/recharge,
|
||||
/obj/item/modular_computer,
|
||||
/obj/item/twohanded/electrostaff,
|
||||
/obj/item/ammo_casing/mws_batt,
|
||||
/obj/item/ammo_box/magazine/mws_mag,
|
||||
/obj/item/electrostaff,
|
||||
/obj/item/gun/ballistic/automatic/magrifle))
|
||||
|
||||
/obj/machinery/recharger/RefreshParts()
|
||||
@@ -143,6 +145,29 @@
|
||||
using_power = TRUE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(charging, /obj/item/ammo_casing/mws_batt))
|
||||
var/obj/item/ammo_casing/mws_batt/R = charging
|
||||
if(R.cell.charge < R.cell.maxcharge)
|
||||
R.cell.give(R.cell.chargerate * recharge_coeff)
|
||||
use_power(250 * recharge_coeff)
|
||||
using_power = 1
|
||||
if(R.BB == null)
|
||||
R.chargeshot()
|
||||
update_icon(using_power)
|
||||
|
||||
if(istype(charging, /obj/item/ammo_box/magazine/mws_mag))
|
||||
var/obj/item/ammo_box/magazine/mws_mag/R = charging
|
||||
for(var/B in R.stored_ammo)
|
||||
var/obj/item/ammo_casing/mws_batt/batt = B
|
||||
if(batt.cell.charge < batt.cell.maxcharge)
|
||||
batt.cell.give(batt.cell.chargerate * recharge_coeff)
|
||||
use_power(250 * recharge_coeff)
|
||||
using_power = 1
|
||||
if(batt.BB == null)
|
||||
batt.chargeshot()
|
||||
update_icon(using_power)
|
||||
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
|
||||
@@ -100,44 +100,61 @@
|
||||
eat(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0)
|
||||
if(stat & (BROKEN|NOPOWER) || safety_mode)
|
||||
return
|
||||
|
||||
var/list/to_eat
|
||||
|
||||
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
|
||||
to_eat = list(AM0)
|
||||
|
||||
var/items_recycled = 0
|
||||
var/buzz = FALSE
|
||||
for(var/i in to_eat)
|
||||
var/atom/movable/AM = i
|
||||
if(QDELETED(AM))
|
||||
continue
|
||||
var/obj/item/bodypart/head/as_head = AM
|
||||
var/obj/item/mmi/as_mmi = AM
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay)
|
||||
if(brain_holder)
|
||||
emergency_stop(AM)
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
crush_living(AM)
|
||||
if(obj_flags & EMAGGED)
|
||||
continue
|
||||
else
|
||||
emergency_stop(AM)
|
||||
return
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
to_eat += crush_living(AM)
|
||||
else
|
||||
emergency_stop(AM)
|
||||
return
|
||||
else if(isitem(AM))
|
||||
var/obj/O = AM
|
||||
if(O.resistance_flags & INDESTRUCTIBLE)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
buzz = TRUE
|
||||
O.forceMove(loc)
|
||||
else
|
||||
recycle_item(AM)
|
||||
to_eat += recycle_item(AM)
|
||||
items_recycled++
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
buzz = TRUE
|
||||
AM.forceMove(loc)
|
||||
|
||||
if(items_recycled && sound)
|
||||
if(items_recycled)
|
||||
playsound(src, item_recycle_sound, 50, 1)
|
||||
if(buzz)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
|
||||
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
|
||||
|
||||
. = list()
|
||||
for(var/A in I)
|
||||
var/atom/movable/AM = A
|
||||
AM.forceMove(loc)
|
||||
if(AM.loc == loc)
|
||||
. += AM
|
||||
|
||||
I.forceMove(loc)
|
||||
var/obj/item/grown/log/L = I
|
||||
if(istype(L))
|
||||
@@ -172,6 +189,7 @@
|
||||
|
||||
/obj/machinery/recycler/proc/crush_living(mob/living/L)
|
||||
|
||||
. = list()
|
||||
L.forceMove(loc)
|
||||
|
||||
if(issilicon(L))
|
||||
@@ -193,7 +211,7 @@
|
||||
if(eat_victim_items)
|
||||
for(var/obj/item/I in L.get_equipped_items(TRUE))
|
||||
if(L.dropItemToGround(I))
|
||||
eat(I, sound=FALSE)
|
||||
. += I
|
||||
|
||||
// Instantly lie down, also go unconscious from the pain, before you die.
|
||||
L.Unconscious(100)
|
||||
|
||||
@@ -9,13 +9,14 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
#define NO_NEW_MESSAGE 0
|
||||
#define NORMAL_MESSAGE_PRIORITY 1
|
||||
#define HIGH_MESSAGE_PRIORITY 2
|
||||
#define EXTREME_MESSAGE_PRIORITY 3 // not implemented, will probably require some hacking... everything needs to have a hidden feature in this game.
|
||||
#define EXTREME_MESSAGE_PRIORITY 3 // is implimented, does require hacking. everything needs to have a hidden feature in this game.
|
||||
|
||||
/obj/machinery/requests_console
|
||||
name = "requests console"
|
||||
desc = "A console intended to send requests to different departments on the station."
|
||||
icon = 'icons/obj/terminals.dmi'
|
||||
icon_state = "req_comp0"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department
|
||||
var/list/messages = list() //List of all messages
|
||||
var/departmentType = 0
|
||||
@@ -47,9 +48,9 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
var/announceAuth = FALSE //Will be set to 1 when you authenticate yourself for announcements
|
||||
var/msgVerified = "" //Will contain the name of the person who verified it
|
||||
var/msgStamped = "" //If a message is stamped, this will contain the stamp name
|
||||
var/message = "";
|
||||
var/dpt = ""; //the department which will be receiving the message
|
||||
var/priority = -1 ; //Priority of the message being sent
|
||||
var/message = ""
|
||||
var/dpt = "" //the department which will be receiving the message
|
||||
var/priority = NORMAL_MESSAGE_PRIORITY //Priority of the message being sent. why is the default -1??
|
||||
var/obj/item/radio/Radio
|
||||
var/emergency //If an emergency has been called by this device. Acts as both a cooldown and lets the responder know where it the emergency was triggered from
|
||||
var/receive_ore_updates = FALSE //If ore redemption machines will send an update when it receives new ores.
|
||||
@@ -61,16 +62,17 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/requests_console/update_icon_state()
|
||||
if(stat & NOPOWER)
|
||||
if(CHECK_BITFIELD(stat, NOPOWER))
|
||||
set_light(0)
|
||||
else
|
||||
set_light(1.4,0.7,"#34D352")//green light
|
||||
set_light(1.4, 0.7, "#34D352")//green light
|
||||
|
||||
if(open)
|
||||
if(!hackState)
|
||||
icon_state="req_comp_open"
|
||||
else
|
||||
icon_state="req_comp_rewired"
|
||||
else if(stat & NOPOWER)
|
||||
else if(CHECK_BITFIELD(stat, NOPOWER))
|
||||
if(icon_state != "req_comp_off")
|
||||
icon_state = "req_comp_off"
|
||||
else
|
||||
@@ -121,7 +123,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
GLOB.req_console_information += department
|
||||
|
||||
Radio = new /obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
Radio.listening = FALSE
|
||||
|
||||
/obj/machinery/requests_console/Destroy()
|
||||
QDEL_NULL(Radio)
|
||||
@@ -130,164 +132,173 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
|
||||
/obj/machinery/requests_console/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(open) //no.
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
if(!open)
|
||||
switch(screen)
|
||||
if(1) //req. assistance
|
||||
dat += "Which department do you need assistance from?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_assistance)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
switch(screen)
|
||||
if(1) //req. assistance
|
||||
dat += "Which department do you need assistance from?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_assistance)
|
||||
if(dpt == department)
|
||||
continue
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><A href='?src=[REF(src)];setScreen=0'><< Back</A><br>"
|
||||
|
||||
if(2) //req. supplies
|
||||
dat += "Which department do you need supplies from?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_supplies)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
if(2) //req. supplies
|
||||
dat += "Which department do you need supplies from?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_supplies)
|
||||
if(dpt == department)
|
||||
continue
|
||||
|
||||
if(3) //relay information
|
||||
dat += "Which department would you like to send information to?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_information)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><A href='?src=[REF(src)];setScreen=0'><< Back</A><br>"
|
||||
|
||||
if(6) //sent successfully
|
||||
dat += "<span class='good'>Message sent.</span><BR><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=0'>Continue</A><BR>"
|
||||
if(3) //relay information
|
||||
dat += "Which department would you like to send information to?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_information)
|
||||
if(dpt == department)
|
||||
continue
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back</a><br>"
|
||||
|
||||
if(7) //unsuccessful; not sent
|
||||
dat += "<span class='bad'>An error occurred.</span><BR><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=0'>Continue</A><BR>"
|
||||
if(6) //sent successfully
|
||||
dat += "<span class='good'>Message sent.</span><br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'>Continue</a><br>"
|
||||
|
||||
if(8) //view messages
|
||||
for (var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if (Console.department == department)
|
||||
Console.newmessagepriority = NO_NEW_MESSAGE
|
||||
Console.update_icon()
|
||||
if(7) //unsuccessful; not sent
|
||||
dat += "<span class='bad'>An error occurred.</span><br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'>Continue</a><br>"
|
||||
|
||||
newmessagepriority = NO_NEW_MESSAGE
|
||||
update_icon()
|
||||
var/messageComposite = ""
|
||||
for(var/msg in messages) // This puts more recent messages at the *top*, where they belong.
|
||||
messageComposite = "<div class='block'>[msg]</div>" + messageComposite
|
||||
dat += messageComposite
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back to Main Menu</A><BR>"
|
||||
if(8) //view messages
|
||||
for(var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if(Console.department == department)
|
||||
Console.newmessagepriority = NO_NEW_MESSAGE
|
||||
Console.update_icon()
|
||||
|
||||
if(9) //authentication before sending
|
||||
dat += "<B>Message Authentication</B><BR><BR>"
|
||||
dat += "<b>Message for [dpt]: </b>[message]<BR><BR>"
|
||||
dat += "<div class='notice'>You may authenticate your message now by scanning your ID or your stamp</div><BR>"
|
||||
dat += "<b>Validated by:</b> [msgVerified ? msgVerified : "<i>Not Validated</i>"]<br>"
|
||||
dat += "<b>Stamped by:</b> [msgStamped ? msgStamped : "<i>Not Stamped</i>"]<br><br>"
|
||||
dat += "<A href='?src=[REF(src)];department=[dpt]'>Send Message</A><BR>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Discard Message</A><BR>"
|
||||
newmessagepriority = NO_NEW_MESSAGE
|
||||
update_icon()
|
||||
var/messageComposite = ""
|
||||
for(var/msg in messages) // This puts more recent messages at the *top*, where they belong.
|
||||
messageComposite = "<div class='block'>[msg]</div>" + messageComposite
|
||||
dat += messageComposite
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back to Main Menu</a><br>"
|
||||
|
||||
if(10) //send announcement
|
||||
dat += "<h3>Station-wide Announcement</h3>"
|
||||
if(announceAuth)
|
||||
dat += "<div class='notice'>Authentication accepted</div><BR>"
|
||||
else
|
||||
dat += "<div class='notice'>Swipe your card to authenticate yourself</div><BR>"
|
||||
dat += "<b>Message: </b>[message ? message : "<i>No Message</i>"]<BR>"
|
||||
dat += "<A href='?src=[REF(src)];writeAnnouncement=1'>[message ? "Edit" : "Write"] Message</A><BR><BR>"
|
||||
if ((announceAuth || IsAdminGhost(user)) && message)
|
||||
dat += "<A href='?src=[REF(src)];sendAnnouncement=1'>Announce Message</A><BR>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Announce Message</span><BR>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
if(9) //authentication before sending
|
||||
dat += "<b>Message Authentication</b> <br><br>"
|
||||
dat += "<b>Message for [dpt]:</b> [message] <br><br>"
|
||||
dat += "<div class='notice'>You may authenticate your message now by scanning your ID or your stamp</div> <br>"
|
||||
|
||||
dat += "<b>Validated by:</b> [msgVerified ? "<span class='good'><b>[msgVerified]</b></span>" : "<i>Not Validated</i>"] <br>"
|
||||
dat += "<b>Stamped by:</b> [msgStamped ? "<span class='boldnotice'>[msgStamped]</span>" : "<i>Not Stamped</i>"] <br><br>"
|
||||
|
||||
dat += "<a href='?src=[REF(src)];department=[dpt]'>Send Message</a> <br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'><< Discard Message</a> <br>"
|
||||
|
||||
else //main menu
|
||||
screen = 0
|
||||
announceAuth = FALSE
|
||||
if (newmessagepriority == NORMAL_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new messages</div><BR>"
|
||||
if (newmessagepriority == HIGH_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>PRIORITY</b> messages</div><BR>"
|
||||
if (newmessagepriority == EXTREME_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>EXTREME PRIORITY</b> messages</div><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=8'>View Messages</A><BR><BR>"
|
||||
if(10) //send announcement
|
||||
dat += "<h3>Station-wide Announcement</h3>"
|
||||
if(announceAuth)
|
||||
dat += "<div class='notice'>Authentication accepted</div><br>"
|
||||
else
|
||||
dat += "<div class='notice'>Swipe your card to authenticate yourself</div> <br>"
|
||||
dat += "<b>Message: </b>[message ? message : "<i>No Message</i>"] <br>"
|
||||
dat += "<a href='?src=[REF(src)];writeAnnouncement=1'>[message ? "Edit" : "Write"] Message</a> <br><br>"
|
||||
if((announceAuth || IsAdminGhost(user)) && message)
|
||||
dat += "<a href='?src=[REF(src)];sendAnnouncement=1'>Announce Message</a> <br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Announce Message</span> <br>"
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back</a> <br>"
|
||||
|
||||
dat += "<A href='?src=[REF(src)];setScreen=1'>Request Assistance</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=2'>Request Supplies</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=3'>Relay Anonymous Information</A><BR><BR>"
|
||||
else //main menu
|
||||
screen = 0
|
||||
announceAuth = FALSE
|
||||
if(newmessagepriority == NORMAL_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new messages</div><br>"
|
||||
if(newmessagepriority == HIGH_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>PRIORITY</b> messages</div><br>"
|
||||
if(newmessagepriority == EXTREME_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>EXTREME PRIORITY</b> messages</div><br>"
|
||||
|
||||
if(!emergency)
|
||||
dat += "<A href='?src=[REF(src)];emergency=1'>Emergency: Security</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];emergency=2'>Emergency: Engineering</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];emergency=3'>Emergency: Medical</A><BR><BR>"
|
||||
else
|
||||
dat += "<B><font color='red'>[emergency] has been dispatched to this location.</font></B><BR><BR>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=8'>View Messages</a> <br><br>"
|
||||
|
||||
if(announcementConsole)
|
||||
dat += "<A href='?src=[REF(src)];setScreen=10'>Send Station-wide Announcement</A><BR><BR>"
|
||||
if (silent)
|
||||
dat += "Speaker <A href='?src=[REF(src)];setSilent=0'>OFF</A>"
|
||||
else
|
||||
dat += "Speaker <A href='?src=[REF(src)];setSilent=1'>ON</A>"
|
||||
var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
dat += "<a href='?src=[REF(src)];setScreen=1'>Request Assistance</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=2'>Request Supplies</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=3'>Relay Anonymous Information</a> <br><br>"
|
||||
|
||||
if(!emergency)
|
||||
dat += "<a href='?src=[REF(src)];emergency=1'>Emergency: Security</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];emergency=2'>Emergency: Engineering</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];emergency=3'>Emergency: Medical</a> <br><br>"
|
||||
else
|
||||
dat += "<b><div class='bad'>[emergency] has been dispatched to this location.</div></b> <br><br>"
|
||||
|
||||
if(announcementConsole)
|
||||
dat += "<a href='?src=[REF(src)];setScreen=10'>Send Station-wide Announcement</a> <br><br>"
|
||||
if(silent)
|
||||
dat += "Speaker <a href='?src=[REF(src)];setSilent=0'>OFF</a>"
|
||||
else
|
||||
dat += "Speaker <a href='?src=[REF(src)];setSilent=1'>ON</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/requests_console/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
if(href_list["write"])
|
||||
dpt = ckey(reject_bad_text(href_list["write"])) //write contains the string of the receiving department's name
|
||||
var/new_message = stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN)
|
||||
if(new_message)
|
||||
message = new_message
|
||||
screen = 9
|
||||
if (text2num(href_list["priority"]) < 2)
|
||||
priority = -1
|
||||
else
|
||||
priority = text2num(href_list["priority"])
|
||||
priority = text2num(href_list["priority"])
|
||||
else
|
||||
dpt = "";
|
||||
msgVerified = ""
|
||||
msgStamped = ""
|
||||
screen = 0
|
||||
priority = -1
|
||||
priority = NORMAL_MESSAGE_PRIORITY //:salt:
|
||||
|
||||
if(href_list["writeAnnouncement"])
|
||||
var/new_message = reject_bad_text(stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN))
|
||||
if(new_message)
|
||||
message = new_message
|
||||
if (text2num(href_list["priority"]) < 2)
|
||||
priority = -1
|
||||
else
|
||||
priority = text2num(href_list["priority"])
|
||||
priority = text2num(href_list["priority"])
|
||||
else
|
||||
message = ""
|
||||
announceAuth = FALSE
|
||||
@@ -295,106 +306,116 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
|
||||
if(href_list["sendAnnouncement"])
|
||||
if(!announcementConsole)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
message = L.treat_message(message)
|
||||
minor_announce(message, "[department] Announcement:")
|
||||
GLOB.news_network.SubmitArticle(message, department, "Station Announcements", null)
|
||||
usr.log_talk(message, LOG_SAY, tag="station announcement from [src]")
|
||||
usr.log_talk(message, LOG_SAY, tag = "station announcement from [src]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has made a station announcement from [src] at [AREACOORD(usr)].")
|
||||
announceAuth = FALSE
|
||||
message = ""
|
||||
screen = 0
|
||||
|
||||
if(href_list["emergency"])
|
||||
if(!emergency)
|
||||
var/radio_freq
|
||||
switch(text2num(href_list["emergency"]))
|
||||
if(1) //Security
|
||||
radio_freq = FREQ_SECURITY
|
||||
emergency = "Security"
|
||||
if(2) //Engineering
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
emergency = "Engineering"
|
||||
if(3) //Medical
|
||||
radio_freq = FREQ_MEDICAL
|
||||
emergency = "Medical"
|
||||
if(radio_freq)
|
||||
Radio.set_frequency(radio_freq)
|
||||
Radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/clear_emergency), 3000)
|
||||
if(emergency) //already has an emergency? do not continue
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if( href_list["department"] && message )
|
||||
var/log_msg = message
|
||||
var/radio_freq
|
||||
switch(text2num(href_list["emergency"]))
|
||||
if(1) //Security
|
||||
radio_freq = FREQ_SECURITY
|
||||
emergency = "Security"
|
||||
if(2) //Engineering
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
emergency = "Engineering"
|
||||
if(3) //Medical
|
||||
radio_freq = FREQ_MEDICAL
|
||||
emergency = "Medical"
|
||||
if(radio_freq)
|
||||
Radio.set_frequency(radio_freq)
|
||||
Radio.talk_into(src, "[emergency] emergency in [department]!!", radio_freq)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/clear_emergency), 5 MINUTES)
|
||||
|
||||
if(href_list["department"] && message)
|
||||
var/sending = message
|
||||
sending += "<br>"
|
||||
if (msgVerified)
|
||||
sending += msgVerified
|
||||
sending += "<br>"
|
||||
if (msgStamped)
|
||||
sending += msgStamped
|
||||
sending += "<br>"
|
||||
screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull)
|
||||
if (sending)
|
||||
var/pass = FALSE
|
||||
var/datum/data_rc_msg/log = new(href_list["department"], department, log_msg, msgStamped, msgVerified, priority)
|
||||
for (var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
|
||||
if (MS.toggled)
|
||||
MS.rc_msgs += log
|
||||
pass = TRUE
|
||||
if(msgVerified)
|
||||
sending += "<span class='good'><b>[msgVerified]</b></span> <br>"
|
||||
if(msgStamped)
|
||||
sending += "<span class='boldnotice'>[msgStamped]</span> <br>"
|
||||
//so you're telling me is you cheated, by making fail happen, then quickly replacing it with 6
|
||||
|
||||
if(pass)
|
||||
var/radio_freq = 0
|
||||
switch(href_list["department"])
|
||||
if("bridge")
|
||||
radio_freq = FREQ_COMMAND
|
||||
if("medbay")
|
||||
radio_freq = FREQ_MEDICAL
|
||||
if("science")
|
||||
radio_freq = FREQ_SCIENCE
|
||||
if("engineering")
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
if("security")
|
||||
radio_freq = FREQ_SECURITY
|
||||
if("cargobay" || "mining")
|
||||
radio_freq = FREQ_SUPPLY
|
||||
Radio.set_frequency(radio_freq)
|
||||
var/authentic
|
||||
if(msgVerified || msgStamped)
|
||||
authentic = " (Authenticated)"
|
||||
var/workingServer = FALSE
|
||||
var/datum/data_rc_msg/log = new(href_list["department"], department, message, msgStamped, msgVerified, priority)
|
||||
for(var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
|
||||
if(MS.on) //on does the calculations. why would this server still work even though the apc is off??
|
||||
LAZYADD(MS.rc_msgs, log)
|
||||
workingServer = TRUE
|
||||
|
||||
var/alert = ""
|
||||
for (var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if (ckey(Console.department) == ckey(href_list["department"]))
|
||||
switch(priority)
|
||||
if(2) //High priority
|
||||
alert = "PRIORITY Alert in [department][authentic]"
|
||||
Console.createmessage(src, alert, sending, 2, 1)
|
||||
if(3) // Extreme Priority
|
||||
alert = "EXTREME PRIORITY Alert from [department][authentic]"
|
||||
Console.createmessage(src, alert , sending, 3, 1)
|
||||
else // Normal priority
|
||||
alert = "Message from [department][authentic]"
|
||||
Console.createmessage(src, alert , sending, 1, 1)
|
||||
screen = 6
|
||||
if(!workingServer)
|
||||
screen = 7
|
||||
say("NOTICE: No server detected! Please contact your local engineering team.")
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(radio_freq)
|
||||
Radio.talk_into(src, "[alert]: <i>[message]</i>", radio_freq)
|
||||
var/radio_freq = 0
|
||||
switch(href_list["department"])
|
||||
if("bridge")
|
||||
radio_freq = FREQ_COMMAND
|
||||
if("medbay")
|
||||
radio_freq = FREQ_MEDICAL
|
||||
if("science")
|
||||
radio_freq = FREQ_SCIENCE
|
||||
if("engineering")
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
if("security")
|
||||
radio_freq = FREQ_SECURITY
|
||||
if("cargobay" || "mining")
|
||||
radio_freq = FREQ_SUPPLY
|
||||
Radio.set_frequency(radio_freq)
|
||||
|
||||
switch(priority)
|
||||
if(2)
|
||||
messages += "<span class='bad'>High Priority</span><BR><b>To:</b> [dpt]<BR>[sending]"
|
||||
else
|
||||
messages += "<b>To: [dpt]</b><BR>[sending]"
|
||||
var/authentic = ""
|
||||
if(msgVerified || msgStamped)
|
||||
authentic = " (Authenticated)"
|
||||
|
||||
var/alert = ""
|
||||
for(var/obj/machinery/requests_console/C in GLOB.allConsoles)
|
||||
if(ckey(C.department) != ckey(href_list["department"]))
|
||||
continue
|
||||
switch(priority)
|
||||
if(HIGH_MESSAGE_PRIORITY) //High priority
|
||||
alert = "PRIORITY Alert from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, HIGH_MESSAGE_PRIORITY)
|
||||
if(EXTREME_MESSAGE_PRIORITY) // Extreme Priority
|
||||
alert = "EXTREME PRIORITY Alert from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, EXTREME_MESSAGE_PRIORITY)
|
||||
else // Normal priority
|
||||
alert = "Message from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, NORMAL_MESSAGE_PRIORITY)
|
||||
screen = 6 //if it ever gets here that means (c.department == href_ls["dept"])
|
||||
|
||||
if(radio_freq)
|
||||
Radio.talk_into(src, "[alert]: <i>[message]</i>", radio_freq)
|
||||
//log to (this)
|
||||
switch(priority)
|
||||
if(HIGH_MESSAGE_PRIORITY)
|
||||
messages += "<span class='bad'>High Priority</span><br><b>To:</b> [dpt]<br>[sending]"
|
||||
if(EXTREME_MESSAGE_PRIORITY)
|
||||
messages += "<span class='bad'>!!!Extreme Priority!!!</span><br><b>To:</b> [dpt]<br>[sending]"
|
||||
else
|
||||
say("NOTICE: No server detected!")
|
||||
messages += "<b>To:</b> [dpt]<br>[sending]"
|
||||
|
||||
|
||||
//Handle screen switching
|
||||
switch(text2num(href_list["setScreen"]))
|
||||
if(null) //skip
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(1) //req. assistance
|
||||
screen = 1
|
||||
if(2) //req. supplies
|
||||
@@ -422,16 +443,14 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
msgVerified = ""
|
||||
msgStamped = ""
|
||||
message = ""
|
||||
priority = -1
|
||||
priority = NORMAL_MESSAGE_PRIORITY // :salt:
|
||||
screen = 0
|
||||
|
||||
//Handle silencing the console
|
||||
switch( href_list["setSilent"] )
|
||||
if(null) //skip
|
||||
if("1")
|
||||
silent = TRUE
|
||||
else
|
||||
silent = FALSE
|
||||
if(href_list["setSilent"] == "1")
|
||||
silent = TRUE
|
||||
else
|
||||
silent = FALSE
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -456,31 +475,32 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
linkedsender = source
|
||||
capitalize(title)
|
||||
switch(priority)
|
||||
if(2) //High priority
|
||||
if(HIGH_MESSAGE_PRIORITY) //High priority
|
||||
if(newmessagepriority < HIGH_MESSAGE_PRIORITY)
|
||||
newmessagepriority = HIGH_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
if(!silent)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'>High Priority</span><BR><b>From:</b> [linkedsender]<BR>[message]"
|
||||
messages += "<span class='bad'>High Priority</span><br><b>From:</b> [linkedsender]<br>[message]" //the fuck is this not being sent
|
||||
|
||||
if(3) // Extreme Priority
|
||||
if(EXTREME_MESSAGE_PRIORITY) // Extreme Priority
|
||||
if(newmessagepriority < EXTREME_MESSAGE_PRIORITY)
|
||||
newmessagepriority = EXTREME_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'>!!!Extreme Priority!!!</span><BR><b>From:</b> [linkedsender]<BR>[message]"
|
||||
//we ignore the silent option because this is !!!IMPORTANT!!!
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'><b>!!!Extreme Priority!!!</span></b><br><b>From:</b> [linkedsender]<br>[message]"
|
||||
|
||||
else // Normal priority
|
||||
if(newmessagepriority < NORMAL_MESSAGE_PRIORITY)
|
||||
newmessagepriority = NORMAL_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
if(!src.silent)
|
||||
if(!silent)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<b>From:</b> [linkedsender]<BR>[message]"
|
||||
messages += "<b>From:</b> [linkedsender]<br>[message]"
|
||||
|
||||
/obj/machinery/requests_console/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/crowbar))
|
||||
@@ -504,23 +524,26 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
to_chat(user, "<span class='warning'>You must open the maintenance panel first!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/card/id/ID = O.GetID()
|
||||
if(ID)
|
||||
if(istype(O, /obj/item/card/id))
|
||||
var/obj/item/card/id/ID = O.GetID()
|
||||
if(!ID)
|
||||
return
|
||||
if(screen == 9)
|
||||
msgVerified = "<font color='green'><b>Verified by [ID.registered_name] ([ID.assignment])</b></font>"
|
||||
msgVerified = "Verified by [ID.registered_name] ([ID.assignment])"
|
||||
updateUsrDialog()
|
||||
if(screen == 10)
|
||||
if (ACCESS_RC_ANNOUNCE in ID.access)
|
||||
if(ACCESS_RC_ANNOUNCE in ID.access)
|
||||
announceAuth = TRUE
|
||||
else
|
||||
announceAuth = FALSE
|
||||
to_chat(user, "<span class='warning'>You are not authorized to send announcements!</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
if (istype(O, /obj/item/stamp))
|
||||
|
||||
if(istype(O, /obj/item/stamp))
|
||||
if(screen == 9)
|
||||
var/obj/item/stamp/T = O
|
||||
msgStamped = "<span class='boldnotice'>Stamped with the [T.name]</span>"
|
||||
msgStamped = "Stamped with the [T.name]"
|
||||
updateUsrDialog()
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/obj/machinery/sheetifier
|
||||
name = "Sheet-meister 2000"
|
||||
desc = "A very sheety machine"
|
||||
icon = 'icons/obj/machines/sheetifier.dmi'
|
||||
icon_state = "base_machine"
|
||||
density = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
circuit = /obj/item/circuitboard/machine/sheetifier
|
||||
layer = BELOW_OBJ_LAYER
|
||||
var/busy_processing = FALSE
|
||||
|
||||
/obj/machinery/sheetifier/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/meat), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, /obj/item/reagent_containers/food/snacks/meat/slab, CALLBACK(src, .proc/CanInsertMaterials), CALLBACK(src, .proc/AfterInsertMaterials))
|
||||
|
||||
/obj/machinery/sheetifier/update_overlays()
|
||||
. = ..()
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
var/mutable_appearance/on_overlay = mutable_appearance(icon, "buttons_on")
|
||||
. += on_overlay
|
||||
|
||||
/obj/machinery/sheetifier/update_icon_state()
|
||||
icon_state = "base_machine[busy_processing ? "_processing" : ""]"
|
||||
|
||||
/obj/machinery/sheetifier/proc/CanInsertMaterials()
|
||||
return !busy_processing
|
||||
|
||||
/obj/machinery/sheetifier/proc/AfterInsertMaterials(item_inserted, id_inserted, amount_inserted)
|
||||
busy_processing = TRUE
|
||||
update_icon()
|
||||
var/datum/material/last_inserted_material = id_inserted
|
||||
var/mutable_appearance/processing_overlay = mutable_appearance(icon, "processing")
|
||||
processing_overlay.color = last_inserted_material.color
|
||||
flick_overlay_static(processing_overlay, src, 64)
|
||||
addtimer(CALLBACK(src, .proc/finish_processing), 64)
|
||||
|
||||
/obj/machinery/sheetifier/proc/finish_processing()
|
||||
busy_processing = FALSE
|
||||
update_icon()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all() //Returns all as sheets
|
||||
@@ -0,0 +1,33 @@
|
||||
/obj/machinery/shuttle
|
||||
name = "shuttle component"
|
||||
desc = "Something for shuttles."
|
||||
density = TRUE
|
||||
obj_integrity = 250
|
||||
max_integrity = 250
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
icon_state = "burst_plasma"
|
||||
idle_power_usage = 150
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine
|
||||
var/icon_state_closed = "burst_plasma"
|
||||
var/icon_state_open = "burst_plasma_open"
|
||||
var/icon_state_off = "burst_plasma_off"
|
||||
|
||||
/obj/machinery/shuttle/Initialize()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines += src
|
||||
|
||||
/obj/machinery/shuttle/Destroy()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines -= src
|
||||
|
||||
/obj/machinery/shuttle/attackby(obj/item/I, mob/living/user, params)
|
||||
if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_closed, I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(panel_open)
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,138 @@
|
||||
//-----------------------------------------------
|
||||
//-------------Engine Thrusters------------------
|
||||
//-----------------------------------------------
|
||||
|
||||
#define ENGINE_HEAT_TARGET 600
|
||||
#define ENGINE_HEATING_POWER 5000000
|
||||
|
||||
/obj/machinery/shuttle/engine
|
||||
name = "shuttle thruster"
|
||||
desc = "A thruster for shuttles."
|
||||
density = TRUE
|
||||
obj_integrity = 250
|
||||
max_integrity = 250
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
icon_state = "burst_plasma"
|
||||
idle_power_usage = 150
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine
|
||||
var/thrust = 0
|
||||
var/fuel_use = 0
|
||||
var/bluespace_capable = TRUE
|
||||
var/cooldown = 0
|
||||
var/thruster_active = FALSE
|
||||
var/datum/weakref/attached_heater
|
||||
|
||||
/obj/machinery/shuttle/engine/plasma
|
||||
name = "plasma thruster"
|
||||
desc = "A thruster that burns plasma stored in an adjacent plasma thruster heater."
|
||||
icon_state = "burst_plasma"
|
||||
icon_state_off = "burst_plasma_off"
|
||||
|
||||
idle_power_usage = 0
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine/plasma
|
||||
thrust = 25
|
||||
fuel_use = 0.24
|
||||
bluespace_capable = FALSE
|
||||
cooldown = 45
|
||||
|
||||
/obj/machinery/shuttle/engine/void
|
||||
name = "void thruster"
|
||||
desc = "A thruster using technology to breach voidspace for propulsion."
|
||||
icon_state = "burst_void"
|
||||
icon_state_off = "burst_void"
|
||||
icon_state_closed = "burst_void"
|
||||
icon_state_open = "burst_void_open"
|
||||
idle_power_usage = 0
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine/void
|
||||
thrust = 400
|
||||
fuel_use = 0
|
||||
bluespace_capable = TRUE
|
||||
cooldown = 90
|
||||
|
||||
/obj/machinery/shuttle/engine/Initialize()
|
||||
. = ..()
|
||||
check_setup()
|
||||
|
||||
/obj/machinery/shuttle/engine/on_construction()
|
||||
. = ..()
|
||||
check_setup()
|
||||
|
||||
/obj/machinery/shuttle/engine/Destroy()
|
||||
attached_heater = FALSE
|
||||
thruster_active = FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/shuttle/engine/proc/check_setup()
|
||||
if(!anchored)
|
||||
attached_heater = null
|
||||
update_engine()
|
||||
return
|
||||
var/heater_turf
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
heater_turf = get_offset_target_turf(src, 0, 1)
|
||||
if(SOUTH)
|
||||
heater_turf = get_offset_target_turf(src, 0, -1)
|
||||
if(EAST)
|
||||
heater_turf = get_offset_target_turf(src, 1, 0)
|
||||
if(WEST)
|
||||
heater_turf = get_offset_target_turf(src, -1, 0)
|
||||
if(!heater_turf)
|
||||
attached_heater = null
|
||||
update_engine()
|
||||
return
|
||||
attached_heater = null
|
||||
for(var/obj/machinery/atmospherics/components/unary/shuttle/heater/as_heater in heater_turf)
|
||||
if(as_heater.dir != dir)
|
||||
continue
|
||||
if(as_heater.panel_open)
|
||||
continue
|
||||
if(!as_heater.anchored)
|
||||
continue
|
||||
attached_heater = WEAKREF(as_heater)
|
||||
break
|
||||
update_engine()
|
||||
return
|
||||
|
||||
/obj/machinery/shuttle/engine/proc/update_engine()
|
||||
if(!attached_heater)
|
||||
icon_state = icon_state_off
|
||||
thruster_active = FALSE
|
||||
return
|
||||
var/obj/machinery/atmospherics/components/unary/shuttle/heater/resolved_heater = attached_heater.resolve()
|
||||
if(panel_open)
|
||||
thruster_active = FALSE
|
||||
else if(resolved_heater?.hasFuel(1))
|
||||
icon_state = icon_state_closed
|
||||
thruster_active = TRUE
|
||||
else
|
||||
thruster_active = FALSE
|
||||
icon_state = icon_state_off
|
||||
return
|
||||
|
||||
/obj/machinery/shuttle/engine/void/update_engine()
|
||||
if(panel_open)
|
||||
thruster_active = FALSE
|
||||
return
|
||||
thruster_active = TRUE
|
||||
icon_state = icon_state_closed
|
||||
return
|
||||
|
||||
//Thanks to spaceheater.dm for inspiration :)
|
||||
/obj/machinery/shuttle/engine/proc/fireEngine()
|
||||
var/turf/heatTurf = loc
|
||||
if(!heatTurf)
|
||||
return
|
||||
var/datum/gas_mixture/env = heatTurf.return_air()
|
||||
var/heat_cap = env.heat_capacity()
|
||||
var/req_power = abs(env.return_temperature() - ENGINE_HEAT_TARGET) * heat_cap
|
||||
req_power = min(req_power, ENGINE_HEATING_POWER)
|
||||
var/deltaTemperature = req_power / heat_cap
|
||||
if(deltaTemperature < 0)
|
||||
return
|
||||
env.temperature += deltaTemperature
|
||||
air_update_turf()
|
||||
|
||||
/obj/machinery/shuttle/engine/default_change_direction_wrench(mob/user, obj/item/I)
|
||||
. = ..()
|
||||
update_engine()
|
||||
@@ -0,0 +1,132 @@
|
||||
//-----------------------------------------------
|
||||
//--------------Engine Heaters-------------------
|
||||
//This uses atmospherics, much like a thermomachine,
|
||||
//but instead of changing temp, it stores plasma and uses
|
||||
//it for the engine.
|
||||
//-----------------------------------------------
|
||||
/obj/machinery/atmospherics/components/unary/shuttle
|
||||
name = "shuttle atmospherics device"
|
||||
desc = "This does something to do with shuttle atmospherics"
|
||||
icon_state = "heater"
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater
|
||||
name = "engine heater"
|
||||
desc = "Directs energy into compressed particles in order to power an attached thruster."
|
||||
icon_state = "heater_pipe"
|
||||
var/icon_state_closed = "heater_pipe"
|
||||
var/icon_state_open = "heater_pipe_open"
|
||||
var/icon_state_off = "heater_pipe"
|
||||
idle_power_usage = 50
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/heater
|
||||
|
||||
density = TRUE
|
||||
max_integrity = 400
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 30)
|
||||
layer = OBJ_LAYER
|
||||
showpipe = TRUE
|
||||
|
||||
pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
|
||||
|
||||
var/gas_type = /datum/gas/plasma
|
||||
var/efficiency_multiplier = 1
|
||||
var/gas_capacity = 0
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/New()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines += src
|
||||
SetInitDirections()
|
||||
update_adjacent_engines()
|
||||
updateGasStats()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/Destroy()
|
||||
. = ..()
|
||||
update_adjacent_engines()
|
||||
GLOB.custom_shuttle_machines -= src
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/on_construction()
|
||||
..(dir, dir)
|
||||
SetInitDirections()
|
||||
update_adjacent_engines()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/default_change_direction_wrench(mob/user, obj/item/I)
|
||||
if(!..())
|
||||
return FALSE
|
||||
SetInitDirections()
|
||||
var/obj/machinery/atmospherics/node = nodes[1]
|
||||
if(node)
|
||||
node.disconnect(src)
|
||||
nodes[1] = null
|
||||
if(!parents[1])
|
||||
return
|
||||
nullifyPipenet(parents[1])
|
||||
|
||||
atmosinit()
|
||||
node = nodes[1]
|
||||
if(node)
|
||||
node.atmosinit()
|
||||
node.addMember(src)
|
||||
build_network()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/RefreshParts()
|
||||
var/cap = 0
|
||||
var/eff = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
cap += M.rating
|
||||
for(var/obj/item/stock_parts/micro_laser/L in component_parts)
|
||||
eff += L.rating
|
||||
gas_capacity = 5000 * ((cap - 1) ** 2) + 1000
|
||||
efficiency_multiplier = round(((eff / 2) / 2.8) ** 2, 0.1)
|
||||
updateGasStats()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/examine(mob/user)
|
||||
. = ..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
. += "The engine heater's gas dial reads [air_contents.return_volume()] liters in internal tank.<br>"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/updateGasStats()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
if(!air_contents)
|
||||
return
|
||||
air_contents.volume = gas_capacity
|
||||
air_contents.temperature = T20C
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/hasFuel(var/required)
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
var/moles = air_contents.total_moles()
|
||||
return moles >= required
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/consumeFuel(var/amount)
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.remove(amount)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/attackby(obj/item/I, mob/living/user, params)
|
||||
update_adjacent_engines()
|
||||
if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_closed, I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(panel_open)
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/update_adjacent_engines()
|
||||
var/engine_turf
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
engine_turf = get_offset_target_turf(src, 0, -1)
|
||||
if(SOUTH)
|
||||
engine_turf = get_offset_target_turf(src, 0, 1)
|
||||
if(EAST)
|
||||
engine_turf = get_offset_target_turf(src, -1, 0)
|
||||
if(WEST)
|
||||
engine_turf = get_offset_target_turf(src, 1, 0)
|
||||
if(!engine_turf)
|
||||
return
|
||||
for(var/obj/machinery/shuttle/engine/E in engine_turf)
|
||||
E.check_setup()
|
||||
@@ -115,8 +115,8 @@
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/space_heater/RefreshParts()
|
||||
var/laser = 0
|
||||
var/cap = 0
|
||||
var/laser = 2
|
||||
var/cap = 1
|
||||
for(var/obj/item/stock_parts/micro_laser/M in component_parts)
|
||||
laser += M.rating
|
||||
for(var/obj/item/stock_parts/capacitor/M in component_parts)
|
||||
@@ -166,6 +166,11 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/space_heater/wrench_act(mob/living/user, obj/item/I)
|
||||
..()
|
||||
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)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
desc = null
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
@@ -289,7 +290,7 @@
|
||||
if("shuttle_id")
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
/obj/machinery/status_display/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
if (port && (shuttle_id == initial(shuttle_id) || override))
|
||||
shuttle_id = port.id
|
||||
update()
|
||||
|
||||
@@ -1,215 +1,164 @@
|
||||
|
||||
/*
|
||||
The log console for viewing the entire telecomms
|
||||
network log
|
||||
*/
|
||||
|
||||
/obj/machinery/computer/telecomms/server
|
||||
name = "telecommunications server monitoring console"
|
||||
icon_screen = "comm_logs"
|
||||
desc = "Has full access to all details and record of the telecommunications network it's monitoring."
|
||||
circuit = /obj/item/circuitboard/computer/comm_server
|
||||
req_access = list(ACCESS_TCOMSAT)
|
||||
|
||||
var/screen = 0 // the screen number:
|
||||
var/list/servers = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/server/SelectedServer
|
||||
var/list/machinelist = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/server/SelectedMachine = null
|
||||
|
||||
var/network = "NULL" // the network to probe
|
||||
var/temp = "" // temporary feedback messages
|
||||
var/notice = ""
|
||||
var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech
|
||||
|
||||
var/universal_translate = 0 // set to 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)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "tcommsserver", "Telecomms Server Monitor", 575, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
req_access = list(ACCESS_TCOMSAT)
|
||||
circuit = /obj/item/circuitboard/computer/comm_server
|
||||
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
data_out["network"] = network
|
||||
data_out["notice"] = notice
|
||||
|
||||
/obj/machinery/computer/telecomms/server/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<TITLE>Telecommunication Server Monitor</TITLE><center><b>Telecommunications Server Monitor</b></center>"
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/server/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data)
|
||||
data_out["servers"] = sortList(data_out["servers"]) //a-z sort
|
||||
|
||||
switch(screen)
|
||||
if(!SelectedMachine) //null is bad.
|
||||
data_out["selected"] = null //but in js, null is good.
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = SelectedMachine.name,
|
||||
id = SelectedMachine.id,
|
||||
status = SelectedMachine.on,
|
||||
traffic = SelectedMachine.totaltraffic, //note: total traffic, not traffic!
|
||||
ref = REF(SelectedMachine)
|
||||
)
|
||||
data_out["selected_logs"] = list()
|
||||
|
||||
// --- Main Menu ---
|
||||
if(!LAZYLEN(SelectedMachine.log_entries))
|
||||
return data_out
|
||||
|
||||
for(var/datum/comm_log_entry/C in SelectedMachine.log_entries)
|
||||
var/list/data = list()
|
||||
data["name"] = C.name //name of the file
|
||||
data["ref"] = REF(C)
|
||||
data["input_type"] = C.input_type //type of input ("Speech File" | "Execution Error").
|
||||
|
||||
if(0)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<br>Current Network: <a href='?src=[REF(src)];network=1'>[network]</a><br>"
|
||||
if(servers.len)
|
||||
dat += "<br>Detected Telecommunication Servers:<ul>"
|
||||
for(var/obj/machinery/telecomms/T in servers)
|
||||
dat += "<li><a href='?src=[REF(src)];viewserver=[T.id]'>[REF(T)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ul>"
|
||||
dat += "<br><a href='?src=[REF(src)];operation=release'>\[Flush Buffer\]</a>"
|
||||
if(C.input_type == "Speech File") //there is a reason why this is not a switch.
|
||||
data["source"] = list(
|
||||
name = C.parameters["name"], //name of the mob | obj
|
||||
job = C.parameters["job"] //job of the mob | obj
|
||||
)
|
||||
|
||||
// -- Determine race of orator --
|
||||
var/mobtype = C.parameters["mobtype"]
|
||||
var/race // The actual race of the mob
|
||||
|
||||
if(ispath(mobtype, /mob/living/carbon/human) || ispath(mobtype, /mob/living/brain))
|
||||
race = "Humanoid"
|
||||
else if(ispath(mobtype, /mob/living/simple_animal/slime))
|
||||
race = "Slime" // NT knows a lot about slimes, but not aliens. Can identify slimes
|
||||
else if(ispath(mobtype, /mob/living/carbon/monkey))
|
||||
race = "Monkey"
|
||||
else if(ispath(mobtype, /mob/living/silicon) || C.parameters["job"] == "AI")
|
||||
race = "Artificial Life" // sometimes M gets deleted prematurely for AIs... just check the job
|
||||
else if(isobj(mobtype))
|
||||
race = "Machinery"
|
||||
else if(ispath(mobtype, /mob/living/simple_animal))
|
||||
race = "Domestic Animal"
|
||||
else
|
||||
dat += "<br>No servers detected. Scan for servers: <a href='?src=[REF(src)];operation=scan'>\[Scan\]</a>"
|
||||
race = "Unidentifiable"
|
||||
|
||||
data["race"] = race
|
||||
// based on [/atom/movable/proc/lang_treat]
|
||||
var/message = C.parameters["message"]
|
||||
var/language = C.parameters["language"]
|
||||
|
||||
// --- Viewing Server ---
|
||||
if(universal_translate || user.has_language(language))
|
||||
message = message
|
||||
else if(!user.has_language(language))
|
||||
var/datum/language/D = GLOB.language_datum_instances[language]
|
||||
message = D.scramble(message)
|
||||
else if(language)
|
||||
message = "(unintelligible)"
|
||||
|
||||
if(1)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<center><a href='?src=[REF(src)];operation=mainmenu'>\[Main Menu\]</a> <a href='?src=[REF(src)];operation=refresh'>\[Refresh\]</a></center>"
|
||||
dat += "<br>Current Network: [network]"
|
||||
dat += "<br>Selected Server: [SelectedServer.id]"
|
||||
data["message"] = message
|
||||
|
||||
if(SelectedServer.totaltraffic >= 1024)
|
||||
dat += "<br>Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes<br><br>"
|
||||
else
|
||||
dat += "<br>Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes<br><br>"
|
||||
else if(C.input_type == "Execution Error")
|
||||
data["message"] = C.parameters["message"]
|
||||
else
|
||||
data["message"] = "(unintelligible)"
|
||||
|
||||
data_out["selected_logs"] += list(data)
|
||||
return data_out
|
||||
|
||||
dat += "Stored Logs: <ol>"
|
||||
|
||||
var/i = 0
|
||||
for(var/datum/comm_log_entry/C in SelectedServer.log_entries)
|
||||
i++
|
||||
|
||||
|
||||
// If the log is a speech file
|
||||
if(C.input_type == "Speech File")
|
||||
dat += "<li><font color = #008F00>[C.name]</font> <font color = #FF0000><a href='?src=[REF(src)];delete=[i]'>\[X\]</a></font><br>"
|
||||
|
||||
// -- Determine race of orator --
|
||||
|
||||
var/mobtype = C.parameters["mobtype"]
|
||||
var/race // The actual race of the mob
|
||||
|
||||
if(ispath(mobtype, /mob/living/carbon/human) || ispath(mobtype, /mob/living/brain))
|
||||
race = "Humanoid"
|
||||
|
||||
// NT knows a lot about slimes, but not aliens. Can identify slimes
|
||||
else if(ispath(mobtype, /mob/living/simple_animal/slime))
|
||||
race = "Slime"
|
||||
|
||||
else if(ispath(mobtype, /mob/living/carbon/monkey))
|
||||
race = "Monkey"
|
||||
|
||||
// sometimes M gets deleted prematurely for AIs... just check the job
|
||||
else if(ispath(mobtype, /mob/living/silicon) || C.parameters["job"] == "AI")
|
||||
race = "Artificial Life"
|
||||
|
||||
else if(isobj(mobtype))
|
||||
race = "Machinery"
|
||||
|
||||
else if(ispath(mobtype, /mob/living/simple_animal))
|
||||
race = "Domestic Animal"
|
||||
|
||||
else
|
||||
race = "<i>Unidentifiable</i>"
|
||||
|
||||
dat += "<u><font color = #18743E>Data type</font></u>: [C.input_type]<br>"
|
||||
dat += "<u><font color = #18743E>Source</font></u>: [C.parameters["name"]] (Job: [C.parameters["job"]])<br>"
|
||||
dat += "<u><font color = #18743E>Class</font></u>: [race]<br>"
|
||||
var/message = C.parameters["message"]
|
||||
var/language = C.parameters["language"]
|
||||
|
||||
// based on [/atom/movable/proc/lang_treat]
|
||||
if (universal_translate || user.has_language(language))
|
||||
message = "\"[message]\""
|
||||
else if (!user.has_language(language))
|
||||
var/datum/language/D = GLOB.language_datum_instances[language]
|
||||
message = "\"[D.scramble(message)]\""
|
||||
else if (language)
|
||||
message = "<i>(unintelligible)</i>"
|
||||
|
||||
dat += "<u><font color = #18743E>Contents</font></u>: [message]<br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
else if(C.input_type == "Execution Error")
|
||||
dat += "<li><font color = #990000>[C.name]</font> <a href='?src=[REF(src)];delete=[i]'>\[X\]</a><br>"
|
||||
dat += "<u><font color = #787700>Error</font></u>: \"[C.parameters["message"]]\"<br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
else
|
||||
dat += "<li><font color = #000099>[C.name]</font> <a href='?src=[REF(src)];delete=[i]'>\[X\]</a><br>"
|
||||
dat += "<u><font color = #18743E>Data type</font></u>: [C.input_type]<br>"
|
||||
dat += "<u><font color = #18743E>Contents</font></u>: <i>(unintelligible)</i><br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
|
||||
dat += "</ol>"
|
||||
|
||||
|
||||
|
||||
user << browse(dat, "window=comm_monitor;size=575x400")
|
||||
onclose(user, "server_control")
|
||||
|
||||
temp = ""
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/telecomms/server/Topic(href, href_list)
|
||||
/obj/machinery/computer/telecomms/server/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["viewserver"])
|
||||
screen = 1
|
||||
for(var/obj/machinery/telecomms/T in servers)
|
||||
if(T.id == href_list["viewserver"])
|
||||
SelectedServer = T
|
||||
break
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
|
||||
if("release")
|
||||
servers = list()
|
||||
screen = 0
|
||||
|
||||
if("mainmenu")
|
||||
screen = 0
|
||||
|
||||
if("scan")
|
||||
if(servers.len > 0)
|
||||
temp = "<font color = #D70B00>- FAILED: CANNOT PROBE WHEN BUFFER FULL -</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/server/T in urange(25, src))
|
||||
if(T.network == network)
|
||||
servers.Add(T)
|
||||
|
||||
if(!servers.len)
|
||||
temp = "<font color = #D70B00>- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -</font color>"
|
||||
else
|
||||
temp = "<font color = #336699>- [servers.len] SERVERS PROBED & BUFFERED -</font color>"
|
||||
|
||||
screen = 0
|
||||
|
||||
if(href_list["delete"])
|
||||
|
||||
if(!src.allowed(usr) && !(obj_flags & EMAGGED))
|
||||
to_chat(usr, "<span class='danger'>ACCESS DENIED.</span>")
|
||||
switch(action)
|
||||
if("mainmenu")
|
||||
SelectedMachine = null
|
||||
notice = ""
|
||||
return
|
||||
if("release")
|
||||
machinelist = list()
|
||||
notice = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
notice = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
SelectedMachine = null
|
||||
machinelist = list()
|
||||
return
|
||||
if("probe")
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
notice = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list) //telecomms just went global!
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
if(SelectedServer)
|
||||
if(!LAZYLEN(machinelist))
|
||||
notice = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine")
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
if("delete")
|
||||
if(!src.allowed(usr) && !CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
to_chat(usr, "<span class='danger'>ACCESS DENIED.</span>")
|
||||
return
|
||||
|
||||
var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])]
|
||||
|
||||
temp = "<font color = #336699>- DELETED ENTRY: [D.name] -</font color>"
|
||||
|
||||
SelectedServer.log_entries.Remove(D)
|
||||
if(!SelectedMachine)
|
||||
notice = "ALERT: No server detected. Server may be nonresponsive."
|
||||
return
|
||||
var/datum/comm_log_entry/D = locate(params["value"])
|
||||
if(!istype(D))
|
||||
notice = "NOTICE: Object not found"
|
||||
return
|
||||
notice = "Deleted entry: [D.name]"
|
||||
LAZYREMOVE(SelectedMachine.log_entries, D)
|
||||
qdel(D)
|
||||
|
||||
else
|
||||
temp = "<font color = #D70B00>- FAILED: NO SELECTED MACHINE -</font color>"
|
||||
|
||||
if(href_list["network"])
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
else
|
||||
|
||||
network = newnet
|
||||
screen = 0
|
||||
servers = list()
|
||||
temp = "<font color = #336699>- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -</font color>"
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/telecomms/server/attackby()
|
||||
. = ..()
|
||||
updateUsrDialog()
|
||||
@@ -3,241 +3,360 @@
|
||||
Lets you read PDA and request console messages.
|
||||
*/
|
||||
|
||||
#define LINKED_SERVER_NONRESPONSIVE (!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
|
||||
// The monitor itself.
|
||||
/obj/machinery/computer/message_monitor
|
||||
name = "message monitor console"
|
||||
desc = "Used to monitor the crew's PDA messages, as well as request console messages."
|
||||
icon_screen = "comm_logs"
|
||||
circuit = /obj/item/circuitboard/computer/message_monitor
|
||||
//Server linked to.
|
||||
|
||||
//Servers, and server linked to.
|
||||
var/network = "tcommsat" // the network to probe
|
||||
var/list/machinelist = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/message_server/linkedServer = null
|
||||
|
||||
//Sparks effect - For emag
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
|
||||
//Messages - Saves me time if I want to change something.
|
||||
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
|
||||
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
|
||||
var/defaultmsg = "<span class='notice'>Welcome. Please select an option.</span>"
|
||||
var/rebootmsg = "<span class='warning'>%$&(�: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!</span>"
|
||||
var/noserver = "ALERT: No server detected. Server may be nonresponsive."
|
||||
var/incorrectkey = "ALERT: Incorrect decryption key!"
|
||||
var/rebootmsg = "%$�(�:SYS&EM INTRN@L ACfES VIOL�TIa█ DEtE₡TED! Ree3ARcinG A█ BAaKUP RdST�RE PbINT \[0xcff32ca/ - PLfASE aAIT"
|
||||
|
||||
//Computer properties
|
||||
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
|
||||
var/hacking = FALSE // Is it being hacked into by the AI/Cyborg
|
||||
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
var/optioncount = 7
|
||||
var/message = "" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
|
||||
// Custom Message Properties
|
||||
var/customsender = "System Administrator"
|
||||
var/obj/item/pda/customrecepient = null
|
||||
var/customsender = "System Administrator"
|
||||
var/customjob = "Admin"
|
||||
var/custommessage = "This is a test, please ignore."
|
||||
|
||||
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)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "telepdalog", name, 727, 510, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
|
||||
if(!linkedServer || !auth) // no need building this if the usr isn't authenticated
|
||||
return data_out
|
||||
|
||||
data_out["recon_logs"] = list()
|
||||
var/i1 = 0
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
i1++
|
||||
if(i1 > 3000)
|
||||
break
|
||||
var/list/data = list(
|
||||
sender = rc.send_dpt,
|
||||
recipient = rc.rec_dpt,
|
||||
message = rc.message,
|
||||
stamp = rc.stamp,
|
||||
auth = rc.id_auth,
|
||||
priority = rc.priority,
|
||||
ref = REF(rc)
|
||||
)
|
||||
data_out["recon_logs"] += list(data)
|
||||
|
||||
data_out["message_logs"] = list()
|
||||
var/i2 = 0
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
i2++
|
||||
if(i2 > 3000)
|
||||
break
|
||||
var/list/data = list(
|
||||
sender = pda.sender,
|
||||
recipient = pda.recipient,
|
||||
message = pda.message,
|
||||
picture = pda.picture ? TRUE : FALSE,
|
||||
ref = REF(pda)
|
||||
)
|
||||
data_out["message_logs"] += list(data)
|
||||
|
||||
return data_out
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
|
||||
data_out["notice"] = message
|
||||
data_out["authenticated"] = auth
|
||||
data_out["network"] = network
|
||||
|
||||
var/mob/living/silicon/S = user
|
||||
if(istype(S) && S.hack_software)
|
||||
data_out["canhack"] = TRUE
|
||||
|
||||
data_out["hacking"] = (hacking || CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
if(hacking)
|
||||
data_out["borg"] = ((isAI(user) || iscyborg(user)) && !CHECK_BITFIELD(obj_flags, EMAGGED)) //even borgs can't read emag
|
||||
return data_out
|
||||
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/message_server/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data) // This /might/ cause an oom. Too bad!
|
||||
data_out["servers"] = sortList(data_out["servers"]) //a-z sort
|
||||
|
||||
data_out["fake_message"] = list(
|
||||
sender = customsender,
|
||||
job = customjob,
|
||||
message = custommessage,
|
||||
recepient = (customrecepient ? "[customrecepient.owner] ([customrecepient.ownjob])" : null)
|
||||
)
|
||||
|
||||
if(!linkedServer)
|
||||
data_out["selected"] = null
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = linkedServer.name,
|
||||
id = linkedServer.id,
|
||||
ref = REF(linkedServer),
|
||||
status = (linkedServer.on && (linkedServer.toggled != FALSE)) // returns true if server is running
|
||||
)
|
||||
return data_out
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("mainmenu") //deselect
|
||||
linkedServer = null
|
||||
auth = FALSE
|
||||
message = ""
|
||||
return
|
||||
if("release") //release server listing
|
||||
machinelist = list()
|
||||
message = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer, and de-auth them, if blank, return default
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
message = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
linkedServer = null
|
||||
machinelist = list()
|
||||
auth = FALSE
|
||||
message = "NOTICE: Network change detected. Server disconnected, please re-authenticate."
|
||||
return
|
||||
if("probe") //probe network for the pda serbs
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
message = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/message_server/T in GLOB.telecomms_list)
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
if(!LAZYLEN(machinelist))
|
||||
message = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine") //selected but not authorized
|
||||
for(var/obj/machinery/telecomms/message_server/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
linkedServer = T
|
||||
break
|
||||
|
||||
if("auth")
|
||||
if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
if(auth)
|
||||
auth = FALSE
|
||||
update_static_data(usr) //make sure it's cleared!
|
||||
return
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey == "")
|
||||
return
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
update_static_data(usr)
|
||||
if("change_auth")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Please log in to change the password!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/dkey = stripped_input(usr, "Please enter the old decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = stripped_input(usr, "Please enter the new key (3 - 20 characters max):")
|
||||
if(!ISINRANGE(length(newkey), 3, 20))
|
||||
message = "NOTICE: Decryption key length too long/short!"
|
||||
return
|
||||
if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "NOTICE: Decryption key set."
|
||||
return
|
||||
message = incorrectkey
|
||||
|
||||
if("hack")
|
||||
if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
addtimer(CALLBACK(src, .proc/BruteForce, usr), (10 SECONDS) * length(linkedServer.decryptkey))
|
||||
|
||||
if("del_log")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Delete aborted!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/datum/data_ref = locate(params["ref"])
|
||||
if(istype(data_ref, /datum/data_rc_msg))
|
||||
LAZYREMOVE(linkedServer.rc_msgs, data_ref)
|
||||
message = "NOTICE: Log Deleted!"
|
||||
else if(istype(data_ref, /datum/data_pda_msg))
|
||||
LAZYREMOVE(linkedServer.pda_msgs, data_ref)
|
||||
message = "NOTICE: Log Deleted!"
|
||||
else
|
||||
message = "NOTICE: Log not found! It may have already been deleted"
|
||||
update_static_data(usr)
|
||||
|
||||
if("clear_log")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Delete aborted!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/what = params["value"]
|
||||
if(what == "pda_logs")
|
||||
linkedServer.pda_msgs = list()
|
||||
if(what == "rc_msgs")
|
||||
linkedServer.rc_msgs = list()
|
||||
update_static_data(usr)
|
||||
if("fake")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
if("reset" in params)
|
||||
ResetMessage()
|
||||
return
|
||||
if("send" in params)
|
||||
if(isnull(customrecepient))
|
||||
message = "NOTICE: No recepient selected!"
|
||||
return
|
||||
if(length(custommessage) <= 0 || custommessage == "")
|
||||
message = "NOTICE: No message entered!"
|
||||
return
|
||||
if(length(customjob) <= 0 || customjob == "")
|
||||
customjob = "Admin"
|
||||
return
|
||||
if(length(customsender) <= 0 || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
//sanitize text!!!
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = sanitize(customsender),
|
||||
"job" = sanitize(customjob),
|
||||
"message" = sanitize(custommessage),
|
||||
"emojis" = TRUE,
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[sanitize(custommessage)]\" to [signal.format_target()]", LOG_PDA)
|
||||
message = ""
|
||||
return
|
||||
// Do not check if it's blank yet
|
||||
// But do check if it's above our set limit (for people who manualy send hrefs at us!)
|
||||
if("sender" in params)
|
||||
var/S = params["sender"]
|
||||
if(length(S) > MAX_NAME_LEN)
|
||||
message = "FAILED: Job string too lengthy"
|
||||
return
|
||||
customsender = S
|
||||
return
|
||||
if("job" in params)
|
||||
var/J = params["job"]
|
||||
if(length(J) > 100)
|
||||
message = "FAILED: Job string too lengthy"
|
||||
return
|
||||
|
||||
customjob = J
|
||||
return
|
||||
if("message" in params)
|
||||
var/M = params["message"]
|
||||
if(length(M) > MAX_MESSAGE_LEN)
|
||||
message = "FAILED: Message string too lengthy"
|
||||
return
|
||||
custommessage = M
|
||||
return
|
||||
|
||||
if("recepient" in params)
|
||||
// Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && LAZYLEN(GLOB.PDAs) > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
return
|
||||
if("refresh")
|
||||
update_static_data(usr)
|
||||
|
||||
/obj/machinery/computer/message_monitor/attackby(obj/item/O, mob/living/user, params)
|
||||
if(istype(O, /obj/item/screwdriver) && (obj_flags & EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
if(istype(O, /obj/item/screwdriver) && CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
//Why this though, you should make it emag to a board level. (i wont do it)
|
||||
to_chat(user, "<span class='warning'>It is too hot to mess with!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
return
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='notice'>A no server error appears on the screen.</span>")
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
screen = 2
|
||||
ENABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.start()
|
||||
var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
|
||||
// Will help make emagging the console not so easy to get away with.
|
||||
MK.info += "<br><br><font color='red'>�%@%(*$%&(�&?*(%&�/{}</font>"
|
||||
var/time = 100 * length(linkedServer.decryptkey)
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), time)
|
||||
message = rebootmsg
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), (10 SECONDS) * length(linkedServer.decryptkey))
|
||||
//message = rebootmsg
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/message_monitor/New()
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
|
||||
/obj/machinery/computer/message_monitor/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/message_monitor/LateInitialize()
|
||||
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
|
||||
if(!linkedServer)
|
||||
for(var/obj/machinery/telecomms/message_server/S in GLOB.telecomms_list)
|
||||
linkedServer = S
|
||||
break
|
||||
|
||||
/obj/machinery/computer/message_monitor/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
//If the computer is being hacked or is emagged, display the reboot message.
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
message = rebootmsg
|
||||
var/dat = "<center><font color='blue'[message]</font></center>"
|
||||
|
||||
if(auth)
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='green'>\[Authenticated\]</font></a>	/"
|
||||
dat += " Server Power: <A href='?src=[REF(src)];active=1'>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
|
||||
else
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='red'>\[Unauthenticated\]</font></a>	/"
|
||||
dat += " Server Power: <u>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
|
||||
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
screen = 2
|
||||
else if(!auth || LINKED_SERVER_NONRESPONSIVE)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
|
||||
switch(screen)
|
||||
//Main menu
|
||||
if(0)
|
||||
//	 = TAB
|
||||
var/i = 0
|
||||
dat += "<dd><A href='?src=[REF(src)];find=1'>	[++i]. Link To A Server</a></dd>"
|
||||
if(auth)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
dat += "<dd><A>	ERROR: Server not found!</A><br></dd>"
|
||||
else
|
||||
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>	[++i]. View Message Logs </a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>	[++i]. View Request Console Logs </a></br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>	[++i]. Clear Message Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>	[++i]. Clear Request Console Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];pass=1'>	[++i]. Set Custom Key</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];msg=1'>	[++i]. Send Admin Message</a><br></dd>"
|
||||
else
|
||||
for(var/n = ++i; n <= optioncount; n++)
|
||||
dat += "<dd><font color='blue'>	[n]. ---------------</font><br></dd>"
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
|
||||
dat += "<dd><A href='?src=[REF(src)];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
|
||||
else
|
||||
dat += "<br>"
|
||||
|
||||
//Bottom message
|
||||
if(!auth)
|
||||
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
|
||||
else
|
||||
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
|
||||
|
||||
//Message Logs
|
||||
if(1)
|
||||
var/index = 0
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += "<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sender</th><th width='15%'>Recipient</th><th width='300px' word-wrap: break-word>Message</th></tr>"
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += "<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_logs=[REF(pda)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[pda.sender]</td><td width='15%'>[pda.recipient]</td><td width='300px'>[pda.message][pda.picture ? " <a href='byond://?src=[REF(pda)];photo=1'>(Photo)</a>":""]</td></tr>"
|
||||
dat += "</table>"
|
||||
//Hacking screen.
|
||||
if(2)
|
||||
if(isAI(user) || iscyborg(user))
|
||||
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
|
||||
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
|
||||
else
|
||||
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
|
||||
dat += {"01000010011100100111010101110100011001010010110<br>
|
||||
10110011001101111011100100110001101101001011011100110011<br>
|
||||
10010000001100110011011110111001000100000011100110110010<br>
|
||||
10111001001110110011001010111001000100000011010110110010<br>
|
||||
10111100100101110001000000100100101110100001000000111011<br>
|
||||
10110100101101100011011000010000001110100011000010110101<br>
|
||||
10110010100100000001100100011000000100000011100110110010<br>
|
||||
10110001101101111011011100110010001110011001000000110011<br>
|
||||
00110111101110010001000000110010101110110011001010111001<br>
|
||||
00111100100100000011000110110100001100001011100100110000<br>
|
||||
10110001101110100011001010111001000100000011101000110100<br>
|
||||
00110000101110100001000000111010001101000011001010010000<br>
|
||||
00111000001100001011100110111001101110111011011110111001<br>
|
||||
00110010000100000011010000110000101110011001011100010000<br>
|
||||
00100100101101110001000000111010001101000011001010010000<br>
|
||||
00110110101100101011000010110111001110100011010010110110<br>
|
||||
10110010100101100001000000111010001101000011010010111001<br>
|
||||
10010000001100011011011110110111001110011011011110110110<br>
|
||||
00110010100100000011000110110000101101110001000000111001<br>
|
||||
00110010101110110011001010110000101101100001000000111100<br>
|
||||
10110111101110101011100100010000001110100011100100111010<br>
|
||||
10110010100100000011010010110111001110100011001010110111<br>
|
||||
00111010001101001011011110110111001110011001000000110100<br>
|
||||
10110011000100000011110010110111101110101001000000110110<br>
|
||||
00110010101110100001000000111001101101111011011010110010<br>
|
||||
10110111101101110011001010010000001100001011000110110001<br>
|
||||
10110010101110011011100110010000001101001011101000010111<br>
|
||||
00010000001001101011000010110101101100101001000000111001<br>
|
||||
10111010101110010011001010010000001101110011011110010000<br>
|
||||
00110100001110101011011010110000101101110011100110010000<br>
|
||||
00110010101101110011101000110010101110010001000000111010<br>
|
||||
00110100001100101001000000111001001101111011011110110110<br>
|
||||
10010000001100100011101010111001001101001011011100110011<br>
|
||||
10010000001110100011010000110000101110100001000000111010<br>
|
||||
001101001011011010110010100101110"}
|
||||
|
||||
//Fake messages
|
||||
if(3)
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];Reset=1'>Reset</a></center><hr>"
|
||||
|
||||
dat += {"<table border='1' width='100%'>
|
||||
<tr><td width='20%'><A href='?src=[REF(src)];select=Sender'>Sender</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=RecJob'>Sender's Job</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=Recepient'>Recipient</a></td>
|
||||
<td width='300px' word-wrap: break-word><A href='?src=[REF(src)];select=Message'>Message</a></td></tr>"}
|
||||
//Sender - Sender's Job - Recepient - Message
|
||||
//Al Green- Your Dad - Your Mom - WHAT UP!?
|
||||
|
||||
dat += {"<tr><td width='20%'>[customsender]</td>
|
||||
<td width='20%'>[customjob]</td>
|
||||
<td width='20%'>[customrecepient ? customrecepient.owner : "NONE"]</td>
|
||||
<td width='300px'>[custommessage]</td></tr>"}
|
||||
dat += "</table><br><center><A href='?src=[REF(src)];select=Send'>Send</a>"
|
||||
|
||||
//Request Console Logs
|
||||
if(4)
|
||||
|
||||
var/index = 0
|
||||
/* data_rc_msg
|
||||
X - 5%
|
||||
var/rec_dpt = "Unspecified" //name of the person - 15%
|
||||
var/send_dpt = "Unspecified" //name of the sender- 15%
|
||||
var/message = "Blank" //transferred message - 300px
|
||||
var/stamp = "Unstamped" - 15%
|
||||
var/id_auth = "Unauthenticated" - 15%
|
||||
var/priority = "Normal" - 10%
|
||||
*/
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += {"<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sending Dep.</th><th width='15%'>Receiving Dep.</th>
|
||||
<th width='300px' word-wrap: break-word>Message</th><th width='15%'>Stamp</th><th width='15%'>ID Auth.</th><th width='15%'>Priority.</th></tr>"}
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += {"<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_requests=[REF(rc)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[rc.send_dpt]</td>
|
||||
<td width='15%'>[rc.rec_dpt]</td><td width='300px'>[rc.message]</td><td width='15%'>[rc.stamp]</td><td width='15%'>[rc.id_auth]</td><td width='15%'>[rc.priority]</td></tr>"}
|
||||
dat += "</table>"
|
||||
|
||||
message = defaultmsg
|
||||
var/datum/browser/popup = new(user, "hologram_console", name, 700, 700)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user)
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>")
|
||||
@@ -245,10 +364,11 @@
|
||||
var/currentKey = linkedServer.decryptkey
|
||||
to_chat(user, "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>")
|
||||
hacking = FALSE
|
||||
screen = 0 // Return the screen back to normal
|
||||
message = ""
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
|
||||
obj_flags &= ~EMAGGED
|
||||
DISABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
message = ""
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/ResetMessage()
|
||||
customsender = "System Administrator"
|
||||
@@ -256,199 +376,12 @@
|
||||
custommessage = "This is a test, please ignore."
|
||||
customjob = "Admin"
|
||||
|
||||
/obj/machinery/computer/message_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
//Authenticate
|
||||
if (href_list["auth"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
auth = FALSE
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Turn the server on/off.
|
||||
if (href_list["active"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.toggled = !linkedServer.toggled
|
||||
//Find a server
|
||||
if (href_list["find"])
|
||||
var/list/message_servers = list()
|
||||
for (var/obj/machinery/telecomms/message_server/M in GLOB.telecomms_list)
|
||||
message_servers += M
|
||||
|
||||
if(message_servers.len > 1)
|
||||
linkedServer = input(usr, "Please select a server.", "Select a server.", null) as null|anything in message_servers
|
||||
message = "<span class='alert'>NOTICE: Server selected.</span>"
|
||||
else if(message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
message = "<span class='notice'>NOTICE: Only Single Server Detected - Server selected.</span>"
|
||||
else
|
||||
message = noserver
|
||||
|
||||
//View the logs - KEY REQUIRED
|
||||
if (href_list["view_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 1
|
||||
|
||||
//Clears the logs - KEY REQUIRED
|
||||
if (href_list["clear_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.pda_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Clears the request console logs - KEY REQUIRED
|
||||
if (href_list["clear_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.rc_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Change the password - KEY REQUIRED
|
||||
if (href_list["pass"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
if(length(newkey) <= 3)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
|
||||
else if(length(newkey) > 16)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
|
||||
else if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Hack the Console to get the password
|
||||
if (href_list["hack"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
screen = 2
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
spawn(100*length(linkedServer.decryptkey))
|
||||
if(src && linkedServer && usr)
|
||||
BruteForce(usr)
|
||||
//Delete the log.
|
||||
if (href_list["delete_logs"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 1)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.pda_msgs -= locate(href_list["delete_logs"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Delete the request console log.
|
||||
if (href_list["delete_requests"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 4)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.rc_msgs -= locate(href_list["delete_requests"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Create a custom message
|
||||
if (href_list["msg"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 3
|
||||
//Fake messaging selection - KEY REQUIRED
|
||||
if (href_list["select"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
else
|
||||
switch(href_list["select"])
|
||||
|
||||
//Reset
|
||||
if("Reset")
|
||||
ResetMessage()
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = stripped_input(usr, "Please enter the sender's name.") || customsender
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
//Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && GLOB.PDAs.len > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = stripped_input(usr, "Please enter the sender's job.") || customjob
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = stripped_input(usr, "Please enter your message.") || custommessage
|
||||
|
||||
//Send message
|
||||
if("Send")
|
||||
if(isnull(customsender) || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
|
||||
if(isnull(customrecepient))
|
||||
message = "<span class='notice'>NOTICE: No recepient selected!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
if(isnull(custommessage) || custommessage == "")
|
||||
message = "<span class='notice'>NOTICE: No message entered!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = "[customsender]",
|
||||
"job" = "[customjob]",
|
||||
"message" = custommessage,
|
||||
"emojis" = TRUE,
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA)
|
||||
|
||||
|
||||
//Request Console Logs - KEY REQUIRED
|
||||
if(href_list["view_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 4
|
||||
|
||||
if (href_list["back"])
|
||||
screen = 0
|
||||
|
||||
return attack_hand(usr)
|
||||
|
||||
#undef LINKED_SERVER_NONRESPONSIVE
|
||||
|
||||
/obj/item/paper/monitorkey
|
||||
name = "monitor decryption key"
|
||||
|
||||
/obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server)
|
||||
..()
|
||||
if (server)
|
||||
if(server)
|
||||
print(server)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
else
|
||||
@@ -460,7 +393,7 @@
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
for (var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if (server.decryptkey)
|
||||
for(var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if(server.decryptkey)
|
||||
print(server)
|
||||
break
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
Telecomms monitor tracks the overall trafficing of a telecommunications network
|
||||
and displays a heirarchy of linked machines.
|
||||
@@ -10,117 +9,98 @@
|
||||
icon_screen = "comm_monitor"
|
||||
desc = "Monitors the details of the telecommunications network it's synced with."
|
||||
|
||||
var/screen = 0 // the screen number:
|
||||
var/list/machinelist = list() // the machines located by the computer
|
||||
var/obj/machinery/telecomms/SelectedMachine
|
||||
var/obj/machinery/telecomms/SelectedMachine = null
|
||||
|
||||
var/network = "NULL" // the network to probe
|
||||
var/notice = ""
|
||||
|
||||
var/temp = "" // temporary feedback messages
|
||||
circuit = /obj/item/circuitboard/computer/comm_monitor
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<TITLE>Telecommunications Monitor</TITLE><center><b>Telecommunications Monitor</b></center>"
|
||||
/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)
|
||||
|
||||
switch(screen)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "telemonitor", name, 575, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
data_out["network"] = network
|
||||
data_out["notice"] = notice
|
||||
|
||||
// --- Main Menu ---
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data)
|
||||
data_out["servers"] = sortList(data_out["servers"])
|
||||
|
||||
if(0)
|
||||
dat += "<br>[temp]<br><br>"
|
||||
dat += "<br>Current Network: <a href='?src=[REF(src)];network=1'>[network]</a><br>"
|
||||
if(machinelist.len)
|
||||
dat += "<br>Detected Network Entities:<ul>"
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
dat += "<li><a href='?src=[REF(src)];viewmachine=[T.id]'>[REF(T)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ul>"
|
||||
dat += "<br><a href='?src=[REF(src)];operation=release'>\[Flush Buffer\]</a>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];operation=probe'>\[Probe Network\]</a>"
|
||||
if(!SelectedMachine) //null is bad.
|
||||
data_out["selected"] = null //but in js, null is good.
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = SelectedMachine.name,
|
||||
id = SelectedMachine.id,
|
||||
status = SelectedMachine.on,
|
||||
traffic = SelectedMachine.traffic,
|
||||
netspeed = SelectedMachine.netspeed,
|
||||
freq_listening = SelectedMachine.freq_listening,
|
||||
long_range_link = SelectedMachine.long_range_link,
|
||||
ref = REF(SelectedMachine)
|
||||
)
|
||||
data_out["selected_servers"] = list()
|
||||
for(var/obj/machinery/telecomms/T in SelectedMachine.links)
|
||||
if(!T.hide)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["selected_servers"] += list(data)
|
||||
|
||||
return data_out
|
||||
|
||||
// --- Viewing Machine ---
|
||||
|
||||
if(1)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<center><a href='?src=[REF(src)];operation=mainmenu'>\[Main Menu\]</a></center>"
|
||||
dat += "<br>Current Network: [network]<br>"
|
||||
dat += "Selected Network Entity: [SelectedMachine.name] ([SelectedMachine.id])<br>"
|
||||
dat += "Linked Entities: <ol>"
|
||||
for(var/obj/machinery/telecomms/T in SelectedMachine.links)
|
||||
if(!T.hide)
|
||||
dat += "<li><a href='?src=[REF(src)];viewmachine=[T.id]'>[REF(T.id)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ol>"
|
||||
|
||||
|
||||
|
||||
user << browse(dat, "window=comm_monitor;size=575x400")
|
||||
onclose(user, "server_control")
|
||||
|
||||
temp = ""
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/Topic(href, href_list)
|
||||
/obj/machinery/computer/telecomms/monitor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("mainmenu")
|
||||
SelectedMachine = null
|
||||
notice = ""
|
||||
return
|
||||
if("release")
|
||||
machinelist = list()
|
||||
notice = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
notice = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
SelectedMachine = null
|
||||
machinelist = list()
|
||||
return
|
||||
if("probe")
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
notice = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["viewmachine"])
|
||||
screen = 1
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == href_list["viewmachine"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
|
||||
if("release")
|
||||
machinelist = list()
|
||||
screen = 0
|
||||
|
||||
if("mainmenu")
|
||||
screen = 0
|
||||
|
||||
if("probe")
|
||||
if(machinelist.len > 0)
|
||||
temp = "<font color = #D70B00>- FAILED: CANNOT PROBE WHEN BUFFER FULL -</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/T in urange(25, src))
|
||||
if(T.network == network)
|
||||
machinelist.Add(T)
|
||||
|
||||
if(!machinelist.len)
|
||||
temp = "<font color = #D70B00>- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -</font color>"
|
||||
else
|
||||
temp = "<font color = #336699>- [machinelist.len] ENTITIES LOCATED & BUFFERED -</font color>"
|
||||
|
||||
screen = 0
|
||||
|
||||
|
||||
if(href_list["network"])
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
else
|
||||
network = newnet
|
||||
screen = 0
|
||||
machinelist = list()
|
||||
temp = "<font color = #336699>- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -</font color>"
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/attackby()
|
||||
. = ..()
|
||||
updateUsrDialog()
|
||||
if(!LAZYLEN(machinelist))
|
||||
notice = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine")
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
var/temp = "" // output message
|
||||
|
||||
/obj/machinery/telecomms/attackby(obj/item/P, mob/user, params)
|
||||
|
||||
var/icon_closed = initial(icon_state)
|
||||
var/icon_open = "[initial(icon_state)]_o"
|
||||
|
||||
if(!on)
|
||||
icon_closed = "[initial(icon_state)]_off"
|
||||
icon_open = "[initial(icon_state)]_o_off"
|
||||
@@ -27,78 +27,240 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/telecomms/ui_interact(mob/user)
|
||||
. = ..()
|
||||
// You need a multitool to use this, or be silicon
|
||||
if(!hasSiliconAccessInArea(user))
|
||||
// istype returns false if the value is null
|
||||
if(!istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
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)
|
||||
if(!canInteract(user))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "teleinteract", "[name] Access", 520, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/telecomms/ui_data(mob/user)
|
||||
. = list() //cpypaste from the vending bus
|
||||
.["notice"] = temp
|
||||
.["multitool"] = FALSE
|
||||
var/obj/item/multitool/P = get_multitool(user)
|
||||
var/dat
|
||||
dat = "<font face = \"Courier\"><HEAD><TITLE>[name]</TITLE></HEAD><center><H3>[name] Access</H3></center>"
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<br>Power Status: <a href='?src=[REF(src)];input=toggle'>[toggled ? "On" : "Off"]</a>"
|
||||
if(on && toggled)
|
||||
if(id != "" && id)
|
||||
dat += "<br>Identification String: <a href='?src=[REF(src)];input=id'>[id]</a>"
|
||||
else
|
||||
dat += "<br>Identification String: <a href='?src=[REF(src)];input=id'>NULL</a>"
|
||||
dat += "<br>Network: <a href='?src=[REF(src)];input=network'>[network]</a>"
|
||||
dat += "<br>Prefabrication: [autolinkers.len ? "TRUE" : "FALSE"]"
|
||||
if(hide)
|
||||
dat += "<br>Shadow Link: ACTIVE</a>"
|
||||
if(P)
|
||||
.["multitool"] = TRUE
|
||||
.["multitool_buf"] = null //to clean the list!
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T))
|
||||
.["multitool_buf"] = list(
|
||||
name = T.name,
|
||||
id = T.id
|
||||
)
|
||||
|
||||
//Show additional options for certain machines.
|
||||
dat += Options_Menu()
|
||||
.["machine"] = list()
|
||||
.["machine"]["power"] = toggled
|
||||
.["machine"]["id"] = id
|
||||
.["machine"]["network"] = network
|
||||
.["machine"]["prefab"] = LAZYLEN(autolinkers) ? TRUE : FALSE
|
||||
.["machine"]["hidden"] = hide
|
||||
|
||||
dat += "<br>Linked Network Entities: <ol>"
|
||||
.["links"] = list()
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
if(T.hide && !hide)
|
||||
continue
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
.["links"] += list(data)
|
||||
|
||||
var/i = 0
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
i++
|
||||
if(T.hide && !hide)
|
||||
continue
|
||||
dat += "<li>[REF(T)] [T.name] ([T.id]) <a href='?src=[REF(src)];unlink=[i]'>\[X\]</a></li>"
|
||||
dat += "</ol>"
|
||||
.["freq_listening"] = freq_listening
|
||||
|
||||
dat += "<br>Filtering Frequencies: "
|
||||
/obj/machinery/telecomms/relay/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["machine"]["isrelay"] = TRUE
|
||||
.["machine"]["broadcast"] = broadcasting
|
||||
.["machine"]["receiving"] = receiving
|
||||
|
||||
i = 0
|
||||
if(length(freq_listening))
|
||||
for(var/x in freq_listening)
|
||||
i++
|
||||
if(i < length(freq_listening))
|
||||
dat += "[format_frequency(x)] GHz<a href='?src=[REF(src)];delete=[x]'>\[X\]</a>; "
|
||||
else
|
||||
dat += "[format_frequency(x)] GHz<a href='?src=[REF(src)];delete=[x]'>\[X\]</a>"
|
||||
else
|
||||
dat += "NONE"
|
||||
/obj/machinery/telecomms/bus/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["machine"]["isbus"] = TRUE
|
||||
.["machine"]["chang_frequency"] = change_frequency
|
||||
.["machine"]["chang_freq_value"] = change_freq_value
|
||||
|
||||
dat += "<br> <a href='?src=[REF(src)];input=freq'>\[Add Filter\]</a>"
|
||||
dat += "<hr>"
|
||||
|
||||
if(P)
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T))
|
||||
dat += "<br><br>MULTITOOL BUFFER: [T] ([T.id]) <a href='?src=[REF(src)];link=1'>\[Link\]</a> <a href='?src=[REF(src)];flush=1'>\[Flush\]"
|
||||
else
|
||||
dat += "<br><br>MULTITOOL BUFFER: <a href='?src=[REF(src)];buffer=1'>\[Add Machine\]</a>"
|
||||
|
||||
dat += "</font>"
|
||||
/obj/machinery/telecomms/ui_act(action, params, datum/tgui/ui)
|
||||
if(!canInteract(usr))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
temp = ""
|
||||
user << browse(dat, "window=tcommachine;size=520x500;can_resize=0")
|
||||
onclose(user, "tcommachine")
|
||||
return TRUE
|
||||
|
||||
switch(action)
|
||||
if("toggle")
|
||||
toggled = !toggled
|
||||
temp = "-% [src.name] has been [toggled ? "activated" : "deactivated"]. %-"
|
||||
update_power()
|
||||
return
|
||||
if("machine")
|
||||
if("id" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
//if the text is blank, return the id it was using
|
||||
var/newid = sanitize_text(reject_bad_text(params["id"]), id) // reject_bad_text can return null!
|
||||
if(length(newid) > 255)
|
||||
temp = "-% Too many characters in new id tag. %-"
|
||||
return
|
||||
temp = "-% New ID assigned: \"[newid]\". %-"
|
||||
id = newid
|
||||
return
|
||||
if("network" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
var/newnet = sanitize(sanitize_text(params["network"], network))
|
||||
if(length(newnet) > 15)
|
||||
temp = "-% Too many characters in new network tag. %-"
|
||||
return
|
||||
network = newnet
|
||||
links = list()
|
||||
temp = "-% New network tag assigned: \"[network]\" %-"
|
||||
return
|
||||
if("multitool")
|
||||
var/obj/item/multitool/P = get_multitool(usr)
|
||||
if("Link" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire buffer %-"
|
||||
return
|
||||
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(!istype(T) || T == src)
|
||||
temp = "-% Unable to acquire buffer %-"
|
||||
return
|
||||
|
||||
if(!(src in T.links))
|
||||
LAZYADD(T.links, src)
|
||||
|
||||
if(!(T in links))
|
||||
LAZYADD(links, T)
|
||||
temp = "-% Successfully linked with [REF(T)] [T.name] %-"
|
||||
|
||||
if("Flush" in params)
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire multitool %-"
|
||||
return
|
||||
|
||||
temp = "-% Buffer successfully flushed. %-"
|
||||
P.buffer = null
|
||||
|
||||
if("Add" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire multitool %-"
|
||||
return
|
||||
|
||||
P.buffer = src
|
||||
temp = "% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-"
|
||||
|
||||
if("unlink")
|
||||
var/obj/machinery/telecomms/T = locate(params["value"])
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(T))
|
||||
temp = "-% Unable to locate machine to unlink from, try again. %-"
|
||||
return
|
||||
|
||||
temp = "-% Removed [REF(T)] [T.name] from linked entities. %-"
|
||||
if(T.links) //lazyrem makes blank list null, which is good but some might cause runtime ee's
|
||||
T.links.Remove(src)
|
||||
links.Remove(T)
|
||||
if("freq")
|
||||
if("add" in params)
|
||||
var/newfreq = input("Specify a new frequency to filter (GHz). Decimals assigned automatically.", src.name, null) as null|num
|
||||
if(!canAccess(usr) || !newfreq || isnull(newfreq))
|
||||
return
|
||||
|
||||
if(findtext(num2text(newfreq), ".")) // did they not read the text?
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
|
||||
newfreq = sanitize_frequency(newfreq, TRUE) //sanitize
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
if(newfreq in freq_listening)
|
||||
temp = "-% Error: Frequency already filtered %-"
|
||||
return
|
||||
|
||||
LAZYADD(freq_listening, newfreq)
|
||||
temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-"
|
||||
|
||||
if("remove" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
var/x = text2num(params["remove"])
|
||||
temp = "-% Removed frequency filter [x] %-"
|
||||
freq_listening.Remove(x)
|
||||
|
||||
/obj/machinery/telecomms/relay/ui_act(action, params)
|
||||
..()
|
||||
switch(action)
|
||||
if("relay")
|
||||
if("broadcast" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
broadcasting = !broadcasting
|
||||
temp = "-% Broadcasting mode changed. %-"
|
||||
return
|
||||
if("receiving" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
receiving = !receiving
|
||||
temp = "-% Receiving mode changed. %-"
|
||||
|
||||
/obj/machinery/telecomms/bus/ui_act(action, params)
|
||||
..()
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if("toggle" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
change_frequency = !change_frequency
|
||||
return
|
||||
if("adjust" in params)
|
||||
var/newfreq = text2num(params["adjust"])
|
||||
if(!canAccess(usr) || !newfreq)
|
||||
return
|
||||
// this should return true, unless the href is handcrafted
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
|
||||
newfreq = sanitize_frequency(newfreq, TRUE)
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
|
||||
change_freq_value = newfreq
|
||||
temp = "-% New frequency to change to assigned: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
|
||||
// Check if the user can use it.
|
||||
/obj/machinery/telecomms/proc/canInteract(mob/user)
|
||||
if(hasSiliconAccessInArea(user) || istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
return TRUE
|
||||
return FALSE
|
||||
// Check if the user is nearby and has a multitool.
|
||||
/obj/machinery/telecomms/proc/canAccess(mob/user)
|
||||
if((canInteract(user) && in_range(user, src)) || hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// Returns a multitool from a user depending on their mobtype.
|
||||
|
||||
/obj/machinery/telecomms/proc/get_multitool(mob/user)
|
||||
|
||||
var/obj/item/multitool/P = null
|
||||
// Let's double check
|
||||
if(!hasSiliconAccessInArea(user) && istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
P = user.get_active_held_item()
|
||||
if(!canInteract(user))
|
||||
return null
|
||||
var/obj/item/multitool/P = user.get_active_held_item()
|
||||
// Is the ref not a null? and is it the actual type?
|
||||
if(istype(P))
|
||||
return P
|
||||
else if(isAI(user))
|
||||
var/mob/living/silicon/ai/U = user
|
||||
P = U.aiMulti
|
||||
@@ -106,170 +268,3 @@
|
||||
if(istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
P = user.get_active_held_item()
|
||||
return P
|
||||
|
||||
// Additional Options for certain machines. Use this when you want to add an option to a specific machine.
|
||||
// Example of how to use below.
|
||||
|
||||
/obj/machinery/telecomms/proc/Options_Menu()
|
||||
return ""
|
||||
|
||||
// The topic for Additional Options. Use this for checking href links for your specific option.
|
||||
// Example of how to use below.
|
||||
/obj/machinery/telecomms/proc/Options_Topic(href, href_list)
|
||||
return
|
||||
|
||||
// RELAY
|
||||
|
||||
/obj/machinery/telecomms/relay/Options_Menu()
|
||||
var/dat = ""
|
||||
dat += "<br>Broadcasting: <A href='?src=[REF(src)];broadcast=1'>[broadcasting ? "YES" : "NO"]</a>"
|
||||
dat += "<br>Receiving: <A href='?src=[REF(src)];receive=1'>[receiving ? "YES" : "NO"]</a>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/telecomms/relay/Options_Topic(href, href_list)
|
||||
|
||||
if(href_list["receive"])
|
||||
receiving = !receiving
|
||||
temp = "<font color = #666633>-% Receiving mode changed. %-</font color>"
|
||||
if(href_list["broadcast"])
|
||||
broadcasting = !broadcasting
|
||||
temp = "<font color = #666633>-% Broadcasting mode changed. %-</font color>"
|
||||
|
||||
// BUS
|
||||
|
||||
/obj/machinery/telecomms/bus/Options_Menu()
|
||||
var/dat = "<br>Change Signal Frequency: <A href='?src=[REF(src)];change_freq=1'>[change_frequency ? "YES ([change_frequency])" : "NO"]</a>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/telecomms/bus/Options_Topic(href, href_list)
|
||||
|
||||
if(href_list["change_freq"])
|
||||
|
||||
var/newfreq = input(usr, "Specify a new frequency for new signals to change to. Enter null to turn off frequency changing. Decimals assigned automatically.", src, network) as null|num
|
||||
if(canAccess(usr))
|
||||
if(newfreq)
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
if(newfreq < 10000)
|
||||
change_frequency = newfreq
|
||||
temp = "<font color = #666633>-% New frequency to change to assigned: \"[newfreq] GHz\" %-</font color>"
|
||||
else
|
||||
change_frequency = 0
|
||||
temp = "<font color = #666633>-% Frequency changing deactivated %-</font color>"
|
||||
|
||||
|
||||
/obj/machinery/telecomms/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!hasSiliconAccessInArea(usr))
|
||||
if(!istype(usr.get_active_held_item(), /obj/item/multitool))
|
||||
return
|
||||
|
||||
var/obj/item/multitool/P = get_multitool(usr)
|
||||
|
||||
if(href_list["input"])
|
||||
switch(href_list["input"])
|
||||
|
||||
if("toggle")
|
||||
|
||||
toggled = !toggled
|
||||
temp = "<font color = #666633>-% [src] has been [toggled ? "activated" : "deactivated"].</font color>"
|
||||
update_power()
|
||||
|
||||
|
||||
if("id")
|
||||
var/newid = reject_bad_text(stripped_input(usr, "Specify the new ID for this machine", src, id, MAX_MESSAGE_LEN))
|
||||
if(newid && canAccess(usr))
|
||||
id = newid
|
||||
temp = "<font color = #666633>-% New ID assigned: \"[id]\" %-</font color>"
|
||||
|
||||
if("network")
|
||||
var/newnet = stripped_input(usr, "Specify the new network for this machine. This will break all current links.", src, network)
|
||||
if(newnet && canAccess(usr))
|
||||
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #666633>-% Too many characters in new network tag %-</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
T.links.Remove(src)
|
||||
|
||||
network = newnet
|
||||
links = list()
|
||||
temp = "<font color = #666633>-% New network tag assigned: \"[network]\" %-</font color>"
|
||||
|
||||
|
||||
if("freq")
|
||||
var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num
|
||||
if(newfreq && canAccess(usr))
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "<font color = #FF0000>-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-</font color>"
|
||||
else
|
||||
if(!(newfreq in freq_listening) && newfreq < 10000)
|
||||
freq_listening.Add(newfreq)
|
||||
temp = "<font color = #666633>-% New frequency filter assigned: \"[newfreq] GHz\" %-</font color>"
|
||||
|
||||
if(href_list["delete"])
|
||||
|
||||
// changed the layout about to workaround a pesky runtime -- Doohl
|
||||
|
||||
var/x = text2num(href_list["delete"])
|
||||
temp = "<font color = #666633>-% Removed frequency filter [x] %-</font color>"
|
||||
freq_listening.Remove(x)
|
||||
|
||||
if(href_list["unlink"])
|
||||
|
||||
if(text2num(href_list["unlink"]) <= length(links))
|
||||
var/obj/machinery/telecomms/T = links[text2num(href_list["unlink"])]
|
||||
if(T)
|
||||
temp = "<font color = #666633>-% Removed [REF(T)] [T.name] from linked entities. %-</font color>"
|
||||
|
||||
// Remove link entries from both T and src.
|
||||
|
||||
if(T.links)
|
||||
T.links.Remove(src)
|
||||
links.Remove(T)
|
||||
|
||||
else
|
||||
temp = "<font color = #666633>-% Unable to locate machine to unlink from, try again. %-</font color>"
|
||||
|
||||
if(href_list["link"])
|
||||
|
||||
if(P)
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T) && T != src)
|
||||
if(!(src in T.links))
|
||||
T.links += src
|
||||
|
||||
if(!(T in links))
|
||||
links += T
|
||||
|
||||
temp = "<font color = #666633>-% Successfully linked with [REF(T)] [T.name] %-</font color>"
|
||||
|
||||
else
|
||||
temp = "<font color = #666633>-% Unable to acquire buffer %-</font color>"
|
||||
|
||||
if(href_list["buffer"])
|
||||
|
||||
P.buffer = src
|
||||
temp = "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>"
|
||||
|
||||
|
||||
if(href_list["flush"])
|
||||
|
||||
temp = "<font color = #666633>-% Buffer successfully flushed. %-</font color>"
|
||||
P.buffer = null
|
||||
|
||||
Options_Topic(href, href_list)
|
||||
|
||||
usr.set_machine(src)
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/telecomms/proc/canAccess(mob/user)
|
||||
if(hasSiliconAccessInArea(user) || in_range(user, src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
idle_power_usage = 50
|
||||
netspeed = 40
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/bus
|
||||
var/change_frequency = 0
|
||||
var/change_frequency = FALSE
|
||||
var/change_freq_value = 0
|
||||
|
||||
/obj/machinery/telecomms/bus/RefreshParts()
|
||||
idle_power_usage = 50
|
||||
@@ -28,8 +29,8 @@
|
||||
if(!istype(signal) || !is_freq_listening(signal))
|
||||
return
|
||||
|
||||
if(change_frequency && signal.frequency != FREQ_SYNDICATE)
|
||||
signal.frequency = change_frequency
|
||||
if(change_frequency && (change_freq_value && signal.frequency != FREQ_SYNDICATE))
|
||||
signal.frequency = change_freq_value
|
||||
|
||||
if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it
|
||||
// send to one linked processor unit
|
||||
|
||||
@@ -140,11 +140,16 @@
|
||||
..()
|
||||
if(href_list["photo"])
|
||||
var/mob/M = usr
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
M << browse("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>PDA Photo</title></head>" \
|
||||
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
|
||||
+ "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
|
||||
+ "</body></html>", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
|
||||
|
||||
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>"
|
||||
|
||||
var/datum/browser/popup = new(M, "pdaphoto", "PDA Photo", picture.psize_x, picture.psize_y)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
onclose(M, "pdaphoto")
|
||||
|
||||
/datum/data_rc_msg
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
totaltraffic += traffic // add current traffic to total traffic
|
||||
|
||||
// Delete particularly old logs
|
||||
if (log_entries.len >= 400)
|
||||
if(LAZYLEN(log_entries) >= 400) //[list].len is not safe
|
||||
log_entries.Cut(1, 2)
|
||||
|
||||
var/datum/comm_log_entry/log = new
|
||||
|
||||
@@ -117,9 +117,9 @@ GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
icon_state = "[initial(icon_state)]_off"
|
||||
|
||||
/obj/machinery/telecomms/proc/update_power()
|
||||
|
||||
if(toggled)
|
||||
if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off
|
||||
// if powered, on. if not powered, off. if too damaged, off
|
||||
if(CHECK_BITFIELD(stat, (BROKEN | NOPOWER | EMPED)))
|
||||
on = FALSE
|
||||
else
|
||||
on = TRUE
|
||||
@@ -137,11 +137,11 @@ GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
|
||||
/obj/machinery/telecomms/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
if(CHECK_BITFIELD(., EMP_PROTECT_SELF))
|
||||
return
|
||||
if(prob(100/severity))
|
||||
if(!(stat & EMPED))
|
||||
stat |= EMPED
|
||||
var/duration = (300 * 10)/severity
|
||||
if(prob(100 / severity))
|
||||
if(!CHECK_BITFIELD(stat, EMPED))
|
||||
ENABLE_BITFIELD(stat, EMPED)
|
||||
var/duration = (300 * 10) / severity
|
||||
spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot.
|
||||
stat &= ~EMPED
|
||||
DISABLE_BITFIELD(stat, EMPED)
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
var/insisting = 0
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
@@ -22,22 +19,116 @@
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
return
|
||||
|
||||
else if(is_special_character(user))
|
||||
to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
|
||||
|
||||
else if (!insisting)
|
||||
to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
|
||||
insisting++
|
||||
|
||||
else
|
||||
to_chat(user, "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
|
||||
if(is_special_character(user))
|
||||
to_chat(user, "You speak. [pick("I want power","Humanity is corrupt, mankind must be destroyed", "I want to rule the world","I want immortality")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. The Wish Granter, sensing the darkness in your heart, has given you limitless power, and it's all yours!")
|
||||
user.dna.add_mutation(HULK)
|
||||
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!
|
||||
to_chat(user, "Things around you feel slower!")
|
||||
charges--
|
||||
insisting = FALSE
|
||||
to_chat(user, "You have a very great feeling about this!")
|
||||
else
|
||||
to_chat(user, "The Wish Granter awaits your wish.")
|
||||
var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","The Station To Disappear","To Kill","Nothing")
|
||||
switch(wish)
|
||||
if("Power") //Gives infinite power in exchange for infinite power going off in your face!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, warping itself into a delaminating supermatter shard!")
|
||||
var/obj/item/stock_parts/cell/infinite/powah = new /obj/item/stock_parts/cell/infinite(get_turf(user))
|
||||
if(user.put_in_hands(powah))
|
||||
to_chat(user, "[powah] materializes into your hands!")
|
||||
else
|
||||
to_chat(user, "[powah] materializes onto the floor.")
|
||||
var/obj/machinery/power/supermatter_crystal/powerwish = new /obj/machinery/power/supermatter_crystal(loc)
|
||||
powerwish.damage = 700 //right at the emergency threshold
|
||||
powerwish.produces_gas = FALSE
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("Wealth") //Gives 1 million space bucks in exchange for being turned into gold!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, warping your body to match the greed in your heart.")
|
||||
new /obj/structure/closet/crate/trashcart/moneywish(loc)
|
||||
new /obj/structure/closet/crate/trashcart/moneywish(loc)
|
||||
user.set_species(/datum/species/golem/gold)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("The Station To Disappear") //teleports you to the station and makes you blind, making the station disappear for you!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is 'granted', but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your eyes to match the darkness in your heart.")
|
||||
user.dna.add_mutation(BLINDMUT)
|
||||
var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(eyes)
|
||||
eyes.applyOrganDamage(eyes.maxHealth)
|
||||
var/list/destinations = list()
|
||||
for(var/obj/item/beacon/B in GLOB.teleportbeacons)
|
||||
var/turf/T = get_turf(B)
|
||||
if(is_station_level(T.z))
|
||||
destinations += B
|
||||
var/chosen_beacon = pick(destinations)
|
||||
var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon))
|
||||
try_move_adjacent(J)
|
||||
playsound(src,'sound/effects/sparks4.ogg',50,1)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("To Kill") //Makes you kill things in exchange for rewards!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your wickedness, warping itself into a dastardly creature for you to kill! ...but it almost seems to reward you for this.")
|
||||
var/obj/item/melee/transforming/energy/sword/cx/killreward = new /obj/item/melee/transforming/energy/sword/cx(get_turf(user))
|
||||
if(user.put_in_hands(killreward))
|
||||
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!
|
||||
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
|
||||
killwish.health = killwish.maxHealth
|
||||
killwish.vine_grab_distance = 6
|
||||
killwish.melee_damage_upper = 30
|
||||
killwish.loot = list(/obj/item/dualsaber/hypereutactic)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("Nothing") //Makes the wish granter disappear
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>The Wish Granter vanishes from sight!</B>")
|
||||
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
|
||||
charges--
|
||||
insisting = FALSE
|
||||
qdel(src)
|
||||
|
||||
charges--
|
||||
insisting = 0
|
||||
//ITEMS THAT IT USES
|
||||
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
/obj/structure/closet/crate/trashcart/moneywish
|
||||
desc = "A heavy, metal trashcart with wheels. Filled with cash."
|
||||
name = "loaded trash cart"
|
||||
|
||||
to_chat(user, "You have a very bad feeling about this.")
|
||||
|
||||
return
|
||||
/obj/structure/closet/crate/trashcart/moneywish/PopulateContents() //25*20*1000=500,000
|
||||
for(var/i in 1 to 25)
|
||||
var/obj/item/stack/spacecash/c1000/lodsamoney = new /obj/item/stack/spacecash/c1000(src)
|
||||
lodsamoney.amount = lodsamoney.max_amount
|
||||
|
||||
@@ -62,18 +62,21 @@
|
||||
|
||||
/obj/mecha/combat/neovgre/process()
|
||||
..()
|
||||
if(GLOB.ratvar_awakens) // At this point only timley intervention by lord singulo could hople to stop the superweapon
|
||||
if(GLOB.ratvar_awakens) // At this point only timley intervention by lord singulo could hope to stop the superweapon
|
||||
cell.charge = INFINITY
|
||||
max_integrity = INFINITY
|
||||
obj_integrity = max_integrity
|
||||
CHECK_TICK //Just to be on the safe side lag wise
|
||||
else if(cell.charge < cell.maxcharge)
|
||||
for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src))
|
||||
var/delta = min(recharge_rate, cell.maxcharge - cell.charge)
|
||||
if (get_clockwork_power() <= delta)
|
||||
cell.charge += delta
|
||||
adjust_clockwork_power(-delta)
|
||||
CHECK_TICK
|
||||
else
|
||||
if(cell.charge < cell.maxcharge)
|
||||
for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src))
|
||||
var/delta = min(recharge_rate, cell.maxcharge - cell.charge)
|
||||
if (get_clockwork_power() >= delta)
|
||||
cell.charge += delta
|
||||
adjust_clockwork_power(-delta)
|
||||
if(obj_integrity < max_integrity && istype(loc, /turf/open/floor/clockwork))
|
||||
obj_integrity += min(max_integrity - obj_integrity, max_integrity / 200)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/mecha/combat/neovgre/Initialize()
|
||||
.=..()
|
||||
@@ -90,7 +93,7 @@
|
||||
energy_drain = 30
|
||||
name = "Aribter 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"
|
||||
fire_sound = 'sound/weapons/neovgre_laser.ogg'
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/can_attach(obj/mecha/combat/neovgre/M)
|
||||
if(istype(M))
|
||||
|
||||
@@ -388,7 +388,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
|
||||
var/output = ..()
|
||||
if(output)
|
||||
return "[output] \[[fuel]: [round(fuel.amount*fuel.mats_per_stack,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
return "[output] \[[fuel]: [round(fuel.amount*MINERAL_MATERIAL_AMOUNT,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/action(target)
|
||||
if(chassis)
|
||||
@@ -398,9 +398,9 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
|
||||
if(P.type == fuel.type && P.amount > 0)
|
||||
var/to_load = max(max_fuel - fuel.amount*fuel.mats_per_stack,0)
|
||||
var/to_load = max(max_fuel - fuel.amount*MINERAL_MATERIAL_AMOUNT,0)
|
||||
if(to_load)
|
||||
var/units = min(max(round(to_load / P.mats_per_stack),1),P.amount)
|
||||
var/units = min(max(round(to_load / MINERAL_MATERIAL_AMOUNT),1),P.amount)
|
||||
fuel.amount += units
|
||||
P.use(units)
|
||||
occupant_message("[units] unit\s of [fuel] successfully loaded.")
|
||||
@@ -454,7 +454,7 @@
|
||||
if(cur_charge < chassis.cell.maxcharge)
|
||||
use_fuel = fuel_per_cycle_active
|
||||
chassis.give_power(power_per_cycle)
|
||||
fuel.amount -= min(use_fuel/fuel.mats_per_stack,fuel.amount)
|
||||
fuel.amount -= min(use_fuel/MINERAL_MATERIAL_AMOUNT,fuel.amount)
|
||||
update_equip_info()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"Firefighter",
|
||||
"Odysseus",
|
||||
"Gygax",
|
||||
"Medical-Spec Gygax",
|
||||
"Durand",
|
||||
"H.O.N.K",
|
||||
"Phazon",
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
layer = BELOW_MOB_LAYER//icon draw layer
|
||||
infra_luminosity = 15 //byond implementation is bugged.
|
||||
force = 5
|
||||
flags_1 = HEAR_1
|
||||
flags_1 = HEAR_1|BLOCK_FACE_ATOM_1
|
||||
var/can_move = 0 //time of next allowed movement
|
||||
var/mob/living/carbon/occupant = null
|
||||
var/mob/living/occupant = null
|
||||
var/step_in = 10 //make a step in step_in/10 sec.
|
||||
var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South.
|
||||
var/dir_in = SOUTH //What direction will the mech face when entered/powered on? Defaults to South.
|
||||
var/normal_step_energy_drain = 10 //How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain.
|
||||
var/step_energy_drain = 10
|
||||
var/melee_energy_drain = 15
|
||||
@@ -495,6 +495,10 @@
|
||||
occupant_message("<span class='warning'>Air port connection teared off!</span>")
|
||||
mecha_log_message("Lost connection to gas port.")
|
||||
|
||||
/obj/mecha/setDir(newdir)
|
||||
. = ..()
|
||||
occupant?.setDir(newdir)
|
||||
|
||||
/obj/mecha/Process_Spacemove(var/movement_dir = 0)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
@@ -5,44 +5,42 @@
|
||||
var/base_icon
|
||||
var/looky_helpy = TRUE
|
||||
|
||||
/datum/component/construction/mecha/examine(mob/user)
|
||||
/datum/component/construction/mecha/examine(datum/source, mob/user, list/examine_list)
|
||||
. = ..()
|
||||
if(looky_helpy)
|
||||
switch(steps[index]["key"])
|
||||
if(TOOL_WRENCH)
|
||||
. += "<span class='notice'>The mech could be <b>wrenched</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech could be <b>wrenched</b> into place.</span>"
|
||||
if(TOOL_SCREWDRIVER)
|
||||
. += "<span class='notice'>The mech could be <b>screwed</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech could be <b>screwed</b> into place.</span>"
|
||||
if(TOOL_WIRECUTTER)
|
||||
. += "<span class='notice'>The mech wires could be <b>trimmed</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech wires could be <b>trimmed</b> into place.</span>"
|
||||
if(/obj/item/stack/cable_coil)
|
||||
. += "<span class='notice'>The mech could use some <b>wiring</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>wiring</b>.</span>"
|
||||
if(/obj/item/circuitboard)
|
||||
. += "<span class='notice'>The mech could use a type of<b>circuitboard</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a type of<b>circuitboard</b>.</span>"
|
||||
if(/obj/item/stock_parts/scanning_module)
|
||||
. += "<span class='notice'>The mech could use a <b>scanning stock part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>scanning stock part</b>.</span>"
|
||||
if(/obj/item/stock_parts/capacitor)
|
||||
. += "<span class='notice'>The mech could use a <b>power based stock part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>power based stock part</b>.</span>"
|
||||
if(/obj/item/stock_parts/cell)
|
||||
. += "<span class='notice'>The mech could use a <b>power source</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>power source</b>.</span>"
|
||||
if(/obj/item/stack/sheet/metal)
|
||||
. += "<span class='notice'>The mech could use some <b>sheets of metal</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>sheets of metal</b>.</span>"
|
||||
if(/obj/item/stack/sheet/plasteel)
|
||||
. += "<span class='notice'>The mech could use some <b>sheets of strong steel</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>sheets of strong steel</b>.</span>"
|
||||
if(/obj/item/bikehorn)
|
||||
. += "<span class='notice'>HONK IT!.</span>"
|
||||
examine_list += "<span class='notice'>HONK IT!.</span>"
|
||||
if(/obj/item/clothing/mask/gas/clown_hat)
|
||||
. += "<span class='notice'>GIVE IT CLOWN MAKEUP HONK!.</span>"
|
||||
examine_list += "<span class='notice'>GIVE IT CLOWN MAKEUP HONK!.</span>"
|
||||
if(/obj/item/clothing/shoes/clown_shoes)
|
||||
. += "<span class='notice'>GIVE IT GOOFY SHOES HONK HONK!.</span>"
|
||||
examine_list += "<span class='notice'>GIVE IT GOOFY SHOES HONK HONK!.</span>"
|
||||
if(/obj/item/mecha_parts/part)
|
||||
. += "<span class='notice'>The mech could use a mech <b>part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a mech <b>part</b>.</span>"
|
||||
if(/obj/item/stack/ore/bluespace_crystal)
|
||||
. += "<span class='notice'>The mech could use a <b>crystal</b> of sorts.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>crystal</b> of sorts.</span>"
|
||||
if(/obj/item/assembly/signaler/anomaly)
|
||||
. += "<span class='notice'>The mech could use a <b>anomaly</b> of sorts.</span>"
|
||||
else
|
||||
return
|
||||
examine_list += "<span class='notice'>The mech could use a <b>anomaly</b> of sorts.</span>"
|
||||
|
||||
/datum/component/construction/mecha/spawn_result()
|
||||
if(!result)
|
||||
@@ -644,6 +642,304 @@
|
||||
user.visible_message("[user] unfastens Gygax Armor Plates.", "<span class='notice'>You unfasten Gygax Armor Plates.</span>")
|
||||
return TRUE
|
||||
|
||||
//Begin Medigax
|
||||
/datum/component/construction/unordered/mecha_chassis/medigax
|
||||
result = /datum/component/construction/mecha/medigax
|
||||
steps = list(
|
||||
/obj/item/mecha_parts/part/medigax_torso,
|
||||
/obj/item/mecha_parts/part/medigax_left_arm,
|
||||
/obj/item/mecha_parts/part/medigax_right_arm,
|
||||
/obj/item/mecha_parts/part/medigax_left_leg,
|
||||
/obj/item/mecha_parts/part/medigax_right_leg,
|
||||
/obj/item/mecha_parts/part/medigax_head
|
||||
)
|
||||
|
||||
/datum/component/construction/mecha/medigax
|
||||
result = /obj/mecha/medical/medigax
|
||||
base_icon = "medigax"
|
||||
steps = list(
|
||||
//1
|
||||
list(
|
||||
"key" = TOOL_WRENCH,
|
||||
"desc" = "The hydraulic systems are disconnected."
|
||||
),
|
||||
|
||||
//2
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_WRENCH,
|
||||
"desc" = "The hydraulic systems are connected."
|
||||
),
|
||||
|
||||
//3
|
||||
list(
|
||||
"key" = /obj/item/stack/cable_coil,
|
||||
"amount" = 5,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "The hydraulic systems are active."
|
||||
),
|
||||
|
||||
//4
|
||||
list(
|
||||
"key" = TOOL_WIRECUTTER,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "The wiring is added."
|
||||
),
|
||||
|
||||
//5
|
||||
list(
|
||||
"key" = /obj/item/circuitboard/mecha/gygax/main,
|
||||
"action" = ITEM_DELETE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "The wiring is adjusted."
|
||||
),
|
||||
|
||||
//6
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Central control module is installed."
|
||||
),
|
||||
|
||||
//7
|
||||
list(
|
||||
"key" = /obj/item/circuitboard/mecha/gygax/peripherals,
|
||||
"action" = ITEM_DELETE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "Central control module is secured."
|
||||
),
|
||||
|
||||
//8
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Peripherals control module is installed."
|
||||
),
|
||||
|
||||
//9
|
||||
list(
|
||||
"key" = /obj/item/circuitboard/mecha/gygax/targeting,
|
||||
"action" = ITEM_DELETE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "Peripherals control module is secured."
|
||||
),
|
||||
|
||||
//10
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Weapon control module is installed."
|
||||
),
|
||||
|
||||
//11
|
||||
list(
|
||||
"key" = /obj/item/stock_parts/scanning_module,
|
||||
"action" = ITEM_MOVE_INSIDE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "Weapon control module is secured."
|
||||
),
|
||||
|
||||
//12
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Scanner module is installed."
|
||||
),
|
||||
|
||||
//13
|
||||
list(
|
||||
"key" = /obj/item/stock_parts/capacitor,
|
||||
"action" = ITEM_MOVE_INSIDE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "Scanner module is secured."
|
||||
),
|
||||
|
||||
//14
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Capacitor is installed."
|
||||
),
|
||||
|
||||
//15
|
||||
list(
|
||||
"key" = /obj/item/stock_parts/cell,
|
||||
"action" = ITEM_MOVE_INSIDE,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "Capacitor is secured."
|
||||
),
|
||||
|
||||
//16
|
||||
list(
|
||||
"key" = TOOL_SCREWDRIVER,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "The power cell is installed."
|
||||
),
|
||||
|
||||
//17
|
||||
list(
|
||||
"key" = /obj/item/stack/sheet/metal,
|
||||
"amount" = 5,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "The power cell is secured."
|
||||
),
|
||||
|
||||
//18
|
||||
list(
|
||||
"key" = TOOL_WRENCH,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "Internal armor is installed."
|
||||
),
|
||||
|
||||
//19
|
||||
list(
|
||||
"key" = TOOL_WELDER,
|
||||
"back_key" = TOOL_WRENCH,
|
||||
"desc" = "Internal armor is wrenched."
|
||||
),
|
||||
|
||||
//20
|
||||
list(
|
||||
"key" = /obj/item/mecha_parts/part/medigax_armor,
|
||||
"action" = ITEM_DELETE,
|
||||
"back_key" = TOOL_WELDER,
|
||||
"desc" = "Internal armor is welded."
|
||||
),
|
||||
|
||||
//21
|
||||
list(
|
||||
"key" = TOOL_WRENCH,
|
||||
"back_key" = TOOL_CROWBAR,
|
||||
"desc" = "External armor is installed."
|
||||
),
|
||||
|
||||
//22
|
||||
list(
|
||||
"key" = TOOL_WELDER,
|
||||
"back_key" = TOOL_WRENCH,
|
||||
"desc" = "External armor is wrenched."
|
||||
),
|
||||
|
||||
)
|
||||
|
||||
/datum/component/construction/mecha/medigax/action(datum/source, atom/used_atom, mob/user)
|
||||
return check_step(used_atom,user)
|
||||
|
||||
/datum/component/construction/mecha/medigax/custom_action(obj/item/I, mob/living/user, diff)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
switch(index)
|
||||
if(1)
|
||||
user.visible_message("[user] connects [parent] hydraulic systems", "<span class='notice'>You connect [parent] hydraulic systems.</span>")
|
||||
if(2)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] activates [parent] hydraulic systems.", "<span class='notice'>You activate [parent] hydraulic systems.</span>")
|
||||
else
|
||||
user.visible_message("[user] disconnects [parent] hydraulic systems", "<span class='notice'>You disconnect [parent] hydraulic systems.</span>")
|
||||
if(3)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] adds the wiring to [parent].", "<span class='notice'>You add the wiring to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] deactivates [parent] hydraulic systems.", "<span class='notice'>You deactivate [parent] hydraulic systems.</span>")
|
||||
if(4)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] adjusts the wiring of [parent].", "<span class='notice'>You adjust the wiring of [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the wiring from [parent].", "<span class='notice'>You remove the wiring from [parent].</span>")
|
||||
if(5)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] into [parent].", "<span class='notice'>You install [I] into [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] disconnects the wiring of [parent].", "<span class='notice'>You disconnect the wiring of [parent].</span>")
|
||||
if(6)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the mainboard.", "<span class='notice'>You secure the mainboard.</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the central control module from [parent].", "<span class='notice'>You remove the central computer mainboard from [parent].</span>")
|
||||
if(7)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] into [parent].", "<span class='notice'>You install [I] into [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the mainboard.", "<span class='notice'>You unfasten the mainboard.</span>")
|
||||
if(8)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the peripherals control module.", "<span class='notice'>You secure the peripherals control module.</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the peripherals control module from [parent].", "<span class='notice'>You remove the peripherals control module from [parent].</span>")
|
||||
if(9)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] into [parent].", "<span class='notice'>You install [I] into [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the peripherals control module.", "<span class='notice'>You unfasten the peripherals control module.</span>")
|
||||
if(10)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the weapon control module.", "<span class='notice'>You secure the weapon control module.</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the weapon control module from [parent].", "<span class='notice'>You remove the weapon control module from [parent].</span>")
|
||||
if(11)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] to [parent].", "<span class='notice'>You install [I] to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the weapon control module.", "<span class='notice'>You unfasten the weapon control module.</span>")
|
||||
if(12)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the scanner module.", "<span class='notice'>You secure the scanner module.</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the scanner module from [parent].", "<span class='notice'>You remove the scanner module from [parent].</span>")
|
||||
if(13)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] to [parent].", "<span class='notice'>You install [I] to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the scanner module.", "<span class='notice'>You unfasten the scanner module.</span>")
|
||||
if(14)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the capacitor.", "<span class='notice'>You secure the capacitor.</span>")
|
||||
else
|
||||
user.visible_message("[user] removes the capacitor from [parent].", "<span class='notice'>You remove the capacitor from [parent].</span>")
|
||||
if(15)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] into [parent].", "<span class='notice'>You install [I] into [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the capacitor.", "<span class='notice'>You unfasten the capacitor.</span>")
|
||||
if(16)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the power cell.", "<span class='notice'>You secure the power cell.</span>")
|
||||
else
|
||||
user.visible_message("[user] pries the power cell from [parent].", "<span class='notice'>You pry the power cell from [parent].</span>")
|
||||
if(17)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs the internal armor layer to [parent].", "<span class='notice'>You install the internal armor layer to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the power cell.", "<span class='notice'>You unfasten the power cell.</span>")
|
||||
if(18)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures the internal armor layer.", "<span class='notice'>You secure the internal armor layer.</span>")
|
||||
else
|
||||
user.visible_message("[user] pries internal armor layer from [parent].", "<span class='notice'>You pry internal armor layer from [parent].</span>")
|
||||
if(19)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] welds the internal armor layer to [parent].", "<span class='notice'>You weld the internal armor layer to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens the internal armor layer.", "<span class='notice'>You unfasten the internal armor layer.</span>")
|
||||
if(20)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] installs [I] to [parent].", "<span class='notice'>You install [I] to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] cuts the internal armor layer from [parent].", "<span class='notice'>You cut the internal armor layer from [parent].</span>")
|
||||
if(21)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] secures Gygax Armor Plates.", "<span class='notice'>You secure Medical Gygax Armor Plates.</span>")
|
||||
else
|
||||
user.visible_message("[user] pries Gygax Armor Plates from [parent].", "<span class='notice'>You pry Medical Gygax Armor Plates from [parent].</span>")
|
||||
if(22)
|
||||
if(diff==FORWARD)
|
||||
user.visible_message("[user] welds Gygax Armor Plates to [parent].", "<span class='notice'>You weld Medical Gygax Armor Plates to [parent].</span>")
|
||||
else
|
||||
user.visible_message("[user] unfastens Gygax Armor Plates.", "<span class='notice'>You unfasten Medical Gygax Armor Plates.</span>")
|
||||
return TRUE
|
||||
// End Medigax
|
||||
|
||||
/datum/component/construction/unordered/mecha_chassis/firefighter
|
||||
result = /datum/component/construction/mecha/firefighter
|
||||
steps = list(
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
/obj/mecha/attack_animal(mob/living/simple_animal/user)
|
||||
mecha_log_message("Attack by simple animal. Attacker - [user].", color="red")
|
||||
if(!user.melee_damage_upper && !user.obj_damage)
|
||||
user.emote("custom", message = "[user.friendly] [src].")
|
||||
user.emote("custom", message = "[user.friendly_verb_continuous] [src].")
|
||||
return 0
|
||||
else
|
||||
var/play_soundeffect = 1
|
||||
@@ -282,9 +282,9 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/mecha/attacked_by(obj/item/I, mob/living/user)
|
||||
/obj/mecha/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
mecha_log_message("Attacked by [I]. Attacker - [user]")
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/mecha/proc/mech_toxin_damage(mob/living/target)
|
||||
playsound(src, 'sound/effects/spray2.ogg', 50, 1)
|
||||
|
||||
@@ -129,6 +129,47 @@
|
||||
desc = "A set of armor plates designed for the Gygax. Designed to effectively deflect damage with a lightweight construction."
|
||||
icon_state = "gygax_armor"
|
||||
|
||||
///////// Medical Gygax
|
||||
|
||||
/obj/item/mecha_parts/chassis/medigax
|
||||
name = "\improper Medical Gygax chassis"
|
||||
construct_type = /datum/component/construction/unordered/mecha_chassis/medigax
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_torso
|
||||
name = "\improper Medical Gygax torso"
|
||||
desc = "A torso part of Gygax. Contains power unit, processing core and life support systems."
|
||||
icon_state = "medigax_harness"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_head
|
||||
name = "\improper Medical Gygax head"
|
||||
desc = "A Gygax head. Houses advanced surveillance and targeting sensors."
|
||||
icon_state = "medigax_head"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_left_arm
|
||||
name = "\improper Medical Gygax left arm"
|
||||
desc = "A Gygax left arm. Data and power sockets are compatible with most exosuit tools and weapons."
|
||||
icon_state = "medigax_l_arm"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_right_arm
|
||||
name = "\improper Medical Gygax right arm"
|
||||
desc = "A Gygax right arm. Data and power sockets are compatible with most exosuit tools and weapons."
|
||||
icon_state = "medigax_r_arm"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_left_leg
|
||||
name = "\improper Medical Gygax left leg"
|
||||
desc = "A Gygax left leg. Constructed with advanced servomechanisms and actuators to enable faster speed."
|
||||
icon_state = "medigax_l_leg"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_right_leg
|
||||
name = "\improper Medical Gygax right leg"
|
||||
desc = "A Gygax right leg. Constructed with advanced servomechanisms and actuators to enable faster speed."
|
||||
icon_state = "medigax_r_leg"
|
||||
|
||||
/obj/item/mecha_parts/part/medigax_armor
|
||||
gender = PLURAL
|
||||
name = "\improper Medical Gygax armor plates"
|
||||
desc = "A set of armor plates designed for the Gygax. Designed to effectively deflect damage with a lightweight construction."
|
||||
icon_state = "medigax_armor"
|
||||
|
||||
//////////// Durand
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
output_access_dialog(id_card, usr)
|
||||
|
||||
if(href_list["del_req_access"] && add_req_access)
|
||||
operation_req_access -= text2num(href_list["add_req_access"])
|
||||
operation_req_access -= text2num(href_list["del_req_access"])
|
||||
output_access_dialog(id_card, usr)
|
||||
|
||||
if(href_list["finish_req_access"])
|
||||
@@ -333,10 +333,13 @@
|
||||
send_byjax(occupant,"exosuit.browser","t_port_connection","[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port")
|
||||
|
||||
if(href_list["dna_lock"])
|
||||
if(occupant && !iscarbon(occupant))
|
||||
to_chat(occupant, "<span class='danger'> You do not have any DNA!</span>")
|
||||
if(!occupant)
|
||||
return
|
||||
dna_lock = occupant.dna.unique_enzymes
|
||||
var/mob/living/carbon/C = occupant
|
||||
if(!istype(C) || !C.dna)
|
||||
to_chat(C, "<span class='danger'> You do not have any DNA!</span>")
|
||||
return
|
||||
dna_lock = C.dna.unique_enzymes
|
||||
occupant_message("You feel a prick as the needle takes your DNA sample.")
|
||||
|
||||
if(href_list["reset_dna"])
|
||||
|
||||
@@ -125,6 +125,24 @@
|
||||
name = "\improper Dark Gygax wreckage"
|
||||
icon_state = "darkgygax-broken"
|
||||
|
||||
/obj/structure/mecha_wreckage/medigax
|
||||
name = "\improper Medical Gygax wreckage"
|
||||
icon_state = "medigax-broken"
|
||||
|
||||
/obj/structure/mecha_wreckage/medigax/Initialize()
|
||||
. = ..()
|
||||
var/list/parts = list(/obj/item/mecha_parts/part/medigax_torso,
|
||||
/obj/item/mecha_parts/part/medigax_head,
|
||||
/obj/item/mecha_parts/part/medigax_left_arm,
|
||||
/obj/item/mecha_parts/part/medigax_right_arm,
|
||||
/obj/item/mecha_parts/part/medigax_left_leg,
|
||||
/obj/item/mecha_parts/part/medigax_right_leg)
|
||||
for(var/i = 0; i < 2; i++)
|
||||
if(parts.len && prob(40))
|
||||
var/part = pick(parts)
|
||||
welder_salvage += part
|
||||
parts -= part
|
||||
|
||||
/obj/structure/mecha_wreckage/marauder
|
||||
name = "\improper Marauder wreckage"
|
||||
icon_state = "marauder-broken"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/obj/mecha/medical/medigax
|
||||
desc = "A Gygax with it's actuator overload stripped and a slick white paint scheme, for medical use, These exosuits are developed and produced by Vey-Med. (© All rights reserved)."
|
||||
name = "\improper Medical Gygax"
|
||||
icon_state = "medigax"
|
||||
step_in = 1.75 // a little faster than an odysseus
|
||||
max_temperature = 25000
|
||||
max_integrity = 250
|
||||
wreckage = /obj/structure/mecha_wreckage/odysseus
|
||||
armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
internal_damage_threshold = 35
|
||||
deflect_chance = 15
|
||||
step_energy_drain = 6
|
||||
infra_luminosity = 6
|
||||
|
||||
|
||||
/obj/mecha/medical/medigax/moved_inside(mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
hud.add_hud_to(H)
|
||||
|
||||
/obj/mecha/medical/medigax/go_out()
|
||||
if(isliving(occupant))
|
||||
var/mob/living/carbon/human/L = occupant
|
||||
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
hud.remove_hud_from(L)
|
||||
..()
|
||||
|
||||
/obj/mecha/medical/medigax/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
var/mob/living/brain/B = mmi_as_oc.brainmob
|
||||
hud.add_hud_to(B)
|
||||
@@ -49,7 +49,9 @@
|
||||
var/original_name
|
||||
desc = "A large piece of space-resistant printed paper."
|
||||
icon = 'icons/obj/contraband.dmi'
|
||||
plane = ABOVE_WALL_PLANE
|
||||
anchored = TRUE
|
||||
buildable_sign = FALSE //Cannot be unwrenched from a wall.
|
||||
var/ruined = FALSE
|
||||
var/random_basetype
|
||||
var/never_random = FALSE // used for the 'random' subclasses.
|
||||
@@ -68,6 +70,8 @@
|
||||
name = "poster - [name]"
|
||||
desc = "A large piece of space-resistant printed paper. [desc]"
|
||||
|
||||
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 300)), 0)
|
||||
|
||||
/obj/structure/sign/poster/proc/randomise(base_type)
|
||||
var/list/poster_types = subtypesof(base_type)
|
||||
var/list/approved_types = list()
|
||||
@@ -424,6 +428,11 @@
|
||||
desc = "A poster decipting a snake shaped into an ominous 'S'!"
|
||||
icon_state = "poster47"
|
||||
|
||||
/obj/structure/sign/poster/contraband/bountyhunters
|
||||
name = "Bounty Hunters"
|
||||
desc = "A poster advertising bounty hunting services. \"I hear you got a problem.\""
|
||||
icon_state = "poster48"
|
||||
|
||||
/obj/structure/sign/poster/official
|
||||
poster_item_name = "motivational poster"
|
||||
poster_item_desc = "An official Nanotrasen-issued poster to foster a compliant and obedient workforce. It comes with state-of-the-art adhesive backing, for easy pinning to any vertical surface."
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
|
||||
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
|
||||
var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one?
|
||||
var/beauty = 0
|
||||
|
||||
/obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases)
|
||||
. = ..()
|
||||
@@ -26,6 +27,8 @@
|
||||
if(LAZYLEN(diseases_to_add))
|
||||
AddComponent(/datum/component/infective, diseases_to_add)
|
||||
|
||||
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0)
|
||||
|
||||
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
|
||||
if(mergeable_decal)
|
||||
qdel(C)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
name = "xeno blood"
|
||||
desc = "It's green and acidic. It looks like... <i>blood?</i>"
|
||||
color = BLOOD_COLOR_XENO
|
||||
beauty = -250
|
||||
|
||||
/obj/effect/decal/cleanable/blood/splatter/xeno
|
||||
color = BLOOD_COLOR_XENO
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
blood_state = BLOOD_STATE_BLOOD
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
|
||||
if (C.blood_DNA)
|
||||
@@ -45,12 +46,14 @@
|
||||
icon_state = "tracks"
|
||||
desc = "They look like tracks left by wheels."
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
|
||||
name = "blood"
|
||||
icon_state = "ltrails_1"
|
||||
desc = "Your instincts say you shouldn't be following these."
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
var/list/existing_dirs = list()
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/update_icon()
|
||||
@@ -88,7 +91,7 @@
|
||||
var/mob/living/carbon/human/H = O
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
if(S && S.bloody_shoes[blood_state])
|
||||
if(color != bloodtype_to_color(S.last_bloodtype))
|
||||
if(color != S.last_blood_color)
|
||||
return
|
||||
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
|
||||
shoe_types |= S.type
|
||||
@@ -101,7 +104,7 @@
|
||||
var/mob/living/carbon/human/H = O
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
if(S && S.bloody_shoes[blood_state])
|
||||
if(color != bloodtype_to_color(S.last_bloodtype))//last entry - we check its color
|
||||
if(color != S.last_blood_color)//last entry - we check its color
|
||||
return
|
||||
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
|
||||
shoe_types |= S.type
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "Someone should clean that up."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "shards"
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/ash
|
||||
name = "ashes"
|
||||
@@ -10,6 +11,7 @@
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "ash"
|
||||
mergeable_decal = FALSE
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/ash/Initialize()
|
||||
. = ..()
|
||||
@@ -24,6 +26,7 @@
|
||||
/obj/effect/decal/cleanable/ash/large
|
||||
name = "large pile of ashes"
|
||||
icon_state = "big_ash"
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/ash/large/Initialize()
|
||||
. = ..()
|
||||
@@ -34,6 +37,7 @@
|
||||
desc = "Back to sand."
|
||||
icon = 'icons/obj/shards.dmi'
|
||||
icon_state = "tiny"
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/glass/Initialize()
|
||||
. = ..()
|
||||
@@ -52,6 +56,7 @@
|
||||
canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall)
|
||||
smooth = SMOOTH_FALSE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
beauty = -75
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize()
|
||||
. = ..()
|
||||
@@ -72,6 +77,10 @@
|
||||
desc = "It's still good. Four second rule!"
|
||||
icon_state = "flour"
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/dust
|
||||
name = "dust"
|
||||
desc = "A thin layer of dust coating the floor."
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow/ecto
|
||||
name = "ectoplasmic puddle"
|
||||
desc = "You know who to call."
|
||||
@@ -80,8 +89,11 @@
|
||||
/obj/effect/decal/cleanable/greenglow
|
||||
name = "glowing goo"
|
||||
desc = "Jeez. I hope that's not for lunch."
|
||||
light_power = 1
|
||||
light_range = 1
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
icon_state = "greenglow"
|
||||
beauty = -300
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -97,6 +109,7 @@
|
||||
layer = WALL_OBJ_LAYER
|
||||
icon_state = "cobweb1"
|
||||
resistance_flags = FLAMMABLE
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/cobweb/cobweb2
|
||||
icon_state = "cobweb2"
|
||||
@@ -108,10 +121,12 @@
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "molten"
|
||||
mergeable_decal = FALSE
|
||||
beauty = -150
|
||||
|
||||
/obj/effect/decal/cleanable/molten_object/large
|
||||
name = "big gooey grey mass"
|
||||
icon_state = "big_molten"
|
||||
beauty = -300
|
||||
|
||||
//Vomit (sorry)
|
||||
/obj/effect/decal/cleanable/vomit
|
||||
@@ -120,6 +135,7 @@
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "vomit_1"
|
||||
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
|
||||
beauty = -150
|
||||
|
||||
/obj/effect/decal/cleanable/vomit/attack_hand(mob/user)
|
||||
. = ..()
|
||||
@@ -152,6 +168,7 @@
|
||||
gender = NEUTER
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/plant_smudge
|
||||
name = "plant smudge"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
blood_state = BLOOD_STATE_OIL
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
mergeable_decal = FALSE
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases)
|
||||
. = ..()
|
||||
@@ -50,6 +51,7 @@
|
||||
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
|
||||
blood_state = BLOOD_STATE_OIL
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
beauty = -100
|
||||
|
||||
/obj/effect/decal/cleanable/oil/Initialize()
|
||||
. = ..()
|
||||
@@ -58,6 +60,7 @@
|
||||
|
||||
/obj/effect/decal/cleanable/oil/streak
|
||||
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/oil/slippery
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "Graffiti. Damn kids."
|
||||
icon = 'icons/effects/crayondecal.dmi'
|
||||
icon_state = "rune1"
|
||||
plane = GAME_PLANE //makes the graffiti visible over a wall.
|
||||
plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall.
|
||||
gender = NEUTER
|
||||
mergeable_decal = FALSE
|
||||
var/do_icon_rotate = TRUE
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
icon = 'icons/turf/decals.dmi'
|
||||
icon_state = "warningline"
|
||||
layer = TURF_DECAL_LAYER
|
||||
plane = ABOVE_WALL_PLANE
|
||||
|
||||
/obj/effect/turf_decal/Initialize()
|
||||
..()
|
||||
@@ -45,4 +46,4 @@
|
||||
var/turf/T = loc
|
||||
if(!istype(T)) //you know this will happen somehow
|
||||
CRASH("Turf decal initialized in an object/nullspace")
|
||||
T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha)
|
||||
T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha)
|
||||
|
||||
@@ -469,6 +469,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
|
||||
/obj/effect/landmark/stationroom
|
||||
var/list/templates = list()
|
||||
layer = BULLET_HOLE_LAYER
|
||||
plane = ABOVE_WALL_PLANE
|
||||
|
||||
/obj/effect/landmark/stationroom/New()
|
||||
..()
|
||||
|
||||
@@ -5,19 +5,21 @@
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "uglymine"
|
||||
var/triggered = 0
|
||||
/// We manually check to see if we've been triggered in case multiple atoms cross us in the time between the mine being triggered and it actually deleting, to avoid a race condition with multiple detonations
|
||||
var/triggered = FALSE
|
||||
|
||||
/obj/effect/mine/proc/mineEffect(mob/victim)
|
||||
to_chat(victim, "<span class='danger'>*click*</span>")
|
||||
|
||||
/obj/effect/mine/Crossed(AM as mob|obj)
|
||||
if(isturf(loc))
|
||||
if(ismob(AM))
|
||||
var/mob/MM = AM
|
||||
if(!(MM.movement_type & FLYING))
|
||||
triggermine(AM)
|
||||
else
|
||||
triggermine(AM)
|
||||
/obj/effect/mine/Crossed(atom/movable/AM)
|
||||
if(triggered || !isturf(loc))
|
||||
return
|
||||
. = ..()
|
||||
|
||||
if(AM.movement_type & FLYING)
|
||||
return
|
||||
|
||||
triggermine(AM)
|
||||
|
||||
/obj/effect/mine/proc/triggermine(mob/victim)
|
||||
if(triggered)
|
||||
@@ -27,9 +29,13 @@
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
mineEffect(victim)
|
||||
SEND_SIGNAL(src, COMSIG_MINE_TRIGGERED)
|
||||
triggered = 1
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir)
|
||||
. = ..()
|
||||
triggermine()
|
||||
|
||||
/obj/effect/mine/explosive
|
||||
name = "explosive mine"
|
||||
@@ -50,6 +56,18 @@
|
||||
if(isliving(victim))
|
||||
victim.DefaultCombatKnockdown(stun_time)
|
||||
|
||||
/obj/effect/mine/shrapnel
|
||||
name = "shrapnel mine"
|
||||
var/shrapnel_type = /obj/item/projectile/bullet/shrapnel
|
||||
var/shrapnel_magnitude = 3
|
||||
|
||||
/obj/effect/mine/shrapnel/mineEffect(mob/victim)
|
||||
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude)
|
||||
|
||||
/obj/effect/mine/shrapnel/sting
|
||||
name = "stinger mine"
|
||||
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball
|
||||
|
||||
/obj/effect/mine/kickmine
|
||||
name = "kick mine"
|
||||
|
||||
@@ -105,7 +123,7 @@
|
||||
/obj/effect/mine/pickup/triggermine(mob/victim)
|
||||
if(triggered)
|
||||
return
|
||||
triggered = 1
|
||||
triggered = TRUE
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
mineEffect(victim)
|
||||
qdel(src)
|
||||
@@ -128,14 +146,13 @@
|
||||
spawn(0)
|
||||
new /datum/hallucination/delusion(victim, TRUE, "demon",duration,0)
|
||||
|
||||
var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc)
|
||||
var/obj/item/chainsaw/doomslayer/chainsaw = new(victim.loc)
|
||||
victim.log_message("entered a blood frenzy", LOG_ATTACK)
|
||||
|
||||
ADD_TRAIT(chainsaw, TRAIT_NODROP, CHAINSAW_FRENZY_TRAIT)
|
||||
victim.drop_all_held_items()
|
||||
victim.put_in_hands(chainsaw, forced = TRUE)
|
||||
chainsaw.attack_self(victim)
|
||||
chainsaw.wield(victim)
|
||||
victim.reagents.add_reagent(/datum/reagent/medicine/adminordrazine,25)
|
||||
to_chat(victim, "<span class='warning'>KILL, KILL, KILL! YOU HAVE NO ALLIES ANYMORE, KILL THEM ALL!</span>")
|
||||
|
||||
|
||||
@@ -451,7 +451,7 @@
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
|
||||
//This is ment for "low" loot that anyone could fine in a toilet, for better gear use high loot toilet
|
||||
//This is meant for "low" loot that anyone could find in a toilet, for better gear use high loot toilet
|
||||
loot = list("" = 30,
|
||||
/obj/item/lighter = 2,
|
||||
/obj/item/tape/random = 1,
|
||||
@@ -476,7 +476,7 @@
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
|
||||
//This is ment for "prison" loot that is rather rare and ment for "prisoners if they get a crowbar to fine, or sec.
|
||||
//This is meant for "prison" loot that is rather rare and meant for "prisoners if they get a crowbar to fine, or sec.
|
||||
loot = list("" = 10,
|
||||
/obj/item/lighter = 5,
|
||||
/obj/item/poster/random_contraband = 5,
|
||||
@@ -491,7 +491,7 @@
|
||||
/obj/item/kitchen/knife = 5,
|
||||
/obj/item/screwdriver = 5,
|
||||
/obj/item/crowbar/red = 1, //Dont you need a crowbar to open this?
|
||||
/obj/item/stack/medical/bruise_pack = 3,
|
||||
/obj/item/stack/medical/suture = 3,
|
||||
/obj/item/reagent_containers/food/drinks/bottle/vodka = 2,
|
||||
/obj/item/radio = 5,
|
||||
/obj/item/flashlight = 4,
|
||||
@@ -611,13 +611,13 @@
|
||||
/obj/item/clothing/mask/breath = 5,
|
||||
/obj/item/clothing/mask/breath/medical = 1
|
||||
)
|
||||
|
||||
|
||||
/obj/effect/spawner/lootdrop/welder_tools/no_turf
|
||||
spawn_on_turf = FALSE
|
||||
|
||||
/obj/effect/spawner/lootdrop/low_tools/no_turf
|
||||
spawn_on_turf = FALSE
|
||||
|
||||
|
||||
/obj/effect/spawner/lootdrop/breathing_tanks/no_turf
|
||||
spawn_on_turf = FALSE
|
||||
|
||||
@@ -644,3 +644,76 @@
|
||||
|
||||
/obj/effect/spawner/lootdrop/glowstick/no_turf
|
||||
spawn_on_turf = FALSE
|
||||
|
||||
// Random Parts
|
||||
|
||||
/obj/effect/spawner/lootdrop/stock_parts
|
||||
name = "random stock parts spawner"
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/stock_parts/capacitor,
|
||||
/obj/item/stock_parts/scanning_module,
|
||||
/obj/item/stock_parts/manipulator,
|
||||
/obj/item/stock_parts/micro_laser,
|
||||
/obj/item/stock_parts/matter_bin,
|
||||
/obj/item/stock_parts/cell
|
||||
)
|
||||
|
||||
// Random Weapon Parts
|
||||
|
||||
/obj/effect/spawner/lootdrop/weapon_parts
|
||||
name = "random weapon parts spawner 50%"
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
loot = list("" = 50,
|
||||
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 13,
|
||||
/obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 13,
|
||||
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 12,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/weapon_parts
|
||||
name = "random weapon parts spawner 20%"
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
loot = list("" = 80,
|
||||
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 5,
|
||||
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 5,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/ammo
|
||||
name = "random ammo 75%"
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
loot = list("" = 25,
|
||||
/obj/item/ammo_box/magazine/wt550m9 = 1,
|
||||
/obj/item/ammo_casing/shotgun/buckshot = 7,
|
||||
/obj/item/ammo_casing/shotgun/rubbershot = 7,
|
||||
/obj/item/ammo_casing/a762 = 15,
|
||||
/obj/item/ammo_box/a762 = 15,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/ammo/fiftypercent
|
||||
name = "random ammo 50%"
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
loot = list("" = 50,
|
||||
/obj/item/ammo_box/magazine/wt550m9 = 2,
|
||||
/obj/item/ammo_casing/shotgun/buckshot = 10,
|
||||
/obj/item/ammo_casing/shotgun/rubbershot = 10,
|
||||
/obj/item/ammo_casing/a762 = 7,
|
||||
/obj/item/ammo_box/a762 = 7,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/ammo/shotgun
|
||||
name = "random ammo 50%"
|
||||
lootcount = 1
|
||||
spawn_on_turf = FALSE
|
||||
loot = list("" = 50,
|
||||
/obj/item/ammo_box/shotgun/loaded/buckshot = 5,
|
||||
/obj/item/ammo_box/shotgun/loaded/beanbag = 5,
|
||||
/obj/item/ammo_box/shotgun/loaded/incendiary = 5,
|
||||
/obj/item/ammo_casing/shotgun/buckshot = 8,
|
||||
/obj/item/ammo_casing/shotgun/rubbershot = 9,
|
||||
/obj/item/ammo_casing/shotgun = 8,
|
||||
/obj/item/ammo_casing/shotgun/incendiary = 10,
|
||||
)
|
||||
|
||||
@@ -24,6 +24,23 @@ again.
|
||||
name = "window spawner"
|
||||
spawn_list = list(/obj/structure/grille, /obj/structure/window/fulltile)
|
||||
dir = SOUTH
|
||||
var/electrochromatic
|
||||
var/electrochromatic_id
|
||||
|
||||
/obj/effect/spawner/structure/window/Initialize()
|
||||
. = ..()
|
||||
if(!electrochromatic)
|
||||
return
|
||||
if(!electrochromatic_id)
|
||||
stack_trace("Electrochromatic window spawner set without electromatic id.")
|
||||
return
|
||||
if(electrochromatic_id[1] == "!")
|
||||
electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id)
|
||||
for(var/obj/structure/window/W in get_turf(src))
|
||||
W.electrochromatic_id = electrochromatic_id
|
||||
W.make_electrochromatic()
|
||||
if(electrochromatic == ELECTROCHROMATIC_DIMMED)
|
||||
W.electrochromatic_dim()
|
||||
|
||||
/obj/effect/spawner/structure/window/hollow
|
||||
name = "hollow window spawner"
|
||||
@@ -140,13 +157,16 @@ again.
|
||||
spawn_list = list(/obj/structure/grille, /obj/structure/window/reinforced/spawner/north, /obj/structure/window/reinforced/spawner/west)
|
||||
. = ..()
|
||||
|
||||
//tinted
|
||||
//tinted and electrochromatic
|
||||
|
||||
/obj/effect/spawner/structure/window/reinforced/tinted
|
||||
name = "tinted reinforced window spawner"
|
||||
icon_state = "twindow_spawner"
|
||||
spawn_list = list(/obj/structure/grille, /obj/structure/window/reinforced/tinted/fulltile)
|
||||
|
||||
/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic
|
||||
name = "electrochromatic reinforced window spawner"
|
||||
electrochromatic = ELECTROCHROMATIC_DIMMED
|
||||
|
||||
//shuttle window
|
||||
|
||||
|
||||
@@ -95,6 +95,56 @@
|
||||
icon_state = "warden_gaze"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit
|
||||
name = "volt blast"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 8
|
||||
icon_state = "volt_hit"
|
||||
light_range = 1.5
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
var/mob/user
|
||||
var/damage = 20
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit/Initialize(mapload, caster)
|
||||
. = ..()
|
||||
user = caster
|
||||
if(user)
|
||||
var/matrix/M = new
|
||||
M.Turn(Get_Angle(src, user))
|
||||
transform = M
|
||||
INVOKE_ASYNC(src, .proc/volthit)
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit/proc/volthit()
|
||||
if(user)
|
||||
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
|
||||
var/hit_amount = 0
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/L in T)
|
||||
if(is_servant_of_ratvar(L))
|
||||
continue
|
||||
var/obj/item/I = L.anti_magic_check()
|
||||
if(I)
|
||||
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
|
||||
continue
|
||||
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
|
||||
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
|
||||
log_combat(user, L, "struck with a volt blast")
|
||||
hit_amount++
|
||||
for(var/obj/mecha/M in T)
|
||||
if(M.occupant)
|
||||
if(is_servant_of_ratvar(M.occupant))
|
||||
continue
|
||||
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
|
||||
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
|
||||
M.take_damage(damage, BURN, 0, 0)
|
||||
hit_amount++
|
||||
if(hit_amount)
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
|
||||
else
|
||||
playsound(src, "sparks", 50, 1)
|
||||
|
||||
/obj/effect/temp_visual/ratvar/ocular_warden/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-8, 8)
|
||||
|
||||
+236
-35
@@ -4,6 +4,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
// if true, everyone item when created will have its name changed to be
|
||||
// more... RPG-like.
|
||||
|
||||
GLOBAL_VAR_INIT(stickpocalypse, FALSE) // if true, all non-embeddable items will be able to harmlessly stick to people when thrown
|
||||
GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to embed in people, takes precedence over stickpocalypse
|
||||
|
||||
/obj/item
|
||||
name = "item"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
@@ -55,7 +58,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
|
||||
var/stagger_force
|
||||
|
||||
/**
|
||||
* Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by().
|
||||
* Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour
|
||||
* and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered.
|
||||
*/
|
||||
var/attack_delay_done = FALSE
|
||||
///next_move click/attack delay of this item.
|
||||
var/click_delay = CLICK_CD_MELEE
|
||||
|
||||
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
|
||||
var/current_equipped_slot
|
||||
pass_flags = PASSTABLE
|
||||
pressure_resistance = 4
|
||||
var/obj/item/master = null
|
||||
@@ -95,7 +108,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
|
||||
|
||||
var/datum/embedding_behavior/embedding
|
||||
var/list/embedding = NONE
|
||||
|
||||
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
|
||||
var/heat = 0
|
||||
@@ -132,15 +145,25 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
|
||||
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
|
||||
|
||||
/* Our block parry data. Should be set in init, or something if you are using it.
|
||||
* This won't be accessed without ITEM_CAN_BLOCK or ITEM_CAN_PARRY so do not set it unless you have to to save memory.
|
||||
* If you decide it's a good idea to leave this unset while turning the flags on, you will runtime. Enjoy.
|
||||
* If this is set to a path, it'll run get_block_parry_data(path). YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
*/
|
||||
var/datum/block_parry_data/block_parry_data
|
||||
|
||||
///Skills vars
|
||||
//list of skill PATHS exercised when using this item. An associated bitfield can be set to indicate additional ways the skill is used by this specific item.
|
||||
var/list/datum/skill/used_skills
|
||||
var/skill_difficulty = THRESHOLD_COMPETENT //how difficult it's to use this item in general.
|
||||
var/skill_difficulty = THRESHOLD_UNTRAINED //how difficult it's to use this item in general.
|
||||
var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item.
|
||||
|
||||
var/canMouseDown = FALSE
|
||||
|
||||
|
||||
/obj/item/Initialize()
|
||||
|
||||
if (attack_verb)
|
||||
if(attack_verb)
|
||||
attack_verb = typelist("attack_verb", attack_verb)
|
||||
|
||||
. = ..()
|
||||
@@ -148,9 +171,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
new path(src)
|
||||
actions_types = null
|
||||
|
||||
if(GLOB.rpg_loot_items)
|
||||
AddComponent(/datum/component/fantasy)
|
||||
|
||||
if(force_string)
|
||||
item_flags |= FORCE_STRING_OVERRIDE
|
||||
|
||||
@@ -160,15 +180,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
if(damtype == "brute")
|
||||
hitsound = "swing_hit"
|
||||
|
||||
if (!embedding)
|
||||
embedding = getEmbeddingBehavior()
|
||||
else if (islist(embedding))
|
||||
embedding = getEmbeddingBehavior(arglist(embedding))
|
||||
else if (!istype(embedding, /datum/embedding_behavior))
|
||||
stack_trace("Invalid type [embedding.type] found in .embedding during /obj/item Initialize()")
|
||||
|
||||
if(sharpness) //give sharp objects butchering functionality, for consistency
|
||||
AddComponent(/datum/component/butchering, 80 * toolspeed)
|
||||
if(used_skills)
|
||||
for(var/path in used_skills)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
LAZYADD(used_skills[path], S.skill_traits)
|
||||
|
||||
/obj/item/Destroy()
|
||||
item_flags &= ~DROPDEL //prevent reqdels
|
||||
@@ -179,6 +194,26 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
qdel(X)
|
||||
return ..()
|
||||
|
||||
/obj/item/ComponentInitialize()
|
||||
. = ..()
|
||||
|
||||
// this proc says it's for initializing components, but we're initializing elements too because it's you and me against the world >:)
|
||||
if(!LAZYLEN(embedding))
|
||||
if(GLOB.embedpocalypse)
|
||||
embedding = EMBED_POINTY
|
||||
name = "pointy [name]"
|
||||
else if(GLOB.stickpocalypse)
|
||||
embedding = EMBED_HARMLESS
|
||||
name = "sticky [name]"
|
||||
|
||||
updateEmbedding()
|
||||
|
||||
if(GLOB.rpg_loot_items)
|
||||
AddComponent(/datum/component/fantasy)
|
||||
|
||||
if(sharpness) //give sharp objects butchering functionality, for consistency
|
||||
AddComponent(/datum/component/butchering, 80 * toolspeed)
|
||||
|
||||
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
|
||||
if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside))
|
||||
return 0
|
||||
@@ -229,8 +264,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
if(resistance_flags & FIRE_PROOF)
|
||||
. += "[src] is made of fire-retardant materials."
|
||||
|
||||
|
||||
|
||||
if(item_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY))
|
||||
var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
|
||||
. += "[src] has the capacity to be used to block and/or parry. <a href='?src=[REF(data)];name=[name];block=[item_flags & ITEM_CAN_BLOCK];parry=[item_flags & ITEM_CAN_PARRY];render=1'>\[Show Stats\]</a>"
|
||||
|
||||
if(!user.research_scanner)
|
||||
return
|
||||
@@ -285,6 +321,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return
|
||||
if(anchored)
|
||||
return
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
|
||||
if(current_equipped_slot in user.check_obscured_slots())
|
||||
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
|
||||
return FALSE
|
||||
|
||||
if(resistance_flags & ON_FIRE)
|
||||
var/mob/living/carbon/C = user
|
||||
@@ -306,7 +346,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
C.update_damage_overlays()
|
||||
return
|
||||
|
||||
if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid.
|
||||
if(acid_level > 20 && ismob(loc))// so we can still remove the clothes on us that have acid.
|
||||
var/mob/living/carbon/C = user
|
||||
if(istype(C))
|
||||
if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
|
||||
@@ -349,6 +389,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return
|
||||
if(anchored)
|
||||
return
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
|
||||
if(current_equipped_slot in user.check_obscured_slots())
|
||||
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
SEND_SIGNAL(loc, COMSIG_TRY_STORAGE_TAKE, src, user.loc, TRUE)
|
||||
|
||||
@@ -392,6 +437,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/obj/item/proc/dropped(mob/user)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
current_equipped_slot = null
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.Remove(user)
|
||||
@@ -404,6 +451,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
// called just as an item is picked up (loc is not yet changed)
|
||||
/obj/item/proc/pickup(mob/user)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
|
||||
item_flags |= IN_INVENTORY
|
||||
|
||||
@@ -420,14 +468,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return usr.client.Click(src, src_location, src_control, params)
|
||||
var/list/directaccess = usr.DirectAccess() //This, specifically, is what requires the copypaste. If this were after the adjacency check, then it'd be impossible to use items in your inventory, among other things.
|
||||
//If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work.
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
if((C.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess))))
|
||||
if(!C.get_active_held_item())
|
||||
C.UnarmedAttack(src, TRUE)
|
||||
if(C.get_active_held_item() == src)
|
||||
melee_attack_chain(C, over)
|
||||
return TRUE //returning TRUE as a "is this overridden?" flag
|
||||
if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && ((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess))))
|
||||
if(!usr.get_active_held_item())
|
||||
usr.UnarmedAttack(src, TRUE)
|
||||
if(usr.get_active_held_item() == src)
|
||||
melee_attack_chain(usr, over)
|
||||
return TRUE //returning TRUE as a "is this overridden?" flag
|
||||
if(!Adjacent(usr) || !over.Adjacent(usr))
|
||||
return // should stop you from dragging through windows
|
||||
|
||||
@@ -440,7 +486,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
// for items that can be placed in multiple slots
|
||||
// note this isn't called during the initial dressing of a player
|
||||
/obj/item/proc/equipped(mob/user, slot)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
. = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
|
||||
current_equipped_slot = slot
|
||||
if(!(. & COMPONENT_NO_GRANT_ACTIONS))
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
@@ -466,11 +514,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
//if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise.
|
||||
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
|
||||
//Set disable_warning to TRUE if you wish it to not give you outputs.
|
||||
/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
|
||||
if(!M)
|
||||
return FALSE
|
||||
|
||||
return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self)
|
||||
return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self, clothing_check, return_warning)
|
||||
|
||||
/obj/item/verb/verb_pickup()
|
||||
set src in oview(1)
|
||||
@@ -605,6 +653,18 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
var/itempush = 1
|
||||
if(w_class < 4)
|
||||
itempush = 0 //too light to push anything
|
||||
if(isliving(hit_atom)) //Living mobs handle hit sounds differently.
|
||||
var/volume = get_volume_by_throwforce_and_or_w_class()
|
||||
if (throwforce > 0)
|
||||
if (throwhitsound)
|
||||
playsound(hit_atom, throwhitsound, volume, TRUE, -1)
|
||||
else if(hitsound)
|
||||
playsound(hit_atom, hitsound, volume, TRUE, -1)
|
||||
else
|
||||
playsound(hit_atom, 'sound/weapons/genhit.ogg',volume, TRUE, -1)
|
||||
else
|
||||
playsound(hit_atom, 'sound/weapons/throwtap.ogg', 1, volume, -1)
|
||||
|
||||
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
|
||||
|
||||
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
|
||||
@@ -736,6 +796,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
..()
|
||||
|
||||
/obj/item/proc/microwave_act(obj/machinery/microwave/M)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_MICROWAVE_ACT, M)
|
||||
if(istype(M) && M.dirty < 100)
|
||||
M.dirty++
|
||||
|
||||
@@ -782,14 +843,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
var/user = usr
|
||||
tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), timedelay, TIMER_STOPPABLE)//timer takes delay in deciseconds, but the pref is in milliseconds. dividing by 100 converts it.
|
||||
|
||||
/obj/item/MouseExited()
|
||||
/obj/item/MouseExited(location,control,params)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_MOUSE_EXIT, location, control, params)
|
||||
deltimer(tip_timer)//delete any in-progress timer if the mouse is moved off the item before it finishes
|
||||
closeToolTip(usr)
|
||||
|
||||
/obj/item/MouseEntered(location,control,params)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_MOUSE_ENTER, location, control, params)
|
||||
|
||||
// Called when a mob tries to use the item as a tool.
|
||||
// Handles most checks.
|
||||
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = 1, max_level = INFINITY)
|
||||
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = STD_USE_TOOL_MULT)
|
||||
// No delay means there is no start message, and no reason to call tool_start_check before use_tool.
|
||||
// Run the start check here so we wouldn't have to call it manually.
|
||||
if(!delay && !tool_start_check(user, amount))
|
||||
@@ -802,7 +866,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
if(delay)
|
||||
if(user.mind && used_skills)
|
||||
delay = user.mind.skill_holder.item_action_skills_mod(src, delay, skill_difficulty, SKILL_USE_TOOL, NONE, FALSE)
|
||||
delay = user.mind.item_action_skills_mod(src, delay, skill_difficulty, SKILL_USE_TOOL, null, FALSE)
|
||||
|
||||
// Create a callback with checks that would be called every tick by do_after.
|
||||
var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, amount, extra_checks)
|
||||
@@ -828,11 +892,14 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
if(delay >= MIN_TOOL_SOUND_DELAY)
|
||||
play_tool_sound(target, volume)
|
||||
|
||||
|
||||
if(user.mind && used_skills && skill_gain_mult)
|
||||
var/gain = skill_gain + delay/SKILL_GAIN_DELAY_DIVISOR
|
||||
for(var/skill in used_skills)
|
||||
if(!(used_skills[skill] & SKILL_TRAINING_TOOL))
|
||||
if(!(SKILL_TRAINING_TOOL in used_skills[skill]))
|
||||
continue
|
||||
user.mind.skill_holder.auto_gain_experience(skill, skill_gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
user.mind.auto_gain_experience(skill, gain*skill_gain_mult*S.item_skill_gain_multi)
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -893,11 +960,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
// if w_volume is 0 you fucked up anyways lol
|
||||
return w_volume || AUTO_SCALE_VOLUME(w_class)
|
||||
|
||||
/obj/item/proc/embedded(mob/living/carbon/human/embedded_mob)
|
||||
/obj/item/proc/embedded(atom/embedded_target)
|
||||
return
|
||||
|
||||
/obj/item/proc/unembedded()
|
||||
return
|
||||
if(item_flags & DROPDEL)
|
||||
QDEL_NULL(src)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Sets our slowdown and updates equipment slowdown of any mob we're equipped on.
|
||||
@@ -913,3 +982,135 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, slowdown))
|
||||
set_slowdown(var_value) //don't care if it's a duplicate edit as slowdown'll be set, do it anyways to force normal behavior.
|
||||
/**
|
||||
* Does the current embedding var meet the criteria for being harmless? Namely, does it explicitly define the pain multiplier and jostle pain mult to be 0? If so, return true.
|
||||
*
|
||||
*/
|
||||
/obj/item/proc/isEmbedHarmless()
|
||||
if(embedding)
|
||||
return !isnull(embedding["pain_mult"]) && !isnull(embedding["jostle_pain_mult"]) && embedding["pain_mult"] == 0 && embedding["jostle_pain_mult"] == 0
|
||||
|
||||
///In case we want to do something special (like self delete) upon failing to embed in something, return true
|
||||
/obj/item/proc/failedEmbed()
|
||||
if(item_flags & DROPDEL)
|
||||
QDEL_NULL(src)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
|
||||
|
||||
|
||||
* tryEmbed() is for when you want to try embedding something without dealing with the damage + hit messages of calling hitby() on the item while targetting the target.
|
||||
|
||||
|
||||
|
||||
*
|
||||
|
||||
|
||||
|
||||
* Really, this is used mostly with projectiles with shrapnel payloads, from [/datum/element/embed/proc/checkEmbedProjectile], and called on said shrapnel. Mostly acts as an intermediate between different embed elements.
|
||||
|
||||
|
||||
|
||||
*
|
||||
|
||||
|
||||
|
||||
* Arguments:
|
||||
|
||||
|
||||
|
||||
* * target- Either a body part, a carbon, or a closed turf. What are we hitting?
|
||||
|
||||
|
||||
|
||||
* * forced- Do we want this to go through 100%?
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/item/proc/tryEmbed(atom/target, forced=FALSE, silent=FALSE)
|
||||
|
||||
|
||||
|
||||
if(!isbodypart(target) && !iscarbon(target) && !isclosedturf(target))
|
||||
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
if(!forced && !LAZYLEN(embedding))
|
||||
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_EMBED_TRY_FORCE, target, forced, silent))
|
||||
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
failedEmbed()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///For when you want to disable an item's embedding capabilities (like transforming weapons and such), this proc will detach any active embed elements from it.
|
||||
|
||||
|
||||
|
||||
/obj/item/proc/disableEmbedding()
|
||||
|
||||
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_DISABLE_EMBED)
|
||||
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///For when you want to add/update the embedding on an item. Uses the vars in [/obj/item/embedding], and defaults to config values for values that aren't set. Will automatically detach previous embed elements on this item.
|
||||
|
||||
|
||||
|
||||
/obj/item/proc/updateEmbedding()
|
||||
if(!islist(embedding) || !LAZYLEN(embedding))
|
||||
return
|
||||
|
||||
AddElement(/datum/element/embed,\
|
||||
embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
|
||||
fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
|
||||
pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
|
||||
pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
|
||||
remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
|
||||
rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
|
||||
ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
|
||||
impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
|
||||
jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
|
||||
jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
|
||||
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
|
||||
embed_chance_turf_mod = (!isnull(embedding["embed_chance_turf_mod"]) ? embedding["embed_chance_turf_mod"] : EMBED_CHANCE_TURF_MOD))
|
||||
return TRUE
|
||||
@@ -143,8 +143,8 @@ RLD
|
||||
//if user can't be seen from A (only checks surroundings' opaqueness) and can't see A.
|
||||
//jarring, but it should stop people from targetting atoms they can't see...
|
||||
//excluding darkness, to allow RLD to be used to light pitch black dark areas.
|
||||
if(!((user in view(view_range, A)) || (user in viewers(view_range, A))))
|
||||
to_chat(user, "<span class='warning'>You focus, pointing \the [src] at whatever outside your field of vision in the given direction... to no avail.</span>")
|
||||
if(!((user in view(view_range, A)) || (user in fov_viewers(view_range, A))))
|
||||
to_chat(user, "<span class='warning'>You focus, pointing \the [src] at whatever outside your field of vision in that direction... to no avail.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -154,7 +154,8 @@ RLD
|
||||
icon_state = "rcd"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
custom_price = 900
|
||||
custom_price = PRICE_ABOVE_EXPENSIVE
|
||||
custom_premium_price = PRICE_ALMOST_ONE_GRAND
|
||||
max_matter = 160
|
||||
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
|
||||
has_ammobar = TRUE
|
||||
@@ -745,7 +746,7 @@ RLD
|
||||
if(istype(A, /obj/machinery/light/))
|
||||
if(checkResource(deconcost, user))
|
||||
to_chat(user, "<span class='notice'>You start deconstructing [A]...</span>")
|
||||
user.Beam(A,icon_state="nzcrentrs_power",time=15)
|
||||
user.Beam(A,icon_state="light_beam",time=15)
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
if(do_after(user, decondelay, target = A))
|
||||
if(!useResource(deconcost, user))
|
||||
@@ -759,7 +760,7 @@ RLD
|
||||
var/turf/closed/wall/W = A
|
||||
if(checkResource(floorcost, user))
|
||||
to_chat(user, "<span class='notice'>You start building a wall light...</span>")
|
||||
user.Beam(A,icon_state="nzcrentrs_power",time=15)
|
||||
user.Beam(A,icon_state="light_beam",time=15)
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 0)
|
||||
if(do_after(user, floordelay, target = A))
|
||||
@@ -805,7 +806,7 @@ RLD
|
||||
var/turf/open/floor/F = A
|
||||
if(checkResource(floorcost, user))
|
||||
to_chat(user, "<span class='notice'>You start building a floor light...</span>")
|
||||
user.Beam(A,icon_state="nzcrentrs_power",time=15)
|
||||
user.Beam(A,icon_state="light_beam",time=15)
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 1)
|
||||
if(do_after(user, floordelay, target = A))
|
||||
@@ -834,6 +835,12 @@ RLD
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/construction/rld/mini
|
||||
name = "mini-rapid-light-device (MRLD)"
|
||||
desc = "A device used to rapidly provide lighting sources to an area. Reload with metal, plasteel, glass or compressed matter cartridges."
|
||||
matter = 100
|
||||
max_matter = 100
|
||||
|
||||
/obj/item/rcd_upgrade
|
||||
name = "RCD advanced design disk"
|
||||
desc = "It seems to be empty."
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/item/twohanded/rcl
|
||||
/obj/item/rcl
|
||||
name = "rapid cable layer"
|
||||
desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables. Do not use without insulation!"
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
@@ -23,15 +23,26 @@
|
||||
var/datum/radial_menu/persistent/wiring_gui_menu
|
||||
var/mob/listeningTo
|
||||
|
||||
/obj/item/twohanded/rcl/Initialize()
|
||||
/obj/item/rcl/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
|
||||
update_icon()
|
||||
|
||||
/obj/item/twohanded/rcl/ComponentInitialize()
|
||||
/obj/item/rcl/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
AddComponent(/datum/component/two_handed)
|
||||
|
||||
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
|
||||
/// triggered on wield of two handed item
|
||||
/obj/item/rcl/proc/on_wield(obj/item/source, mob/user)
|
||||
active = TRUE
|
||||
|
||||
/// triggered on unwield of two handed item
|
||||
/obj/item/rcl/proc/on_unwield(obj/item/source, mob/user)
|
||||
active = FALSE
|
||||
|
||||
/obj/item/rcl/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
|
||||
@@ -86,26 +97,26 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/twohanded/rcl/examine(mob/user)
|
||||
/obj/item/rcl/examine(mob/user)
|
||||
. = ..()
|
||||
if(loaded)
|
||||
. += "<span class='info'>It contains [loaded.amount]/[max_amount] cables.</span>"
|
||||
|
||||
/obj/item/twohanded/rcl/Destroy()
|
||||
/obj/item/rcl/Destroy()
|
||||
QDEL_NULL(loaded)
|
||||
last = null
|
||||
listeningTo = null
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/rcl/update_icon_state()
|
||||
/obj/item/rcl/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
item_state = initial(item_state)
|
||||
if(!loaded || !loaded.amount)
|
||||
icon_state += "-empty"
|
||||
item_state += "-0"
|
||||
|
||||
/obj/item/twohanded/rcl/update_overlays()
|
||||
/obj/item/rcl/update_overlays()
|
||||
. = ..()
|
||||
if(!loaded || !loaded.amount)
|
||||
return
|
||||
@@ -113,7 +124,7 @@
|
||||
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
|
||||
. += cable_overlay
|
||||
|
||||
/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
|
||||
/obj/item/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE)
|
||||
. = ..()
|
||||
if(!isinhands || !(loaded?.amount))
|
||||
return
|
||||
@@ -121,7 +132,7 @@
|
||||
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
|
||||
. += cable_overlay
|
||||
|
||||
/obj/item/twohanded/rcl/proc/is_empty(mob/user, loud = 1)
|
||||
/obj/item/rcl/proc/is_empty(mob/user, loud = 1)
|
||||
update_icon()
|
||||
if(!loaded || !loaded.amount)
|
||||
if(loud)
|
||||
@@ -130,26 +141,23 @@
|
||||
QDEL_NULL(loaded)
|
||||
loaded = null
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
unwield(user)
|
||||
active = wielded
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/twohanded/rcl/pickup(mob/user)
|
||||
/obj/item/rcl/pickup(mob/user)
|
||||
..()
|
||||
getMobhook(user)
|
||||
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/dropped(mob/wearer)
|
||||
/obj/item/rcl/dropped(mob/wearer)
|
||||
..()
|
||||
UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED)
|
||||
listeningTo = null
|
||||
last = null
|
||||
|
||||
/obj/item/twohanded/rcl/attack_self(mob/user)
|
||||
/obj/item/rcl/attack_self(mob/user)
|
||||
..()
|
||||
active = wielded
|
||||
if(!active)
|
||||
last = null
|
||||
else if(!last)
|
||||
@@ -158,7 +166,7 @@
|
||||
last = C
|
||||
break
|
||||
|
||||
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
obj/item/rcl/proc/getMobhook(mob/to_hook)
|
||||
if(listeningTo == to_hook)
|
||||
return
|
||||
if(listeningTo)
|
||||
@@ -166,7 +174,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger)
|
||||
listeningTo = to_hook
|
||||
|
||||
/obj/item/twohanded/rcl/proc/trigger(mob/user)
|
||||
/obj/item/rcl/proc/trigger(mob/user)
|
||||
if(active)
|
||||
layCable(user)
|
||||
if(wiring_gui_menu) //update the wire options as you move
|
||||
@@ -174,7 +182,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
|
||||
|
||||
//previous contents of trigger(), lays cable each time the player moves
|
||||
/obj/item/twohanded/rcl/proc/layCable(mob/user)
|
||||
/obj/item/rcl/proc/layCable(mob/user)
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
if(is_empty(user, 0))
|
||||
@@ -207,7 +215,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
update_icon()
|
||||
|
||||
//searches the current tile for a stub cable of the same colour
|
||||
/obj/item/twohanded/rcl/proc/findLinkingCable(mob/user)
|
||||
/obj/item/rcl/proc/findLinkingCable(mob/user)
|
||||
var/turf/T
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
@@ -223,10 +231,8 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
continue
|
||||
if(C.d1 == 0)
|
||||
return C
|
||||
return
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiGenerateChoices(mob/user)
|
||||
/obj/item/rcl/proc/wiringGuiGenerateChoices(mob/user)
|
||||
var/fromdir = 0
|
||||
var/obj/structure/cable/linkingCable = findLinkingCable(user)
|
||||
if(linkingCable)
|
||||
@@ -243,12 +249,12 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
wiredirs[icondir] = img
|
||||
return wiredirs
|
||||
|
||||
/obj/item/twohanded/rcl/proc/showWiringGui(mob/user)
|
||||
/obj/item/rcl/proc/showWiringGui(mob/user)
|
||||
var/list/choices = wiringGuiGenerateChoices(user)
|
||||
|
||||
wiring_gui_menu = show_radial_menu_persistent(user, src , choices, select_proc = CALLBACK(src, .proc/wiringGuiReact, user), radius = 42)
|
||||
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiUpdate(mob/user)
|
||||
/obj/item/rcl/proc/wiringGuiUpdate(mob/user)
|
||||
if(!wiring_gui_menu)
|
||||
return
|
||||
|
||||
@@ -259,7 +265,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
|
||||
|
||||
//Callback used to respond to interactions with the wiring menu
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiReact(mob/living/user,choice)
|
||||
/obj/item/rcl/proc/wiringGuiReact(mob/living/user,choice)
|
||||
if(!choice) //close on a null choice (the center button)
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
return
|
||||
@@ -290,7 +296,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
|
||||
wiringGuiUpdate(user)
|
||||
|
||||
/obj/item/twohanded/rcl/ui_action_click(mob/user, action)
|
||||
/obj/item/rcl/ui_action_click(mob/user, action)
|
||||
if(istype(action, /datum/action/item_action/rcl_col))
|
||||
current_color_index++;
|
||||
if (current_color_index > colors.len)
|
||||
@@ -308,13 +314,13 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
else //open the menu
|
||||
showWiringGui(user)
|
||||
|
||||
/obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff
|
||||
/obj/item/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff
|
||||
loaded = new()
|
||||
loaded.max_amount = max_amount
|
||||
loaded.amount = max_amount
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/rcl/ghetto
|
||||
/obj/item/rcl/ghetto
|
||||
actions_types = list()
|
||||
max_amount = 30
|
||||
name = "makeshift rapid cable layer"
|
||||
|
||||
@@ -7,7 +7,7 @@ RSF
|
||||
name = "\improper Rapid-Service-Fabricator"
|
||||
desc = "A device used to rapidly deploy service items."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcd"
|
||||
icon_state = "rsf"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
opacity = 0
|
||||
@@ -110,7 +110,7 @@ RSF
|
||||
name = "Cookie Synthesizer"
|
||||
desc = "A self-recharging device used to rapidly deploy cookies."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcd"
|
||||
icon_state = "rsf"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
var/matter = 10
|
||||
|
||||
@@ -125,3 +125,112 @@
|
||||
user.put_in_hands(ink)
|
||||
to_chat(user, "<span class='notice'>You remove [ink] from [src].</span>")
|
||||
ink = null
|
||||
|
||||
|
||||
/obj/item/airlock_painter/decal
|
||||
name = "decal painter"
|
||||
desc = "An airlock painter, reprogramed to use a different style of paint in order to apply decals for floor tiles as well, in addition to repainting doors. Decals break when the floor tiles are removed. Alt-Click to change design."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "decal_sprayer"
|
||||
item_state = "decalsprayer"
|
||||
custom_materials = list(/datum/material/iron=2000, /datum/material/glass=500)
|
||||
var/stored_dir = 2
|
||||
var/stored_color = ""
|
||||
var/stored_decal = "warningline"
|
||||
var/stored_decal_total = "warningline"
|
||||
var/color_list = list("","red","white")
|
||||
var/dir_list = list(1,2,4,8)
|
||||
var/decal_list = list(list("Warning Line","warningline"),
|
||||
list("Warning Line Corner","warninglinecorner"),
|
||||
list("Caution Label","caution"),
|
||||
list("Directional Arrows","arrows"),
|
||||
list("Stand Clear Label","stand_clear"),
|
||||
list("Box","box"),
|
||||
list("Box Corner","box_corners"),
|
||||
list("Delivery Marker","delivery"),
|
||||
list("Warning Box","warn_full"))
|
||||
|
||||
/obj/item/airlock_painter/decal/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
var/turf/open/floor/F = target
|
||||
if(!proximity)
|
||||
to_chat(user, "<span class='notice'>You need to get closer!</span>")
|
||||
return
|
||||
if(use_paint(user) && isturf(F))
|
||||
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
|
||||
|
||||
/obj/item/airlock_painter/decal/attack_self(mob/user)
|
||||
if((ink) && (ink.charges >= 1))
|
||||
to_chat(user, "<span class='notice'>[src] beeps to prevent you from removing the toner until out of charges.</span>")
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/airlock_painter/decal/AltClick(mob/user)
|
||||
. = ..()
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/airlock_painter/decal/Initialize()
|
||||
. = ..()
|
||||
ink = new /obj/item/toner/large(src)
|
||||
|
||||
/obj/item/airlock_painter/decal/proc/update_decal_path()
|
||||
var/yellow_fix = "" //This will have to do until someone refactor's markings.dm
|
||||
if (stored_color)
|
||||
yellow_fix = "_"
|
||||
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
|
||||
return
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "decal_painter", name, 500, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["decal_direction"] = stored_dir
|
||||
data["decal_color"] = stored_color
|
||||
data["decal_style"] = stored_decal
|
||||
data["decal_list"] = list()
|
||||
data["color_list"] = list()
|
||||
data["dir_list"] = list()
|
||||
|
||||
for(var/i in decal_list)
|
||||
data["decal_list"] += list(list(
|
||||
"name" = i[1],
|
||||
"decal" = i[2]
|
||||
))
|
||||
for(var/j in color_list)
|
||||
data["color_list"] += list(list(
|
||||
"colors" = j
|
||||
))
|
||||
for(var/k in dir_list)
|
||||
data["dir_list"] += list(list(
|
||||
"dirs" = k
|
||||
))
|
||||
return data
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_act(action,list/params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
//Lists of decals and designs
|
||||
if("select decal")
|
||||
var/selected_decal = params["decals"]
|
||||
stored_decal = selected_decal
|
||||
if("select color")
|
||||
var/selected_color = params["colors"]
|
||||
stored_color = selected_color
|
||||
if("selected direction")
|
||||
var/selected_direction = text2num(params["dirs"])
|
||||
stored_dir = selected_direction
|
||||
update_decal_path()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/airlock_painter/decal/debug
|
||||
name = "extreme decal painter"
|
||||
icon_state = "decal_sprayer_ex"
|
||||
|
||||
/obj/item/airlock_painter/decal/debug/Initialize()
|
||||
. = ..()
|
||||
ink = new /obj/item/toner/extreme(src)
|
||||
@@ -58,18 +58,22 @@
|
||||
/obj/item/wallframe/proc/after_attach(var/obj/O)
|
||||
transfer_fingerprints_to(O)
|
||||
|
||||
/obj/item/wallframe/attackby(obj/item/W, mob/user, params)
|
||||
..()
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
// For camera-building borgs
|
||||
var/turf/T = get_step(get_turf(user), user.dir)
|
||||
if(iswallturf(T))
|
||||
T.attackby(src, user, params)
|
||||
/obj/item/wallframe/screwdriver_act(mob/user, obj/item/I)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
// For camera-building borgs
|
||||
var/turf/T = get_step(get_turf(user), user.dir)
|
||||
if(iswallturf(T))
|
||||
T.attackby(src, user)
|
||||
|
||||
/obj/item/wallframe/wrench_act(mob/user, obj/item/I)
|
||||
if(!custom_materials)
|
||||
return
|
||||
var/metal_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT)
|
||||
var/glass_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT)
|
||||
|
||||
if(istype(W, /obj/item/wrench) && (metal_amt || glass_amt))
|
||||
if(metal_amt || glass_amt)
|
||||
to_chat(user, "<span class='notice'>You dismantle [src].</span>")
|
||||
if(metal_amt)
|
||||
new /obj/item/stack/sheet/metal(get_turf(src), metal_amt)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/obj/item/binoculars
|
||||
name = "binoculars"
|
||||
desc = "Used for long-distance surveillance."
|
||||
item_state = "binoculars"
|
||||
icon_state = "binoculars"
|
||||
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/mob/listeningTo
|
||||
var/zoom_out_amt = 6
|
||||
var/zoom_amt = 10
|
||||
|
||||
/obj/item/binoculars/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
|
||||
|
||||
/obj/item/binoculars/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12)
|
||||
|
||||
/obj/item/binoculars/Destroy()
|
||||
listeningTo = null
|
||||
return ..()
|
||||
|
||||
/obj/item/binoculars/proc/on_wield(obj/item/source, mob/user)
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
|
||||
listeningTo = user
|
||||
user.visible_message("<span class='notice'>[user] holds [src] up to [user.p_their()] eyes.</span>", "<span class='notice'>You hold [src] up to your eyes.</span>")
|
||||
item_state = "binoculars_wielded"
|
||||
user.regenerate_icons()
|
||||
if(!user?.client)
|
||||
return
|
||||
var/client/C = user.client
|
||||
var/_x = 0
|
||||
var/_y = 0
|
||||
switch(user.dir)
|
||||
if(NORTH)
|
||||
_y = zoom_amt
|
||||
if(EAST)
|
||||
_x = zoom_amt
|
||||
if(SOUTH)
|
||||
_y = -zoom_amt
|
||||
if(WEST)
|
||||
_x = -zoom_amt
|
||||
C.change_view(world.view + zoom_out_amt)
|
||||
C.pixel_x = world.icon_size*_x
|
||||
C.pixel_y = world.icon_size*_y
|
||||
/obj/item/binoculars/proc/on_unwield(obj/item/source, mob/user)
|
||||
unwield(user)
|
||||
|
||||
/obj/item/binoculars/proc/unwield(mob/user)
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
|
||||
listeningTo = null
|
||||
user.visible_message("<span class='notice'>[user] lowers [src].</span>", "<span class='notice'>You lower [src].</span>")
|
||||
item_state = "binoculars"
|
||||
user.regenerate_icons()
|
||||
if(user && user.client)
|
||||
user.regenerate_icons()
|
||||
var/client/C = user.client
|
||||
C.change_view(CONFIG_GET(string/default_view))
|
||||
user.client.pixel_x = 0
|
||||
user.client.pixel_y = 0
|
||||
@@ -0,0 +1,69 @@
|
||||
/obj/item/broom
|
||||
name = "broom"
|
||||
desc = "This is my BROOMSTICK! It can be used manually or braced with two hands to sweep items as you move. It has a telescopic handle for compact storage."
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "broom0"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
|
||||
force = 8
|
||||
throwforce = 10
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
attack_verb = list("swept", "brushed off", "bludgeoned", "whacked")
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/broom/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
|
||||
|
||||
/obj/item/broom/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12, icon_wielded="broom1")
|
||||
|
||||
/obj/item/broom/update_icon_state()
|
||||
icon_state = "broom0"
|
||||
|
||||
/// triggered on wield of two handed item
|
||||
/obj/item/broom/proc/on_wield(obj/item/source, mob/user)
|
||||
to_chat(user, "<span class='notice'>You brace the [src] against the ground in a firm sweeping stance.</span>")
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/sweep)
|
||||
|
||||
/// triggered on unwield of two handed item
|
||||
/obj/item/broom/proc/on_unwield(obj/item/source, mob/user)
|
||||
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/obj/item/broom/afterattack(atom/A, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
sweep(user, A, FALSE)
|
||||
|
||||
/obj/item/broom/proc/sweep(mob/user, atom/A, moving = TRUE)
|
||||
var/turf/target
|
||||
if (!moving)
|
||||
if (isturf(A))
|
||||
target = A
|
||||
else
|
||||
target = A.loc
|
||||
else
|
||||
target = user.loc
|
||||
if (!isturf(target))
|
||||
return
|
||||
if (locate(/obj/structure/table) in target.contents)
|
||||
return
|
||||
var/i = 0
|
||||
for(var/obj/item/garbage in target.contents)
|
||||
if(!garbage.anchored)
|
||||
garbage.Move(get_step(target, user.dir), user.dir)
|
||||
i++
|
||||
if(i >= 20)
|
||||
break
|
||||
if(i >= 1)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 30, TRUE, -1)
|
||||
|
||||
/obj/item/broom/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) //bless you whoever fixes this copypasta
|
||||
J.put_in_cart(src, user)
|
||||
J.mybroom=src
|
||||
J.update_icon()
|
||||
@@ -83,7 +83,7 @@
|
||||
/obj/item/card/emag/bluespace
|
||||
name = "bluespace cryptographic sequencer"
|
||||
desc = "It's a blue card with a magnetic strip attached to some circuitry. It appears to have some sort of transmitter attached to it."
|
||||
color = rgb(40, 130, 255)
|
||||
icon_state = "emag_bs"
|
||||
prox_check = FALSE
|
||||
|
||||
/obj/item/card/emag/attack()
|
||||
@@ -166,6 +166,7 @@
|
||||
slot_flags = ITEM_SLOT_ID
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
var/id_type_name = "identification card"
|
||||
var/mining_points = 0 //For redeeming at mining equipment vendors
|
||||
var/list/access = list()
|
||||
var/registered_name = null // The name registered_name on the card
|
||||
@@ -174,6 +175,8 @@
|
||||
var/bank_support = ID_FREE_BANK_ACCOUNT
|
||||
var/datum/bank_account/registered_account
|
||||
var/obj/machinery/paystand/my_store
|
||||
var/uses_overlays = TRUE
|
||||
var/icon/cached_flat_icon
|
||||
|
||||
/obj/item/card/id/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -187,6 +190,15 @@
|
||||
if(ID_LOCKED_BANK_ACCOUNT)
|
||||
registered_account = new /datum/bank_account/remote/non_transferable(pick(GLOB.redacted_strings))
|
||||
|
||||
/obj/item/card/id/Destroy()
|
||||
if(bank_support == ID_LOCKED_BANK_ACCOUNT)
|
||||
QDEL_NULL(registered_account)
|
||||
else
|
||||
registered_account = null
|
||||
if(my_store)
|
||||
my_store.my_card = null
|
||||
my_store = null
|
||||
return ..()
|
||||
|
||||
/obj/item/card/id/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
@@ -311,20 +323,19 @@
|
||||
registered_account.bank_card_talk("<span class='warning'>ERROR: UNABLE TO LOGIN DUE TO SCHEDULED MAINTENANCE. MAINTENANCE IS SCHEDULED TO COMPLETE IN [(registered_account.withdrawDelay - world.time)/10] SECONDS.</span>", TRUE)
|
||||
return
|
||||
|
||||
var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num|null, 1)
|
||||
var/amount_to_remove = input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num|null
|
||||
|
||||
if(!amount_to_remove || amount_to_remove < 0)
|
||||
return
|
||||
if(!alt_click_can_use_id(user))
|
||||
return
|
||||
if(registered_account.adjust_money(-amount_to_remove))
|
||||
amount_to_remove = FLOOR(min(amount_to_remove, registered_account.account_balance), 1)
|
||||
if(amount_to_remove && registered_account.adjust_money(-amount_to_remove))
|
||||
var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
|
||||
user.put_in_hands(holochip)
|
||||
to_chat(user, "<span class='notice'>You withdraw [amount_to_remove] credits into a holochip.</span>")
|
||||
return
|
||||
else
|
||||
var/difference = amount_to_remove - registered_account.account_balance
|
||||
registered_account.bank_card_talk("<span class='warning'>ERROR: The linked account requires [difference] more credit\s to perform that withdrawal.</span>", TRUE)
|
||||
registered_account.bank_card_talk("<span class='warning'>ERROR: The linked account has no sufficient credits to perform that withdrawal.</span>", TRUE)
|
||||
|
||||
/obj/item/card/id/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -354,20 +365,38 @@
|
||||
/obj/item/card/id/RemoveID()
|
||||
return src
|
||||
|
||||
/*
|
||||
Usage:
|
||||
update_label()
|
||||
Sets the id name to whatever registered_name and assignment is
|
||||
/obj/item/card/id/update_overlays()
|
||||
. = ..()
|
||||
if(!uses_overlays)
|
||||
return
|
||||
cached_flat_icon = null
|
||||
var/job = assignment ? ckey(GetJobName()) : null
|
||||
if(registered_name == "Captain")
|
||||
job = "captain"
|
||||
if(registered_name && registered_name != "Captain")
|
||||
. += mutable_appearance(icon, "assigned")
|
||||
if(job)
|
||||
. += mutable_appearance(icon, "id[job]")
|
||||
|
||||
/obj/item/card/id/proc/get_cached_flat_icon()
|
||||
if(!cached_flat_icon)
|
||||
cached_flat_icon = getFlatIcon(src)
|
||||
return cached_flat_icon
|
||||
|
||||
|
||||
/obj/item/card/id/get_examine_string(mob/user, thats = FALSE)
|
||||
if(uses_overlays)
|
||||
return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" //displays all overlays in chat
|
||||
return ..()
|
||||
|
||||
update_label("John Doe", "Clowny")
|
||||
Properly formats the name and occupation and sets the id name to the arguments
|
||||
*/
|
||||
/obj/item/card/id/proc/update_label(newname, newjob)
|
||||
if(newname || newjob)
|
||||
name = "[(!newname) ? "identification card" : "[newname]'s ID Card"][(!newjob) ? "" : " ([newjob])"]"
|
||||
update_icon()
|
||||
return
|
||||
|
||||
name = "[(!registered_name) ? "identification card" : "[registered_name]'s ID Card"][(!assignment) ? "" : " ([assignment])"]"
|
||||
update_icon()
|
||||
|
||||
/obj/item/card/id/silver
|
||||
name = "silver identification card"
|
||||
@@ -380,6 +409,7 @@ update_label("John Doe", "Clowny")
|
||||
/obj/item/card/id/silver/reaper
|
||||
name = "Thirteen's ID Card (Reaper)"
|
||||
access = list(ACCESS_MAINT_TUNNELS)
|
||||
icon_state = "reaper"
|
||||
assignment = "Reaper"
|
||||
registered_name = "Thirteen"
|
||||
|
||||
@@ -531,7 +561,7 @@ update_label("John Doe", "Clowny")
|
||||
/obj/item/card/id/ert
|
||||
name = "\improper CentCom ID"
|
||||
desc = "An ERT ID card."
|
||||
icon_state = "centcom"
|
||||
icon_state = "ert_commander"
|
||||
registered_name = "Emergency Response Team Commander"
|
||||
assignment = "Emergency Response Team Commander"
|
||||
|
||||
@@ -540,6 +570,7 @@ update_label("John Doe", "Clowny")
|
||||
. = ..()
|
||||
|
||||
/obj/item/card/id/ert/Security
|
||||
icon_state = "ert_security"
|
||||
registered_name = "Security Response Officer"
|
||||
assignment = "Security Response Officer"
|
||||
|
||||
@@ -548,6 +579,7 @@ update_label("John Doe", "Clowny")
|
||||
. = ..()
|
||||
|
||||
/obj/item/card/id/ert/Engineer
|
||||
icon_state = "ert_engineer"
|
||||
registered_name = "Engineer Response Officer"
|
||||
assignment = "Engineer Response Officer"
|
||||
|
||||
@@ -556,6 +588,7 @@ update_label("John Doe", "Clowny")
|
||||
. = ..()
|
||||
|
||||
/obj/item/card/id/ert/Medical
|
||||
icon_state = "ert_medical"
|
||||
registered_name = "Medical Response Officer"
|
||||
assignment = "Medical Response Officer"
|
||||
|
||||
@@ -564,6 +597,7 @@ update_label("John Doe", "Clowny")
|
||||
. = ..()
|
||||
|
||||
/obj/item/card/id/ert/chaplain
|
||||
icon_state = "ert_chaplain"
|
||||
registered_name = "Religious Response Officer"
|
||||
assignment = "Religious Response Officer"
|
||||
|
||||
@@ -616,40 +650,49 @@ update_label("John Doe", "Clowny")
|
||||
. += "<span class='notice'>Your sentence is up! You're free!</span>"
|
||||
|
||||
/obj/item/card/id/prisoner/one
|
||||
icon_state = "prisoner_001"
|
||||
name = "Prisoner #13-001"
|
||||
registered_name = "Prisoner #13-001"
|
||||
|
||||
/obj/item/card/id/prisoner/two
|
||||
icon_state = "prisoner_002"
|
||||
name = "Prisoner #13-002"
|
||||
registered_name = "Prisoner #13-002"
|
||||
|
||||
/obj/item/card/id/prisoner/three
|
||||
icon_state = "prisoner_003"
|
||||
name = "Prisoner #13-003"
|
||||
registered_name = "Prisoner #13-003"
|
||||
|
||||
/obj/item/card/id/prisoner/four
|
||||
icon_state = "prisoner_004"
|
||||
name = "Prisoner #13-004"
|
||||
registered_name = "Prisoner #13-004"
|
||||
|
||||
/obj/item/card/id/prisoner/five
|
||||
icon_state = "prisoner_005"
|
||||
name = "Prisoner #13-005"
|
||||
registered_name = "Prisoner #13-005"
|
||||
|
||||
/obj/item/card/id/prisoner/six
|
||||
icon_state = "prisoner_006"
|
||||
name = "Prisoner #13-006"
|
||||
registered_name = "Prisoner #13-006"
|
||||
|
||||
/obj/item/card/id/prisoner/seven
|
||||
icon_state = "prisoner_007"
|
||||
name = "Prisoner #13-007"
|
||||
registered_name = "Prisoner #13-007"
|
||||
|
||||
/obj/item/card/id/mining
|
||||
name = "mining ID"
|
||||
icon_state = "retro"
|
||||
access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/away
|
||||
name = "a perfectly generic identification card"
|
||||
desc = "A perfectly generic identification card. Looks like it could use some flavor."
|
||||
icon_state = "retro"
|
||||
access = list(ACCESS_AWAY_GENERAL)
|
||||
|
||||
/obj/item/card/id/away/hotel
|
||||
@@ -692,6 +735,7 @@ update_label("John Doe", "Clowny")
|
||||
/obj/item/card/id/departmental_budget
|
||||
name = "departmental card (FUCK)"
|
||||
desc = "Provides access to the departmental budget."
|
||||
icon_state = "budgetcard"
|
||||
var/department_ID = ACCOUNT_CIV
|
||||
var/department_name = ACCOUNT_CIV_NAME
|
||||
|
||||
@@ -704,6 +748,7 @@ update_label("John Doe", "Clowny")
|
||||
B.bank_cards += src
|
||||
name = "departmental card ([department_name])"
|
||||
desc = "Provides access to the [department_name]."
|
||||
icon_state = "[lowertext(department_ID)]_budget"
|
||||
SSeconomy.dep_cards += src
|
||||
|
||||
/obj/item/card/id/departmental_budget/Destroy()
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
// CHAINSAW
|
||||
/obj/item/chainsaw
|
||||
name = "chainsaw"
|
||||
desc = "A versatile power tool. Useful for limbing trees and delimbing humans."
|
||||
icon_state = "chainsaw_off"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
force = 13
|
||||
var/force_on = 24
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
throwforce = 13
|
||||
throw_speed = 2
|
||||
throw_range = 4
|
||||
custom_materials = list(/datum/material/iron=13000)
|
||||
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
|
||||
hitsound = "swing_hit"
|
||||
sharpness = IS_SHARP
|
||||
actions_types = list(/datum/action/item_action/startchainsaw)
|
||||
tool_behaviour = TOOL_SAW
|
||||
toolspeed = 0.5
|
||||
var/on = FALSE
|
||||
var/wielded = FALSE // track wielded status on item
|
||||
|
||||
/obj/item/chainsaw/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
|
||||
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
|
||||
|
||||
/obj/item/chainsaw/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/chainsawhit.ogg', TRUE)
|
||||
AddComponent(/datum/component/two_handed, require_twohands=TRUE)
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
|
||||
/// triggered on wield of two handed item
|
||||
/obj/item/chainsaw/proc/on_wield(obj/item/source, mob/user)
|
||||
wielded = TRUE
|
||||
|
||||
/// triggered on unwield of two handed item
|
||||
/obj/item/chainsaw/proc/on_unwield(obj/item/source, mob/user)
|
||||
wielded = FALSE
|
||||
|
||||
/obj/item/chainsaw/suicide_act(mob/living/carbon/user)
|
||||
if(on)
|
||||
user.visible_message("<span class='suicide'>[user] begins to tear [user.p_their()] head off with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
playsound(src, 'sound/weapons/chainsawhit.ogg', 100, 1)
|
||||
var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(myhead)
|
||||
myhead.dismember()
|
||||
else
|
||||
user.visible_message("<span class='suicide'>[user] smashes [src] into [user.p_their()] neck, destroying [user.p_their()] esophagus! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
playsound(src, 'sound/weapons/genhit1.ogg', 100, 1)
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/chainsaw/attack_self(mob/user)
|
||||
on = !on
|
||||
to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]")
|
||||
force = on ? force_on : initial(force)
|
||||
throwforce = on ? force_on : force
|
||||
update_icon()
|
||||
var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
|
||||
butchering.butchering_enabled = on
|
||||
|
||||
if(on)
|
||||
hitsound = 'sound/weapons/chainsawhit.ogg'
|
||||
else
|
||||
hitsound = "swing_hit"
|
||||
|
||||
/obj/item/chainsaw/update_icon_state()
|
||||
icon_state = "chainsaw_[on ? "on" : "off"]"
|
||||
|
||||
/obj/item/chainsaw/get_dismemberment_chance()
|
||||
if(wielded)
|
||||
. = ..()
|
||||
|
||||
/obj/item/chainsaw/doomslayer
|
||||
name = "THE GREAT COMMUNICATOR"
|
||||
desc = "<span class='warning'>VRRRRRRR!!!</span>"
|
||||
armour_penetration = 100
|
||||
force_on = 30
|
||||
|
||||
/obj/item/chainsaw/doomslayer/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = 100
|
||||
return ..()
|
||||
|
||||
/obj/item/chainsaw/doomslayer/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
owner.visible_message("<span class='danger'>Ranged attacks just make [owner] angrier!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return ..()
|
||||
@@ -65,7 +65,7 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
|
||||
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(field)
|
||||
field_disconnect(field)
|
||||
..()
|
||||
|
||||
@@ -8,6 +8,9 @@ CIGARS
|
||||
SMOKING PIPES
|
||||
CHEAP LIGHTERS
|
||||
ZIPPO
|
||||
ROLLING PAPER
|
||||
VAPES
|
||||
BONGS
|
||||
|
||||
CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
*/
|
||||
@@ -506,7 +509,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
resistance_flags = FIRE_PROOF
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
|
||||
custom_price = 55
|
||||
custom_price = PRICE_ALMOST_CHEAP
|
||||
|
||||
/obj/item/lighter/Initialize()
|
||||
. = ..()
|
||||
@@ -616,6 +619,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
desc = "A cheap-as-free lighter."
|
||||
icon_state = "lighter"
|
||||
fancy = FALSE
|
||||
custom_price = PRICE_CHEAP_AS_FREE
|
||||
overlay_list = list(
|
||||
"transp",
|
||||
"tall",
|
||||
@@ -790,6 +794,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
reagents.clear_reagents()
|
||||
|
||||
/obj/item/clothing/mask/vape/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == SLOT_WEAR_MASK)
|
||||
if(!screw)
|
||||
to_chat(user, "<span class='notice'>You start puffing on the vape.</span>")
|
||||
@@ -799,6 +804,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
to_chat(user, "<span class='warning'>You need to close the cap first!</span>")
|
||||
|
||||
/obj/item/clothing/mask/vape/dropped(mob/user)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
name = "Security Cameras (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security
|
||||
|
||||
/obj/item/circuitboard/computer/security/shuttle
|
||||
name = "Shuttlelinking Security Cameras (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security/shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/xenobiology
|
||||
name = "circuit board (Xenobiology Console)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/xenobio
|
||||
@@ -112,9 +116,9 @@
|
||||
build_path = /obj/machinery/computer/cloning
|
||||
var/list/records = list()
|
||||
|
||||
/obj/item/circuitboard/computer/prototype_cloning
|
||||
/obj/item/circuitboard/computer/cloning/prototype
|
||||
name = "Prototype Cloning (Computer Board)"
|
||||
build_path = /obj/machinery/computer/prototype_cloning
|
||||
build_path = /obj/machinery/computer/cloning/prototype
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/battle
|
||||
name = "Arcade Battle (Computer Board)"
|
||||
@@ -293,6 +297,10 @@
|
||||
name = "Mining Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining
|
||||
|
||||
/obj/item/circuitboard/computer/snow_taxi
|
||||
name = "Snow Taxi (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/snow_taxi
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship
|
||||
name = "White Ship (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship
|
||||
@@ -375,3 +383,11 @@
|
||||
/obj/item/circuitboard/computer/nanite_cloud_controller
|
||||
name = "Nanite Cloud Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/nanite_cloud_controller
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/flight_control
|
||||
name = "Shuttle Flight Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/custom_shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/docker
|
||||
name = "Shuttle Navigation Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
|
||||
@@ -61,6 +61,14 @@
|
||||
name = "Experimental Clone Pod (Machine Board)"
|
||||
build_path = /obj/machinery/clonepod/experimental
|
||||
|
||||
/obj/item/circuitboard/machine/sheetifier
|
||||
name = "Sheet-meister 2000 (Machine Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/sheetifier
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/manipulator = 2,
|
||||
/obj/item/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/circuitboard/machine/abductor
|
||||
name = "alien board (Report This)"
|
||||
icon_state = "abductor_mod"
|
||||
@@ -692,6 +700,17 @@
|
||||
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/chem_dispenser/apothecary
|
||||
name = "Apotechary Chem Dispenser (Machine Board)"
|
||||
build_path = /obj/machinery/chem_dispenser/apothecary
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 1,
|
||||
/obj/item/stock_parts/capacitor = 1,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/obj/item/stock_parts/cell = 1)
|
||||
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/upgraded/plus)
|
||||
|
||||
/obj/item/circuitboard/machine/chem_dispenser/drinks
|
||||
name = "Soda Dispenser (Machine Board)"
|
||||
build_path = /obj/machinery/chem_dispenser/drinks
|
||||
@@ -707,6 +726,10 @@
|
||||
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/sleeper/party
|
||||
name = "Party Pod (Machine Board)"
|
||||
build_path = /obj/machinery/sleeper/party
|
||||
|
||||
/obj/item/circuitboard/machine/smoke_machine
|
||||
name = "Smoke Machine (Machine Board)"
|
||||
build_path = /obj/machinery/smoke_machine
|
||||
@@ -884,6 +907,16 @@
|
||||
name = "Departmental Protolathe - Service (Machine Board)"
|
||||
build_path = /obj/machinery/rnd/production/protolathe/department/service
|
||||
|
||||
/obj/item/circuitboard/machine/bepis
|
||||
name = "BEPIS Chamber (Machine Board)"
|
||||
build_path = /obj/machinery/rnd/bepis
|
||||
req_components = list(
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/capacitor = 1,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stock_parts/micro_laser = 1,
|
||||
/obj/item/stock_parts/scanning_module = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/techfab
|
||||
name = "\improper Techfab (Machine Board)"
|
||||
build_path = /obj/machinery/rnd/production/techfab
|
||||
@@ -1068,3 +1101,37 @@
|
||||
/obj/item/stock_parts/matter_bin = 3,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/hypnochair
|
||||
name = "Enhanced Interrogation Chamber (Machine Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/hypnochair
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stock_parts/scanning_module = 2
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine
|
||||
name = "Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine
|
||||
req_components = list()
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine/plasma
|
||||
name = "Plasma Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine/plasma
|
||||
req_components = list(/obj/item/stock_parts/capacitor = 2,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/micro_laser = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine/void
|
||||
name = "Void Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine/void
|
||||
req_components = list(/obj/item/stock_parts/capacitor/quadratic = 2,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/micro_laser/quadultra = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/heater
|
||||
name = "Electronic Engine Heater (Machine Board)"
|
||||
build_path = /obj/machinery/atmospherics/components/unary/shuttle/heater
|
||||
req_components = list(/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stock_parts/matter_bin = 1)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user