diff --git a/code/__DEFINES/~yogs_defines/flags.dm b/code/__DEFINES/~yogs_defines/flags.dm new file mode 100644 index 000000000000..0e9aa44ac625 --- /dev/null +++ b/code/__DEFINES/~yogs_defines/flags.dm @@ -0,0 +1,2 @@ +// Movement types +#define IMMOBILE 0 // We still use this for floor cluwnes \ No newline at end of file diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 5a83264b43d0..f6f26112402b 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1304,6 +1304,16 @@ var/msg = "[key_name(usr)] has removed [key_name(H)] from purrbation." // yogs - Yog Tickets message_admins(msg) admin_ticket_log(H, msg) + + else if(href_list["cluwneing"]) // yogs start -- adds cluwneify verb in VV + if(!check_rights(R_SPAWN)) return + var/mob/living/carbon/human/H = locate(href_list["cluwneing"]) + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + H.cluwneify() + message_admins("[key_name(usr)] has made [key_name(H)] into a Cluwne.") + return // yogs end else if(href_list["adjustDamage"] && href_list["mobToDamage"]) if(!check_rights(NONE)) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7815f85b9d64..fcaa50e4d0a5 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -101,6 +101,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/polymorph_all, /client/proc/show_tip, /client/proc/smite, + /client/proc/spawn_floor_cluwne, // Yogs /client/proc/rejuv_all, // yogs - Revive All /client/proc/admin_away )) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c85ec1af3ed7..e273e3357089 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -849,6 +849,7 @@ .["Make alien"] = "?_src_=vars;[HrefToken()];makealien=[REF(src)]" .["Make slime"] = "?_src_=vars;[HrefToken()];makeslime=[REF(src)]" .["Toggle Purrbation"] = "?_src_=vars;[HrefToken()];purrbation=[REF(src)]" + .["Make Cluwne"] = "?_src_=vars;[HrefToken()];cluwneing=[REF(src)]" // yogs -- make cluwne /mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user) //If they dragged themselves and we're currently aggressively grabbing them try to piggyback diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 65480cd113c7..d7c46a5fc974 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -8,6 +8,7 @@ vend_reply = "Thank you for using AutoDrobe!" products = list(/obj/item/clothing/suit/chickensuit = 1, /obj/item/clothing/head/chicken = 1, + /obj/item/clothing/mask/yogs/cluwne/happy_cluwne = 1, // yogs /obj/item/clothing/under/rank/blueclown = 1, /obj/item/clothing/under/rank/greenclown = 1, /obj/item/clothing/under/rank/yellowclown = 1, @@ -126,7 +127,7 @@ /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman/fake = 1, /obj/item/skub = 1,) - + refill_canister = /obj/item/vending_refill/autodrobe /obj/machinery/vending/autodrobe/all_access diff --git a/yogstation.dme b/yogstation.dme index d4f6d6dcb8b7..2254a760181f 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -101,6 +101,7 @@ #include "code\__DEFINES\~yogs_defines\access.dm" #include "code\__DEFINES\~yogs_defines\admin.dm" #include "code\__DEFINES\~yogs_defines\components.dm" +#include "code\__DEFINES\~yogs_defines\flags.dm" #include "code\__DEFINES\~yogs_defines\jobs.dm" #include "code\__DEFINES\~yogs_defines\keybindings.dm" #include "code\__DEFINES\~yogs_defines\preferences.dm" @@ -2659,16 +2660,19 @@ #include "yogstation\code\__HELPERS\_lists.dm" #include "yogstation\code\__HELPERS\mobs.dm" #include "yogstation\code\__HELPERS\unsorted.dm" +#include "yogstation\code\_DEFINES\DNA.dm" #include "yogstation\code\_onclick\click.dm" #include "yogstation\code\controllers\subsystem\input.dm" #include "yogstation\code\controllers\subsystem\mapping.dm" #include "yogstation\code\controllers\subsystem\yogs.dm" #include "yogstation\code\datums\mind.dm" +#include "yogstation\code\datums\mutations.dm" #include "yogstation\code\datums\shuttles.dm" #include "yogstation\code\datums\world_topic.dm" #include "yogstation\code\datums\components\crawl.dm" #include "yogstation\code\datums\components\daniel.dm" #include "yogstation\code\datums\components\uplink.dm" +#include "yogstation\code\datums\diseases\cluwnification.dm" #include "yogstation\code\datums\diseases\advance\symptoms\confusion.dm" #include "yogstation\code\datums\diseases\advance\symptoms\heal.dm" #include "yogstation\code\datums\ruins\free_miners.dm" @@ -2711,6 +2715,7 @@ #include "yogstation\code\modules\admin\verbs\adminhelp.dm" #include "yogstation\code\modules\admin\verbs\adminsay.dm" #include "yogstation\code\modules\admin\verbs\fix_air.dm" +#include "yogstation\code\modules\admin\verbs\spawnfloorcluwne.dm" #include "yogstation\code\modules\antagonists\_common\antag_datum.dm" #include "yogstation\code\modules\antagonists\abductor\equipment\abduction_outfits.dm" #include "yogstation\code\modules\antagonists\slaughter\slaughter.dm" @@ -2725,6 +2730,9 @@ #include "yogstation\code\modules\clothing\chameleon.dm" #include "yogstation\code\modules\clothing\clothing.dm" #include "yogstation\code\modules\clothing\donator.dm" +#include "yogstation\code\modules\clothing\mask.dm" +#include "yogstation\code\modules\clothing\shoe.dm" +#include "yogstation\code\modules\clothing\under.dm" #include "yogstation\code\modules\clothing\head\jobs.dm" #include "yogstation\code\modules\clothing\shoes\colour.dm" #include "yogstation\code\modules\clothing\shoes\miscellaneous.dm" @@ -2739,8 +2747,11 @@ #include "yogstation\code\modules\donor\borg_skins.dm" #include "yogstation\code\modules\donor\donor_items.dm" #include "yogstation\code\modules\events\bureaucratic_error.dm" +#include "yogstation\code\modules\events\dolphin_migration.dm" +#include "yogstation\code\modules\events\floorcluwne.dm" #include "yogstation\code\modules\events\ion_storm.dm" #include "yogstation\code\modules\events\weightless.dm" +#include "yogstation\code\modules\food_and_drinks\food\snacks_meat.dm" #include "yogstation\code\modules\jobs\job_types\captain.dm" #include "yogstation\code\modules\jobs\job_types\cargo_service.dm" #include "yogstation\code\modules\jobs\job_types\job.dm" @@ -2757,19 +2768,24 @@ #include "yogstation\code\modules\mob\mob.dm" #include "yogstation\code\modules\mob\say.dm" #include "yogstation\code\modules\mob\dead\new_player\new_player.dm" +#include "yogstation\code\modules\mob\living\carbon\life.dm" +#include "yogstation\code\modules\mob\living\carbon\reindex_screams.dm" #include "yogstation\code\modules\mob\living\carbon\human\life.dm" #include "yogstation\code\modules\mob\living\carbon\human\species_types\plantpeople.dm" #include "yogstation\code\modules\mob\living\silicon\silicon.dm" #include "yogstation\code\modules\mob\living\silicon\ai\ai.dm" #include "yogstation\code\modules\mob\living\silicon\ai\vox_sounds.dm" #include "yogstation\code\modules\mob\living\silicon\robot\robot.dm" +#include "yogstation\code\modules\mob\living\simple_animal\floor_cluwne.dm" #include "yogstation\code\modules\mob\living\simple_animal\hostile\megafauna\colossus.dm" +#include "yogstation\code\modules\mob\living\simple_animal\hostile\retaliate\dolphin.dm" #include "yogstation\code\modules\power\hugbox.dm" #include "yogstation\code\modules\power\lighting.dm" #include "yogstation\code\modules\power\validhunter.dm" #include "yogstation\code\modules\reagents\reagent_containers\hypospray.dm" #include "yogstation\code\modules\research\rdconsole.dm" #include "yogstation\code\modules\research\designs\stock_parts_designs.dm" +#include "yogstation\code\modules\spells\cluwnecurse.dm" #include "yogstation\code\modules\spells\spells.dm" #include "yogstation\code\modules\spells\spell_types\mime.dm" #include "yogstation\code\modules\uplink\uplink_item.dm" diff --git a/yogstation/code/_DEFINES/DNA.dm b/yogstation/code/_DEFINES/DNA.dm new file mode 100644 index 000000000000..22187fc98edc --- /dev/null +++ b/yogstation/code/_DEFINES/DNA.dm @@ -0,0 +1 @@ +#define CLUWNEMUT "Cluwne" \ No newline at end of file diff --git a/yogstation/code/datums/diseases/cluwnification.dm b/yogstation/code/datums/diseases/cluwnification.dm new file mode 100644 index 000000000000..0b83ee07cadd --- /dev/null +++ b/yogstation/code/datums/diseases/cluwnification.dm @@ -0,0 +1,61 @@ +/datum/disease/cluwnification + name = "Anomalous Clown Retrovirus" + form = "Infection" + max_stages = 5 + stage_prob = 2 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "A mix of nothing, Driest Martini and bleach" + cures = list("bleach", "nothing", "driestmartini") + agent = "Fury from the circus of hell itself." + viable_mobtypes = list(/mob/living/carbon/human) + desc = "Subject will become dizzy, confused and steadily more retarded before being turned into a cluwne!" + severity = DISEASE_SEVERITY_BIOHAZARD + +/datum/disease/cluwnification/stage_act() + ..() + switch(stage) + if(1) + if(prob(2)) + to_chat(affected_mob, "You feel a little silly.") + if(prob(2)) + to_chat(affected_mob, "Your head feels funny.") + if(2) + if(prob(2)) + to_chat(affected_mob, "You hear honking.") + playsound(affected_mob, 'sound/items/bikehorn.ogg', 30, FALSE) + if(prob(2)) + to_chat(affected_mob, "Your head starts to spin.") + affected_mob.confused += 5 + + if(3) + if(prob(5)) + to_chat(affected_mob, "Your mind starts to slip.") + affected_mob.set_drugginess(5) + if(prob(2)) + to_chat(affected_mob, "Your can feel your brain startng to break down.") + affected_mob.adjustBrainLoss(3) + affected_mob.updatehealth() + if(prob(5)) + to_chat(affected_mob, "Your head starts to spin.") + affected_mob.confused += 5 + if(4) + if(prob(10)) + to_chat(affected_mob, "OH GOD THE HONKING!!") + playsound(affected_mob, 'sound/items/bikehorn.ogg', 50, FALSE) + if(prob(10)) + to_chat(affected_mob, "Your brain feels like its being ripped apart.") + affected_mob.adjustBrainLoss(10) + affected_mob.updatehealth() + if(prob(15)) + affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) + if(prob(10)) + to_chat(affected_mob, "You fail to form any kind of coherent thought") + affected_mob.set_drugginess(10) + affected_mob.confused += 10 + if(5) + if(prob(30)) + if (!(affected_mob.dna.check_mutation(CLUWNEMUT))) + to_chat(affected_mob, "IT HURTS!!") + var/mob/living/carbon/human/H = affected_mob + H.cluwneify() \ No newline at end of file diff --git a/yogstation/code/datums/mutations.dm b/yogstation/code/datums/mutations.dm new file mode 100644 index 000000000000..9cc3235d4b66 --- /dev/null +++ b/yogstation/code/datums/mutations.dm @@ -0,0 +1,75 @@ +/datum/mutation/human/cluwne + + name = "Cluwne" + quality = NEGATIVE + dna_block = NON_SCANNABLE + text_gain_indication = "You feel like your brain is tearing itself apart." + +/datum/mutation/human/cluwne/on_acquiring(mob/living/carbon/human/owner) + if(..()) + return + owner.dna.add_mutation(CLOWNMUT) + owner.dna.add_mutation(EPILEPSY) + owner.setBrainLoss(200) + + var/mob/living/carbon/human/H = owner + + if(!istype(H.wear_mask, /obj/item/clothing/mask/yogs/cluwne)) + if(!H.doUnEquip(H.wear_mask)) + qdel(H.wear_mask) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/yogs/cluwne(H), SLOT_WEAR_MASK) + if(!istype(H.w_uniform, /obj/item/clothing/under/yogs/cluwne)) + if(!H.doUnEquip(H.w_uniform)) + qdel(H.w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/under/yogs/cluwne(H), SLOT_W_UNIFORM) + if(!istype(H.shoes, /obj/item/clothing/shoes/yogs/cluwne)) + if(!H.doUnEquip(H.shoes)) + qdel(H.shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/yogs/cluwne(H), SLOT_SHOES) + + owner.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(owner), SLOT_GLOVES) // this is purely for cosmetic purposes incase they aren't wearing anything in that slot + owner.equip_to_slot_or_del(new /obj/item/storage/backpack/clown(owner), SLOT_BACK) // ditto + +/datum/mutation/human/cluwne/on_life(mob/living/carbon/human/owner) + if((prob(15) && owner.IsUnconscious())) + owner.setBrainLoss(200) // there I changed it to setBrainLoss + switch(rand(1, 6)) + if(1) + owner.say("HONK") + if(2 to 5) + owner.emote("scream") + if(6) + owner.Stun(1) + owner.Knockdown(20) + owner.Jitter(500) + +/datum/mutation/human/cluwne/on_losing(mob/living/carbon/human/owner) + owner.adjust_fire_stacks(1) + owner.IgniteMob() + owner.dna.add_mutation(CLUWNEMUT) + +/mob/living/carbon/human/proc/cluwneify() + dna.add_mutation(CLUWNEMUT) + emote("scream") + regenerate_icons() + visible_message("[src]'s body glows green, the glow dissipating only to leave behind a cluwne formerly known as [src]!", \ + "Your brain feels like it's being torn apart, and after a short while, you notice that you've become a cluwne!") + flash_act() + +/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner) + if(prob(10) && owner.stat == CONSCIOUS) + owner.Stun(20) + switch(rand(1, 3)) + if(1) + owner.emote("twitch") + if(2 to 3) + owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") + var/x_offset_old = owner.pixel_x + var/y_offset_old = owner.pixel_y + var/x_offset = owner.pixel_x + rand(-2,2) + var/y_offset = owner.pixel_y + rand(-1,1) + animate(owner, pixel_x = x_offset, pixel_y = y_offset, time = 1) + animate(owner, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1) + +/datum/mutation/human/hulk + species_allowed = list() diff --git a/yogstation/code/game/area/Space_Station_13_areas.dm b/yogstation/code/game/area/Space_Station_13_areas.dm index 31d8e11a1dad..a3afd3ac5c1a 100644 --- a/yogstation/code/game/area/Space_Station_13_areas.dm +++ b/yogstation/code/game/area/Space_Station_13_areas.dm @@ -8,4 +8,15 @@ /area/clerk name = "Clerks office" - icon_state = "cafeteria" \ No newline at end of file + icon_state = "cafeteria" + +/area/maintenance + ambientsounds = list('sound/ambience/ambimaint1.ogg', + 'sound/ambience/ambimaint2.ogg', + 'sound/ambience/ambimaint3.ogg', + 'sound/ambience/ambimaint4.ogg', + 'sound/ambience/ambimaint5.ogg', + 'sound/voice/lowHiss2.ogg', //Xeno Breathing Hisses, Hahahaha I'm not even sorry. + 'sound/voice/lowHiss3.ogg', + 'sound/voice/lowHiss4.ogg', + 'yogstation/sound/misc/honk_echo_distant.ogg') \ No newline at end of file diff --git a/yogstation/code/modules/admin/verbs/spawnfloorcluwne.dm b/yogstation/code/modules/admin/verbs/spawnfloorcluwne.dm new file mode 100644 index 000000000000..92f574fb496a --- /dev/null +++ b/yogstation/code/modules/admin/verbs/spawnfloorcluwne.dm @@ -0,0 +1,19 @@ +/client/proc/spawn_floor_cluwne() + set category = "Fun" + set name = "Unleash Floor Cluwne" + set desc = "Pick a specific target or just let it select randomly and spawn the floor cluwne mob on the station. Be warned: spawning more than one may cause issues!" + var/target + + if(!check_rights(R_FUN)) + return + + var/turf/T = get_turf(usr) + target = input("Any specific target in mind? Please note only live, non cluwned, human targets are valid.", "Target", target) as null|anything in GLOB.player_list + if(target && ishuman(target)) + var/mob/living/carbon/human/H = target + var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T) + FC.Acquire_Victim(H) + else + new /mob/living/simple_animal/hostile/floor_cluwne(T) + log_admin("[key_name(usr)] spawned floor cluwne.") + message_admins("[key_name(usr)] spawned floor cluwne.") \ No newline at end of file diff --git a/yogstation/code/modules/clothing/clothing.dm b/yogstation/code/modules/clothing/clothing.dm index 415017a41479..4959e99df907 100644 --- a/yogstation/code/modules/clothing/clothing.dm +++ b/yogstation/code/modules/clothing/clothing.dm @@ -22,6 +22,9 @@ alternate_worn_icon = 'yogstation/icons/mob/mask.dmi' icon = 'yogstation/icons/obj/clothing/masks.dmi' +/obj/item + var/list/alternate_screams = list() + /obj/item/clothing/shoes/yogs alternate_worn_icon = 'yogstation/icons/mob/feet.dmi' icon = 'yogstation/icons/obj/clothing/shoes.dmi' diff --git a/yogstation/code/modules/clothing/mask.dm b/yogstation/code/modules/clothing/mask.dm new file mode 100644 index 000000000000..3f35eafa5dbc --- /dev/null +++ b/yogstation/code/modules/clothing/mask.dm @@ -0,0 +1,58 @@ +#define CLUWNEDOWN 50 + +/obj/item/clothing/mask/yogs/cluwne + name = "clown wig and mask" + desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask." + flags_cover = MASKCOVERSEYES + icon_state = "cluwne" + item_state = "cluwne" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + flags_1 = MASKINTERNALS + item_flags = ABSTRACT | NODROP | DROPDEL + flags_inv = HIDEEARS|HIDEEYES + +/obj/item/clothing/mask/yogs/cluwne/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == SLOT_WEAR_MASK) + var/mob/living/carbon/human/H = user + H.dna.add_mutation(CLUWNEMUT) + return + +/obj/item/clothing/mask/yogs/cluwne/happy_cluwne + name = "Happy Cluwne Mask" + desc = "The mask of a poor cluwne that has been scrubbed of its curse by the Nanotrasen supernatural machinations division. Guaranteed to be %99 curse free and %99.9 not haunted. " + flags_1 = MASKINTERNALS + alternate_screams = list('yogstation/sound/voice/cluwnelaugh1.ogg','yogstation/sound/voice/cluwnelaugh2.ogg','yogstation/sound/voice/cluwnelaugh3.ogg') + var/can_cluwne = TRUE + +/obj/item/clothing/mask/yogs/cluwne/happy_cluwne/equipped(mob/user, slot) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(slot == SLOT_WEAR_MASK) + if(prob(1) && can_cluwne) // Its %99 curse free! + log_admin("[key_name(H)] was made into a cluwne by [src]") + message_admins("[key_name(H)] got cluwned by [src]") + to_chat(H, "The masks straps suddenly tighten to your face and your thoughts are erased by a horrible green light!") + H.dropItemToGround(src) + H.cluwneify() + qdel(src) + else if(prob(0.1) && can_cluwne) //And %99.9 free form being haunted by vengeful jester-like entites. + var/turf/T = get_turf(src) + var/mob/living/simple_animal/hostile/floor_cluwne/S = new(T) + S.Acquire_Victim(user) + log_admin("[key_name(user)] summoned a floor cluwne using the [src]") + message_admins("[key_name(user)] summoned a floor cluwne using the [src]") + to_chat(H, "The mask suddenly slips off your face and... slides under the floor?") + to_chat(H, "...dneirf uoy ot gnoleb ton seod tahT") + qdel(src) + else if(can_cluwne) + can_cluwne = FALSE + addtimer(CALLBACK(src, .proc/re_cluwne), CLUWNEDOWN) + +/obj/item/clothing/mask/yogs/cluwne/happy_cluwne/proc/re_cluwne() + if(!can_cluwne) + can_cluwne = TRUE + +#undef CLUWNEDOWN \ No newline at end of file diff --git a/yogstation/code/modules/clothing/shoe.dm b/yogstation/code/modules/clothing/shoe.dm new file mode 100644 index 000000000000..b20d57e0b8d3 --- /dev/null +++ b/yogstation/code/modules/clothing/shoe.dm @@ -0,0 +1,26 @@ +/obj/item/clothing/shoes/yogs/cluwne + desc = "The prankster's standard-issue clowning shoes. Damn, they're huge!" + name = "clown shoes" + icon_state = "cluwne" + item_state = "cluwne" + item_color = "cluwne" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + item_flags = NODROP | DROPDEL + slowdown = SHOES_SLOWDOWN+1 + var/footstep = 1 + pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown + +/obj/item/clothing/shoes/yogs/cluwne/step_action() + if(footstep > 1) + playsound(src, "clownstep", 50, 1) + footstep = 0 + else + footstep++ + +/obj/item/clothing/shoes/yogs/cluwne/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == SLOT_SHOES) + var/mob/living/carbon/human/H = user + H.dna.add_mutation(CLUWNEMUT) + return \ No newline at end of file diff --git a/yogstation/code/modules/clothing/under.dm b/yogstation/code/modules/clothing/under.dm new file mode 100644 index 000000000000..aa5d22b90e05 --- /dev/null +++ b/yogstation/code/modules/clothing/under.dm @@ -0,0 +1,18 @@ +/obj/item/clothing/under/yogs/cluwne + name = "clown suit" + desc = "'HONK!'" + alternate_screams = list('yogstation/sound/voice/cluwnelaugh1.ogg','yogstation/sound/voice/cluwnelaugh2.ogg','yogstation/sound/voice/cluwnelaugh3.ogg') + icon_state = "cluwne" + item_state = "cluwne" + item_color = "cluwne" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + item_flags = NODROP | DROPDEL + can_adjust = 0 + +/obj/item/clothing/under/yogs/cluwne/equipped(mob/living/carbon/user, slot) + if(!ishuman(user)) + return + if(slot == SLOT_W_UNIFORM) + var/mob/living/carbon/human/H = user + H.dna.add_mutation(CLUWNEMUT) + return ..() \ No newline at end of file diff --git a/yogstation/code/modules/events/floorcluwne.dm b/yogstation/code/modules/events/floorcluwne.dm new file mode 100644 index 000000000000..0147179c579c --- /dev/null +++ b/yogstation/code/modules/events/floorcluwne.dm @@ -0,0 +1,27 @@ +/datum/round_event_control/floor_cluwne + name = "Floor Cluwne" + typepath = /datum/round_event/floor_cluwne + max_occurrences = 1 + min_players = 20 + + +/datum/round_event/floor_cluwne/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines) + if(QDELETED(temp_vent)) + continue + if(is_station_level(temp_vent.loc.z) && !temp_vent.welded) + var/datum/pipeline/temp_vent_parent = temp_vent.parents[1] + if(temp_vent_parent.other_atmosmch.len > 20) + vents += temp_vent + + if(!vents.len) + message_admins("No valid spawn locations found, aborting...") + return MAP_ERROR + + var/turf/T = get_turf(pick(vents.len)) + var/mob/living/simple_animal/hostile/floor_cluwne/S = new(T) + playsound(S, 'yogstation/sound/misc/bikehorn_creepy.ogg', 50, 1, -1) + message_admins("A floor cluwne has been spawned at [COORD(T)][ADMIN_JMP(T)]") + log_game("A floor cluwne has been spawned at [COORD(T)]") + return SUCCESSFUL_SPAWN \ No newline at end of file diff --git a/yogstation/code/modules/mob/living/carbon/life.dm b/yogstation/code/modules/mob/living/carbon/life.dm new file mode 100644 index 000000000000..5480643c5eb2 --- /dev/null +++ b/yogstation/code/modules/mob/living/carbon/life.dm @@ -0,0 +1,4 @@ +/mob/living/carbon/handle_brain_damage() + for(var/T in get_traumas()) + var/datum/brain_trauma/BT = T + BT.on_life() \ No newline at end of file diff --git a/yogstation/code/modules/mob/living/carbon/reindex_screams.dm b/yogstation/code/modules/mob/living/carbon/reindex_screams.dm new file mode 100644 index 000000000000..7f5d625f621e --- /dev/null +++ b/yogstation/code/modules/mob/living/carbon/reindex_screams.dm @@ -0,0 +1,45 @@ +/mob/living + var/list/alternate_screams + +/mob/living/carbon/proc/reindex_screams() + clear_screams() + if(head) + add_screams(head.alternate_screams) + if(wear_mask) + add_screams(wear_mask.alternate_screams) + if(back) + add_screams(back.alternate_screams) + +/mob/living/carbon/human/reindex_screams() + ..() + //More slots in humans. + if(ears) + add_screams(ears.alternate_screams) + if(wear_suit) + add_screams(wear_suit.alternate_screams) + if(w_uniform) + add_screams(w_uniform.alternate_screams) + if(glasses) + add_screams(glasses.alternate_screams) + if(gloves) + add_screams(gloves.alternate_screams) + if(shoes) + add_screams(shoes.alternate_screams) + if(belt) + add_screams(belt.alternate_screams) + if(s_store) + add_screams(s_store.alternate_screams) + if(wear_id) + add_screams(wear_id.alternate_screams) + +//Note that the following two are for /mob/living, while the above two are for /carbon and /human +/mob/living/proc/add_screams(var/list/screams) + LAZYINITLIST(alternate_screams) + if(!screams || screams.len == 0) + return + for(var/S in screams) + LAZYADD(alternate_screams, S) + +/mob/living/proc/clear_screams() + LAZYINITLIST(alternate_screams) + LAZYCLEARLIST(alternate_screams) \ No newline at end of file diff --git a/yogstation/code/modules/mob/living/emote.dm b/yogstation/code/modules/mob/living/emote.dm new file mode 100644 index 000000000000..8d73833f5ad4 --- /dev/null +++ b/yogstation/code/modules/mob/living/emote.dm @@ -0,0 +1,3 @@ + LAZYINITLIST(user.alternate_screams) + if(LAZYLEN(user.alternate_screams)) + sound = pick(user.alternate_screams) \ No newline at end of file diff --git a/yogstation/code/modules/mob/living/simple_animal/floor_cluwne.dm b/yogstation/code/modules/mob/living/simple_animal/floor_cluwne.dm new file mode 100644 index 000000000000..69d914277680 --- /dev/null +++ b/yogstation/code/modules/mob/living/simple_animal/floor_cluwne.dm @@ -0,0 +1,438 @@ +GLOBAL_VAR_INIT(floor_cluwnes, 0) + +#define STAGE_HAUNT 1 +#define STAGE_SPOOK 2 +#define STAGE_TORMENT 3 +#define STAGE_ATTACK 4 +#define MANIFEST_DELAY 9 + +/mob/living/simple_animal/hostile/floor_cluwne + name = "???" + desc = "...." + icon = 'yogstation/icons/obj/clothing/masks.dmi' + icon_state = "cluwne" + icon_living = "cluwne" + icon_gib = "clown_gib" + maxHealth = 250 + health = 250 + speed = -1 + attacktext = "attacks" + attack_sound = 'sound/items/bikehorn.ogg' + del_on_death = TRUE + pass_flags = PASSTABLE | PASSGRILLE | PASSMOB | LETPASSTHROW | PASSGLASS | PASSBLOB//it's practically a ghost when unmanifested (under the floor) + loot = list(/obj/item/clothing/mask/yogs/cluwne) + wander = FALSE + minimum_distance = 2 + move_to_delay = 1 + environment_smash = FALSE + lose_patience_timeout = FALSE + pixel_y = 8 + pressure_resistance = 200 + minbodytemp = 0 + maxbodytemp = 1500 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + var/mob/living/carbon/human/current_victim + var/manifested = FALSE + var/switch_stage = 60 + var/stage = STAGE_HAUNT + var/interest = 0 + var/target_area + var/invalid_area_typecache = list(/area/space, /area/lavaland, /area/centcom, /area/reebe, /area/shuttle/syndicate) + var/eating = FALSE + var/obj/effect/dummy/floorcluwne_orbit/poi + + +/mob/living/simple_animal/hostile/floor_cluwne/Initialize() + . = ..() + access_card = new /obj/item/card/id(src) + access_card.access = get_all_accesses()//THERE IS NO ESCAPE + access_card.item_flags |= NODROP + invalid_area_typecache = typecacheof(invalid_area_typecache) + Manifest() + if(!current_victim) + Acquire_Victim() + poi = new /obj/effect/dummy/floorcluwne_orbit(src) + +/mob/living/simple_animal/hostile/floor_cluwne/Destroy() + QDEL_NULL(poi) + return ..() + + +/mob/living/simple_animal/hostile/floor_cluwne/attack_hand(mob/living/carbon/human/M) + ..() + playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) + + +/mob/living/simple_animal/hostile/floor_cluwne/CanPass(atom/A, turf/target) + return TRUE + + +/mob/living/simple_animal/hostile/floor_cluwne/Life() + do_jitter_animation(1000) + pixel_y = 8 + + if(is_type_in_typecache(get_area(src.loc), invalid_area_typecache) || !is_station_level(z)) + var/area = pick(GLOB.teleportlocs) + var/area/tp = GLOB.teleportlocs[area] + forceMove(pick(get_area_turfs(tp.type))) + + if(!current_victim) + Acquire_Victim() + + if(stage && !manifested) + On_Stage() + + if(stage == STAGE_ATTACK) + playsound(src, 'yogstation/sound/misc/cluwne_breathing.ogg', 75, 1) + + if(eating) + return + + var/turf/T = get_turf(current_victim) + if(prob(5))//checks roughly every 20 ticks + if(current_victim.stat == DEAD || current_victim.dna.check_mutation(CLUWNEMUT) || is_type_in_typecache(get_area(T), invalid_area_typecache) || !is_station_level(current_victim.z)) + Acquire_Victim() + + if(get_dist(src, current_victim) > 9 && !manifested && !is_type_in_typecache(get_area(T), invalid_area_typecache))//if cluwne gets stuck he just teleports + do_teleport(src, T) + + interest++ + if(interest >= switch_stage * 4) + stage = STAGE_ATTACK + + else if(interest >= switch_stage * 2) + stage = STAGE_TORMENT + + else if(interest >= switch_stage) + stage = STAGE_SPOOK + + else if(interest < switch_stage) + stage = STAGE_HAUNT + + ..() + +/mob/living/simple_animal/hostile/floor_cluwne/Goto(target, delay, minimum_distance) + if(!manifested && !is_type_in_typecache(get_area(current_victim.loc), invalid_area_typecache) && is_station_level(current_victim.z)) + walk_to(src, target, minimum_distance, delay) + else + walk_to(src,0) + + +/mob/living/simple_animal/hostile/floor_cluwne/FindTarget() + return current_victim + + +/mob/living/simple_animal/hostile/floor_cluwne/CanAttack(atom/the_target)//you will not escape + return TRUE + + +/mob/living/simple_animal/hostile/floor_cluwne/AttackingTarget() + return + + +/mob/living/simple_animal/hostile/floor_cluwne/LoseTarget() + return + + +/mob/living/simple_animal/hostile/floor_cluwne/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)//prevents runtimes with machine fuckery + return FALSE + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Acquire_Victim(specific) + for(var/I in GLOB.player_list)//better than a potential recursive loop + var/mob/living/carbon/human/H = pick(GLOB.player_list)//so the check is fair + + if(specific) + H = specific + if(H.stat != DEAD && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(get_area(H.loc), invalid_area_typecache) && is_station_level(H.z)) + return target = current_victim + + if(H && ishuman(H) && H.stat != DEAD && H != current_victim && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(get_area(H.loc), invalid_area_typecache) && is_station_level(H.z)) + current_victim = H + interest = 0 + stage = STAGE_HAUNT + return target = current_victim + + message_admins("floor Cluwne was deleted due to a lack of valid targets, if this was a manually targeted instance please re-evaluate your choice.") + qdel(src) + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Manifest()//handles disappearing and appearance anim + if(manifested) + movement_type = IMMOBILE + new /obj/effect/temp_visual/fcluwne_manifest(src.loc) + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Appear), MANIFEST_DELAY) + + else + layer = GAME_PLANE + invisibility = INVISIBILITY_MAXIMUM + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + density = FALSE + movement_type = FLYING + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Appear()//handled in a seperate proc so floor cluwne doesn't appear before the animation finishes + layer = LYING_MOB_LAYER + invisibility = FALSE + mouse_opacity = MOUSE_OPACITY_OPAQUE + density = TRUE + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Reset_View(screens, colour, mob/living/carbon/human/H) + if(screens) + for(var/whole_screen in screens) + animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING) + if(colour && H) + H.client.color = colour + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/On_Stage() + var/mob/living/carbon/human/H = current_victim + switch(stage) + + if(STAGE_HAUNT) + + if(prob(5)) + H.blur_eyes(1) + + if(prob(5)) + H.playsound_local(src,'yogstation/sound/voice/cluwnelaugh2_reversed.ogg', 1) + + if(prob(5)) + H.playsound_local(src,'yogstation/sound/misc/bikehorn_creepy.ogg', 5) + + if(prob(3)) + var/obj/item/I = locate() in orange(H, 8) + if(I && !I.anchored) + I.throw_at(H, 4, 3) + to_chat(H, "What threw that?") + + if(STAGE_SPOOK) + + if(prob(4)) + var/turf/T = get_turf(H) + T.handle_slip(H, 20) + to_chat(H, "The floor shifts underneath you!") + + if(prob(5)) + H.playsound_local(src,'yogstation/sound/voice/cluwnelaugh2.ogg', 2) + + if(prob(5)) + H.playsound_local(src,'yogstation/sound/voice/cluwnelaugh2_reversed.ogg', 2) + + if(prob(5)) + H.playsound_local(src,'yogstation/sound/misc/bikehorn_creepy.ogg', 10) + to_chat(H, "knoh") + + if(prob(5)) + var/obj/item/I = locate() in orange(H, 8) + if(I && !I.anchored) + I.throw_at(H, 4, 3) + to_chat(H, "What threw that?") + + if(prob(2)) + to_chat(H, "yalp ot tnaw I") + Appear() + manifested = FALSE + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 1) + if(current_victim.hud_used)//yay skewium + var/list/screens = list(current_victim.hud_used.plane_masters["[GAME_PLANE]"], current_victim.hud_used.plane_masters["[LIGHTING_PLANE]"]) + var/matrix/skew = matrix() + var/intensity = 8 + skew.set_skew(rand(-intensity,intensity), rand(-intensity,intensity)) + var/matrix/newmatrix = skew + + for(var/whole_screen in screens) + animate(whole_screen, transform = newmatrix, time = 5, easing = QUAD_EASING, loop = -1) + animate(transform = -newmatrix, time = 5, easing = QUAD_EASING) + + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Reset_View, screens), 10) + + if(STAGE_TORMENT) + + if(prob(5)) + var/turf/T = get_turf(H) + T.handle_slip(H, 20) + to_chat(H, "The floor shifts underneath you!") + + if(prob(3)) + playsound(src,pick('sound/spookoween/scary_horn.ogg', 'sound/spookoween/scary_horn2.ogg', 'sound/spookoween/scary_horn3.ogg'), 30, 1) + + if(prob(3)) + playsound(src,'yogstation/sound/voice/cluwnelaugh1.ogg', 30, 1) + + if(prob(3)) + playsound(src,'yogstation/sound/voice/cluwnelaugh2_reversed.ogg', 30, 1) + + if(prob(5)) + playsound(src,'yogstation/sound/misc/bikehorn_creepy.ogg', 30, 1) + + if(prob(4)) + for(var/obj/item/I in orange(H, 8)) + if(I && !I.anchored) + I.throw_at(H, 4, 3) + to_chat(H, "What the hell?!") + + if(prob(2)) + to_chat(H, "Something feels very wrong...") + H.playsound_local(src,'sound/hallucinations/behind_you1.ogg', 25) + H.flash_act() + + if(prob(2)) + to_chat(H, "!?REHTOMKNOH eht esiarp uoy oD") + to_chat(H, "Something grabs your foot!") + H.playsound_local(src,'sound/hallucinations/i_see_you1.ogg', 25) + H.Stun(20) + + if(prob(3)) + to_chat(H, "KNOH ?od nottub siht seod tahW") + for(var/turf/open/O in range(src, 6)) + O.MakeSlippery(TURF_WET_WATER, 10) + playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1) + + if(prob(1)) + to_chat(H, "WHAT THE FUCK IS THAT?!") + to_chat(H, ".KNOH !nuf hcum os si uoy htiw gniyalP .KNOH KNOH KNOH") + H.playsound_local(src,'sound/hallucinations/im_here1.ogg', 25) + H.reagents.add_reagent("mindbreaker", 3) + H.reagents.add_reagent("laughter", 5) + H.reagents.add_reagent("mercury", 3) + Appear() + manifested = FALSE + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 2) + for(var/obj/machinery/light/L in range(H, 8)) + L.flicker() + + if(STAGE_ATTACK) + + if(!eating) + for(var/I in getline(src,H)) + var/turf/T = I + if(T.density) + forceMove(H.loc) + for(var/obj/structure/O in T) + if(O.density || istype(O, /obj/machinery/door/airlock)) + forceMove(H.loc) + + manifested = TRUE + Manifest() + to_chat(H, "You feel the floor closing in on your feet!") + H.Knockdown(300) + H.emote("scream") + H.adjustBruteLoss(10) + if(!eating) + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Grab, H), 50) + for(var/turf/open/O in range(src, 6)) + O.MakeSlippery(TURF_WET_LUBE, 20) + playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1) + + eating = TRUE + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Grab(mob/living/carbon/human/H) + to_chat(H, "You feel a cold, gloved hand clamp down on your ankle!") + for(var/I in 1 to get_dist(src, H)) + + if(do_after(src, 10, target = H)) + step_towards(H, src) + playsound(H, pick('yogstation/sound/effects/bodyscrape-01.ogg', 'yogstation/sound/effects/bodyscrape-02.ogg'), 20, 1, -4) + H.emote("scream") + if(prob(25)) + playsound(src, pick('yogstation/sound/voice/cluwnelaugh1.ogg', 'yogstation/sound/voice/cluwnelaugh2.ogg', 'yogstation/sound/voice/cluwnelaugh3.ogg'), 50, 1) + + if(get_dist(src,H) <= 1) + visible_message("[src] begins dragging [H] under the floor!") + + if(do_after(src, 50, target = H) && eating) + H.become_blind() + H.layer = GAME_PLANE + H.invisibility = INVISIBILITY_MAXIMUM + H.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + H.density = FALSE + H.anchored = TRUE + addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Kill, H), 100) + visible_message("[src] pulls [H] under!") + to_chat(H, "[src] drags you underneath the floor!") + else + eating = FALSE + + manifested = FALSE + Manifest() + + +/mob/living/simple_animal/hostile/floor_cluwne/proc/Kill(mob/living/carbon/human/H) + playsound(H, 'yogstation/sound/effects/cluwne_feast.ogg', 100, 0, -4) + var/old_color = H.client.color + var/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0) + var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0) + H.client.color = pure_red + + animate(H.client,color = red_splash, time = 10, easing = SINE_EASING|EASE_OUT) + for(var/turf/T in orange(H, 4)) + H.add_splatter_floor(T) + if(do_after(src, 50, target = H)) + + H.unequip_everything()//more runtime prevention + + if(prob(75)) + for(var/I in H.bodyparts) + var/obj/item/bodypart/O = I + if(O.name == "head")//irksome runtimes + O.dismember() + continue + O.drop_organs() + O.dismember() + else + H.cluwneify() + H.adjustBruteLoss(30) + H.adjustBrainLoss(100) + + H.cure_blind() + H.layer = initial(H.layer) + H.invisibility = initial(H.invisibility) + H.mouse_opacity = initial(H.mouse_opacity) + H.density = initial(H.density) + H.anchored = initial(H.anchored) + Reset_View(FALSE, old_color, H) + + eating = FALSE + switch_stage = switch_stage * 0.75 //he gets faster after each feast + for(var/mob/M in GLOB.player_list) + M.playsound_local(get_turf(M), 'yogstation/sound/misc/honk_echo_distant.ogg', 50, 1, pressure_affected = FALSE) + + interest = 0 + stage = STAGE_HAUNT + Acquire_Victim() + +//manifestation animation +/obj/effect/temp_visual/fcluwne_manifest + icon = 'yogstation/icons/turf/floors.dmi' + icon_state = "fcluwne_manifest" + layer = TURF_LAYER + duration = INFINITY + randomdir = FALSE + + +/obj/effect/temp_visual/fcluwne_manifest/Initialize() + . = ..() + playsound(src, 'yogstation/sound/misc/floor_cluwne_emerge.ogg', 100, 1) + +/obj/effect/dummy/floorcluwne_orbit + name = "floor cluwne" + desc = "If you have this, tell a coder or admin!" + +/obj/effect/dummy/floorcluwne_orbit/Initialize() + . = ..() + GLOB.floor_cluwnes += 1 + name += " ([GLOB.floor_cluwnes])" + GLOB.poi_list += src + +/obj/effect/dummy/floorcluwne_orbit/Destroy() + . = ..() + GLOB.poi_list -= src + +#undef STAGE_HAUNT +#undef STAGE_SPOOK +#undef STAGE_TORMENT +#undef STAGE_ATTACK +#undef MANIFEST_DELAY diff --git a/yogstation/code/modules/spells/cluwnecurse.dm b/yogstation/code/modules/spells/cluwnecurse.dm new file mode 100644 index 000000000000..8ad6f3fb8b1b --- /dev/null +++ b/yogstation/code/modules/spells/cluwnecurse.dm @@ -0,0 +1,40 @@ +/obj/effect/proc_holder/spell/targeted/cluwnecurse + name = "Curse of the Cluwne" + desc = "This spell dooms the fate of any unlucky soul to the live of a pitiful cluwne, a terrible creature that is hunted for fun." + school = "transmutation" + charge_type = "recharge" + charge_max = 600 + charge_counter = 0 + clothes_req = 1 + stat_allowed = 0 + invocation = "CLU WO'NIS CA'TE'BEST'IS MAXIMUS!" + invocation_type = "shout" + range = 3 + cooldown_min = 75 + selection_type = "range" + var/list/compatible_mobs = list(/mob/living/carbon/human) + action_icon = 'yogstation/icons/mob/actions.dmi' + action_icon_state = "cluwne" + +/obj/effect/proc_holder/spell/targeted/cluwnecurse/cast(list/targets, mob/user = usr) + if(!targets.len) + to_chat(user, "No target found in range.") + return + var/mob/living/carbon/target = targets[1] + if(!(target.type in compatible_mobs)) + to_chat(user, "You are unable to curse [target]!") + return + if(!(target in oview(range))) + to_chat(user, "They are too far away!") + return + var/mob/living/carbon/human/H = target + H.cluwneify() + +/datum/spellbook_entry/cluwnecurse + name = "Cluwne Curse" + spell_type = /obj/effect/proc_holder/spell/targeted/cluwnecurse + +/datum/action/spell_action/New(Target) + ..() + var/obj/effect/proc_holder/spell/S = Target + icon_icon = S.action_icon \ No newline at end of file diff --git a/yogstation/icons/mob/actions.dmi b/yogstation/icons/mob/actions.dmi new file mode 100644 index 000000000000..3832ec10186d Binary files /dev/null and b/yogstation/icons/mob/actions.dmi differ diff --git a/yogstation/icons/mob/feet.dmi b/yogstation/icons/mob/feet.dmi index 50e1e11506fd..1281fd7e00a0 100644 Binary files a/yogstation/icons/mob/feet.dmi and b/yogstation/icons/mob/feet.dmi differ diff --git a/yogstation/icons/mob/mask.dmi b/yogstation/icons/mob/mask.dmi index cf74d73796c8..33549a6c604b 100644 Binary files a/yogstation/icons/mob/mask.dmi and b/yogstation/icons/mob/mask.dmi differ diff --git a/yogstation/icons/mob/uniform.dmi b/yogstation/icons/mob/uniform.dmi index 33b443af193b..b01b18fee7aa 100644 Binary files a/yogstation/icons/mob/uniform.dmi and b/yogstation/icons/mob/uniform.dmi differ diff --git a/yogstation/icons/obj/clothing/masks.dmi b/yogstation/icons/obj/clothing/masks.dmi index cf74d73796c8..e2ffad30372a 100644 Binary files a/yogstation/icons/obj/clothing/masks.dmi and b/yogstation/icons/obj/clothing/masks.dmi differ diff --git a/yogstation/icons/obj/clothing/shoes.dmi b/yogstation/icons/obj/clothing/shoes.dmi index 813440155c33..3aa768354e93 100644 Binary files a/yogstation/icons/obj/clothing/shoes.dmi and b/yogstation/icons/obj/clothing/shoes.dmi differ diff --git a/yogstation/icons/obj/clothing/uniforms.dmi b/yogstation/icons/obj/clothing/uniforms.dmi index 0c03bad19ac3..e3c9d621ccbb 100644 Binary files a/yogstation/icons/obj/clothing/uniforms.dmi and b/yogstation/icons/obj/clothing/uniforms.dmi differ diff --git a/yogstation/icons/turf/floors.dmi b/yogstation/icons/turf/floors.dmi new file mode 100644 index 000000000000..e027c5999352 Binary files /dev/null and b/yogstation/icons/turf/floors.dmi differ diff --git a/yogstation/sound/effects/bodyscrape-01.ogg b/yogstation/sound/effects/bodyscrape-01.ogg new file mode 100644 index 000000000000..48c7563412b7 Binary files /dev/null and b/yogstation/sound/effects/bodyscrape-01.ogg differ diff --git a/yogstation/sound/effects/bodyscrape-02.ogg b/yogstation/sound/effects/bodyscrape-02.ogg new file mode 100644 index 000000000000..b870b5d7b021 Binary files /dev/null and b/yogstation/sound/effects/bodyscrape-02.ogg differ diff --git a/yogstation/sound/effects/cluwne_feast.ogg b/yogstation/sound/effects/cluwne_feast.ogg new file mode 100644 index 000000000000..47c23e644557 Binary files /dev/null and b/yogstation/sound/effects/cluwne_feast.ogg differ diff --git a/yogstation/sound/misc/bikehorn_creepy.ogg b/yogstation/sound/misc/bikehorn_creepy.ogg new file mode 100644 index 000000000000..7fb3290f5cf9 Binary files /dev/null and b/yogstation/sound/misc/bikehorn_creepy.ogg differ diff --git a/yogstation/sound/misc/cluwne_breathing.ogg b/yogstation/sound/misc/cluwne_breathing.ogg new file mode 100644 index 000000000000..30de4d7931ab Binary files /dev/null and b/yogstation/sound/misc/cluwne_breathing.ogg differ diff --git a/yogstation/sound/misc/floor_cluwne_emerge.ogg b/yogstation/sound/misc/floor_cluwne_emerge.ogg new file mode 100644 index 000000000000..cf8254fc21d6 Binary files /dev/null and b/yogstation/sound/misc/floor_cluwne_emerge.ogg differ diff --git a/yogstation/sound/misc/honk_echo_distant.ogg b/yogstation/sound/misc/honk_echo_distant.ogg new file mode 100644 index 000000000000..32e95884bc9f Binary files /dev/null and b/yogstation/sound/misc/honk_echo_distant.ogg differ diff --git a/yogstation/sound/voice/cluwnelaugh1.ogg b/yogstation/sound/voice/cluwnelaugh1.ogg new file mode 100644 index 000000000000..6a128cf3a35d Binary files /dev/null and b/yogstation/sound/voice/cluwnelaugh1.ogg differ diff --git a/yogstation/sound/voice/cluwnelaugh2.ogg b/yogstation/sound/voice/cluwnelaugh2.ogg new file mode 100644 index 000000000000..e118709ce216 Binary files /dev/null and b/yogstation/sound/voice/cluwnelaugh2.ogg differ diff --git a/yogstation/sound/voice/cluwnelaugh2_reversed.ogg b/yogstation/sound/voice/cluwnelaugh2_reversed.ogg new file mode 100644 index 000000000000..5dc7e9b7c39b Binary files /dev/null and b/yogstation/sound/voice/cluwnelaugh2_reversed.ogg differ diff --git a/yogstation/sound/voice/cluwnelaugh3.ogg b/yogstation/sound/voice/cluwnelaugh3.ogg new file mode 100644 index 000000000000..5ff795c94c9f Binary files /dev/null and b/yogstation/sound/voice/cluwnelaugh3.ogg differ