diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index 0a4ac519d9e..3b31e34b2f4 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -47,9 +47,9 @@
//End positions
#define COMPONENT_EXNAME_CHANGED 1
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom)
+#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
#define COMPONENT_ATOM_BLOCK_EXIT 1
-#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume)
@@ -106,9 +106,9 @@
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
#define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable)
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
+#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable)
#define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable)
#define COMPONENT_MOVABLE_BLOCK_UNCROSS 1
-#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable)
#define COMSIG_MOVABLE_BUMP "movable_bump" //from base of atom/movable/Bump(): (/atom)
#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum)
#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone)
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 2862010d316..c2e56d8338c 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -11,6 +11,7 @@
#define isconstruct(A) (istype(A, /mob/living/simple_animal/hostile/construct))
//Objects
+#define isitem(A) (istype(A, /obj/item))
#define ismecha(A) (istype(A, /obj/mecha))
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 9e8b9b9c3a6..58e3305a45b 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -7,6 +7,8 @@
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
+ if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
+ return
return
/obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby!
@@ -28,6 +30,8 @@
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user, def_zone)
+ SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user)
+ SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(flags & (NOBLUDGEON))
return 0
@@ -74,6 +78,8 @@
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
+ if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
+ return
if(flags & (NOBLUDGEON))
return
user.changeNext_move(CLICK_CD_MELEE)
diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm
new file mode 100644
index 00000000000..e9b6bb6e42a
--- /dev/null
+++ b/code/datums/components/squeak.dm
@@ -0,0 +1,88 @@
+// Squeak component ported over from tg
+
+/datum/component/squeak
+ var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1)
+ var/list/override_squeak_sounds
+ var/squeak_chance = 100
+ var/volume = 30
+
+ // This is so shoes don't squeak every step
+ var/steps = 0
+ var/step_delay = 1
+
+ // This is to stop squeak spam from inhand usage
+ var/last_use = 0
+ var/use_delay = 20
+
+/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override)
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+ RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak)
+ if(ismovableatom(parent))
+ RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak)
+ RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed)
+ RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
+ if(isitem(parent))
+ RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak)
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
+ if(istype(parent, /obj/item/clothing/shoes))
+ RegisterSignal(parent, COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
+
+ override_squeak_sounds = custom_sounds
+ if(chance_override)
+ squeak_chance = chance_override
+ if(volume_override)
+ volume = volume_override
+ if(isnum(step_delay_override))
+ step_delay = step_delay_override
+ if(isnum(use_delay_override))
+ use_delay = use_delay_override
+
+/datum/component/squeak/proc/play_squeak()
+ if(prob(squeak_chance))
+ if(!override_squeak_sounds)
+ playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1)
+ else
+ playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1)
+
+/datum/component/squeak/proc/step_squeak()
+ if(steps > step_delay)
+ play_squeak()
+ steps = 0
+ else
+ steps++
+
+/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
+ RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE)
+
+/datum/component/squeak/proc/on_drop(datum/source, mob/user)
+ UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING)
+
+/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM)
+ if(isitem(AM))
+ var/obj/item/I = AM
+ if(I.flags & ABSTRACT)
+ return
+ else if(istype(AM, /obj/item/projectile))
+ var/obj/item/projectile/P = AM
+ if(P.original != parent)
+ return
+ var/atom/current_parent = parent
+ if(isturf(current_parent.loc))
+ play_squeak()
+
+/datum/component/squeak/proc/use_squeak()
+ if(last_use + use_delay < world.time)
+ last_use = world.time
+ play_squeak()
+
+/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/holder, obj/machinery/disposal/source)
+ //We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted
+ RegisterSignal(holder, COMSIG_ATOM_DIR_CHANGE, .proc/holder_dir_change)
+
+/datum/component/squeak/proc/holder_dir_change(datum/source, old_dir, new_dir)
+ //If the dir changes it means we're going through a bend in the pipes, let's pretend we bumped the wall
+ if(old_dir != new_dir)
+ play_squeak()
\ No newline at end of file
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 5ca34ceb57e..4398229391b 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -150,9 +150,11 @@
//Hook for running code when a dir change occurs
/atom/proc/setDir(newdir)
+ SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
+ SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
if(does_attack_animation)
user.changeNext_move(CLICK_CD_MELEE)
add_attack_logs(user, src, "Punched with hulk powers")
@@ -305,8 +307,8 @@
/atom/proc/ex_act()
return
-/atom/proc/blob_act()
- return
+/atom/proc/blob_act(obj/structure/blob/B)
+ SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B)
/atom/proc/fire_act()
return
@@ -734,3 +736,14 @@ var/list/blood_splatter_icons = list()
if(!L)
return null
return L.AllowDrop() ? L : get_turf(L)
+
+/atom/Entered(atom/movable/AM, atom/oldLoc)
+ SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc)
+
+/atom/Exit(atom/movable/AM, atom/newLoc)
+ . = ..()
+ if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT)
+ return FALSE
+
+/atom/Exited(atom/movable/AM, atom/newLoc)
+ SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 36d3ce81ea2..a5d2366c46c 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -126,10 +126,11 @@
// Previously known as HasEntered()
// This is automatically called when something enters your square
/atom/movable/Crossed(atom/movable/AM)
- return
+ SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
if(A && yes)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
if(throwing)
throwing.hit_atom(A)
. = 1
@@ -213,6 +214,7 @@
//called when src is thrown into hit_atom
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
set waitfor = 0
+ SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(!QDELETED(hit_atom))
return hit_atom.hitby(src)
diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm
index 6d0084b9000..493c0da90c9 100644
--- a/code/game/gamemodes/blob/theblob.dm
+++ b/code/game/gamemodes/blob/theblob.dm
@@ -19,7 +19,7 @@
src.update_icon()
..(loc)
for(var/atom/A in loc)
- A.blob_act()
+ A.blob_act(src)
return
@@ -126,7 +126,7 @@
qdel(B)
for(var/atom/A in T)//Hit everything in the turf
- A.blob_act()
+ A.blob_act(src)
return 1
/obj/structure/blob/ex_act(severity)
@@ -141,7 +141,7 @@
/obj/structure/blob/Crossed(var/mob/living/L)
..()
- L.blob_act()
+ L.blob_act(src)
/obj/structure/blob/tesla_act(power)
..()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9af8b04580a..c1ff654c246 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -310,6 +310,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
return ..()
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
if(prob(final_block_chance))
owner.visible_message("[owner] blocks [attack_text] with [src]!")
return 1
@@ -324,6 +325,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
A.Remove(user)
if(flags & DROPDEL)
qdel(src)
+ SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
@@ -351,6 +353,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
+ SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
@@ -498,6 +501,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/throw_impact(atom/A)
if(A && !QDELETED(A))
+ SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A)
var/itempush = 1
if(w_class < WEIGHT_CLASS_BULKY)
itempush = 0 // too light to push anything
@@ -548,6 +552,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
return I == src
/obj/item/Crossed(atom/movable/AM)
+ . = ..()
if(prob(trip_chance) && ishuman(AM))
var/mob/living/carbon/human/H = AM
on_trip(H)
diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm
index 165a61baa75..1143954faef 100644
--- a/code/game/objects/items/weapons/clown_items.dm
+++ b/code/game/objects/items/weapons/clown_items.dm
@@ -18,35 +18,21 @@
hitsound = null
throwforce = 3
w_class = WEIGHT_CLASS_TINY
+ var/list/honk_sounds = list('sound/items/bikehorn.ogg' = 1)
throw_speed = 3
throw_range = 15
attack_verb = list("HONKED")
- var/spam_flag = 0
- var/honk_sound = 'sound/items/bikehorn.ogg'
- var/cooldowntime = 20
-
-/obj/item/bikehorn/attack(mob/living/carbon/M, mob/living/carbon/user)
- if(!spam_flag)
- playsound(loc, honk_sound, 50, 1, -1) //plays instead of tap.ogg!
- return ..()
-
-/obj/item/bikehorn/attack_self(mob/user)
- if(!spam_flag)
- spam_flag = 1
- playsound(src.loc, honk_sound, 50, 1)
- src.add_fingerprint(user)
- spawn(cooldowntime)
- spam_flag = 0
- return
+/obj/item/bikehorn/Initialize()
+ . = ..()
+ AddComponent(/datum/component/squeak, honk_sounds, 50)
/obj/item/bikehorn/airhorn
name = "air horn"
desc = "Damn son, where'd you find this?"
icon_state = "air_horn"
- honk_sound = 'sound/items/AirHorn2.ogg'
- cooldowntime = 50
origin_tech = "materials=4;engineering=4"
+ honk_sounds = list('sound/items/airhorn2.ogg' = 1)
/obj/item/bikehorn/golden
name = "golden bike horn"
@@ -63,11 +49,10 @@
..()
/obj/item/bikehorn/golden/proc/flip_mobs(mob/living/carbon/M, mob/user)
- if(!spam_flag)
- var/turf/T = get_turf(src)
- for(M in ohearers(7, T))
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(!H.can_hear())
- continue
- M.emote("flip")
+ var/turf/T = get_turf(src)
+ for(M in ohearers(7, T))
+ if(istype(M, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(!H.can_hear())
+ continue
+ M.emote("flip")
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index e657e9f8538..b48774eb046 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -507,10 +507,8 @@
icon = 'icons/obj/watercloset.dmi'
icon_state = "rubberducky"
item_state = "rubberducky"
+ honk_sounds = list('sound/items/squeaktoy.ogg' = 1)
attack_verb = list("quacked", "squeaked")
- honk_sound = 'sound/items/squeaktoy.ogg' //credit to DANMITCH3LL of freesound for this
-
-
/obj/structure/sink
name = "sink"
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index d7ed44c3c9a..7eb81c589e1 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -136,6 +136,7 @@
/turf/Entered(atom/movable/M, atom/OL, ignoreRest = 0)
+ ..()
if(ismob(M))
var/mob/O = M
if(!O.lastarea)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 1bf3ec01750..855c092f3ae 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -411,6 +411,7 @@ BLIND // can't see anything
..()
/obj/item/clothing/shoes/proc/step_action(var/mob/living/carbon/human/H) //squeek squeek
+ SEND_SIGNAL(src, COMSIG_SHOES_STEP_ACTION)
if(shoe_sound)
var/turf/T = get_turf(H)
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 76bef3e056b..62ced953ae2 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -69,15 +69,17 @@
item_state = "clown"
item_color = "clown"
flags_size = ONESIZEFITSALL
- var/honk_sound = 'sound/items/bikehorn.ogg'
+
+/obj/item/clothing/under/rank/clown/Initialize()
+ . = ..()
+ AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50)
/obj/item/clothing/under/rank/clown/hit_reaction()
- playsound(loc, honk_sound, 50, 1, -1)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
if(H.mind && H.mind.assigned_role == "Clown")
score_clownabuse++
- return 0
+ return ..()
/obj/item/clothing/under/rank/head_of_personnel
desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"."
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index ada24f85259..127656ece55 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -1490,9 +1490,9 @@
icon = 'icons/obj/custom_items.dmi'
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
righthand_file = 'icons/mob/inhands/fluff_righthand.dmi'
+ honk_sounds = list('sound/items/teri_horn.ogg' = 1)
icon_state = "teri_horn"
item_state = "teri_horn"
- honk_sound = 'sound/items/teri_horn.ogg'
/obj/item/clothing/accessory/medal/fluff/elo //V-Force_Bomber: E.L.O.
name = "distinguished medal of loyalty and excellence"
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 3ed45508b87..8d644b87c35 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -33,6 +33,10 @@
can_collar = 1
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
+/mob/living/simple_animal/mouse/Initialize()
+ . = ..()
+ AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg' = 1), 50)
+
/mob/living/simple_animal/mouse/handle_automated_speech()
..()
if(prob(speak_chance))
@@ -81,39 +85,15 @@
get_scooped(M)
..()
-//make mice fit under tables etc? this was hacky, and not working
-/*
-/mob/living/simple_animal/mouse/Move(var/dir)
-
- var/turf/target_turf = get_step(src,dir)
- //CanReachThrough(src.loc, target_turf, src)
- var/can_fit_under = 0
- if(target_turf.ZCanPass(get_turf(src),1))
- can_fit_under = 1
-
- ..(dir)
- if(can_fit_under)
- src.loc = target_turf
- for(var/d in cardinal)
- var/turf/O = get_step(T,d)
- //Simple pass check.
- if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles)
- open += O
- */
-
-///mob/living/simple_animal/mouse/restrained() //Hotfix to stop mice from doing things with MouseDrop
-// return 1
-
/mob/living/simple_animal/mouse/start_pulling(var/atom/movable/AM)//Prevents mouse from pulling things
to_chat(src, "You are too small to pull anything.")
return
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
- if( ishuman(AM) )
+ if(ishuman(AM))
if(!stat)
var/mob/M = AM
to_chat(M, "[bicon(src)] Squeek!")
- M << 'sound/effects/mousesqueek.ogg'
..()
/mob/living/simple_animal/mouse/death(gibbed)
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index f6474c4a16b..d0007ab7266 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -538,6 +538,7 @@
// note AM since can contain mobs or objs
for(var/atom/movable/AM in D)
AM.loc = src
+ SEND_SIGNAL(AM, COMSIG_MOVABLE_DISPOSING, src, D)
if(istype(AM, /mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
if(FAT in H.mutations) // is a human and fat?
diff --git a/paradise.dme b/paradise.dme
index 5e2ba112406..ad5d486914b 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -261,6 +261,7 @@
#include "code\datums\cache\powermonitor.dm"
#include "code\datums\components\_component.dm"
#include "code\datums\components\material_container.dm"
+#include "code\datums\components\squeak.dm"
#include "code\datums\diseases\_disease.dm"
#include "code\datums\diseases\_MobProcs.dm"
#include "code\datums\diseases\anxiety.dm"
diff --git a/sound/items/toysqueak1.ogg b/sound/items/toysqueak1.ogg
new file mode 100644
index 00000000000..e64a6fb179d
Binary files /dev/null and b/sound/items/toysqueak1.ogg differ
diff --git a/sound/items/toysqueak2.ogg b/sound/items/toysqueak2.ogg
new file mode 100644
index 00000000000..fddf1edfb92
Binary files /dev/null and b/sound/items/toysqueak2.ogg differ
diff --git a/sound/items/toysqueak3.ogg b/sound/items/toysqueak3.ogg
new file mode 100644
index 00000000000..338f4d8aa90
Binary files /dev/null and b/sound/items/toysqueak3.ogg differ