This commit is contained in:
Ghommie
2019-10-30 14:46:42 +01:00
2045 changed files with 85542 additions and 70698 deletions
+1 -1
View File
@@ -179,7 +179,7 @@
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
+2
View File
@@ -186,6 +186,7 @@ Class Procs:
if(isliving(A))
var/mob/living/L = A
L.update_canmove()
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
/obj/machinery/proc/can_be_occupant(atom/movable/am)
@@ -498,6 +499,7 @@ Class Procs:
/obj/machinery/Exited(atom/movable/AM, atom/newloc)
. = ..()
if (AM == occupant)
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
+8 -8
View File
@@ -80,7 +80,7 @@
popup.open()
/obj/machinery/autolathe/on_deconstruction()
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params)
@@ -164,7 +164,7 @@
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
busy = TRUE
use_power(power)
@@ -188,7 +188,7 @@
return
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
@@ -213,7 +213,7 @@
var/T = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
T += MB.rating*75000
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
@@ -262,7 +262,7 @@
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
if(ispath(D.build_path, /obj/item/stack))
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
@@ -294,7 +294,7 @@
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
if(ispath(D.build_path, /obj/item/stack))
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
@@ -309,7 +309,7 @@
return dat
/obj/machinery/autolathe/proc/materials_printout()
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
@@ -322,7 +322,7 @@
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
return FALSE
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
+361
View File
@@ -0,0 +1,361 @@
/obj/machinery/bloodbankgen
name = "blood bank generator"
desc = "Generates universally applicable synthetics for all blood types. Add regular blood to convert."
icon = 'icons/obj/bloodbank.dmi'
icon_state = "bloodbank-off"
density = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 80
circuit = /obj/item/circuitboard/machine/bloodbankgen
interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_ALLOW_SILICON
var/draining = FALSE
var/filling = FALSE
var/obj/item/reagent_containers/blood/bag = null
var/obj/item/reagent_containers/blood/outbag = null
var/bloodstored = 0
var/maxbloodstored = 1000
var/menustat = "menu"
var/efficiency = 0
var/productivity = 0
/obj/machinery/bloodbankgen/Initialize()
. = ..()
create_reagents(1000)
update_icon()
/obj/machinery/bloodbankgen/Destroy()
QDEL_NULL(bag)
QDEL_NULL(outbag)
return ..()
/obj/machinery/bloodbankgen/contents_explosion(severity, target)
..()
if(bag)
bag.ex_act(severity, target)
if(outbag)
outbag.ex_act(severity, target)
/obj/machinery/bloodbankgen/handle_atom_del(atom/A)
..()
if(A == bag)
bag = null
update_icon()
updateUsrDialog()
if(A == outbag)
outbag = null
update_icon()
updateUsrDialog()
/obj/machinery/bloodbankgen/RefreshParts()
var/E = 0
var/P = 0
for(var/obj/item/stock_parts/manipulator/M in component_parts)
E += M.rating
efficiency = E
productivity = P
/obj/machinery/bloodbankgen/update_icon()
cut_overlays()
if(is_operational())
icon_state = "bloodbank-on"
if(panel_open)
add_overlay("bloodbank-panel")
if(src.bag)
add_overlay("bloodbag-input")
if(bag.reagents.total_volume)
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "input-reagent")
var/percent = round((bag.reagents.total_volume / bag.volume) * 100)
switch(percent)
if(0 to 9)
filling_overlay.icon_state = "input-reagent0"
if(10 to 24)
filling_overlay.icon_state = "input-reagent10"
if(25 to 49)
filling_overlay.icon_state = "input-reagent25"
if(50 to 74)
filling_overlay.icon_state = "input-reagent50"
if(75 to 79)
filling_overlay.icon_state = "input-reagent75"
if(80 to 90)
filling_overlay.icon_state = "input-reagent80"
if(91 to INFINITY)
filling_overlay.icon_state = "input-reagent100"
filling_overlay.color = list(mix_color_from_reagents(bag.reagents.reagent_list))
add_overlay(filling_overlay)
if(src.outbag)
add_overlay("bloodbag-output")
if(outbag.reagents.total_volume)
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "output-reagent")
var/percent = round((outbag.reagents.total_volume / outbag.volume) * 100)
switch(percent)
if(0 to 9)
filling_overlay.icon_state = "output-reagent0"
if(10 to 24)
filling_overlay.icon_state = "output-reagent10"
if(25 to 49)
filling_overlay.icon_state = "output-reagent25"
if(50 to 74)
filling_overlay.icon_state = "output-reagent50"
if(75 to 79)
filling_overlay.icon_state = "output-reagent75"
if(80 to 90)
filling_overlay.icon_state = "output-reagent80"
if(91 to INFINITY)
filling_overlay.icon_state = "output-reagent100"
filling_overlay.color = list(mix_color_from_reagents(outbag.reagents.reagent_list))
add_overlay(filling_overlay)
return
/obj/machinery/bloodbankgen/process()
if(!is_operational())
return PROCESS_KILL
bloodstored = reagents.total_volume
var/transfer_amount = 20
if(draining)
if(reagents.total_volume >= reagents.maximum_volume)
draining = FALSE
return
if(bag)
if(bag.reagents.total_volume)
var/datum/reagent/blood/B = bag.reagents.has_reagent("blood")
if(B)
var/amount = reagents.maximum_volume - reagents.total_volume //monitor the machine's internal storage
amount = min(amount, transfer_amount)
if(!amount)
draining = FALSE
updateUsrDialog()
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
return
if(bag.blood_type == "SY") //no infinite loops using synthetics.
reagents.add_reagent("syntheticblood", amount)
else
reagents.add_reagent("syntheticblood", (amount+(5*efficiency)))
if(bag.reagents.total_volume >= amount)
bag.reagents.remove_reagent("blood", amount)
else
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
draining = FALSE
bag.update_icon()
update_icon()
updateUsrDialog()
else
draining = FALSE
updateUsrDialog()
return
if(filling)
if(!reagents || !reagents.total_volume)
filling = FALSE //there ain't anything in the machine yo.
return
if(outbag && outbag.reagents.total_volume < outbag.reagents.maximum_volume)
var/amount = outbag.reagents.maximum_volume - outbag.reagents.total_volume //monitor the output bag's internal storage
amount = min(amount, transfer_amount)
if(!amount)
filling = FALSE
visible_message("[src] pings.")
playsound(loc, 'sound/machines/beep.ogg', 50, 1)
updateUsrDialog()
return
reagents.trans_to(outbag, amount)
outbag.update_icon()
update_icon()
updateUsrDialog()
else
visible_message("[src] pings.")
playsound(loc, 'sound/machines/beep.ogg', 50, 1)
filling = FALSE
updateUsrDialog()
return
/obj/machinery/bloodbankgen/attackby(obj/item/O, mob/user, params)
if(user.a_intent == INTENT_HARM)
return ..()
if(default_deconstruction_screwdriver(user, "bloodbank-off", "bloodbank-off", O))
if(bag)
var/obj/item/reagent_containers/blood/B = bag
B.forceMove(drop_location())
bag = null
if(outbag)
var/obj/item/reagent_containers/blood/B = outbag
B.forceMove(drop_location())
outbag = null
update_icon()
return
if(default_deconstruction_crowbar(O))
return
if(istype(O, /obj/item/reagent_containers/blood))
. = 1 //no afterattack
if(!panel_open)
if(bag && outbag)
to_chat(user, "<span class='warning'>This machine already has bags attached.</span>")
if(!bag && !outbag)
var/choice = alert(user, "Choose where to place [O]", "", "Input", "Cancel", "Output")
switch(choice)
if("Cancel")
return FALSE
if("Input")
attachinput(O, user)
if("Output")
attachoutput(O, user)
else if(!bag)
attachinput(O, user)
else if(!outbag)
attachoutput(O, user)
else
to_chat(user, "<span class='warning'>Close the maintenance panel first.</span>")
return
else
to_chat(user, "<span class='warning'>You cannot put this in [src]!</span>")
/obj/machinery/bloodbankgen/ui_interact(mob/user)
. = ..()
if(!is_operational())
return
var/dat
switch(menustat)
if("noblood")
dat += "<div class='statusDisplay'>You do not have enough blood product to create synthetics.</div>"
menustat = "menu"
if("complete")
dat += "<div class='statusDisplay'>Operation complete.</div>"
menustat = "menu"
if("nobagspace")
dat += "<div class='statusDisplay'>Not enough space left in container. Please replace receptical.</div>"
menustat = "menu"
dat+= "<br><B>Current Synthetics stockpile: [reagents.total_volume] units.</B><HR>"
dat += "<br>Supply Bag<HR>"
if(bag)
dat += "<br>Current Capacity: [bag.reagents.total_volume] of [bag.reagents.maximum_volume]"
if(bag.reagents && bag.reagents.total_volume)
dat += "<br><a href='?src=\ref[src];activateinput=1'>Drain</a>"
dat += "<br><a href='?src=\ref[src];detachinput=1'>Detach</a>"
dat += "<br><br>Synthetics Bag<HR>"
if(outbag)
dat += "<br>Current Capacity:[outbag.reagents.total_volume] of [outbag.reagents.maximum_volume]"
if(!(outbag.reagents.total_volume >= outbag.reagents.maximum_volume))
dat += "<br><a href='?src=\ref[src];activateoutput=1'>Fill</a>"
dat += "<br><a href='?src=\ref[src];detachoutput=1'>Detach</a>"
if(!bag && !outbag)
dat += "<div class='statusDisplay'>No containers inside, please insert container.</div>"
var/datum/browser/popup = new(user, "bloodbankgen", name, 350, 520)
popup.set_content(dat)
popup.open()
/obj/machinery/bloodbankgen/proc/activateinput()
if(bag)
draining = TRUE
update_icon()
else
to_chat(usr, "<span class='warning'>There is no blood bag in the input slot.</span>")
return
/obj/machinery/bloodbankgen/proc/activateoutput()
if(outbag)
filling = TRUE
update_icon()
else
to_chat(usr, "<span class='warning'>There is no blood bag in the output slot.</span>")
return
/obj/machinery/bloodbankgen/proc/check_container_volume(list/reagents, multiplier = 1)
var/sum_reagents = 0
for(var/R in reagents)
sum_reagents += reagents[R]
sum_reagents *= multiplier
if(outbag.reagents.total_volume + sum_reagents > outbag.reagents.maximum_volume)
menustat = "nobagspace"
return FALSE
return TRUE
/obj/machinery/bloodbankgen/proc/detachinput()
if(bag)
bag.forceMove(drop_location())
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
usr.put_in_hands(bag)
bag = null
update_icon()
/obj/machinery/bloodbankgen/proc/detachoutput()
if(outbag)
outbag.forceMove(drop_location())
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
usr.put_in_hands(outbag)
outbag = null
update_icon()
/obj/machinery/bloodbankgen/proc/attachinput(obj/item/O, mob/user)
if(!bag)
if(!user.transferItemToLoc(O, src))
return
bag = O
to_chat(user, "<span class='notice'>You add [O] to the machine's input slot.</span>")
update_icon()
updateUsrDialog()
else
to_chat(user, "<span class='notice'>There is already something in this slot!</span>")
/obj/machinery/bloodbankgen/proc/attachoutput(obj/item/O, mob/user)
if(!outbag)
if(!user.transferItemToLoc(O, src))
return
outbag = O
to_chat(user, "<span class='notice'>You add [O] to the machine's output slot.</span>")
update_icon()
updateUsrDialog()
else
to_chat(user, "<span class='notice'>There is already something in this slot!</span>")
/obj/machinery/bloodbankgen/Topic(href, href_list)
if(..() || panel_open)
return
usr.set_machine(src)
if(href_list["activateinput"])
activateinput()
updateUsrDialog()
else if(href_list["detachinput"])
detachinput()
updateUsrDialog()
else if(href_list["activateoutput"])
activateoutput()
updateUsrDialog()
else if(href_list["detachoutput"])
detachoutput()
updateUsrDialog()
+21 -13
View File
@@ -175,11 +175,12 @@
//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")
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
H.Unconscious(80)
clonemind.transfer_to(H)
@@ -241,13 +242,14 @@
var/obj/item/I = pick_n_take(unattached_flesh)
if(isorgan(I))
var/obj/item/organ/O = I
O.organ_flags &= ~ORGAN_FROZEN
O.Insert(mob_occupant)
else if(isbodypart(I))
var/obj/item/bodypart/BP = I
BP.attach_limb(mob_occupant)
//Premature clones may have brain damage.
mob_occupant.adjustBrainLoss(-((speed_coeff / 2) * dmg_mult))
mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult))
use_power(7500) //This might need tweaking.
@@ -261,6 +263,7 @@
for(var/i in unattached_flesh)
if(isorgan(i))
var/obj/item/organ/O = i
O.organ_flags &= ~ORGAN_FROZEN
O.Insert(mob_occupant)
else if(isbodypart(i))
var/obj/item/bodypart/BP = i
@@ -346,6 +349,9 @@
if(mess) //Clean that mess and dump those gibs!
for(var/obj/fl in unattached_flesh)
fl.forceMove(T)
if(istype(fl, /obj/item/organ))
var/obj/item/organ/O = fl
O.organ_flags &= ~ORGAN_FROZEN
unattached_flesh.Cut()
mess = FALSE
new /obj/effect/gibspawner/generic(get_turf(src))
@@ -356,11 +362,12 @@
if(!mob_occupant)
return
REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, "cloning")
REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, "cloning")
REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, "cloning")
REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, "cloning")
REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, "cloning")
REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, CLONING_POD_TRAIT)
if(grab_ghost_when == CLONER_MATURE_CLONE)
mob_occupant.grab_ghost()
@@ -442,7 +449,7 @@
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.setBrainLoss(CLONE_INITIAL_DAMAGE)
//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.
@@ -458,8 +465,9 @@
for(var/o in H.internal_organs)
var/obj/item/organ/organ = o
if(!istype(organ) || organ.vital)
if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL))
continue
organ.organ_flags |= ORGAN_FROZEN
organ.Remove(H, special=TRUE)
organ.forceMove(src)
unattached_flesh += organ
+4 -3
View File
@@ -1,8 +1,7 @@
#define ARCADE_WEIGHT_TRICK 4
#define ARCADE_WEIGHT_USELESS 2
#define ARCADE_WEIGHT_RARE 1
#define ARCADE_WEIGHT_PLUSH 65
#define ARCADE_RATIO_PLUSH 0.20 // average 1 out of 6 wins is a plush.
/obj/machinery/computer/arcade
name = "random arcade"
@@ -27,7 +26,6 @@
/obj/item/toy/katana = ARCADE_WEIGHT_TRICK,
/obj/item/toy/minimeteor = ARCADE_WEIGHT_TRICK,
/obj/item/toy/nuke = ARCADE_WEIGHT_TRICK,
/obj/item/toy/plush/random = ARCADE_WEIGHT_PLUSH,
/obj/item/toy/redbutton = ARCADE_WEIGHT_TRICK,
/obj/item/toy/spinningtoy = ARCADE_WEIGHT_TRICK,
/obj/item/toy/sword = ARCADE_WEIGHT_TRICK,
@@ -90,6 +88,9 @@
var/obj/item/circuitboard/CB = new thegame()
new CB.build_path(loc, CB)
return INITIALIZE_HINT_QDEL
//The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
//Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
prizes[/obj/item/toy/plush/random] = counterlist_sum(prizes) * ARCADE_RATIO_PLUSH
Reset()
/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
+16 -38
View File
@@ -17,7 +17,7 @@
network += lowertext(i)
/obj/machinery/computer/security/check_eye(mob/user)
if( (stat & (NOPOWER|BROKEN)) || user.incapacitated() || user.eye_blind )
if(CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
user.unset_machine()
return
if(!(user in watchers))
@@ -30,14 +30,6 @@
if(!C.can_use())
user.unset_machine()
return
if(!issilicon(user))
if(!Adjacent(user))
user.unset_machine()
return
else if(iscyborg(user))
var/list/viewing = viewers(src)
if(!viewing.Find(user))
user.unset_machine()
/obj/machinery/computer/security/on_unset_machine(mob/user)
watchers.Remove(user)
@@ -97,36 +89,22 @@
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
return
if(C)
var/camera_fail = 0
if(!C.can_use() || user.machine != src || user.eye_blind || user.incapacitated())
camera_fail = 1
else if(iscyborg(user))
var/list/viewing = viewers(src)
if(!viewing.Find(user))
camera_fail = 1
else if(!issilicon(user))
if(!Adjacent(user))
camera_fail = 1
if(camera_fail)
user.unset_machine()
return 0
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
if(isAI(user))
var/mob/living/silicon/ai/A = user
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
user.reset_perspective(C)
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
user.clear_fullscreen("flash", 5)
watchers[user] = C
use_power(50)
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
else
if(!C || !C.can_use() || CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
user.unset_machine()
return FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
if(isAI(user))
var/mob/living/silicon/ai/A = user
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
user.reset_perspective(C)
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
user.clear_fullscreen("flash", 5)
watchers[user] = C
use_power(50)
addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
//returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
+10 -2
View File
@@ -374,7 +374,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
else
if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept))
region_access |= 1
region_access |= 6
get_subordinates("Head of Personnel")
if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept))
region_access |= 2
@@ -388,6 +387,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept))
region_access |= 5
get_subordinates("Chief Engineer")
if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept))
region_access |= 6
get_subordinates("Quartermaster")
if(region_access)
authenticated = 1
else if ((!( authenticated ) && issilicon(usr)) && (!modify))
@@ -607,7 +609,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
typed_circuit.target_dept = target_dept
else
target_dept = typed_circuit.target_dept
var/list/dept_list = list("general","security","medical","science","engineering")
var/list/dept_list = list("civilian","security","medical","science","engineering","cargo")
name = "[dept_list[target_dept]] department console"
/obj/machinery/computer/card/minor/hos
@@ -631,3 +633,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
icon_screen = "idce"
light_color = LIGHT_COLOR_YELLOW
/obj/machinery/computer/card/minor/qm
target_dept = 6
icon_screen = "idqm"
light_color = LIGHT_COLOR_ORANGE
+4 -4
View File
@@ -159,11 +159,11 @@
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoprocess</a>"
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoprocess</a>"
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<span class='linkOff'>Autoprocess</span>"
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
@@ -228,7 +228,7 @@
dat += "<h4>[src.active_record.fields["name"]]</h4>"
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a><br>"
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
var/obj/item/implant/health/H = locate(active_record.fields["imp"])
if ((H) && (istype(H)))
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
@@ -335,7 +335,7 @@
Nuke_request(input, usr)
to_chat(usr, "<span class='notice'>Request sent.</span>")
usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY)
priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg')
priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
CM.lastTimeUsed = world.time
+2 -2
View File
@@ -484,7 +484,7 @@
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
else if(href_list["del_c"])
if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
@@ -575,7 +575,7 @@
if(user)
if(message)
if(authenticated)
if(user.canUseTopic(src, BE_CLOSE))
if(user.canUseTopic(src, !issilicon(user)))
if(!record1 || record1 == active1)
if(!record2 || record2 == active2)
return 1
-1
View File
@@ -1 +0,0 @@
/obj/machinery/computer/prisoner
@@ -35,11 +35,11 @@
dat += "<HR>Chemical Implants<BR>"
var/turf/Tr = null
for(var/obj/item/implant/chem/C in GLOB.tracked_chem_implants)
Tr = get_turf(C)
if((Tr) && (Tr.z != src.z))
continue//Out of range
if(!C.imp_in)
continue
Tr = get_turf(C.imp_in)
if((Tr) && (Tr.z != src.z))
continue//Out of range
dat += "ID: [C.imp_in.name] | Remaining Units: [C.reagents.total_volume] <BR>"
dat += "| Inject: "
dat += "<A href='?src=[REF(src)];inject1=[REF(C)]'>(<font class='bad'>(1)</font>)</A>"
@@ -48,9 +48,9 @@
dat += "********************************<BR>"
dat += "<HR>Tracking Implants<BR>"
for(var/obj/item/implant/tracking/T in GLOB.tracked_implants)
if(!isliving(T.imp_in))
if(!T.imp_in || !isliving(T.imp_in))
continue
Tr = get_turf(T)
Tr = get_turf(T.imp_in)
if((Tr) && (Tr.z != src.z))
continue//Out of range
+2 -2
View File
@@ -455,7 +455,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
if("Delete Record (ALL)")
if(active1)
@@ -801,7 +801,7 @@ What a mess.*/
/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
if(user)
if(authenticated)
if(user.canUseTopic(src, BE_CLOSE))
if(user.canUseTopic(src, !issilicon(user)))
if(!trim(message1))
return 0
if(!record1 || record1 == active1)
@@ -33,7 +33,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
to_chat(user, "<span class='notice'>[src] already has an uplink in it.</span>")
return
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
if(hidden_uplink)
if(!user.transferItemToLoc(I, src))
return
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
linkedboss.storedcrystals += hidden_uplink.telecrystals
if(addLog)
@@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
@@ -94,7 +94,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
dat += "No linked management consoles detected. Scan for uplink stations using the management console.<BR><BR>"
if(uplinkholder)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
if(linkedboss)
dat += "Donate TC: <a href='byond://?src=[REF(src)];donate=1'>1</a> | <a href='byond://?src=[REF(src)];donate=5'>5</a> | <a href='byond://?src=[REF(src)];donate=-1'>All</a>"
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
dat += "[A.name] | "
if(A.uplinkholder)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, A.uplinkholder)
var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals."
if(storedcrystals)
dat+= "<BR>Add TC: <a href ='?src=[REF(src)];target=[REF(A)];give=1'>1</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=5'>5</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=10'>10</a> | <a href ='?src=[REF(src)];target=[REF(A)];give=-1'>All</a>"
+34 -4
View File
@@ -10,6 +10,7 @@
var/obj/machinery/teleport/station/power_station
var/calibrating
var/turf/target
var/obj/item/implant/imp_t
/obj/machinery/computer/teleporter/Initialize()
. = ..()
@@ -89,6 +90,7 @@
say("Processing hub calibration to target...")
calibrating = 1
power_station.update_icon()
spawn(50 * (3 - power_station.teleporter_hub.accurate)) //Better parts mean faster calibration
calibrating = 0
if(check_hub_connection())
@@ -96,6 +98,7 @@
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
updateDialog()
updateDialog()
@@ -109,6 +112,9 @@
/obj/machinery/computer/teleporter/proc/reset_regime()
target = null
if(imp_t)
UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
imp_t = null
if(regime_set == "Teleporter")
regime_set = "Gate"
else
@@ -124,18 +130,32 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
if(!I.imp_in || !isliving(I.loc) || !I.allow_teleport)
if(!I.imp_in || !I.allow_teleport || !isliving(I.imp_in))
continue
else
var/mob/living/M = I.loc
var/mob/living/M = I.imp_in
if(M.stat == DEAD)
if(M.timeofdeath + I.lifespan_postmortem < world.time)
continue
if(is_eligible(I))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
if(is_eligible(M))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //check if we are still around
return
target = L[desc]
if(imp_t)
UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
imp_t = null
if(isliving(target)) //make sure the living mob is still implanted to be a valid target
var/mob/living/M = target
var/obj/item/implant/tracking/I = locate() in M.implants
if(I)
RegisterSignal(I, COMSIG_IMPLANT_REMOVING, .proc/untarget_implant)
imp_t = I
else
target = null
return
var/turf/T = get_turf(target)
log_game("[key_name(user)] has set the teleporter target to [target] at [AREACOORD(T)]")
@@ -149,6 +169,8 @@
to_chat(user, "<span class='alert'>No active connected stations located.</span>")
return
var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //again, check if we are still around
return
var/obj/machinery/teleport/station/target_station = L[desc]
if(!target_station || !target_station.teleporter_hub)
return
@@ -164,6 +186,14 @@
target_station.teleporter_console.stat &= ~NOPOWER
target_station.teleporter_console.update_icon()
/obj/machinery/computer/teleporter/proc/untarget_implant() //untargets from mob the racker was once implanted in to prevent issues.
target = null
if(power_station)
power_station.engaged = FALSE
power_station.teleporter_hub?.update_icon()
UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
imp_t = null
/obj/machinery/computer/teleporter/proc/is_eligible(atom/movable/AM)
var/turf/T = get_turf(AM)
if(!T)
+497
View File
@@ -0,0 +1,497 @@
/*
* Cryogenic refrigeration unit. Basically a despawner.
* Stealing a lot of concepts/code from sleepers due to massive laziness.
* The despawn tick will only fire if it's been more than time_till_despawned ticks
* since time_entered, which is world.time when the occupant moves in.
* ~ Zuhayr
*/
//Main cryopod console.
/obj/machinery/computer/cryopod
name = "cryogenic oversight console"
desc = "An interface between crew and the cryogenic storage oversight systems."
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "cellconsole_1"
circuit = /obj/item/circuitboard/cryopodcontrol
density = FALSE
interaction_flags_machine = INTERACT_MACHINE_OFFLINE
req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) //Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with.
var/mode = null
var/menu = 1 //Which menu screen to display
//Used for logging people entering cryosleep and important items they are carrying.
var/list/frozen_crew = list()
var/list/frozen_items = list()
// Used for containing rare items traitors need to steal, so it's not
// game-over if they get iced
var/list/objective_items = list()
// A cache of theft datums so you don't have to re-create them for
// each item check
var/list/theft_cache = list()
var/allow_items = TRUE
/obj/machinery/computer/cryopod/attack_ai()
attack_hand()
/obj/machinery/computer/cryopod/ui_interact(mob/user = usr)
if(!is_operational())
return
user.set_machine(src)
add_fingerprint(user)
var/dat = ""
dat += "<h2>Welcome, [user.real_name].</h2><hr/>"
dat += "<br><br>"
switch(src.menu)
if(1)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View crew storage log</a><br><br>"
if(allow_items)
dat += "<a href='byond://?src=[REF(src)];menu=3'>View objects storage log</a><br><br>"
dat += "<a href='byond://?src=[REF(src)];item=1'>Recover object</a><br><br>"
dat += "<a href='byond://?src=[REF(src)];allitems=1'>Recover all objects</a><br>"
if(2)
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
dat += "<h3>Recently stored Crew</h3><br/><hr/><br/>"
if(!frozen_crew.len)
dat += "There has been no storage usage at this terminal.<br/>"
else
for(var/person in frozen_crew)
dat += "[person]<br/>"
dat += "<hr/>"
if(3)
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
dat += "<h3>Recently stored objects</h3><br/><hr/><br/>"
if(!frozen_items.len)
dat += "There has been no storage usage at this terminal.<br/>"
else
for(var/obj/item/I in frozen_items)
dat += "[I.name]<br/>"
dat += "<hr/>"
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/computer/cryopod/Topic(href, href_list)
if(..())
return TRUE
var/mob/user = usr
add_fingerprint(user)
if(href_list["item"])
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
updateUsrDialog()
return
if(!allow_items) return
if(frozen_items.len == 0)
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
updateUsrDialog()
return
var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
playsound(src, "terminal_type", 25, 0)
if(!I)
return
if(!(I in frozen_items))
to_chat(user, "<span class='notice'>\The [I] is no longer in storage.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
updateUsrDialog()
return
visible_message("<span class='notice'>The console beeps happily as it disgorges \the [I].</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
I.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(I)
frozen_items -= I
updateUsrDialog()
else if(href_list["allitems"])
playsound(src, "terminal_type", 25, 0)
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
updateUsrDialog()
return
if(!allow_items) return
if(frozen_items.len == 0)
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
visible_message("<span class='notice'>The console beeps happily as it disgorges the desired objects.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
for(var/obj/item/I in frozen_items)
I.forceMove(drop_location())
frozen_items -= I
updateUsrDialog()
else if (href_list["menu"])
src.menu = text2num(href_list["menu"])
playsound(src, "terminal_type", 25, 0)
updateUsrDialog()
ui_interact(usr)
updateUsrDialog()
return
/obj/item/circuitboard/cryopodcontrol
name = "Circuit board (Cryogenic Oversight Console)"
build_path = "/obj/machinery/computer/cryopod"
/obj/machinery/computer/cryopod/contents_explosion()
return
//Cryopods themselves.
/obj/machinery/cryopod
name = "cryogenic freezer"
desc = "Suited for Cyborgs and Humanoids, the pod is a safe place for personnel affected by the Space Sleep Disorder to get some rest."
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "cryopod-open"
density = TRUE
anchored = TRUE
state_open = TRUE
var/on_store_message = "has entered long-term storage."
var/on_store_name = "Cryogenic Oversight"
// 15 minutes-ish safe period before being despawned.
var/time_till_despawn = 15 * 600 // This is reduced by 90% if a player manually enters cryo
var/despawn_world_time = null // Used to keep track of the safe period.
var/obj/machinery/computer/cryopod/control_computer
var/last_no_computer_message = 0
// These items are preserved when the process() despawn proc occurs.
var/list/preserve_items = list(
/obj/item/hand_tele,
/obj/item/card/id/captains_spare,
/obj/item/aicard,
/obj/item/mmi,
/obj/item/paicard,
/obj/item/gun,
/obj/item/pinpointer,
/obj/item/clothing/shoes/magboots,
/obj/item/areaeditor/blueprints,
/obj/item/clothing/head/helmet/space,
/obj/item/clothing/suit/space,
/obj/item/clothing/suit/armor,
/obj/item/defibrillator/compact,
/obj/item/reagent_containers/hypospray/CMO,
/obj/item/clothing/accessory/medal/gold/captain,
/obj/item/clothing/gloves/krav_maga,
/obj/item/nullrod,
/obj/item/tank/jetpack,
/obj/item/documents,
/obj/item/nuke_core_container
)
// These items will NOT be preserved
var/list/do_not_preserve_items = list (
/obj/item/mmi/posibrain,
/obj/item/gun/energy/laser/mounted,
/obj/item/gun/energy/e_gun/advtaser/mounted,
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/gun/energy/e_gun/advtaser/cyborg,
/obj/item/gun/energy/printer,
/obj/item/gun/energy/kinetic_accelerator/cyborg,
/obj/item/gun/energy/laser/cyborg
)
/obj/machinery/cryopod/Initialize(mapload)
. = ..()
update_icon()
find_control_computer(mapload)
/obj/machinery/cryopod/proc/find_control_computer(urgent = FALSE)
for(var/obj/machinery/computer/cryopod/C in get_area(src))
control_computer = C
if(C)
return C
break
// Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged
if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time)
log_admin("Cryopod in [get_area(src)] could not find control computer!")
message_admins("Cryopod in [get_area(src)] could not find control computer!")
last_no_computer_message = world.time
return control_computer != null
/obj/machinery/cryopod/close_machine(mob/user)
if(!control_computer)
find_control_computer(TRUE)
if((isnull(user) || istype(user)) && state_open && !panel_open)
..(user)
var/mob/living/mob_occupant = occupant
if(mob_occupant && mob_occupant.stat != DEAD)
to_chat(occupant, "<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
despawn_world_time = world.time + (time_till_despawn * 0.1)
else
despawn_world_time = world.time + time_till_despawn
icon_state = "cryopod"
/obj/machinery/cryopod/open_machine()
..()
icon_state = "cryopod-open"
density = TRUE
name = initial(name)
/obj/machinery/cryopod/container_resist(mob/living/user)
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
"<span class='notice'>You climb out of [src]!</span>")
open_machine()
/obj/machinery/cryopod/relaymove(mob/user)
container_resist(user)
/obj/machinery/cryopod/process()
if(!occupant)
return
var/mob/living/mob_occupant = occupant
if(mob_occupant)
// Eject dead people
if(mob_occupant.stat == DEAD)
open_machine()
if(!(world.time > despawn_world_time + 100))//+ 10 seconds
return
if(!mob_occupant.client && mob_occupant.stat < 2) //Occupant is living and has no client.
if(!control_computer)
find_control_computer(urgent = TRUE)//better hope you found it this time
despawn_occupant()
#define CRYO_DESTROY 0
#define CRYO_PRESERVE 1
#define CRYO_OBJECTIVE 2
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
if(istype(I, T.targetitem) && T.check_special_completion(I))
return CRYO_OBJECTIVE
for(var/T in preserve_items)
if(istype(I, T) && !(I.type in do_not_preserve_items))
return CRYO_PRESERVE
return CRYO_DESTROY
// This function can not be undone; do not call this unless you are sure
/obj/machinery/cryopod/proc/despawn_occupant()
if(!control_computer)
find_control_computer()
var/mob/living/mob_occupant = occupant
//Handle Borg stuff first
if(iscyborg(mob_occupant))
var/mob/living/silicon/robot/R = mob_occupant
if(!istype(R)) return ..()
R.contents -= R.mmi
qdel(R.mmi)
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
if(should_preserve_item(O) != CRYO_DESTROY) // Preserve important things inside the item
continue
O.forceMove(src)
R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
//Drop all items into the pod.
for(var/obj/item/I in mob_occupant)
mob_occupant.doUnEquip(I)
I.forceMove(src)
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
if(should_preserve_item(I) != CRYO_DESTROY) // Don't remove the contents of things that need preservation
continue
for(var/obj/item/O in I.contents)
if(istype(O, /obj/item/tank)) //Stop eating pockets, you fuck!
continue
O.forceMove(src)
//Delete all items not on the preservation list.
var/list/items = contents
items -= mob_occupant // Don't delete the occupant
for(var/obj/item/I in items)
if(istype(I, /obj/item/pda))
var/obj/item/pda/P = I
QDEL_NULL(P.id)
qdel(P)
continue
var/preserve = should_preserve_item(I)
if(preserve == CRYO_DESTROY)
qdel(I)
else if(control_computer && control_computer.allow_items)
control_computer.frozen_items += I
if(preserve == CRYO_OBJECTIVE)
control_computer.objective_items += I
I.loc = null
else
I.forceMove(loc)
//Update any existing objectives involving this mob.
for(var/datum/objective/O in GLOB.objectives)
// We don't want revs to get objectives that aren't for heads of staff. Letting
// them win or lose based on cryo is silly so we remove the objective.
if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind)
qdel(O)
else if(O.target && istype(O.target, /datum/mind))
if(O.target == mob_occupant.mind)
if(O.owner && O.owner.current)
to_chat(O.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
O.target = null
spawn(10) //This should ideally fire after the occupant is deleted.
if(!O)
return
O.find_target()
O.update_explanation_text()
if(!(O.target))
O.owner.objectives -= O
qdel(O)
if(mob_occupant.mind && mob_occupant.mind.assigned_role)
//Handle job slot/tater cleanup.
var/job = mob_occupant.mind.assigned_role
SSjob.FreeRole(job)
if(mob_occupant.mind.objectives.len)
mob_occupant.mind.objectives.Cut()
mob_occupant.mind.special_role = null
// Delete them from datacore.
var/announce_rank = null
for(var/datum/data/record/R in GLOB.data_core.medical)
if((R.fields["name"] == mob_occupant.real_name))
qdel(R)
for(var/datum/data/record/T in GLOB.data_core.security)
if((T.fields["name"] == mob_occupant.real_name))
qdel(T)
for(var/datum/data/record/G in GLOB.data_core.general)
if((G.fields["name"] == mob_occupant.real_name))
announce_rank = G.fields["rank"]
qdel(G)
for(var/obj/machinery/computer/cloning/cloner in world)
for(var/datum/data/record/R in cloner.records)
if(R.fields["name"] == mob_occupant.real_name)
cloner.records.Remove(R)
//Make an announcement and log the person entering storage.
if(control_computer)
control_computer.frozen_crew += "[mob_occupant.real_name]"
if(GLOB.announcement_systems.len)
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
announcer.announce("CRYOSTORAGE", mob_occupant.real_name, announce_rank, list())
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
// Ghost and delete the mob.
if(!mob_occupant.get_ghost(1))
mob_occupant.ghostize(0) // Players who cryo out may not re-enter the round
QDEL_NULL(occupant)
open_machine()
name = initial(name)
#undef CRYO_DESTROY
#undef CRYO_PRESERVE
#undef CRYO_OBJECTIVE
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
return
if(occupant)
to_chat(user, "<span class='boldnotice'>The cryo pod is already occupied!</span>")
return
if(target.stat == DEAD)
to_chat(user, "<span class='notice'>Dead people can not be put into cryo.</span>")
return
if(target.client && user != target)
if(iscyborg(target))
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're online.</span>")
else
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're conscious.</span>")
return
else if(target.client)
if(alert(target,"Would you like to enter cryosleep?",,"Yes","No") == "No")
return
var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!"
if(target == user && world.time - target.client.cryo_warned > 5 MINUTES)//if we haven't warned them in the last 5 minutes
var/caught = FALSE
if(target.mind.assigned_role in GLOB.command_positions)
alert("<span class='userdanger'>You're a Head of Staff![generic_plsnoleave_message] Be sure to put your locker items back into your locker!</span>")
caught = TRUE
if(iscultist(target) || is_servant_of_ratvar(target))
to_chat(target, "<span class='userdanger'>You're a Cultist![generic_plsnoleave_message]</span>")
caught = TRUE
if(is_devil(target))
alert("<span class='userdanger'>You're a Devil![generic_plsnoleave_message]</span>")
caught = TRUE
if(istype(SSticker.mode, /datum/antagonist/gang))
if(target.mind.has_antag_datum(/datum/antagonist/gang))
alert("<span class='userdanger'>You're a Gangster![generic_plsnoleave_message]</span>")
caught = TRUE
if(istype(SSticker.mode, /datum/antagonist/rev))
if(target.mind.has_antag_datum(/datum/antagonist/rev/head))
alert("<span class='userdanger'>You're a Head Revolutionary![generic_plsnoleave_message]</span>")
caught = TRUE
else if(target.mind.has_antag_datum(/datum/antagonist/rev))
alert("<span class='userdanger'>You're a Revolutionary![generic_plsnoleave_message]</span>")
caught = TRUE
if(caught)
target.client.cryo_warned = world.time
return
if(!target || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
return
//rerun the checks in case of shenanigans
if(target == user)
visible_message("[user] starts climbing into the cryo pod.")
else
visible_message("[user] starts putting [target] into the cryo pod.")
if(occupant)
to_chat(user, "<span class='boldnotice'>\The [src] is in use.</span>")
return
close_machine(target)
to_chat(target, "<span class='boldnotice'>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</span>")
name = "[name] ([occupant.name])"
log_admin("<span class='notice'>[key_name(target)] entered a stasis pod.</span>")
message_admins("[key_name_admin(target)] entered a stasis pod. (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
add_fingerprint(target)
//Attacks/effects.
/obj/machinery/cryopod/blob_act()
return //Sorta gamey, but we don't really want these to be destroyed.
+2 -1
View File
@@ -74,7 +74,8 @@
to_chat(user, "<span class='notice'>You start adding [I] to [src]...</span>")
if(do_after(user, 50, target=src))
W.use(5)
new /turf/closed/wall/mineral/wood/nonmetal(get_turf(src))
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal)
qdel(src)
return
return ..()
+1 -1
View File
@@ -326,7 +326,7 @@
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
//add_blood doesn't work for borgs/xenos, but add_blood_floor does.
//add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does.
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(DOOR_CRUSH_DAMAGE)
+2 -2
View File
@@ -146,7 +146,7 @@
if((stat & (NOPOWER|BROKEN)) || !anchored)
return
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!materials.has_materials(using_materials))
return // We require more minerals
@@ -211,7 +211,7 @@
/obj/machinery/droneDispenser/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
I.play_tool_sound(src)
to_chat(user, "<span class='notice'>You retrieve the materials from [src].</span>")
+8 -7
View File
@@ -42,17 +42,18 @@
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")
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
H.key = C.key
C.transfer_ckey(H)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
+13 -11
View File
@@ -135,17 +135,19 @@ The console is located at computer/gulag_teleporter.dm
if(linked_reclaimer)
linked_reclaimer.stored_items[occupant] = list()
var/mob/living/mob_occupant = occupant
for(var/obj/item/W in mob_occupant)
if(!is_type_in_typecache(W, telegulag_required_items) && mob_occupant.temporarilyRemoveItemFromInventory(W))
if(istype(W, /obj/item/restraints/handcuffs))
W.forceMove(get_turf(src))
continue
if(linked_reclaimer)
linked_reclaimer.stored_items[mob_occupant] += W
linked_reclaimer.contents += W
W.forceMove(linked_reclaimer)
else
W.forceMove(src)
for(var/A in mob_occupant.get_equipped_items(TRUE))
var/obj/item/I = A
if(is_type_in_typecache(I, telegulag_required_items) || !mob_occupant.temporarilyRemoveItemFromInventory(I))
continue
if(istype(I, /obj/item/restraints/handcuffs))
I.forceMove(get_turf(src))
continue
if(linked_reclaimer)
linked_reclaimer.stored_items[mob_occupant] += I
linked_reclaimer.contents += I
I.forceMove(linked_reclaimer)
else
I.forceMove(src)
/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/data/record/R)
if(!ishuman(occupant))
+20 -14
View File
@@ -8,14 +8,14 @@
icon_state = "iv_drip"
anchored = FALSE
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
var/mob/living/carbon/attached = null
var/mob/living/carbon/attached
var/mode = IV_INJECTING
var/obj/item/reagent_containers/beaker = null
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/machinery/iv_drip/Initialize()
/obj/machinery/iv_drip/Initialize(mapload)
. = ..()
update_icon()
@@ -84,6 +84,8 @@
if(Adjacent(target) && usr.Adjacent(target))
if(beaker)
usr.visible_message("<span class='warning'>[usr] attaches [src] to [target].</span>", "<span class='notice'>You attach [src] to [target].</span>")
log_combat(usr, target, "attached", src, "containing: [beaker.name] - ([beaker.reagents.log_list()])")
add_fingerprint(usr)
attached = target
START_PROCESSING(SSmachines, src)
update_icon()
@@ -100,6 +102,8 @@
return
beaker = W
to_chat(user, "<span class='notice'>You attach [W] to [src].</span>")
user.log_message("attached a [W] to [src] at [AREACOORD(src)] containing ([beaker.reagents.log_list()])", LOG_ATTACK)
add_fingerprint(user)
update_icon()
return
else
@@ -142,10 +146,11 @@
if(!amount)
if(prob(5))
visible_message("[src] pings.")
playsound(loc, 'sound/machines/beep.ogg', 50, 1)
return
// If the human is losing too much blood, beep.
if(attached.blood_volume < ( (BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) ) )
if(attached.blood_volume < ((BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) && ishuman(attached))) //really couldn't care less about monkeys
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
attached.transfer_blood_to(beaker, amount)
@@ -178,9 +183,10 @@
if(usr.incapacitated())
return
if(beaker)
beaker.forceMove(drop_location())
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
if(!usr.put_in_hands(beaker))
beaker.forceMove(drop_location())
beaker = null
update_icon()
@@ -195,27 +201,27 @@
if(usr.incapacitated())
return
mode = !mode
to_chat(usr, "The IV drip is now [mode ? "injecting" : "taking blood"].")
update_icon()
/obj/machinery/iv_drip/examine(mob/user)
..()
. = ..()
if(get_dist(user, src) > 2)
return
to_chat(user, "The IV drip is [mode ? "injecting" : "taking blood"].")
. += "[src] is [mode ? "injecting" : "taking blood"].\n"
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
to_chat(user, "<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>")
. += "\t<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>\n"
else
to_chat(user, "<span class='notice'>Attached is an empty [beaker.name].</span>")
. += "\t<span class='notice'>Attached is an empty [beaker.name].</span>\n"
else
to_chat(user, "<span class='notice'>No chemicals are attached.</span>")
. += "\t<span class='notice'>No chemicals are attached.</span>\n"
to_chat(user, "<span class='notice'>[attached ? attached : "No one"] is attached.</span>")
. += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
to_chat(user,.)
#undef IV_TAKING
#undef IV_INJECTING
#undef IV_INJECTING
@@ -40,6 +40,8 @@
var/stun_projectile = null //stun mode projectile type
var/stun_projectile_sound
var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any
var/nonlethal_projectile_sound
var/lethal_projectile = null //lethal mode projectile type
var/lethal_projectile_sound
@@ -535,13 +537,22 @@
T = closer
break
var/mob/living/carbon/C
if(iscarbon(target))
C = target
update_icon()
var/obj/item/projectile/A
//any emagged turrets drains 2x power and uses a different projectile?
if(mode == TURRET_STUN)
use_power(reqpower)
A = new stun_projectile(T)
playsound(loc, stun_projectile_sound, 75, 1)
if(nonlethal_projectile && C && C.resting)
use_power(reqpower*0.5)
A = new nonlethal_projectile(T)
playsound(loc, nonlethal_projectile_sound, 75, 1)
else
use_power(reqpower)
A = new stun_projectile(T)
playsound(loc, stun_projectile_sound, 75, 1)
else
use_power(reqpower * 2)
A = new lethal_projectile(T)
@@ -653,6 +664,8 @@
base_icon_state = "standard"
stun_projectile = /obj/item/projectile/energy/electrode
stun_projectile_sound = 'sound/weapons/taser.ogg'
nonlethal_projectile = /obj/item/projectile/beam/disabler
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
lethal_projectile = /obj/item/projectile/beam/laser
lethal_projectile_sound = 'sound/weapons/laser.ogg'
desc = "An energy blaster auto-turret."
@@ -662,6 +675,8 @@
base_icon_state = "standard"
stun_projectile = /obj/item/projectile/energy/electrode
stun_projectile_sound = 'sound/weapons/taser.ogg'
nonlethal_projectile = /obj/item/projectile/beam/disabler
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
lethal_projectile = /obj/item/projectile/beam/laser/heavylaser
lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg'
desc = "An energy blaster auto-turret."
@@ -681,6 +696,8 @@
/obj/machinery/porta_turret/ai
faction = list("silicon")
nonlethal_projectile = /obj/item/projectile/beam/disabler
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
/obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp)
return 10 //AI turrets shoot at everything not in their faction
+5 -5
View File
@@ -32,10 +32,10 @@
mat_mod *= 50000
for(var/obj/item/stock_parts/manipulator/M in component_parts)
amt_made = 12.5 * M.rating //% of materials salvaged
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = mat_mod
amount_produced = min(50, amt_made) + 50
GET_COMPONENT(butchering, /datum/component/butchering)
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.effectiveness = amount_produced
butchering.bonus_modifier = amount_produced/5
@@ -99,7 +99,7 @@
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContents()
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
@@ -144,7 +144,7 @@
qdel(L)
return
else
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(I)
if(!material_amount)
qdel(I)
@@ -195,7 +195,7 @@
L.Unconscious(100)
L.adjustBruteLoss(crush_damage)
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
GET_COMPONENT(butchering, /datum/component/butchering)
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.Butcher(src,L)
/obj/machinery/recycler/deathtrap
+4 -1
View File
@@ -245,6 +245,7 @@
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
else
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
mob_occupant.radiation = 0
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
if(suit)
@@ -264,6 +265,8 @@
things_to_clear += occupant.GetAllContents()
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
AM.clean_blood()
AM.fingerprints = list()
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
if(contamination)
qdel(contamination)
@@ -434,4 +437,4 @@
if(I)
I.forceMove(loc)
. = TRUE
update_icon()
update_icon()
+39 -9
View File
@@ -1,3 +1,7 @@
GLOBAL_VAR_INIT(singularity_counter, 0)
#define METEOR_DISASTER_MODIFIER 0.5
////////////////////////////////////////
//Singularity beacon
////////////////////////////////////////
@@ -13,39 +17,57 @@
stat = 0
verb_say = "states"
var/cooldown = 0
var/active = 0
var/active = FALSE
var/meteor_buff = FALSE
var/icontype = "beacon"
/obj/machinery/power/singularity_beacon/proc/Activate(mob/user = null)
if(active)
return FALSE
if(surplus() < 1500)
if(user)
to_chat(user, "<span class='notice'>The connected wire doesn't have enough current.</span>")
return
return FALSE
if(is_station_level(z))
increment_meteor_waves()
for(var/obj/singularity/singulo in GLOB.singularities)
if(singulo.z == z)
singulo.target = src
icon_state = "[icontype]1"
active = 1
active = TRUE
if(user)
to_chat(user, "<span class='notice'>You activate the beacon.</span>")
return TRUE
/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user = null)
/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user)
if(!active)
return FALSE
for(var/obj/singularity/singulo in GLOB.singularities)
if(singulo.target == src)
singulo.target = null
icon_state = "[icontype]0"
active = 0
active = FALSE
if(user)
to_chat(user, "<span class='notice'>You deactivate the beacon.</span>")
if(meteor_buff)
decrement_meteor_waves()
return TRUE
/obj/machinery/power/singularity_beacon/proc/increment_meteor_waves()
meteor_buff = TRUE
GLOB.singularity_counter++
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
W.weight += round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
/obj/machinery/power/singularity_beacon/proc/decrement_meteor_waves()
meteor_buff = FALSE
GLOB.singularity_counter--
for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
W.weight -= round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
/obj/machinery/power/singularity_beacon/attack_ai(mob/user)
return
/obj/machinery/power/singularity_beacon/attack_hand(mob/user)
. = ..()
if(.)
@@ -86,6 +108,12 @@
if(!active)
return
var/is_on_station = is_station_level(z)
if(meteor_buff && !is_on_station)
decrement_meteor_waves()
else if(!meteor_buff && is_on_station)
increment_meteor_waves()
if(surplus() >= 1500)
add_load(1500)
if(cooldown <= world.time)
@@ -133,3 +161,5 @@
/obj/item/sbeacondrop/clownbomb
desc = "A label on it reads: <i>Warning: Activating this device will send a silly explosive to your location</i>."
droptype = /obj/machinery/syndicatebomb/badmin/clown
#undef METEOR_DISASTER_MODIFIER
+2
View File
@@ -209,5 +209,7 @@
icon_state = "controller-o"
else if(stat & (BROKEN|NOPOWER))
icon_state = "controller-p"
else if(teleporter_console && teleporter_console.calibrating)
icon_state = "controller-c"
else
icon_state = "controller"
+84
View File
@@ -0,0 +1,84 @@
/obj/machinery/turnstile
name = "turnstile"
desc = "A mechanical door that permits one-way access and prevents tailgating."
icon = 'icons/obj/turnstile.dmi'
icon_state = "turnstile_map"
density = FALSE
armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100, fire = 90, acid = 70)
anchored = TRUE
use_power = FALSE
idle_power_usage = 2
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = OPEN_DOOR_LAYER
/obj/machinery/turnstile/Initialize()
. = ..()
icon_state = "turnstile"
/obj/machinery/turnstile/CanAtmosPass(turf/T)
return TRUE
/obj/machinery/turnstile/bullet_act(obj/item/projectile/P, def_zone)
return -1 //Pass through!
/obj/machinery/turnstile/proc/allowed_access(var/mob/B)
if(B.pulledby && ismob(B.pulledby))
return allowed(B.pulledby) | allowed(B)
else
return allowed(B)
/obj/machinery/turnstile/CanPass(atom/movable/AM, turf/T)
if(ismob(AM))
var/mob/B = AM
if(isliving(AM))
var/mob/living/M = AM
if(world.time - M.last_bumped <= 5)
return FALSE
M.last_bumped = world.time
var/allowed_access = FALSE
var/turf/behind = get_step(src, dir)
if(B in behind.contents)
allowed_access = allowed_access(B)
else
to_chat(usr, "<span class='notice'>\the [src] resists your efforts.</span>")
return FALSE
if(allowed_access)
flick("operate", src)
playsound(src,'sound/items/ratchet.ogg',50,0,3)
return TRUE
else
flick("deny", src)
playsound(src,'sound/machines/deniedbeep.ogg',50,0,3)
return FALSE
if(ispath(AM, /obj/item/))
return TRUE
else
return FALSE
/obj/machinery/turnstile/CheckExit(atom/movable/AM as mob|obj, target)
if(isliving(AM))
var/mob/living/M = AM
var/outdir = dir
if(allowed_access(M))
switch(dir)
if(NORTH)
outdir = SOUTH
if(SOUTH)
outdir = NORTH
if(EAST)
outdir = WEST
if(WEST)
outdir = EAST
var/turf/outturf = get_step(src, outdir)
var/canexit = (target == src.loc) | (target == outturf)
if(!canexit && world.time - M.last_bumped <= 5)
to_chat(usr, "<span class='notice'>\the [src] resists your efforts.</span>")
M.last_bumped = world.time
return canexit
else
return TRUE
+4 -6
View File
@@ -11,10 +11,6 @@
var/obj/item/color_source
var/max_wash_capacity = 5
/obj/machinery/washing_machine/ComponentInitialize()
. = ..()
AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
/obj/machinery/washing_machine/examine(mob/user)
..()
to_chat(user, "<span class='notice'>Alt-click it to start a wash cycle.</span>")
@@ -59,7 +55,8 @@
M.Translate(rand(-3, 3), rand(-1, 3))
animate(src, transform=M, time=2)
/obj/machinery/washing_machine/proc/clean_blood()
/obj/machinery/washing_machine/clean_blood()
..()
if(!busy)
bloody_mess = FALSE
update_icon()
@@ -67,7 +64,8 @@
/obj/machinery/washing_machine/proc/wash_cycle()
for(var/X in contents)
var/atom/movable/AM = X
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
AM.clean_blood()
AM.machine_wash(src)
busy = FALSE