diff --git a/code/modules/asset_cache/assets/paper.dm b/code/modules/asset_cache/assets/paper.dm
index bf6f2ef8846..d150e568a75 100644
--- a/code/modules/asset_cache/assets/paper.dm
+++ b/code/modules/asset_cache/assets/paper.dm
@@ -19,6 +19,7 @@
"stamp-merged" = 'icons/stamp_icons/large_stamp-merged.png',
"stamp-closed" = 'icons/stamp_icons/large_stamp-closed.png',
"stamp-crow" = 'icons/stamp_icons/crow-stamp.png',
+ "stamp-warden" = 'icons/stamp_icons/large_stamp-warden.png',
//BUBBERSTATION ADDITION: END - Bubberstation Stamp Icons
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
diff --git a/code/modules/balloon_alert/balloon_alert.dm b/code/modules/balloon_alert/balloon_alert.dm
index cf890c01308..86e0011efc2 100644
--- a/code/modules/balloon_alert/balloon_alert.dm
+++ b/code/modules/balloon_alert/balloon_alert.dm
@@ -4,7 +4,7 @@
#define BALLOON_TEXT_FULLY_VISIBLE_TIME (0.7 SECONDS)
#define BALLOON_TEXT_TOTAL_LIFETIME(mult) (BALLOON_TEXT_SPAWN_TIME + BALLOON_TEXT_FULLY_VISIBLE_TIME*mult + BALLOON_TEXT_FADE_TIME)
/// The increase in duration per character in seconds
-#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT (0.05)
+#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT (0.07) // BUBBER EDIT CHANGE - Original: 0.05
/// The amount of characters needed before this increase takes into effect
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN 10
diff --git a/html/changelogs/AutoChangeLog-pr-2335.yml b/html/changelogs/AutoChangeLog-pr-2335.yml
new file mode 100644
index 00000000000..0e2b705fbe7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2335.yml
@@ -0,0 +1,7 @@
+author: "Middiwiddi, LT3"
+delete-after: True
+changes:
+ - rscadd: "Added 'nyamagotchi', a tamagotchi clone that's cute and cat-themed. Interactive and able to attach on belt."
+ - rscadd: "Added nyamagotchi to toy vending machine and clothesdrobe"
+ - rscadd: "Added nyamagotchi to 'pockets' loadout options."
+ - rscadd: "nyamagotchi works as a companion for monophobia.\n:cl:\n\n\n"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-2408.yml b/html/changelogs/AutoChangeLog-pr-2408.yml
new file mode 100644
index 00000000000..7718e65cc53
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2408.yml
@@ -0,0 +1,4 @@
+author: "xPokee"
+delete-after: True
+changes:
+ - bugfix: "fixed bacon and cloth cookies from cyborg snack dispensers not having a proper taste"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-2436.yml b/html/changelogs/AutoChangeLog-pr-2436.yml
new file mode 100644
index 00000000000..dc25c7490b8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2436.yml
@@ -0,0 +1,5 @@
+author: "Majkl-J and Cepha"
+delete-after: True
+changes:
+ - rscadd: "Ponytails (Berly) hair added"
+ - rscadd: "Short (Side) hair added"
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml
index 6ac129e14b1..08d1b76e8b2 100644
--- a/html/changelogs/archive/2024-11.yml
+++ b/html/changelogs/archive/2024-11.yml
@@ -326,3 +326,13 @@
2024-11-14:
LT3:
- bugfix: Alternate meow and purr emotes work again
+2024-11-15:
+ Arturlang:
+ - bugfix: Fixes the bokken having 16 damage when unwielded, and 8 when it is
+ Boviro:
+ - rscadd: gives the warden a stamp
+ sippykot:
+ - balance: NT's bluespace technology doubles lunchbox storage from 4 to 8 items
+ with special lining
+ - rscadd: lunchboxes can also hold condiments and gum now... and cigarettes and
+ lighters, at the insistence of our sponsors in the space tobacco industry
diff --git a/icons/stamp_icons/large_stamp-warden.png b/icons/stamp_icons/large_stamp-warden.png
new file mode 100644
index 00000000000..ed8e9a25013
Binary files /dev/null and b/icons/stamp_icons/large_stamp-warden.png differ
diff --git a/modular_skyrat/master_files/code/modules/loadout/categories/toys.dm b/modular_skyrat/master_files/code/modules/loadout/categories/toys.dm
index e556808344d..c936dbc9159 100644
--- a/modular_skyrat/master_files/code/modules/loadout/categories/toys.dm
+++ b/modular_skyrat/master_files/code/modules/loadout/categories/toys.dm
@@ -411,3 +411,9 @@
/datum/loadout_item/toys/purple_laser
name = "Purple Laser Pointer"
item_path = /obj/item/laser_pointer/limited/purple
+
+/datum/loadout_item/toys/nyamagotchi
+ name = "Nyamagotchi"
+ item_path = /obj/item/toy/nyamagotchi
+ ui_icon = 'modular_zubbers/icons/obj/toys/toys.dmi'
+ ui_icon_state = "nya"
diff --git a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
index ea279958909..66f1d803447 100644
--- a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
+++ b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
@@ -148,6 +148,7 @@
icon = 'modular_skyrat/master_files/icons/obj/food/snacks.dmi'
icon_state = "bacon_strip"
foodtypes = MEAT
+ tastes = list("bacon" = 1)
/obj/item/food/cookie/cloth
name = "odd cookie"
@@ -155,3 +156,4 @@
icon = 'modular_skyrat/master_files/icons/obj/food/snacks.dmi'
icon_state = "cookie_cloth"
foodtypes = CLOTH
+ tastes = list("synthetic clothing fibers" = 1)
diff --git a/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm b/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
index a354d6ec6b1..4d9b1faf252 100644
--- a/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
+++ b/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
@@ -314,7 +314,7 @@
/obj/item/forging/reagent_weapon/bokken
name = "reagent bokken"
desc = "A bokken that is capable of blocking attacks when wielding in two hands, possibly including bullets should the user be brave enough."
- force = 16
+ force = 8
icon_state = "bokken"
inhand_icon_state = "bokken"
worn_icon_state = "bokken_back"
@@ -349,7 +349,7 @@
. = ..()
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield))
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield))
- AddComponent(/datum/component/two_handed, force_multiplier = 0.5)
+ AddComponent(/datum/component/two_handed, force_multiplier = 1.5)
/obj/item/forging/reagent_weapon/bokken/proc/on_wield()
SIGNAL_HANDLER
diff --git a/modular_zubbers/code/_globalvars/lists/maintenance_loot_common.dm b/modular_zubbers/code/_globalvars/lists/maintenance_loot_common.dm
index 609012c5d9f..df67a71665b 100644
--- a/modular_zubbers/code/_globalvars/lists/maintenance_loot_common.dm
+++ b/modular_zubbers/code/_globalvars/lists/maintenance_loot_common.dm
@@ -946,6 +946,7 @@ GLOBAL_LIST_INIT(common_loot, list( //common: basic items
/obj/item/instrument/violin = 10,
/obj/item/instrument/violin/golden = 1
) = 25,
+ /obj/item/toy/nyamagotchi = 15,
/obj/item/paper/fluff/stations/soap = 50,
list(
/obj/item/soap = 50,
diff --git a/modular_zubbers/code/game/brain_damage/severe.dm b/modular_zubbers/code/game/brain_damage/severe.dm
index e62f48df7c3..b3ddea4184c 100644
--- a/modular_zubbers/code/game/brain_damage/severe.dm
+++ b/modular_zubbers/code/game/brain_damage/severe.dm
@@ -6,6 +6,12 @@
for(var/obj/item/toy/plush/plush in owner.held_items) //Now you have an excuse to carry a shark plushie around all the time
if(plush.stuffed)
return FALSE
+ for(var/obj/item/toy/nyamagotchi/cat in oview(owner, 1))
+ if(cat.alive == 1)
+ return FALSE
+ for(var/obj/item/toy/nyamagotchi/cat in owner.held_items) // virtual pets are friends too!
+ if(cat.alive == 1)
+ return FALSE
for(var/mob/M in owner.held_items) //makes sure to check hands for your tiny friends!
if(!isliving(M))
continue
diff --git a/modular_zubbers/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/modular_zubbers/code/game/objects/structures/crates_lockers/closets/secure/security.dm
new file mode 100644
index 00000000000..b15ebd6e872
--- /dev/null
+++ b/modular_zubbers/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -0,0 +1,3 @@
+/obj/structure/closet/secure_closet/warden/PopulateContents()
+ . = ..()
+ new /obj/item/stamp/warden(src)
diff --git a/modular_zubbers/code/game/traits/negative.dm b/modular_zubbers/code/game/traits/negative.dm
index 00858c45fe9..ed11c4dcb2a 100644
--- a/modular_zubbers/code/game/traits/negative.dm
+++ b/modular_zubbers/code/game/traits/negative.dm
@@ -1,3 +1,4 @@
/datum/quirk/monophobia
value = -8
mob_trait = TRAIT_MONOPHOBIA
+ mail_goodies = list(/obj/item/toy/nyamagotchi)
diff --git a/modular_zubbers/code/modules/arcades/code/loot/arcade_weights_classic.dm b/modular_zubbers/code/modules/arcades/code/loot/arcade_weights_classic.dm
index f1c0bb73772..bceb5e13ea2 100644
--- a/modular_zubbers/code/modules/arcades/code/loot/arcade_weights_classic.dm
+++ b/modular_zubbers/code/modules/arcades/code/loot/arcade_weights_classic.dm
@@ -53,6 +53,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool_classic, list(
/obj/item/toy/katana = 100,
/obj/item/toy/minimeteor = 50,
/obj/item/toy/nuke = 50,
+ /obj/item/toy/nyamagotchi = 75,
/obj/item/toy/redbutton = 50,
/obj/item/toy/spinningtoy = 50,
/obj/item/toy/spinningtoy/dark_matter = 50,
diff --git a/modular_zubbers/code/modules/lunchbox/code/lunchbox.dm b/modular_zubbers/code/modules/lunchbox/code/lunchbox.dm
index 2b535d6eab9..fd557066092 100644
--- a/modular_zubbers/code/modules/lunchbox/code/lunchbox.dm
+++ b/modular_zubbers/code/modules/lunchbox/code/lunchbox.dm
@@ -13,10 +13,14 @@
/obj/item/storage/lunchbox/Initialize(mapload)
. = ..()
- atom_storage.max_slots = 4
+ atom_storage.max_slots = 8
atom_storage.set_holdable(list(
/obj/item/food,
/obj/item/reagent_containers/cup,
+ /obj/item/reagent_containers/condiment,
+ /obj/item/storage/box/gum,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/lighter,
))
/obj/item/storage/lunchbox/nanotrasen
diff --git a/modular_zubbers/code/modules/mob/dead/new_player/sprite_accessories/hair.dm b/modular_zubbers/code/modules/mob/dead/new_player/sprite_accessories/hair.dm
index b151ffefca8..109cb409211 100644
--- a/modular_zubbers/code/modules/mob/dead/new_player/sprite_accessories/hair.dm
+++ b/modular_zubbers/code/modules/mob/dead/new_player/sprite_accessories/hair.dm
@@ -44,3 +44,14 @@
icon = 'modular_zubbers/icons/customization/hair.dmi'
name = "Inari"
icon_state = "hair_inari"
+
+// short_side and ponytails_berly sprites by Cepha
+/datum/sprite_accessory/hair/short_side
+ icon = 'modular_zubbers/icons/customization/hair.dmi'
+ name = "Short (Side)"
+ icon_state = "hair_short_side"
+
+/datum/sprite_accessory/hair/ponytails_berly
+ icon = 'modular_zubbers/icons/customization/hair.dmi'
+ name = "Ponytails (Berly)"
+ icon_state = "hair_tails_berly"
diff --git a/modular_zubbers/code/modules/nyamagotchi/nyamagotchi.dm b/modular_zubbers/code/modules/nyamagotchi/nyamagotchi.dm
new file mode 100644
index 00000000000..6fea8b7104d
--- /dev/null
+++ b/modular_zubbers/code/modules/nyamagotchi/nyamagotchi.dm
@@ -0,0 +1,383 @@
+#define NO_ANIMAL 0
+#define ANIMAL_ALIVE 1
+#define ANIMAL_DEAD 2
+
+#define MEOW_NORMAL 'sound/creatures/cat/cat_meow1.ogg'
+#define MEOW_SAD 'modular_zubbers/code/modules/nyamagotchi/sound/cat_sad.ogg'
+#define MEOW_CRITICAL 'modular_zubbers/code/modules/nyamagotchi/sound/cat_alert.ogg'
+#define EAT_FOOD 'modular_zubbers/code/modules/nyamagotchi/sound/cat_eat.ogg'
+#define PURR_PLAY 'sound/creatures/cat/cat_purr1.ogg'
+#define PURR_SLEEP 'sound/creatures/cat/cat_purr3.ogg'
+
+/obj/item/toy/nyamagotchi
+ name = "Nyamagotchi"
+ desc = "A small electronic 'pet' that requires care and attention. An ancient relic sure to evoke nostalgic feelings."
+ icon = 'modular_zubbers/icons/obj/toys/toys.dmi'
+ icon_state = "nya"
+ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
+ inhand_icon_state = "electronic"
+ slot_flags = ITEM_SLOT_BELT
+ w_class = WEIGHT_CLASS_SMALL
+ force = 2
+ throwforce = 2
+ actions_types = list(/datum/action/item_action/nyamagotchi_menu)
+ custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT, /datum/material/glass = SMALL_MATERIAL_AMOUNT, /datum/material/plastic = SMALL_MATERIAL_AMOUNT)
+ // interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_ALLOW_USER_LOCATION | INTERACT_ATOM_IGNORE_MOBILITY
+ var/list/icons_available = list()
+ var/radial_icon_file = 'modular_zubbers/code/modules/nyamagotchi/sprites/radial_nyamagotchi.dmi'
+
+ /// Hunger level (0 = full, 100 = starving)
+ var/hunger = 0
+ /// Happiness level (0 = sad, 100 = very happy)
+ var/happiness = 100
+ /// Energy level (0 = tired, 100 = full of energy)
+ var/energy = 0
+ /// Age in "days" or some unit of time
+ var/age = 0
+ /// How often a 'life' cycle of the pet runs
+ var/update_rate = 45 SECONDS
+ /// The last action the pet performed
+ var/last_task = null
+
+ var/alive = NO_ANIMAL
+ var/list/rest_messages = list(
+ "Zzz... Zzz... Zzz...",
+ "Honk, shew! Hooonk, shewww...!",
+ "Snoozin' time, nya...",
+ "Honk shoo!",
+ "Nini...~",
+ "Zzz... Zzz... Zzz... Zzz... Zzz...",
+ )
+ var/list/play_messages = list(
+ "Wowzers meowzers, that was fun!",
+ "That was so much fun, nya!",
+ "YAY!!!",
+ "I had a great time playing with you!",
+ "YIPPEEE!!!", "That was a blast!",
+ "Wowzers meowzers, that was a blast!",
+ )
+ var/list/feed_messages = list(
+ "NOM NOM NOM. Ice cream, yum!",
+ "Mmm, that was tasty!",
+ "So yummy!",
+ "Oooh! Delicious!",
+ "MONCH MONCH MONCH.",
+ "MUNCH MUNCH, that was so heckin' tasty, nya!",
+ "Yum, that was delicious!",
+ "What a PURRFECT meal, nya!",
+ )
+ var/list/hunger_warning = list(
+ "Wowzers meowzers, I'm hungry, nya!",
+ "Excuse me! I'm feeling a bit peckish, nya!",
+ "I could eat the world right now, nya!",
+ "Soooo hongry!",
+ "I'm feeling a bit hungry, nya!",
+ "I needs the food, mrow!",
+ )
+ var/list/hunger_critical = list(
+ "HELLO! Food, pwease?...",
+ "HEY!!! I'm starving...",
+ "HONNNNGRYYY!!!",
+ "so so hungry...",
+ )
+ var/list/happiness_warning = list(
+ "Some fun would be purrfect, nya...",
+ "I'm feeling a bit down, nya...",
+ "Playtime! Now!",
+ "This is no fun...",
+ "I'm BORED, nya!",
+ "So sad! So bored! Need to play!",
+ "Wah... So sad, nya...",
+ "I'm feeling a bit blue, nya...",
+ "I'm sad...",
+ "Play with meeee! PLEASE.",
+ "My fun levels are low, nya...",
+ )
+ var/list/full_critical = list(
+ "So this... is how it ends for me...",
+ "Is this how it ends... cold, alone, unfed...",
+ "Fading... fast... my last request: snacks and snuggles, please...",
+ "I see the end... all nine lives gone...",
+ "Abandoned... like a stray... in my own virtual world...",
+ "It’s getting so dark and cold...",
+ )
+ var/list/energy_warning = list(
+ "I'm feeling a bit sleepy, nya...",
+ "Sleempy...",
+ "I be needin' a naps, nya!",
+ "Need to do the big sleeps, please!",
+ "I'm feeling a bit exhausted, nya...",
+ "I could go for a nap...",
+ )
+ var/list/energy_critical = list(
+ "SO, SO EEPY, NYA...",
+ "Please, I need to rest...",
+ "I'm feel like I'm gonna pass out...",
+ "Why won't you let me sleep?...",
+ "EEPY. EEPY. eepy...",
+ )
+ COOLDOWN_DECLARE(mute_pet)
+ COOLDOWN_DECLARE(needs_alert)
+
+/obj/item/toy/nyamagotchi/Initialize(mapload)
+ . = ..()
+ if(prob(3))
+ name = "pocket pussy" // mrowwww!
+ register_context()
+ update_available_icons()
+
+/obj/item/toy/nyamagotchi/examine(mob/user)
+ . = ..()
+ if(in_range(src, user) || isobserver(user))
+ . += "[readout()]"
+ if(!COOLDOWN_FINISHED(src, mute_pet))
+ . += span_notice("Alt-click to disable mute feature.")
+ else
+ . += span_notice("Alt-click to temporarily mute notifications.")
+
+/obj/item/toy/nyamagotchi/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+ context[SCREENTIP_CONTEXT_LMB] = "Interact"
+ context[SCREENTIP_CONTEXT_ALT_LMB] = "Toggle mute"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/item/toy/nyamagotchi/proc/readout()
+ switch(alive)
+ if(NO_ANIMAL)
+ return span_notice("[src] is ready to be started!")
+ if(ANIMAL_ALIVE)
+ return span_notice("[src] is alive, it has reached age [age]! Use the 'Check Status' button to see its stats!")
+ if(ANIMAL_DEAD)
+ return span_purple("[src] is DEAD. You're a terrible person.")
+
+/obj/item/toy/nyamagotchi/proc/update_available_icons()
+ icons_available = list()
+ if(alive == ANIMAL_ALIVE)
+ icons_available += list(
+ "Feed" = image(radial_icon_file, "feed"),
+ "Play" = image(radial_icon_file, "play"),
+ "Rest" = image(radial_icon_file, "rest"),
+ "Check Status" = image(radial_icon_file, "status",
+ ))
+ else
+ icons_available += list("Start!" = image(radial_icon_file, "start"))
+
+/obj/item/toy/nyamagotchi/attack_self(mob/user)
+ pet_menu(user)
+
+/obj/item/toy/nyamagotchi/proc/pet_menu(mob/user, list/modifiers)
+ update_available_icons()
+ if(icons_available)
+ var/selection = show_radial_menu(user, src, icons_available, radius = 38, require_near = TRUE, tooltips = TRUE)
+ if(!selection)
+ return
+ switch(selection)
+ if("Start!")
+ start()
+ if("Feed")
+ feed()
+ if("Play")
+ play()
+ if("Rest")
+ rest()
+ if("Check Status")
+ check_status()
+
+/obj/item/toy/nyamagotchi/click_alt(mob/living/user)
+ if(user != loc)
+ return
+
+ if(COOLDOWN_FINISHED(src, mute_pet))
+ COOLDOWN_START(src, mute_pet, update_rate * 5.75)
+ user.balloon_alert(user, "muted!")
+ to_chat(user, span_notice("You turn on [src]'s mute feature."))
+
+ else
+ COOLDOWN_RESET(src, mute_pet)
+ user.balloon_alert(user, "unmuted!")
+ to_chat(user, span_notice("You turn off [src]'s mute feature."))
+ be_known(sfx = MEOW_NORMAL)
+
+/obj/item/toy/nyamagotchi/proc/start()
+ alive = ANIMAL_ALIVE
+ // give a slightly random start
+ hunger = rand(30, 60)
+ happiness = rand(80, 100)
+ energy = rand(60, 90)
+ be_known(sfx = 'sound/misc/bloop.ogg', speech = "I'm alive, nya!")
+ addtimer(CALLBACK(src, PROC_REF(be_known), MEOW_NORMAL), 2 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(update)), update_rate)
+
+// status update loop
+/obj/item/toy/nyamagotchi/proc/update()
+ if(!alive)
+ return
+
+ last_task = null
+
+ if(happiness <= 21) // unhappy pets get hungry and tired faster
+ hunger += rand(1, 2)
+ energy -= rand(1, 3)
+
+ if(hunger >= 70 || energy <= 30)
+ happiness -= clamp(rand(2, 4), 0, happiness)
+
+ age += 1 // Increase age over time
+ hunger += rand(1, 3) // Increase hunger over time
+ happiness -= clamp(rand(1, 3), 0, happiness) // Decrease happiness over time
+ energy -= rand(1, 3) // Decrease energy over time
+
+ // check if the nyamagotchi is still alive
+ if(hunger >= 100 || energy <= 0)
+ die()
+ return
+
+ // schedule our next check
+ addtimer(CALLBACK(src, PROC_REF(update)), update_rate)
+
+ // make the nyamagotchi say things if attention is needed, otherwise just a small chance of a reminder meow
+ var/list/tama_alerts = list()
+ var/selected_alert
+ if((hunger >= 83 || energy <= 17) && happiness <= 21)
+ be_known(sfx = MEOW_CRITICAL, speech = pick(full_critical))
+ return
+ if(hunger >= 83)
+ tama_alerts += "vhungry"
+ if(energy <= 17)
+ tama_alerts += "vtired"
+ if(tama_alerts.len)
+ selected_alert = pick(tama_alerts)
+ switch(selected_alert)
+ if("vhungry")
+ be_known(sfx = MEOW_CRITICAL, speech = pick(hunger_critical))
+ return
+ if("vtired")
+ be_known(sfx = MEOW_CRITICAL, speech = pick(energy_critical))
+ return
+
+ if(!COOLDOWN_FINISHED(src, needs_alert))
+ return // to not be too annoying
+
+ if(hunger >= 70)
+ tama_alerts += "hungry"
+ if(happiness <= 30)
+ tama_alerts += "sad"
+ if(energy <= 30)
+ tama_alerts += "tired"
+ if(tama_alerts.len)
+ COOLDOWN_START(src, needs_alert, update_rate * 2.25)
+ selected_alert = pick(tama_alerts)
+ switch(selected_alert)
+ if("hungry")
+ be_known(sfx = MEOW_SAD, speech = pick(hunger_warning))
+ if("sad")
+ be_known(sfx = MEOW_SAD, speech = pick(happiness_warning))
+ if("tired")
+ be_known(sfx = MEOW_SAD, speech = pick(energy_warning))
+ else if(prob(25))
+ be_known(sfx = MEOW_NORMAL)
+
+/obj/item/toy/nyamagotchi/proc/be_known(sfx, speech, visible)
+ if(!COOLDOWN_FINISHED(src, mute_pet))
+ return
+
+ if(!isnull(sfx))
+ playsound(source = src, soundin = sfx, vol = 40, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE)
+
+ if(!isnull(speech))
+ say(speech, message_range = 2)
+
+ if(!isnull(visible))
+ balloon_alert_to_viewers(message = visible, vision_distance = COMBAT_MESSAGE_RANGE + 2)
+
+// Interactions
+/obj/item/toy/nyamagotchi/proc/action_check()
+ if(!isnull(last_task))
+ usr.balloon_alert(usr, "still [last_task]!")
+ be_known(sfx = MEOW_SAD)
+ return FALSE
+ return TRUE
+
+/obj/item/toy/nyamagotchi/proc/feed()
+ if(!action_check())
+ return
+ else if(hunger > 20)
+ hunger -= min(rand(30, 40), hunger)
+ to_chat(usr, span_purple("You fed [src]! Its hunger is now at [hunger]."))
+ be_known(sfx = EAT_FOOD, speech = pick(feed_messages))
+ last_task = "eating"
+ else
+ usr.balloon_alert(usr, "not hungry!")
+
+/obj/item/toy/nyamagotchi/proc/play()
+ if(!action_check())
+ return
+ else if(happiness < 80)
+ happiness += min(rand(30, 40), 100 - happiness)
+ to_chat(usr, span_purple("You play with [src]! Its happiness is now [happiness]."))
+ be_known(sfx = PURR_PLAY, speech = pick(play_messages))
+ last_task = "playing"
+ else
+ usr.balloon_alert(usr, "not bored!")
+
+/obj/item/toy/nyamagotchi/proc/rest()
+ if(!action_check())
+ return
+ else if(energy < 80)
+ energy += min(rand(30, 40), 100 - energy)
+ to_chat(usr, span_purple("[src] rests and regains energy. Its energy is now [energy]."))
+ be_known(sfx = PURR_SLEEP, speech = pick(rest_messages))
+ last_task = "resting"
+ else
+ usr.balloon_alert(usr, "not tired!")
+
+// Function for when the nyamagotchi dies
+/obj/item/toy/nyamagotchi/proc/die()
+ last_task = null
+ alive = ANIMAL_DEAD
+ audible_message(span_warning("[src] makes a weak, sad noise and then goes silent... Rest in peace."), hearing_distance = COMBAT_MESSAGE_RANGE)
+ if(ishuman(loc))
+ to_chat(loc, span_warning("[src] shows an x3 on its display. It's dead. You're a terrible person."))
+ //src.icon_state = "dead"
+ be_known(sfx = 'sound/misc/sadtrombone.ogg', visible = "nyamagotchi died!")
+ update_available_icons()
+
+/obj/item/toy/nyamagotchi/proc/check_status()
+ balloon_alert(usr, "hunger: [hunger] happiness: [happiness] energy: [energy]")
+
+/datum/action/item_action/nyamagotchi_menu
+ name = "Check Nyamagotchi"
+ button_icon = 'modular_zubbers/icons/obj/toys/toys.dmi'
+ button_icon_state = "nya"
+
+/datum/job/psychologist/New()
+ LAZYADDASSOC(mail_goodies, /obj/item/toy/nyamagotchi, 45)
+ . = ..()
+
+/obj/effect/spawner/random/entertainment/dice
+ name = "dice spawner"
+ icon_state = "dice_bag"
+ spawn_loot_count = 3
+ spawn_loot_double = FALSE
+ spawn_loot_split = TRUE
+ loot = list(
+ /obj/item/dice/d4,
+ /obj/item/dice/d6,
+ /obj/item/dice/d8,
+ /obj/item/dice/d10,
+ /obj/item/dice/d12,
+ /obj/item/dice/d20,
+ /obj/item/dice/fourdd6,
+ /obj/item/toy/nyamagotchi,
+ )
+
+#undef NO_ANIMAL
+#undef ANIMAL_ALIVE
+#undef ANIMAL_DEAD
+
+#undef MEOW_NORMAL
+#undef MEOW_SAD
+#undef MEOW_CRITICAL
+#undef EAT_FOOD
+#undef PURR_PLAY
+#undef PURR_SLEEP
diff --git a/modular_zubbers/code/modules/nyamagotchi/sound/cat_alert.ogg b/modular_zubbers/code/modules/nyamagotchi/sound/cat_alert.ogg
new file mode 100644
index 00000000000..fc5a18e6089
Binary files /dev/null and b/modular_zubbers/code/modules/nyamagotchi/sound/cat_alert.ogg differ
diff --git a/modular_zubbers/code/modules/nyamagotchi/sound/cat_eat.ogg b/modular_zubbers/code/modules/nyamagotchi/sound/cat_eat.ogg
new file mode 100644
index 00000000000..10bf1204b67
Binary files /dev/null and b/modular_zubbers/code/modules/nyamagotchi/sound/cat_eat.ogg differ
diff --git a/modular_zubbers/code/modules/nyamagotchi/sound/cat_sad.ogg b/modular_zubbers/code/modules/nyamagotchi/sound/cat_sad.ogg
new file mode 100644
index 00000000000..5ebba2ec3ba
Binary files /dev/null and b/modular_zubbers/code/modules/nyamagotchi/sound/cat_sad.ogg differ
diff --git a/modular_zubbers/code/modules/nyamagotchi/sprites/radial_nyamagotchi.dmi b/modular_zubbers/code/modules/nyamagotchi/sprites/radial_nyamagotchi.dmi
new file mode 100644
index 00000000000..22332846f75
Binary files /dev/null and b/modular_zubbers/code/modules/nyamagotchi/sprites/radial_nyamagotchi.dmi differ
diff --git a/modular_zubbers/code/modules/paperwork/stamps.dm b/modular_zubbers/code/modules/paperwork/stamps.dm
index 34e3662136e..54acbb0bc4b 100644
--- a/modular_zubbers/code/modules/paperwork/stamps.dm
+++ b/modular_zubbers/code/modules/paperwork/stamps.dm
@@ -24,3 +24,9 @@
icon_state = "stamp-crow"
desc = "A rubber stamp for stamping vaguely legal contracts."
dye_color = DYE_BLACK
+
+/obj/item/stamp/warden
+ name = "warden's rubber stamp"
+ icon = 'modular_zubbers/icons/obj/service/bureaucracy.dmi'
+ icon_state = "stamp-warden"
+ dye_color = DYE_HOS
diff --git a/modular_zubbers/code/modules/vending/games.dm b/modular_zubbers/code/modules/vending/games.dm
index 53cb7359e76..344dcf80781 100644
--- a/modular_zubbers/code/modules/vending/games.dm
+++ b/modular_zubbers/code/modules/vending/games.dm
@@ -111,6 +111,7 @@
/obj/item/holosign_creator/hardlight_wheelchair = 3,
/obj/item/instrument/piano_synth/headphones/catear_headphone = 3,
/obj/item/clothing/accessory/pocketwatch = 3,
+ /obj/item/toy/nyamagotchi = 3,
),
)
)
diff --git a/modular_zubbers/icons/customization/hair.dmi b/modular_zubbers/icons/customization/hair.dmi
index 0bfc80618ca..8d82d950386 100644
Binary files a/modular_zubbers/icons/customization/hair.dmi and b/modular_zubbers/icons/customization/hair.dmi differ
diff --git a/modular_zubbers/icons/obj/service/bureaucracy.dmi b/modular_zubbers/icons/obj/service/bureaucracy.dmi
index 56a7df27b6d..28891145bef 100644
Binary files a/modular_zubbers/icons/obj/service/bureaucracy.dmi and b/modular_zubbers/icons/obj/service/bureaucracy.dmi differ
diff --git a/modular_zubbers/icons/obj/toys/toys.dmi b/modular_zubbers/icons/obj/toys/toys.dmi
new file mode 100644
index 00000000000..b31b5064dec
Binary files /dev/null and b/modular_zubbers/icons/obj/toys/toys.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 22ffd6eb1e1..2ce59ab04fe 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -8810,6 +8810,7 @@
#include "modular_zubbers\code\game\objects\structures\beds_chairs\sofa.dm"
#include "modular_zubbers\code\game\objects\structures\crates_lockers\closets.dm"
#include "modular_zubbers\code\game\objects\structures\crates_lockers\closets\secure\scientist.dm"
+#include "modular_zubbers\code\game\objects\structures\crates_lockers\closets\secure\security.dm"
#include "modular_zubbers\code\game\objects\structures\flags\signs_flags.dm"
#include "modular_zubbers\code\game\objects\structures\plaques\static_plaques.dm"
#include "modular_zubbers\code\game\traits\negative.dm"
@@ -9179,6 +9180,7 @@
#include "modular_zubbers\code\modules\modular_weapons\code\company_and_or_faction_based\szot_dynamica\pistol.dm"
#include "modular_zubbers\code\modules\movespeed\_movespeed_modifier.dm"
#include "modular_zubbers\code\modules\movespeed\modifiers\status_effects.dm"
+#include "modular_zubbers\code\modules\nyamagotchi\nyamagotchi.dm"
#include "modular_zubbers\code\modules\opposing_force\code\items.dm"
#include "modular_zubbers\code\modules\opposing_force\code\equipment\antagonist_powers.dm"
#include "modular_zubbers\code\modules\pai\ghost_pai.dm"