diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index be771e0676..e82976d4a3 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -29,6 +29,7 @@ GLOBAL_LIST_EMPTY(zombie_infection_list) // A list of all zombie_infection org
GLOBAL_LIST_EMPTY(meteor_list) // List of all meteors.
GLOBAL_LIST_EMPTY(active_jammers) // List of active radio jammers
GLOBAL_LIST_EMPTY(ladders)
+GLOBAL_LIST_EMPTY(trophy_cases)
GLOBAL_LIST_EMPTY(wire_color_directory)
GLOBAL_LIST_EMPTY(wire_name_directory)
\ No newline at end of file
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index e1cf992e8b..6b3e47054c 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -11,10 +11,14 @@ SUBSYSTEM_DEF(persistence)
var/list/saved_messages = list()
var/savefile/chisel_messages_sav
+ var/savefile/trophy_sav
+ var/list/saved_trophies = list()
+
/datum/controller/subsystem/persistence/Initialize()
LoadSatchels()
LoadPoly()
LoadChiselMessages()
+ LoadTrophies()
..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
@@ -105,10 +109,49 @@ SUBSYSTEM_DEF(persistence)
M.persists = FALSE
qdel(M)
+/datum/controller/subsystem/persistence/proc/LoadTrophies()
+ trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav")
+ var/saved_json
+ trophy_sav >> saved_json
+
+ var/decoded_json = json_decode(saved_json)
+
+ if(!islist(decoded_json))
+ return
+
+ saved_trophies = decoded_json
+
+ SetUpTrophies(saved_trophies.Copy())
+
+/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
+ for(var/A in GLOB.trophy_cases)
+ var/obj/structure/displaycase/trophy/T = A
+ T.added_roundstart = TRUE
+
+ var/trophy_data = pick_n_take(trophy_items)
+
+ if(!islist(trophy_data))
+ continue
+
+ var/list/chosen_trophy = trophy_data
+
+ if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
+ continue
+
+ var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
+ if(!path)
+ continue
+
+ T.showpiece = new /obj/item/showpiece_dummy(T, path)
+ T.trophy_message = chosen_trophy["message"]
+ T.placer_key = chosen_trophy["placer_key"]
+ T.update_icon()
+
/datum/controller/subsystem/persistence/proc/CollectData()
CollectChiselMessages()
CollectSecretSatchels()
+ CollectTrophies()
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
for(var/A in new_secret_satchels)
@@ -135,4 +178,16 @@ SUBSYSTEM_DEF(persistence)
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
- saved_messages += list(M.pack()) // dm eats one list.
+ saved_messages += list(M.pack()) // dm eats one list
+
+
+/datum/controller/subsystem/persistence/proc/CollectTrophies()
+ trophy_sav << json_encode(saved_trophies)
+
+/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
+ if(!T.added_roundstart && T.showpiece)
+ var/list/data = list()
+ data["path"] = T.showpiece.type
+ data["message"] = T.trophy_message
+ data["placer_key"] = T.placer_key
+ saved_trophies += list(data)
\ No newline at end of file
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index be1b49074d..3817a16685 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -16,27 +16,25 @@
var/obj/item/weapon/electronics/airlock/electronics
var/start_showpiece_type = null //add type for items on display
-/obj/structure/displaycase/New()
- ..()
+/obj/structure/displaycase/Initialize()
+ . = ..()
if(start_showpiece_type)
showpiece = new start_showpiece_type (src)
update_icon()
/obj/structure/displaycase/Destroy()
if(electronics)
- qdel(electronics)
- electronics = null
+ QDEL_NULL(electronics)
if(showpiece)
- qdel(showpiece)
- showpiece = null
+ QDEL_NULL(showpiece)
return ..()
/obj/structure/displaycase/examine(mob/user)
..()
- if(showpiece)
- to_chat(user, "There's [showpiece] inside.")
if(alert)
to_chat(user, "Hooked up with an anti-theft system.")
+ if(showpiece)
+ to_chat(user, "There's [showpiece] inside.")
/obj/structure/displaycase/proc/dump()
@@ -176,8 +174,8 @@
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (showpiece && (broken || open))
- dump()
to_chat(user, "You deactivate the hover field built into the case.")
+ dump()
src.add_fingerprint(user)
update_icon()
return
@@ -249,3 +247,96 @@
desc = "A glass lab container for storing interesting creatures."
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
req_access = list(GLOB.access_rd)
+
+
+
+/obj/structure/displaycase/trophy
+ name = "trophy display case"
+ desc = "Store your trophies of accomplishment in here, and they will stay forever."
+ var/trophy_message = ""
+ var/placer_key = ""
+ var/added_roundstart = TRUE
+ alert = TRUE
+ integrity_failure = 0
+
+/obj/structure/displaycase/trophy/Initialize()
+ . = ..()
+ GLOB.trophy_cases += src
+
+/obj/structure/displaycase/trophy/Destroy()
+ GLOB.trophy_cases -= src
+ return ..()
+
+/obj/structure/displaycase/trophy/examine(mob/user)
+ ..()
+ if(trophy_message)
+ to_chat(user, "The plaque reads:")
+ to_chat(user, trophy_message)
+
+/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
+
+ if(!user.Adjacent(src)) //no TK museology
+ return
+
+ if(!added_roundstart)
+ to_chat(user, "You've already put something new in this case.")
+ return
+
+ if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ for(var/a in W.GetAllContents())
+ if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ if(user.drop_item())
+
+ if(showpiece)
+ to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
+ QDEL_NULL(showpiece)
+
+ to_chat(user, "You insert [W] into the case.")
+ W.forceMove(src)
+ showpiece = W
+ added_roundstart = FALSE
+ update_icon()
+
+ placer_key = user.ckey
+
+ trophy_message = W.desc //default value
+
+ var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
+ if(chosen_plaque)
+ if(user.Adjacent(src))
+ trophy_message = chosen_plaque
+ to_chat(user, "You set the plaque's text.")
+ else
+ to_chat(user, "You are too far to set the plaque's text.")
+
+ SSpersistence.SaveTrophy(src)
+
+ else
+ to_chat(user, "\The [W] is stuck to your hand, you can't put it in the [src.name]!")
+
+ return
+
+/obj/structure/displaycase/trophy/dump()
+ if (showpiece)
+ if(added_roundstart)
+ visible_message("The [showpiece] crumbles to dust!")
+ new /obj/effect/decal/cleanable/ash(loc)
+ QDEL_NULL(showpiece)
+ else
+ ..()
+
+/obj/item/showpiece_dummy
+ name = "Cheap replica"
+
+/obj/item/showpiece_dummy/Initialize(mapload, path)
+ . = ..()
+ var/obj/item/I = path
+ name = initial(I.name)
+ icon = initial(I.icon)
+ icon_state = initial(I.icon_state)