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