Merge branch 'master' into upstream-merge-30580

This commit is contained in:
LetterJay
2017-09-11 23:19:07 -05:00
committed by GitHub
118 changed files with 4811 additions and 3743 deletions
+7 -1
View File
@@ -5,7 +5,7 @@
// How multiple components of the exact same type are handled in the same datum
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
// All signals. Format:
@@ -16,3 +16,9 @@
#define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: ()
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom)
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable)
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from the base of atom/attackby: (obj/item, mob/living, params)
#define COMSIG_PARENT_EXAMINE "atom_examine" //from the base of atom/examine: (mob)
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom)
#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable)
+2
View File
@@ -25,6 +25,8 @@
#define islava(A) (istype(A, /turf/open/lava))
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
//Mobs
#define isliving(A) (istype(A, /mob/living))
+5
View File
@@ -458,3 +458,8 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define SHELLEO_ERRORLEVEL 1
#define SHELLEO_STDOUT 2
#define SHELLEO_STDERR 3
//server security mode
#define SECURITY_SAFE 1
#define SECURITY_ULTRASAFE 2
#define SECURITY_TRUSTED 3
-3
View File
@@ -2,6 +2,3 @@
#define TRACK_NUKE_DISK 1 //We track the nuclear authentication disk, either to protect it or steal it
#define TRACK_MALF_AI 2 //We track the malfunctioning AI, so we can prevent it from blowing us all up
#define TRACK_INFILTRATOR 3 //We track the Syndicate infiltrator, so we can get back to ship when the nuke's armed
#define TRACK_OPERATIVES 4 //We track the closest operative, so we can regroup when we need to
#define TRACK_ATOM 5 //We track a specified atom, so admins can make us function for events
#define TRACK_COORDINATES 6 //We point towards the specified coordinates on our z-level, so we can navigate
+3 -1
View File
@@ -9,7 +9,9 @@
//keep these in sync with TGS3
#define SERVICE_WORLD_PARAM "server_service"
#define SERVICE_PR_TEST_JSON "..\\..\\prtestjob.json"
#define SERVICE_VERSION_PARAM "server_service_version"
#define SERVICE_PR_TEST_JSON "prtestjob.json"
#define SERVICE_PR_TEST_JSON_OLD "..\\..\\[SERVICE_PR_TEST_JSON]"
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
+24 -1
View File
@@ -10,6 +10,9 @@
w_class = WEIGHT_CLASS_TINY
flags_1 = NOBLUDGEON_1
/*Inferno707*/
/obj/item/clothing/neck/cloak/inferno
name = "Kiara's Cloak"
desc = "The design on this seems a little too familiar."
@@ -19,6 +22,16 @@
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
/obj/item/clothing/neck/petcollar/inferno
name = "Kiara's Collar"
desc = "A soft black collar that seems to stretch to fit whoever wears it."
icon_state = "infcollar"
item_state = "infcollar"
item_color = null
tagname = null
/*DirtyOldHarry*/
/obj/item/lighter/gold
name = "\improper Engraved Zippo"
desc = "A shiny and relatively expensive zippo lighter. There's a small etched in verse on the bottom that reads, 'No Gods, No Masters, Only Man.'"
@@ -30,4 +43,14 @@
slot_flags = SLOT_BELT
heat = 1500
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
light_color = LIGHT_COLOR_FIRE
/*Zombierobin*/
/obj/item/clothing/neck/scarf/zomb //Default white color, same functionality as beanies.
name = "A special scarf"
icon_state = "zombscarf"
desc = "A fashionable collar"
item_color = "zombscarf"
dog_fashion = /datum/dog_fashion/head
+92
View File
@@ -0,0 +1,92 @@
/datum/component/archaeology
dupe_type = COMPONENT_DUPE_UNIQUE
var/list/archdrops
var/prob2drop
var/dug
/datum/component/archaeology/Initialize(_prob2drop, list/_archdrops = list())
prob2drop = Clamp(_prob2drop, 0, 100)
archdrops = _archdrops
RegisterSignal(COMSIG_PARENT_ATTACKBY,.proc/Dig)
RegisterSignal(COMSIG_ATOM_EX_ACT, .proc/BombDig)
RegisterSignal(COMSIG_ATOM_SING_PULL, .proc/SingDig)
/datum/component/archaeology/InheritComponent(datum/component/archaeology/A, i_am_original)
var/list/other_archdrops = A.archdrops
var/list/_archdrops = archdrops
for(var/I in other_archdrops)
_archdrops[I] += other_archdrops[I]
/datum/component/archaeology/proc/Dig(mob/user, obj/item/W)
if(dug)
to_chat(user, "<span class='notice'>Looks like someone has dug here already.</span>")
return FALSE
else
var/digging_speed
if (istype(W, /obj/item/shovel))
var/obj/item/shovel/S = W
digging_speed = S.digspeed
else if (istype(W, /obj/item/pickaxe))
var/obj/item/pickaxe/P = W
digging_speed = P.digspeed
if (digging_speed && isturf(user.loc))
to_chat(user, "<span class='notice'>You start digging...</span>")
playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1)
if(do_after(user, digging_speed, target = parent))
to_chat(user, "<span class='notice'>You dig a hole.</span>")
gets_dug()
dug = TRUE
SSblackbox.add_details("pick_used_mining",W.type)
return TRUE
return FALSE
/datum/component/archaeology/proc/gets_dug()
if(dug)
return
else
var/turf/open/OT = get_turf(parent)
for(var/thing in archdrops)
var/maxtodrop = archdrops[thing]
for(var/i in 1 to maxtodrop)
if(prob(prob2drop)) // can't win them all!
new thing(OT)
if(isopenturf(OT))
if(OT.postdig_icon_change)
if(istype(OT, /turf/open/floor/plating/asteroid/) && !OT.postdig_icon)
var/turf/open/floor/plating/asteroid/AOT = parent
AOT.icon_plating = "[AOT.environment_type]_dug"
AOT.icon_state = "[AOT.environment_type]_dug"
else
if(isplatingturf(OT))
var/turf/open/floor/plating/POT = parent
POT.icon_plating = "[POT.postdig_icon]"
OT.icon_state = "[OT.postdig_icon]"
if(OT.slowdown) //Things like snow slow you down until you dig them.
OT.slowdown = 0
dug = TRUE
/datum/component/archaeology/proc/SingDig(S, current_size)
switch(current_size)
if(STAGE_THREE)
if(prob(30))
gets_dug()
if(STAGE_FOUR)
if(prob(50))
gets_dug()
else
if(current_size >= STAGE_FIVE && prob(70))
gets_dug()
/datum/component/archaeology/proc/BombDig(severity, target)
switch(severity)
if(3)
return
if(2)
if(prob(20))
gets_dug()
if(1)
gets_dug()
+1159 -1138
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -6,8 +6,14 @@
var/date
/datum/getrev/New()
if(world.RunningService() && fexists(SERVICE_PR_TEST_JSON))
testmerge = json_decode(file2text(SERVICE_PR_TEST_JSON))
if(world.RunningService())
var/file_name
if(ServiceVersion()) //will return null for versions < 3.0.91.0
file_name = SERVICE_PR_TEST_JSON_OLD
else
file_name = SERVICE_PR_TEST_JSON
if(fexists(file_name))
testmerge = json_decode(file2text(file_name))
#ifdef SERVERTOOLS
else if(!world.RunningService() && fexists("../prtestjob.lk")) //tgs2 support
var/list/tmp = world.file2list("..\\prtestjob.lk")
+1 -1
View File
@@ -311,7 +311,7 @@
traitor_mob.mind.store_memory("<B>Radio Frequency:</B> [format_frequency(R.traitor_frequency)] ([R.name]).")
else if(uplink_loc == PDA)
PDA.lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]"
PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
traitor_mob.mind.store_memory("<B>Uplink Passcode:</B> [PDA.lock_code] ([PDA.name]).")
+3 -2
View File
@@ -304,6 +304,7 @@
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
contents_explosion(severity, target)
SendSignal(COMSIG_ATOM_EX_ACT, severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
return
@@ -468,8 +469,8 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/singularity_act()
return
/atom/proc/singularity_pull()
return
/atom/proc/singularity_pull(obj/singularity/S, current_size)
SendSignal(COMSIG_ATOM_SING_PULL, S, current_size)
/atom/proc/acid_act(acidpwr, acid_volume)
return
@@ -26,8 +26,8 @@
to_chat(user, "<span class='inathneq'>An emergency shuttle has arrived and this prism is no longer useful; attempt to activate it to gain a partial refund of components used.</span>")
else
var/efficiency = get_efficiency_mod(TRUE)
to_chat(user, "<span class='inathneq_small'>It requires at least <b>[get_delay_cost()]W</b> of power to attempt to delay the arrival of an emergency shuttle by <b>[2 * efficiency]</b> minutes.</span>")
to_chat(user, "<span class='inathneq_small'>This cost increases by <b>[delay_cost_increase]W</b> for every previous activation.</span>")
to_chat(user, "<span class='inathneq_small'>It requires at least <b>[DisplayPower(get_delay_cost())]</b> of power to attempt to delay the arrival of an emergency shuttle by <b>[2 * efficiency]</b> minutes.</span>")
to_chat(user, "<span class='inathneq_small'>This cost increases by <b>[DisplayPower(delay_cost_increase)]</b> for every previous activation.</span>")
/obj/structure/destructible/clockwork/powered/prolonging_prism/forced_disable(bad_effects)
if(active)
@@ -126,7 +126,7 @@
if(!hex_combo)
hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)
else
hex_combo.overlays += mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)
hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER))
if(hex_combo) //YOU BUILT A HEXAGON
hex_combo.pixel_x = -16
hex_combo.pixel_y = -16
@@ -309,8 +309,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
owner_AI.nuking = TRUE
owner_AI.doomsday_device = DOOM
owner_AI.doomsday_device.start()
for(var/pinpointer in GLOB.pinpointer_list)
var/obj/item/pinpointer/P = pinpointer
for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes
qdel(src)
@@ -0,0 +1,11 @@
diff a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm (rejected hunks)
@@ -309,8 +309,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
owner_AI.nuking = TRUE
owner_AI.doomsday_device = DOOM
owner_AI.doomsday_device.start()
- for(var/pinpointer in GLOB.pinpointer_list)
- var/obj/item/weapon/pinpointer/P = pinpointer
+ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes
qdel(src)
@@ -12,6 +12,8 @@
var/list/abductee_minds
var/flash = " - || - "
var/obj/machinery/abductor/console/console
var/message_cooldown = 0
var/breakout_time = 0.75
/obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target))
@@ -40,25 +42,23 @@
/obj/machinery/abductor/experiment/relaymove(mob/user)
if(user.stat != CONSCIOUS)
return
container_resist(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/abductor/experiment/container_resist(mob/living/user)
var/breakout_time = 600
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about a minute.)</span>")
user.visible_message("<span class='italics'>You hear a metallic creaking from [src]!</span>")
if(do_after(user,(breakout_time), target = src))
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 [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
return
visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>")
to_chat(user, "<span class='notice'>You successfully break out of [src]!</span>")
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/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H)
var/icon/photo = null
var/g = (H.gender == FEMALE) ? "f" : "m"
+1 -1
View File
@@ -325,7 +325,7 @@
gloves = /obj/item/clothing/gloves/combat
back = /obj/item/storage/backpack
ears = /obj/item/device/radio/headset/syndicate/alt
l_pocket = /obj/item/pinpointer/syndicate
l_pocket = /obj/item/pinpointer/nuke/syndicate
id = /obj/item/card/id/syndicate
belt = /obj/item/gun/ballistic/automatic/pistol
backpack_contents = list(/obj/item/storage/box/syndie=1)
@@ -0,0 +1,10 @@
diff a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm (rejected hunks)
@@ -325,7 +325,7 @@
gloves = /obj/item/clothing/gloves/combat
back = /obj/item/weapon/storage/backpack
ears = /obj/item/device/radio/headset/syndicate/alt
- l_pocket = /obj/item/weapon/pinpointer/syndicate
+ l_pocket = /obj/item/weapon/pinpointer/nuke/syndicate
id = /obj/item/weapon/card/id/syndicate
belt = /obj/item/weapon/gun/ballistic/automatic/pistol
backpack_contents = list(/obj/item/weapon/storage/box/syndie=1)
+5 -5
View File
@@ -362,9 +362,9 @@
if(safety)
if(timing)
set_security_level(previous_level)
for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(initial(S.mode))
S.nuke_warning = FALSE
S.alert = FALSE
timing = FALSE
bomb_set = TRUE
detonation_timer = null
@@ -381,16 +381,16 @@
bomb_set = TRUE
set_security_level("delta")
detonation_timer = world.time + (timer_set * 10)
for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start()
else
bomb_set = FALSE
detonation_timer = null
set_security_level(previous_level)
for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(initial(S.mode))
S.nuke_warning = FALSE
S.alert = FALSE
countdown.stop()
update_icon()
@@ -0,0 +1,33 @@
diff a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm (rejected hunks)
@@ -362,9 +362,9 @@
if(safety)
if(timing)
set_security_level(previous_level)
- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(initial(S.mode))
- S.nuke_warning = FALSE
+ S.alert = FALSE
timing = FALSE
bomb_set = TRUE
detonation_timer = null
@@ -381,16 +381,16 @@
bomb_set = TRUE
set_security_level("delta")
detonation_timer = world.time + (timer_set * 10)
- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start()
else
bomb_set = FALSE
detonation_timer = null
set_security_level(previous_level)
- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(initial(S.mode))
- S.nuke_warning = FALSE
+ S.alert = FALSE
countdown.stop()
update_icon()
+34 -131
View File
@@ -1,56 +1,7 @@
//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk.
/obj/item/pinpointer
name = "pinpointer"
desc = "A handheld tracking device that locks onto certain signals."
icon = 'icons/obj/device.dmi'
icon_state = "pinoff"
flags_1 = CONDUCT_1
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL = 500, MAT_GLASS = 250)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/active = FALSE
var/atom/movable/target = null //The thing we're searching for
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
var/target_x = 0 //The target coordinates if we're tracking those
var/target_y = 0
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
var/mode = TRACK_NUKE_DISK //What are we looking for?
/obj/item/pinpointer/nuke
var/mode = TRACK_NUKE_DISK
/obj/item/pinpointer/New()
..()
GLOB.pinpointer_list += src
/obj/item/pinpointer/Destroy()
STOP_PROCESSING(SSfastprocess, src)
GLOB.pinpointer_list -= src
return ..()
/obj/item/pinpointer/attack_self(mob/living/user)
active = !active
user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates their pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
icon_state = "pin[active ? "onnull" : "off"]"
if(active)
START_PROCESSING(SSfastprocess, src)
else
target = null //Restarting the pinpointer forces a target reset
STOP_PROCESSING(SSfastprocess, src)
/obj/item/pinpointer/attackby(obj/item/I, mob/living/user, params)
if(mode != TRACK_ATOM)
return ..()
user.visible_message("<span class='notice'>[user] tunes [src] to [I].</span>", "<span class='notice'>You fine-tune [src]'s tracking to track [I].</span>")
playsound(src, 'sound/machines/click.ogg', 50, 1)
constant_target = I
/obj/item/pinpointer/examine(mob/user)
/obj/item/pinpointer/nuke/examine(mob/user)
..()
var/msg = "Its tracking indicator reads "
switch(mode)
@@ -60,12 +11,6 @@
msg += "\"01000001 01001001\"."
if(TRACK_INFILTRATOR)
msg += "\"vasvygengbefuvc\"."
if(TRACK_OPERATIVES)
msg += "\"[target ? "Operative [target]" : "friends"]\"."
if(TRACK_ATOM)
msg += "\"[initial(constant_target.name)]\"."
if(TRACK_COORDINATES)
msg += "\"([target_x], [target_y])\"."
else
msg = "Its tracking indicator is blank."
to_chat(user, msg)
@@ -73,22 +18,20 @@
if(bomb.timing)
to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.get_time_left()]")
/obj/item/pinpointer/process()
if(!active)
STOP_PROCESSING(SSfastprocess, src)
return
scan_for_target()
point_to_target()
my_god_jc_a_bomb()
addtimer(CALLBACK(src, .proc/refresh_target), 50, TIMER_UNIQUE)
/obj/item/pinpointer/nuke/process()
..()
if(active) // If shit's going down
for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list)
if(bomb.timing)
if(!alert)
alert = TRUE
playsound(src, 'sound/items/nuke_toy_lowpower.ogg', 50, 0)
if(isliving(loc))
var/mob/living/L = loc
to_chat(L, "<span class='userdanger'>Your [name] vibrates and lets out a tinny alarm. Uh oh.</span>")
/obj/item/pinpointer/proc/scan_for_target() //Looks for whatever it's tracking
if(target)
if(isliving(target))
var/mob/living/L = target
if(L.stat == DEAD)
target = null
return
/obj/item/pinpointer/nuke/scan_for_target()
target = null
switch(mode)
if(TRACK_NUKE_DISK)
var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list
@@ -104,76 +47,36 @@
target = A
if(TRACK_INFILTRATOR)
target = SSshuttle.getShuttle("syndicate")
if(TRACK_OPERATIVES)
var/list/possible_targets = list()
var/turf/here = get_turf(src)
for(var/V in SSticker.mode.syndicates)
var/datum/mind/M = V
if(M.current && M.current.stat != DEAD)
possible_targets |= M.current
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
if(closest_operative)
target = closest_operative
if(TRACK_ATOM)
if(constant_target)
target = constant_target
if(TRACK_COORDINATES)
var/turf/T = get_turf(src)
target = locate(target_x, target_y, T.z)
..()
/obj/item/pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
if(!active)
return
if(!target || (mode == TRACK_ATOM && !constant_target))
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
return
var/turf/here = get_turf(src)
var/turf/there = get_turf(target)
if(here.z != there.z)
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
return
if(get_dist_euclidian(here,there)<=minimum_range)
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
else
setDir(get_dir(here, there))
switch(get_dist(here, there))
if(1 to 8)
icon_state = "pinon[nuke_warning ? "alert" : "close"]"
if(9 to 16)
icon_state = "pinon[nuke_warning ? "alert" : "medium"]"
if(16 to INFINITY)
icon_state = "pinon[nuke_warning ? "alert" : "far"]"
/obj/item/pinpointer/proc/my_god_jc_a_bomb() //If we should get the hell back to the ship
for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list)
if(bomb.timing)
if(!nuke_warning)
nuke_warning = TRUE
playsound(src, 'sound/items/nuke_toy_lowpower.ogg', 50, 0)
if(isliving(loc))
var/mob/living/L = loc
to_chat(L, "<span class='userdanger'>Your [name] vibrates and lets out a tinny alarm. Uh oh.</span>")
/obj/item/pinpointer/proc/switch_mode_to(new_mode) //If we shouldn't be tracking what we are
/obj/item/pinpointer/nuke/proc/switch_mode_to(new_mode)
if(isliving(loc))
var/mob/living/L = loc
to_chat(L, "<span class='userdanger'>Your [name] beeps as it reconfigures its tracking algorithms.</span>")
playsound(L, 'sound/machines/triple_beep.ogg', 50, 1)
mode = new_mode
target = null //Switch modes so we can find the new target
scan_for_target()
/obj/item/pinpointer/proc/refresh_target() //Periodically removes the target to allow the pinpointer to update (i.e. malf AI shunts, an operative dies)
target = null
/obj/item/pinpointer/syndicate //Syndicate pinpointers automatically point towards the infiltrator once the nuke is active.
/obj/item/pinpointer/nuke/syndicate // Syndicate pinpointers automatically point towards the infiltrator once the nuke is active.
name = "syndicate pinpointer"
desc = "A handheld tracking device that locks onto certain signals. It's configured to switch tracking modes once it detects the activation signal of a nuclear device."
icon_state = "pinpointer_syndicate"
/obj/item/pinpointer/syndicate/cyborg //Cyborg pinpointers just look for a random operative.
/obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative.
name = "cyborg syndicate pinpointer"
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
mode = TRACK_OPERATIVES
flags_1 = NODROP_1
/obj/item/pinpointer/syndicate_cyborg/scan_for_target()
target = null
var/list/possible_targets = list()
var/turf/here = get_turf(src)
for(var/V in SSticker.mode.syndicates)
var/datum/mind/M = V
if(M.current && M.current.stat != DEAD)
possible_targets |= M.current
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
if(closest_operative)
target = closest_operative
..()
@@ -0,0 +1,21 @@
diff a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm (rejected hunks)
@@ -30,7 +30,6 @@
var/mob/living/L = loc
to_chat(L, "<span class='userdanger'>Your [name] vibrates and lets out a tinny alarm. Uh oh.</span>")
-
/obj/item/pinpointer/nuke/scan_for_target()
target = null
switch(mode)
@@ -58,10 +57,10 @@
mode = new_mode
scan_for_target()
-
/obj/item/pinpointer/nuke/syndicate // Syndicate pinpointers automatically point towards the infiltrator once the nuke is active.
name = "syndicate pinpointer"
desc = "A handheld tracking device that locks onto certain signals. It's configured to switch tracking modes once it detects the activation signal of a nuclear device."
+ icon_state = "pinpointer_syndicate"
/obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative.
name = "cyborg syndicate pinpointer"
+1 -1
View File
@@ -186,7 +186,7 @@
return ..()
//Old ninja objectives.
/datum/objective_item/special/pinpointer
/datum/objective_item/special/pinpointer/nuke
name = "the captain's pinpointer."
targetitem = /obj/item/pinpointer
difficulty = 10
@@ -0,0 +1,10 @@
diff a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm (rejected hunks)
@@ -158,7 +158,7 @@
difficulty = 10
//Old ninja objectives.
-/datum/objective_item/special/pinpointer
+/datum/objective_item/special/pinpointer/nuke
name = "the captain's pinpointer."
targetitem = /obj/item/pinpointer
difficulty = 10
+3
View File
@@ -392,6 +392,9 @@
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
container_resist()
/obj/machinery/clonepod/container_resist(mob/living/user)
if(user.stat == CONSCIOUS)
go_out()
+12 -12
View File
@@ -14,6 +14,8 @@
var/damage_coeff
var/scan_level
var/precision_coeff
var/message_cooldown
var/breakout_time = 2
/obj/machinery/dna_scannernew/RefreshParts()
scan_level = 0
@@ -65,23 +67,20 @@
open_machine()
/obj/machinery/dna_scannernew/container_resist(mob/living/user)
var/breakout_time = 2
if(state_open || !locked) //Open and unlocked, no need to escape
state_open = TRUE
if(!locked)
open_machine()
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)</span>")
user.visible_message("<span class='italics'>You hear a metallic creaking from [src]!</span>")
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 [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
return
locked = FALSE
visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>")
to_chat(user, "<span class='notice'>You successfully break out of [src]!</span>")
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/dna_scannernew/proc/locate_computer(type_)
@@ -122,10 +121,11 @@
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
if(user.stat || locked)
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return
open_machine()
return
/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
+12 -11
View File
@@ -19,6 +19,8 @@ The console is located at computer/gulag_teleporter.dm
active_power_usage = 5000
circuit = /obj/item/circuitboard/machine/gulag_teleporter
var/locked = FALSE
var/message_cooldown
var/breakout_time = 1
var/jumpsuit_type = /obj/item/clothing/under/rank/prisoner
var/shoes_type = /obj/item/clothing/shoes/sneakers/orange
var/obj/machinery/gulag_item_reclaimer/linked_reclaimer
@@ -46,7 +48,7 @@ The console is located at computer/gulag_teleporter.dm
/obj/machinery/gulag_teleporter/interact(mob/user)
if(locked)
to_chat(user, "[src] is locked.")
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return
toggle_open()
@@ -89,28 +91,27 @@ The console is located at computer/gulag_teleporter.dm
if(user.stat != CONSCIOUS)
return
if(locked)
to_chat(user, "[src] is locked!")
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return
open_machine()
/obj/machinery/gulag_teleporter/container_resist(mob/living/user)
var/breakout_time = 600
if(!locked)
open_machine()
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about a minute.)</span>")
user.visible_message("<span class='italics'>You hear a metallic creaking from [src]!</span>")
if(do_after(user,(breakout_time), target = src))
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 [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
return
locked = FALSE
visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>")
to_chat(user, "<span class='notice'>You successfully break out of [src]!</span>")
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/gulag_teleporter/proc/locate_reclaimer()
+396 -369
View File
@@ -1,379 +1,406 @@
// SUIT STORAGE UNIT /////////////////
/obj/machinery/suit_storage_unit
name = "suit storage unit"
desc = "An industrial unit made to hold space suits. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
icon = 'icons/obj/suitstorage.dmi'
icon_state = "close"
// SUIT STORAGE UNIT /////////////////
/obj/machinery/suit_storage_unit
name = "suit storage unit"
desc = "An industrial unit made to hold space suits. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
icon = 'icons/obj/suitstorage.dmi'
icon_state = "close"
anchored = TRUE
density = TRUE
max_integrity = 250
var/obj/item/clothing/suit/space/suit = null
var/obj/item/clothing/head/helmet/space/helmet = null
var/obj/item/clothing/mask/mask = null
var/obj/item/storage = null
var/suit_type = null
var/helmet_type = null
var/mask_type = null
var/storage_type = null
state_open = FALSE
var/locked = FALSE
panel_open = FALSE
var/safeties = TRUE
var/uv = FALSE
var/uv_super = FALSE
var/uv_cycles = 6
/obj/machinery/suit_storage_unit/standard_unit
suit_type = /obj/item/clothing/suit/space/eva
helmet_type = /obj/item/clothing/head/helmet/space/eva
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/captain
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/jetpack/oxygen/captain
/obj/machinery/suit_storage_unit/engine
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/ce
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
mask_type = /obj/item/clothing/mask/breath
storage_type= /obj/item/clothing/shoes/magboots/advance
/obj/machinery/suit_storage_unit/security
suit_type = /obj/item/clothing/suit/space/hardsuit/security
mask_type = /obj/item/clothing/mask/gas/sechailer
/obj/machinery/suit_storage_unit/hos
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/internals/oxygen
/obj/machinery/suit_storage_unit/atmos
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
mask_type = /obj/item/clothing/mask/gas
storage_type = /obj/item/watertank/atmos
/obj/machinery/suit_storage_unit/mining
suit_type = /obj/item/clothing/suit/hooded/explorer
mask_type = /obj/item/clothing/mask/gas/explorer
/obj/machinery/suit_storage_unit/mining/eva
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/cmo
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/rd
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/syndicate
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
mask_type = /obj/item/clothing/mask/gas/syndicate
storage_type = /obj/item/tank/jetpack/oxygen/harness
/obj/machinery/suit_storage_unit/ert/command
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/security
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/engineer
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/medical
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
max_integrity = 250
var/obj/item/clothing/suit/space/suit = null
var/obj/item/clothing/head/helmet/space/helmet = null
var/obj/item/clothing/mask/mask = null
var/obj/item/storage = null
var/suit_type = null
var/helmet_type = null
var/mask_type = null
var/storage_type = null
state_open = FALSE
var/locked = FALSE
panel_open = FALSE
var/safeties = TRUE
var/uv = FALSE
var/uv_super = FALSE
var/uv_cycles = 6
var/message_cooldown
var/breakout_time = 0.5
/obj/machinery/suit_storage_unit/standard_unit
suit_type = /obj/item/clothing/suit/space/eva
helmet_type = /obj/item/clothing/head/helmet/space/eva
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/captain
suit_type = /obj/item/clothing/suit/space/hardsuit/captain
mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/jetpack/oxygen/captain
/obj/machinery/suit_storage_unit/engine
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/ce
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
mask_type = /obj/item/clothing/mask/breath
storage_type= /obj/item/clothing/shoes/magboots/advance
/obj/machinery/suit_storage_unit/security
suit_type = /obj/item/clothing/suit/space/hardsuit/security
mask_type = /obj/item/clothing/mask/gas/sechailer
/obj/machinery/suit_storage_unit/hos
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/internals/oxygen
/obj/machinery/suit_storage_unit/atmos
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
mask_type = /obj/item/clothing/mask/gas
storage_type = /obj/item/watertank/atmos
/obj/machinery/suit_storage_unit/mining
suit_type = /obj/item/clothing/suit/hooded/explorer
mask_type = /obj/item/clothing/mask/gas/explorer
/obj/machinery/suit_storage_unit/mining/eva
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/cmo
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/rd
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/syndicate
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
mask_type = /obj/item/clothing/mask/gas/syndicate
storage_type = /obj/item/tank/jetpack/oxygen/harness
/obj/machinery/suit_storage_unit/ert/command
suit_type = /obj/item/clothing/suit/space/hardsuit/ert
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/security
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/engineer
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/medical
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/Initialize()
. = ..()
wires = new /datum/wires/suit_storage_unit(src)
if(suit_type)
suit = new suit_type(src)
if(helmet_type)
helmet = new helmet_type(src)
if(mask_type)
mask = new mask_type(src)
if(storage_type)
storage = new storage_type(src)
update_icon()
/obj/machinery/suit_storage_unit/Destroy()
wires = new /datum/wires/suit_storage_unit(src)
if(suit_type)
suit = new suit_type(src)
if(helmet_type)
helmet = new helmet_type(src)
if(mask_type)
mask = new mask_type(src)
if(storage_type)
storage = new storage_type(src)
update_icon()
/obj/machinery/suit_storage_unit/Destroy()
QDEL_NULL(suit)
QDEL_NULL(helmet)
QDEL_NULL(mask)
QDEL_NULL(storage)
return ..()
/obj/machinery/suit_storage_unit/update_icon()
cut_overlays()
if(uv)
if(uv_super)
add_overlay("super")
else if(occupant)
add_overlay("uvhuman")
else
add_overlay("uv")
else if(state_open)
if(stat & BROKEN)
add_overlay("broken")
else
add_overlay("open")
if(suit)
add_overlay("suit")
if(helmet)
add_overlay("helm")
if(storage)
add_overlay("storage")
else if(occupant)
add_overlay("human")
/obj/machinery/suit_storage_unit/power_change()
..()
if(!is_operational() && state_open)
open_machine()
dump_contents()
update_icon()
/obj/machinery/suit_storage_unit/proc/dump_contents()
dropContents()
helmet = null
suit = null
mask = null
storage = null
occupant = null
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
return ..()
/obj/machinery/suit_storage_unit/update_icon()
cut_overlays()
if(uv)
if(uv_super)
add_overlay("super")
else if(occupant)
add_overlay("uvhuman")
else
add_overlay("uv")
else if(state_open)
if(stat & BROKEN)
add_overlay("broken")
else
add_overlay("open")
if(suit)
add_overlay("suit")
if(helmet)
add_overlay("helm")
if(storage)
add_overlay("storage")
else if(occupant)
add_overlay("human")
/obj/machinery/suit_storage_unit/power_change()
..()
if(!is_operational() && state_open)
open_machine()
dump_contents()
update_icon()
/obj/machinery/suit_storage_unit/proc/dump_contents()
dropContents()
helmet = null
suit = null
mask = null
storage = null
occupant = null
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
open_machine()
dump_contents()
new /obj/item/stack/sheet/metal (loc, 2)
qdel(src)
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
return
var/mob/living/target = A
if(!state_open)
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
return
if(!is_operational())
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
return
if(occupant || helmet || suit || storage)
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
return
if(target == user)
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
else
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
if(do_mob(user, target, 30))
if(occupant || helmet || suit || storage)
return
if(target == user)
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind them!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
else
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
close_machine(target)
add_fingerprint(user)
/obj/machinery/suit_storage_unit/proc/cook()
if(uv_cycles)
uv_cycles--
uv = TRUE
locked = TRUE
update_icon()
if(occupant)
var/mob/living/mob_occupant = occupant
if(uv_super)
mob_occupant.adjustFireLoss(rand(20, 36))
else
mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream")
addtimer(CALLBACK(src, .proc/cook), 50)
else
uv_cycles = initial(uv_cycles)
uv = FALSE
locked = FALSE
if(uv_super)
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
helmet = null
qdel(helmet)
suit = null
qdel(suit) // Delete everything but the occupant.
mask = null
qdel(mask)
storage = null
qdel(storage)
// The wires get damaged too.
wires.cut_all()
else
if(!occupant)
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
else
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
I.clean_blood()
I.fingerprints = list()
open_machine(FALSE)
if(occupant)
dump_contents()
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
if(!prob(prb))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
if(electrocute_mob(user, src, src, 1, TRUE))
return 1
/obj/machinery/suit_storage_unit/relaymove(mob/user)
container_resist(user)
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
add_fingerprint(user)
if(locked)
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", "<span class='notice'>You start kicking against the doors...</span>")
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
else
open_machine()
dump_contents()
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
visible_message("<span class='notice'>You see [user] bursts out of [src]!</span>", "<span class='notice'>You escape the cramped confines of [src]!</span>")
open_machine()
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(state_open && is_operational())
if(istype(I, /obj/item/clothing/suit/space))
if(suit)
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
return
if(!user.drop_item())
return
suit = I
else if(istype(I, /obj/item/clothing/head/helmet))
if(helmet)
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
return
if(!user.drop_item())
return
helmet = I
else if(istype(I, /obj/item/clothing/mask))
if(mask)
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
return
if(!user.drop_item())
return
mask = I
else
if(storage)
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
return
if(!user.drop_item())
return
storage = I
I.loc = src
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
update_icon()
return
if(panel_open && is_wire_tool(I))
wires.interact(user)
if(!state_open)
if(default_deconstruction_screwdriver(user, "panel", "close", I))
return
if(default_pry_open(I))
dump_contents()
return
return ..()
open_machine()
dump_contents()
new /obj/item/stack/sheet/metal (loc, 2)
qdel(src)
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
return
var/mob/living/target = A
if(!state_open)
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
return
if(!is_operational())
to_chat(user, "<span class='warning'>The unit is not operational!</span>")
return
if(occupant || helmet || suit || storage)
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
return
if(target == user)
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
else
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
if(do_mob(user, target, 30))
if(occupant || helmet || suit || storage)
return
if(target == user)
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind them!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
else
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
close_machine(target)
add_fingerprint(user)
/obj/machinery/suit_storage_unit/proc/cook()
if(uv_cycles)
uv_cycles--
uv = TRUE
locked = TRUE
update_icon()
if(occupant)
var/mob/living/mob_occupant = occupant
if(uv_super)
mob_occupant.adjustFireLoss(rand(20, 36))
else
mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream")
addtimer(CALLBACK(src, .proc/cook), 50)
else
uv_cycles = initial(uv_cycles)
uv = FALSE
locked = FALSE
if(uv_super)
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
helmet = null
qdel(helmet)
suit = null
qdel(suit) // Delete everything but the occupant.
mask = null
qdel(mask)
storage = null
qdel(storage)
// The wires get damaged too.
wires.cut_all()
else
if(!occupant)
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
else
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
I.clean_blood()
I.fingerprints = list()
open_machine(FALSE)
if(occupant)
dump_contents()
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
if(!prob(prb))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
if(electrocute_mob(user, src, src, 1, TRUE))
return 1
/obj/machinery/suit_storage_unit/relaymove(mob/user)
if(locked)
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return
open_machine()
dump_contents()
/obj/machinery/suit_storage_unit/container_resist(mob/living/user)
if(!locked)
open_machine()
dump_contents()
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
"<span class='notice'>You start kicking against the doors... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a thump from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
"<span class='notice'>You successfully break out of [src]!</span>")
open_machine()
dump_contents()
add_fingerprint(user)
if(locked)
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
"<span class='notice'>You start kicking against the doors...</span>")
addtimer(CALLBACK(src, .proc/resist_open, user), 300)
else
open_machine()
dump_contents()
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
visible_message("<span class='notice'>You see [user] bursts out of [src]!</span>", \
"<span class='notice'>You escape the cramped confines of [src]!</span>")
open_machine()
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(state_open && is_operational())
if(istype(I, /obj/item/clothing/suit/space))
if(suit)
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
return
if(!user.drop_item())
return
suit = I
else if(istype(I, /obj/item/clothing/head/helmet))
if(helmet)
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
return
if(!user.drop_item())
return
helmet = I
else if(istype(I, /obj/item/clothing/mask))
if(mask)
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
return
if(!user.drop_item())
return
mask = I
else
if(storage)
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
return
if(!user.drop_item())
return
storage = I
I.loc = src
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
update_icon()
return
if(panel_open && is_wire_tool(I))
wires.interact(user)
if(!state_open)
if(default_deconstruction_screwdriver(user, "panel", "close", I))
return
if(default_pry_open(I))
dump_contents()
return
return ..()
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/suit_storage_unit/ui_data()
var/list/data = list()
data["locked"] = locked
data["open"] = state_open
data["safeties"] = safeties
data["uv_active"] = uv
data["uv_super"] = uv_super
if(helmet)
data["helmet"] = helmet.name
if(suit)
data["suit"] = suit.name
if(mask)
data["mask"] = mask.name
if(storage)
data["storage"] = storage.name
if(occupant)
data["occupied"] = 1
return data
/obj/machinery/suit_storage_unit/ui_act(action, params)
if(..() || uv)
return
switch(action)
if("door")
if(state_open)
close_machine()
else
open_machine(0)
if(occupant)
dump_contents() // Dump out contents if someone is in there.
. = TRUE
if("lock")
locked = !locked
. = TRUE
if("uv")
if(occupant && safeties)
return
else if(!helmet && !mask && !suit && !storage && !occupant)
return
else
if(occupant)
var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
cook()
. = TRUE
if("dispense")
if(!state_open)
return
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
var/item_name = params["item"]
if(item_name in valid_items)
var/obj/item/I = vars[item_name]
vars[item_name] = null
if(I)
I.forceMove(loc)
. = TRUE
update_icon()
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
ui.open()
/obj/machinery/suit_storage_unit/ui_data()
var/list/data = list()
data["locked"] = locked
data["open"] = state_open
data["safeties"] = safeties
data["uv_active"] = uv
data["uv_super"] = uv_super
if(helmet)
data["helmet"] = helmet.name
if(suit)
data["suit"] = suit.name
if(mask)
data["mask"] = mask.name
if(storage)
data["storage"] = storage.name
if(occupant)
data["occupied"] = 1
return data
/obj/machinery/suit_storage_unit/ui_act(action, params)
if(..() || uv)
return
switch(action)
if("door")
if(state_open)
close_machine()
else
open_machine(0)
if(occupant)
dump_contents() // Dump out contents if someone is in there.
. = TRUE
if("lock")
locked = !locked
. = TRUE
if("uv")
if(occupant && safeties)
return
else if(!helmet && !mask && !suit && !storage && !occupant)
return
else
if(occupant)
var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
cook()
. = TRUE
if("dispense")
if(!state_open)
return
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
var/item_name = params["item"]
if(item_name in valid_items)
var/obj/item/I = vars[item_name]
vars[item_name] = null
if(I)
I.forceMove(loc)
. = TRUE
update_icon()
+1 -1
View File
@@ -869,7 +869,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/dropper = 3, /obj/item/stack/medical/gauze = 8, /obj/item/reagent_containers/pill/patch/styptic = 5, /obj/item/reagent_containers/pill/insulin = 10,
/obj/item/reagent_containers/pill/patch/silver_sulf = 5, /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/spray/medical/sterilizer = 1,
/obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/salglu_solution = 3,
/obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/device/healthanalyzer = 4, /obj/item/device/sensor_device = 2)
/obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/device/healthanalyzer = 4, /obj/item/device/sensor_device = 2, /obj/item/pinpointer/crew = 2)
contraband = list(/obj/item/reagent_containers/pill/tox = 3, /obj/item/reagent_containers/pill/morphine = 4, /obj/item/reagent_containers/pill/charcoal = 6)
premium = list(/obj/item/storage/box/hug/medical = 1, /obj/item/reagent_containers/hypospray/medipen = 3, /obj/item/storage/belt/medical = 3, /obj/item/wrench/medical = 1)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
@@ -58,7 +58,9 @@
/turf/open/floor/plating/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
for(var/turf/open/floor/plating/asteroid/M in range(1, drill.chassis))
if(get_dir(drill.chassis,M)&drill.chassis.dir)
M.gets_dug()
for(var/I in GetComponents(/datum/component/archaeology))
var/datum/component/archaeology/archy = I
archy.gets_dug()
drill.log_message("Drilled through [src]")
drill.move_ores()
+2 -1
View File
@@ -549,9 +549,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
transfer_blood = 0
/obj/item/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FOUR)
throw_at(S,14,3, spin=0)
else ..()
else return
/obj/item/throw_impact(atom/A)
if(A && !QDELETED(A))
@@ -90,7 +90,7 @@
return
if(!isnull(target) && !target.toff)
charges--
var/lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]"
var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
to_chat(U, "<span class='notice'>Virus Sent! The unlock code to the target is: [lock_code]</span>")
if(!target.hidden_uplink)
var/obj/item/device/uplink/uplink = new(target)
@@ -428,7 +428,7 @@
/obj/item/device/flashlight/glowstick/update_icon()
item_state = "glowstick"
overlays.Cut()
cut_overlays()
if(!fuel)
icon_state = "glowstick-empty"
cut_overlays()
@@ -0,0 +1,152 @@
//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk.
/obj/item/weapon/pinpointer
name = "pinpointer"
desc = "A handheld tracking device that locks onto certain signals."
icon = 'icons/obj/device.dmi'
icon_state = "pinpointer"
flags = CONDUCT
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL = 500, MAT_GLASS = 250)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/active = FALSE
var/atom/movable/target = null //The thing we're searching for
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/alert = FALSE // TRUE to display things more seriously
/obj/item/weapon/pinpointer/New()
..()
GLOB.pinpointer_list += src
/obj/item/weapon/pinpointer/Destroy()
STOP_PROCESSING(SSfastprocess, src)
GLOB.pinpointer_list -= src
return ..()
/obj/item/weapon/pinpointer/attack_self(mob/living/user)
active = !active
user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates their pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
if(active)
START_PROCESSING(SSfastprocess, src)
else
target = null
STOP_PROCESSING(SSfastprocess, src)
update_pointer_overlay()
/obj/item/weapon/pinpointer/process()
if(!active)
STOP_PROCESSING(SSfastprocess, src)
return
scan_for_target()
update_pointer_overlay()
/obj/item/weapon/pinpointer/proc/scan_for_target()
return
/obj/item/weapon/pinpointer/proc/update_pointer_overlay()
cut_overlays()
if(!active)
return
if(!target)
add_overlay("pinon[alert ? "alert" : ""]null")
var/turf/here = get_turf(src)
var/turf/there = get_turf(target)
if(here.z != there.z)
add_overlay("pinon[alert ? "alert" : ""]null")
return
if(get_dist_euclidian(here,there) <= minimum_range)
add_overlay("pinon[alert ? "alert" : ""]direct")
else
setDir(get_dir(here, there))
switch(get_dist(here, there))
if(1 to 8)
add_overlay("pinon[alert ? "alert" : "close"]")
if(9 to 16)
add_overlay("pinon[alert ? "alert" : "medium"]")
if(16 to INFINITY)
add_overlay("pinon[alert ? "alert" : "far"]")
/obj/item/weapon/pinpointer/crew // A replacement for the old crew monitoring consoles
name = "crew pinpointer"
desc = "A handheld tracking device that points to crew suit sensors."
icon_state = "pinpointer_crew"
/obj/item/weapon/pinpointer/crew/proc/trackable(mob/living/carbon/human/H)
var/turf/here = get_turf(src)
if((H.z == 0 || H.z == here.z) && istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = H.w_uniform
// Suit sensors must be on maximum.
if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS)
return FALSE
var/turf/there = get_turf(H)
return (H.z != 0 || (there && there.z == H.z))
return FALSE
/obj/item/weapon/pinpointer/crew/attack_self(mob/living/user)
if(active)
active = FALSE
user.visible_message("<span class='notice'>[user] deactivates their pinpointer.</span>", "<span class='notice'>You deactivate your pinpointer.</span>")
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
target = null //Restarting the pinpointer forces a target reset
STOP_PROCESSING(SSfastprocess, src)
update_pointer_overlay()
return
var/list/name_counts = list()
var/list/names = list()
for(var/mob/living/carbon/human/H in GLOB.mob_list)
if(!trackable(H))
continue
var/name = "Unknown"
if(H.wear_id)
var/obj/item/weapon/card/id/I = H.wear_id.GetID()
name = I.registered_name
while(name in name_counts)
name_counts[name]++
name = text("[] ([])", name, name_counts[name])
names[name] = H
name_counts[name] = 1
if(!names.len)
user.visible_message("<span class='notice'>[user]'s pinpointer fails to detect a signal.</span>", "<span class='notice'>Your pinpointer fails to detect a signal.</span>")
return
var/A = input(user, "Person to track", "Pinpoint") in names
if(!src || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !A)
return
target = names[A]
active = TRUE
user.visible_message("<span class='notice'>[user] activates their pinpointer.</span>", "<span class='notice'>You activate your pinpointer.</span>")
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
START_PROCESSING(SSfastprocess, src)
update_pointer_overlay()
/obj/item/weapon/pinpointer/crew/scan_for_target()
if(target)
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!trackable(H))
target = null
if(!target)
active = FALSE
/obj/item/weapon/pinpointer/process()
if(!active)
STOP_PROCESSING(SSfastprocess, src)
return
scan_for_target()
update_pointer_overlay()
@@ -86,7 +86,7 @@
icon_state = null
active = TRUE
if(tile_overlay)
loc.overlays += tile_overlay
loc.add_overlay(tile_overlay)
else
if(crossed)
trigger() //no cheesing.
+188 -187
View File
@@ -1,187 +1,188 @@
/obj/machinery/implantchair
name = "mindshield implanter"
desc = "Used to implant occupants with mindshield implants."
icon = 'icons/obj/machines/implantchair.dmi'
icon_state = "implantchair"
density = TRUE
opacity = 0
anchored = TRUE
var/ready = TRUE
var/replenishing = FALSE
var/ready_implants = 5
var/max_implants = 5
var/injection_cooldown = 600
var/replenish_cooldown = 6000
var/implant_type = /obj/item/implant/mindshield
var/auto_inject = FALSE
var/auto_replenish = TRUE
var/special = FALSE
var/special_name = "special function"
/obj/machinery/implantchair/Initialize()
. = ..()
open_machine()
update_icon()
/obj/machinery/implantchair/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, "implantchair", name, 375, 280, master_ui, state)
ui.open()
/obj/machinery/implantchair/ui_data()
var/list/data = list()
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
data["occupant"] = list()
if(occupant)
var/mob/living/mob_occupant = occupant
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
data["special_name"] = special ? special_name : null
data["ready_implants"] = ready_implants
data["ready"] = ready
data["replenishing"] = replenishing
return data
/obj/machinery/implantchair/ui_act(action, params)
if(..())
return
switch(action)
if("door")
if(state_open)
close_machine()
else
open_machine()
. = TRUE
if("implant")
implant(occupant,usr)
. = TRUE
/obj/machinery/implantchair/proc/implant(mob/living/M,mob/user)
if (!istype(M))
return
if(!ready_implants || !ready)
return
if(implant_action(M,user))
ready_implants--
if(!replenishing && auto_replenish)
replenishing = TRUE
addtimer(CALLBACK(src,"replenish"),replenish_cooldown)
if(injection_cooldown > 0)
ready = FALSE
addtimer(CALLBACK(src,"set_ready"),injection_cooldown)
else
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, 1)
update_icon()
/obj/machinery/implantchair/proc/implant_action(mob/living/M)
var/obj/item/implant/I = new implant_type
if(I.implant(M))
visible_message("<span class='warning'>[M] has been implanted by the [name].</span>")
return 1
/obj/machinery/implantchair/update_icon()
icon_state = initial(icon_state)
if(state_open)
icon_state += "_open"
if(occupant)
icon_state += "_occupied"
if(ready)
add_overlay("ready")
else
cut_overlays()
/obj/machinery/implantchair/proc/replenish()
if(ready_implants < max_implants)
ready_implants++
if(ready_implants < max_implants)
addtimer(CALLBACK(src,"replenish"),replenish_cooldown)
else
replenishing = FALSE
/obj/machinery/implantchair/proc/set_ready()
ready = TRUE
update_icon()
/obj/machinery/implantchair/container_resist(mob/living/user)
if(state_open)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about about a minute.)</span>")
audible_message("<span class='italics'>You hear a metallic creaking from [src]!</span>",hearing_distance = 2)
if(do_after(user, 600, target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
return
visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>")
to_chat(user, "<span class='notice'>You successfully break out of [src]!</span>")
open_machine()
/obj/machinery/implantchair/relaymove(mob/user)
container_resist(user)
/obj/machinery/implantchair/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser())
return
close_machine(target)
/obj/machinery/implantchair/close_machine(mob/living/user)
if((isnull(user) || istype(user)) && state_open)
..(user)
if(auto_inject && ready && ready_implants > 0)
implant(user,null)
/obj/machinery/implantchair/genepurge
name = "Genetic purifier"
desc = "Used to purge human genome of foreign influences"
special = TRUE
special_name = "Purge genome"
injection_cooldown = 0
replenish_cooldown = 300
/obj/machinery/implantchair/genepurge/implant_action(mob/living/carbon/human/H,mob/user)
if(!istype(H))
return 0
H.set_species(/datum/species/human, 1)//lizards go home
purrbation_remove(H)//remove cats
H.dna.remove_all_mutations()//hulks out
return 1
/obj/machinery/implantchair/brainwash
name = "Neural Imprinter"
desc = "Used to <s>indoctrinate</s> rehabilitate hardened recidivists."
special_name = "Imprint"
injection_cooldown = 3000
auto_inject = FALSE
auto_replenish = FALSE
special = TRUE
var/objective = "Obey the law. Praise Nanotrasen."
var/custom = FALSE
/obj/machinery/implantchair/brainwash/implant_action(mob/living/C,mob/user)
if(!istype(C) || !C.mind) // I don't know how this makes any sense for silicons but laws trump objectives anyway.
return 0
if(custom)
if(!user || !user.Adjacent(src))
return 0
objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120)
message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
log_game("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
var/datum/objective/custom_objective = new/datum/objective(objective)
custom_objective.owner = C.mind
C.mind.objectives += custom_objective
C.mind.announce_objectives()
message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
return 1
/obj/machinery/implantchair
name = "mindshield implanter"
desc = "Used to implant occupants with mindshield implants."
icon = 'icons/obj/machines/implantchair.dmi'
icon_state = "implantchair"
density = TRUE
opacity = 0
anchored = TRUE
var/ready = TRUE
var/replenishing = FALSE
var/ready_implants = 5
var/max_implants = 5
var/injection_cooldown = 600
var/replenish_cooldown = 6000
var/implant_type = /obj/item/implant/mindshield
var/auto_inject = FALSE
var/auto_replenish = TRUE
var/special = FALSE
var/special_name = "special function"
var/message_cooldown
var/breakout_time = 1
/obj/machinery/implantchair/Initialize()
. = ..()
open_machine()
update_icon()
/obj/machinery/implantchair/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, "implantchair", name, 375, 280, master_ui, state)
ui.open()
/obj/machinery/implantchair/ui_data()
var/list/data = list()
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
data["occupant"] = list()
if(occupant)
var/mob/living/mob_occupant = occupant
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
data["special_name"] = special ? special_name : null
data["ready_implants"] = ready_implants
data["ready"] = ready
data["replenishing"] = replenishing
return data
/obj/machinery/implantchair/ui_act(action, params)
if(..())
return
switch(action)
if("door")
if(state_open)
close_machine()
else
open_machine()
. = TRUE
if("implant")
implant(occupant,usr)
. = TRUE
/obj/machinery/implantchair/proc/implant(mob/living/M,mob/user)
if (!istype(M))
return
if(!ready_implants || !ready)
return
if(implant_action(M,user))
ready_implants--
if(!replenishing && auto_replenish)
replenishing = TRUE
addtimer(CALLBACK(src,"replenish"),replenish_cooldown)
if(injection_cooldown > 0)
ready = FALSE
addtimer(CALLBACK(src,"set_ready"),injection_cooldown)
else
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, 1)
update_icon()
/obj/machinery/implantchair/proc/implant_action(mob/living/M)
var/obj/item/implant/I = new implant_type
if(I.implant(M))
visible_message("<span class='warning'>[M] has been implanted by the [name].</span>")
return 1
/obj/machinery/implantchair/update_icon()
icon_state = initial(icon_state)
if(state_open)
icon_state += "_open"
if(occupant)
icon_state += "_occupied"
if(ready)
add_overlay("ready")
else
cut_overlays()
/obj/machinery/implantchair/proc/replenish()
if(ready_implants < max_implants)
ready_implants++
if(ready_implants < max_implants)
addtimer(CALLBACK(src,"replenish"),replenish_cooldown)
else
replenishing = FALSE
/obj/machinery/implantchair/proc/set_ready()
ready = TRUE
update_icon()
/obj/machinery/implantchair/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 [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
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/implantchair/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/implantchair/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser())
return
close_machine(target)
/obj/machinery/implantchair/close_machine(mob/living/user)
if((isnull(user) || istype(user)) && state_open)
..(user)
if(auto_inject && ready && ready_implants > 0)
implant(user,null)
/obj/machinery/implantchair/genepurge
name = "Genetic purifier"
desc = "Used to purge human genome of foreign influences"
special = TRUE
special_name = "Purge genome"
injection_cooldown = 0
replenish_cooldown = 300
/obj/machinery/implantchair/genepurge/implant_action(mob/living/carbon/human/H,mob/user)
if(!istype(H))
return 0
H.set_species(/datum/species/human, 1)//lizards go home
purrbation_remove(H)//remove cats
H.dna.remove_all_mutations()//hulks out
return 1
/obj/machinery/implantchair/brainwash
name = "Neural Imprinter"
desc = "Used to <s>indoctrinate</s> rehabilitate hardened recidivists."
special_name = "Imprint"
injection_cooldown = 3000
auto_inject = FALSE
auto_replenish = FALSE
special = TRUE
var/objective = "Obey the law. Praise Nanotrasen."
var/custom = FALSE
/obj/machinery/implantchair/brainwash/implant_action(mob/living/C,mob/user)
if(!istype(C) || !C.mind) // I don't know how this makes any sense for silicons but laws trump objectives anyway.
return 0
if(custom)
if(!user || !user.Adjacent(src))
return 0
objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120)
message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
log_game("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
var/datum/objective/custom_objective = new/datum/objective(objective)
custom_objective.owner = C.mind
C.mind.objectives += custom_objective
C.mind.announce_objectives()
message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
return 1
+150
View File
@@ -0,0 +1,150 @@
//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk.
/obj/item/pinpointer
name = "pinpointer"
desc = "A handheld tracking device that locks onto certain signals."
icon = 'icons/obj/device.dmi'
icon_state = "pinpointer"
flags_1 = CONDUCT_1
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL = 500, MAT_GLASS = 250)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/active = FALSE
var/atom/movable/target //The thing we're searching for
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/alert = FALSE // TRUE to display things more seriously
/obj/item/pinpointer/Initialize()
. = ..()
GLOB.pinpointer_list += src
/obj/item/pinpointer/Destroy()
STOP_PROCESSING(SSfastprocess, src)
GLOB.pinpointer_list -= src
return ..()
/obj/item/pinpointer/attack_self(mob/living/user)
active = !active
user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates their pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
if(active)
START_PROCESSING(SSfastprocess, src)
else
target = null
STOP_PROCESSING(SSfastprocess, src)
update_icon()
/obj/item/pinpointer/process()
if(!active)
return PROCESS_KILL
scan_for_target()
update_icon()
/obj/item/pinpointer/proc/scan_for_target()
return
/obj/item/pinpointer/update_icon()
cut_overlays()
if(!active)
return
if(!target)
add_overlay("pinon[alert ? "alert" : ""]null")
var/turf/here = get_turf(src)
var/turf/there = get_turf(target)
if(here.z != there.z)
add_overlay("pinon[alert ? "alert" : ""]null")
return
if(get_dist_euclidian(here,there) <= minimum_range)
add_overlay("pinon[alert ? "alert" : ""]direct")
else
setDir(get_dir(here, there))
switch(get_dist(here, there))
if(1 to 8)
add_overlay("pinon[alert ? "alert" : "close"]")
if(9 to 16)
add_overlay("pinon[alert ? "alert" : "medium"]")
if(16 to INFINITY)
add_overlay("pinon[alert ? "alert" : "far"]")
/obj/item/pinpointer/crew // A replacement for the old crew monitoring consoles
name = "crew pinpointer"
desc = "A handheld tracking device that points to crew suit sensors."
icon_state = "pinpointer_crew"
/obj/item/pinpointer/crew/proc/trackable(mob/living/carbon/human/H)
var/turf/here = get_turf(src)
if((H.z == 0 || H.z == here.z) && istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = H.w_uniform
// Suit sensors must be on maximum.
if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS)
return FALSE
var/turf/there = get_turf(H)
return (H.z != 0 || (there && there.z == H.z))
return FALSE
/obj/item/pinpointer/crew/attack_self(mob/living/user)
if(active)
active = FALSE
user.visible_message("<span class='notice'>[user] deactivates their pinpointer.</span>", "<span class='notice'>You deactivate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
target = null //Restarting the pinpointer forces a target reset
STOP_PROCESSING(SSfastprocess, src)
update_icon()
return
var/list/name_counts = list()
var/list/names = list()
for(var/mob/living/carbon/human/H in GLOB.mob_list)
if(!trackable(H))
continue
var/crewmember_name = "Unknown"
if(H.wear_id)
var/obj/item/card/id/I = H.wear_id.GetID()
crewmember_name = I.registered_name
while(crewmember_name in name_counts)
name_counts[crewmember_name]++
crewmember_name = text("[] ([])", crewmember_name, name_counts[crewmember_name])
names[crewmember_name] = H
name_counts[crewmember_name] = 1
if(!names.len)
user.visible_message("<span class='notice'>[user]'s pinpointer fails to detect a signal.</span>", "<span class='notice'>Your pinpointer fails to detect a signal.</span>")
return
var/A = input(user, "Person to track", "Pinpoint") in names
if(!A || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated())
return
target = names[A]
active = TRUE
user.visible_message("<span class='notice'>[user] activates their pinpointer.</span>", "<span class='notice'>You activate your pinpointer.</span>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
START_PROCESSING(SSfastprocess, src)
update_icon()
/obj/item/pinpointer/crew/scan_for_target()
if(target)
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!trackable(H))
target = null
if(!target) //target can be set to null from above code, or elsewhere
active = FALSE
/obj/item/pinpointer/process()
if(!active)
return PROCESS_KILL
scan_for_target()
update_icon()
+187 -13
View File
@@ -1,27 +1,201 @@
/obj/item/banner
name = "banner"
desc = "A banner with Nanotrasen's logo on it."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "banner"
item_state = "banner"
force = 8
attack_verb = list("forcefully inspired", "violently encouraged", "relentlessly galvanized")
lefthand_file = 'icons/mob/inhands/equipment/banners_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/banners_righthand.dmi'
desc = "A banner with Nanotrasen's logo on it."
var/moralecooldown = 0
var/moralewait = 600
var/inspiration_available = TRUE //If this banner can be used to inspire crew
var/morale_time = 0
var/morale_cooldown = 600 //How many deciseconds between uses
var/list/job_loyalties //Mobs with any of these assigned roles will be inspired
var/list/role_loyalties //Mobs with any of these special roles will be inspired
var/warcry
/obj/item/banner/examine(mob/user)
..()
if(inspiration_available)
to_chat(user, "<span class='notice'>Activate it in your hand to inspire nearby allies of this banner's allegiance!</span>")
/obj/item/banner/attack_self(mob/living/carbon/human/user)
if(moralecooldown + moralewait > world.time)
if(!inspiration_available)
return
to_chat(user, "<span class='notice'>You increase the morale of your fellows!</span>")
moralecooldown = world.time
if(morale_time > world.time)
to_chat(user, "<span class='warning'>You aren't feeling inspired enough to flourish [src] again yet.</span>")
return
user.visible_message("<span class='big notice'>[user] flourishes [src]!</span>", \
"<span class='notice'>You raise [src] skywards, inspiring your allies!</span>")
playsound(src, "rustle", 100, FALSE)
if(warcry)
user.say("[warcry]")
var/old_transform = user.transform
user.transform *= 1.2
animate(user, transform = old_transform, time = 10)
morale_time = world.time + morale_cooldown
for(var/mob/living/carbon/human/H in range(4,get_turf(src)))
to_chat(H, "<span class='notice'>Your morale is increased by [user]'s banner!</span>")
H.adjustBruteLoss(-15)
H.adjustFireLoss(-15)
H.AdjustStun(-40)
H.AdjustKnockdown(-40)
H.AdjustUnconscious(-40)
var/list/inspired = list()
var/has_job_loyalties = LAZYLEN(job_loyalties)
var/has_role_loyalties = LAZYLEN(role_loyalties)
inspired += user //The user is always inspired, regardless of loyalties
for(var/mob/living/carbon/human/H in range(4, get_turf(src)))
if(H.stat == DEAD || H == user)
continue
if(H.mind && (has_job_loyalties || has_role_loyalties))
if(has_job_loyalties && H.mind.assigned_role in job_loyalties)
inspired += H
else if(has_role_loyalties && H.mind.special_role in role_loyalties)
inspired += H
else if(check_inspiration(H))
inspired += H
for(var/V in inspired)
var/mob/living/carbon/human/H = V
if(H != user)
to_chat(H, "<span class='notice'>Your confidence surges as [user] flourishes [user.p_their()] [name]!</span>")
inspiration(H)
special_inspiration(H)
/obj/item/banner/proc/check_inspiration(mob/living/carbon/human/H) //Banner-specific conditions for being eligible
return
/obj/item/banner/proc/inspiration(mob/living/carbon/human/H)
H.adjustBruteLoss(-15)
H.adjustFireLoss(-15)
H.AdjustStun(-40)
H.AdjustKnockdown(-40)
H.AdjustUnconscious(-40)
playsound(H, 'sound/magic/staff_healing.ogg', 25, FALSE)
/obj/item/banner/proc/special_inspiration(mob/living/carbon/human/H) //Any banner-specific inspiration effects go here
return
/obj/item/banner/security
name = "securistan banner"
desc = "The banner of Securistan, ruling the station with an iron fist."
icon_state = "banner_security"
job_loyalties = list("Security Officer", "Warden", "Detective", "Head of Security")
warcry = "EVERYONE DOWN ON THE GROUND!!"
/obj/item/banner/security/mundane
inspiration_available = FALSE
/datum/crafting_recipe/security_banner
name = "Securistan Banner"
result = /obj/item/banner/security/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/security = 1)
category = CAT_MISC
/obj/item/banner/medical
name = "meditopia banner"
desc = "The banner of Meditopia, generous benefactors that cure wounds and shelter the weak."
icon_state = "banner_medical"
job_loyalties = list("Medical Doctor", "Chemist", "Geneticist", "Virologist", "Chief Medical Officer")
warcry = "No wounds cannot be healed!"
/obj/item/banner/medical/mundane
inspiration_available = FALSE
/obj/item/banner/medical/check_inspiration(mob/living/carbon/human/H)
return H.stat //Meditopia is moved to help those in need
/datum/crafting_recipe/medical_banner
name = "Meditopia Banner"
result = /obj/item/banner/medical/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/medical = 1)
category = CAT_MISC
/obj/item/banner/medical/special_inspiration(mob/living/carbon/human/H)
H.adjustToxLoss(-15)
H.setOxyLoss(0)
H.reagents.add_reagent("inaprovaline", 5)
/obj/item/banner/science
name = "sciencia banner"
desc = "The banner of Sciencia, bold and daring thaumaturges and researchers that take the path less traveled."
icon_state = "banner_science"
job_loyalties = list("Scientist", "Roboticist", "Research Director")
warcry = "For Cuban Pete!"
/obj/item/banner/science/mundane
inspiration_available = FALSE
/obj/item/banner/science/check_inspiration(mob/living/carbon/human/H)
return H.on_fire //Sciencia is pleased by dedication to the art of Toxins
/datum/crafting_recipe/science_banner
name = "Sciencia Banner"
result = /obj/item/banner/science/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/scientist = 1)
category = CAT_MISC
/obj/item/banner/cargo
name = "cargonia banner"
desc = "The banner of the eternal Cargonia, with the mystical power of conjuring any object into existence."
icon_state = "banner_cargo"
job_loyalties = list("Cargo Technician", "Shaft Miner", "Quartermaster")
warcry = "Hail Cargonia!"
/obj/item/banner/cargo/mundane
inspiration_available = FALSE
/datum/crafting_recipe/cargo_banner
name = "Cargonia Banner"
result = /obj/item/banner/cargo/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/cargotech = 1)
category = CAT_MISC
/obj/item/banner/engineering
name = "engitopia banner"
desc = "The banner of Engitopia, wielders of limitless power."
icon_state = "banner_engineering"
job_loyalties = list("Station Engineer", "Atmospheric Technician", "Chief Engineer")
warcry = "All hail lord Singuloth!!"
/obj/item/banner/engineering/mundane
inspiration_available = FALSE
/obj/item/banner/engineering/special_inspiration(mob/living/carbon/human/H)
H.radiation = 0
/datum/crafting_recipe/engineering_banner
name = "Engitopia Banner"
result = /obj/item/banner/engineering/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/rank/engineer = 1)
category = CAT_MISC
/obj/item/banner/command
name = "command banner"
desc = "The banner of Command, a staunch and ancient line of bueraucratic kings and queens."
//No icon state here since the default one is the NT banner
job_loyalties = list("Captain", "Head of Personnel", "Chief Engineer", "Head of Security", "Research Director", "Chief Medical Officer")
warcry = "Hail Nanotrasen!"
/obj/item/banner/command/mundane
inspiration_available = FALSE
/obj/item/banner/command/check_inspiration(mob/living/carbon/human/H)
return H.isloyal() //Command is stalwart but rewards their allies.
/datum/crafting_recipe/command_banner
name = "Command Banner"
result = /obj/item/banner/command/mundane
time = 40
reqs = list(/obj/item/stack/rods = 2,
/obj/item/clothing/under/captainparade = 1)
category = CAT_MISC
/obj/item/banner/red
name = "red banner"
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -487,7 +487,7 @@
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
flags_1 = CONDUCT_1
force = 13
var/force_on = 21
var/force_on = 24
w_class = WEIGHT_CLASS_HUGE
throwforce = 13
throw_speed = 2
File diff suppressed because it is too large Load Diff
+1
View File
@@ -169,6 +169,7 @@
return
/obj/singularity_pull(S, current_size)
..()
if(!anchored || current_size >= STAGE_FIVE)
step_towards(src,S)
@@ -16,7 +16,7 @@
integrity_failure = 50
armor = list(melee = 20, bullet = 10, laser = 10, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 70, acid = 60)
var/breakout_time = 2
var/lastbang
var/message_cooldown
var/can_weld_shut = TRUE
var/horizontal = FALSE
var/allow_objects = FALSE
@@ -300,14 +300,12 @@
/obj/structure/closet/relaymove(mob/user)
if(user.stat || !isturf(loc) || !isliving(user))
return
var/mob/living/L = user
if(!open())
if(L.last_special <= world.time)
container_resist(L)
if(world.time > lastbang+5)
lastbang = world.time
for(var/mob/M in get_hearers_in_view(src, null))
M.show_message("<FONT size=[max(0, 5 - get_dist(src, M))]>BANG, bang!</FONT>", 2)
if(locked)
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return
container_resist()
/obj/structure/closet/attack_hand(mob/user)
..()
@@ -367,9 +365,10 @@
//okay, so the closet is either welded or locked... resist!!!
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
to_chat(user, "<span class='notice'>You lean on the back of [src] and start pushing the door open.</span>")
visible_message("<span class='warning'>[src] begins to shake violently!</span>")
if(do_after(user,(breakout_time * 60 * 10), target = src)) //minutes * 60seconds * 10deciseconds
user.visible_message("<span class='warning'>[src] begins to shake violently!</span>", \
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear banging from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) )
return
//we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting
@@ -388,7 +387,7 @@
/obj/structure/closet/AltClick(mob/user)
..()
if(!user.canUseTopic(src, be_close=TRUE))
if(!user.canUseTopic(src, be_close=TRUE) || isturf(loc))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(opened || !secure)
@@ -83,7 +83,7 @@
new /obj/item/storage/belt/security/full(src)
new /obj/item/gun/energy/e_gun/hos(src)
new /obj/item/device/flashlight/seclite(src)
new /obj/item/pinpointer(src)
new /obj/item/pinpointer/nuke(src)
/obj/structure/closet/secure_closet/warden
name = "\proper warden's locker"
@@ -108,6 +108,7 @@
new /obj/item/clothing/gloves/krav_maga/sec(src)
new /obj/item/door_remote/head_of_security(src)
new /obj/item/gun/ballistic/shotgun/automatic/combat/compact(src)
new /obj/item/pinpointer/crew(src)
/obj/structure/closet/secure_closet/security
name = "security officer's locker"
@@ -183,6 +184,7 @@
new /obj/item/reagent_containers/spray/pepper(src)
new /obj/item/clothing/suit/armor/vest/det_suit(src)
new /obj/item/storage/belt/holster/full(src)
new /obj/item/pinpointer/crew(src)
new /obj/item/device/mass_spectrometer(src)
/obj/structure/closet/secure_closet/injection
+1
View File
@@ -45,6 +45,7 @@
qdel(src)
/obj/structure/lattice/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FOUR)
deconstruct()
+21 -5
View File
@@ -23,6 +23,8 @@
var/obj/structure/tray/connected = null
var/locked = FALSE
var/opendir = SOUTH
var/message_cooldown
var/breakout_time = 1
/obj/structure/bodycontainer/Destroy()
open()
@@ -41,6 +43,11 @@
/obj/structure/bodycontainer/relaymove(mob/user)
if(user.stat || !isturf(loc))
return
if(locked)
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return
open()
/obj/structure/bodycontainer/attack_paw(mob/user)
@@ -84,11 +91,20 @@
qdel(src)
/obj/structure/bodycontainer/container_resist(mob/living/user)
open()
/obj/structure/bodycontainer/relay_container_resist(mob/living/user, obj/O)
to_chat(user, "<span class='notice'>You slam yourself into the side of [O].</span>")
container_resist(user)
if(!locked)
open()
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message(null, \
"<span class='notice'>You lean on the back of [src] and start pushing the tray open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
"<span class='notice'>You successfully break out of [src]!</span>")
open()
/obj/structure/bodycontainer/proc/open()
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
@@ -30,6 +30,7 @@
return ..()
/obj/structure/transit_tube/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
@@ -62,10 +62,14 @@
AM.ex_act(severity, target)
/obj/structure/transit_tube_pod/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
/obj/structure/transit_tube_pod/container_resist(mob/living/user)
if(!user.incapacitated())
empty_pod()
return
if(!moving)
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
+1
View File
@@ -105,6 +105,7 @@
qdel(src)
/obj/structure/window/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
+3
View File
@@ -4,6 +4,9 @@
var/wet = 0
var/wet_time = 0 // Time in seconds that this floor will be wet for.
var/mutable_appearance/wet_overlay
var/postdig_icon_change = FALSE
var/postdig_icon
var/list/archdrops
/turf/open/indestructible
name = "floor"
+1
View File
@@ -170,6 +170,7 @@
return make_plating()
/turf/open/floor/singularity_pull(S, current_size)
..()
if(current_size == STAGE_THREE)
if(prob(30))
if(floor_tile)
@@ -269,6 +269,7 @@
narsie_act(force, ignore_mobs, probability)
/turf/open/floor/vines/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
if(prob(50))
ChangeTurf(src.baseturf)
@@ -9,11 +9,11 @@
icon = 'icons/turf/floors.dmi'
icon_state = "asteroid"
icon_plating = "asteroid"
postdig_icon_change = TRUE
var/environment_type = "asteroid"
var/turf_type = /turf/open/floor/plating/asteroid //Because caves do whacky shit to revert to normal
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
var/sand_type = /obj/item/ore/glass
var/floor_variance = 20 //probability floor has a different icon state
archdrops = list(/obj/item/ore/glass = 5)
/turf/open/floor/plating/asteroid/Initialize()
var/proper_name = name
@@ -22,6 +22,9 @@
if(prob(floor_variance))
icon_state = "[environment_type][rand(0,12)]"
if(LAZYLEN(archdrops))
AddComponent(/datum/component/archaeology, 100, archdrops)
/turf/open/floor/plating/asteroid/burn_tile()
return
@@ -31,46 +34,7 @@
/turf/open/floor/plating/asteroid/MakeDry(wet_setting = TURF_WET_WATER)
return
/turf/open/floor/plating/asteroid/ex_act(severity, target)
contents_explosion(severity, target)
switch(severity)
if(3)
return
if(2)
if(prob(20))
src.gets_dug()
if(1)
src.gets_dug()
/turf/open/floor/plating/asteroid/attackby(obj/item/W, mob/user, params)
//note that this proc does not call ..()
if(!W || !user)
return 0
var/digging_speed = 0
if (istype(W, /obj/item/shovel))
var/obj/item/shovel/S = W
digging_speed = S.digspeed
else if (istype(W, /obj/item/pickaxe))
var/obj/item/pickaxe/P = W
digging_speed = P.digspeed
if (digging_speed)
var/turf/T = user.loc
if(!isturf(T))
return
if (dug)
to_chat(user, "<span class='warning'>This area has already been dug!</span>")
return
to_chat(user, "<span class='notice'>You start digging...</span>")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
if(do_after(user, digging_speed, target = src))
if(istype(src, /turf/open/floor/plating/asteroid))
to_chat(user, "<span class='notice'>You dig a hole.</span>")
gets_dug()
SSblackbox.add_details("pick_used_mining","[W.type]")
if(istype(W, /obj/item/storage/bag/ore))
var/obj/item/storage/bag/ore/S = W
if(S.collection_mode == 1)
@@ -88,37 +52,16 @@
var/turf/open/floor/light/F = T
F.state = L.state
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
/turf/open/floor/plating/asteroid/proc/gets_dug()
if(dug)
return
for(var/i in 1 to 5)
new sand_type(src)
dug = 1
icon_plating = "[environment_type]_dug"
icon_state = "[environment_type]_dug"
slowdown = 0
return
return ..()
/turf/open/floor/plating/asteroid/singularity_act()
if(turf_z_is_planet(src))
return ..()
ChangeTurf(/turf/open/space)
/turf/open/floor/plating/asteroid/singularity_pull(S, current_size)
if(dug)
return
switch(current_size)
if(STAGE_THREE)
if(!prob(30))
gets_dug()
if(STAGE_FOUR)
if(prob(50))
gets_dug()
else
if(current_size >= STAGE_FIVE && prob(70))
gets_dug()
/turf/open/floor/plating/asteroid/basalt
name = "volcanic floor"
@@ -127,7 +70,7 @@
icon_state = "basalt"
icon_plating = "basalt"
environment_type = "basalt"
sand_type = /obj/item/ore/glass/basalt
archdrops = list(/obj/item/ore/glass/basalt = 5)
floor_variance = 15
/turf/open/floor/plating/asteroid/basalt/lava //lava underneath
@@ -147,10 +90,10 @@
if("basalt5", "basalt9")
B.set_light(1.4, 0.6, LIGHT_COLOR_LAVA) //barely anything!
/turf/open/floor/plating/asteroid/basalt/gets_dug()
if(!dug)
set_light(0)
/turf/open/floor/plating/asteroid/basalt/ComponentActivated(datum/component/C)
..()
if(istype(C, /datum/component/archaeology))
set_light(0)
///////Surface. The surface is warm, but survivable without a suit. Internals are required. The floors break to chasms, which drop you into the underground.
@@ -340,8 +283,8 @@
initial_gas_mix = "TEMP=180"
slowdown = 2
environment_type = "snow"
sand_type = /obj/item/stack/sheet/mineral/snow
flags_1 = NONE
archdrops = list(/obj/item/stack/sheet/mineral/snow = 5)
/turf/open/floor/plating/asteroid/snow/airless
initial_gas_mix = "TEMP=2.7"
@@ -58,6 +58,7 @@
make_plating(1)
/turf/open/floor/engine/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
if(floor_tile)
if(prob(30))
@@ -247,6 +247,7 @@
icon_state = "r_wall"
/turf/closed/wall/r_wall/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
if(prob(30))
dismantle_wall()
+1
View File
@@ -245,6 +245,7 @@
QDEL_IN(O, 50)
/turf/closed/wall/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
if(prob(50))
dismantle_wall()
+2 -2
View File
@@ -524,12 +524,12 @@
/turf/proc/photograph(limit=20)
var/image/I = new()
I.overlays += src
I.add_overlay(src)
for(var/V in contents)
var/atom/A = V
if(A.invisibility)
continue
I.overlays += A
I.add_overlay(A)
if(limit)
limit--
else
+19
View File
@@ -1,3 +1,6 @@
GLOBAL_VAR(security_mode)
GLOBAL_PROTECT(security_mode)
/world/New()
log_world("World loaded at [time_stamp()]")
@@ -5,6 +8,8 @@
GLOB.config_error_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
CheckSecurityMode()
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
config = new
@@ -94,6 +99,20 @@
if(GLOB.round_id)
log_game("Round ID: [GLOB.round_id]")
/world/proc/CheckSecurityMode()
//try to write to data
if(!text2file("The world is running at least safe mode", "data/server_security_check.lock"))
GLOB.security_mode = SECURITY_ULTRASAFE
warning("/tg/station 13 is not supported in ultrasafe security mode. Everything will break!")
return
//try to shell
if(shell("echo \"The world is running in trusted mode\"") != null)
GLOB.security_mode = SECURITY_TRUSTED
else
GLOB.security_mode = SECURITY_SAFE
warning("/tg/station 13 uses many file operations, a few shell()s, and some external call()s. Trusted mode is recommended. You can download our source code for your own browsing and compilation at https://github.com/tgstation/tgstation")
/world/Topic(T, addr, master, key)
var/list/input = params2list(T)
+4
View File
@@ -49,6 +49,10 @@
open_machine()
/obj/machinery/vr_sleeper/container_resist(mob/living/user)
open_machine()
/obj/machinery/vr_sleeper/Destroy()
open_machine()
cleanup_vr_human()
+2
View File
@@ -22,6 +22,8 @@
return 0
/proc/jobban_buildcache(client/C)
if(!SSdbcore.Connect())
return
if(C && istype(C))
C.jobbancache = list()
var/datum/DBQuery/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+2 -2
View File
@@ -50,8 +50,8 @@ GLOBAL_VAR_INIT(highlander, FALSE)
equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears)
equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head)
equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_l_store)
for(var/obj/item/pinpointer/P in src)
equip_to_slot_or_del(new /obj/item/pinpointer/nuke(src), slot_l_store)
for(var/obj/item/pinpointer/nuke/P in src)
P.attack_self(src)
var/obj/item/card/id/W = new(src)
W.icon_state = "centcom"
+3
View File
@@ -135,4 +135,7 @@
for(var/mob/M in GLOB.player_list)
if(M.client)
SEND_SOUND(M, sound(null))
var/client/C = M.client
if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
C.chatOutput.sendMusic(" ")
SSblackbox.add_details("admin_verb","Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -222,6 +222,7 @@ Pipelines + Other Objects -> Pipe network
build_network()
/obj/machinery/atmospherics/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
@@ -32,6 +32,8 @@
var/running_bob_anim = FALSE
var/escape_in_progress = FALSE
var/message_cooldown
var/breakout_time = 0.5
/obj/machinery/atmospherics/components/unary/cryo_cell/Initialize()
. = ..()
@@ -219,7 +221,9 @@
update_icon()
/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/user)
container_resist(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/atmospherics/components/unary/cryo_cell/open_machine(drop = 0)
if(!state_open && !panel_open)
@@ -239,16 +243,17 @@
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user)
if(escape_in_progress)
to_chat(user, "<span class='notice'>You are already trying to exit (This will take around 30 seconds)</span>")
return
escape_in_progress = TRUE
to_chat(user, "<span class='notice'>You struggle inside the cryotube, kicking the release with your foot... (This will take around 30 seconds.)</span>")
audible_message("<span class='notice'>You hear a thump from [src].</span>")
if(do_after(user, 300))
if(occupant == user) // Check they're still here.
open_machine()
escape_in_progress = FALSE
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 glass of [src]!</span>", \
"<span class='notice'>You struggle inside [src], kicking the release with your foot... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='italics'>You hear a thump from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
"<span class='notice'>You successfully break out of [src]!</span>")
open_machine()
/obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user)
..()
@@ -120,6 +120,7 @@
return 1
/obj/machinery/meter/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
new /obj/item/pipe_meter(loc)
qdel(src)
@@ -233,6 +233,9 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
set category = "Preferences"
set desc = "Stop Current Sounds"
SEND_SOUND(usr, sound(null))
var/client/C = usr.client
if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
C.chatOutput.sendMusic(" ")
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+2 -2
View File
@@ -308,8 +308,8 @@
name = "Chainsaw"
result = /obj/item/twohanded/required/chainsaw
reqs = list(/obj/item/circular_saw = 1,
/obj/item/stack/cable_coil = 1,
/obj/item/stack/sheet/plasteel = 1)
/obj/item/stack/cable_coil = 3,
/obj/item/stack/sheet/plasteel = 5)
tools = list(/obj/item/weldingtool)
time = 50
category = CAT_WEAPONRY
@@ -51,6 +51,9 @@
/obj/machinery/gibber/container_resist(mob/living/user)
go_out()
/obj/machinery/gibber/relaymove(mob/living/user)
go_out()
/obj/machinery/gibber/attack_hand(mob/user)
if(stat & (NOPOWER|BROKEN))
return
@@ -225,4 +228,4 @@
if(M.loc == input_plate)
M.forceMove(src)
M.gib()
M.gib()
@@ -142,69 +142,60 @@
user.set_machine(src)
interact(user)
/*******************
* SmartFridge Menu
********************/
/obj/machinery/smartfridge/interact(mob/user)
if(stat)
return FALSE
var/dat = "<TT><b>Select an item:</b><br>"
/obj/machinery/smartfridge/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, "smartvend", name, 440, 550, master_ui, state)
ui.set_autoupdate(FALSE)
ui.open()
if (contents.len == 0)
dat += "<font color = 'red'>No product loaded!</font>"
else
var/listofitems = list()
for (var/atom/movable/O in contents)
/obj/machinery/smartfridge/ui_data(mob/user)
. = list()
var/listofitems = list()
for (var/I in src)
var/atom/movable/O = I
if (!QDELETED(O))
if (listofitems[O.name])
listofitems[O.name]++
listofitems[O.name]["amount"]++
else
listofitems[O.name] = 1
sortList(listofitems)
listofitems[O.name] = list("name" = O.name, "type" = O.type, "amount" = 1)
sortList(listofitems)
for (var/O in listofitems)
if(listofitems[O] <= 0)
continue
var/N = listofitems[O]
var/itemName = url_encode(O)
dat += "<FONT color = 'blue'><B>[capitalize(O)]</B>:"
dat += " [N] </font>"
dat += "<a href='byond://?src=\ref[src];vend=[itemName];amount=1'>Vend</A> "
if(N > 5)
dat += "(<a href='byond://?src=\ref[src];vend=[itemName];amount=5'>x5</A>)"
if(N > 10)
dat += "(<a href='byond://?src=\ref[src];vend=[itemName];amount=10'>x10</A>)"
if(N > 25)
dat += "(<a href='byond://?src=\ref[src];vend=[itemName];amount=25'>x25</A>)"
if(N > 1)
dat += "(<a href='?src=\ref[src];vend=[itemName];amount=[N]'>All</A>)"
.["contents"] = listofitems
.["name"] = name
.["isdryer"] = FALSE
dat += "<br>"
dat += "</TT>"
user << browse("<HEAD><TITLE>[src] supplies</TITLE></HEAD><TT>[dat]</TT>", "window=smartfridge")
onclose(user, "smartfridge")
return dat
/obj/machinery/smartfridge/handle_atom_del(atom/A) // Update the UIs in case something inside gets deleted
SStgui.update_uis(src)
/obj/machinery/smartfridge/Topic(var/href, var/list/href_list)
if(..())
/obj/machinery/smartfridge/ui_act(action, params)
. = ..()
if(.)
return
usr.set_machine(src)
switch(action)
if("Release")
var/desired = 0
var/N = href_list["vend"]
var/amount = text2num(href_list["amount"])
if (params["amount"])
desired = text2num(params["amount"])
else
desired = input("How many items?", "How many items would you like to take out?", 1) as null|num
var/i = amount
for(var/obj/O in contents)
if(i <= 0)
break
if(O.name == N)
O.loc = src.loc
i--
if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src)) // Sanity checkin' in case stupid stuff happens while we wait for input()
return FALSE
updateUsrDialog()
for(var/obj/item/O in src)
if(desired <= 0)
break
if(O.name == params["name"])
O.forceMove(drop_location())
desired--
return TRUE
return FALSE
// ----------------------------
@@ -240,20 +231,23 @@
/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1)
..()
/obj/machinery/smartfridge/drying_rack/interact(mob/user)
var/dat = ..()
if(dat)
dat += "<br>"
dat += "<a href='byond://?src=\ref[src];dry=1'>Toggle Drying</A> "
user << browse("<HEAD><TITLE>[src] supplies</TITLE></HEAD><TT>[dat]</TT>", "window=smartfridge")
onclose(user, "smartfridge")
/obj/machinery/smartfridge/drying_rack/ui_data(mob/user)
. = ..()
.["isdryer"] = TRUE
.["verb"] = "Take"
.["drying"] = drying
/obj/machinery/smartfridge/drying_rack/Topic(href, list/href_list)
..()
if(href_list["dry"])
toggle_drying(FALSE)
updateUsrDialog()
update_icon()
/obj/machinery/smartfridge/drying_rack/ui_act(action, params)
. = ..()
if(.)
update_icon() // This is to handle a case where the last item is taken out manually instead of through drying pop-out
return
switch(action)
if("Dry")
toggle_drying(FALSE)
return TRUE
return FALSE
/obj/machinery/smartfridge/drying_rack/power_change()
if(powered() && anchored)
@@ -279,6 +273,7 @@
..()
if(drying)
if(rack_dry())//no need to update unless something got dried
SStgui.update_uis(src)
update_icon()
/obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O)
+1 -1
View File
@@ -248,7 +248,7 @@
if(istype(src, /obj/machinery/hydroponics/soil))
add_atom_colour(rgb(255, 175, 0), FIXED_COLOUR_PRIORITY)
else
overlays += mutable_appearance('icons/obj/hydroponics/equipment.dmi', "gaia_blessing")
add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "gaia_blessing"))
set_light(3)
update_icon_hoses()
+1
View File
@@ -33,6 +33,7 @@ Chief Medical Officer
id = /obj/item/card/id/silver
belt = /obj/item/device/pda/heads/cmo
l_pocket = /obj/item/pinpointer/crew
ears = /obj/item/device/radio/headset/heads/cmo
uniform = /obj/item/clothing/under/rank/chief_medical_officer
shoes = /obj/item/clothing/shoes/sneakers/brown
@@ -1,8 +1,8 @@
/datum/sprite_accessory
var/extra = 0
var/extra = FALSE
var/extra_icon = 'icons/mob/mam_bodyparts.dmi'
var/extra_color_src = MUTCOLORS2 //The color source for the extra overlay.
var/extra2 = 0
var/extra2 = FALSE
var/extra2_icon = 'icons/mob/mam_bodyparts.dmi'
var/extra2_color_src = MUTCOLORS3
// var/list/ckeys_allowed = null
@@ -13,6 +13,10 @@
icon = 'icons/mob/mam_bodyparts.dmi'
*/
/***************** Alphabetical Order please ***************
************* Keep it to Ears, Tails, Tails Animated *********/
/datum/sprite_accessory/tails/lizard/none
name = "None"
icon_state = "None"
@@ -31,12 +35,17 @@
color_src = 0
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/human/bear
name = "Bear"
icon_state = "bear"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails/human/bear
name = "Bear"
icon_state = "bear"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/human/bear
/datum/sprite_accessory/tails_animated/human/bear
name = "Bear"
icon_state = "bear"
icon = 'icons/mob/mam_bodyparts.dmi'
@@ -51,10 +60,27 @@
icon_state = "catbig"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/human/cow
name = "Cow"
icon_state = "cow"
icon = 'icons/mob/mam_bodyparts.dmi'
gender_specific = 1
/datum/sprite_accessory/tails/human/cow
name = "Cow"
icon_state = "cow"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails_animated/human/cow
name = "Cow"
icon_state = "cow"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/fennec
name = "Fennec"
icon_state = "fennec"
icon = 'icons/mob/mam_bodyparts.dmi'
hasinner = 1
/datum/sprite_accessory/tails/human/fennec
name = "Fennec"
@@ -76,37 +102,49 @@
name = "Fox"
icon_state = "fox"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/tails_animated/human/fox
name = "Fox"
icon_state = "fox"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/tails/human/horse
name = "Horse"
icon_state = "horse"
icon = 'icons/mob/mam_bodyparts.dmi'
color_src = HAIR
/datum/sprite_accessory/tails_animated/human/horse
name = "Horse"
icon_state = "horse"
icon = 'icons/mob/mam_bodyparts.dmi'
color_src = HAIR
/datum/sprite_accessory/tails/human/husky
name = "Husky"
icon_state = "husky"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/tails_animated/human/husky
name = "Husky"
icon_state = "husky"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/tails/human/kitsune
name = "Kitsune"
icon_state = "kitsune"
extra = 1
extra = TRUE
extra_color_src = MUTCOLORS2
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails_animated/human/kitsune
name = "Kitsune"
icon_state = "kitsune"
extra = 1
extra = TRUE
extra_color_src = MUTCOLORS2
icon = 'icons/mob/mam_bodyparts.dmi'
@@ -146,6 +184,24 @@
name = "Otusian"
icon_state = "otie"
/datum/sprite_accessory/ears/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
hasinner= 1
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = 0
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails_animated/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = 0
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/human/skunk
name = "skunk"
icon_state = "skunk"
@@ -191,7 +247,7 @@
/datum/sprite_accessory/ears/wolf
name = "Wolf"
icon_state = "wolf"
extra = 1
hasinner = 1
/datum/sprite_accessory/tails/human/wolf
name = "Wolf"
@@ -203,18 +259,6 @@
icon_state = "wolf"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/tails/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = 0
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/ears/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
hasinner= 1
icon = 'icons/mob/mam_bodyparts.dmi'
/******************************************
*************** Body Parts ****************
*******************************************/
@@ -248,36 +292,37 @@
name = "Beak"
icon_state = "bird"
icon = 'icons/mob/mam_bodyparts.dmi'
color_src = MUTCOLORS3
/datum/sprite_accessory/snouts/lcanid
name = "Fox, Long"
icon_state = "lcanid"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/snouts/scanid
name = "Fox, Short"
icon_state = "scanid"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/snouts/wolf
name = "Wolf"
icon_state = "wolf"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/snouts/husky
name = "Husky"
icon_state = "husky"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/snouts/otie
name = "Otie"
icon_state = "otie"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/******************************************
************ Actual Species ***************
@@ -286,31 +331,30 @@
/datum/sprite_accessory/mam_tails/ailurus
name = "Ailurus"
icon_state = "ailurus"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/ailurus
name = "Ailurus"
icon_state = "ailurus"
extra = 1
extra_color_src = MUTCOLORS2
/datum/sprite_accessory/mam_tails/bear
name = "Bear"
icon_state = "bear"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = TRUE
/datum/sprite_accessory/mam_ears/bear
name = "Bear"
icon_state = "bear"
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/mam_tails/bear
name = "Bear"
icon_state = "bear"
/datum/sprite_accessory/mam_tails_animated/bear
name = "Bear"
icon_state = "bear"
/datum/sprite_accessory/mam_ears/catbig
name = "Cat, Big"
icon_state = "cat"
hasinner = 1
icon = 'icons/mob/mutant_bodyparts.dmi'
/datum/sprite_accessory/mam_tails/catbig
name = "Cat, Big"
icon_state = "catbig"
@@ -323,6 +367,14 @@
name = "Cow"
icon_state = "cow"
gender_specific = 1
/datum/sprite_accessory/mam_tail/cow
name = "Cow"
icon_state = "cow"
/datum/sprite_accessory/mam_tails_animated/cow
name = "Cow"
icon_state = "cow"
/datum/sprite_accessory/mam_ears/deer
name = "Deer"
@@ -331,8 +383,7 @@
/datum/sprite_accessory/mam_tails/eevee
name = "Eevee"
icon_state = "eevee"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_ears/eevee
name = "Eevee"
@@ -341,8 +392,7 @@
/datum/sprite_accessory/mam_tails_animated/eevee
name = "Eevee"
icon_state = "eevee"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_ears/fennec
name = "Fennec"
@@ -360,25 +410,17 @@
/datum/sprite_accessory/mam_ears/fox
name = "Fox"
icon_state = "fox"
hasinner = 0
hasinner = 1
/datum/sprite_accessory/mam_tails/fox
name = "Fox"
icon_state = "fox"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/fox
name = "Fox"
icon_state = "fox"
extra = 1
extra_color_src = MUTCOLORS2
/datum/sprite_accessory/mam_ears/husky
name = "Husky"
icon_state = "wolf"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails/hawk
name = "Hawk"
@@ -388,20 +430,36 @@
name = "Hawk"
icon_state = "hawk"
/datum/sprite_accessory/mam_tails/horse
name = "Horse"
icon_state = "horse"
color_src = HAIR
/datum/sprite_accessory/mam_tails_animated/horse
name = "Horse"
icon_state = "Horse"
color_src = HAIR
/datum/sprite_accessory/mam_ears/husky
name = "Husky"
icon_state = "wolf"
icon = 'icons/mob/mam_bodyparts.dmi'
extra = TRUE
/datum/sprite_accessory/mam_tails/husky
name = "Husky"
icon_state = "husky"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/husky
name = "Husky"
icon_state = "husky"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_ears/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails/kangaroo
name = "kangaroo"
@@ -414,14 +472,12 @@
/datum/sprite_accessory/mam_tails/kitsune
name = "Kitsune"
icon_state = "kitsune"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/kitsune
name = "Kitsune"
icon_state = "kitsune"
extra = 1
extra_color_src = MUTCOLORS2
extra = TRUE
/datum/sprite_accessory/mam_ears/lab
name = "Dog, Long"
@@ -462,6 +518,32 @@
name = "Otusian"
icon_state = "otie"
/datum/sprite_accessory/mam_ears/rabbit
name = "Rabbit"
icon_state = "rabbit"
hasinner= 1
/datum/sprite_accessory/mam_tails/rabbit
name = "Rabbit"
icon_state = "rabbit"
/datum/sprite_accessory/mam_tails_animated/rabbit
name = "Rabbit"
icon_state = "rabbit"
/datum/sprite_accessory/mam_ears/sergal
name = "Sergal"
icon_state = "sergal"
hasinner= 1
/datum/sprite_accessory/mam_tails/sergal
name = "Sergal"
icon_state = "sergal"
/datum/sprite_accessory/mam_tails_animated/sergal
name = "Sergal"
icon_state = "sergal"
/datum/sprite_accessory/mam_ears/skunk
name = "skunk"
icon_state = "skunk"
@@ -470,13 +552,13 @@
name = "skunk"
icon_state = "skunk"
color_src = 0
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/skunk
name = "skunk"
icon_state = "skunk"
color_src = 0
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails/shark
name = "Shark"
@@ -486,19 +568,19 @@
/datum/sprite_accessory/mam_tails_animated/shark
name = "Shark"
icon_state = "shark"
color_src = 0
color_src = MUTCOLORS
/datum/sprite_accessory/mam_tails/shepherd
name = "Shepherd"
icon_state = "shepherd"
extra = 1
extra2 = 1
extra = TRUE
extra2 = TRUE
/datum/sprite_accessory/mam_tails_animated/shepherd
name = "Shepherd"
icon_state = "shepherd"
extra = 1
extra2 = 1
extra = TRUE
extra2 = TRUE
/datum/sprite_accessory/mam_ears/squirrel
name = "Squirrel"
@@ -516,7 +598,7 @@
/datum/sprite_accessory/mam_ears/wolf
name = "Wolf"
icon_state = "wolf"
extra = 1
hasinner = 1
/datum/sprite_accessory/mam_tails/wolf
name = "Wolf"
@@ -526,26 +608,13 @@
name = "Wolf"
icon_state = "wolf"
/datum/sprite_accessory/mam_tails/rabbit
name = "Rabbit"
icon_state = "rabbit"
/datum/sprite_accessory/mam_tails_animated/rabbit
name = "Rabbit"
icon_state = "rabbit"
/datum/sprite_accessory/mam_ears/rabbit
name = "Rabbit"
icon_state = "rabbit"
hasinner= 1
/******************************************
************ Body Markings ****************
*******************************************/
/datum/sprite_accessory/mam_body_markings
extra = 1
extra2 = 1
extra = TRUE
extra2 = TRUE
icon = 'icons/mob/mam_body_markings.dmi'
/datum/sprite_accessory/mam_body_markings/none
@@ -555,8 +624,6 @@
/datum/sprite_accessory/mam_body_markings/ailurus
name = "Red Panda"
icon_state = "ailurus"
extra_color_src = MUTCOLORS2
extra2_color_src = MUTCOLORS3
gender_specific = 1
/datum/sprite_accessory/mam_body_markings/belly
@@ -598,13 +665,11 @@
/datum/sprite_accessory/mam_body_markings/fennec
name = "Fennec"
icon_state = "Fennec"
extra_color_src = MUTCOLORS3
gender_specific = 1
/datum/sprite_accessory/mam_body_markings/fox
name = "Fox"
icon_state = "fox"
extra_color_src = MUTCOLORS3
gender_specific = 1
/datum/sprite_accessory/mam_body_markings/hawk
@@ -668,9 +733,9 @@
/datum/sprite_accessory/taur
icon = 'icons/mob/mam_taur.dmi'
extra_icon = 'icons/mob/mam_taur.dmi'
extra = 1
extra = TRUE
extra2_icon = 'icons/mob/mam_taur.dmi'
extra2 = 1
extra2 = TRUE
center = TRUE
dimension_x = 64
@@ -805,19 +870,17 @@
/datum/sprite_accessory/mam_body_markings/guilmon
name = "Guilmon"
icon_state = "guilmon"
extra_color_src = MUTCOLORS2
extra2_color_src = MUTCOLORS3
gender_specific = 1
/datum/sprite_accessory/mam_tails/guilmon
name = "Guilmon"
icon_state = "guilmon"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_tails_animated/guilmon
name = "Guilmon"
icon_state = "guilmon"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_ears/guilmon
name = "Guilmon"
@@ -834,33 +897,33 @@
name = "DataShark"
icon_state = "datashark"
color_src = 0
/*
//Till I get my snowflake only ckey lock, these are locked-locked :D
/datum/sprite_accessory/mam_ears/sabresune
name = "sabresune"
icon_state = "sabresune"
extra = 1
extra = TRUE
extra_color_src = MUTCOLORS3
locked = TRUE
/datum/sprite_accessory/mam_tails/sabresune
name = "sabresune"
icon_state = "sabresune"
extra = 1
extra = TRUE
locked = TRUE
/datum/sprite_accessory/mam_tails_animated/sabresune
name = "sabresune"
icon_state = "sabresune"
extra = 1
extra = TRUE
/datum/sprite_accessory/mam_body_markings/sabresune
name = "Sabresune"
icon_state = "sabresune"
color_src = MUTCOLORS2
extra = 0
extra2 = 0
extra = FALSE
extra2 = FALSE
locked = TRUE
*/
@@ -643,6 +643,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
update_hair()
/mob/living/carbon/human/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_THREE)
for(var/obj/item/hand in held_items)
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand))
@@ -651,7 +652,6 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
rad_act(current_size * 3)
if(mob_negates_gravity())
return
..()
/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C)
CHECK_DNA_AND_SPECIES(C)
@@ -1,67 +1,67 @@
/mob/living/carbon/human/movement_delay()
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
/mob/living/carbon/human/movement_delay()
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(isobj(shoes) && (shoes.flags_1&NOSLIP_1) && !(lube&GALOSHES_DONT_HELP))
return 0
return ..()
/mob/living/carbon/human/experience_pressure_difference()
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
return 0
return ..()
/mob/living/carbon/human/experience_pressure_difference()
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
if(shoes && shoes.flags_1&NOSLIP_1)
return 0
return ..()
/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity(src))
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_move(src, NewLoc)
if(shoes)
if(!lying && !buckled)
if(loc == NewLoc)
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
if(oldFP && oldFP.blood_state == S.blood_state)
return
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
FP.blood_state = S.blood_state
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
if(S.blood_DNA && S.blood_DNA.len)
FP.transfer_blood_dna(S.blood_DNA)
FP.update_icon()
update_inv_shoes()
//End bloody footprints
S.step_action()
/mob/living/carbon/human/Moved()
. = ..()
if(buckled_mobs && buckled_mobs.len && riding_datum)
riding_datum.on_vehicle_move()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(..())
return 1
return dna.species.space_move(src)
return 0
return ..()
/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity(src))
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_move(src, NewLoc)
if(shoes)
if(!lying && !buckled)
if(loc == NewLoc)
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
if(oldFP && oldFP.blood_state == S.blood_state)
return
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
FP.blood_state = S.blood_state
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
if(S.blood_DNA && S.blood_DNA.len)
FP.transfer_blood_dna(S.blood_DNA)
FP.update_icon()
update_inv_shoes()
//End bloody footprints
S.step_action()
/mob/living/carbon/human/Moved()
. = ..()
if(buckled_mobs && buckled_mobs.len && riding_datum)
riding_datum.on_vehicle_move()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(..())
return 1
return dna.species.space_move(src)
+4 -2
View File
@@ -72,7 +72,7 @@
emote("gasp")
if(istype(loc, /obj/))
var/obj/loc_as_obj = loc
loc_as_obj.handle_internal_lifeform(src,0)
loc_as_obj.handle_internal_lifeform(src,0)
else
//Breathe from internal
breath = get_breath_from_internal(BREATH_VOLUME)
@@ -117,7 +117,9 @@
if(!breath || (breath.total_moles() == 0) || !lungs)
if(reagents.has_reagent("epinephrine") && lungs)
return
adjustOxyLoss(1)
var/oxy_loss = min(losebreath, 1)
adjustOxyLoss(oxy_loss)
losebreath -= oxy_loss
failed_last_breath = 1
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
return 0
@@ -68,6 +68,6 @@
if(!ancestor_name)
file_data["ancestor_name"] = name
fdel(json_file)
WRITE_FILE(json_file, json_encode(json_file))
WRITE_FILE(json_file, json_encode(file_data))
if(!dead)
memory_saved = 1
+16 -13
View File
@@ -429,6 +429,7 @@
else
return 0
var/old_direction = dir
var/atom/movable/pullee = pulling
if(pullee && get_dist(src, pullee) > 1)
stop_pulling()
@@ -444,10 +445,6 @@
var/pull_dir = get_dir(src, pulling)
if(get_dist(src, pulling) > 1 || ((pull_dir - 1) & pull_dir)) //puller and pullee more than one tile away or in diagonal position
if(isliving(pulling))
var/mob/living/M = pulling
if(M.lying && !M.buckled && (prob(M.getBruteLoss()*200/M.maxHealth)))
M.makeTrail(T)
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
stop_pulling()
@@ -458,6 +455,10 @@
if (s_active && !(CanReach(s_active,view_only = TRUE)))
s_active.close(src)
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
/mob/living/movement_delay(ignorewalk = 0)
. = ..()
if(isopenturf(loc) && !is_flying())
@@ -474,31 +475,32 @@
if(MOVE_INTENT_WALK)
. += config.walk_speed
/mob/living/proc/makeTrail(turf/target_turf)
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
if(!has_gravity())
return
var/blood_exists = FALSE
for(var/obj/effect/decal/cleanable/trail_holder/C in loc) //checks for blood splatter already on the floor
for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor
blood_exists = TRUE
if(isturf(loc))
if(isturf(start))
var/trail_type = getTrail()
if(trail_type)
var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage.
var/newdir = get_dir(target_turf, loc)
if(newdir != dir)
newdir = newdir | dir
var/newdir = get_dir(target_turf, start)
if(newdir != direction)
newdir = newdir | direction
if(newdir == 3) //N + S
newdir = NORTH
else if(newdir == 12) //E + W
newdir = EAST
if((newdir in GLOB.cardinals) && (prob(50)))
newdir = turn(get_dir(target_turf, loc), 180)
newdir = turn(get_dir(target_turf, start), 180)
if(!blood_exists)
new /obj/effect/decal/cleanable/trail_holder(loc)
for(var/obj/effect/decal/cleanable/trail_holder/TH in loc)
new /obj/effect/decal/cleanable/trail_holder(start)
for(var/obj/effect/decal/cleanable/trail_holder/TH in start)
if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
TH.existing_dirs += newdir
TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir))
@@ -690,6 +692,7 @@
who.equip_to_slot(what, where, TRUE)
/mob/living/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_SIX)
throw_at(S,14,3, spin=1)
else
+2 -2
View File
@@ -35,9 +35,9 @@
if(nuking)
set_security_level("red")
nuking = FALSE
for(var/obj/item/pinpointer/P in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
P.nuke_warning = FALSE
P.alert = FALSE
if(doomsday_device)
doomsday_device.timing = FALSE
@@ -0,0 +1,13 @@
diff a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm (rejected hunks)
@@ -35,9 +35,9 @@
if(nuking)
set_security_level("red")
nuking = FALSE
- for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
- P.nuke_warning = FALSE
+ P.alert = FALSE
if(doomsday_device)
doomsday_device.timing = FALSE
@@ -599,7 +599,7 @@
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/card/emag,
/obj/item/crowbar/cyborg,
/obj/item/pinpointer/syndicate/cyborg)
/obj/item/pinpointer/syndicate_cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/security,
@@ -625,7 +625,7 @@
/obj/item/roller/robo,
/obj/item/card/emag,
/obj/item/crowbar/cyborg,
/obj/item/pinpointer/syndicate/cyborg,
/obj/item/pinpointer/syndicate_cyborg,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/gun/medbeam)
ratvar_modules = list(
@@ -0,0 +1,19 @@
diff a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm (rejected hunks)
@@ -519,7 +519,7 @@
/obj/item/weapon/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
- /obj/item/weapon/pinpointer/syndicate/cyborg)
+ /obj/item/weapon/pinpointer/syndicate_cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/security,
@@ -545,7 +545,7 @@
/obj/item/roller/robo,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
- /obj/item/weapon/pinpointer/syndicate/cyborg,
+ /obj/item/weapon/pinpointer/syndicate_cyborg,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/weapon/gun/medbeam)
ratvar_modules = list(
@@ -15,6 +15,10 @@
/mob/living/simple_animal/drone/verb/toggle_light()
set category = "Drone"
set name = "Toggle drone light"
if(stat == DEAD)
to_chat(src, "<span class='warning'>There's no light in your life... by that I mean you're dead.</span>")
return
if(light_on)
set_light(0)
else
+1 -1
View File
@@ -587,7 +587,7 @@
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
stat("CPU:", "[world.cpu]")
stat("Instances:", "[world.contents.len]")
stat("Instances:", "[num2text(world.contents.len, 10)]")
GLOB.stat_entry()
config.stat_entry()
stat(null)
+2 -2
View File
@@ -874,9 +874,9 @@
occupier.loc = src.loc
occupier.death()
occupier.gib()
for(var/obj/item/pinpointer/P in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Pinpointers go back to tracking the nuke disk
P.nuke_warning = FALSE
P.alert = FALSE
/obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
if(card.AI)
+13
View File
@@ -0,0 +1,13 @@
diff a/code/modules/power/apc.dm b/code/modules/power/apc.dm (rejected hunks)
@@ -867,9 +867,9 @@
occupier.loc = src.loc
occupier.death()
occupier.gib()
- for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
+ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Pinpointers go back to tracking the nuke disk
- P.nuke_warning = FALSE
+ P.alert = FALSE
/obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
if(card.AI)
+1
View File
@@ -170,6 +170,7 @@ By design, d1 is the smallest direction and d2 is the highest
return 0
/obj/structure/cable/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
@@ -335,6 +335,7 @@
/obj/structure/disposalpipe/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
+1
View File
@@ -58,6 +58,7 @@
return ..()
/obj/machinery/disposal/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
@@ -430,3 +430,23 @@
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
build_path = /obj/item/organ/liver/cybernetic/upgraded
category = list("Medical Designs")
/datum/design/cybernetic_lungs
name = "Cybernetic Lungs"
desc = "A pair of cybernetic lungs."
id = "cybernetic_lungs"
req_tech = list("biotech" = 4, "materials" = 4)
build_type = PROTOLATHE
materials = list(MAT_METAL = 500, MAT_GLASS = 500)
build_path = /obj/item/organ/lungs/cybernetic
category = list("Medical Designs")
/datum/design/cybernetic_lungs_u
name = "Upgraded Cybernetic Lungs"
desc = "A pair of upgraded cybernetic lungs."
id = "cybernetic_lungs_u"
req_tech = list("biotech" = 5, "materials" = 5, "engineering" = 5)
build_type = PROTOLATHE
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
build_path = /obj/item/organ/lungs/cybernetic/upgraded
category = list("Medical Designs")
+25 -61
View File
@@ -46,71 +46,35 @@
desc = "The incomplete body of a golem. Add ten sheets of any mineral to finish."
var/shell_type = /obj/effect/mob_spawn/human/golem
var/has_owner = FALSE //if the resulting golem obeys someone
w_class = WEIGHT_CLASS_BULKY
w_class = WEIGHT_CLASS_BULKY
/obj/item/golem_shell/attackby(obj/item/I, mob/user, params)
..()
var/species
if(istype(I, /obj/item/stack/))
var/static/list/golem_shell_species_types = list(
/obj/item/stack/sheet/metal = /datum/species/golem,
/obj/item/stack/sheet/glass = /datum/species/golem/glass,
/obj/item/stack/sheet/plasteel = /datum/species/golem/plasteel,
/obj/item/stack/sheet/mineral/sandstone = /datum/species/golem/sand,
/obj/item/stack/sheet/mineral/plasma = /datum/species/golem/plasma,
/obj/item/stack/sheet/mineral/diamond = /datum/species/golem/diamond,
/obj/item/stack/sheet/mineral/gold = /datum/species/golem/gold,
/obj/item/stack/sheet/mineral/silver = /datum/species/golem/silver,
/obj/item/stack/sheet/mineral/uranium = /datum/species/golem/uranium,
/obj/item/stack/sheet/mineral/bananium = /datum/species/golem/bananium,
/obj/item/stack/sheet/mineral/titanium = /datum/species/golem/titanium,
/obj/item/stack/sheet/mineral/plastitanium = /datum/species/golem/plastitanium,
/obj/item/stack/sheet/mineral/abductor = /datum/species/golem/alloy,
/obj/item/stack/sheet/mineral/wood = /datum/species/golem/wood,
/obj/item/stack/sheet/bluespace_crystal = /datum/species/golem/bluespace,
/obj/item/stack/sheet/runed_metal = /datum/species/golem/runic,
/obj/item/stack/medical/gauze = /datum/species/golem/cloth,
/obj/item/stack/sheet/cloth = /datum/species/golem/cloth,
/obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine,
/obj/item/stack/sheet/plastic = /datum/species/golem/plastic)
if(istype(I, /obj/item/stack))
var/obj/item/stack/O = I
if(istype(O, /obj/item/stack/sheet/metal))
species = /datum/species/golem
if(istype(O, /obj/item/stack/sheet/glass))
species = /datum/species/golem/glass
if(istype(O, /obj/item/stack/sheet/plasteel))
species = /datum/species/golem/plasteel
if(istype(O, /obj/item/stack/sheet/mineral/sandstone))
species = /datum/species/golem/sand
if(istype(O, /obj/item/stack/sheet/mineral/plasma))
species = /datum/species/golem/plasma
if(istype(O, /obj/item/stack/sheet/mineral/diamond))
species = /datum/species/golem/diamond
if(istype(O, /obj/item/stack/sheet/mineral/gold))
species = /datum/species/golem/gold
if(istype(O, /obj/item/stack/sheet/mineral/silver))
species = /datum/species/golem/silver
if(istype(O, /obj/item/stack/sheet/mineral/uranium))
species = /datum/species/golem/uranium
if(istype(O, /obj/item/stack/sheet/mineral/bananium))
species = /datum/species/golem/bananium
if(istype(O, /obj/item/stack/sheet/mineral/titanium))
species = /datum/species/golem/titanium
if(istype(O, /obj/item/stack/sheet/mineral/plastitanium))
species = /datum/species/golem/plastitanium
if(istype(O, /obj/item/stack/sheet/mineral/abductor))
species = /datum/species/golem/alloy
if(istype(O, /obj/item/stack/sheet/mineral/wood))
species = /datum/species/golem/wood
if(istype(O, /obj/item/stack/sheet/bluespace_crystal))
species = /datum/species/golem/bluespace
if(istype(O, /obj/item/stack/sheet/runed_metal))
species = /datum/species/golem/runic
if(istype(O, /obj/item/stack/medical/gauze) || istype(O, /obj/item/stack/sheet/cloth))
species = /datum/species/golem/cloth
if(istype(O, /obj/item/stack/sheet/mineral/adamantine))
species = /datum/species/golem/adamantine
if(istype(O, /obj/item/stack/sheet/plastic))
species = /datum/species/golem/plastic
var/species = golem_shell_species_types[O.merge_type]
if(species)
if(O.use(10))
to_chat(user, "You finish up the golem shell with ten sheets of [O].")
@@ -4,6 +4,10 @@ GLOBAL_PROTECT(reboot_mode)
/world/proc/RunningService()
return params[SERVICE_WORLD_PARAM]
/proc/ServiceVersion()
if(world.RunningService())
return world.params[SERVICE_VERSION_PARAM]
/world/proc/ExportService(command)
return RunningService() && shell("python code/modules/server_tools/nudge.py \"[command]\"") == 0
+3 -2
View File
@@ -14,7 +14,8 @@ All ShuttleMove procs go here
// Called from the new turf before anything has been moved
// Only gets called if fromShuttleMove returns true first
// returns the new move_mode (based on the old)
/turf/proc/toShuttleMove(turf/oldT, shuttle_dir, move_mode)
/turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle)
var/shuttle_dir = shuttle.dir
for(var/i in contents)
var/atom/movable/thing = i
if(ismob(thing))
@@ -383,4 +384,4 @@ All ShuttleMove procs go here
/obj/effect/abstract/proximity_checker/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock)
//timer so it only happens once
addtimer(CALLBACK(monitor, /datum/proximity_monitor/proc/SetRange, monitor.current_range, TRUE), 0, TIMER_UNIQUE)
addtimer(CALLBACK(monitor, /datum/proximity_monitor/proc/SetRange, monitor.current_range, TRUE), 0, TIMER_UNIQUE)
+1 -1
View File
@@ -570,7 +570,7 @@
move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode) //atoms
move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs
move_mode = newT.toShuttleMove(oldT, dir, move_mode) //turfs
move_mode = newT.toShuttleMove(oldT, move_mode , src) //turfs
if(move_mode & MOVE_AREA)
areas_to_move[old_area] = TRUE
+23
View File
@@ -320,6 +320,29 @@
safe_toxins_min = 16 //We breath THIS!
safe_toxins_max = 0
/obj/item/organ/lungs/cybernetic
name = "cybernetic lungs"
desc = "A cybernetic version of the lungs found in traditional humanoid entities. It functions the same as an organic lung and is merely meant as a replacement."
icon_state = "lungs-c"
origin_tech = "biotech=4"
/obj/item/organ/lungs/cybernetic/emp_act()
owner.losebreath = 20
/obj/item/organ/lungs/cybernetic/upgraded
name = "upgraded cybernetic lungs"
desc = "A more advanced version of the stock cybernetic lungs. They are capable of filtering out lower levels of toxins and carbon-dioxide."
icon_state = "lungs-c-u"
origin_tech = "biotech=5"
safe_toxins_max = 20
safe_co2_max = 20
cold_level_1_threshold = 200
cold_level_2_threshold = 140
cold_level_3_threshold = 100
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
#undef HEAT_GAS_DAMAGE_LEVEL_1
+2
View File
@@ -47,6 +47,7 @@
say_mod = "hisses"
taste_sensitivity = 10 // combined nose + tongue, extra sensitive
/*
/obj/item/organ/tongue/lizard/TongueSpeech(var/message)
var/regex/lizard_hiss = new("s+", "g")
var/regex/lizard_hiSS = new("S+", "g")
@@ -54,6 +55,7 @@
message = lizard_hiss.Replace(message, "sss")
message = lizard_hiSS.Replace(message, "SSS")
return message
*/
/obj/item/organ/tongue/fly
name = "proboscis"