Refactors the safe Christmas trees to use a safe present subtype by way of a blacklist (#5027)

## About The Pull Request
Updates the safe tree to use a proper blacklist instead of being boring
and just giving bloodthirsty spacemen and women toys... They were good
all year, they crave violence. This replaces the round start Christmas
trees with the safe trees, which no longer only give out toys, but also
no longer give out admin/debug gear. A compromise for all, just in time
for Christmas!

The Christmas event present spawns have all been replaced with the safe
variants that utilize the blacklist, the other means of acquiring
presents have been left untouched.
## Why It's Good For The Game
People not getting admin tools out of Christmas presents and causing
headaches for staff is probably good for the game, maybe.
## Proof Of Testing
<details>
<summary>Screenshots/Videos</summary>
<img width="418" height="452" alt="image"
src="https://github.com/user-attachments/assets/df6554ee-084a-40c2-9592-94c88f6569c4"
/>

</details>

## Changelog
🆑 xPokee, LT3
balance: All Christmas event presents have been replaced with the safe
variants.
refactor: The safe Christmas tree subtype now uses a blacklist instead
of just giving toys.
admin: Added a new verb in the 'game' tab to blacklist presents on the
fly.
/🆑
This commit is contained in:
Alexis
2025-12-27 16:20:08 -08:00
committed by GitHub
parent b0aeb68858
commit 080e131b50
9 changed files with 110 additions and 6 deletions
+1 -1
View File
@@ -104,7 +104,7 @@
return
if(HAS_MIND_TRAIT(user, TRAIT_CANNOT_OPEN_PRESENTS))
var/turf/floor = get_turf(src)
var/obj/item/thing = new /obj/item/gift/anything(floor)
var/obj/item/thing = new /obj/item/gift/mostly_anything(floor) // BUBBER EDIT - Previous: var/obj/item/thing = new /obj/item/gift/anything(floor)
if(!atom_storage.attempt_insert(thing, user, override = TRUE, force = STORAGE_SOFT_LOCKED))
qdel(thing)
+1 -1
View File
@@ -5,7 +5,7 @@
suit = /obj/item/clothing/suit/space/santa
back = /obj/item/storage/backpack/santabag
backpack_contents = list(
/obj/item/gift/anything = 5,
/obj/item/gift/mostly_anything = 5, // BUBBER EDIT - Previous: /obj/item/gift/anything
)
gloves = /obj/item/clothing/gloves/color/red
head = /obj/item/clothing/head/helmet/space/santahat/beardless
+1 -1
View File
@@ -53,7 +53,7 @@
/// Christmas tree, no presents included.
var/festive_tree = /obj/structure/flora/tree/pine/xmas
/// Christmas tree, presents included.
var/christmas_tree = /obj/structure/flora/tree/pine/xmas/presents
var/christmas_tree = /obj/structure/flora/tree/pine/xmas/presents/safe // BUBBER EDIT - Previous: /obj/structure/flora/tree/pine/xmas/presents
/obj/effect/spawner/xmastree/Initialize(mapload)
. = ..()
+1 -1
View File
@@ -992,7 +992,7 @@ GLOBAL_LIST_INIT(holiday_mail, list())
GLOB.maintenance_loot += list(
list(
/obj/item/clothing/head/costume/santa = 1,
/obj/item/gift/anything = 1,
/obj/item/gift/mostly_anything = 1, // BUBBER EDIT - Previous: /obj/item/gift/anything
/obj/item/toy/xmas_cracker = 3,
) = maint_holiday_weight,
)
+2 -2
View File
@@ -1,11 +1,11 @@
/obj/structure/flora/tree/pine/xmas/presents/safe
icon_state = "pinepresents"
desc = "A wondrous decorated Christmas tree. It has presents!"
gift_type = /obj/item/gift //only give safe gifts from the tree
gift_type = /obj/item/gift/mostly_anything // Give presents, but filter them from the list of blacklisted debug/admin items.
unlimited = FALSE
/obj/structure/flora/tree/pine/xmas/presents/safe/unlimited
icon_state = "pinepresents"
desc = "A wondrous decorated Christmas tree. It has presents!"
gift_type = /obj/item/gift //only give safe gifts from the tree
gift_type = /obj/item/gift/mostly_anything // Give presents, but filter them from the list of blacklisted debug/admin items.
unlimited = TRUE
@@ -0,0 +1,25 @@
// Saves christmas tree blacklist data
/datum/controller/subsystem/persistence/proc/save_xmas_gift_blacklist()
var/json_file = file("data/xmas_gift_blacklist.json")
var/list/file_data = list()
var/xmas_list_length = LAZYLEN(GLOB.xmas_gift_blacklist)
file_data["data"] = LAZYCOPY(GLOB.xmas_gift_blacklist)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
log_game("Saved [xmas_list_length] items into xmas gift blacklist.")
// Loads christmas tree blacklist data
/datum/controller/subsystem/persistence/proc/load_xmas_gift_blacklist()
var/json_file = file("data/xmas_gift_blacklist.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
var/list/decoded_xmas_list = json["data"]
var/xmas_list_length = LAZYLEN(decoded_xmas_list)
if(!xmas_list_length)
return
log_game("Loaded [xmas_list_length] items into xmas gift blacklist.")
GLOB.xmas_gift_blacklist = LAZYCOPY(decoded_xmas_list)
@@ -0,0 +1,68 @@
/// Gifts that typically contain pretty much any item in the game, except with all of the admin/debug gear filtered out.
/obj/item/gift/mostly_anything
name = "christmas gift"
desc = "It could be pretty much anything!"
/obj/item/gift/mostly_anything/get_gift_type(obj/item/gift/mostly_anything/present)
var/static/list/obj/item/possible_gifts = null
if(isnull(possible_gifts))
possible_gifts = get_sane_item_types(/obj/item)
var/list/filtered = list()
for(var/type in possible_gifts)
if(!is_blacklisted(type, GLOB.xmas_gift_blacklist))
filtered += type
if(!length(filtered))
return null
return pick(filtered)
/obj/item/gift/mostly_anything/proc/is_blacklisted(typepath)
for(var/blacklisted_type in GLOB.xmas_gift_blacklist)
if(ispath(typepath, blacklisted_type))
return TRUE
return FALSE
/// The actual blacklist for the admin/debug gear. It goes at the bottom as it may end up getting quite long.
GLOBAL_LIST_INIT(xmas_gift_blacklist, list(
/datum/storage/box/debug,
/obj/item/uplink,
/obj/item/clothing/ears/earmuffs/debug,
/obj/item/gps/visible_debug,
/obj/item/clothing/glasses/meson/engine/admin,
/obj/item/storage/bag/sheetsnatcher/debug,
/obj/item/construction/rcd/combat/admin,
/obj/item/disk/tech_disk/debug,
/obj/item/flashlight/emp/debug,
/obj/item/card/id/advanced/debug,
/obj/item/debug/omnitool/item_spawner,
/obj/item/borg/projectile_dampen/debug,
/obj/item/clothing/glasses/debug,
/obj/item/gun/magic/wand/resurrection/debug,
/obj/item/mod/control/pre_equipped/administrative,
/obj/item/mod/control/pre_equipped/debug,
/obj/item/mod/control/pre_equipped/chrono,
/obj/item/gun/energy/laser/instakill,
/obj/item/gun/magic/wand/death,
/obj/item/disk/nuclear,
/obj/item/melee/energy/axe,
/obj/item/phystool,
/obj/item/physic_manipulation_tool/advanced,
/obj/item/gun/magic/wand/polymorph,
/obj/item/gun/magic/staff/chaos,
/obj/item/gun/energy/pulse,
/obj/item/dna_probe/carp_scanner,
/obj/item/antag_granter,
/obj/item/storage/box/syndie_kit/romerol,
/obj/item/reagent_containers/cup/bottle/romerol,
/obj/item/card/emag/battlecruiser,
/obj/item/proteon_orb,
/obj/structure/fluff/paper, // So I stop getting 500 papers
/obj/item/circuitboard, // Like above but for boards.
/obj/item/circuit_component, // I hate these things.
/obj/item/organ/genital, // Rule 8.
/obj/item/melee/supermatter_sword,
))
@@ -0,0 +1,8 @@
ADMIN_VERB(blacklist_xmas_item, R_ADMIN, "Blacklist Xmas Gift Item", "Take away a gift, you monster.", ADMIN_CATEGORY_GAME)
var/item_to_ban = tgui_input_text(user, "Typepath to blacklist from the tree?", "Grinching Time...", max_length = 128)
var/pathed_item = text2path(item_to_ban)
if(ispath(pathed_item))
LAZYADD(GLOB.xmas_gift_blacklist, item_to_ban)
log_admin("[key_name(user)] added [item_to_ban] to the Christmas blacklist.")
message_admins("[key_name(user)] added [item_to_ban] to the Christmas blacklist!")
BLACKBOX_LOG_ADMIN_VERB("Blacklist Xmas Gift Item")
+3
View File
@@ -8861,6 +8861,7 @@
#include "modular_zubbers\code\controllers\configuration\entries\game_options.dm"
#include "modular_zubbers\code\controllers\configuration\entries\nsfw.dm"
#include "modular_zubbers\code\controllers\subsystem\air.dm"
#include "modular_zubbers\code\controllers\subsystem\dynamic_xmas_blacklist.dm"
#include "modular_zubbers\code\controllers\subsystem\job.dm"
#include "modular_zubbers\code\controllers\subsystem\map_vote.dm"
#include "modular_zubbers\code\controllers\subsystem\mapping.dm"
@@ -9061,6 +9062,7 @@
#include "modular_zubbers\code\game\objects\items\cigarettes.dm"
#include "modular_zubbers\code\game\objects\items\cigs_lighters.dm"
#include "modular_zubbers\code\game\objects\items\flatpacks.dm"
#include "modular_zubbers\code\game\objects\items\gift.dm"
#include "modular_zubbers\code\game\objects\items\holy_weapons.dm"
#include "modular_zubbers\code\game\objects\items\kiss.dm"
#include "modular_zubbers\code\game\objects\items\more_pkas.dm"
@@ -9117,6 +9119,7 @@
#include "modular_zubbers\code\modules\admin\transform.dm"
#include "modular_zubbers\code\modules\admin\smites\pie.dm"
#include "modular_zubbers\code\modules\admin\verbs\admin.dm"
#include "modular_zubbers\code\modules\admin\verbs\blacklist_xmas_item.dm"
#include "modular_zubbers\code\modules\admin\verbs\debug.dm"
#include "modular_zubbers\code\modules\alt_anomaly_refinery\anomaly_refinery.dm"
#include "modular_zubbers\code\modules\alternative_job_titles\code\alt_job_titles.dm"