Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n"
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
dat += "Gender identity: [active2.fields["id_gender"]] "
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 8db5ebd1b8..7b34c026d4 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -53,7 +53,7 @@
/*
/obj/machinery/computer/pod/attackby(I as obj, user as mob)
if(istype(I, /obj/item/weapon/screwdriver))
- playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, W.usesound, 50, 1)
if(do_after(user, 20))
if(stat & BROKEN)
user << "The broken glass falls out."
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 389828843f..1179d3a2b2 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -56,7 +56,7 @@
/obj/machinery/computer/secure_data/attack_hand(mob/user as mob)
if(..())
return
- if (src.z > 6)
+ if (using_map && !(src.z in using_map.contact_levels))
user << "Unable to establish a connection: You're too far away from the station!"
return
var/dat
@@ -127,6 +127,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 1a67778fdf..fb92e700ff 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -39,7 +39,7 @@
/obj/machinery/computer/skills/attack_hand(mob/user as mob)
if(..())
return
- if (src.z > 6)
+ if (using_map && !(src.z in using_map.contact_levels))
user << "Unable to establish a connection: You're too far away from the station!"
return
var/dat
@@ -93,6 +93,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
diff --git a/code/game/machinery/computer3/buildandrepair.dm b/code/game/machinery/computer3/buildandrepair.dm
index a064d8ce1c..f780e42b27 100644
--- a/code/game/machinery/computer3/buildandrepair.dm
+++ b/code/game/machinery/computer3/buildandrepair.dm
@@ -79,8 +79,8 @@
switch(state)
if(0)
if(istype(P, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(user, 20 * P.toolspeed))
user << "You wrench the frame into place."
src.anchored = 1
src.state = 1
@@ -89,16 +89,16 @@
if(!WT.remove_fuel(0, user))
user << "The welding tool must be on to complete this task."
return
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src.loc, WT.usesound, 50, 1)
+ if(do_after(user, 20 * WT.toolspeed))
if(!src || !WT.isOn()) return
user << "You deconstruct the frame."
new /obj/item/stack/material/steel( src.loc, 5 )
qdel(src)
if(1)
if(istype(P, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(user, 20 * P.toolspeed))
user << "You unfasten the frame."
src.anchored = 0
src.state = 0
@@ -114,12 +114,12 @@
else
user << "This frame does not accept circuit boards of this type!"
if(istype(P, /obj/item/weapon/screwdriver) && circuit)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You screw the circuit board into place."
src.state = 2
src.icon_state = "2"
if(istype(P, /obj/item/weapon/crowbar) && circuit)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You remove the circuit board."
src.state = 1
src.icon_state = "0"
@@ -127,15 +127,15 @@
src.circuit = null
if(2)
if(istype(P, /obj/item/weapon/screwdriver) && circuit)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You unfasten the circuit board."
src.state = 1
src.icon_state = "1"
if(istype(P, /obj/item/weapon/crowbar))
if(battery)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- if(do_after(10))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(10 * P.toolspeed))
battery.loc = loc
user << "You remove [battery]."
battery = null
@@ -168,7 +168,7 @@
if(components.len)
user << "There are parts in the way!"
return
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You remove the cables."
src.state = 2
src.icon_state = "2"
@@ -190,13 +190,13 @@
src.icon_state = "4"
if(4)
if(istype(P, /obj/item/weapon/crowbar))
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You remove the glass panel."
src.state = 3
src.icon_state = "3"
new /obj/item/stack/material/glass( src.loc, 2 )
if(istype(P, /obj/item/weapon/screwdriver))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You connect the monitor."
var/obj/machinery/computer3/B = new src.circuit.build_path ( src.loc, built=1 )
/*if(circuit.powernet) B:powernet = circuit.powernet
diff --git a/code/game/machinery/computer3/component.dm b/code/game/machinery/computer3/component.dm
index 47d5e29853..44540a9299 100644
--- a/code/game/machinery/computer3/component.dm
+++ b/code/game/machinery/computer3/component.dm
@@ -41,7 +41,7 @@
*/
/obj/item/part/computer/ai_holder
- name = "intelliCard computer module"
+ name = "intelliCore computer module"
desc = "Contains a specialized nacelle for dealing with highly sensitive equipment without interference."
attackby_types = list(/obj/item/device/aicard)
@@ -81,8 +81,8 @@
return
// Transfer over the AI.
- transfer << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
- user << "Transfer successful: [transfer.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed."
+ transfer << "You have been transferred into a mobile terminal. Sadly, there is no remote access from here."
+ user << "Transfer successful: [transfer.name] placed within mobile terminal."
transfer.loc = src
transfer.cancel_camera()
diff --git a/code/game/machinery/computer3/computers/communications.dm b/code/game/machinery/computer3/computers/communications.dm
index c4ec88f8e0..6f802c54bd 100644
--- a/code/game/machinery/computer3/computers/communications.dm
+++ b/code/game/machinery/computer3/computers/communications.dm
@@ -184,7 +184,7 @@
stat_msg2 = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40), 40)
computer.updateDialog()
- // OMG CENTCOMM LETTERHEAD
+ // OMG CENTCOM LETTERHEAD
if("MessageCentCom" in href_list)
if(!computer.radio.subspace)
return
diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm
index 57a662db46..bb4228397d 100644
--- a/code/game/machinery/computer3/computers/medical.dm
+++ b/code/game/machinery/computer3/computers/medical.dm
@@ -95,6 +95,7 @@
dat += "Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Fingerprint: [active1.fields["fingerprint"]] \n \
diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm
index a314bed273..6b77a274bf 100644
--- a/code/game/machinery/computer3/computers/security.dm
+++ b/code/game/machinery/computer3/computers/security.dm
@@ -134,6 +134,7 @@
dat += text(" \
Name: [active1.fields["name"]] \
ID: [active1.fields["id"]] \n \
+ Entity Classification: [active1.fields["brain_type"]] \n \
Sex: [active1.fields["sex"]] \n \
Age: [active1.fields["age"]] \n \
Rank: [active1.fields["rank"]] \n \
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 1236ae0e5b..c3b6e010d6 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -42,7 +42,7 @@
icon_state = "box_1"
else
if(istype(P, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src, W.usesound, 75, 1)
user << "You dismantle the frame"
new /obj/item/stack/material/steel(src.loc, 5)
qdel(src)
@@ -72,7 +72,7 @@
user << "This frame does not accept circuit boards of this type!"
else
if(istype(P, /obj/item/weapon/wirecutters))
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You remove the cables."
state = 1
icon_state = "box_0"
@@ -81,7 +81,7 @@
if(3)
if(istype(P, /obj/item/weapon/crowbar))
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
state = 2
circuit.loc = src.loc
circuit = null
@@ -103,28 +103,28 @@
component_check = 0
break
if(component_check)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
var/obj/machinery/new_machine = new src.circuit.build_path(src.loc, src.dir)
-
+
if(new_machine.component_parts)
new_machine.component_parts.Cut()
else
new_machine.component_parts = list()
-
+
src.circuit.construct(new_machine)
-
+
for(var/obj/O in src)
if(circuit.contain_parts) // things like disposal don't want their parts in them
O.loc = new_machine
else
O.loc = null
new_machine.component_parts += O
-
+
if(circuit.contain_parts)
circuit.loc = new_machine
else
circuit.loc = null
-
+
new_machine.RefreshParts()
qdel(src)
else
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 5d0f707ae8..33529f4447 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -180,17 +180,23 @@
G.loc = src
user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!")
else if(istype(G, /obj/item/weapon/grab))
- if(!ismob(G:affecting))
+ var/obj/item/weapon/grab/grab = G
+ if(!ismob(grab.affecting))
return
- for(var/mob/living/carbon/slime/M in range(1,G:affecting))
- if(M.Victim == G:affecting)
- usr << "[G:affecting:name] will not fit into the cryo because they have a slime latched onto their head."
+ for(var/mob/living/simple_animal/slime/M in range(1,grab.affecting))
+ if(M.victim == grab.affecting)
+ usr << "[grab.affecting.name] will not fit into the cryo because they have a slime latched onto their head."
return
- var/mob/M = G:affecting
+ var/mob/M = grab.affecting
if(put_mob(M))
- qdel(G)
+ qdel(grab)
return
+/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(var/mob/target, var/mob/user) //Allows borgs to put people into cryo without external assistance
+ if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target))
+ return
+ put_mob(target)
+
/obj/machinery/atmospherics/unary/cryo_cell/update_icon()
overlays.Cut()
icon_state = "pod[on]"
@@ -338,8 +344,8 @@
set name = "Move Inside"
set category = "Object"
set src in oview(1)
- for(var/mob/living/carbon/slime/M in range(1,usr))
- if(M.Victim == usr)
+ for(var/mob/living/simple_animal/slime/M in range(1,usr))
+ if(M.victim == usr)
usr << "You're too busy getting your life sucked out of you."
return
if(usr.stat != 0)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 6441a5e72a..e02309abd4 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -314,7 +314,7 @@
if(occupant)
occupant.forceMove(loc)
occupant.resting = 1
- ..()
+ return ..()
/obj/machinery/cryopod/initialize()
..()
@@ -430,6 +430,10 @@
else
W.forceMove(src.loc)
+ for(var/obj/structure/B in items)
+ if(istype(B,/obj/structure/bed))
+ qdel(B)
+
//Update any existing objectives involving this mob.
for(var/datum/objective/O in all_objectives)
// We don't want revs to get objectives that aren't for heads of staff. Letting
@@ -499,50 +503,10 @@
if(!ismob(grab.affecting))
return
-
- if(!check_occupant_allowed(grab.affecting))
- return
-
- var/willing = null //We don't want to allow people to be forced into despawning.
- var/mob/M = grab.affecting
-
- if(M.client)
- if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes")
- if(!M || !grab || !grab.affecting) return
- willing = 1
else
- willing = 1
+ go_in(grab.affecting,user)
- if(willing)
- visible_message("\The [user] starts putting [grab:affecting:name] into \the [src].", 3)
-
- if(do_after(user, 20))
- if(!M || !grab || !grab:affecting) return
-
- M.forceMove(src)
-
- if(M.client)
- M.client.perspective = EYE_PERSPECTIVE
- M.client.eye = src
-
- icon_state = occupied_icon_state
-
- M << "[on_enter_occupant_message]"
- M << "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round."
- set_occupant(M)
- time_entered = world.time
- if(ishuman(M) && applies_stasis)
- var/mob/living/carbon/human/H = M
- H.in_stasis = 1
-
- // Book keeping!
- var/turf/location = get_turf(src)
- log_admin("[key_name_admin(M)] has entered a stasis pod. (JMP)")
- message_admins("[key_name_admin(M)] has entered a stasis pod.")
-
- //Despawning occurs when process() is called with an occupant without a client.
- add_fingerprint(M)
/obj/machinery/cryopod/verb/eject()
set name = "Eject Pod"
@@ -561,6 +525,9 @@
for(var/obj/item/W in items)
W.forceMove(get_turf(src))
+ for(var/obj/structure/bed/S in src.contents)
+ S.forceMove(get_turf(src))
+
go_out()
add_fingerprint(usr)
@@ -579,8 +546,8 @@
usr << "\The [src] is in use."
return
- for(var/mob/living/carbon/slime/M in range(1,usr))
- if(M.Victim == usr)
+ for(var/mob/living/simple_animal/slime/M in range(1,usr))
+ if(M.victim == usr)
usr << "You're too busy getting your life sucked out of you."
return
@@ -602,7 +569,9 @@
set_occupant(usr)
if(ishuman(usr) && applies_stasis)
var/mob/living/carbon/human/H = occupant
- H.in_stasis = 1
+ H.Stasis(1000)
+ if(usr.buckled && istype(usr.buckled, /obj/structure/bed/chair/wheelchair))
+ usr.buckled.loc = usr.loc
icon_state = occupied_icon_state
@@ -638,7 +607,7 @@
occupant.forceMove(get_turf(src))
if(ishuman(occupant) && applies_stasis)
var/mob/living/carbon/human/H = occupant
- H.in_stasis = 0
+ H.Stasis(0)
set_occupant(null)
icon_state = base_icon_state
@@ -650,3 +619,63 @@
name = initial(name)
if(occupant)
name = "[name] ([occupant])"
+
+/obj/machinery/cryopod/MouseDrop_T(var/mob/target, var/mob/user)
+ if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user))
+ return
+ go_in(target, user)
+
+/obj/machinery/cryopod/proc/go_in(var/mob/M, var/mob/user)
+ if(!check_occupant_allowed(M))
+ return
+ if(!M)
+ return
+ if(occupant)
+ to_chat(user,"\The [src] is already occupied.")
+ return
+
+ var/willing = null //We don't want to allow people to be forced into despawning.
+
+ if(M.client)
+ if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes")
+ if(!M) return
+ willing = 1
+ else
+ willing = 1
+
+ if(willing)
+ if(M == user)
+ visible_message("[usr] [on_enter_visible_message] [src].", 3)
+ else
+ visible_message("\The [user] starts putting [M] into \the [src].", 3)
+
+ if(do_after(user, 20))
+ if(occupant)
+ to_chat(user,"\The [src] is already occupied.")
+ return
+ M.forceMove(src)
+
+ if(M.client)
+ M.client.perspective = EYE_PERSPECTIVE
+ M.client.eye = src
+ else return
+
+ icon_state = occupied_icon_state
+
+ M << "[on_enter_occupant_message]"
+ M << "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round."
+ set_occupant(M)
+ time_entered = world.time
+ if(ishuman(M) && applies_stasis)
+ var/mob/living/carbon/human/H = M
+ H.Stasis(1000)
+ if(M.buckled && istype(M.buckled, /obj/structure/bed/chair/wheelchair))
+ M.buckled.loc = M.loc
+
+ // Book keeping!
+ var/turf/location = get_turf(src)
+ log_admin("[key_name_admin(M)] has entered a stasis pod. (JMP)")
+ message_admins("[key_name_admin(M)] has entered a stasis pod.")
+
+ //Despawning occurs when process() is called with an occupant without a client.
+ add_fingerprint(M)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index fa4b601e91..76eb2da2d5 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -61,7 +61,7 @@ for reference:
var/health = 100
var/maxhealth = 100
var/material/material
-
+
/obj/structure/barricade/New(var/newloc, var/material_name)
..(newloc)
if(!material_name)
@@ -74,7 +74,7 @@ for reference:
desc = "This space is blocked off by a barricade made of [material.display_name]."
color = material.icon_colour
maxhealth = material.integrity
- health = maxhealth
+ health = maxhealth
/obj/structure/barricade/get_material()
return material
@@ -237,7 +237,7 @@ for reference:
var/turf/Tsec = get_turf(src)
/* var/obj/item/stack/rods/ =*/
- PoolOrNew(/obj/item/stack/rods, Tsec)
+ new /obj/item/stack/rods(Tsec)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 6aeecfc8e5..acd7a446c1 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -32,7 +32,11 @@
var/datum/wires/airlock/wires = null
var/open_sound_powered = 'sound/machines/airlock.ogg'
- var/open_sound_unpowered = 'sound/machines/airlock_creaking.ogg'
+ var/open_sound_unpowered = 'sound/machines/airlockforced.ogg'
+ var/close_sound_powered = 'sound/machines/airlockclose.ogg'
+ var/denied_sound = 'sound/machines/deniedbeep.ogg'
+ var/bolt_up_sound = 'sound/machines/boltsup.ogg'
+ var/bolt_down_sound = 'sound/machines/boltsdown.ogg'
/obj/machinery/door/airlock/attack_generic(var/mob/user, var/damage)
if(stat & (BROKEN|NOPOWER))
@@ -57,6 +61,37 @@
return
..()
+/obj/machinery/door/airlock/attack_alien(var/mob/user) //Familiar, right? Doors. -Mechoid
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ if(src.locked || src.welded)
+ visible_message("\The [user] begins digging into \the [src] internals!")
+ src.do_animate("deny")
+ if(do_after(user,5 SECONDS,src))
+ visible_message("\The [user] forces \the [src] open, sparks flying from its electronics!")
+ src.do_animate("spark")
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ src.locked = 0
+ src.welded = 0
+ update_icon()
+ open(1)
+ src.emag_act()
+ else if(src.density)
+ visible_message("\The [user] begins forcing \the [src] open!")
+ if(do_after(user, 5 SECONDS,src))
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ visible_message("\The [user] forces \the [src] open!")
+ open(1)
+ else
+ visible_message("\The [user] forces \the [src] closed!")
+ close(1)
+ else
+ src.do_animate("deny")
+ visible_message("\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].")
+ return
+ ..()
+
/obj/machinery/door/airlock/get_material()
if(mineral)
return get_material_by_name(mineral)
@@ -96,6 +131,11 @@
name = "External Airlock"
icon = 'icons/obj/doors/Doorext.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_ext
+
+/obj/machinery/door/airlock/glass_external
+ name = "External Airlock"
+ icon = 'icons/obj/doors/Doorextglass.dmi'
+ assembly_type = /obj/structure/door_assembly/door_assembly_ext
opacity = 0
glass = 1
@@ -263,6 +303,7 @@
icon = 'icons/obj/doors/Dooruranium.dmi'
mineral = "uranium"
var/last_event = 0
+ var/rad_power = 7.5
/obj/machinery/door/airlock/process()
// Deliberate no call to parent.
@@ -280,15 +321,10 @@
/obj/machinery/door/airlock/uranium/process()
if(world.time > last_event+20)
if(prob(50))
- radiate()
+ radiation_repository.radiate(src, rad_power)
last_event = world.time
..()
-/obj/machinery/door/airlock/uranium/proc/radiate()
- for(var/mob/living/L in range (3,src))
- L.apply_effect(15,IRRADIATE,0)
- return
-
/obj/machinery/door/airlock/phoron
name = "Phoron Airlock"
desc = "No way this can end badly."
@@ -580,8 +616,7 @@ About the new airlock wires panel:
if("deny")
if(density && src.arePowerSystemsOn())
flick("door_deny", src)
- if(secured_wires)
- playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ playsound(src, denied_sound, 50, 0, 3)
return
/obj/machinery/door/airlock/attack_ai(mob/user as mob)
@@ -676,6 +711,12 @@ About the new airlock wires panel:
if(src.shock(user, 100))
return
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ src.attack_alien(user)
+ return
+
if(src.p_open)
user.set_machine(src)
wires.Interact(user)
@@ -757,7 +798,10 @@ About the new airlock wires panel:
update_icon()
return 1
-/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob)
+/obj/machinery/door/airlock/proc/can_remove_electronics()
+ return src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN))))
+
+/obj/machinery/door/airlock/attackby(obj/item/C, mob/user as mob)
//world << text("airlock attackby src [] obj [] mob []", src, C, user)
if(!istype(usr, /mob/living/silicon))
if(src.isElectrified())
@@ -777,7 +821,7 @@ About the new airlock wires panel:
src.welded = 1
else
src.welded = null
- playsound(src, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src.loc, C.usesound, 75, 1)
src.update_icon()
return
else
@@ -788,8 +832,10 @@ About the new airlock wires panel:
to_chat(usr,"The panel is broken and cannot be closed.")
else
src.p_open = 0
+ playsound(src, C.usesound, 50, 1)
else
src.p_open = 1
+ playsound(src, C.usesound, 50, 1)
src.update_icon()
else if(istype(C, /obj/item/weapon/wirecutters))
return src.attack_hand(user)
@@ -801,10 +847,10 @@ About the new airlock wires panel:
var/obj/item/weapon/pai_cable/cable = C
cable.plugin(src, user)
else if(!repairing && istype(C, /obj/item/weapon/crowbar))
- if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) )
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ if(can_remove_electronics())
+ playsound(src, C.usesound, 75, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.")
- if(do_after(user,40))
+ if(do_after(user,40 * C.toolspeed))
to_chat(user,"You removed the airlock electronics!")
var/obj/structure/door_assembly/da = new assembly_type(src.loc)
@@ -895,9 +941,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
- playsound(src.loc, open_sound_powered, 100, 1)
+ playsound(src.loc, open_sound_powered, 50, 1)
else
- playsound(src.loc, open_sound_unpowered, 100, 1)
+ playsound(src.loc, open_sound_unpowered, 75, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -992,9 +1038,9 @@ About the new airlock wires panel:
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0
if(arePowerSystemsOn())
- playsound(src.loc, open_sound_powered, 100, 1)
+ playsound(src.loc, close_sound_powered, 50, 1)
else
- playsound(src.loc, open_sound_unpowered, 100, 1)
+ playsound(src.loc, open_sound_unpowered, 75, 1)
for(var/turf/turf in locs)
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis)
@@ -1009,6 +1055,7 @@ About the new airlock wires panel:
if (operating && !forced) return 0
src.locked = 1
+ playsound(src, bolt_down_sound, 30, 0, 3)
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
update_icon()
@@ -1022,6 +1069,7 @@ About the new airlock wires panel:
if(operating || !src.arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) return
src.locked = 0
+ playsound(src, bolt_up_sound, 30, 0, 3)
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
update_icon()
diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm
index 805bb7dba9..ba8aa85b2c 100644
--- a/code/game/machinery/doors/airlock_control.dm
+++ b/code/game/machinery/doors/airlock_control.dm
@@ -145,7 +145,7 @@ obj/machinery/door/airlock/New()
obj/machinery/door/airlock/Destroy()
if(frequency && radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
obj/machinery/airlock_sensor
icon = 'icons/obj/airlock_machines.dmi'
@@ -220,7 +220,7 @@ obj/machinery/airlock_sensor/New()
obj/machinery/airlock_sensor/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
obj/machinery/airlock_sensor/airlock_interior
command = "cycle_interior"
@@ -292,7 +292,7 @@ obj/machinery/access_button/New()
obj/machinery/access_button/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ return ..()
obj/machinery/access_button/airlock_interior
frequency = 1379
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 3d899377cc..bf40ad9fff 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -13,7 +13,7 @@
icon = 'icons/obj/doors/rapid_pdoor.dmi'
icon_state = null
min_force = 20 //minimum amount of force needed to damage the door with a melee weapon
-
+ var/material/implicit_material
// Icon states for different shutter types. Simply change this instead of rewriting the update_icon proc.
var/icon_state_open = null
var/icon_state_opening = null
@@ -29,6 +29,13 @@
//turning this off prevents awkward zone geometry in places like medbay lobby, for example.
block_air_zones = 0
+/obj/machinery/door/blast/initialize()
+ ..()
+ implicit_material = get_material_by_name("plasteel")
+
+/obj/machinery/door/blast/get_material()
+ return implicit_material
+
// Proc: Bumped()
// Parameters: 1 (AM - Atom that tried to walk through this object)
// Description: If we are open returns zero, otherwise returns result of parent function.
@@ -46,6 +53,7 @@
icon_state = icon_state_closed
else
icon_state = icon_state_open
+ radiation_repository.resistance_cache.Remove(get_turf(src))
return
// Proc: force_open()
@@ -88,6 +96,17 @@
else
src.force_close()
+//Proc: attack_hand
+//Description: Attacked with empty hand. Only to allow special attack_bys.
+/obj/machinery/door/blast/attack_hand(mob/user as mob)
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ src.attack_alien(user)
+ return
+ ..()
+
+
// Proc: attackby()
// Parameters: 2 (C - Item this object was clicked with, user - Mob which clicked this object)
// Description: If we are clicked with crowbar, wielded fire axe, or armblade, try to manually open the door.
@@ -110,25 +129,8 @@
usr << "[src]'s motors resist your effort."
return
- if(istype(C, /obj/item/stack/material) && C.get_material_name() == "plasteel") // Repairing.
- var/amt = Ceiling((maxhealth - health)/150)
- if(!amt)
- usr << "\The [src] is already fully repaired."
- return
- var/obj/item/stack/P = C
- if(P.amount < amt)
- usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
- return
- usr << "You begin repairing [src]..."
- if(do_after(usr, 30))
- if(P.use(amt))
- usr << "You have repaired \The [src]"
- src.repair()
- else
- usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
-
- else if(src.density)
+ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's a weapon, let's hit it.
var/obj/item/weapon/W = C
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(W.damtype == BRUTE || W.damtype == BURN)
@@ -139,8 +141,61 @@
user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
playsound(src.loc, hitsound, 100, 1)
take_damage(W.force*0.35) //it's a blast door, it should take a while. -Luke
+ return
+
+ else if(istype(C, /obj/item/stack/material) && C.get_material_name() == "plasteel") // Repairing.
+ var/amt = Ceiling((maxhealth - health)/150)
+ if(!amt)
+ usr << "\The [src] is already fully repaired."
+ return
+ var/obj/item/stack/P = C
+ if(P.amount < amt)
+ usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
+ return
+ usr << "You begin repairing [src]..."
+ if(do_after(usr, 30))
+ if(P.use(amt))
+ usr << "You have repaired \The [src]"
+ src.repair()
+ else
+ usr << "You don't have enough sheets to repair this! You need at least [amt] sheets."
+
+ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's not a weapon.... Eh, let's attack it anyway.
+ var/obj/item/weapon/W = C
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(W.damtype == BRUTE || W.damtype == BURN)
+ user.do_attack_animation(src)
+ if(W.force < min_force) //No actual non-weapon item shouls have a force greater than the min_force, but let's include this just in case.
+ user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
+ else
+ user.visible_message("\The [user] forcefully strikes \the [src] with \the [W]!")
+ playsound(src.loc, hitsound, 100, 1)
+ take_damage(W.force*0.15) //If the item isn't a weapon, let's make this take longer than usual to break it down.
return
+// Proc: attack_alien()
+// Parameters: Attacking Xeno mob.
+// Description: Forces open the door after a delay.
+/obj/machinery/door/blast/attack_alien(var/mob/user) //Familiar, right? Doors.
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ if(src.density)
+ visible_message("\The [user] begins forcing \the [src] open!")
+ if(do_after(user, 15 SECONDS,src))
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ visible_message("\The [user] forces \the [src] open!")
+ force_open(1)
+ else
+ visible_message("\The [user] begins forcing \the [src] closed!")
+ if(do_after(user, 5 SECONDS,src))
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ visible_message("\The [user] forces \the [src] closed!")
+ force_close(1)
+ else
+ visible_message("\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].")
+ return
+ ..()
// Proc: open()
// Parameters: None
@@ -205,4 +260,4 @@ obj/machinery/door/blast/regular/open
icon_state_opening = "shutterc0"
icon_state_closed = "shutter1"
icon_state_closing = "shutterc1"
- icon_state = "shutter1"
\ No newline at end of file
+ icon_state = "shutter1"
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index cd38f9f1ce..4c3823f11e 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -73,8 +73,7 @@
/obj/machinery/door/Destroy()
density = 0
update_nearby_tiles()
- ..()
- return
+ . = ..()
/obj/machinery/door/process()
if(close_door_at && world.time >= close_door_at)
@@ -164,7 +163,7 @@
switch (Proj.damage_type)
if(BRUTE)
new /obj/item/stack/material/steel(src.loc, 2)
- PoolOrNew(/obj/item/stack/rods, list(src.loc, 3))
+ new /obj/item/stack/rods(src.loc, 3)
if(BURN)
new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes!
qdel(src)
@@ -242,8 +241,8 @@
var/obj/item/weapon/weldingtool/welder = I
if(welder.remove_fuel(0,user))
user << "You start to fix dents and weld \the [repairing] into place."
- playsound(src, 'sound/items/Welder.ogg', 100, 1)
- if(do_after(user, 5 * repairing.amount) && welder && welder.isOn())
+ playsound(src, welder.usesound, 50, 1)
+ if(do_after(user, (5 * repairing.amount) * welder.toolspeed) && welder && welder.isOn())
user << "You finish repairing the damage to \the [src]."
health = between(health, health + repairing.amount*DOOR_REPAIR_AMOUNT, maxhealth)
update_icon()
@@ -253,7 +252,7 @@
if(repairing && istype(I, /obj/item/weapon/crowbar))
user << "You remove \the [repairing]."
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, I.usesound, 100, 1)
repairing.loc = user.loc
repairing = null
return
@@ -362,6 +361,7 @@
icon_state = "door1"
else
icon_state = "door0"
+ radiation_repository.resistance_cache.Remove(get_turf(src))
return
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index cbdcfb9f2f..931e6cbe1e 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -60,18 +60,18 @@
var/area/A = get_area(src)
ASSERT(istype(A))
- A.all_doors.Add(src)
+ LAZYADD(A.all_doors, src)
areas_added = list(A)
for(var/direction in cardinal)
A = get_area(get_step(src,direction))
if(istype(A) && !(A in areas_added))
- A.all_doors.Add(src)
+ LAZYADD(A.all_doors, src)
areas_added += A
/obj/machinery/door/firedoor/Destroy()
for(var/area/A in areas_added)
- A.all_doors.Remove(src)
+ LAZYREMOVE(A.all_doors, src)
. = ..()
/obj/machinery/door/firedoor/get_material()
@@ -135,13 +135,19 @@
if(operating)
return//Already doing something.
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ src.attack_alien(user)
+ return
+
if(blocked)
user << "\The [src] is welded solid!"
return
var/alarmed = lockdown
for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor
- if(A.fire || A.air_doors_activated)
+ if(A.firedoors_closed)
alarmed = 1
var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\
@@ -179,12 +185,37 @@
spawn(50)
alarmed = 0
for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle
- if(A.fire || A.air_doors_activated)
+ if(A.firedoors_closed)
alarmed = 1
if(alarmed)
nextstate = FIREDOOR_CLOSED
close()
+/obj/machinery/door/firedoor/attack_alien(var/mob/user) //Familiar, right? Doors.
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/X = user
+ if(istype(X.species, /datum/species/xenos))
+ if(src.blocked)
+ visible_message("\The [user] begins digging into \the [src] internals!")
+ if(do_after(user,5 SECONDS,src))
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ src.blocked = 0
+ update_icon()
+ open(1)
+ else if(src.density)
+ visible_message("\The [user] begins forcing \the [src] open!")
+ if(do_after(user, 2 SECONDS,src))
+ playsound(src.loc, 'sound/machines/airlock_creaking.ogg', 100, 1)
+ visible_message("\The [user] forces \the [src] open!")
+ open(1)
+ else
+ visible_message("\The [user] forces \the [src] closed!")
+ close(1)
+ else
+ visible_message("\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].")
+ return
+ ..()
+
/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob)
add_fingerprint(user)
if(operating)
@@ -198,12 +229,13 @@
user.visible_message("\The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\
"You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\
"You hear something being welded.")
- playsound(src, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src, W.usesound, 100, 1)
update_icon()
return
if(density && istype(C, /obj/item/weapon/screwdriver))
hatch_open = !hatch_open
+ playsound(src, C.usesound, 50, 1)
user.visible_message("[user] has [hatch_open ? "opened" : "closed"] \the [src] maintenance hatch.",
"You have [hatch_open ? "opened" : "closed"] the [src] maintenance hatch.")
update_icon()
@@ -217,7 +249,7 @@
"You start to remove the electronics from [src].")
if(do_after(user,30))
if(blocked && density && hatch_open)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, C.usesound, 50, 1)
user.visible_message("[user] has removed the electronics from \the [src].",
"You have removed the electronics from [src].")
@@ -262,8 +294,8 @@
"You hear metal strain.")
prying = 1
update_icon()
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
- if(do_after(user,30))
+ playsound(src, C.usesound, 100, 1)
+ if(do_after(user,30 * C.toolspeed))
if(istype(C, /obj/item/weapon/crowbar))
if(stat & (BROKEN|NOPOWER) || !density)
user.visible_message("\The [user] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\
@@ -368,7 +400,9 @@
switch(animation)
if("opening")
flick("door_opening", src)
+ playsound(src, 'sound/machines/firelockopen.ogg', 37, 1)
if("closing")
+ playsound(src, 'sound/machines/firelockclose.ogg', 37, 1)
flick("door_closing", src)
return
diff --git a/code/game/machinery/doors/firedoor_assembly.dm b/code/game/machinery/doors/firedoor_assembly.dm
index a96065d2c6..f30c2e6146 100644
--- a/code/game/machinery/doors/firedoor_assembly.dm
+++ b/code/game/machinery/doors/firedoor_assembly.dm
@@ -14,7 +14,7 @@ obj/structure/firedoor_assembly/update_icon()
else
icon_state = "door_construction"
-obj/structure/firedoor_assembly/attackby(C as obj, mob/user as mob)
+obj/structure/firedoor_assembly/attackby(obj/item/C, mob/user as mob)
if(istype(C, /obj/item/stack/cable_coil) && !wired && anchored)
var/obj/item/stack/cable_coil/cable = C
if (cable.get_amount() < 1)
@@ -27,7 +27,7 @@ obj/structure/firedoor_assembly/attackby(C as obj, mob/user as mob)
user << "You wire \the [src]."
else if(istype(C, /obj/item/weapon/wirecutters) && wired )
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src.loc, C.usesound, 100, 1)
user.visible_message("[user] cuts the wires from \the [src].", "You start to cut the wires from \the [src].")
if(do_after(user, 40))
@@ -48,7 +48,7 @@ obj/structure/firedoor_assembly/attackby(C as obj, mob/user as mob)
user << "You must secure \the [src] first!"
else if(istype(C, /obj/item/weapon/wrench))
anchored = !anchored
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src.loc, C.usesound, 50, 1)
user.visible_message("[user] has [anchored ? "" : "un" ]secured \the [src]!",
"You have [anchored ? "" : "un" ]secured \the [src]!")
update_icon()
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 13352a1645..4fc02c70cc 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -60,7 +60,7 @@
/obj/machinery/door/window/Destroy()
density = 0
update_nearby_tiles()
- ..()
+ return ..()
/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj)
if (!( ismob(AM) ))
@@ -180,6 +180,21 @@
if (src.operating == 1)
return
+ // Fixing.
+ if(istype(I, /obj/item/weapon/weldingtool) && user.a_intent == I_HELP)
+ var/obj/item/weapon/weldingtool/WT = I
+ if(health < maxhealth)
+ if(WT.remove_fuel(1 ,user))
+ to_chat(user, "You begin repairing [src]...")
+ playsound(src, WT.usesound, 50, 1)
+ if(do_after(user, 40 * WT.toolspeed, target = src))
+ health = maxhealth
+ update_icon()
+ to_chat(user, "You repair [src].")
+ else
+ to_chat(user, "[src] is already in good condition!")
+ return
+
//Emags and ninja swords? You may pass.
if (istype(I, /obj/item/weapon/melee/energy/blade))
if(emag_act(10, user))
@@ -193,9 +208,9 @@
//If it's opened/emagged, crowbar can pry it out of its frame.
if (!density && istype(I, /obj/item/weapon/crowbar))
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, I.usesound, 50, 1)
user.visible_message("[user] begins prying the windoor out of the frame.", "You start to pry the windoor out of the frame.")
- if (do_after(user,40))
+ if (do_after(user,40 * I.toolspeed))
to_chat(user,"You pried the windoor out of the frame!")
var/obj/structure/windoor_assembly/wa = new/obj/structure/windoor_assembly(src.loc)
diff --git a/code/game/machinery/floor_light.dm b/code/game/machinery/floor_light.dm
index a134e68e3f..40ff7a3b04 100644
--- a/code/game/machinery/floor_light.dm
+++ b/code/game/machinery/floor_light.dm
@@ -31,8 +31,8 @@ var/list/floor_light_cache = list()
if(!WT.remove_fuel(0, user))
user << "\The [src] must be on to complete this task."
return
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
- if(!do_after(user, 20))
+ playsound(src.loc, WT.usesound, 50, 1)
+ if(!do_after(user, 20 * WT.toolspeed))
return
if(!src || !WT.isOn())
return
@@ -150,7 +150,7 @@ var/list/floor_light_cache = list()
var/area/A = get_area(src)
if(A)
on = 0
- ..()
+ . = ..()
/obj/machinery/floor_light/cultify()
default_light_colour = "#FF0000"
diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm
index f553bfa9fe..c6b32d75db 100644
--- a/code/game/machinery/frame.dm
+++ b/code/game/machinery/frame.dm
@@ -17,13 +17,20 @@
construction_frame_floor += cancel
/datum/frame/frame_types
- var/name
- var/frame_size = 5
- var/frame_class
- var/circuit
- var/frame_style = "floor"
- var/x_offset
- var/y_offset
+ var/icon/icon_override // Icon to set on frame object when building. If null icon is unchanged.
+ var/name // Name assigned to the frame object.
+ var/frame_size = 5 // Sheets of metal required to build.
+ var/frame_class // Determines construction method. "machine", "computer", "alarm", or "display"
+ var/circuit // Type path of the circuit board that comes built in with this frame. Null to require adding a circuit.
+ var/frame_style = "floor" // "floor" or "wall"
+ var/x_offset // For wall frames: pixel_x
+ var/y_offset // For wall frames: pixel_y
+
+// Get the icon state to use at a given state. Default implementation is based on the frame's name
+/datum/frame/frame_types/proc/get_icon_state(var/state)
+ var/type = lowertext(name)
+ type = replacetext(type, " ", "_")
+ return "[type]_[state]"
/datum/frame/frame_types/computer
name = "Computer"
@@ -203,9 +210,9 @@
/obj/structure/frame/update_icon()
..()
- var/type = lowertext(frame_type.name)
- type = replacetext(type, " ", "_")
- icon_state = "[type]_[state]"
+ if(frame_type.icon_override)
+ icon = frame_type.icon_override
+ icon_state = frame_type.get_icon_state(state)
/obj/structure/frame/proc/check_components(mob/user as mob)
components = list()
@@ -251,8 +258,8 @@
if(istype(P, /obj/item/weapon/wrench))
if(state == 0 && !anchored)
user << "You start to wrench the frame into place."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(user, 20 * P.toolspeed))
anchored = 1
if(!need_circuit && circuit)
state = 2
@@ -263,8 +270,8 @@
user << "You wrench the frame into place."
else if(state == 0 && anchored)
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src, P.usesound, 50, 1)
+ if(do_after(user, 20 * P.toolspeed))
user << "You unfasten the frame."
anchored = 0
@@ -272,8 +279,8 @@
if(state == 0)
var/obj/item/weapon/weldingtool/WT = P
if(WT.remove_fuel(0, user))
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(user, 20 * P.toolspeed))
if(src && WT.isOn())
user << "You deconstruct the frame."
new /obj/item/stack/material/steel(src.loc, frame_type.frame_size)
@@ -304,18 +311,18 @@
else if(istype(P, /obj/item/weapon/screwdriver))
if(state == 1)
if(need_circuit && circuit)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You screw the circuit board into place."
state = 2
else if(state == 2)
if(need_circuit && circuit)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You unfasten the circuit board."
state = 1
else if(!need_circuit && circuit)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You unfasten the outer cover."
state = 0
@@ -327,7 +334,7 @@
component_check = 0
break
if(component_check)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
var/obj/machinery/new_machine = new circuit.build_path(src.loc, dir)
// Handle machines that have allocated default parts in thier constructor.
if(new_machine.component_parts)
@@ -357,7 +364,7 @@
return
else if(frame_type.frame_class == "alarm")
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You fasten the cover."
var/obj/machinery/B = new circuit.build_path(src.loc)
B.pixel_x = pixel_x
@@ -371,7 +378,7 @@
else if(state == 4)
if(frame_type.frame_class == "computer")
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You connect the monitor."
var/obj/machinery/B = new circuit.build_path(src.loc)
B.pixel_x = pixel_x
@@ -384,7 +391,7 @@
return
else if(frame_type.frame_class == "display")
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You connect the monitor."
var/obj/machinery/B = new circuit.build_path(src.loc)
B.pixel_x = pixel_x
@@ -399,7 +406,7 @@
else if(istype(P, /obj/item/weapon/crowbar))
if(state == 1)
if(need_circuit && circuit)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the circuit board."
state = 0
circuit.forceMove(src.loc)
@@ -409,7 +416,7 @@
else if(state == 3)
if(frame_type.frame_class == "machine")
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
if(components.len == 0)
user << "There are no components to remove."
else
@@ -422,13 +429,13 @@
else if(state == 4)
if(frame_type.frame_class == "computer")
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the glass panel."
state = 3
new /obj/item/stack/material/glass(src.loc, 2)
else if(frame_type.frame_class == "display")
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the glass panel."
state = 3
new /obj/item/stack/material/glass(src.loc, 2)
@@ -476,25 +483,25 @@
else if(istype(P, /obj/item/weapon/wirecutters))
if(state == 3)
if(frame_type.frame_class == "computer")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the cables."
state = 2
new /obj/item/stack/cable_coil(src.loc, 5)
else if(frame_type.frame_class == "display")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the cables."
state = 2
new /obj/item/stack/cable_coil(src.loc, 5)
else if(frame_type.frame_class == "alarm")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the cables."
state = 2
new /obj/item/stack/cable_coil(src.loc, 5)
else if(frame_type.frame_class == "machine")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, P.usesound, 50, 1)
user << "You remove the cables."
state = 2
new /obj/item/stack/cable_coil(src.loc, 5)
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 158b718e83..e0156196d6 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -202,7 +202,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/Destroy()
for (var/mob/living/silicon/ai/master in masters)
clear_holo(master)
- ..()
+ return ..()
/*
Holographic project of everything else.
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 97c430f9d0..1e67fb8b4f 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -74,6 +74,7 @@
if(istype(W, /obj/item/weapon/screwdriver))
add_fingerprint(user)
disable = !disable
+ playsound(src, W.usesound, 50, 1)
if(disable)
user.visible_message("[user] has disabled the [src]!", "You disable the connection to the [src].")
icon_state = "[base_state]-d"
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index e50688b7a9..306a098638 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -66,7 +66,7 @@
return
if(istype(W, /obj/item/weapon/screwdriver))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
user << "You start to dismantle the IV drip."
if(do_after(user, 15))
user << "You dismantle the IV drip."
diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm
index 4eb0e7d408..5b5bb8c475 100644
--- a/code/game/machinery/jukebox.dm
+++ b/code/game/machinery/jukebox.dm
@@ -84,7 +84,7 @@ datum/track/New(var/title_name, var/audio)
StopPlaying()
user.visible_message("[user] has [anchored ? "un" : ""]secured \the [src].", "You [anchored ? "un" : ""]secure \the [src].")
anchored = !anchored
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
power_change()
update_icon()
return
@@ -224,7 +224,7 @@ datum/track/New(var/title_name, var/audio)
StopPlaying()
user.visible_message("[user] has [anchored ? "un" : ""]secured \the [src].", "You [anchored ? "un" : ""]secure \the [src].")
anchored = !anchored
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
power_change()
update_icon()
return
diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm
index a6af0f13f2..26b21c9a13 100644
--- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm
+++ b/code/game/machinery/kitchen/cooking_machines/_cooker.dm
@@ -76,10 +76,21 @@
else if(istype(check, /obj/item/weapon/disk/nuclear))
user << "Central Command would kill you if you [cook_type] that."
return 0
- else if(!istype(check) && !istype(check, /obj/item/weapon/holder) && !istype(check, /obj/item/organ))
- user << "That's not edible."
- return 0
-
+ else if(!istype(check) && !istype(check, /obj/item/weapon/holder) && !istype(check, /obj/item/organ)) //Gripper check has to go here, else it still just cuts it off. ~Mechoid
+ // Is it a borg using a gripper?
+ if(istype(check, /obj/item/weapon/gripper)) // Grippers. ~Mechoid.
+ var/obj/item/weapon/gripper/B = check //B, for Borg.
+ if(!B.wrapped)
+ user << "\The [B] is not holding anything."
+ return 0
+ else
+ var/B_held = B.wrapped
+ user << "You use \the [B] to put \the [B_held] into \the [src]."
+ return 0
+ else
+ user << "That's not edible."
+ return 0
+
if(istype(I, /obj/item/organ))
var/obj/item/organ/O = I
if(O.robotic)
@@ -91,8 +102,8 @@
for(var/mob/living/M in cooking_obj.contents)
M.apply_damage(rand(30,40), BURN, "chest")
- // Not sure why a food item that passed the previous checks would fail to drop, but safety first.
- if(!user.unEquip(I))
+ // Not sure why a food item that passed the previous checks would fail to drop, but safety first. (Hint: Borg grippers. That is why. ~Mechoid.)
+ if(!user.unEquip(I) && !istype(user,/mob/living/silicon/robot))
return
// We can actually start cooking now.
@@ -134,7 +145,7 @@
// Copy reagents over. trans_to_obj must be used, as trans_to fails for snacks due to is_open_container() failing.
if(cooking_obj.reagents && cooking_obj.reagents.total_volume)
cooking_obj.reagents.trans_to_obj(result, cooking_obj.reagents.total_volume)
-
+
// Set cooked data.
var/obj/item/weapon/reagent_containers/food/snacks/food_item = cooking_obj
if(istype(food_item) && islist(food_item.cooked))
@@ -170,7 +181,7 @@
cooking_obj = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src)
// Produce nasty smoke.
visible_message("\The [src] vomits a gout of rancid smoke!")
- var/datum/effect/effect/system/smoke_spread/bad/smoke = PoolOrNew(/datum/effect/effect/system/smoke_spread/bad)
+ var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
smoke.attach(src)
smoke.set_up(10, 0, usr.loc)
smoke.start()
@@ -183,7 +194,7 @@
/obj/machinery/cooker/attack_hand(var/mob/user)
- if(cooking_obj)
+ if(cooking_obj && user.Adjacent(src)) //Fixes borgs being able to teleport food in these machines to themselves.
user << "You grab \the [cooking_obj] from \the [src]."
user.put_in_hands(cooking_obj)
cooking = 0
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index a3b0f9fdd4..c789c94db5 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -1,5 +1,5 @@
/obj/machinery/microwave
- name = "Microwave"
+ name = "microwave"
icon = 'icons/obj/kitchen.dmi'
icon_state = "mw"
layer = 2.9
@@ -67,7 +67,8 @@
"\The [user] starts to fix part of the microwave.", \
"You start to fix part of the microwave." \
)
- if (do_after(user,20))
+ playsound(src, O.usesound, 50, 1)
+ if (do_after(user,20 * O.toolspeed))
user.visible_message( \
"\The [user] fixes part of the microwave.", \
"You have fixed part of the microwave." \
@@ -78,7 +79,7 @@
"\The [user] starts to fix part of the microwave.", \
"You start to fix part of the microwave." \
)
- if (do_after(user,20))
+ if (do_after(user,20 * O.toolspeed))
user.visible_message( \
"\The [user] fixes the microwave.", \
"You have fixed the microwave." \
@@ -96,7 +97,7 @@
return
else if(src.dirty==100) // The microwave is all dirty so can't be used!
- if(istype(O, /obj/item/weapon/reagent_containers/spray/cleaner)) // If they're trying to clean it then let them
+ if(istype(O, /obj/item/weapon/reagent_containers/spray/cleaner) || istype(O, /obj/item/weapon/soap)) // If they're trying to clean it then let them
user.visible_message( \
"\The [user] starts to clean the microwave.", \
"You start to clean the microwave." \
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index ae48142b4d..86b481b31b 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -65,20 +65,12 @@
req_access = list(access_research)
/obj/machinery/smartfridge/secure/extract/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/xenoproduct/))
- return 1
- return 0
+ if(istype(O, /obj/item/slime_extract))
+ return TRUE
+ if(istype(O, /obj/item/slimepotion))
+ return TRUE
+ return FALSE
-/obj/machinery/smartfridge/secure/extract/New()
- ..()
- var/datum/stored_item/I = new(src, /obj/item/xenoproduct/slime/core)
- item_records.Add(I)
- for(var/i=1 to 5)
- var/obj/item/xenoproduct/slime/core/C = new(src)
- C.traits = new()
- C.nameVar = "grey"
- I.add_product(C)
-
/obj/machinery/smartfridge/secure/medbay
name = "\improper Refrigerated Medicine Storage"
@@ -139,6 +131,7 @@
icon_state = "drying_rack"
icon_on = "drying_rack_on"
icon_off = "drying_rack"
+ icon_panel = "drying_rack-panel"
/obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj)
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/))
@@ -217,6 +210,7 @@
if(istype(O, /obj/item/weapon/screwdriver))
panel_open = !panel_open
user.visible_message("[user] [panel_open ? "opens" : "closes"] the maintenance panel of \the [src].", "You [panel_open ? "open" : "close"] the maintenance panel of \the [src].")
+ playsound(src, O.usesound, 50, 1)
overlays.Cut()
if(panel_open)
overlays += image(icon, icon_panel)
@@ -250,6 +244,16 @@
if(P.contents.len > 0)
user << "Some items are refused."
+ else if(istype(O, /obj/item/weapon/gripper)) // Grippers. ~Mechoid.
+ var/obj/item/weapon/gripper/B = O //B, for Borg.
+ if(!B.wrapped)
+ user << "\The [B] is not holding anything."
+ return
+ else
+ var/B_held = B.wrapped
+ user << "You use \the [B] to put \the [B_held] into \the [src]."
+ return
+
else
user << "\The [src] smartly refuses [O]."
return 1
@@ -260,7 +264,7 @@
locked = -1
user << "You short out the product lock on [src]."
return 1
-
+
/obj/machinery/smartfridge/proc/stock(obj/item/O)
var/hasRecord = FALSE //Check to see if this passes or not.
for(var/datum/stored_item/I in item_records)
@@ -273,7 +277,7 @@
item.add_product(O)
item_records.Add(item)
nanomanager.update_uis(src)
-
+
/obj/machinery/smartfridge/proc/vend(datum/stored_item/I)
I.get_product(get_turf(src))
nanomanager.update_uis(src)
@@ -357,7 +361,7 @@
if (!throw_item)
continue
break
-
+
if(!throw_item)
return 0
spawn(0)
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index b0946bf347..f476c295e2 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -155,7 +155,7 @@ Class Procs:
if(use_power && stat == 0)
use_power(7500/severity)
- var/obj/effect/overlay/pulse2 = PoolOrNew(/obj/effect/overlay, src.loc)
+ var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(src.loc)
pulse2.icon = 'icons/effects/effects.dmi'
pulse2.icon_state = "empdisable"
pulse2.name = "emp sparks"
@@ -331,7 +331,7 @@ Class Procs:
/obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/obj/item/weapon/screwdriver/S)
if(!istype(S))
return 0
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, S.usesound, 50, 1)
panel_open = !panel_open
user << "You [panel_open ? "open" : "close"] the maintenance hatch of [src]."
update_icon()
@@ -343,8 +343,8 @@ Class Procs:
if(!circuit)
return 0
user << "You start disconnecting the monitor."
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- if(do_after(user, 20))
+ playsound(src, S.usesound, 50, 1)
+ if(do_after(user, 20 * S.toolspeed))
if(stat & BROKEN)
user << "The broken glass falls out."
new /obj/item/weapon/material/shard(src.loc)
@@ -355,7 +355,7 @@ Class Procs:
/obj/machinery/proc/alarm_deconstruction_screwdriver(var/mob/user, var/obj/item/weapon/screwdriver/S)
if(!istype(S))
return 0
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, S.usesound, 50, 1)
panel_open = !panel_open
user << "The wires have been [panel_open ? "exposed" : "unexposed"]"
update_icon()
@@ -367,7 +367,7 @@ Class Procs:
if(!panel_open)
return 0
user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src.loc, W.usesound, 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
. = dismantle()
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index 8700caf785..ac0af16378 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -75,7 +75,7 @@ var/global/list/navbeacons = list() // no I don't like putting this in, but it w
if(istype(I, /obj/item/weapon/screwdriver))
open = !open
-
+ playsound(src, I.usesound, 50, 1)
user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "You [open ? "open" : "close"] the beacon's cover.")
updateicon()
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index f2a0132b5a..5ce605afcc 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -268,7 +268,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
switch(screen)
if(0)
dat += "Welcome to Newscasting Unit #[unit_no]. Interface & News networks Operational."
- dat += " Property of Nanotransen Inc"
+ dat += " Property of NanoTrasen Inc"
if(news_network.wanted_issue)
dat+= " Read Wanted Issue"
dat+= "
Create Feed Channel"
diff --git a/code/game/machinery/nuclear_bomb.dm b/code/game/machinery/nuclear_bomb.dm
index ea5c78d734..018cf75f53 100644
--- a/code/game/machinery/nuclear_bomb.dm
+++ b/code/game/machinery/nuclear_bomb.dm
@@ -56,6 +56,7 @@ var/bomb_set
/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/screwdriver))
+ playsound(src, O.usesound, 50, 1)
add_fingerprint(user)
if(auth)
if(opened == 0)
@@ -103,7 +104,7 @@ var/bomb_set
user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...")
- if(do_after(user,40))
+ if(do_after(user,40 * WT.toolspeed))
if(!src || !user || !WT.remove_fuel(5, user)) return
user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.")
removal_stage = 1
@@ -113,7 +114,8 @@ var/bomb_set
if(istype(O,/obj/item/weapon/crowbar))
user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...")
- if(do_after(user,15))
+ playsound(src, O.usesound, 50, 1)
+ if(do_after(user,15 * O.toolspeed))
if(!src || !user) return
user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.")
removal_stage = 2
@@ -129,8 +131,8 @@ var/bomb_set
return
user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...")
-
- if(do_after(user,40))
+ playsound(src, WT.usesound, 50, 1)
+ if(do_after(user,40 * WT.toolspeed))
if(!src || !user || !WT.remove_fuel(5, user)) return
user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.")
removal_stage = 3
@@ -140,8 +142,8 @@ var/bomb_set
if(istype(O,/obj/item/weapon/wrench))
user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...")
-
- if(do_after(user,50))
+ playsound(src, O.usesound, 50, 1)
+ if(do_after(user,50 * O.toolspeed))
if(!src || !user) return
user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.")
removal_stage = 4
@@ -151,8 +153,8 @@ var/bomb_set
if(istype(O,/obj/item/weapon/crowbar))
user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...")
-
- if(do_after(user,80))
+ playsound(src, O.usesound, 50, 1)
+ if(do_after(user,80 * O.toolspeed))
if(!src || !user) return
user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!")
anchored = 0
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 4abdb685d0..4547b4eaf3 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -55,6 +55,7 @@ Buildable meters
#define PIPE_DTVALVE 45
#define PIPE_DTVALVEM 46
+#define PIPE_PASSIVE_VENT 47
/obj/item/pipe
name = "pipe"
@@ -198,6 +199,8 @@ Buildable meters
else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down))
src.pipe_type = PIPE_DOWN
///// Z-Level stuff
+ else if(istype(make_from, /obj/machinery/atmospherics/pipe/vent))
+ src.pipe_type = PIPE_PASSIVE_VENT
else
src.pipe_type = pipe_type
src.set_dir(dir)
@@ -272,6 +275,7 @@ Buildable meters
"dvalve", \
"dt-valve", \
"dt-valve m", \
+ "passive vent", \
)
name = nlist[pipe_type+1] + " fitting"
var/list/islist = list( \
@@ -325,6 +329,7 @@ Buildable meters
"dvalve", \
"dtvalve", \
"dtvalvem", \
+ "passive vent", \
)
icon_state = islist[pipe_type + 1]
@@ -414,6 +419,8 @@ Buildable meters
if(PIPE_UP,PIPE_DOWN,PIPE_SUPPLY_UP,PIPE_SUPPLY_DOWN,PIPE_SCRUBBERS_UP,PIPE_SCRUBBERS_DOWN)
return dir
///// Z-Level stuff
+ if(PIPE_PASSIVE_VENT)
+ return dir
return 0
/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes
@@ -485,7 +492,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -504,7 +511,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -523,7 +530,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -542,7 +549,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -559,7 +566,7 @@ Buildable meters
P.initialize_directions = pipe_dir //this var it's used to know if the pipe is bent or not
P.initialize_directions_he = pipe_dir
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -594,7 +601,7 @@ Buildable meters
var/turf/T = M.loc
M.level = !T.is_plating() ? 2 : 1
M.initialize()
- if (deleted(M))
+ if (QDELETED(M))
usr << pipefailtext
return 1
M.build_network()
@@ -663,7 +670,7 @@ Buildable meters
var/turf/T = M.loc
M.level = !T.is_plating() ? 2 : 1
M.initialize()
- if (deleted(M))
+ if (QDELETED(M))
usr << pipefailtext
return 1
M.build_network()
@@ -740,7 +747,7 @@ Buildable meters
P.initialize_directions = src.get_pdir()
P.initialize_directions_he = src.get_hdir()
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext //"There's nothing to connect this pipe to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
return 1
P.build_network()
@@ -922,7 +929,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
- if (deleted(P))
+ if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -1230,8 +1237,19 @@ Buildable meters
P.level = !T.is_plating() ? 2 : 1
P.initialize()
P.build_network()
+ if(PIPE_PASSIVE_VENT)
+ var/obj/machinery/atmospherics/pipe/vent/P = new(loc)
+ P.set_dir(dir)
+ P.initialize_directions = pipe_dir
+ var/turf/T = P.loc
+ P.level = !T.is_plating() ? 2 : 1
+ P.initialize()
+ P.build_network()
+ if (P.node1)
+ P.node1.initialize()
+ P.node1.build_network()
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
user.visible_message( \
"[user] fastens the [src].", \
"You have fastened the [src].", \
@@ -1262,7 +1280,7 @@ Buildable meters
user << "You need to fasten it to a pipe"
return 1
new/obj/machinery/meter( src.loc )
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
user << "You have fastened the meter to the pipe"
qdel(src)
//not sure why these are necessary
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 7727b675d2..8bc779adf3 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -46,6 +46,7 @@
Universal pipe adapter
Connector
Unary Vent
+Passive Vent
Gas Pump
Pressure Regulator
High Power Gas Pump
@@ -110,9 +111,9 @@
return
else if (istype(W, /obj/item/weapon/wrench))
if (unwrenched==0)
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
user << "You begin to unfasten \the [src] from the floor..."
- if (do_after(user, 40))
+ if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
"[user] unfastens \the [src].", \
"You have unfastened \the [src]. Now it can be pulled somewhere else.", \
@@ -123,9 +124,9 @@
if (usr.machine==src)
usr << browse(null, "window=pipedispenser")
else /*if (unwrenched==1)*/
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
user << "You begin to fasten \the [src] to the floor..."
- if (do_after(user, 20))
+ if (do_after(user, 20 * W.toolspeed))
user.visible_message( \
"[user] fastens \the [src].", \
"You have fastened \the [src]. Now it can dispense pipes.", \
diff --git a/code/game/machinery/pipe/pipelayer.dm b/code/game/machinery/pipe/pipelayer.dm
index 40726825a1..c960879e54 100644
--- a/code/game/machinery/pipe/pipelayer.dm
+++ b/code/game/machinery/pipe/pipelayer.dm
@@ -23,9 +23,8 @@
update_icon()
/obj/machinery/pipelayer/Destroy()
- qdel(W)
- W = null
- ..()
+ qdel_null(W)
+ . = ..()
/obj/machinery/pipelayer/RefreshParts()
var/mb_rating = 0
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 595712afd3..8eba407e72 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -329,15 +329,15 @@ var/list/turret_icons
)
wrenching = 1
- if(do_after(user, 50))
+ if(do_after(user, 50 * I.toolspeed))
//This code handles moving the turret around. After all, it's a portable turret!
if(!anchored)
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
anchored = 1
update_icon()
user << "You secure the exterior bolts on the turret."
else if(anchored)
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
anchored = 0
user << "You unsecure the exterior bolts on the turret."
update_icon()
@@ -525,7 +525,7 @@ var/list/turret_icons
if(isanimal(L) || issmall(L)) // Animals are not so dangerous
return check_anomalies ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET
- if(isalien(L)) // Xenos are dangerous
+ if(isxenomorph(L) || isalien(L)) // Xenos are dangerous
return check_anomalies ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET
if(ishuman(L)) //if the target is a human, analyze threat level
@@ -567,7 +567,7 @@ var/list/turret_icons
set_raised_raising(raised, 1)
update_icon()
- var/atom/flick_holder = PoolOrNew(/atom/movable/porta_turret_cover, loc)
+ var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1
flick("popup", flick_holder)
sleep(10)
@@ -588,7 +588,7 @@ var/list/turret_icons
set_raised_raising(raised, 1)
update_icon()
- var/atom/flick_holder = PoolOrNew(/atom/movable/porta_turret_cover, loc)
+ var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1
flick("popdown", flick_holder)
sleep(10)
@@ -711,14 +711,14 @@ var/list/turret_icons
switch(build_step)
if(0) //first step
if(istype(I, /obj/item/weapon/wrench) && !anchored)
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
user << "You secure the external bolts."
anchored = 1
build_step = 1
return
else if(istype(I, /obj/item/weapon/crowbar) && !anchored)
- playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
+ playsound(loc, I.usesound, 75, 1)
user << "You dismantle the turret construction."
new /obj/item/stack/material/steel(loc, 5)
qdel(src)
@@ -736,7 +736,7 @@ var/list/turret_icons
return
else if(istype(I, /obj/item/weapon/wrench))
- playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(loc, I.usesound, 75, 1)
user << "You unfasten the external bolts."
anchored = 0
build_step = 0
@@ -744,7 +744,7 @@ var/list/turret_icons
if(2)
if(istype(I, /obj/item/weapon/wrench))
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
user << "You bolt the metal armor into place."
build_step = 3
return
@@ -757,8 +757,8 @@ var/list/turret_icons
user << "You need more fuel to complete this task."
return
- playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
- if(do_after(user, 20))
+ playsound(loc, I.usesound, 50, 1)
+ if(do_after(user, 20 * I.toolspeed))
if(!src || !WT.remove_fuel(5, user)) return
build_step = 1
user << "You remove the turret's interior metal armor."
@@ -784,7 +784,7 @@ var/list/turret_icons
return
else if(istype(I, /obj/item/weapon/wrench))
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
user << "You remove the turret's metal armor bolts."
build_step = 2
return
@@ -803,7 +803,7 @@ var/list/turret_icons
if(5)
if(istype(I, /obj/item/weapon/screwdriver))
- playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
build_step = 6
user << "You close the internal access hatch."
return
@@ -821,7 +821,7 @@ var/list/turret_icons
return
else if(istype(I, /obj/item/weapon/screwdriver))
- playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(loc, I.usesound, 100, 1)
build_step = 5
user << "You open the internal access hatch."
return
@@ -833,8 +833,8 @@ var/list/turret_icons
if(WT.get_fuel() < 5)
user << "You need more fuel to complete this task."
- playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
- if(do_after(user, 30))
+ playsound(loc, WT.usesound, 50, 1)
+ if(do_after(user, 30 * WT.toolspeed))
if(!src || !WT.remove_fuel(5, user))
return
build_step = 8
@@ -851,7 +851,7 @@ var/list/turret_icons
qdel(src) // qdel
else if(istype(I, /obj/item/weapon/crowbar))
- playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
+ playsound(loc, I.usesound, 75, 1)
user << "You pry off the turret's exterior armor."
new /obj/item/stack/material/steel(loc, 2)
build_step = 6
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 6dd278dc63..6455fa6430 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -81,7 +81,7 @@ obj/machinery/recharger
return
anchored = !anchored
to_chat(user, "You [anchored ? "attached" : "detached"] the recharger.")
- playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(loc, G.usesound, 75, 1)
else if(default_deconstruction_screwdriver(user, G))
return
else if(default_deconstruction_crowbar(user, G))
@@ -187,6 +187,17 @@ obj/machinery/recharger
update_use_power(1)
return
+ if(istype(charging, /obj/item/weapon/weldingtool/electric))
+ var/obj/item/weapon/weldingtool/electric/C = charging
+ if(!C.power_supply.fully_charged())
+ icon_state = icon_state_charging
+ C.power_supply.give(active_power_usage*CELLRATE)
+ update_use_power(2)
+ else
+ icon_state = icon_state_charged
+ update_use_power(1)
+ return
+
/obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored)
..(severity)
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 2854d0ac25..64aecd9c0f 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -97,7 +97,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
req_console_supplies -= department
if(departmentType & RC_INFO)
req_console_information -= department
- ..()
+ return ..()
/obj/machinery/requests_console/attack_hand(user as mob)
if(..(user))
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index d60d49b47e..830c5f8d6d 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -68,6 +68,7 @@
return
else if(istype(I, /obj/item/weapon/screwdriver))
panel_open = !panel_open
+ playsound(src, I.usesound, 50, 1)
user.visible_message("[user] [panel_open ? "opens" : "closes"] the hatch on the [src].", "You [panel_open ? "open" : "close"] the hatch on the [src].")
update_icon()
if(!panel_open && user.machine == src)
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index 98582f3ccc..527b5f1283 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -90,6 +90,10 @@
if(STATUS_DISPLAY_BLANK) //blank
return 1
if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer
+ if(!emergency_shuttle)
+ message1 = "-ETA-"
+ message2 = "Never" // You're here forever.
+ return 1
if(emergency_shuttle.waiting_to_leave())
message1 = "-ETD-"
if(emergency_shuttle.shuttle.is_launching())
@@ -172,12 +176,16 @@
maptext = new_text
/obj/machinery/status_display/proc/get_shuttle_timer_arrival()
+ if(!emergency_shuttle)
+ return "Error"
var/timeleft = emergency_shuttle.estimate_arrival_time()
if(timeleft < 0)
return ""
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/obj/machinery/status_display/proc/get_shuttle_timer_departure()
+ if(!emergency_shuttle)
+ return "Error"
var/timeleft = emergency_shuttle.estimate_launch_time()
if(timeleft < 0)
return ""
diff --git a/code/game/machinery/status_display_ai.dm b/code/game/machinery/status_display_ai.dm
index 6984017c3d..d0764221ba 100644
--- a/code/game/machinery/status_display_ai.dm
+++ b/code/game/machinery/status_display_ai.dm
@@ -23,6 +23,9 @@ var/list/ai_status_emotions = list(
"Dorfy" = new /datum/ai_emotion("ai_urist"),
"Facepalm" = new /datum/ai_emotion("ai_facepalm"),
"Friend Computer" = new /datum/ai_emotion("ai_friend"),
+ "Corgi" = new /datum/ai_emotion("ai_corgi"),
+ "Communist" = new /datum/ai_emotion("ai_redoctober"),
+ "Heart" = new /datum/ai_emotion("ai_heart"),
"Tribunal" = new /datum/ai_emotion("ai_tribunal", "serithi"),
"Tribunal Malfunctioning" = new /datum/ai_emotion("ai_tribunal_malf", "serithi")
)
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index c6a49b25f7..30a0743e09 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -473,7 +473,7 @@
return
if(istype(I, /obj/item/weapon/screwdriver))
panelopen = !panelopen
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, I.usesound, 100, 1)
user << text("You [] the unit's maintenance panel.",(panelopen ? "open up" : "close"))
updateUsrDialog()
return
@@ -692,6 +692,7 @@
else if(istype(I,/obj/item/weapon/screwdriver))
panel_open = !panel_open
+ playsound(src, I.usesound, 50, 1)
user << "You [panel_open ? "open" : "close"] the maintenance panel."
updateUsrDialog()
return
diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm
index fd69e4f50e..3441b09cbb 100644
--- a/code/game/machinery/supplybeacon.dm
+++ b/code/game/machinery/supplybeacon.dm
@@ -51,7 +51,7 @@
return
anchored = !anchored
user.visible_message("\The [user] [anchored ? "secures" : "unsecures"] \the [src].")
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
return
return ..()
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 2f53931312..442703a42e 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -126,6 +126,7 @@
if(anchored)
anchored = 0
user << "You unscrew the beacon from the floor."
+ playsound(src, W.usesound, 50, 1)
disconnect_from_network()
return
else
@@ -134,6 +135,7 @@
return
anchored = 1
user << "You screw the beacon to the floor and attach the cable."
+ playsound(src, W.usesound, 50, 1)
return
..()
return
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 9838d80722..27a03eb410 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -138,6 +138,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(original)
original.data["done"] = 1
+ // For some reason level is both used as a list and not a list, and now it needs to be a list.
+ // Because this is a 'all in one' machine, we're gonna just cheat.
+ signal.data["level"] = using_map.contact_levels.Copy()
+
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index 002da7bc53..208b9d51e8 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -38,24 +38,24 @@
if(0)
if(istype(P, /obj/item/weapon/screwdriver))
user << "You unfasten the bolts."
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
construct_op ++
if(1)
if(istype(P, /obj/item/weapon/screwdriver))
user << "You fasten the bolts."
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
construct_op --
if(istype(P, /obj/item/weapon/wrench))
user << "You dislodge the external plating."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src.loc, P.usesound, 75, 1)
construct_op ++
if(2)
if(istype(P, /obj/item/weapon/wrench))
user << "You secure the external plating."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src.loc, P.usesound, 75, 1)
construct_op --
if(istype(P, /obj/item/weapon/wirecutters))
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src.loc, P.usesound, 50, 1)
user << "You remove the cables."
construct_op ++
var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( user.loc )
@@ -72,8 +72,8 @@
user << "You need five coils of wire for this."
if(istype(P, /obj/item/weapon/crowbar))
user << "You begin prying out the circuit board other components..."
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- if(do_after(user,60))
+ playsound(src.loc, P.usesound, 50, 1)
+ if(do_after(user,60 * P.toolspeed))
user << "You finish prying out the components."
// Drop all the component stuff
@@ -168,6 +168,7 @@
dat += "
MULTITOOL BUFFER: [P.buffer] ([P.buffer.id]) \[Link\] \[Flush\]"
else
dat += "
MULTITOOL BUFFER: \[Add Machine\]"
+ P.update_icon()
dat += ""
temp = ""
diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm
index 93d6743b8e..842c2021b7 100644
--- a/code/game/machinery/telecomms/presets.dm
+++ b/code/game/machinery/telecomms/presets.dm
@@ -48,7 +48,7 @@
network = "tcommsat"
produces_heat = 0
autolinkers = list("hub_cent", "c_relay", "s_relay", "m_relay", "r_relay",
- "centcomm", "receiverCent", "broadcasterCent")
+ "centcom", "receiverCent", "broadcasterCent")
//Receivers
@@ -110,7 +110,7 @@
network = "tcommsat"
freq_listening = list(ERT_FREQ, DTH_FREQ)
produces_heat = 0
- autolinkers = list("processorCent", "centcomm")
+ autolinkers = list("processorCent", "centcom")
//Processors
@@ -203,7 +203,7 @@
id = "CentCom Server"
freq_listening = list(ERT_FREQ, DTH_FREQ)
produces_heat = 0
- autolinkers = list("centcomm")
+ autolinkers = list("centcom")
//Broadcasters
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 8797e7af8b..1951ba7c47 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -547,8 +547,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
race = "[H.species.name]"
log.parameters["intelligible"] = 1
else if(isbrain(M))
- var/mob/living/carbon/brain/B = M
- race = "[B.species.name]"
+ race = "Brain"
log.parameters["intelligible"] = 1
else if(M.isMonkey())
race = "Monkey"
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 013001e388..b3c2c23f64 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -19,18 +19,24 @@
/obj/machinery/computer/teleporter/initialize()
..()
- var/obj/machinery/teleport/station/station = locate(/obj/machinery/teleport/station, get_step(src, dir))
+ var/obj/machinery/teleport/station/station
var/obj/machinery/teleport/hub/hub
- if(station)
- hub = locate(/obj/machinery/teleport/hub, get_step(station, dir))
+
+ // Search surrounding turfs for the station, and then search the station's surrounding turfs for the hub.
+ for(var/direction in cardinal)
+ station = locate(/obj/machinery/teleport/station, get_step(src, direction))
+ if(station)
+ for(direction in cardinal)
+ hub = locate(/obj/machinery/teleport/hub, get_step(station, direction))
+ if(hub)
+ break
+ break
if(istype(station))
station.com = hub
- station.set_dir(dir)
if(istype(hub))
hub.com = src
- hub.set_dir(dir)
/obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/card/data/))
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 3d53a053f0..fdab318780 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -183,6 +183,7 @@
else if(istype(W, /obj/item/weapon/screwdriver))
panel_open = !panel_open
user << "You [panel_open ? "open" : "close"] the maintenance panel."
+ playsound(src, W.usesound, 50, 1)
overlays.Cut()
if(panel_open)
overlays += image(icon, "[initial(icon_state)]-panel")
@@ -202,13 +203,13 @@
nanomanager.update_uis(src)
return
else if(istype(W, /obj/item/weapon/wrench))
- playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, W.usesound, 100, 1)
if(anchored)
user.visible_message("[user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
else
user.visible_message("[user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
- if(do_after(user, 20))
+ if(do_after(user, 20 * W.toolspeed))
if(!src) return
user << "You [anchored? "un" : ""]secured \the [src]!"
anchored = !anchored
@@ -693,6 +694,7 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/rum = 5,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/sake = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth = 5,
@@ -712,6 +714,7 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/space_mountain_wind = 5,
/obj/item/weapon/reagent_containers/food/drinks/cans/sodawater = 15,
/obj/item/weapon/reagent_containers/food/drinks/cans/tonic = 15,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 15,
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask = 5,
/obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask = 5,
/obj/item/weapon/reagent_containers/food/drinks/ice = 10,
@@ -769,12 +772,14 @@
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10,
- /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10)
+ /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 6)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1,
- /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1)
+ /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 1)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
/obj/machinery/vending/fitness
@@ -872,7 +877,7 @@
/obj/machinery/vending/wallmed1
name = "NanoMed"
- desc = "Wall-mounted Medical Equipment dispenser."
+ desc = "A wall-mounted version of the NanoMed."
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
icon_deny = "wallmed-deny"
@@ -884,7 +889,7 @@
/obj/machinery/vending/wallmed2
name = "NanoMed"
- desc = "Wall-mounted Medical Equipment dispenser."
+ desc = "A wall-mounted version of the NanoMed, containing only vital first aid equipment."
icon_state = "wallmed"
icon_deny = "wallmed-deny"
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
@@ -1029,7 +1034,7 @@
icon_state = "engivend"
icon_deny = "engivend-deny"
req_access = list(access_engine_equip)
- products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
+ products = list(/obj/item/device/geiger = 4,/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,
/obj/item/weapon/circuitboard/airalarm = 10,/obj/item/weapon/circuitboard/firealarm = 10,/obj/item/weapon/circuitboard/status_display = 2,
/obj/item/weapon/circuitboard/ai_status_display = 2,/obj/item/weapon/circuitboard/newscaster = 2,/obj/item/weapon/circuitboard/holopad = 2,
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index cf96260358..f245682861 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -115,7 +115,7 @@
user << "You can't fit \the [W] inside."
return
- else if(istype(W, /obj/item/clothing))
+ else if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/bedsheet))
if(washing.len < 5)
if(state in list(1, 3))
user.drop_item()
diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm
index ffe30bf3fd..acd680ba57 100644
--- a/code/game/mecha/equipment/tools/medical_tools.dm
+++ b/code/game/mecha/equipment/tools/medical_tools.dm
@@ -7,7 +7,7 @@
energy_drain = 20
range = MELEE
equip_cooldown = 50
- var/mob/living/carbon/occupant = null
+ var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 10
required_type = /obj/mecha/medical
@@ -28,7 +28,7 @@
Exit(atom/movable/O)
return 0
- action(var/mob/living/carbon/target)
+ action(var/mob/living/carbon/human/target)
if(!action_checks(target))
return
if(!istype(target))
@@ -39,8 +39,8 @@
if(occupant)
occupant_message("The sleeper is already occupied")
return
- for(var/mob/living/carbon/slime/M in range(1,target))
- if(M.Victim == target)
+ for(var/mob/living/simple_animal/slime/M in range(1,target))
+ if(M.victim == target)
occupant_message("[target] will not fit into the sleeper because they have a slime latched onto their head.")
return
occupant_message("You start putting [target] into [src].")
@@ -56,6 +56,7 @@
target.forceMove(src)
occupant = target
target.reset_view(src)
+ occupant.Stasis(3)
/*
if(target.client)
target.client.perspective = EYE_PERSPECTIVE
@@ -80,6 +81,7 @@
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
*/
+ occupant.Stasis(0)
occupant = null
pr_mech_sleeper.stop()
set_ready_state(1)
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 41f1ba44ef..a1cbba3102 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -208,7 +208,7 @@
for(var/a = 1 to 5)
spawn(0)
- var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(chassis))
+ var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(chassis))
var/turf/my_target
if(a == 1)
my_target = T
@@ -973,11 +973,7 @@
process(var/obj/item/mecha_parts/mecha_equipment/generator/nuclear/EG)
if(..())
- for(var/mob/living/carbon/M in view(EG.chassis))
- if(istype(M,/mob/living/carbon/human))
- M.apply_effect((EG.rad_per_cycle*3),IRRADIATE,0)
- else
- M.apply_effect(EG.rad_per_cycle, IRRADIATE)
+ radiation_repository.radiate(EG, (EG.rad_per_cycle * 3))
return 1
@@ -1158,8 +1154,8 @@
usr << "Kinda hard to climb in while handcuffed don't you think?"
return
- for(var/mob/living/carbon/slime/M in range(1,usr))
- if(M.Victim == usr)
+ for(var/mob/living/simple_animal/slime/M in range(1,usr))
+ if(M.victim == usr)
usr << "You're too busy getting your life sucked out of you."
return
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 09ff0075db..dd3940d421 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -140,18 +140,14 @@
cell = null
internal_tank = null
- qdel(pr_int_temp_processor)
- qdel(pr_inertial_movement)
- qdel(pr_give_air)
- qdel(pr_internal_damage)
- qdel(spark_system)
- pr_int_temp_processor = null
- pr_give_air = null
- pr_internal_damage = null
- spark_system = null
+ qdel_null(pr_int_temp_processor)
+ qdel_null(pr_inertial_movement)
+ qdel_null(pr_give_air)
+ qdel_null(pr_internal_damage)
+ qdel_null(spark_system)
mechas_list -= src //global mech list
- ..()
+ . = ..()
////////////////////////
////// Helpers /////////
@@ -398,14 +394,14 @@
/obj/mecha/proc/mechstep(direction)
var/result = step(src,direction)
if(result)
- playsound(src,'sound/mecha/mechstep.ogg',40,1)
+ playsound(src,"mechstep",40,1)
return result
/obj/mecha/proc/mechsteprand()
var/result = step_rand(src)
if(result)
- playsound(src,'sound/mecha/mechstep.ogg',40,1)
+ playsound(src,"mechstep",40,1)
return result
/obj/mecha/Bump(var/atom/obstacle)
@@ -1019,8 +1015,8 @@
usr << "Access denied"
src.log_append_to_last("Permission denied.")
return
- for(var/mob/living/carbon/slime/M in range(1,usr))
- if(M.Victim == usr)
+ for(var/mob/living/simple_animal/slime/M in range(1,usr))
+ if(M.victim == usr)
usr << "You're too busy getting your life sucked out of you."
return
// usr << "You start climbing into [src.name]"
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index f456a95d73..a91e022f9b 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -1,4 +1,6 @@
-/obj
+
+
+/atom/movable
var/can_buckle = 0
var/buckle_movable = 0
var/buckle_dir = 0
@@ -6,33 +8,34 @@
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
var/mob/living/buckled_mob = null
-/obj/attack_hand(mob/living/user)
+
+/atom/movable/attack_hand(mob/living/user)
. = ..()
if(can_buckle && buckled_mob)
user_unbuckle_mob(user)
+/obj/proc/attack_alien(mob/user as mob) //For calling in the event of Xenomorph or other alien checks.
+ return
+
/obj/attack_robot(mob/living/user)
if(Adjacent(user) && buckled_mob) //Checks if what we're touching is adjacent to us and has someone buckled to it. This should prevent interacting with anti-robot manual valves among other things.
return attack_hand(user) //Process as if we're a normal person touching the object.
return ..() //Otherwise, treat this as an AI click like usual.
-/obj/MouseDrop_T(mob/living/M, mob/living/user)
+/atom/movable/MouseDrop_T(mob/living/M, mob/living/user)
. = ..()
if(can_buckle && istype(M))
user_buckle_mob(M, user)
-//Cleanup
-/obj/Del()
- unbuckle_mob()
- return ..()
-
-/obj/Destroy()
+/atom/movable/Destroy()
unbuckle_mob()
return ..()
-/obj/proc/buckle_mob(mob/living/M)
- if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.pinned.len || (buckle_require_restraints && !M.restrained()))
+/atom/movable/proc/buckle_mob(mob/living/M, forced = FALSE, check_loc = TRUE)
+ if((!can_buckle && !forced) || !istype(M) || M.buckled || M.pinned.len || (buckle_require_restraints && !M.restrained()))
+ return 0
+ if(check_loc && M.loc != loc)
return 0
if(buckled_mob) //Handles trying to buckle yourself to the chair when someone is on it
M << "\The [src] already has someone buckled to it."
@@ -42,34 +45,33 @@
M.facing_dir = null
M.set_dir(buckle_dir ? buckle_dir : dir)
M.update_canmove()
+ M.update_floating( M.Check_Dense_Object() )
buckled_mob = M
post_buckle_mob(M)
return 1
-/obj/proc/unbuckle_mob()
+/atom/movable/proc/unbuckle_mob()
if(buckled_mob && buckled_mob.buckled == src)
. = buckled_mob
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
+ buckled_mob.update_floating( buckled_mob.Check_Dense_Object() )
buckled_mob = null
post_buckle_mob(.)
-/obj/proc/post_buckle_mob(mob/living/M)
+/atom/movable/proc/post_buckle_mob(mob/living/M)
return
-/obj/proc/user_buckle_mob(mob/living/M, mob/user)
+/atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, var/forced = FALSE, var/silent = FALSE)
if(!ticker)
user << "You can't buckle anyone in before the game starts."
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
return
if(M == buckled_mob)
return
- if(istype(M, /mob/living/carbon/slime))
- user << "The [M] is too squishy to buckle in."
- return
add_fingerprint(user)
unbuckle_mob()
@@ -78,20 +80,21 @@
if(M.loc != src.loc)
step_towards(M, src)
- . = buckle_mob(M)
+ . = buckle_mob(M, forced)
if(.)
- if(M == user)
- M.visible_message(\
- "[M.name] buckles themselves to [src].",\
- "You buckle yourself to [src].",\
- "You hear metal clanking.")
- else
- M.visible_message(\
- "[M.name] is buckled to [src] by [user.name]!",\
- "You are buckled to [src] by [user.name]!",\
- "You hear metal clanking.")
+ if(!silent)
+ if(M == user)
+ M.visible_message(\
+ "[M.name] buckles themselves to [src].",\
+ "You buckle yourself to [src].",\
+ "You hear metal clanking.")
+ else
+ M.visible_message(\
+ "[M.name] is buckled to [src] by [user.name]!",\
+ "You are buckled to [src] by [user.name]!",\
+ "You hear metal clanking.")
-/obj/proc/user_unbuckle_mob(mob/user)
+/atom/movable/proc/user_unbuckle_mob(mob/user)
var/mob/living/M = unbuckle_mob()
if(M)
if(M != user)
@@ -107,3 +110,19 @@
add_fingerprint(user)
return M
+/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
+ if(buckled_mob)
+// if(!buckled_mob.Move(newloc, direct))
+ if(!buckled_mob.forceMove(newloc, direct))
+ loc = buckled_mob.loc
+ last_move = buckled_mob.last_move
+ buckled_mob.inertia_dir = last_move
+ return FALSE
+ else
+ buckled_mob.set_dir(dir)
+ return TRUE
+
+/atom/movable/Move(atom/newloc, direct = 0)
+ . = ..()
+ if(. && buckled_mob && !handle_buckled_mob_movement(newloc, direct)) //movement failed due to buckled mob(s)
+ . = 0
diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm
new file mode 100644
index 0000000000..3d9713cd29
--- /dev/null
+++ b/code/game/objects/effects/alien/aliens.dm
@@ -0,0 +1,443 @@
+/* Alien Effects!
+ * Contains:
+ * effect/alien
+ * Resin
+ * Weeds
+ * Acid
+ * Egg
+ */
+
+/*
+ * effect/alien
+ */
+/obj/effect/alien
+ name = "alien thing"
+ desc = "theres something alien about this"
+ icon = 'icons/mob/alien.dmi'
+
+/*
+ * Resin
+ */
+/obj/effect/alien/resin
+ name = "resin"
+ desc = "Looks like some kind of slimy growth."
+ icon_state = "resin"
+
+ density = 1
+ opacity = 1
+ anchored = 1
+ var/health = 200
+ //var/mob/living/affecting = null
+
+/obj/effect/alien/resin/wall
+ name = "resin wall"
+ desc = "Purple slime solidified into a wall."
+ icon_state = "resinwall" //same as resin, but consistency ho!
+
+/obj/effect/alien/resin/membrane
+ name = "resin membrane"
+ desc = "Purple slime just thin enough to let light pass through."
+ icon_state = "resinmembrane"
+ opacity = 0
+ health = 120
+
+/obj/effect/alien/resin/New()
+ ..()
+ var/turf/T = get_turf(src)
+ T.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
+
+/obj/effect/alien/resin/Destroy()
+ var/turf/T = get_turf(src)
+ T.thermal_conductivity = initial(T.thermal_conductivity)
+ ..()
+
+/obj/effect/alien/resin/proc/healthcheck()
+ if(health <=0)
+ density = 0
+ qdel(src)
+ return
+
+/obj/effect/alien/resin/bullet_act(var/obj/item/projectile/Proj)
+ health -= Proj.damage
+ ..()
+ healthcheck()
+ return
+
+/obj/effect/alien/resin/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ health-=50
+ if(2.0)
+ health-=50
+ if(3.0)
+ if (prob(50))
+ health-=50
+ else
+ health-=25
+ healthcheck()
+ return
+
+/obj/effect/alien/resin/hitby(AM as mob|obj)
+ ..()
+ for(var/mob/O in viewers(src, null))
+ O.show_message("[src] was hit by [AM].", 1)
+ var/tforce = 0
+ if(ismob(AM))
+ tforce = 10
+ else
+ tforce = AM:throwforce
+ playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ health = max(0, health - tforce)
+ healthcheck()
+ ..()
+ return
+
+/obj/effect/alien/resin/attack_hand()
+ usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if (HULK in usr.mutations)
+ usr << "You easily destroy the [name]."
+ for(var/mob/O in oviewers(src))
+ O.show_message("[usr] destroys the [name]!", 1)
+ health = 0
+ else
+
+ // Aliens can get straight through these.
+ if(istype(usr,/mob/living/carbon))
+ var/mob/living/carbon/M = usr
+ if(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
+ for(var/mob/O in oviewers(src))
+ O.show_message("[usr] strokes the [name] and it melts away!", 1)
+ health = 0
+ healthcheck()
+ return
+
+ usr << "You claw at the [name]."
+ for(var/mob/O in oviewers(src))
+ O.show_message("[usr] claws at the [name]!", 1)
+ health -= rand(5,10)
+ healthcheck()
+ return
+
+/obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob)
+
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ var/aforce = W.force
+ health = max(0, health - aforce)
+ playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ healthcheck()
+ ..()
+ return
+
+/obj/effect/alien/resin/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ if(air_group) return 0
+ if(istype(mover) && mover.checkpass(PASSGLASS))
+ return !opacity
+ return !density
+
+
+/*
+ * Weeds
+ */
+#define NODERANGE 3
+
+/obj/effect/alien/weeds
+ name = "weeds"
+ desc = "Weird purple weeds."
+ icon_state = "weeds"
+
+ anchored = 1
+ density = 0
+ layer = 2
+ var/health = 15
+ var/obj/effect/alien/weeds/node/linked_node = null
+
+/obj/effect/alien/weeds/node
+ icon_state = "weednode"
+ name = "purple sac"
+ desc = "Weird purple octopus-like thing."
+ layer = 3
+ light_range = NODERANGE
+ var/node_range = NODERANGE
+
+/obj/effect/alien/weeds/node/New()
+ ..(src.loc, src)
+
+
+/obj/effect/alien/weeds/New(pos, node)
+ ..()
+ if(istype(loc, /turf/space))
+ qdel(src)
+ return
+ linked_node = node
+ if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2")
+ spawn(rand(150, 200))
+ if(src)
+ Life()
+ return
+
+/obj/effect/alien/weeds/proc/Life()
+ set background = 1
+ var/turf/U = get_turf(src)
+/*
+ if (locate(/obj/movable, U))
+ U = locate(/obj/movable, U)
+ if(U.density == 1)
+ qdel(src)
+ return
+Alien plants should do something if theres a lot of poison
+ if(U.poison> 200000)
+ health -= round(U.poison/200000)
+ update()
+ return
+*/
+ if (istype(U, /turf/space))
+ qdel(src)
+ return
+
+ if(!linked_node || (get_dist(linked_node, src) > linked_node.node_range) )
+ return
+
+ direction_loop:
+ for(var/dirn in cardinal)
+ var/turf/T = get_step(src, dirn)
+
+ if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space))
+ continue
+
+ // if (locate(/obj/movable, T)) // don't propogate into movables
+ // continue
+
+ for(var/obj/O in T)
+ if(O.density)
+ continue direction_loop
+
+ new /obj/effect/alien/weeds(T, linked_node)
+
+
+/obj/effect/alien/weeds/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ if(2.0)
+ if (prob(50))
+ qdel(src)
+ if(3.0)
+ if (prob(5))
+ qdel(src)
+ return
+
+/obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(W.attack_verb.len)
+ visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]")
+ else
+ visible_message("\The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]")
+
+ var/damage = W.force / 4.0
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+
+ if(WT.remove_fuel(0, user))
+ damage = 15
+ playsound(loc, 'sound/items/Welder.ogg', 100, 1)
+
+ health -= damage
+ healthcheck()
+
+/obj/effect/alien/weeds/proc/healthcheck()
+ if(health <= 0)
+ qdel(src)
+
+
+/obj/effect/alien/weeds/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature > 300 + T0C)
+ health -= 5
+ healthcheck()
+
+#undef NODERANGE
+
+
+/*
+ * Acid
+ */
+/obj/effect/alien/acid
+ name = "acid"
+ desc = "Burbling corrossive stuff. I wouldn't want to touch it."
+ icon_state = "acid"
+
+ density = 0
+ opacity = 0
+ anchored = 1
+
+ var/atom/target
+ var/ticks = 0
+ var/target_strength = 0
+
+/obj/effect/alien/acid/New(loc, target)
+ ..(loc)
+ src.target = target
+
+ if(isturf(target)) // Turf take twice as long to take down.
+ target_strength = 8
+ else
+ target_strength = 4
+ tick()
+
+/obj/effect/alien/acid/proc/tick()
+ if(!target)
+ qdel(src)
+
+ ticks += 1
+
+ if(ticks >= target_strength)
+
+ for(var/mob/O in hearers(src, null))
+ O.show_message("[src.target] collapses under its own weight into a puddle of goop and undigested debris!", 1)
+
+ if(istype(target, /turf/simulated/wall)) // I hate turf code.
+ var/turf/simulated/wall/W = target
+ W.dismantle_wall(1)
+ else
+ qdel(target)
+ qdel(src)
+ return
+
+ switch(target_strength - ticks)
+ if(6)
+ visible_message("[src.target] is holding up against the acid!")
+ if(4)
+ visible_message("[src.target]\s structure is being melted by the acid!")
+ if(2)
+ visible_message("[src.target] is struggling to withstand the acid!")
+ if(0 to 1)
+ visible_message("[src.target] begins to crumble under the acid!")
+ spawn(rand(150, 200)) tick()
+
+/*
+ * Egg
+ */
+/var/const //for the status var
+ BURST = 0
+ BURSTING = 1
+ GROWING = 2
+ GROWN = 3
+
+ MIN_GROWTH_TIME = 1800 //time it takes to grow a hugger
+ MAX_GROWTH_TIME = 3000
+
+/obj/effect/alien/egg
+ desc = "It looks like a weird egg"
+ name = "egg"
+// icon_state = "egg_growing" // So the egg looks 'grown', even though it's not.
+ icon_state = "egg"
+ density = 0
+ anchored = 1
+
+ var/health = 100
+ var/status = BURST //can be GROWING, GROWN or BURST; all mutually exclusive
+ flags = PROXMOVE
+
+/obj/effect/alien/egg/New()
+/*
+ if(config.aliens_allowed)
+ ..()
+ spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME))
+ Grow()
+ else
+ qdel(src)
+*/
+/obj/effect/alien/egg/attack_hand(user as mob)
+
+ var/mob/living/carbon/M = user
+ if(!istype(M) || !(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs))
+ return attack_hand(user)
+
+ switch(status)
+ if(BURST)
+ user << "You clear the hatched egg."
+ qdel(src)
+ return
+/* if(GROWING)
+ user << "The child is not developed yet."
+ return
+ if(GROWN)
+ user << "You retrieve the child."
+ Burst(0)
+ return
+
+/obj/effect/alien/egg/proc/GetFacehugger() // Commented out for future edit.
+ return locate(/obj/item/clothing/mask/facehugger) in contents
+
+/obj/effect/alien/egg/proc/Grow()
+ icon_state = "egg"
+// status = GROWN
+ status = BURST
+// new /obj/item/clothing/mask/facehugger(src)
+ return
+*/
+/obj/effect/alien/egg/proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining
+ if(status == GROWN || status == GROWING)
+// var/obj/item/clothing/mask/facehugger/child = GetFacehugger()
+ icon_state = "egg_hatched"
+/* flick("egg_opening", src)
+ status = BURSTING
+ spawn(15)
+ status = BURST
+ child.loc = get_turf(src)
+
+ if(kill && istype(child))
+ child.Die()
+ else
+ for(var/mob/M in range(1,src))
+ if(CanHug(M))
+ child.Attach(M)
+ break
+*/
+/obj/effect/alien/egg/bullet_act(var/obj/item/projectile/Proj)
+ health -= Proj.damage
+ ..()
+ healthcheck()
+ return
+
+
+/obj/effect/alien/egg/attackby(var/obj/item/weapon/W, var/mob/user)
+ if(health <= 0)
+ return
+ if(W.attack_verb.len)
+ src.visible_message("\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]")
+ else
+ src.visible_message("\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]")
+ var/damage = W.force / 4.0
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+
+ if(WT.remove_fuel(0, user))
+ damage = 15
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+
+ src.health -= damage
+ src.healthcheck()
+
+
+/obj/effect/alien/egg/proc/healthcheck()
+ if(health <= 0)
+ Burst()
+
+/obj/effect/alien/egg/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature > 500 + T0C)
+ health -= 5
+ healthcheck()
+/*
+/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj)
+ if(status == GROWN)
+ if(!CanHug(AM))
+ return
+
+ var/mob/living/carbon/C = AM
+ if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST)
+ return
+
+ Burst(0)
+*/
\ No newline at end of file
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index 3f077116e9..be7e759a63 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -12,6 +12,10 @@
create_reagents(500)
return
+/obj/effect/effect/smoke/chem/Destroy()
+ walk(src, 0) // Because we might have called walk_to, we must stop the walk loop or BYOND keeps an internal reference to us forever.
+ return ..()
+
/datum/effect/effect/system/smoke_spread/chem
smoke_type = /obj/effect/effect/smoke/chem
var/obj/chemholder
@@ -152,7 +156,7 @@
if(passed_smoke)
smoke = passed_smoke
else
- smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location)
+ smoke = new /obj/effect/effect/smoke/chem(location)
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
@@ -166,10 +170,10 @@
sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner
smoke.set_opacity(0) // lighting and view range updates
fadeOut(smoke)
- qdel(src)
+ qdel(smoke)
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1)
- var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location)
+ var/obj/effect/effect/smoke/chem/spores = new /obj/effect/effect/smoke/chem(location)
spores.name = "cloud of [seed.seed_name] [seed.seed_noun]"
..(T, I, dist, spores)
diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm
index b29b2440e6..2c28dd7ecb 100644
--- a/code/game/objects/effects/chem/foam.dm
+++ b/code/game/objects/effects/chem/foam.dm
@@ -108,7 +108,7 @@
F.amount += amount
return
- F = PoolOrNew(/obj/effect/effect/foam, list(location, metal))
+ F = new /obj/effect/effect/foam(location, metal)
F.amount = amount
if(!metal) // don't carry other chemicals if a metal foam
@@ -139,7 +139,7 @@
/obj/structure/foamedmetal/Destroy()
density = 0
update_nearby_tiles(1)
- ..()
+ return ..()
/obj/structure/foamedmetal/proc/updateicon()
if(metal == 1)
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index fc764efd02..3cdca23fde 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -222,7 +222,7 @@ var/global/list/image/splatter_cache=list()
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
sleep(3)
if (i > 0)
- var/obj/effect/decal/cleanable/blood/b = PoolOrNew(/obj/effect/decal/cleanable/blood/splatter, src.loc)
+ var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
b.basecolor = src.basecolor
b.update_icon()
diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm
index cd3618c936..0d00d32830 100644
--- a/code/game/objects/effects/decals/contraband.dm
+++ b/code/game/objects/effects/decals/contraband.dm
@@ -122,7 +122,7 @@
/obj/structure/sign/poster/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/wirecutters))
- playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src.loc, W.usesound, 100, 1)
if(ruined)
user << "You remove the remnants of the poster."
qdel(src)
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 485ea6987b..a3b3ab81cb 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -13,11 +13,6 @@ would spawn and follow the beaker, even if it is carried or thrown.
unacidable = 1//So effect are not targeted by alien acid.
pass_flags = PASSTABLE | PASSGRILLE
-/obj/effect/Destroy()
- if(reagents)
- reagents.delete()
- return ..()
-
/datum/effect/effect/system
var/number = 3
var/cardinals = 0
@@ -75,7 +70,7 @@ steam.start() -- spawns the effect
spawn(0)
if(holder)
src.location = get_turf(holder)
- var/obj/effect/effect/steam/steam = PoolOrNew(/obj/effect/effect/steam, src.location)
+ var/obj/effect/effect/steam/steam = new /obj/effect/effect/steam(src.location)
var/direction
if(src.cardinals)
direction = pick(cardinal)
@@ -146,7 +141,7 @@ steam.start() -- spawns the effect
spawn(0)
if(holder)
src.location = get_turf(holder)
- var/obj/effect/effect/sparks/sparks = PoolOrNew(/obj/effect/effect/sparks, src.location)
+ var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location)
src.total_sparks++
var/direction
if(src.cardinals)
@@ -184,8 +179,10 @@ steam.start() -- spawns the effect
/obj/effect/effect/smoke/New()
..()
- spawn (time_to_live)
- qdel(src)
+ if(time_to_live)
+ spawn (time_to_live)
+ if(!QDELETED(src))
+ qdel(src)
/obj/effect/effect/smoke/Crossed(mob/living/carbon/M as mob )
..()
@@ -283,7 +280,7 @@ steam.start() -- spawns the effect
spawn(0)
if(holder)
src.location = get_turf(holder)
- var/obj/effect/effect/smoke/smoke = PoolOrNew(smoke_type, src.location)
+ var/obj/effect/effect/smoke/smoke = new smoke_type(src.location)
src.total_smoke++
smoke.color = I
var/direction = src.direction
@@ -334,7 +331,7 @@ steam.start() -- spawns the effect
var/turf/T = get_turf(src.holder)
if(T != src.oldposition)
if(isturf(T))
- var/obj/effect/effect/ion_trails/I = PoolOrNew(/obj/effect/effect/ion_trails, src.oldposition)
+ var/obj/effect/effect/ion_trails/I = new /obj/effect/effect/ion_trails(src.oldposition)
src.oldposition = T
I.set_dir(src.holder.dir)
flick("ion_fade", I)
@@ -380,7 +377,7 @@ steam.start() -- spawns the effect
src.processing = 0
spawn(0)
if(src.number < 3)
- var/obj/effect/effect/steam/I = PoolOrNew(/obj/effect/effect/steam, src.oldposition)
+ var/obj/effect/effect/steam/I = new /obj/effect/effect/steam(src.oldposition)
src.number++
src.oldposition = get_turf(holder)
I.set_dir(src.holder.dir)
@@ -420,7 +417,7 @@ steam.start() -- spawns the effect
start()
if (amount <= 2)
- var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(2, 1, location)
s.start()
diff --git a/code/game/objects/effects/gibs.dm b/code/game/objects/effects/gibs.dm
index 9d630113bb..16db09edb6 100644
--- a/code/game/objects/effects/gibs.dm
+++ b/code/game/objects/effects/gibs.dm
@@ -24,7 +24,7 @@
var/obj/effect/decal/cleanable/blood/gibs/gib = null
if(sparks)
- var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo
s.start()
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index e80b7d8f10..e031b09f5e 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -21,9 +21,9 @@
newplayer_start += loc
delete_me = 1
return
- if("JoinLate")
- latejoin += loc
- delete_me = 1
+ if("JoinLate") // Bit difference, since we need the spawn point to move.
+ latejoin += src
+ // delete_me = 1
return
if("JoinLateGateway")
latejoin_gateway += loc
@@ -87,9 +87,11 @@
if(delete_me)
qdel(src)
-/obj/effect/landmark/Destroy()
- landmarks_list -= src
- return ..()
+/obj/effect/landmark/Destroy(var/force = FALSE)
+ if(delete_me || force)
+ landmarks_list -= src
+ return ..()
+ return QDEL_HINT_LETMELIVE
/obj/effect/landmark/start
name = "start"
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 27e6d7c74a..52f920775e 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -26,7 +26,7 @@
call(src,triggerproc)(M)
/obj/effect/mine/proc/triggerrad(obj)
- var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src)
s.start()
obj:radiation += 50
@@ -39,7 +39,7 @@
if(ismob(obj))
var/mob/M = obj
M.Stun(30)
- var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src)
s.start()
spawn(0)
@@ -67,7 +67,7 @@
qdel(src)
/obj/effect/mine/proc/triggerkick(obj)
- var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src)
s.start()
qdel(obj:client)
diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm
index fb4716043f..7f2f509d01 100644
--- a/code/game/objects/effects/spawners/bombspawner.dm
+++ b/code/game/objects/effects/spawners/bombspawner.dm
@@ -111,15 +111,15 @@
set name = "Instant TTV"
if(!check_rights(R_SPAWN)) return
-
+
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
-
+
var/p = input("Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt)) as num|null
if(p == null) return
-
+
var/o = input("Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt)) as num|null
if(o == null) return
-
+
var/c = input("Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt)) as num|null
if(c == null) return
@@ -129,13 +129,13 @@
name = "TTV bomb"
icon = 'icons/mob/screen1.dmi'
icon_state = "x"
-
+
var/assembly_type = /obj/item/device/assembly/signaler
-
+
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
- var/phoron_amt = 10.96
- var/oxygen_amt = 16.44
- var/carbon_amt = 0.0
+ var/phoron_amt = 12
+ var/oxygen_amt = 18
+ var/carbon_amt = 0
/obj/effect/spawner/newbomb/timer
name = "TTV bomb - timer"
@@ -144,8 +144,8 @@
/obj/effect/spawner/newbomb/timer/syndicate
name = "TTV bomb - merc"
//High yield bombs. Yes, it is possible to make these with toxins
- phoron_amt = 15.66
- oxygen_amt = 24.66
+ phoron_amt = 18.5
+ oxygen_amt = 28.5
/obj/effect/spawner/newbomb/proximity
name = "TTV bomb - proximity"
@@ -170,15 +170,20 @@
PT.master = V
OT.master = V
- PT.air_contents.temperature = PHORON_FLASHPOINT
+ PT.valve_welded = 1
PT.air_contents.gas["phoron"] = phoron_amt
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
+ PT.air_contents.total_moles = phoron_amt + carbon_amt
+ PT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
PT.air_contents.update_values()
- OT.air_contents.temperature = PHORON_FLASHPOINT
+ OT.valve_welded = 1
OT.air_contents.gas["oxygen"] = oxygen_amt
+ OT.air_contents.total_moles = oxygen_amt
+ OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
OT.air_contents.update_values()
+
var/obj/item/device/assembly/S = new assembly_type(V)
@@ -190,3 +195,62 @@
V.update_icon()
qdel(src)
+
+
+
+///////////////////////
+//One Tank Bombs, WOOOOOOO! -Luke
+///////////////////////
+
+/obj/effect/spawner/onetankbomb
+ name = "Single-tank bomb"
+ icon = 'icons/mob/screen1.dmi'
+ icon_state = "x"
+
+// var/assembly_type = /obj/item/device/assembly/signaler
+
+ //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
+ var/phoron_amt = 0
+ var/oxygen_amt = 0
+
+/obj/effect/spawner/onetankbomb/New(newloc) //just needs an assembly.
+ ..(newloc)
+
+ var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb, /obj/item/weapon/tank/oxygen/onetankbomb)
+ new type(src.loc)
+
+ qdel(src)
+
+/obj/effect/spawner/onetankbomb/full
+ name = "Single-tank bomb"
+ icon = 'icons/mob/screen1.dmi'
+ icon_state = "x"
+
+// var/assembly_type = /obj/item/device/assembly/signaler
+
+ //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
+/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
+ ..(newloc)
+
+ var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
+ new type(src.loc)
+
+ qdel(src)
+
+/obj/effect/spawner/onetankbomb/frag
+ name = "Single-tank bomb"
+ icon = 'icons/mob/screen1.dmi'
+ icon_state = "x"
+
+// var/assembly_type = /obj/item/device/assembly/signaler
+
+ //Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
+/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
+ ..(newloc)
+
+ var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
+ new type(src.loc)
+
+ qdel(src)
+
+
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 1077d757ae..e4df02202f 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -35,7 +35,7 @@
if(WT.remove_fuel(0, user))
damage = 15
- playsound(loc, 'sound/items/Welder.ogg', 100, 1)
+ playsound(src, W.usesound, 100, 1)
health -= damage
healthcheck()
@@ -94,7 +94,7 @@
var/obj/item/organ/external/O = loc
O.implants -= src
- ..()
+ return ..()
/obj/effect/spider/eggcluster/process()
amount_grown += rand(0,2)
@@ -105,7 +105,7 @@
O = loc
for(var/i=0, i[src] dies!")
- PoolOrNew(/obj/effect/decal/cleanable/spiderling_remains, src.loc)
+ new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
qdel(src)
/obj/effect/spider/spiderling/healthcheck()
@@ -217,7 +219,7 @@
break
if(amount_grown >= 100)
- var/spawn_type = pick(typesof(/mob/living/simple_animal/hostile/giant_spider))
+ var/spawn_type = pick(grow_as)
new spawn_type(src.loc, src)
qdel(src)
else if(isorgan(loc))
diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm
index 3b1a3b54f5..3d97946bd4 100644
--- a/code/game/objects/empulse.dm
+++ b/code/game/objects/empulse.dm
@@ -15,7 +15,7 @@ proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_rang
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
if(first_range > 1)
- var/obj/effect/overlay/pulse = PoolOrNew(/obj/effect/overlay, epicenter)
+ var/obj/effect/overlay/pulse = new /obj/effect/overlay(epicenter)
pulse.icon = 'icons/effects/effects.dmi'
pulse.icon_state = "emppulse"
pulse.name = "emp pulse"
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index b081530e10..0bf146f037 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,23 +1,26 @@
//TODO: Flash range does nothing currently
-proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN)
+proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
+ var/multi_z_scalar = config.multi_z_explosion_scalar
src = null //so we don't abort once src is deleted
spawn(0)
- if(config.use_recursive_explosions)
- var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
- explosion_rec(epicenter, power)
- return
-
var/start = world.timeofday
epicenter = get_turf(epicenter)
if(!epicenter) return
// Handles recursive propagation of explosions.
- if(devastation_range > 2 || heavy_impact_range > 2)
- if(HasAbove(epicenter.z) && z_transfer & UP)
- explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP)
- if(HasBelow(epicenter.z) && z_transfer & DOWN)
- explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN)
+ if(z_transfer && multi_z_scalar)
+ var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) )
+ var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) )
+ var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) )
+ var/adj_flash = max(0, (multi_z_scalar * flash_range) - (shaped ? 2 : 0) )
+
+
+ if(adj_dev > 0 || adj_heavy > 0)
+ if(HasAbove(epicenter.z) && z_transfer & UP)
+ explosion(GetAbove(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, UP, shaped)
+ if(HasBelow(epicenter.z) && z_transfer & DOWN)
+ explosion(GetBelow(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, DOWN, shaped)
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
@@ -30,31 +33,30 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
far_dist += devastation_range * 20
var/frequency = get_rand_frequency()
for(var/mob/M in player_list)
- // Double check for client
- if(M && M.client)
+ if(M.z == epicenter.z)
var/turf/M_turf = get_turf(M)
- if(M_turf && M_turf.z == epicenter.z)
- var/dist = get_dist(M_turf, epicenter)
- // If inside the blast radius + world.view - 2
- if(dist <= round(max_range + world.view - 2, 1))
- M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
-
- //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
-
- else if(dist <= far_dist)
- var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
- far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
- M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
+ var/dist = get_dist(M_turf, epicenter)
+ // If inside the blast radius + world.view - 2
+ if(dist <= round(max_range + world.view - 2, 1))
+ M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
+ else if(dist <= far_dist)
+ var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
+ far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
+ M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
var/close = range(world.view+round(devastation_range,1), epicenter)
// to all distanced mobs play a different sound
- for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close))
- // check if the mob can hear
- if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space))
- M << 'sound/effects/explosionfar.ogg'
+ for(var/mob/M in world)
+ if(M.z == epicenter.z)
+ if(!(M in close))
+ // check if the mob can hear
+ if(M.ear_deaf <= 0 || !M.ear_deaf)
+ if(!istype(M.loc,/turf/space))
+ M << 'sound/effects/explosionfar.ogg'
+
if(adminlog)
- message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)")
- log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
+ message_admins("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)")
+ log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
@@ -70,41 +72,42 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
var/x0 = epicenter.x
var/y0 = epicenter.y
var/z0 = epicenter.z
+ if(config.use_recursive_explosions)
+ var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
+ explosion_rec(epicenter, power, shaped)
+ else
+ for(var/turf/T in trange(max_range, epicenter))
+ var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
- for(var/turf/T in trange(max_range, epicenter))
- var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
+ if(dist < devastation_range) dist = 1
+ else if(dist < heavy_impact_range) dist = 2
+ else if(dist < light_impact_range) dist = 3
+ else continue
- if(dist < devastation_range) dist = 1
- else if(dist < heavy_impact_range) dist = 2
- else if(dist < light_impact_range) dist = 3
- else continue
-
- T.ex_act(dist)
- if(T)
+ if(!T)
+ T = locate(x0,y0,z0)
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
var/atom/movable/AM = atom_movable
if(AM && AM.simulated) AM.ex_act(dist)
+ T.ex_act(dist)
+
var/took = (world.timeofday-start)/10
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
- if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds."
+ if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds."
//Machines which report explosions.
for(var/i,i<=doppler_arrays.len,i++)
var/obj/machinery/doppler_array/Array = doppler_arrays[i]
if(Array)
Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took)
-
sleep(8)
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
makepowernets()
defer_powernet_rebuild = 0
-
return 1
-
-
proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in range(range, epicenter))
tile.ex_act(2)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 4316da3c49..6b4a09c6a5 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -10,6 +10,7 @@
var/burn_point = null
var/burning = null
var/hitsound = null
+ var/usesound = null // Like hitsound, but for when used properly and not to kill someone.
var/storage_cost = null
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
var/no_attack_log = 0 //If it's an item we don't want to log attack_logs with, set this to 1
@@ -50,7 +51,7 @@
var/zoomdevicename = null //name used for message when binoculars/scope is used
var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars.
- var/embed_chance = -1 //-1 makes it calculate embed chance, 0 won't embed, and 100 will always embed
+ var/embed_chance = -1 //0 won't embed, and 100 will always embed
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
@@ -78,13 +79,15 @@
// Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called.
var/list/sprite_sheets_obj = list()
+ var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast.
+
/obj/item/New()
- if(embed_chance == -1)
- if(sharp)
- embed_chance = force/w_class
- else
- embed_chance = force/(w_class*3)
..()
+ if(embed_chance < 0)
+ if(sharp)
+ embed_chance = max(5, round(force/w_class))
+ else
+ embed_chance = max(5, round(force/(w_class*3)))
/obj/item/equipped()
..()
@@ -340,12 +343,12 @@ var/list/global/slot_flags_enumeration = list(
return 0
if( !(istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed)) )
return 0
+ if(slot_legcuffed) //Going to put this check above the handcuff check because the survival of the universe depends on it.
+ if(!istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Putting it here might actually do nothing.
+ return 0
if(slot_handcuffed)
- if(!istype(src, /obj/item/weapon/handcuffs))
- return 0
- if(slot_legcuffed)
- if(!istype(src, /obj/item/weapon/legcuffs))
- return 0
+ if(!istype(src, /obj/item/weapon/handcuffs) || istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Legcuffs are a child of handcuffs, but we don't want to use legcuffs as handcuffs...
+ return 0 //In theory, this would never happen, but let's just do the legcuff check anyways.
if(slot_in_backpack) //used entirely for equipping spawned mobs or at round start
var/allow = 0
if(H.back && istype(H.back, /obj/item/weapon/storage/backpack))
@@ -446,7 +449,7 @@ var/list/global/slot_flags_enumeration = list(
if(!hit_zone)
U.do_attack_animation(M)
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
- visible_message("\red [U] attempts to stab [M] in the eyes, but misses!")
+ visible_message("[U] attempts to stab [M] in the eyes, but misses!")
return
user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index 1450fa94ce..16e27006b4 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -77,14 +77,20 @@
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
..()
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
- if(!ishuman(usr)) return
+ if(!ishuman(usr)) return 0
if(opened) return 0
if(contents.len) return 0
visible_message("[usr] folds up the [src.name]")
- new item_path(get_turf(src))
+ var/folded = new item_path(get_turf(src))
spawn(0)
qdel(src)
- return
+ return folded
+
+/obj/structure/closet/body_bag/relaymove(mob/user,direction)
+ if(src.loc != get_turf(src))
+ src.loc.relaymove(user,direction)
+ else
+ ..()
/obj/structure/closet/body_bag/proc/get_occupants()
var/list/occupants = list()
@@ -109,37 +115,43 @@
/obj/item/bodybag/cryobag
name = "stasis bag"
- desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant, especially useful if short on time or in \
- a hostile enviroment."
+ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
+ especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi'
icon_state = "bodybag_folded"
item_state = "bodybag_cryo_folded"
origin_tech = list(TECH_BIO = 4)
+ var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/item/bodybag/cryobag/attack_self(mob/user)
var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
R.add_fingerprint(user)
+ if(syringe)
+ R.syringe = syringe
+ syringe = null
qdel(src)
/obj/structure/closet/body_bag/cryobag
name = "stasis bag"
- desc = "A non-reusable plastic bag designed to prevent additional damage to an occupant, especially useful if short on time or in \
- a hostile enviroment."
+ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
+ especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi'
item_path = /obj/item/bodybag/cryobag
store_misc = 0
store_items = 0
var/used = 0
var/obj/item/weapon/tank/tank = null
+ var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
+ var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/structure/closet/body_bag/cryobag/New()
tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened.
..()
/obj/structure/closet/body_bag/cryobag/Destroy()
- qdel(tank)
- tank = null
- ..()
+ qdel_null(syringe)
+ qdel_null(tank)
+ return ..()
/obj/structure/closet/body_bag/cryobag/open()
. = ..()
@@ -151,11 +163,19 @@
O.desc = "Pretty useless now.."
qdel(src)
+/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
+ . = ..()
+ if(. && syringe)
+ var/obj/item/bodybag/cryobag/folded = .
+ folded.syringe = syringe
+ syringe = null
+
/obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
- H.in_stasis = 1
+ H.Stasis(stasis_level)
src.used = 1
+ inject_occupant(H)
if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM
@@ -167,7 +187,7 @@
/obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
- H.in_stasis = 0
+ H.Stasis(0)
if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM
@@ -181,10 +201,19 @@
return tank.air_contents
..()
+/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H)
+ if(!syringe)
+ return
+
+ if(H.reagents)
+ syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD)
+
/obj/structure/closet/body_bag/cryobag/examine(mob/user)
..()
if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
user << "You peer into \the [src]."
+ if(syringe)
+ user << "It has a syringe added to it."
for(var/mob/living/L in contents)
L.examine(user)
@@ -196,5 +225,28 @@
var/obj/item/device/healthanalyzer/analyzer = W
for(var/mob/living/L in contents)
analyzer.attack(L,user)
+
+ else if(istype(W,/obj/item/weapon/reagent_containers/syringe))
+ if(syringe)
+ to_chat(user,"\The [src] already has an injector! Remove it first.")
+ else
+ var/obj/item/weapon/reagent_containers/syringe/syringe = W
+ to_chat(user,"You insert \the [syringe] into \the [src], and it locks into place.")
+ user.unEquip(syringe)
+ src.syringe = syringe
+ syringe.loc = null
+ for(var/mob/living/carbon/human/H in contents)
+ inject_occupant(H)
+ break
+
+ else if(istype(W,/obj/item/weapon/screwdriver))
+ if(syringe)
+ if(used)
+ to_chat(user,"The injector cannot be removed now that the stasis bag has been used!")
+ else
+ syringe.forceMove(src.loc)
+ to_chat(user,"You pry \the [syringe] out of \the [src].")
+ syringe = null
+
else
..()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 674e746c28..7f1d83cc4a 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -1083,7 +1083,10 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (last_text && world.time < last_text + 5)
return
- if(!can_use())
+ if (!can_use())
+ return
+
+ if (is_jammed(src))
return
last_text = world.time
@@ -1105,6 +1108,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(M.stat == DEAD && M.client && (M.is_preference_enabled(/datum/client_preference/ghost_ears))) // src.client is so that ghosts don't have to listen to mice
if(istype(M, /mob/new_player))
continue
+ if(M.forbid_seeing_deadchat)
+ continue
M.show_message("PDA Message - [owner] -> [P.owner]: [t]")
if(!conversations.Find("\ref[P]"))
@@ -1156,6 +1161,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
// Do nothing
/obj/item/device/pda/proc/new_message_from_pda(var/obj/item/device/pda/sending_device, var/message)
+ if (is_jammed(src))
+ return
new_message(sending_device, sending_device.owner, sending_device.ownjob, message)
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message, var/reply = 1)
@@ -1463,8 +1470,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/Destroy()
PDAs -= src
if (src.id && prob(90)) //IDs are kept in 90% of the cases
- src.id.loc = get_turf(src.loc)
- ..()
+ src.id.forceMove(get_turf(src.loc))
+ else
+ qdel_null(src.id)
+ qdel_null(src.cartridge)
+ qdel_null(src.pai)
+ return ..()
/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery.
if (istype(AM, /mob/living))
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 2c4368736e..c53ba712db 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -78,6 +78,10 @@ var/list/civilian_cartridges = list(
var/message2
var/list/stored_data = list()
+/obj/item/weapon/cartridge/Destroy()
+ qdel_null(radio)
+ return ..()
+
/obj/item/weapon/cartridge/engineering
name = "\improper Power-ON cartridge"
icon_state = "cart-e"
@@ -164,10 +168,6 @@ var/list/civilian_cartridges = list(
radio = new /obj/item/radio/integrated/signal(src)
..()
-/obj/item/weapon/cartridge/signal/Destroy()
- qdel(radio)
- ..()
-
/obj/item/weapon/cartridge/quartermaster
name = "\improper Space Parts & Space Vendors cartridge"
desc = "Perfect for the Quartermaster on the go!"
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
index 5e7d63e1e9..019425db0e 100644
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ b/code/game/objects/items/devices/PDA/radio.dm
@@ -103,7 +103,7 @@
/obj/item/radio/integrated/beepsky/Destroy()
if(radio_controller)
radio_controller.remove_object(src, control_freq)
- ..()
+ return ..()
/*
* Radio Cartridge, essentially a signaler.
@@ -152,4 +152,4 @@
/obj/item/radio/integrated/signal/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ return ..()
diff --git a/code/game/objects/items/devices/ai_detector.dm b/code/game/objects/items/devices/ai_detector.dm
new file mode 100644
index 0000000000..7fa6f74521
--- /dev/null
+++ b/code/game/objects/items/devices/ai_detector.dm
@@ -0,0 +1,121 @@
+#define PROXIMITY_OFF_CAMERANET "_no_camera"
+#define PROXIMITY_NONE ""
+#define PROXIMITY_NEAR "_yellow"
+#define PROXIMITY_ON_SCREEN "_red"
+#define PROXIMITY_TRACKING "_tracking"
+#define PROXIMITY_TRACKING_FAIL "_tracking_fail"
+
+// This is another syndie-multitool, except this one detects when the AI and/or Security is peeping on the holder.
+
+/obj/item/device/multitool/ai_detector
+ var/range_alert = 7 // Will turn red if the AI can observe its holder.
+ var/range_warning = 14 // Will turn yellow if the AI's eye is near the holder.
+ var/detect_state = PROXIMITY_NONE
+ origin_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_ILLEGAL = 2)
+
+/obj/item/device/multitool/ai_detector/New()
+ // It's really really unlikely for the view range to change. But why not be futureproof anyways?
+ range_alert = world.view
+ range_warning = world.view * 2
+ processing_objects += src
+ ..()
+
+/obj/item/device/multitool/ai_detector/Destroy()
+ processing_objects -= src
+ return ..()
+
+/obj/item/device/multitool/ai_detector/process()
+ var/old_detect_state = detect_state
+ var/new_detect_state = detect_ai()
+ detect_state = new_detect_state
+ update_icon()
+ update_warning(old_detect_state, new_detect_state)
+ return
+
+// This also detects security using cameras.
+/obj/item/device/multitool/ai_detector/proc/detect_ai()
+ var/mob/living/carrier = isliving(loc) ? loc : null
+
+ // First, let's check if any AIs are actively tracking them.
+ for(var/mob/living/silicon/ai/AI in silicon_mob_list)
+ if(carrier && AI.cameraFollow == carrier)
+ if(!carrier.tracking_status()) // Successful tracking returns a 0, so we need to invert it.
+ return PROXIMITY_TRACKING
+ else
+ return PROXIMITY_TRACKING_FAIL
+
+ // If there's no turf then cameras won't do anything anyways.
+ var/turf/T = get_turf(src)
+ if(!T)
+ return PROXIMITY_OFF_CAMERANET
+
+ // Security is also a concern, so we need to see if any cameras are in use.
+ // Note that this will trigger upon the security console being used, regardless if someone is actually watching,
+ // because there isn't a nice way to test if someone is actually looking. Probably better that way too.
+ var/list/our_local_area = range(range_alert, T)
+ for(var/obj/machinery/camera/C in our_local_area)
+ if(C.camera_computers_using_this.len) // Only check cameras actively being used.
+ var/list/their_local_area = C.can_see(range_alert)
+ if(T in their_local_area)
+ return PROXIMITY_ON_SCREEN
+
+ // Now for the somewhat harder AI cameranet checks.
+
+ // Check if we are even on the cameranet.
+ if(!cameranet.checkVis(T))
+ return PROXIMITY_OFF_CAMERANET
+
+ var/datum/chunk/chunk = cameranet.getChunk(T.x, T.y, T.z)
+ if(!chunk)
+ return PROXIMITY_OFF_CAMERANET
+
+ // Check if the AI eye is able to see us, or if it's almost able to.
+ if(chunk.seenby.len)
+ for(var/mob/observer/eye/aiEye/A in chunk.seenby)
+ var/turf/detect_turf = get_turf(A)
+ if(get_dist(T, detect_turf) <= range_alert)
+ return PROXIMITY_ON_SCREEN
+ if(get_dist(T, detect_turf) <= range_warning)
+ return PROXIMITY_NEAR
+
+ // If we reach this point, AI or sec isn't near us.
+ return PROXIMITY_NONE
+
+/obj/item/device/multitool/ai_detector/update_icon()
+ icon_state = "[initial(icon_state)][detect_state]"
+
+/obj/item/device/multitool/ai_detector/proc/update_warning(var/old_state, var/new_state)
+ var/mob/living/carrier = isliving(loc) ? loc : null
+
+ // Now to warn our holder, if the state changes.
+ if(!carrier)
+ return
+
+ if(new_state != old_state)
+ switch(new_state)
+ if(PROXIMITY_OFF_CAMERANET)
+ to_chat(carrier, "\icon[src] Now outside of camera network.")
+ carrier << 'sound/machines/defib_failed.ogg'
+ if(PROXIMITY_NONE)
+ to_chat(carrier, "\icon[src] Now within camera network, AI and cameras unfocused.")
+ carrier << 'sound/machines/defib_safetyOff.ogg'
+ if(PROXIMITY_NEAR)
+ to_chat(carrier, "\icon[src] Warning: AI focus at nearby location.")
+ carrier << 'sound/machines/defib_SafetyOn.ogg'
+ if(PROXIMITY_ON_SCREEN)
+ to_chat(carrier, "\icon[src] Alert: AI or camera focused at current location!")
+ carrier <<'sound/machines/defib_ready.ogg'
+ if(PROXIMITY_TRACKING)
+ to_chat(carrier, "\icon[src] Danger: AI is actively tracking you!")
+ carrier << 'sound/machines/defib_success.ogg'
+ if(PROXIMITY_TRACKING_FAIL)
+ to_chat(carrier, "\icon[src] Danger: AI is attempting to actively track you, but you are outside of the camera network!")
+ carrier <<'sound/machines/defib_ready.ogg'
+
+
+#undef PROXIMITY_OFF_CAMERANET
+#undef PROXIMITY_NONE
+#undef PROXIMITY_NEAR
+#undef PROXIMITY_ON_SCREEN
+#undef PROXIMITY_TRACKING
+#undef PROXIMITY_TRACKING_FAIL
\ No newline at end of file
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index c609d38c4a..5a7a028054 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -1,9 +1,10 @@
/obj/item/device/aicard
- name = "inteliCard"
+ name = "intelliCore"
+ desc = "Used to preserve and transport an AI."
icon = 'icons/obj/pda.dmi'
icon_state = "aicard" // aicard-full
item_state = "aicard"
- w_class = ITEMSIZE_SMALL
+ w_class = ITEMSIZE_NORMAL
slot_flags = SLOT_BELT
show_messages = 0
@@ -57,12 +58,12 @@
var/user = usr
if (href_list["wipe"])
- var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No")
+ var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "Yes", "No")
if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE))
- admin_attack_log(user, carded_ai, "Wiped using \the [src.name]", "Was wiped with \the [src.name]", "used \the [src.name] to wipe")
+ admin_attack_log(user, carded_ai, "Purged using \the [src.name]", "Was purged with \the [src.name]", "used \the [src.name] to purge")
flush = 1
carded_ai.suiciding = 1
- carded_ai << "Your core files are being wiped!"
+ carded_ai << "Your power has been disabled!"
while (carded_ai && carded_ai.stat != 2)
carded_ai.adjustOxyLoss(2)
carded_ai.updatehealth()
@@ -93,22 +94,22 @@
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
if(!ai.client)
- user << "ERROR: AI [ai.name] is offline. Unable to download."
+ user << "ERROR: AI [ai.name] is offline. Unable to transfer."
return 0
if(carded_ai)
- user << "Transfer failed: Existing AI found on remote terminal. Remove existing AI to install a new one."
+ user << "Transfer failed: Existing AI found on remote device. Remove existing AI to install a new one."
return 0
- user.visible_message("\The [user] starts downloading \the [ai] into \the [src]...", "You start downloading \the [ai] into \the [src]...")
- ai << "\The [user] is downloading you into \the [src]!"
+ user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
+ ai << "\The [user] is transferring you into \the [src]!"
if(do_after(user, 100))
if(istype(ai.loc, /turf/))
new /obj/structure/AIcore/deactivated(get_turf(ai))
ai.carded = 1
- admin_attack_log(user, ai, "Carded with [src.name]", "Was carded with [src.name]", "used the [src.name] to card")
+ admin_attack_log(user, ai, "Extracted with [src.name]", "Was extracted with [src.name]", "used the [src.name] to extract")
src.name = "[initial(name)] - [ai.name]"
ai.loc = src
@@ -119,9 +120,9 @@
carded_ai = ai
if(ai.client)
- ai << "You have been downloaded to a mobile storage device. Remote access lost."
+ ai << "You have been transferred into a mobile core. Remote access lost."
if(user.client)
- user << "Transfer successful: [ai.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
+ user << "Transfer successful: [ai.name] extracted from current device and placed within mobile core."
ai.canmove = 1
update_icon()
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 4b870481fa..9775d64042 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -47,7 +47,7 @@
qdel(active_dummy)
active_dummy = null
usr << "You deactivate the [src]."
- var/obj/effect/overlay/T = PoolOrNew(/obj/effect/overlay, get_turf(src))
+ var/obj/effect/overlay/T = new /obj/effect/overlay(get_turf(src))
T.icon = 'icons/effects/effects.dmi'
flick("emppulse",T)
spawn(8) qdel(T)
@@ -55,7 +55,7 @@
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
var/obj/O = new saved_item(src)
if(!O) return
- var/obj/effect/dummy/chameleon/C = PoolOrNew(/obj/effect/dummy/chameleon, usr.loc)
+ var/obj/effect/dummy/chameleon/C = new /obj/effect/dummy/chameleon(usr.loc)
C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src)
qdel(O)
usr << "You activate the [src]."
diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm
index 8bfe2dffca..e2f4137cb4 100644
--- a/code/game/objects/items/devices/communicator/communicator.dm
+++ b/code/game/objects/items/devices/communicator/communicator.dm
@@ -169,9 +169,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
// Parameters: None
// Description: Simple check to see if the exonet node is active.
/obj/item/device/communicator/proc/get_connection_to_tcomms()
- if(node)
- if(node.on && node.allow_external_communicators)
- return 1
+ if(node && node.on && node.allow_external_communicators && !is_jammed(src))
+ return 1
return 0
// Proc: process()
@@ -182,7 +181,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(update_ticks % 5)
if(!node)
node = get_exonet_node()
- if(!node || !node.on || !node.allow_external_communicators)
+ if(!get_connection_to_tcomms())
close_connection(reason = "Connection timed out")
// Proc: attackby()
@@ -212,6 +211,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
alert_called = 0
update_icon()
ui_interact(user)
+ if(video_source)
+ watch_video(user)
// Proc: MouseDrop()
//Same thing PDAs do
@@ -255,12 +256,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(exonet)
exonet.remove_address()
exonet = null
- ..()
+ return ..()
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI arguments)
// Description: Uses a bunch of for loops to turn lists into lists of lists, so they can be displayed in nanoUI, then displays various buttons to the user.
-/obj/item/device/communicator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+/obj/item/device/communicator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
// this is the data which will be sent to the ui
var/data[0] //General nanoUI information
var/communicators[0] //List of communicators
@@ -355,7 +356,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 475, 700)
+ ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 475, 700, state = key_state)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
@@ -519,6 +520,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
return
src << "\icon[origin_atom] Receiving communicator request from [origin_atom]. To answer, use the Call Communicator \
verb, and select that name to answer the call."
+ src << 'sound/machines/defib_SafetyOn.ogg'
comm.voice_invites |= src
if(message == "ping")
if(client && client.prefs.communicator_visibility)
@@ -527,6 +529,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
if(message == "text")
src << "\icon[origin_atom] Received text message from [origin_atom]: \"[text]\""
+ src << 'sound/machines/defib_safetyOff.ogg'
exonet_messages.Add("From [origin_atom]: [text]")
return
@@ -802,7 +805,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(exonet)
exonet.remove_address()
exonet = null
- ..()
+ return ..()
// Proc: update_icon()
// Parameters: None
@@ -1032,7 +1035,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(!Adjacent(user) || !video_source) return
user.set_machine(video_source)
user.reset_view(video_source)
- user << "Now viewing video session. To leave camera view: OOC -> Cancel Camera View"
+ to_chat(user,"Now viewing video session. To leave camera view, close the communicator window OR: OOC -> Cancel Camera View")
+ to_chat(user,"To return to an active video session, use the communicator in your hand.")
spawn(0)
while(user.machine == video_source && Adjacent(user))
var/turf/T = get_turf(video_source)
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index 73efffe121..b9b8af0c0d 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -1,184 +1,657 @@
-//The case the paddles are kept in.
+#define DEFIB_TIME_LIMIT (10 MINUTES) //past this many seconds, defib is useless.
+#define DEFIB_TIME_LOSS (2 MINUTES) //past this many seconds, brain damage occurs.
+
+//backpack item
/obj/item/device/defib_kit
- name = "defibrillator kit"
- desc = "This KHI-branded defib kit is a semi-automated model. Remove pads, slap on chest, wait."
- icon = 'icons/obj/device.dmi'
- icon_state = "defib_kit"
+ name = "defibrillator"
+ desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
+ icon = 'icons/obj/defibrillator.dmi'
+ icon_state = "defibunit"
+ item_state = "defibunit"
+ slot_flags = SLOT_BACK
+ force = 5
+ throwforce = 6
+ w_class = ITEMSIZE_LARGE
+ origin_tech = list(TECH_BIO = 4, TECH_POWER = 2)
+ action_button_name = "Remove/Replace Paddles"
+
+ var/obj/item/weapon/shockpaddles/linked/paddles
+ var/obj/item/weapon/cell/bcell = null
+
+/obj/item/device/defib_kit/New() //starts without a cell for rnd
+ ..()
+ if(ispath(paddles))
+ paddles = new paddles(src, src)
+ else
+ paddles = new(src, src)
+
+ if(ispath(bcell))
+ bcell = new bcell(src)
+ update_icon()
+
+/obj/item/device/defib_kit/Destroy()
+ . = ..()
+ qdel_null(paddles)
+ qdel_null(bcell)
+
+/obj/item/device/defib_kit/loaded //starts with highcap cell
+ bcell = /obj/item/weapon/cell/high
+
+
+/obj/item/device/defib_kit/update_icon()
+ var/list/new_overlays = list()
+
+ if(paddles && paddles.loc == src) //in case paddles got destroyed somehow.
+ new_overlays += "[initial(icon_state)]-paddles"
+ if(bcell)
+ if(bcell.check_charge(paddles.chargecost))
+ if(paddles.combat)
+ new_overlays += "[initial(icon_state)]-combat"
+ else if(!paddles.safety)
+ new_overlays += "[initial(icon_state)]-emagged"
+ else
+ new_overlays += "[initial(icon_state)]-powered"
+
+ var/ratio = Ceiling(bcell.percent()/25) * 25
+ new_overlays += "[initial(icon_state)]-charge[ratio]"
+ else
+ new_overlays += "[initial(icon_state)]-nocell"
+
+ overlays = new_overlays
+
+/obj/item/device/defib_kit/ui_action_click()
+ toggle_paddles()
+
+/obj/item/device/defib_kit/attack_hand(mob/user)
+ if(loc == user)
+ toggle_paddles()
+ else
+ ..()
+
+/obj/item/device/defib_kit/MouseDrop()
+ if(ismob(src.loc))
+ if(!CanMouseDrop(src))
+ return
+ var/mob/M = src.loc
+ if(!M.unEquip(src))
+ return
+ src.add_fingerprint(usr)
+ M.put_in_any_hand_if_possible(src)
+
+
+/obj/item/device/defib_kit/attackby(obj/item/weapon/W, mob/user, params)
+ if(W == paddles)
+ reattach_paddles(user)
+ else if(istype(W, /obj/item/weapon/cell))
+ if(bcell)
+ to_chat(user, "\the [src] already has a cell.")
+ else
+ if(!user.unEquip(W))
+ return
+ W.forceMove(src)
+ bcell = W
+ to_chat(user, "You install a cell in \the [src].")
+ update_icon()
+
+ else if(isscrewdriver(W))
+ if(bcell)
+ bcell.update_icon()
+ bcell.forceMove(get_turf(src.loc))
+ bcell = null
+ to_chat(user, "You remove the cell from \the [src].")
+ update_icon()
+ else
+ return ..()
+
+/obj/item/device/defib_kit/emag_act(var/remaining_charges, var/mob/user)
+ if(paddles)
+ . = paddles.emag_act(user)
+ update_icon()
+ return
+
+//Paddle stuff
+
+/obj/item/device/defib_kit/verb/toggle_paddles()
+ set name = "Toggle Paddles"
+ set category = "Object"
+
+ var/mob/living/carbon/human/user = usr
+ if(!paddles)
+ to_chat(user, "The paddles are missing!")
+ return
+
+ if(paddles.loc != src)
+ reattach_paddles(user) //Remove from their hands and back onto the defib unit
+ return
+
+ if(!slot_check())
+ to_chat(user, "You need to equip [src] before taking out [paddles].")
+ else
+ if(!usr.put_in_hands(paddles)) //Detach the paddles into the user's hands
+ to_chat(user, "You need a free hand to hold the paddles!")
+ update_icon() //success
+
+//checks that the base unit is in the correct slot to be used
+/obj/item/device/defib_kit/proc/slot_check()
+ var/mob/M = loc
+ if(!istype(M))
+ return 0 //not equipped
+
+ if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src)
+ return 1
+ if((slot_flags & SLOT_BELT) && M.get_equipped_item(slot_belt) == src)
+ return 1
+
+ return 0
+
+/obj/item/device/defib_kit/dropped(mob/user)
+ ..()
+ reattach_paddles(user) //paddles attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
+
+/obj/item/device/defib_kit/proc/reattach_paddles(mob/user)
+ if(!paddles) return
+
+ if(ismob(paddles.loc))
+ var/mob/M = paddles.loc
+ if(M.drop_from_inventory(paddles, src))
+ to_chat(user, "\The [paddles] snap back into the main unit.")
+ else
+ paddles.forceMove(src)
+
+ update_icon()
+
+/*
+ Base Unit Subtypes
+*/
+
+/obj/item/device/defib_kit/compact
+ name = "compact defibrillator"
+ desc = "A belt-equipped defibrillator that can be rapidly deployed."
+ icon_state = "defibcompact"
+ item_state = "defibcompact"
+ w_class = ITEMSIZE_NORMAL
+ slot_flags = SLOT_BELT
+ origin_tech = list(TECH_BIO = 5, TECH_POWER = 3)
+
+/obj/item/device/defib_kit/compact/loaded
+ bcell = /obj/item/weapon/cell/high
+
+
+/obj/item/device/defib_kit/compact/combat
+ name = "combat defibrillator"
+ desc = "A belt-equipped blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
+ paddles = /obj/item/weapon/shockpaddles/linked/combat
+
+/obj/item/device/defib_kit/compact/combat/loaded
+ bcell = /obj/item/weapon/cell/high
+
+/obj/item/weapon/shockpaddles/linked/combat
+ combat = 1
+ safety = 0
+ chargetime = (1 SECONDS)
+
+
+//paddles
+
+/obj/item/weapon/shockpaddles
+ name = "defibrillator paddles"
+ desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
+ icon = 'icons/obj/defibrillator.dmi'
+ icon_state = "defibpaddles"
+ item_state = "defibpaddles"
+ gender = PLURAL
+ force = 2
+ throwforce = 6
w_class = ITEMSIZE_LARGE
- var/state //0 off, 1 open, 2 working, 3 dead
- var/uses = 2 //Calculates initial uses based on starting cell size
- var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies
- var/pad_name = "defib pads" //Just the name given for some cosmetic things
- var/chance = 75 //Percent chance of working
- var/charge_cost //Set in New() based on uses
- var/obj/item/weapon/cell/cell //The size is mostly irrelevant, see 'uses'
- var/mob/living/carbon/human/patient //The person the paddles are on
+ var/safety = 1 //if you can zap people with the paddles on harm mode
+ var/combat = 0 //If it can be used to revive people wearing thick clothing (e.g. spacesuits)
+ var/cooldowntime = (6 SECONDS) // How long in deciseconds until the defib is ready again after use.
+ var/chargetime = (2 SECONDS)
+ var/chargecost = 1000 //units of charge
+ var/burn_damage_amt = 5
+ var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies
-/obj/item/device/defib_kit/New()
+ var/wielded = 0
+ var/cooldown = 0
+ var/busy = 0
+
+/obj/item/weapon/shockpaddles/proc/set_cooldown(var/delay)
+ cooldown = 1
+ update_icon()
+
+ spawn(delay)
+ if(cooldown)
+ cooldown = 0
+ update_icon()
+
+ make_announcement("beeps, \"Unit is re-energized.\"", "notice")
+ playsound(src, 'sound/machines/defib_ready.ogg', 50, 0)
+
+/obj/item/weapon/shockpaddles/update_held_icon()
+ var/mob/living/M = loc
+ if(istype(M) && M.item_is_in_hands(src) && !M.hands_are_full())
+ wielded = 1
+ name = "[initial(name)] (wielded)"
+ else
+ wielded = 0
+ name = initial(name)
+ update_icon()
..()
- //Create cell and determine uses (futureproofing against cell size changes)
- cell = new(src)
- charge_cost = cell.maxcharge / uses
- statechange(0)
-/obj/item/device/defib_kit/attack_self(mob/user as mob)
- ..()
- if(patient)
- patient = null
- user.visible_message("[user] returns the pads to \the [src] and closes it.",
- "You return the pads to \the [src] and close it.")
- statechange(0)
+/obj/item/weapon/shockpaddles/update_icon()
+ icon_state = "defibpaddles[wielded]"
+ item_state = "defibpaddles[wielded]"
+ if(cooldown)
+ icon_state = "defibpaddles[wielded]_cooldown"
-/obj/item/device/defib_kit/MouseDrop(var/mob/living/carbon/human/onto)
- if(istype(onto) && Adjacent(usr) && !usr.restrained() && !usr.stat)
- var/mob/living/carbon/human/user = usr
- //<--Feel free to code clothing checks right here
- if(can_defib(onto))
- user.visible_message("[user] begins applying [pad_name] to [onto].",
- "You begin applying [pad_name] to [onto].")
- if(do_after(user, 100, onto))
- patient = onto
- statechange(1,patient)
- user.visible_message("[user] applies [pad_name] to [onto].",
- "You finish applying [pad_name] to [onto].")
-
-
-//can_defib() check is where all of the qualifying conditions should go
-//Could probably toss in checks here for damage, organs, etc, but for now I'll leave it as just this
-/obj/item/device/defib_kit/proc/can_defib(var/mob/living/carbon/human/target)
- var/mob/living/carbon/human/user = usr
- if(use_on_synthetic && !target.isSynthetic())
- to_chat(user, "[src] isn't designed for organics!")
+/obj/item/weapon/shockpaddles/proc/can_use(mob/user, mob/M)
+ if(busy)
return 0
- else if(!use_on_synthetic && target.isSynthetic())
- to_chat(user, "[src] isn't designed for synthetics!")
+ if(!check_charge(chargecost))
+ to_chat(user, "\The [src] doesn't have enough charge left to do that.")
return 0
- else if(!target.isSynthetic() && ((world.time - target.timeofdeath) > (10 MINUTES)))//Can only revive organics within a few minutes
- to_chat(user, "There is no spark of life in [target.name], they've been dead too long to revive this way.")
+ if(!wielded && !isrobot(user))
+ to_chat(user, "You need to wield the paddles with both hands before you can use them on someone!")
+ return 0
+ if(cooldown)
+ to_chat(user, "\The [src] are re-energizing!")
return 0
return 1
+//Checks for various conditions to see if the mob is revivable
+/obj/item/weapon/shockpaddles/proc/can_defib(mob/living/carbon/human/H) //This is checked before doing the defib operation
+ if((H.species.flags & NO_SCAN))
+ return "buzzes, \"Unrecogized physiology. Operation aborted.\""
+ else if(H.isSynthetic() && !use_on_synthetic)
+ return "buzzes, \"Synthetic Body. Operation aborted.\""
+ else if(!H.isSynthetic() && use_on_synthetic)
+ return "buzzes, \"Organic Body. Operation aborted.\""
-/obj/item/device/defib_kit/attackby(var/obj/item/A as obj, mob/living/user as mob)
+ if(H.stat != DEAD)
+ return "buzzes, \"Patient is not in a valid state. Operation aborted.\""
+
+ if(!check_contact(H))
+ return "buzzes, \"Patient's chest is obstructed. Operation aborted.\""
+
+ return null
+
+/obj/item/weapon/shockpaddles/proc/can_revive(mob/living/carbon/human/H) //This is checked right before attempting to revive
+
+ var/deadtime = world.time - H.timeofdeath
+ if (deadtime > DEFIB_TIME_LIMIT && !H.isSynthetic())
+ return "buzzes, \"Resuscitation failed - Excessive neural degeneration. Further attempts futile.\""
+
+ H.updatehealth()
+ if(H.health + H.getOxyLoss() <= config.health_threshold_dead || (HUSK in H.mutations))
+ return "buzzes, \"Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.\""
+
+ var/bad_vital_organ = check_vital_organs(H)
+ if(bad_vital_organ)
+ return bad_vital_organ
+
+ //this needs to be last since if any of the 'other conditions are met their messages take precedence
+ if(!H.client && !H.teleop)
+ return "buzzes, \"Resuscitation failed - Mental interface error. Further attempts may be successful.\""
+
+ return null
+
+/obj/item/weapon/shockpaddles/proc/check_contact(mob/living/carbon/human/H)
+ if(!combat)
+ for(var/obj/item/clothing/cloth in list(H.wear_suit, H.w_uniform))
+ if((cloth.body_parts_covered & UPPER_TORSO) && (cloth.item_flags & THICKMATERIAL))
+ return FALSE
+ return TRUE
+
+/obj/item/weapon/shockpaddles/proc/check_vital_organs(mob/living/carbon/human/H)
+ for(var/organ_tag in H.species.has_organ)
+ var/obj/item/organ/O = H.species.has_organ[organ_tag]
+ var/name = initial(O.name)
+ var/vital = initial(O.vital) //check for vital organs
+ if(vital)
+ O = H.internal_organs_by_name[organ_tag]
+ if(!O)
+ return "buzzes, \"Resuscitation failed - Patient is missing vital organ ([name]). Further attempts futile.\""
+ if(O.damage > O.max_damage)
+ return "buzzes, \"Resuscitation failed - Excessive damage to vital organ ([name]). Further attempts futile.\""
+ return null
+
+/obj/item/weapon/shockpaddles/proc/check_blood_level(mob/living/carbon/human/H)
+ if(!H.should_have_organ(O_HEART))
+ return FALSE
+
+ var/obj/item/organ/internal/heart/heart = H.internal_organs_by_name[O_HEART]
+ if(!heart)
+ return TRUE
+
+ var/blood_volume = round((H.vessel.get_reagent_amount("blood")/H.species.blood_volume)*100)
+ if(!heart || heart.is_broken())
+ blood_volume *= 0.3
+ else if(heart.is_bruised())
+ blood_volume *= 0.7
+ else if(heart.damage > 1)
+ blood_volume *= 0.8
+ return blood_volume < BLOOD_VOLUME_SURVIVE
+
+/obj/item/weapon/shockpaddles/proc/check_charge(var/charge_amt)
+ return 0
+
+/obj/item/weapon/shockpaddles/proc/checked_use(var/charge_amt)
+ return 0
+
+/obj/item/weapon/shockpaddles/attack(mob/living/M, mob/living/user, var/target_zone)
+ var/mob/living/carbon/human/H = M
+ if(!istype(H) || user.a_intent == I_HURT)
+ return ..() //Do a regular attack. Harm intent shocking happens as a hit effect
+
+ if(can_use(user, H))
+ busy = 1
+ update_icon()
+
+ do_revive(H, user)
+
+ busy = 0
+ update_icon()
+
+ return 1
+
+//Since harm-intent now skips the delay for deliberate placement, you have to be able to hit them in combat in order to shock people.
+/obj/item/weapon/shockpaddles/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
+ if(ishuman(target) && can_use(user, target))
+ busy = 1
+ update_icon()
+
+ do_electrocute(target, user, hit_zone)
+
+ busy = 0
+ update_icon()
+
+ return 1
+
+ return ..()
+
+// This proc is used so that we can return out of the revive process while ensuring that busy and update_icon() are handled
+/obj/item/weapon/shockpaddles/proc/do_revive(mob/living/carbon/human/H, mob/user)
+ if(!H.client && !H.teleop)
+ to_chat(find_dead_player(H.ckey, 1), "Someone is attempting to resuscitate you. Re-enter your body if you want to be revived!")
+
+ //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
+ user.visible_message("\The [user] begins to place [src] on [H]'s chest.", "You begin to place [src] on [H]'s chest...")
+ if(!do_after(user, 30, H))
+ return
+ user.visible_message("\The [user] places [src] on [H]'s chest.", "You place [src] on [H]'s chest.")
+ playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+
+ var/error = can_defib(H)
+ if(error)
+ make_announcement(error, "warning")
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ return
+
+ if(check_blood_level(H))
+ make_announcement("buzzes, \"Warning - Patient is in hypovolemic shock.\"", "warning") //also includes heart damage
+
+ //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
+ if(!do_after(user, chargetime, H))
+ return
+
+ //deduct charge here, in case the base unit was EMPed or something during the delay time
+ if(!checked_use(chargecost))
+ make_announcement("buzzes, \"Insufficient charge.\"", "warning")
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ return
+
+ H.visible_message("\The [H]'s body convulses a bit.")
+ playsound(get_turf(src), "bodyfall", 50, 1)
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ set_cooldown(cooldowntime)
+
+ error = can_revive(H)
+ if(error)
+ make_announcement(error, "warning")
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ return
+
+ H.apply_damage(burn_damage_amt, BURN, BP_TORSO)
+
+ //set oxyloss so that the patient is just barely in crit, if possible
+ var/barely_in_crit = config.health_threshold_crit - 1
+ var/adjust_health = barely_in_crit - H.health //need to increase health by this much
+ H.adjustOxyLoss(-adjust_health)
+
+ make_announcement("pings, \"Resuscitation successful.\"", "notice")
+ playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
+
+ make_alive(H)
+
+ log_and_message_admins("used \a [src] to revive [key_name(H)].")
+
+
+/obj/item/weapon/shockpaddles/proc/do_electrocute(mob/living/carbon/human/H, mob/user, var/target_zone)
+ var/obj/item/organ/external/affecting = H.get_organ(target_zone)
+ if(!affecting)
+ to_chat(user, "They are missing that body part!")
+ return
+
+ //no need to spend time carefully placing the paddles, we're just trying to shock them
+ user.visible_message("\The [user] slaps [src] onto [H]'s [affecting.name].", "You overcharge [src] and slap them onto [H]'s [affecting.name].")
+
+ //Just stop at awkwardly slapping electrodes on people if the safety is enabled
+ if(safety)
+ to_chat(user, "You can't do that while the safety is enabled.")
+ return
+
+ playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+ audible_message("\The [src] lets out a steadily rising hum...")
+
+ if(!do_after(user, chargetime, H))
+ return
+
+ //deduct charge here, in case the base unit was EMPed or something during the delay time
+ if(!checked_use(chargecost))
+ make_announcement("buzzes, \"Insufficient charge.\"", "warning")
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ return
+
+ user.visible_message("\The [user] shocks [H] with \the [src]!", "You shock [H] with \the [src]!")
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
+ playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
+ set_cooldown(cooldowntime)
+
+ H.stun_effect_act(2, 120, target_zone)
+ var/burn_damage = H.electrocute_act(burn_damage_amt*2, src, def_zone = target_zone)
+ if(burn_damage > 15 && H.can_feel_pain())
+ H.emote("scream")
+
+ admin_attack_log(user, H, "Electrocuted using \a [src]", "Was electrocuted with \a [src]", "used \a [src] to electrocute")
+
+/obj/item/weapon/shockpaddles/proc/make_alive(mob/living/carbon/human/M) //This revives the mob
+ var/deadtime = world.time - M.timeofdeath
+
+ dead_mob_list.Remove(M)
+ if((M in living_mob_list) || (M in dead_mob_list))
+ WARNING("Mob [M] was defibbed but already in the living or dead list still!")
+ living_mob_list += M
+
+ M.timeofdeath = 0
+ M.stat = UNCONSCIOUS //Life() can bring them back to consciousness if it needs to.
+ M.regenerate_icons()
+ M.failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
+ M.reload_fullscreen()
+
+ M.emote("gasp")
+ M.Weaken(rand(10,25))
+ M.updatehealth()
+ apply_brain_damage(M, deadtime)
+
+/obj/item/weapon/shockpaddles/proc/apply_brain_damage(mob/living/carbon/human/H, var/deadtime)
+ if(deadtime < DEFIB_TIME_LOSS) return
+
+ if(!H.should_have_organ(O_BRAIN)) return //no brain
+
+ var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN]
+ if(!brain) return //no brain
+
+ var/brain_damage = Clamp((deadtime - DEFIB_TIME_LOSS)/(DEFIB_TIME_LIMIT - DEFIB_TIME_LOSS)*brain.max_damage, H.getBrainLoss(), brain.max_damage)
+ H.setBrainLoss(brain_damage)
+
+/obj/item/weapon/shockpaddles/proc/make_announcement(var/message, var/msg_class)
+ audible_message("\The [src] [message]", "\The [src] vibrates slightly.")
+
+/obj/item/weapon/shockpaddles/emag_act(mob/user)
+ if(safety)
+ safety = 0
+ to_chat(user, "You silently disable \the [src]'s safety protocols with the cryptographic sequencer.")
+ update_icon()
+ return 1
+ else
+ safety = 1
+ to_chat(user, "You silently enable \the [src]'s safety protocols with the cryptographic sequencer.")
+ update_icon()
+ return 1
+
+/obj/item/weapon/shockpaddles/emp_act(severity)
+ var/new_safety = rand(0, 1)
+ if(safety != new_safety)
+ safety = new_safety
+ if(safety)
+ make_announcement("beeps, \"Safety protocols enabled!\"", "notice")
+ playsound(get_turf(src), 'sound/machines/defib_safetyon.ogg', 50, 0)
+ else
+ make_announcement("beeps, \"Safety protocols disabled!\"", "warning")
+ playsound(get_turf(src), 'sound/machines/defib_safetyoff.ogg', 50, 0)
+ update_icon()
..()
- if(!cell && istype(A,/obj/item/weapon/cell))
- if(!user.unEquip(A)) return
- to_chat(user,"You jack \the [A] into \the [src]'s battery mount.")
- A.forceMove(src)
- src.cell = A
+/obj/item/weapon/shockpaddles/robot
+ name = "defibrillator paddles"
+ desc = "A pair of advanced shockpaddles powered by a robot's internal power cell, able to penetrate thick clothing."
+ chargecost = 50
+ combat = 1
+ icon_state = "defibpaddles0"
+ item_state = "defibpaddles0"
+ cooldowntime = (3 SECONDS)
- else if(istype(A,/obj/item/weapon/screwdriver))
- if(cell)
- to_chat(user,"You remove \the [cell] from \the [src].")
- if(user.r_hand && user.l_hand)
- cell.forceMove(get_turf(user))
- else
- cell.forceMove(user.put_in_hands(cell))
- cell = null
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- else
- to_chat(user,"The power source has already been removed!")
+/obj/item/weapon/shockpaddles/robot/check_charge(var/charge_amt)
+ if(isrobot(src.loc))
+ var/mob/living/silicon/robot/R = src.loc
+ return (R.cell && R.cell.check_charge(charge_amt))
-/obj/item/device/defib_kit/proc/statechange(var/new_state, var/pat)
- if(state == new_state) return //Let's just save ourselves some time
- state = new_state
- icon_state = "[initial(icon_state)][state]"
- var/turf/T = get_turf(src)
- var/state_words = ""
- switch(state)
- if(0)
- state_words = "It is currently closed."
- processing_objects -= src
+/obj/item/weapon/shockpaddles/robot/checked_use(var/charge_amt)
+ if(isrobot(src.loc))
+ var/mob/living/silicon/robot/R = src.loc
+ return (R.cell && R.cell.checked_use(charge_amt))
+
+/*
+ Shockpaddles that are linked to a base unit
+*/
+/obj/item/weapon/shockpaddles/linked
+ var/obj/item/device/defib_kit/base_unit
+
+/obj/item/weapon/shockpaddles/linked/New(newloc, obj/item/device/defib_kit/defib)
+ base_unit = defib
+ ..(newloc)
+
+/obj/item/weapon/shockpaddles/linked/Destroy()
+ if(base_unit)
+ //ensure the base unit's icon updates
+ if(base_unit.paddles == src)
+ base_unit.paddles = null
+ base_unit.update_icon()
+ base_unit = null
+ return ..()
+
+/obj/item/weapon/shockpaddles/linked/dropped(mob/user)
+ ..() //update twohanding
+ if(base_unit)
+ base_unit.reattach_paddles(user) //paddles attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
+
+/obj/item/weapon/shockpaddles/linked/check_charge(var/charge_amt)
+ return (base_unit.bcell && base_unit.bcell.check_charge(charge_amt))
+
+/obj/item/weapon/shockpaddles/linked/checked_use(var/charge_amt)
+ return (base_unit.bcell && base_unit.bcell.checked_use(charge_amt))
+
+/obj/item/weapon/shockpaddles/linked/make_announcement(var/message, var/msg_class)
+ base_unit.audible_message("\The [base_unit] [message]", "\The [base_unit] vibrates slightly.")
+
+/*
+ Standalone Shockpaddles
+*/
+
+/obj/item/weapon/shockpaddles/standalone
+ desc = "A pair of shockpaddles powered by an experimental miniaturized reactor" //Inspired by the advanced e-gun
+ var/fail_counter = 0
+
+/obj/item/weapon/shockpaddles/standalone/Destroy()
+ . = ..()
+ if(fail_counter)
+ processing_objects.Remove(src)
+
+/obj/item/weapon/shockpaddles/standalone/check_charge(var/charge_amt)
+ return 1
+
+/obj/item/weapon/shockpaddles/standalone/checked_use(var/charge_amt)
+ radiation_repository.radiate(src, charge_amt/12) //just a little bit of radiation. It's the price you pay for being powered by magic I guess
+ return 1
+
+/obj/item/weapon/shockpaddles/standalone/process()
+ if(fail_counter > 0)
+ radiation_repository.radiate(src, fail_counter--)
+ else
+ processing_objects.Remove(src)
+
+/obj/item/weapon/shockpaddles/standalone/emp_act(severity)
+ ..()
+ var/new_fail = 0
+ switch(severity)
if(1)
- state_words = "A green light is lit; it has charge."
- processing_objects |= src
+ new_fail = max(fail_counter, 20)
+ visible_message("\The [src]'s reactor overloads!")
if(2)
- state_words = "A yellow light is flashing: it's in the process of reviving a patient."
- T.visible_message("A yellow light starts flashing on \the [src].")
- playsound(T, 'sound/machines/chime.ogg', 50, 0)
- if(3)
- state_words = "A red light is flashing: the battery needs to be recharged."
- T.visible_message("A red light starts flashing on \the [src].")
- playsound(T, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ new_fail = max(fail_counter, 8)
+ if(ismob(loc))
+ to_chat(loc, "\The [src] feel pleasantly warm.")
- desc = "[initial(desc)] [state_words][pat ? " The pads are attached to [pat]." : ""]"
- update_icon()
+ if(new_fail && !fail_counter)
+ processing_objects.Add(src)
+ fail_counter = new_fail
-/obj/item/device/defib_kit/process()
- if(!state) //0 or null
- statechange(0)
- processing_objects -= src
- return
-
- //Patient moved too far
- if(patient && !(get_dist(src,patient) <= 1)) //You separated the kit and pads too far
- audible_message("There is a clatter as the [pad_name] are yanked off of [patient].")
- statechange(0)
- patient = null
- return
-
- //Battery died
- if(!cell || cell.charge < charge_cost)
- statechange(3,patient)
- return
-
- //A patient isn't being worked on, but we have one, so start
- if(patient && patient.stat == DEAD && state != 2)
- statechange(2)
- if(attempt_shock()) //Try to shock them, has timer and such
- patient.visible_message("[patient] convulses!")
- playsound(src.loc, 'sound/effects/sparks2.ogg', 75, 1)
- //Actual rezzing code
- if(prob(chance))
- if(!patient.client && patient.mind) //Don't force the dead person to come back if they don't want to.
- for(var/mob/observer/dead/ghost in player_list)
- if(ghost.mind == patient.mind)
- to_chat(ghost, "Someone is trying to \
- revive you. Return to your body if you want to be revived! \
- (Verbs -> Ghost -> Re-enter corpse). You have 15 seconds to do this!")
- sleep(15 SECONDS)
- break
-
- if(patient.client)
- patient.adjustOxyLoss(-20) //Look, blood stays oxygenated for quite some time, but I'm not recoding the entire oxy system
- patient.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
- dead_mob_list -= patient
- living_mob_list += patient
- patient.timeofdeath = null
- patient.visible_message("[patient]'s eyes open!")
- log_and_message_admins("[patient] was revived.")
- cell.charge -= charge_cost //Always charge the cost after any attempt, failed or not
- sleep(20) //Wait 2 seconds before next attempt
- statechange(1,patient) //Back to ready
-
-/obj/item/device/defib_kit/proc/attempt_shock()
- if(!patient || cell.charge < charge_cost)
- return
-
- var/zap_time = world.time + (7 SECONDS)
- var/o_patient_loc = patient.loc
- . = 1
-
- while(world.time < zap_time) //This is basically a custom do_after() call
- sleep(1)
-
- //Failed: We lost something important
- if(!patient || !cell || cell.charge < charge_cost)
- . = 0
- break
-
- //Failed: The locations aren't right
- if((o_patient_loc != patient.loc) || !(get_dist(src,patient) <= 1))
- . = 0
- break
-
- return
+/* From the Bay port, this doesn't seem to have a sprite.
+/obj/item/weapon/shockpaddles/standalone/traitor
+ name = "defibrillator paddles"
+ desc = "A pair of unusual looking paddles powered by an experimental miniaturized reactor. It possesses both the ability to penetrate armor and to deliver powerful shocks."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "defibpaddles0"
+ item_state = "defibpaddles0"
+ combat = 1
+ safety = 0
+ chargetime = (1 SECONDS)
+*/
+//FBP Defibs
/obj/item/device/defib_kit/jumper_kit
name = "jumper cable kit"
- desc = "This Morpheus-branded FBP defib kit is a semi-automated model. Apply cables, step back, wait."
- icon_state = "jumper_kit"
+ desc = "A device that delivers powerful shocks to detachable jumper cables that are capable of reviving full body prosthetics."
+ icon_state = "jumperunit"
+ item_state = "jumperunit"
+ paddles = /obj/item/weapon/shockpaddles/linked/jumper
+
+/obj/item/device/defib_kit/jumper_kit/loaded
+ bcell = /obj/item/weapon/cell/high
+
+/obj/item/weapon/shockpaddles/linked/jumper
+ name = "jumper cables"
+ icon_state = "jumperpaddles"
+ item_state = "jumperpaddles"
use_on_synthetic = 1
- pad_name = "jumper cables"
+
+/obj/item/weapon/shockpaddles/robot/jumper
+ name = "jumper cables"
+ desc = "A pair of advanced shockpaddles powered by a robot's internal power cell, able to penetrate thick clothing."
+ icon_state = "jumperpaddles0"
+ item_state = "jumperpaddles0"
+ use_on_synthetic = 1
+
+#undef DEFIB_TIME_LIMIT
+#undef DEFIB_TIME_LOSS
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 9b573a2cf1..dd10e80859 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -37,7 +37,7 @@
/obj/item/device/flashlight/Destroy()
if(power_use)
processing_objects -= src
- ..()
+ return ..()
/obj/item/device/flashlight/verb/toggle()
set name = "Toggle Flashlight Brightness"
@@ -73,7 +73,7 @@
if(brightness_level == "low")
set_light(brightness_on/2)
else if(brightness_level == "high")
- set_light(brightness_on*4)
+ set_light(brightness_on*1.5)
else
set_light(brightness_on)
@@ -109,6 +109,7 @@
user << "You flick the switch on [src], but nothing happens."
return 0
on = !on
+ playsound(src.loc, 'sound/weapons/empty.ogg', 15, 1, -3)
update_icon()
user.update_action_buttons()
return 1
@@ -448,10 +449,11 @@
/obj/item/device/flashlight/slime
gender = PLURAL
name = "glowing slime extract"
- desc = "A glowing ball of what appears to be amber."
+ desc = "A slimy ball that appears to be glowing from bioluminesence."
icon = 'icons/obj/lighting.dmi'
icon_state = "floor1" //not a slime extract sprite but... something close enough!
item_state = "slime"
+ light_color = "#FFF423"
w_class = ITEMSIZE_TINY
brightness_on = 6
on = 1 //Bio-luminesence has one setting, on.
diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm
new file mode 100644
index 0000000000..62cb9d9862
--- /dev/null
+++ b/code/game/objects/items/devices/geiger.dm
@@ -0,0 +1,53 @@
+#define RAD_LEVEL_LOW 5 //10 // Around the level at which radiation starts to become harmful
+#define RAD_LEVEL_MODERATE 15 //15
+#define RAD_LEVEL_HIGH 50 //50
+#define RAD_LEVEL_VERY_HIGH 100 //100
+
+//Geiger counter
+//Rewritten version of TG's geiger counter
+//I opted to show exact radiation levels
+
+/obj/item/device/geiger
+ name = "geiger counter"
+ desc = "A handheld device used for detecting and measuring radiation in an area."
+ icon_state = "geiger_off"
+ item_state = "multitool"
+ w_class = ITEMSIZE_SMALL
+ var/scanning = 0
+ var/radiation_count = 0
+
+/obj/item/device/geiger/New()
+ processing_objects |= src
+
+/obj/item/device/geiger/process()
+ if(!scanning)
+ return
+ radiation_count = radiation_repository.get_rads_at_turf(get_turf(src))
+ update_icon()
+
+/obj/item/device/geiger/examine(mob/user)
+ ..(user)
+ to_chat(user, "[scanning ? "ambient" : "stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.")
+
+/obj/item/device/geiger/attack_self(var/mob/user)
+ scanning = !scanning
+ update_icon()
+ to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] [src].")
+
+/obj/item/device/geiger/update_icon()
+ if(!scanning)
+ icon_state = "geiger_off"
+ return 1
+
+ switch(radiation_count)
+ if(null) icon_state = "geiger_on_1"
+ if(-INFINITY to RAD_LEVEL_LOW) icon_state = "geiger_on_1"
+ if(RAD_LEVEL_LOW + 1 to RAD_LEVEL_MODERATE) icon_state = "geiger_on_2"
+ if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH) icon_state = "geiger_on_3"
+ if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) icon_state = "geiger_on_4"
+ if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) icon_state = "geiger_on_5"
+
+#undef RAD_LEVEL_LOW
+#undef RAD_LEVEL_MODERATE
+#undef RAD_LEVEL_HIGH
+#undef RAD_LEVEL_VERY_HIGH
\ No newline at end of file
diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm
index 2f05a6f385..9ae5f62732 100644
--- a/code/game/objects/items/devices/hacktool.dm
+++ b/code/game/objects/items/devices/hacktool.dm
@@ -23,10 +23,10 @@
hack_state = null
return ..()
-/obj/item/device/multitool/hacktool/attackby(var/obj/W, var/mob/user)
+/obj/item/device/multitool/hacktool/attackby(var/obj/item/W, var/mob/user)
if(isscrewdriver(W))
in_hack_mode = !in_hack_mode
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src.loc, W.usesound, 50, 1)
else
..()
diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm
index 025196b218..ca7ace1a59 100644
--- a/code/game/objects/items/devices/modkit.dm
+++ b/code/game/objects/items/devices/modkit.dm
@@ -14,7 +14,7 @@
/obj/item/clothing/suit/space/void
)
-/obj/item/device/modkit/afterattack(obj/O, mob/user as mob, proximity)
+/obj/item/device/modkit/afterattack(obj/item/O, mob/user as mob, proximity)
if(!proximity)
return
@@ -47,7 +47,7 @@
user << "[O] must be safely placed on the ground for modification."
return
- playsound(user.loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src.loc, O.usesound, 100, 1)
user.visible_message("\The [user] opens \the [src] and modifies \the [O].","You open \the [src] and modify \the [O].")
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 85c680ca98..d79fc021db 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -22,6 +22,7 @@
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
var/obj/machinery/clonepod/connecting //same for cryopod linkage
var/obj/machinery/connectable //Used to connect machinery.
+ toolspeed = 1
/obj/item/device/multitool/attack_self(mob/user)
var/clear = alert("Do you want to clear the buffers on the [src]?",, "Yes", "No",)
@@ -30,4 +31,17 @@
connecting = null
connectable = null
else
- ..()
\ No newline at end of file
+ ..()
+
+/obj/item/device/multitool/cyborg
+ name = "multitool"
+ desc = "Optimised and stripped-down version of a regular multitool."
+ toolspeed = 0.5
+
+/obj/item/device/multitool/alien
+ name = "alien multitool"
+ desc = "An omni-technological interface."
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "multitool"
+ toolspeed = 0.1
+ origin_tech = list(TECH_MAGNETS = 5, TECH_ENGINEERING = 5)
\ No newline at end of file
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index e0e05ff467..8e1803ad40 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -27,7 +27,8 @@
//Will stop people throwing friend pAIs into the singularity so they can respawn
if(!isnull(pai))
pai.death(0)
- ..()
+ qdel_null(radio)
+ return ..()
/obj/item/device/paicard/attack_self(mob/user)
if (!in_range(src, user))
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 910d983e22..e4c1bb3f20 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -42,6 +42,7 @@
anchored = 1
mode = 1
src.visible_message("[user] attaches [src] to the cable!")
+ playsound(src, I.usesound, 50, 1)
return
else
user << "Device must be placed over an exposed cable to attach to it."
@@ -54,6 +55,7 @@
mode = 0
src.visible_message("[user] detaches [src] from the cable!")
set_light(0)
+ playsound(src, I.usesound, 50, 1)
icon_state = "powersink0"
return
diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm
index 7bec1014d7..e26b75486e 100644
--- a/code/game/objects/items/devices/radio/encryptionkey.dm
+++ b/code/game/objects/items/devices/radio/encryptionkey.dm
@@ -14,7 +14,7 @@
/obj/item/device/encryptionkey/attackby(obj/item/weapon/W as obj, mob/user as mob)
/obj/item/device/encryptionkey/syndicate
- icon_state = "cypherkey"
+ icon_state = "syn_cypherkey"
channels = list("Mercenary" = 1)
origin_tech = list(TECH_ILLEGAL = 3)
syndie = 1//Signifies that it de-crypts Syndicate transmissions
@@ -26,7 +26,7 @@
syndie = 1
/obj/item/device/encryptionkey/binary
- icon_state = "cypherkey"
+ icon_state = "bin_cypherkey"
translate_binary = 1
origin_tech = list(TECH_ILLEGAL = 3)
@@ -123,4 +123,5 @@
/obj/item/device/encryptionkey/ert
name = "\improper ERT radio encryption key"
+ icon_state = "cent_cypherkey"
channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Supply" = 1, "Service" = 1)
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index a56ea4fa98..5a8a73ee72 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -13,7 +13,7 @@
var/translate_hive = 0
var/obj/item/device/encryptionkey/keyslot1 = null
var/obj/item/device/encryptionkey/keyslot2 = null
- var/ks1type = /obj/item/device/encryptionkey
+ var/ks1type = null
var/ks2type = null
/obj/item/device/radio/headset/New()
@@ -317,6 +317,20 @@
item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hos
+/obj/item/device/radio/headset/mmi_radio
+ name = "brain-integrated radio"
+ desc = "MMIs and synthetic brains are often equipped with these."
+ icon = 'icons/obj/robot_component.dmi'
+ icon_state = "radio"
+ item_state = "headset"
+ var/mmiowner = null
+ var/radio_enabled = 1
+
+/obj/item/device/radio/headset/mmi_radio/receive_range(freq, level)
+ if (!radio_enabled || istype(src.loc.loc, /mob/living/silicon) || istype(src.loc.loc, /obj/item/organ/internal))
+ return -1 //Transciever Disabled.
+ return ..(freq, level, 1)
+
/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.set_machine(src)
@@ -348,6 +362,7 @@
recalculateChannels()
user << "You pop out the encryption keys in the headset!"
+ playsound(src, W.usesound, 50, 1)
else
user << "This headset doesn't have any encryption keys! How useless..."
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 8e9a72d203..9aa65bb54e 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -96,7 +96,7 @@
/obj/item/device/radio/intercom/Destroy()
processing_objects -= src
- ..()
+ return ..()
/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
src.add_fingerprint(user)
@@ -113,6 +113,7 @@
if(istype(W, /obj/item/weapon/screwdriver)) // Opening the intercom up.
wiresexposed = !wiresexposed
user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
+ playsound(src, W.usesound, 50, 1)
if(wiresexposed)
if(!on)
icon_state = "intercom-p_open"
@@ -123,7 +124,7 @@
return
if(wiresexposed && istype(W, /obj/item/weapon/wirecutters))
user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, W.usesound, 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
var/obj/structure/frame/A = new /obj/structure/frame(src.loc)
var/obj/item/weapon/circuitboard/M = circuit
diff --git a/code/game/objects/items/devices/radio/jammer.dm b/code/game/objects/items/devices/radio/jammer.dm
new file mode 100644
index 0000000000..680b5e2b37
--- /dev/null
+++ b/code/game/objects/items/devices/radio/jammer.dm
@@ -0,0 +1,113 @@
+var/global/list/active_radio_jammers = list()
+
+/proc/is_jammed(var/obj/radio)
+ var/turf/Tr = get_turf(radio)
+ if(!Tr) return 0 //Nullspace radios don't get jammed.
+
+ for(var/jammer in active_radio_jammers)
+ var/obj/item/device/radio_jammer/J = jammer
+ var/turf/Tj = get_turf(J)
+
+ if(J.on && Tj.z == Tr.z) //If we're on the same Z, it's worth checking.
+ var/dist = get_dist(Tj,Tr)
+ if(dist <= J.jam_range)
+ return list("jammer" = J, "distance" = dist)
+
+/obj/item/device/radio_jammer
+ name = "subspace jammer"
+ desc = "Primarily for blocking subspace communications, preventing the use of headsets, PDAs, and communicators."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "jammer0"
+ var/active_state = "jammer1"
+ var/last_overlay_percent = null // Stores overlay icon_state to avoid excessive recreation of overlays.
+
+ var/on = 0
+ var/jam_range = 7
+ var/obj/item/weapon/cell/device/weapon/power_source
+ var/tick_cost = 80 // Will last for roughly one minute, as process() ticks every 2 seconds.
+
+ origin_tech = list(TECH_ILLEGAL = 7, TECH_BLUESPACE = 5) //Such technology! Subspace jamming!
+
+/obj/item/device/radio_jammer/New()
+ power_source = new(src)
+ update_icon() // So it starts with the full overlay.
+
+/obj/item/device/radio_jammer/Destroy()
+ if(on)
+ turn_off()
+ qdel_null(power_source)
+ return ..()
+
+/obj/item/device/radio_jammer/proc/turn_off(mob/user)
+ if(user)
+ to_chat(user,"\The [src] deactivates.")
+ processing_objects.Remove(src)
+ active_radio_jammers -= src
+ on = FALSE
+ update_icon()
+
+/obj/item/device/radio_jammer/proc/turn_on(mob/user)
+ if(user)
+ to_chat(user,"\The [src] is now active.")
+ processing_objects.Add(src)
+ active_radio_jammers += src
+ on = TRUE
+ update_icon()
+
+/obj/item/device/radio_jammer/process()
+ if(!power_source || !power_source.check_charge(tick_cost))
+ var/mob/living/notify
+ if(isliving(loc))
+ notify = loc
+ turn_off(notify)
+ else
+ power_source.use(tick_cost)
+ update_icon()
+
+
+/obj/item/device/radio_jammer/attack_hand(mob/user)
+ if(user.get_inactive_hand() == src && power_source)
+ to_chat(user,"You eject \the [power_source] from \the [src].")
+ user.put_in_hands(power_source)
+ power_source = null
+ turn_off()
+ else
+ return ..()
+
+/obj/item/device/radio_jammer/attack_self(mob/user)
+ if(on)
+ turn_off(user)
+ else
+ if(power_source)
+ turn_on(user)
+ else
+ to_chat(user,"\The [src] has no power source!")
+
+/obj/item/device/radio_jammer/attackby(obj/W, mob/user)
+ if(istype(W,/obj/item/weapon/cell/device/weapon) && !power_source)
+ power_source = W
+ power_source.update_icon() //Why doesn't a cell do this already? :|
+ user.unEquip(power_source)
+ power_source.forceMove(src)
+ update_icon()
+ to_chat(user,"You insert \the [power_source] into \the [src].")
+
+/obj/item/device/radio_jammer/update_icon()
+ if(on)
+ icon_state = active_state
+ else
+ icon_state = initial(icon_state)
+
+ var/overlay_percent = 0
+ if(power_source)
+ overlay_percent = between(0, round( power_source.percent() , 25), 100)
+ else
+ overlay_percent = 0
+
+ // Only Cut() if we need to.
+ if(overlay_percent != last_overlay_percent)
+ overlays.Cut()
+ var/image/I = image(src.icon, src, "jammer_overlay_[overlay_percent]")
+ overlays += I
+ last_overlay_percent = overlay_percent
+
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 74d9a4b8ed..842fb09816 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -40,7 +40,7 @@ var/global/list/default_medbay_channels = list(
var/list/channels = list() //see communications.dm for full list. First channel is a "default" for :h
var/subspace_transmission = 0
var/syndie = 0//Holder to see if it's a syndicate encrypted radio
- var/centComm = 0//Holder to see if it's a CentComm encrypted radio
+ var/centComm = 0//Holder to see if it's a CentCom encrypted radio
flags = CONDUCT
slot_flags = SLOT_BELT
throw_speed = 2
@@ -362,6 +362,12 @@ var/global/list/default_medbay_channels = list(
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
+ var/list/jamming = is_jammed(src)
+ if(jamming)
+ var/distance = jamming["distance"]
+ to_chat(M,"\icon[src] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.")
+ return 0
+
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
@@ -503,6 +509,8 @@ var/global/list/default_medbay_channels = list(
return -1
if(!listening)
return -1
+ if(is_jammed(src))
+ return -1
if(!(0 in level))
var/turf/position = get_turf(src)
if(!position || !(position.z in level))
@@ -621,6 +629,7 @@ var/global/list/default_medbay_channels = list(
recalculateChannels()
user << "You pop out the encryption key in the radio!"
+ playsound(src, W.usesound, 50, 1)
else
user << "This radio doesn't have any encryption keys!"
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 5d883784aa..ccbbb5fea7 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -99,6 +99,8 @@ REAGENT SCANNER
if(M.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
user.show_message("[OX] | [TX] | [BU] | [BR]")
+ if(M.radiation)
+ user.show_message("Radiation detected.")
if(istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if(C.reagents.total_volume)
@@ -351,8 +353,8 @@ REAGENT SCANNER
/obj/item/device/slime_scanner
name = "slime scanner"
- icon_state = "adv_spectrometer"
- item_state = "analyzer"
+ icon_state = "xenobio"
+ item_state = "xenobio"
origin_tech = list(TECH_BIO = 1)
w_class = ITEMSIZE_SMALL
flags = CONDUCT
@@ -362,32 +364,38 @@ REAGENT SCANNER
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 20)
/obj/item/device/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob)
- if (!isslime(M))
+ if(!isslime(M))
user << "This device can only scan slimes!"
return
- var/mob/living/carbon/slime/T = M
+ var/mob/living/simple_animal/slime/S = M
user.show_message("Slime scan results:")
- user.show_message(text("[T.colour] [] slime", T.is_adult ? "adult" : "baby"))
- user.show_message(text("Nutrition: [T.nutrition]/[]", T.get_max_nutrition()))
- if (T.nutrition < T.get_starve_nutrition())
- user.show_message("Warning: slime is starving!")
- else if (T.nutrition < T.get_hunger_nutrition())
- user.show_message("Warning: slime is hungry")
- user.show_message("Electric change strength: [T.powerlevel]")
- user.show_message("Health: [T.health]")
- if (T.slime_mutation[4] == T.colour)
- user.show_message("This slime does not evolve any further")
- else
- if (T.slime_mutation[3] == T.slime_mutation[4])
- if (T.slime_mutation[2] == T.slime_mutation[1])
- user.show_message(text("Possible mutation: []", T.slime_mutation[3]))
- user.show_message("Genetic destability: [T.mutation_chance/2]% chance of mutation on splitting")
- else
- user.show_message(text("Possible mutations: [], [], [] (x2)", T.slime_mutation[1], T.slime_mutation[2], T.slime_mutation[3]))
- user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting")
- else
- user.show_message(text("Possible mutations: [], [], [], []", T.slime_mutation[1], T.slime_mutation[2], T.slime_mutation[3], T.slime_mutation[4]))
- user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting")
- if (T.cores > 1)
- user.show_message("Anomalious slime core amount detected")
- user.show_message("Growth progress: [T.amount_grown]/10")
+ user.show_message(text("[S.slime_color] [] slime", S.is_adult ? "adult" : "baby"))
+
+ user.show_message("Health: [S.health]")
+ user.show_message("Mutation Probability: [S.mutation_chance]")
+
+ var/list/mutations = list()
+ for(var/potential_color in S.slime_mutation)
+ var/mob/living/simple_animal/slime/slime = potential_color
+ mutations.Add(initial(slime.slime_color))
+
+ user.show_message("Potental to mutate into [english_list(mutations)] colors.")
+ user.show_message("Extract potential: [S.cores]")
+
+ user.show_message(text("Nutrition: [S.nutrition]/[]", S.get_max_nutrition()))
+ if (S.nutrition < S.get_starve_nutrition())
+ user.show_message("Warning: Subject is starving!")
+ else if (S.nutrition < S.get_hunger_nutrition())
+ user.show_message("Warning: Subject is hungry.")
+ user.show_message("Electric change strength: [S.power_charge]")
+
+ if(S.resentment)
+ user.show_message("Warning: Subject is harboring resentment.")
+ if(S.docile)
+ user.show_message("Subject has been pacified.")
+ if(S.rabid)
+ user.show_message("Subject is enraged and extremely dangerous!")
+ if(S.unity)
+ user.show_message("Subject is friendly to other slime colors.")
+
+ user.show_message("Growth progress: [S.amount_grown]/10")
diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm
index fb34bb0996..a2d6ce3341 100644
--- a/code/game/objects/items/devices/suit_cooling.dm
+++ b/code/game/objects/items/devices/suit_cooling.dm
@@ -138,6 +138,7 @@
else
cover_open = 1
user << "You unscrew the panel."
+ playsound(src, W.usesound, 50, 1)
updateicon()
return
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 2564b3eff0..791725c14b 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -416,7 +416,8 @@
/obj/item/device/tape/attackby(obj/item/I, mob/user, params)
if(ruined && istype(I, /obj/item/weapon/screwdriver))
to_chat(user, "You start winding the tape back in...")
- if(do_after(user, 120, target = src))
+ playsound(src, I.usesound, 50, 1)
+ if(do_after(user, 120 * I.toolspeed, target = src))
to_chat(user, "You wound the tape back in.")
fix()
return
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index 88b53bd342..35697914ee 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -169,7 +169,7 @@
valve_open = 0
- if(deleted(tank_one) || deleted(tank_two))
+ if(QDELETED(tank_one) || QDELETED(tank_two))
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
diff --git a/code/game/objects/items/devices/uplink_random_lists.dm b/code/game/objects/items/devices/uplink_random_lists.dm
index f3533c5a01..38605da018 100644
--- a/code/game/objects/items/devices/uplink_random_lists.dm
+++ b/code/game/objects/items/devices/uplink_random_lists.dm
@@ -57,7 +57,7 @@ var/datum/uplink_random_selection/all_uplink_selection = new/datum/uplink_random
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/mc9mm)
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/revolver)
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/a357)
- items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/heavysniper, 15, 0)
+ items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/heavysnipermerc, 15, 0)
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/sniperammo, 15, 0)
items += new/datum/uplink_random_item(/datum/uplink_item/item/grenades/emp, 50)
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/crossbow, 33)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index ebdd95791d..f113e5f153 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -208,6 +208,9 @@
O.job = "Cyborg"
+ for(var/datum/language/L in M.brainmob.languages)
+ O.add_language(L.name)
+
O.cell = chest.cell
O.cell.loc = O
W.loc = O//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 28179f7dbd..584d6dd105 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -12,7 +12,7 @@
/obj/item/borg/upgrade/proc/action(var/mob/living/silicon/robot/R)
if(R.stat == DEAD)
- usr << "The [src] will not function on a deceased robot."
+ to_chat(usr, "The [src] will not function on a deceased robot.")
return 1
return 0
@@ -66,7 +66,7 @@
/obj/item/borg/upgrade/restart/action(var/mob/living/silicon/robot/R)
if(R.health < 0)
- usr << "You have to repair the robot before using this module!"
+ to_chat(usr, "You have to repair the robot before using this module!")
return 0
if(!R.key)
@@ -110,8 +110,8 @@
if(..()) return 0
if(!R.module || !(type in R.module.supported_upgrades))
- R << "Upgrade mounting error! No suitable hardpoint detected!"
- usr << "There's no mounting point for the module!"
+ to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
+ to_chat(usr, "There's no mounting point for the module!")
return 0
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in R.module
@@ -120,12 +120,12 @@
if(!T)
T = locate() in R.module.modules
if(!T)
- usr << "This robot has had its taser removed!"
+ to_chat(usr, "This robot has had its taser removed!")
return 0
if(T.recharge_time <= 2)
- R << "Maximum cooling achieved for this hardpoint!"
- usr << "There's no room for another cooling unit!"
+ to_chat(R, "Maximum cooling achieved for this hardpoint!")
+ to_chat(usr, "There's no room for another cooling unit!")
return 0
else
@@ -135,7 +135,7 @@
/obj/item/borg/upgrade/jetpack
name = "mining robot jetpack"
- desc = "A carbon dioxide jetpack suitable for low-gravity mining operations."
+ desc = "A carbon dioxide jetpack suitable for low-gravity operations."
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
require_module = 1
@@ -143,21 +143,24 @@
/obj/item/borg/upgrade/jetpack/action(var/mob/living/silicon/robot/R)
if(..()) return 0
- if(!R.module || !(type in R.module.supported_upgrades))
- R << "Upgrade mounting error! No suitable hardpoint detected!"
- usr << "There's no mounting point for the module!"
- return 0
- else
+ var/obj/item/weapon/tank/jetpack/carbondioxide/T = locate() in R.module
+ if(!T)
+ T = locate() in R.module.contents
+ if(!T)
+ T = locate() in R.module.modules
+ if(!T)
R.module.modules += new/obj/item/weapon/tank/jetpack/carbondioxide
for(var/obj/item/weapon/tank/jetpack/carbondioxide in R.module.modules)
R.internals = src
- //R.icon_state="Miner+j"
return 1
-
+ if(T)
+ to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
+ to_chat(usr, "There's no mounting point for the module!")
+ return 0
/obj/item/borg/upgrade/syndicate/
- name = "illegal equipment module"
- desc = "Unlocks the hidden, deadlier functions of a robot"
+ name = "scrambled equipment module"
+ desc = "Unlocks new and often deadly module specific items of a robot"
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
require_module = 1
@@ -165,8 +168,8 @@
/obj/item/borg/upgrade/syndicate/action(var/mob/living/silicon/robot/R)
if(..()) return 0
- if(R.emagged == 1)
+ if(R.emag_items == 1)
return 0
- R.emagged = 1
+ R.emag_items = 1
return 1
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 15f3310322..54142ea35c 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -155,7 +155,7 @@
singular_name = "advanced trauma kit"
desc = "An advanced trauma kit for severe injuries."
icon_state = "traumakit"
- heal_brute = 0
+ heal_brute = 5
origin_tech = list(TECH_BIO = 1)
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -213,7 +213,7 @@
singular_name = "advanced burn kit"
desc = "An advanced treatment kit for severe burns."
icon_state = "burnkit"
- heal_burn = 0
+ heal_burn = 5
origin_tech = list(TECH_BIO = 1)
@@ -279,16 +279,25 @@
if(M == user && prob(75))
user.visible_message("\The [user] fumbles [src].", "You fumble [src].", "You hear something being wrapped.")
return
- var/obj/item/stack/medical/splint/S = split(1)
- if(S)
- if(affecting.apply_splint(S))
- S.forceMove(affecting)
- if (M != user)
+ if(ishuman(user))
+ var/obj/item/stack/medical/splint/S = split(1)
+ if(S)
+ if(affecting.apply_splint(S))
+ S.forceMove(affecting)
+ if (M != user)
+ user.visible_message("\The [user] finishes applying [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.")
+ else
+ user.visible_message("\The [user] successfully applies [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.")
+ return
+ S.dropInto(src.loc) //didn't get applied, so just drop it
+ if(isrobot(user))
+ var/obj/item/stack/medical/splint/B = src
+ if(B)
+ if(affecting.apply_splint(B))
+ B.forceMove(affecting)
user.visible_message("\The [user] finishes applying [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.")
- else
- user.visible_message("\The [user] successfully applies [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.")
- return
- S.dropInto(src.loc) //didn't get applied, so just drop it
+ B.use(1)
+ return
user.visible_message("\The [user] fails to apply [src].", "You fail to apply [src].", "You hear something being wrapped.")
return
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index d337d064e0..a670d7dd27 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -84,6 +84,22 @@
desc = "A piece of blue carpet. It is the same size as a normal floor tile!"
icon_state = "tile-bluecarpet"
+// TODO - Add descriptions to these
+/obj/item/stack/tile/carpet/bcarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/blucarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/turcarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/sblucarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/gaycarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/purcarpet
+ icon_state = "tile-carpet"
+/obj/item/stack/tile/carpet/oracarpet
+ icon_state = "tile-carpet"
+
/obj/item/stack/tile/floor
name = "floor tile"
singular_name = "floor tile"
@@ -96,37 +112,55 @@
throw_range = 20
flags = CONDUCT
-/obj/item/stack/tile/floor_red
+/obj/item/stack/tile/floor/red
name = "red floor tile"
singular_name = "red floor tile"
color = COLOR_RED_GRAY
icon_state = "tile_white"
-/obj/item/stack/tile/floor_steel
+// VOREStation Edit
+/obj/item/stack/tile/floor/techgrey
+ name = "grey techfloor tile"
+ singular_name = "grey techfloor tile"
+ icon_state = "techtile_grey"
+
+/obj/item/stack/tile/floor/techgrid
+ name = "grid techfloor tile"
+ singular_name = "grid techfloor tile"
+ icon_state = "techtile_grid"
+
+/obj/item/stack/tile/floor/steel_dirty
+ name = "steel floor tile"
+ singular_name = "steel floor tile"
+ icon_state = "tile_steel"
+ matter = list("plasteel" = SHEET_MATERIAL_AMOUNT / 4)
+// VOREStation Edit End
+
+/obj/item/stack/tile/floor/steel
name = "steel floor tile"
singular_name = "steel floor tile"
icon_state = "tile_steel"
matter = list("plasteel" = SHEET_MATERIAL_AMOUNT / 4)
-/obj/item/stack/tile/floor_white
+/obj/item/stack/tile/floor/white
name = "white floor tile"
singular_name = "white floor tile"
icon_state = "tile_white"
matter = list("plastic" = SHEET_MATERIAL_AMOUNT / 4)
-/obj/item/stack/tile/floor_yellow
+/obj/item/stack/tile/floor/yellow
name = "yellow floor tile"
singular_name = "yellow floor tile"
color = COLOR_BROWN
icon_state = "tile_white"
-/obj/item/stack/tile/floor_dark
+/obj/item/stack/tile/floor/dark
name = "dark floor tile"
singular_name = "dark floor tile"
icon_state = "fr_tile"
matter = list("plasteel" = SHEET_MATERIAL_AMOUNT / 4)
-/obj/item/stack/tile/floor_freezer
+/obj/item/stack/tile/floor/freezer
name = "freezer floor tile"
singular_name = "freezer floor tile"
icon_state = "tile_freezer"
@@ -151,4 +185,4 @@
throwforce = 1.0
throw_speed = 5
throw_range = 20
- flags = 0
\ No newline at end of file
+ flags = 0
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 51d79ed05b..385351da97 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -773,6 +773,7 @@
var/phrase = "I don't want to exist anymore!"
/obj/structure/plushie/attack_hand(mob/user)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(user.a_intent == I_HELP)
user.visible_message("\The [user] hugs [src]!","You hug [src]!")
else if (user.a_intent == I_HURT)
@@ -813,8 +814,11 @@
desc = "A very generic small plushie. It seems to not want to exist."
icon = 'icons/obj/toy.dmi'
icon_state = "nymphplushie"
+ var/last_message = 0
/obj/item/toy/plushie/attack_self(mob/user as mob)
+ if(world.time - last_message <= 1 SECOND)
+ return
if(user.a_intent == I_HELP)
user.visible_message("\The [user] hugs [src]!","You hug [src]!")
else if (user.a_intent == I_HURT)
@@ -823,6 +827,7 @@
user.visible_message("\The [user] attempts to strangle [src]!","You attempt to strangle [src]!")
else
user.visible_message("\The [user] pokes the [src].","You poke the [src].")
+ last_message = world.time
/obj/item/toy/plushie/nymph
name = "diona nymph plush"
diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm
index c5e6614de2..60a847a4d6 100755
--- a/code/game/objects/items/weapons/AI_modules.dm
+++ b/code/game/objects/items/weapons/AI_modules.dm
@@ -20,9 +20,9 @@ AI MODULES
origin_tech = list(TECH_DATA = 3)
var/datum/ai_laws/laws = null
-/obj/item/weapon/aiModule/proc/install(var/obj/machinery/computer/C)
- if (istype(C, /obj/machinery/computer/aiupload))
- var/obj/machinery/computer/aiupload/comp = C
+/obj/item/weapon/aiModule/proc/install(var/atom/movable/AM, var/mob/living/user)
+ if (istype(AM, /obj/machinery/computer/aiupload))
+ var/obj/machinery/computer/aiupload/comp = AM
if(comp.stat & NOPOWER)
usr << "The upload computer has no power!"
return
@@ -33,10 +33,6 @@ AI MODULES
usr << "You haven't selected an AI to transmit laws to!"
return
- if(ticker && ticker.mode && ticker.mode.name == "blob")
- usr << "Law uploads have been disabled by [using_map.company_name]!"
- return
-
if (comp.current.stat == 2 || comp.current.control_disabled == 1)
usr << "Upload failed. No signal is being detected from the AI."
else if (comp.current.see_in_dark == 0)
@@ -52,8 +48,8 @@ AI MODULES
usr << "Upload complete. The AI's laws have been modified."
- else if (istype(C, /obj/machinery/computer/borgupload))
- var/obj/machinery/computer/borgupload/comp = C
+ else if (istype(AM, /obj/machinery/computer/borgupload))
+ var/obj/machinery/computer/borgupload/comp = AM
if(comp.stat & NOPOWER)
usr << "The upload computer has no power!"
return
@@ -74,6 +70,31 @@ AI MODULES
comp.current.show_laws()
usr << "Upload complete. The robot's laws have been modified."
+ else if(istype(AM, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = AM
+ if(R.stat == DEAD)
+ to_chat(user, "Law Upload Error: Unit is nonfunctional.")
+ return
+ if(R.emagged)
+ to_chat(user, "Law Upload Error: Cannot obtain write access to laws.")
+ to_chat(R, "Law modification attempt detected. Blocking.")
+ return
+ if(R.connected_ai)
+ to_chat(user, "Law Upload Error: Unit is slaved to an AI.")
+ return
+
+ R.visible_message("\The [user] slides a law module into \the [R].")
+ to_chat(R, "Local law upload in progress.")
+ to_chat(user, "Uploading laws from board. This will take a moment...")
+ if(do_after(user, 10 SECONDS))
+ transmitInstructions(R, user)
+ to_chat(R, "These are your laws now:")
+ R.show_laws()
+ to_chat(user, "Law upload complete. Unit's laws have been modified.")
+ else
+ to_chat(user, "Law Upload Error: Law board was removed before upload was complete. Aborting.")
+ to_chat(R, "Law upload aborted.")
+
/obj/item/weapon/aiModule/proc/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
log_law_changes(target, sender)
@@ -109,7 +130,7 @@ AI MODULES
targetName = targName
desc = text("A 'safeguard' AI module: 'Safeguard []. Anyone threatening or attempting to harm [] is no longer to be considered a crew member, and is a threat which must be neutralized.'", targetName, targetName)
-/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C)
+/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!targetName)
usr << "No name detected on module, please enter one."
return 0
@@ -135,7 +156,7 @@ AI MODULES
targetName = targName
desc = text("A 'one crew member' AI module: 'Only [] is a crew member.'", targetName)
-/obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C)
+/obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!targetName)
usr << "No name detected on module, please enter one."
return 0
@@ -231,7 +252,7 @@ AI MODULES
target.add_supplied_law(lawpos, law)
lawchanges.Add("The law was '[newFreeFormLaw]'")
-/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C)
+/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
return 0
@@ -342,7 +363,7 @@ AI MODULES
target.add_inherent_law(law)
lawchanges.Add("The law is '[newFreeFormLaw]'")
-/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C)
+/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
return 0
@@ -371,7 +392,7 @@ AI MODULES
target.add_ion_law(law)
target.show_laws()
-/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C)
+/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C, var/mob/living/user)
if(!newFreeFormLaw)
usr << "No law detected on module, please create one."
return 0
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index 10a847b469..d404b5cd44 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -39,7 +39,7 @@ RSF
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
if (mode == 1)
mode = 2
- user << "Changed dispensing mode to 'Drinking Glass'"
+ user << "Changed dispensing mode to 'Drinking Glass:Pint'"
return
if (mode == 2)
mode = 3
@@ -82,7 +82,7 @@ RSF
product = new /obj/item/clothing/mask/smokable/cigarette()
used_energy = 10
if(2)
- product = new /obj/item/weapon/reagent_containers/food/drinks/glass2()
+ product = new /obj/item/weapon/reagent_containers/food/drinks/glass2/pint()
used_energy = 50
if(3)
product = new /obj/item/weapon/paper()
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index a5fe817011..3f00543008 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -256,7 +256,7 @@
/obj/item/weapon/card/id/centcom
name = "\improper CentCom. ID"
- desc = "An ID straight from Cent. Com."
+ desc = "An ID straight from Central Command."
icon_state = "centcom"
registered_name = "Central Command"
assignment = "General"
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index ee2d2f2c57..48ab1df6bb 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -279,12 +279,18 @@ CIGARETTE PACKETS ARE IN FANCY.DM
chem_volume = 15
max_smoketime = 300
smoketime = 300
+ var/nicotine_amt = 2
matchmes = "USER lights their NAME with their FLAME."
lightermes = "USER manages to light their NAME with FLAME."
zippomes = "With a flick of their wrist, USER lights their NAME with their FLAME."
weldermes = "USER casually lights the NAME with FLAME."
ignitermes = "USER fiddles with FLAME, and manages to light their NAME."
+/obj/item/clothing/mask/smokable/cigarette/New()
+ ..()
+ if(nicotine_amt)
+ reagents.add_reagent("nicotine", nicotine_amt)
+
/obj/item/clothing/mask/smokable/cigarette/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
@@ -332,6 +338,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
max_smoketime = 1500
smoketime = 1500
chem_volume = 20
+ nicotine_amt = 4
matchmes = "USER lights their NAME with their FLAME."
lightermes = "USER manages to offend their NAME by lighting it with FLAME."
zippomes = "With a flick of their wrist, USER lights their NAME with their FLAME."
@@ -342,6 +349,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
name = "\improper Cohiba Robusto cigar"
desc = "There's little more you could want from a cigar."
icon_state = "cigar2"
+ nicotine_amt = 7
/obj/item/clothing/mask/smokable/cigarette/cigar/havana
name = "premium Havanian cigar"
@@ -350,6 +358,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
max_smoketime = 7200
smoketime = 7200
chem_volume = 30
+ nicotine_amt = 10
/obj/item/weapon/cigbutt
name = "cigarette butt"
@@ -472,6 +481,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/flame/lighter/zippo
name = "\improper Zippo lighter"
desc = "The zippo."
+ icon = 'icons/obj/zippo.dmi'
icon_state = "zippo"
item_state = "zippo"
@@ -542,3 +552,61 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(location)
location.hotspot_expose(700, 5)
return
+
+//Here we add Zippo skins.
+
+/obj/item/weapon/flame/lighter/zippo/black
+ name = "\improper holy Zippo lighter"
+ desc = "Only in regards to Christianity, that is."
+ icon_state = "blackzippo"
+
+/obj/item/weapon/flame/lighter/zippo/blue
+ name = "\improper blue Zippo lighter"
+ icon_state = "bluezippo"
+
+/obj/item/weapon/flame/lighter/zippo/engraved
+ name = "\improper engraved Zippo lighter"
+ icon_state = "engravedzippo"
+ item_state = "zippo"
+
+/obj/item/weapon/flame/lighter/zippo/gold
+ name = "\improper golden Zippo lighter"
+ icon_state = "goldzippo"
+
+/obj/item/weapon/flame/lighter/zippo/moff
+ name = "\improper moth Zippo lighter"
+ desc = "Too cute to be a Tymisian."
+ icon_state = "moffzippo"
+
+/obj/item/weapon/flame/lighter/zippo/red
+ name = "\improper red Zippo lighter"
+ icon_state = "redzippo"
+
+/obj/item/weapon/flame/lighter/zippo/ironic
+ name = "\improper ironic Zippo lighter"
+ desc = "What a quiant idea."
+ icon_state = "ironiczippo"
+
+/obj/item/weapon/flame/lighter/zippo/capitalist
+ name = "\improper capitalist Zippo lighter"
+ desc = "Made of gold and obsidian, this is truly not worth however much you spent on it."
+ icon_state = "cappiezippo"
+
+/obj/item/weapon/flame/lighter/zippo/communist
+ name = "\improper communist Zippo lighter"
+ desc = "All you need to spark a revolution."
+ icon_state = "commiezippo"
+
+/obj/item/weapon/flame/lighter/zippo/royal
+ name = "\improper royal Zippo lighter"
+ desc = "An incredibly fancy lighter, gilded and covered in the color of royalty."
+ icon_state = "royalzippo"
+
+/obj/item/weapon/flame/lighter/zippo/gonzo
+ name = "\improper Gonzo Zippo lighter"
+ desc = "A lighter with the iconic Gonzo fist painted on it."
+ icon_state = "gonzozippo"
+
+/obj/item/weapon/flame/lighter/zippo/rainbow
+ name = "\improper rainbow Zippo lighter"
+ icon_state = "rainbowzippo"
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/circuitboards/computer/research.dm b/code/game/objects/items/weapons/circuitboards/computer/research.dm
index f49b80e6df..fa9ed16797 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/research.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/research.dm
@@ -8,6 +8,7 @@
/obj/item/weapon/circuitboard/rdconsole/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I,/obj/item/weapon/screwdriver))
+ playsound(src, I.usesound, 50, 1)
user.visible_message("\The [user] adjusts the jumper on \the [src]'s access protocol pins.", "You adjust the jumper on the access protocol pins.")
if(build_path == /obj/machinery/computer/rdconsole/core)
name = T_BOARD("RD Console - Robotics")
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/research.dm b/code/game/objects/items/weapons/circuitboards/machinery/research.dm
index 1e4fe2afd9..31e0d9c063 100644
--- a/code/game/objects/items/weapons/circuitboards/machinery/research.dm
+++ b/code/game/objects/items/weapons/circuitboards/machinery/research.dm
@@ -13,6 +13,7 @@ obj/item/weapon/circuitboard/rdserver
obj/item/weapon/circuitboard/rdserver/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I,/obj/item/weapon/screwdriver))
+ playsound(src, I.usesound, 50, 1)
user.visible_message("\The [user] adjusts the jumper on \the [src]'s access protocol pins.", "You adjust the jumper on the access protocol pins.")
if(build_path == /obj/machinery/r_n_d/server/core)
name = T_BOARD("RD Console - Robotics")
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
deleted file mode 100644
index 9099ff3bd1..0000000000
--- a/code/game/objects/items/weapons/dice.dm
+++ /dev/null
@@ -1,59 +0,0 @@
-/obj/item/weapon/dice
- name = "d6"
- desc = "A dice with six sides."
- icon = 'icons/obj/dice.dmi'
- icon_state = "d66"
- w_class = ITEMSIZE_TINY
- var/sides = 6
- attack_verb = list("diced")
-
-/obj/item/weapon/dice/New()
- icon_state = "[name][rand(1,sides)]"
-
-/obj/item/weapon/dice/d4
- name = "d4"
- desc = "A dice with four sides."
- icon_state = "d44"
- sides = 4
-
-/obj/item/weapon/dice/d8
- name = "d8"
- desc = "A dice with eight sides."
- icon_state = "d88"
- sides = 8
-
-/obj/item/weapon/dice/d10
- name = "d10"
- desc = "A dice with ten sides."
- icon_state = "d1010"
- sides = 10
-
-/obj/item/weapon/dice/d12
- name = "d12"
- desc = "A dice with twelve sides."
- icon_state = "d1212"
- sides = 12
-
-/obj/item/weapon/dice/d20
- name = "d20"
- desc = "A dice with twenty sides."
- icon_state = "d2020"
- sides = 20
-
-/obj/item/weapon/dice/d100
- name = "d100"
- desc = "A dice with ten sides. This one is for the tens digit."
- icon_state = "d10010"
- sides = 10
-
-/obj/item/weapon/dice/attack_self(mob/user as mob)
- var/result = rand(1, sides)
- var/comment = ""
- if(sides == 20 && result == 20)
- comment = "Nat 20!"
- else if(sides == 20 && result == 1)
- comment = "Ouch, bad luck."
- icon_state = "[name][result]"
- user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
- "You throw [src]. It lands on a [result]. [comment]", \
- "You hear [src] landing on a [result]. [comment]")
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 1a8cc97def..1e1565a2ae 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -28,6 +28,7 @@
if(istype(I, /obj/item/weapon/screwdriver))
open_panel = !open_panel
user << "You [open_panel ? "open" : "close"] the wire panel."
+ playsound(src, I.usesound, 50, 1)
else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler ))
wires.Interact(user)
else
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 3bcb68bcee..eba48464f0 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -107,7 +107,7 @@
spawn(0)
if(!src || !reagents.total_volume) return
- var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(src))
+ var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src))
var/turf/my_target
if(a <= the_targets.len)
my_target = the_targets[a]
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index c3f93a016f..649b5677ca 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -27,15 +27,10 @@
/obj/item/weapon/flamethrower/Destroy()
- if(weldtool)
- qdel(weldtool)
- if(igniter)
- qdel(igniter)
- if(ptank)
- qdel(ptank)
- ..()
- return
-
+ qdel_null(weldtool)
+ qdel_null(igniter)
+ qdel_null(ptank)
+ . = ..()
/obj/item/weapon/flamethrower/process()
if(!lit)
@@ -86,7 +81,7 @@
if(ptank)
ptank.loc = T
ptank = null
- PoolOrNew(/obj/item/stack/rods, T)
+ new /obj/item/stack/rods(T)
qdel(src)
return
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 0ec3dc13df..0eaf073cfa 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -19,6 +19,11 @@
New()
create_reagents(1000)
+ Destroy()
+ qdel_null(detonator)
+ qdel_null_list(beakers)
+ return ..()
+
attack_self(mob/user as mob)
if(!stage || stage==1)
if(detonator)
@@ -81,7 +86,7 @@
// user << "You need to add at least one beaker before locking the assembly."
user << "You lock the empty assembly."
name = "fake grenade"
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, W.usesound, 50, 1)
icon_state = initial(icon_state) +"_locked"
stage = 2
else if(stage == 2)
@@ -91,7 +96,7 @@
return
else
user << "You unlock the assembly."
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src.loc, W.usesound, 50, -3)
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
icon_state = initial(icon_state) + (detonator?"_ass":"")
stage = 1
diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/weapons/grenades/explosive.dm
index 62d13c3a2b..ccf8b89ee2 100644
--- a/code/game/objects/items/weapons/grenades/explosive.dm
+++ b/code/game/objects/items/weapons/grenades/explosive.dm
@@ -27,13 +27,17 @@
no_attack_log = 1
muzzle_type = null
+/obj/item/projectile/bullet/pellet/fragment/strong
+ damage = 15
+ armor_penetration = 20
+
/obj/item/weapon/grenade/explosive
name = "fragmentation grenade"
desc = "A fragmentation grenade, optimized for harming personnel without causing massive structural damage."
icon_state = "frggrenade"
item_state = "grenade"
- var/fragment_type = /obj/item/projectile/bullet/pellet/fragment
+ var/fragment_types = list(/obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment/strong)
var/num_fragments = 63 //total number of fragments produced by the grenade
var/explosion_size = 2 //size of the center explosion
@@ -48,29 +52,49 @@
if(!O) return
if(explosion_size)
- explosion(O, -1, -1, 2, round(explosion_size/2), 0)
+ on_explosion(O)
+ src.fragmentate(O, num_fragments, spread_range, fragment_types)
+ qdel(src)
- var/list/target_turfs = getcircle(O, spread_range)
- var/fragments_per_projectile = round(num_fragments/target_turfs.len)
- for(var/turf/T in target_turfs)
- var/obj/item/projectile/bullet/pellet/fragment/P = new (O)
+/obj/proc/fragmentate(var/turf/T=get_turf(src), var/fragment_number = 30, var/spreading_range = 5, var/list/fragtypes=list(/obj/item/projectile/bullet/pellet/fragment/))
+ set waitfor = 0
+ var/list/target_turfs = getcircle(T, spreading_range)
+ var/fragments_per_projectile = round(fragment_number/target_turfs.len)
+ for(var/turf/O in target_turfs)
+ sleep(0)
+ var/fragment_type = pickweight(fragtypes)
+ var/obj/item/projectile/bullet/pellet/fragment/P = new fragment_type(T)
P.pellets = fragments_per_projectile
P.shot_from = src.name
- P.launch(T)
-
- //var/cone = new /obj/item/weapon/caution/cone (T)
- //spawn(100) qdel(cone)
+ P.launch(O)
//Make sure to hit any mobs in the source turf
- for(var/mob/living/M in O)
+ for(var/mob/living/M in T)
//lying on a frag grenade while the grenade is on the ground causes you to absorb most of the shrapnel.
//you will most likely be dead, but others nearby will be spared the fragments that hit you instead.
if(M.lying && isturf(src.loc))
- P.attack_mob(M, 0, 0)
+ P.attack_mob(M, 0, 5)
+ else if(!M.lying && src.loc != get_turf(src)) //if it's not on the turf, it must be in the mob!
+ P.attack_mob(M, 0, 25) //you're holding a grenade, dude!
else
P.attack_mob(M, 0, 100) //otherwise, allow a decent amount of fragments to pass
- qdel(src)
+
+/obj/item/weapon/grenade/explosive/proc/on_explosion(var/turf/O)
+ if(explosion_size)
+ explosion(O, -1, -1, explosion_size, round(explosion_size/2), 0)
+
+
+/obj/item/weapon/grenade/explosive/frag
+ name = "fragmentation grenade"
+ desc = "A military fragmentation grenade, designed to explode in a deadly shower of fragments."
+ icon_state = "frag"
+ loadable = null
+
+ fragment_types = list(/obj/item/projectile/bullet/pellet/fragment)
+ num_fragments = 200 //total number of fragments produced by the grenade
+
+ //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index d02ccf2185..940029e735 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -91,6 +91,10 @@
M << "Your ears start to ring!"
M.update_icons()
+/obj/item/weapon/grenade/flashbang/Destroy()
+ walk(src, 0) // Because we might have called walk_away, we must stop the walk loop or BYOND keeps an internal reference to us forever.
+ return ..()
+
/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
desc = "Use of this weapon may constiute a war crime in your area, consult your local Colony Director."
name = "clusterbang"
diff --git a/code/game/objects/items/weapons/grenades/fragmentation.dm b/code/game/objects/items/weapons/grenades/fragmentation.dm
deleted file mode 100644
index 9f10e9b4d4..0000000000
--- a/code/game/objects/items/weapons/grenades/fragmentation.dm
+++ /dev/null
@@ -1,61 +0,0 @@
-//Fragmentation grenade projectile
-/obj/item/projectile/bullet/pellet/fragment
- damage = 15
- range_step = 2
-
- base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone
- spread_step = 20
-
- silenced = 1 //embedding messages are still produced so it's kind of weird when enabled.
- no_attack_log = 1
- muzzle_type = null
-
-/obj/item/weapon/grenade/frag
- name = "fragmentation grenade"
- desc = "A military fragmentation grenade, designed to explode in a deadly shower of fragments."
- icon_state = "frag"
- loadable = null
-
- var/num_fragments = 200 //total number of fragments produced by the grenade
- var/fragment_damage = 15
- var/damage_step = 2 //projectiles lose a fragment each time they travel this distance. Can be a non-integer.
- var/explosion_size = 2 //size of the center explosion
-
- //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
- var/spread_range = 7
-
-/obj/item/weapon/grenade/frag/prime()
- ..()
-
- var/turf/O = get_turf(src)
- if(!O) return
-
- if(explosion_size)
- explosion(O, -1, round(explosion_size/2), explosion_size, round(explosion_size/2), 0)
-
- var/list/target_turfs = getcircle(O, spread_range)
- var/fragments_per_projectile = round(num_fragments/target_turfs.len)
-
- for(var/turf/T in target_turfs)
- var/obj/item/projectile/bullet/pellet/fragment/P = new (O)
-
- P.damage = fragment_damage
- P.pellets = fragments_per_projectile
- P.range_step = damage_step
- P.shot_from = src.name
-
- P.launch(T)
-
- //var/cone = new /obj/item/weapon/caution/cone (T)
- //spawn(100) qdel(cone)
-
- //Make sure to hit any mobs in the source turf
- for(var/mob/living/M in O)
- //lying on a frag grenade while the grenade is on the ground causes you to absorb most of the shrapnel.
- //you will most likely be dead, but others nearby will be spared the fragments that hit you instead.
- if(M.lying && isturf(src.loc))
- P.attack_mob(M, 0, 0)
- else
- P.attack_mob(M, 0, 100) //otherwise, allow a decent amount of fragments to pass
-
- qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm
index d64627fcf3..2c89be0ac7 100644
--- a/code/game/objects/items/weapons/grenades/smokebomb.dm
+++ b/code/game/objects/items/weapons/grenades/smokebomb.dm
@@ -12,7 +12,7 @@
/obj/item/weapon/grenade/smokebomb/New()
..()
- src.smoke = PoolOrNew(/datum/effect/effect/system/smoke_spread/bad)
+ src.smoke = new /datum/effect/effect/system/smoke_spread/bad()
src.smoke.attach(src)
/obj/item/weapon/grenade/smokebomb/Destroy()
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
index 8e112d9655..f9cbc65b59 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
@@ -40,3 +40,22 @@
spawner_type = /mob/living/simple_animal/hostile/carp
deliveryamt = 5
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
+
+/obj/item/weapon/grenade/spawnergrenade/spider
+ name = "spider delivery grenade"
+ spawner_type = /mob/living/simple_animal/hostile/giant_spider/hunter
+ deliveryamt = 3
+ origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
+
+//Sometimes you just need a sudden influx of spiders.
+/obj/item/weapon/grenade/spawnergrenade/spider/briefcase
+ name = "briefcase"
+ desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional."
+ icon_state = "briefcase"
+ item_state = "briefcase"
+ flags = CONDUCT
+ force = 8.0
+ throw_speed = 1
+ throw_range = 4
+ w_class = ITEMSIZE_LARGE
+ deliveryamt = 6
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 1190d7f812..17bb6b84be 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -41,6 +41,8 @@
user << "You need to have a firm grip on [C] before you can put \the [src] on!"
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
+ if(user == target)
+ return 1
if(istype(user, /mob/living/silicon/robot))
if(user.Adjacent(target))
return 1
@@ -179,3 +181,84 @@ var/last_chew = 0
icon = 'icons/obj/bureaucracy.dmi'
breakouttime = 200
cuff_type = "duct tape"
+
+//Legcuffs. Not /really/ handcuffs, but its close enough.
+/obj/item/weapon/handcuffs/legcuffs
+ name = "legcuffs"
+ desc = "Use this to keep prisoners in line."
+ gender = PLURAL
+ icon = 'icons/obj/items.dmi'
+ icon_state = "handcuff"
+ flags = CONDUCT
+ throwforce = 0
+ w_class = ITEMSIZE_NORMAL
+ origin_tech = list(TECH_MATERIAL = 1)
+ breakouttime = 300 //Deciseconds = 30s = 0.5 minute
+ cuff_type = "legcuffs"
+ sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/handcuffs.dmi')
+ elastic = 0
+ cuff_sound = 'sound/weapons/handcuffs.ogg' //This shold work for now.
+
+/obj/item/weapon/handcuffs/legcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
+ if(!user.IsAdvancedToolUser())
+ return
+
+ if ((CLUMSY in user.mutations) && prob(50))
+ user << "Uh ... how do those things work?!"
+ place_legcuffs(user, user)
+ return
+
+ if(!C.handcuffed)
+ if (C == user)
+ place_legcuffs(user, user)
+ return
+
+ //check for an aggressive grab (or robutts)
+ if(can_place(C, user))
+ place_legcuffs(C, user)
+ else
+ user << "You need to have a firm grip on [C] before you can put \the [src] on!"
+
+/obj/item/weapon/handcuffs/legcuffs/proc/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
+ playsound(src.loc, cuff_sound, 30, 1, -2)
+
+ var/mob/living/carbon/human/H = target
+ if(!istype(H))
+ return 0
+
+ if (!H.has_organ_for_slot(slot_legcuffed))
+ user << "\The [H] needs at least two ankles before you can cuff them together!"
+ return 0
+
+ if(istype(H.shoes,/obj/item/clothing/shoes/magboots/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
+ user << "\The [src] won't fit around \the [H.shoes]!"
+ return 0
+
+ user.visible_message("\The [user] is attempting to put [cuff_type] on \the [H]!")
+
+ if(!do_after(user,30))
+ return 0
+
+ if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
+ return 0
+
+ H.attack_log += text("\[[time_stamp()]\] Has been legcuffed (attempt) by [user.name] ([user.ckey])")
+ user.attack_log += text("\[[time_stamp()]\] Attempted to legcuff [H.name] ([H.ckey])")
+ msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]")
+ feedback_add_details("legcuffs","H")
+
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(H)
+
+ user.visible_message("\The [user] has put [cuff_type] on \the [H]!")
+
+ // Apply cuffs.
+ var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
+ if(dispenser)
+ lcuffs = new(get_turf(user))
+ else
+ user.drop_from_inventory(lcuffs)
+ lcuffs.loc = target
+ target.legcuffed = lcuffs
+ target.update_inv_legcuffed()
+ return 1
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 6554e80f8b..806047ae37 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -52,7 +52,7 @@
/obj/item/weapon/implant/Destroy()
if(part)
part.implants.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/implant/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/implanter))
@@ -452,11 +452,11 @@ the implant may become unstable and either pre-maturely inject the subject or si
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
//give the syndies a bit of stealth
- a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm", "General")
+ a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm")
// a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm", "Security")
// a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm", "Medical")
else
- a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm", "General")
+ a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm")
// a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm", "Security")
// a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm", "Medical")
qdel(a)
@@ -464,13 +464,13 @@ the implant may become unstable and either pre-maturely inject the subject or si
if ("emp")
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
var/name = prob(50) ? t.name : pick(teleportlocs)
- a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm", "General")
+ a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm")
// a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm", "Security")
// a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm", "Medical")
qdel(a)
else
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
- a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm", "General")
+ a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
// a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm", "Security")
// a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm", "Medical")
qdel(a)
diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm
index 66080882be..44b33721cf 100644
--- a/code/game/objects/items/weapons/implants/implantchair.dm
+++ b/code/game/objects/items/weapons/implants/implantchair.dm
@@ -76,13 +76,14 @@
attackby(var/obj/item/weapon/G as obj, var/mob/user as mob)
if(istype(G, /obj/item/weapon/grab))
- if(!ismob(G:affecting))
+ var/obj/item/weapon/grab/grab = G
+ if(!ismob(grab.affecting))
return
- for(var/mob/living/carbon/slime/M in range(1,G:affecting))
- if(M.Victim == G:affecting)
- usr << "[G:affecting:name] will not fit into the [src.name] because they have a slime latched onto their head."
+ for(var/mob/living/simple_animal/slime/M in range(1,grab.affecting))
+ if(M.victim == grab.affecting)
+ usr << "[grab.affecting.name] will not fit into the [src.name] because they have a slime latched onto their head."
return
- var/mob/M = G:affecting
+ var/mob/M = grab.affecting
if(put_mob(M))
qdel(G)
src.updateUsrDialog()
diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm
index cf55cbd706..856e7a5d8b 100644
--- a/code/game/objects/items/weapons/implants/implantcircuits.dm
+++ b/code/game/objects/items/weapons/implants/implantcircuits.dm
@@ -1,5 +1,6 @@
/obj/item/weapon/implant/integrated_circuit
name = "electronic implant"
+ desc = "It's a case, for building very tiny electronics with."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "setup_implant"
var/obj/item/device/electronic_assembly/implant/IC = null
@@ -38,7 +39,10 @@
IC.examine(user)
/obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user)
- if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) )
+ if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) || istype(O, /obj/item/weapon/cell/device) )
IC.attackby(O, user)
else
- ..()
\ No newline at end of file
+ ..()
+
+/obj/item/weapon/implant/integrated_circuit/attack_self(mob/user)
+ IC.attack_self(user)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/improvised_components.dm b/code/game/objects/items/weapons/improvised_components.dm
index 9e6e05a807..105a76473f 100644
--- a/code/game/objects/items/weapons/improvised_components.dm
+++ b/code/game/objects/items/weapons/improvised_components.dm
@@ -9,6 +9,7 @@
/obj/item/weapon/material/butterflyconstruction/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/screwdriver))
user << "You finish the concealed blade weapon."
+ playsound(src, W.usesound, 50, 1)
new /obj/item/weapon/material/butterfly(user.loc, material.name)
qdel(src)
return
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index 6ea812ad3a..533f5b30aa 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -147,6 +147,47 @@
|
|
|
|
|