mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
[MIRROR] Trophy case update [MDB IGNORE] (#17616)
This commit is contained in:
@@ -3673,7 +3673,7 @@
|
||||
/obj/effect/turf_decal/tile/blue/fourcorners,
|
||||
/obj/structure/displaycase{
|
||||
start_showpiece_type = /obj/item/dice/d6/space;
|
||||
trophy_message = "Stolen from dice collector before he could enjoy his day."
|
||||
desc = "Contains an artifact stolen from dice collector before he could enjoy his day."
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/cabin/caves/mountain)
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
#define ACCESS_CHAPEL_OFFICE "chapel_office"
|
||||
/// Access to the chapel's crematorium.
|
||||
#define ACCESS_CREMATORIUM "crematorium"
|
||||
/// Access to the curator's private rooms in the Library, as well as access both into and out of the Library via Maintenance.
|
||||
/// Access to the curator's private rooms in the Library and the trophy display cases, as well as access both into and out of the Library via Maintenance.
|
||||
#define ACCESS_LIBRARY "library"
|
||||
/// Access to the Bar, the Bar's Backroom, the bar sign, the bar robot portal, and the bar's vending machines. Some other bar-things too.
|
||||
#define ACCESS_BAR "bar"
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
#define MAX_NAME_LEN 42
|
||||
#define MAX_BROADCAST_LEN 512
|
||||
#define MAX_CHARTER_LEN 80
|
||||
#define MAX_PLAQUE_LEN 144
|
||||
|
||||
// Audio/Visual Flags. Used to determine what sense are required to notice a message.
|
||||
#define MSG_VISUAL (1<<0)
|
||||
|
||||
@@ -25,37 +25,40 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/rounds_since_engine_exploded = 0
|
||||
|
||||
/datum/controller/subsystem/persistence/Initialize()
|
||||
LoadPoly()
|
||||
load_poly()
|
||||
load_wall_engravings()
|
||||
load_prisoner_tattoos()
|
||||
LoadTrophies()
|
||||
LoadRecentMaps()
|
||||
LoadPhotoPersistence()
|
||||
LoadRandomizedRecipes()
|
||||
LoadPanicBunker() //SKYRAT EDIT ADDITION - PANICBUNKER
|
||||
load_trophies()
|
||||
load_recent_maps()
|
||||
load_photo_persistence()
|
||||
load_randomized_recipes()
|
||||
load_custom_outfits()
|
||||
load_delamination_counter()
|
||||
load_panic_bunker() //SKYRAT EDIT ADDITION - PANICBUNKER
|
||||
|
||||
load_adventures()
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
///Collects all data to persist.
|
||||
/datum/controller/subsystem/persistence/proc/collect_data()
|
||||
save_wall_engravings()
|
||||
save_prisoner_tattoos()
|
||||
CollectTrophies()
|
||||
CollectMaps()
|
||||
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()//SKYRAT EDIT ADDITION - PANICBUNKER
|
||||
SaveScars()
|
||||
collect_trophies()
|
||||
collect_maps()
|
||||
save_photo_persistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||
save_randomized_recipes()
|
||||
save_scars()
|
||||
save_custom_outfits()
|
||||
save_delamination_counter()
|
||||
save_panic_bunker() //SKYRAT EDIT ADDITION - PANICBUNKER
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPoly()
|
||||
///Loads up Poly's speech buffer.
|
||||
/datum/controller/subsystem/persistence/proc/load_poly()
|
||||
for(var/mob/living/simple_animal/parrot/poly/P in GLOB.alive_mob_list)
|
||||
twitterize(P.speech_buffer, "polytalk")
|
||||
break //Who's been duping the bird?!
|
||||
|
||||
///Loads all engravings, and places a select amount in maintenance and the prison.
|
||||
/datum/controller/subsystem/persistence/proc/load_wall_engravings()
|
||||
var/json_file = file(ENGRAVING_SAVE_FILE)
|
||||
if(!fexists(json_file))
|
||||
@@ -97,6 +100,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
log_world("Loaded [successfully_loaded_engravings] engraved messages on map [SSmapping.config.map_name]")
|
||||
|
||||
///Saves all new engravings in the world.
|
||||
/datum/controller/subsystem/persistence/proc/save_wall_engravings()
|
||||
var/list/saved_data = list()
|
||||
|
||||
@@ -136,6 +140,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
return json
|
||||
|
||||
///Loads all tattoos, and select a few based on the amount of prisoner spawn positions.
|
||||
/datum/controller/subsystem/persistence/proc/load_prisoner_tattoos()
|
||||
var/json_file = file(PRISONER_TATTOO_SAVE_FILE)
|
||||
if(!fexists(json_file))
|
||||
@@ -159,6 +164,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
log_world("Loaded [prison_tattoos_to_use.len] prison tattoos")
|
||||
|
||||
///Saves all tattoos, so they can appear on prisoners in future rounds
|
||||
/datum/controller/subsystem/persistence/proc/save_prisoner_tattoos()
|
||||
var/json_file = file(PRISONER_TATTOO_SAVE_FILE)
|
||||
var/list/saved_data = list()
|
||||
@@ -190,27 +196,68 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
return json
|
||||
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadTrophies()
|
||||
if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new
|
||||
var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav")
|
||||
var/saved_json
|
||||
S >> saved_json
|
||||
if(!saved_json)
|
||||
return
|
||||
saved_trophies = json_decode(saved_json)
|
||||
fdel("data/npc_saves/TrophyItems.sav")
|
||||
else
|
||||
/// Loads the trophies from the source file, and places a few in trophy display cases.
|
||||
/datum/controller/subsystem/persistence/proc/load_trophies()
|
||||
var/list/raw_saved_trophies = list()
|
||||
if(fexists("data/npc_saves/TrophyItems.json"))
|
||||
var/json_file = file("data/npc_saves/TrophyItems.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
saved_trophies = json["data"]
|
||||
SetUpTrophies(saved_trophies.Copy())
|
||||
raw_saved_trophies = json["data"]
|
||||
fdel("data/npc_saves/TrophyItems.json")
|
||||
else
|
||||
var/json_file = file("data/trophy_items.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
raw_saved_trophies = json["data"]
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
||||
for(var/raw_json in raw_saved_trophies)
|
||||
var/datum/trophy_data/parsed_trophy_data = new
|
||||
parsed_trophy_data.load_from_json(raw_json)
|
||||
saved_trophies += parsed_trophy_data
|
||||
|
||||
set_up_trophies()
|
||||
|
||||
///trophy data datum, for admin manipulation
|
||||
/datum/trophy_data
|
||||
///path of the item the trophy will try to mimic, null if path_string is invalid
|
||||
var/path
|
||||
///the message that appears under the item
|
||||
var/message
|
||||
///the key of the one who placed the item in the trophy case
|
||||
var/placer_key
|
||||
|
||||
/datum/trophy_data/proc/load_from_json(list/json_data)
|
||||
path = json_data["path"]
|
||||
message = json_data["message"]
|
||||
placer_key = json_data["placer_key"]
|
||||
|
||||
/datum/trophy_data/proc/to_json()
|
||||
var/list/new_data = list()
|
||||
new_data["path"] = path
|
||||
new_data["message"] = message
|
||||
new_data["placer_key"] = placer_key
|
||||
new_data["is_valid"] = text2path(path) ? TRUE : FALSE
|
||||
return new_data
|
||||
|
||||
/// Returns a list for the admin trophy panel.
|
||||
/datum/controller/subsystem/persistence/proc/trophy_ui_data()
|
||||
var/list/ui_data = list()
|
||||
for(var/datum/trophy_data/data in saved_trophies)
|
||||
var/list/pdata = data.to_json()
|
||||
pdata["ref"] = REF(data)
|
||||
ui_data += list(pdata)
|
||||
|
||||
return ui_data
|
||||
|
||||
/// Loads up the amount of times maps appeared to alter their appearance in voting and rotation.
|
||||
/datum/controller/subsystem/persistence/proc/load_recent_maps()
|
||||
var/map_sav = FILE_RECENT_MAPS
|
||||
if(!fexists(FILE_RECENT_MAPS))
|
||||
return
|
||||
@@ -231,44 +278,45 @@ SUBSYSTEM_DEF(persistence)
|
||||
if(run >= 2) //If run twice in the last KEEP_ROUNDS_MAP + 1 (including current) rounds, disable map for voting and rotation.
|
||||
blocked_maps += VM.map_name
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
|
||||
for(var/A in GLOB.trophy_cases)
|
||||
var/obj/structure/displaycase/trophy/T = A
|
||||
if (T.showpiece)
|
||||
continue
|
||||
T.added_roundstart = TRUE
|
||||
/// Puts trophies into trophy cases.
|
||||
/datum/controller/subsystem/persistence/proc/set_up_trophies()
|
||||
|
||||
var/trophy_data = pick_n_take(trophy_items)
|
||||
var/list/valid_trophies = list()
|
||||
|
||||
if(!islist(trophy_data))
|
||||
for(var/datum/trophy_data/data in saved_trophies)
|
||||
|
||||
if(!data) //sanity for incorrect deserialization
|
||||
continue
|
||||
|
||||
var/list/chosen_trophy = trophy_data
|
||||
|
||||
if(!length(chosen_trophy)) //Malformed
|
||||
var/path = text2path(data.path)
|
||||
if(!path) //If the item no longer exist, ignore it
|
||||
continue
|
||||
|
||||
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
|
||||
if(!path)
|
||||
valid_trophies += data
|
||||
|
||||
for(var/obj/structure/displaycase/trophy/trophy_case in GLOB.trophy_cases)
|
||||
if(!valid_trophies.len)
|
||||
break
|
||||
|
||||
if(trophy_case.showpiece)
|
||||
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_appearance()
|
||||
trophy_case.set_up_trophy(pick_n_take(valid_trophies))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
|
||||
///Loads up the photo album source file.
|
||||
/datum/controller/subsystem/persistence/proc/get_photo_albums()
|
||||
var/album_path = file("data/photo_albums.json")
|
||||
if(fexists(album_path))
|
||||
return json_decode(file2text(album_path))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/GetPhotoFrames()
|
||||
///Loads up the photo frames source file.
|
||||
/datum/controller/subsystem/persistence/proc/get_photo_frames()
|
||||
var/frame_path = file("data/photo_frames.json")
|
||||
if(fexists(frame_path))
|
||||
return json_decode(file2text(frame_path))
|
||||
|
||||
/// Removes the identifier of a persitent photo frame from the json.
|
||||
/datum/controller/subsystem/persistence/proc/RemovePhotoFrame(identifier)
|
||||
/// Removes the identifier of a persistent photo frame from the json.
|
||||
/datum/controller/subsystem/persistence/proc/remove_photo_frames(identifier)
|
||||
var/frame_path = file("data/photo_frames.json")
|
||||
if(!fexists(frame_path))
|
||||
return
|
||||
@@ -280,7 +328,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(frame_path)
|
||||
WRITE_FILE(frame_path, frame_json)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPhotoPersistence()
|
||||
///Loads photo albums, and populates them; also loads and applies frames to picture frames.
|
||||
/datum/controller/subsystem/persistence/proc/load_photo_persistence()
|
||||
var/album_path = file("data/photo_albums.json")
|
||||
var/frame_path = file("data/photo_frames.json")
|
||||
if(fexists(album_path))
|
||||
@@ -303,7 +352,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
if(json[PF.persistence_id])
|
||||
PF.load_from_id(json[PF.persistence_id])
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SavePhotoPersistence()
|
||||
///Saves the contents of photo albums and the picture frames.
|
||||
/datum/controller/subsystem/persistence/proc/save_photo_persistence()
|
||||
var/album_path = file("data/photo_albums.json")
|
||||
var/frame_path = file("data/photo_frames.json")
|
||||
|
||||
@@ -339,13 +389,25 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
WRITE_FILE(frame_path, frame_json)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectTrophies()
|
||||
var/json_file = file("data/npc_saves/TrophyItems.json")
|
||||
///Collects trophies from all existing trophy cases.
|
||||
/datum/controller/subsystem/persistence/proc/collect_trophies()
|
||||
for(var/trophy_case in GLOB.trophy_cases)
|
||||
save_trophy(trophy_case)
|
||||
|
||||
var/json_file = file("data/trophy_items.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = remove_duplicate_trophies(saved_trophies)
|
||||
var/list/converted_data = list()
|
||||
|
||||
for(var/datum/trophy_data/data in saved_trophies)
|
||||
converted_data += list(data.to_json())
|
||||
|
||||
converted_data = remove_duplicate_trophies(converted_data)
|
||||
|
||||
file_data["data"] = converted_data
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
///gets the list of json trophies, and deletes the ones with an identical path and message
|
||||
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
|
||||
var/list/ukeys = list()
|
||||
. = list()
|
||||
@@ -357,15 +419,17 @@ SUBSYSTEM_DEF(persistence)
|
||||
. += list(trophy)
|
||||
ukeys[tkey] = TRUE
|
||||
|
||||
/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)
|
||||
///If there is a trophy in the trophy case, saved it, if the trophy was not a holo trophy and has a message attached.
|
||||
/datum/controller/subsystem/persistence/proc/save_trophy(obj/structure/displaycase/trophy/trophy_case)
|
||||
if(!trophy_case.holographic_showpiece && trophy_case.showpiece && trophy_case.trophy_message)
|
||||
var/datum/trophy_data/data = new
|
||||
data.path = trophy_case.showpiece.type
|
||||
data.message = trophy_case.trophy_message
|
||||
data.placer_key = trophy_case.placer_key
|
||||
saved_trophies += data
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectMaps()
|
||||
///Updates the list of the most recent maps.
|
||||
/datum/controller/subsystem/persistence/proc/collect_maps()
|
||||
if(length(saved_maps) > KEEP_ROUNDS_MAP) //Get rid of extras from old configs.
|
||||
saved_maps.Cut(KEEP_ROUNDS_MAP+1)
|
||||
var/mapstosave = min(length(saved_maps)+1, KEEP_ROUNDS_MAP)
|
||||
@@ -380,7 +444,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRandomizedRecipes()
|
||||
///Loads all randomized recipes.
|
||||
/datum/controller/subsystem/persistence/proc/load_randomized_recipes()
|
||||
var/json_file = file("data/RandomizedChemRecipes.json")
|
||||
var/json
|
||||
if(fexists(json_file))
|
||||
@@ -404,7 +469,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
else
|
||||
log_game("Randomized recipe [randomized_type] resulted in conflicting recipes.")
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveRandomizedRecipes()
|
||||
///Saves all randomized recipes.
|
||||
/datum/controller/subsystem/persistence/proc/save_randomized_recipes()
|
||||
var/json_file = file("data/RandomizedChemRecipes.json")
|
||||
var/list/file_data = list()
|
||||
|
||||
@@ -418,7 +484,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveScars()
|
||||
///Saves all scars for everyone's original characters
|
||||
/datum/controller/subsystem/persistence/proc/save_scars()
|
||||
for(var/i in GLOB.joined_player_list)
|
||||
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
|
||||
if(!istype(ending_human) || !ending_human.mind?.original_character_slot_index || !ending_human.client?.prefs.read_preference(/datum/preference/toggle/persistent_scars))
|
||||
@@ -434,7 +501,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
else
|
||||
original_human.save_persistent_scars()
|
||||
|
||||
|
||||
///Loads the custom outfits of every admin.
|
||||
/datum/controller/subsystem/persistence/proc/load_custom_outfits()
|
||||
var/file = file("data/custom_outfits.json")
|
||||
if(!fexists(file))
|
||||
@@ -456,6 +523,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
continue
|
||||
GLOB.custom_outfits += outfit
|
||||
|
||||
///Saves each admin's custom outfit list
|
||||
/datum/controller/subsystem/persistence/proc/save_custom_outfits()
|
||||
var/file = file("data/custom_outfits.json")
|
||||
fdel(file)
|
||||
|
||||
@@ -9,28 +9,28 @@
|
||||
armor = list(MELEE = 30, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 10, BIO = 0, FIRE = 70, ACID = 100)
|
||||
max_integrity = 200
|
||||
integrity_failure = 0.25
|
||||
///The showpiece item inside the case
|
||||
var/obj/item/showpiece = null
|
||||
var/obj/item/showpiece_type = null //This allows for showpieces that can only hold items if they're the same istype as this.
|
||||
///This allows for showpieces that can only hold items if they're the same istype as this.
|
||||
var/obj/item/showpiece_type = null
|
||||
///Is the displaycase hooked up to a burglar alarm?
|
||||
var/alert = TRUE
|
||||
///Is the displaycase open at the moment?
|
||||
var/open = FALSE
|
||||
var/openable = TRUE
|
||||
var/custom_glass_overlay = FALSE ///If we have a custom glass overlay to use.
|
||||
///If we have a custom glass overlay to use.
|
||||
var/custom_glass_overlay = FALSE
|
||||
var/obj/item/electronics/airlock/electronics
|
||||
var/start_showpiece_type = null //add type for items on display
|
||||
var/list/start_showpieces = list() //Takes sublists in the form of list("type" = /obj/item/bikehorn, "trophy_message" = "henk")
|
||||
var/trophy_message = ""
|
||||
///Add type for items on display
|
||||
var/start_showpiece_type = null
|
||||
///Displaycase is fixed by glass
|
||||
var/glass_fix = TRUE
|
||||
///Represents a signel source of screaming when broken
|
||||
var/datum/alarm_handler/alarm_manager
|
||||
///Used for subtypes that have a UI in them. The examine on click while adjecent will not fire, as we already get a popup
|
||||
var/autoexamine_while_closed = TRUE
|
||||
|
||||
/obj/structure/displaycase/Initialize(mapload)
|
||||
. = ..()
|
||||
if(start_showpieces.len && !start_showpiece_type)
|
||||
var/list/showpiece_entry = pick(start_showpieces)
|
||||
if (showpiece_entry && showpiece_entry["type"])
|
||||
start_showpiece_type = showpiece_entry["type"]
|
||||
if (showpiece_entry["trophy_message"])
|
||||
trophy_message = showpiece_entry["trophy_message"]
|
||||
if(start_showpiece_type)
|
||||
showpiece = new start_showpiece_type (src)
|
||||
update_appearance()
|
||||
@@ -61,9 +61,8 @@
|
||||
. += span_notice("Hooked up with an anti-theft system.")
|
||||
if(showpiece)
|
||||
. += span_notice("There's \a [showpiece] inside.")
|
||||
if(trophy_message)
|
||||
. += "The plaque reads:\n [trophy_message]"
|
||||
|
||||
///Removes the showpiece from the displaycase
|
||||
/obj/structure/displaycase/proc/dump()
|
||||
if(QDELETED(showpiece))
|
||||
return
|
||||
@@ -124,27 +123,27 @@
|
||||
. += "[initial(icon_state)]_closed"
|
||||
return
|
||||
|
||||
/obj/structure/displaycase/attackby(obj/item/W, mob/living/user, params)
|
||||
if(W.GetID() && !broken && openable)
|
||||
/obj/structure/displaycase/attackby(obj/item/tool, mob/living/user, params)
|
||||
if(tool.GetID() && !broken)
|
||||
if(allowed(user))
|
||||
to_chat(user, span_notice("You [open ? "close":"open"] [src]."))
|
||||
to_chat(user, span_notice("You [open ? "close":"open"] [src]."))
|
||||
toggle_lock(user)
|
||||
else
|
||||
to_chat(user, span_alert("Access denied."))
|
||||
else if(W.tool_behaviour == TOOL_WELDER && !user.combat_mode && !broken)
|
||||
else if(tool.tool_behaviour == TOOL_WELDER && !user.combat_mode && !broken)
|
||||
if(atom_integrity < max_integrity)
|
||||
if(!W.tool_start_check(user, amount=5))
|
||||
if(!tool.tool_start_check(user, amount=5))
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("You begin repairing [src]..."))
|
||||
if(W.use_tool(src, user, 40, amount=5, volume=50))
|
||||
if(tool.use_tool(src, user, 40, amount=5, volume=50))
|
||||
atom_integrity = max_integrity
|
||||
update_appearance()
|
||||
to_chat(user, span_notice("You repair [src]."))
|
||||
else
|
||||
to_chat(user, span_warning("[src] is already in good condition!"))
|
||||
return
|
||||
else if(!alert && W.tool_behaviour == TOOL_CROWBAR && openable) //Only applies to the lab cage and player made display cases
|
||||
else if(!alert && tool.tool_behaviour == TOOL_CROWBAR) //Only applies to the lab cage and player made display cases
|
||||
if(broken)
|
||||
if(showpiece)
|
||||
to_chat(user, span_warning("Remove the displayed object first!"))
|
||||
@@ -153,35 +152,39 @@
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, span_notice("You start to [open ? "close":"open"] [src]..."))
|
||||
if(W.use_tool(src, user, 20))
|
||||
to_chat(user, span_notice("You [open ? "close":"open"] [src]."))
|
||||
if(tool.use_tool(src, user, 20))
|
||||
to_chat(user, span_notice("You [open ? "close":"open"] [src]."))
|
||||
toggle_lock(user)
|
||||
else if(open && !showpiece)
|
||||
insert_showpiece(W, user)
|
||||
else if(glass_fix && broken && istype(W, /obj/item/stack/sheet/glass))
|
||||
var/obj/item/stack/sheet/glass/G = W
|
||||
if(G.get_amount() < 2)
|
||||
insert_showpiece(tool, user)
|
||||
return TRUE //cancel the attack chain, wether we successfully placed an item or not
|
||||
else if(glass_fix && broken && istype(tool, /obj/item/stack/sheet/glass))
|
||||
var/obj/item/stack/sheet/glass/glass_sheet = tool
|
||||
if(glass_sheet.get_amount() < 2)
|
||||
to_chat(user, span_warning("You need two glass sheets to fix the case!"))
|
||||
return
|
||||
to_chat(user, span_notice("You start fixing [src]..."))
|
||||
if(do_after(user, 20, target = src))
|
||||
G.use(2)
|
||||
glass_sheet.use(2)
|
||||
broken = FALSE
|
||||
atom_integrity = max_integrity
|
||||
update_appearance()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/proc/insert_showpiece(obj/item/wack, mob/user)
|
||||
if(showpiece_type && !istype(wack, showpiece_type))
|
||||
///Handles placing an item into the display case. Returns TRUE if the item failed to be placed inside the container, useful for descendants
|
||||
/obj/structure/displaycase/proc/insert_showpiece(obj/item/new_showpiece, mob/user)
|
||||
if(showpiece_type && !istype(new_showpiece, showpiece_type))
|
||||
to_chat(user, span_notice("This doesn't belong in this kind of display."))
|
||||
return TRUE
|
||||
if(user.transferItemToLoc(wack, src))
|
||||
showpiece = wack
|
||||
to_chat(user, span_notice("You put [wack] on display."))
|
||||
if(user.transferItemToLoc(new_showpiece, src))
|
||||
showpiece = new_showpiece
|
||||
to_chat(user, span_notice("You put [new_showpiece] on display."))
|
||||
update_appearance()
|
||||
|
||||
///Opens and closes the display case
|
||||
/obj/structure/displaycase/proc/toggle_lock(mob/user)
|
||||
playsound(src, 'sound/machines/click.ogg', 20, TRUE)
|
||||
open = !open
|
||||
update_appearance()
|
||||
|
||||
@@ -200,10 +203,12 @@
|
||||
add_fingerprint(user)
|
||||
return
|
||||
else
|
||||
//prevents remote "kicks" with TK
|
||||
//prevents remote "kicks" with TK
|
||||
if (!Adjacent(user))
|
||||
return
|
||||
if (!user.combat_mode)
|
||||
if(!open && !autoexamine_while_closed)
|
||||
return
|
||||
if(!user.is_blind())
|
||||
user.examinate(src)
|
||||
return
|
||||
@@ -290,11 +295,17 @@
|
||||
/obj/structure/displaycase/trophy
|
||||
name = "trophy display case"
|
||||
desc = "Store your trophies of accomplishment in here, and they will stay forever."
|
||||
var/placer_key = ""
|
||||
var/added_roundstart = TRUE
|
||||
var/is_locked = TRUE
|
||||
integrity_failure = 0
|
||||
openable = FALSE
|
||||
req_access = list(ACCESS_LIBRARY)
|
||||
autoexamine_while_closed = FALSE
|
||||
///the key of the player who placed the item in the case
|
||||
var/placer_key = ""
|
||||
///is the trophy a hologram, not a real item placed by a player?
|
||||
var/holographic_showpiece = FALSE
|
||||
///are we about to edit
|
||||
var/historian_mode = FALSE
|
||||
///the trophy message
|
||||
var/trophy_message = ""
|
||||
|
||||
/obj/structure/displaycase/trophy/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -304,93 +315,121 @@
|
||||
GLOB.trophy_cases -= src
|
||||
return ..()
|
||||
|
||||
///Creates a showpiece dummy to display, using persistent data
|
||||
/obj/structure/displaycase/trophy/proc/set_up_trophy(datum/trophy_data/chosen_trophy)
|
||||
showpiece = new /obj/item/showpiece_dummy(src, text2path(chosen_trophy.path))
|
||||
trophy_message = trim(chosen_trophy.message, MAX_PLAQUE_LEN)
|
||||
if(trophy_message == "")
|
||||
trophy_message = trim(showpiece.desc, MAX_PLAQUE_LEN)
|
||||
placer_key = trim(chosen_trophy.placer_key)
|
||||
holographic_showpiece = TRUE
|
||||
update_appearance()
|
||||
|
||||
/obj/structure/displaycase/trophy/attackby(obj/item/W, mob/living/user, params)
|
||||
|
||||
if(!user.Adjacent(src)) //no TK museology
|
||||
if(istype(W, /obj/item/key/displaycase))
|
||||
toggle_historian_mode(user)
|
||||
return
|
||||
if(user.combat_mode)
|
||||
return ..()
|
||||
if(W.tool_behaviour == TOOL_WELDER && !broken)
|
||||
return ..()
|
||||
|
||||
if(user.is_holding_item_of_type(/obj/item/key/displaycase))
|
||||
if(added_roundstart)
|
||||
is_locked = !is_locked
|
||||
to_chat(user, span_notice("You [!is_locked ? "un" : ""]lock the case."))
|
||||
else
|
||||
to_chat(user, span_warning("The lock is stuck shut!"))
|
||||
return
|
||||
|
||||
if(is_locked)
|
||||
to_chat(user, span_warning("The case is shut tight with an old-fashioned physical lock. Maybe you should ask the curator for the key?"))
|
||||
return
|
||||
|
||||
if(!added_roundstart)
|
||||
to_chat(user, span_warning("You've already put something new in this case!"))
|
||||
return
|
||||
|
||||
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, span_warning("The case rejects the [W]!"))
|
||||
return
|
||||
|
||||
for(var/a in W.get_all_contents())
|
||||
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, span_warning("The case rejects the [W]!"))
|
||||
return
|
||||
|
||||
if(user.transferItemToLoc(W, src))
|
||||
|
||||
if(showpiece)
|
||||
to_chat(user, span_notice("You press a button, and [showpiece] descends into the floor of the case."))
|
||||
QDEL_NULL(showpiece)
|
||||
|
||||
to_chat(user, span_notice("You insert [W] into the case."))
|
||||
showpiece = W
|
||||
added_roundstart = FALSE
|
||||
update_appearance()
|
||||
|
||||
placer_key = user.ckey
|
||||
|
||||
trophy_message = W.desc //default value
|
||||
|
||||
var/chosen_plaque = tgui_input_text(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque", trophy_message)
|
||||
if(chosen_plaque)
|
||||
if(user.Adjacent(src))
|
||||
trophy_message = chosen_plaque
|
||||
to_chat(user, span_notice("You set the plaque's text."))
|
||||
else
|
||||
to_chat(user, span_warning("You are too far to set the plaque's text!"))
|
||||
|
||||
SSpersistence.SaveTrophy(src)
|
||||
return TRUE
|
||||
|
||||
else
|
||||
to_chat(user, span_warning("\The [W] is stuck to your hand, you can't put it in the [src.name]!"))
|
||||
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/trophy/dump()
|
||||
if (showpiece)
|
||||
if(added_roundstart)
|
||||
visible_message(span_danger("The [showpiece] crumbles to dust!"))
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
if(holographic_showpiece)
|
||||
visible_message(span_danger("[showpiece] fizzles and vanishes!"))
|
||||
do_sparks(number = 1, cardinal_only = FALSE, source = src)
|
||||
QDEL_NULL(showpiece)
|
||||
holographic_showpiece = FALSE
|
||||
else
|
||||
return ..()
|
||||
..()
|
||||
placer_key = ""
|
||||
trophy_message = null
|
||||
|
||||
/obj/structure/displaycase/trophy/insert_showpiece(obj/item/new_showpiece, mob/user)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(showpiece == new_showpiece)
|
||||
placer_key = user.ckey
|
||||
|
||||
///Toggles the mode that shows the historian panel on the UI, enabling saving the looks and the trophy message of the current trophy
|
||||
/obj/structure/displaycase/trophy/proc/toggle_historian_mode(mob/user)
|
||||
historian_mode = !historian_mode
|
||||
balloon_alert(user, "[historian_mode ? "enabled" : "disabled"] historian mode.")
|
||||
playsound(src, 'sound/machines/twobeep.ogg', vary = 50)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/structure/displaycase/trophy/toggle_lock(mob/user)
|
||||
..()
|
||||
SStgui.close_uis(src)
|
||||
|
||||
/obj/structure/displaycase/trophy/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["historian_mode"] = historian_mode
|
||||
data["holographic_showpiece"] = holographic_showpiece
|
||||
data["max_length"] = MAX_PLAQUE_LEN
|
||||
data["has_showpiece"] = showpiece ? TRUE : FALSE
|
||||
if(showpiece)
|
||||
data["showpiece_name"] = capitalize(format_text(showpiece.name))
|
||||
data["showpiece_description"] = trophy_message ? format_text(trophy_message) : null
|
||||
return data
|
||||
|
||||
/obj/structure/displaycase/trophy/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
if(showpiece)
|
||||
data["showpiece_icon"] = icon2base64(getFlatIcon(showpiece, no_anim=TRUE))
|
||||
return data
|
||||
|
||||
/obj/structure/displaycase/trophy/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("insert_key")
|
||||
if(historian_mode)
|
||||
return
|
||||
var/obj/item/key/displaycase/trophy_key = usr.get_active_held_item()
|
||||
if(istype(trophy_key))
|
||||
toggle_historian_mode(usr)
|
||||
return TRUE
|
||||
return
|
||||
if("change_message")
|
||||
if(showpiece && !holographic_showpiece)
|
||||
var/new_trophy_message = tgui_input_text(usr, "Let's make history!", "Trophy Message", trophy_message, MAX_PLAQUE_LEN)
|
||||
if(!new_trophy_message)
|
||||
return
|
||||
trophy_message = new_trophy_message
|
||||
return TRUE
|
||||
if("lock")
|
||||
if(!historian_mode)
|
||||
return
|
||||
toggle_historian_mode(usr)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/displaycase/trophy/ui_interact(mob/user, datum/tgui/ui)
|
||||
if(open)
|
||||
return
|
||||
if(isliving(usr))
|
||||
var/mob/living/living_usr = usr
|
||||
if(living_usr.combat_mode)
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Trophycase", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/item/key/displaycase
|
||||
name = "display case key"
|
||||
desc = "The key to the curator's display cases."
|
||||
|
||||
/obj/item/showpiece_dummy
|
||||
name = "Cheap replica"
|
||||
name = "holographic 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)
|
||||
var/obj/item/item_path = path
|
||||
name = initial(item_path.name)
|
||||
desc = initial(item_path.desc)
|
||||
icon = initial(item_path.icon)
|
||||
icon_state = initial(item_path.icon_state)
|
||||
|
||||
/obj/structure/displaycase/forsale
|
||||
name = "vend-a-tray"
|
||||
@@ -403,6 +442,7 @@
|
||||
alert = FALSE //No, we're not calling the fire department because someone stole your cookie.
|
||||
glass_fix = FALSE //Fixable with tools instead.
|
||||
pass_flags = PASSTABLE ///Can be placed and moved onto a table.
|
||||
autoexamine_while_closed = FALSE
|
||||
///The price of the item being sold. Altered by grab intent ID use.
|
||||
var/sale_price = 20
|
||||
///The Account which will receive payment for purchases. Set by the first ID to swipe the tray.
|
||||
@@ -417,6 +457,19 @@
|
||||
if(!broken && !open)
|
||||
. += "[initial(icon_state)]_overlay"
|
||||
|
||||
/obj/structure/displaycase/forsale/insert_showpiece(obj/item/new_showpiece, mob/user)
|
||||
if(..())
|
||||
return TRUE
|
||||
update_static_data_for_all_viewers()
|
||||
|
||||
/obj/structure/displaycase/forsale/dump()
|
||||
..()
|
||||
update_static_data_for_all_viewers()
|
||||
|
||||
/obj/structure/displaycase/forsale/toggle_lock()
|
||||
..()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/structure/displaycase/forsale/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
@@ -426,19 +479,18 @@
|
||||
|
||||
/obj/structure/displaycase/forsale/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/register = FALSE
|
||||
if(payments_acc)
|
||||
register = TRUE
|
||||
data["owner_name"] = payments_acc.account_holder
|
||||
if(showpiece)
|
||||
data["product_name"] = capitalize(showpiece.name)
|
||||
var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state))
|
||||
data["product_icon"] = base64
|
||||
data["registered"] = register
|
||||
data["owner_name"] = payments_acc ? payments_acc.account_holder : null
|
||||
data["product_name"] = showpiece ?capitalize(format_text(showpiece.name)) : null
|
||||
data["registered"] = payments_acc ? TRUE : FALSE
|
||||
data["product_cost"] = sale_price
|
||||
data["tray_open"] = open
|
||||
return data
|
||||
|
||||
/obj/structure/displaycase/forsale/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["product_icon"] = showpiece ? icon2base64(getFlatIcon(showpiece, no_anim=TRUE)) : null
|
||||
return data
|
||||
|
||||
/obj/structure/displaycase/forsale/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
@@ -471,16 +523,16 @@
|
||||
to_chat(usr, span_notice("You do not possess the funds to purchase this."))
|
||||
return TRUE
|
||||
else
|
||||
account.adjust_money(-sale_price, "Display Case: [capitalize(showpiece)]")
|
||||
account.adjust_money(-sale_price, "Display Case: [capitalize(showpiece.name)]")
|
||||
if(payments_acc)
|
||||
payments_acc.adjust_money(sale_price, "Display Case: [capitalize(showpiece)]")
|
||||
payments_acc.adjust_money(sale_price, "Display Case: [capitalize(showpiece.name)]")
|
||||
usr.put_in_hands(showpiece)
|
||||
to_chat(usr, span_notice("You purchase [showpiece] for [sale_price] credits."))
|
||||
playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE)
|
||||
flick("[initial(icon_state)]_vend", src)
|
||||
showpiece = null
|
||||
update_appearance()
|
||||
SStgui.update_uis(src)
|
||||
update_static_data_for_all_viewers()
|
||||
return TRUE
|
||||
if("Open")
|
||||
if(!payments_acc)
|
||||
@@ -492,7 +544,6 @@
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
|
||||
return
|
||||
toggle_lock()
|
||||
SStgui.update_uis(src)
|
||||
if("Register")
|
||||
if(payments_acc)
|
||||
return
|
||||
@@ -522,6 +573,7 @@
|
||||
SStgui.update_uis(src)
|
||||
return TRUE
|
||||
. = TRUE
|
||||
|
||||
/obj/structure/displaycase/forsale/attackby(obj/item/I, mob/living/user, params)
|
||||
if(isidcard(I))
|
||||
//Card Registration
|
||||
@@ -530,18 +582,16 @@
|
||||
to_chat(user, span_warning("This ID card has no account registered!"))
|
||||
return
|
||||
if(payments_acc == potential_acc.registered_account)
|
||||
playsound(src, 'sound/machines/click.ogg', 20, TRUE)
|
||||
toggle_lock()
|
||||
return
|
||||
if(istype(I, /obj/item/modular_computer))
|
||||
return TRUE
|
||||
SStgui.update_uis(src)
|
||||
. = ..()
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/forsale/multitool_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(atom_integrity <= (integrity_failure * max_integrity))
|
||||
if(atom_integrity <= (integrity_failure * max_integrity))
|
||||
to_chat(user, span_notice("You start recalibrating [src]'s hover field..."))
|
||||
if(do_after(user, 20, target = src))
|
||||
broken = FALSE
|
||||
|
||||
@@ -96,6 +96,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
|
||||
/client/proc/list_dna,
|
||||
/client/proc/list_fingerprints,
|
||||
/client/proc/message_pda, /*send a message to somebody on PDA*/
|
||||
/datum/admins/proc/trophy_manager,
|
||||
/client/proc/fax_panel, /*send a paper to fax*/
|
||||
)
|
||||
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel))
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/datum/admins/proc/trophy_manager()
|
||||
set name = "Trophy Manager"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/datum/trophy_manager/ui = new(usr)
|
||||
ui.ui_interact(usr)
|
||||
|
||||
/// Trophy Admin Management Panel
|
||||
/datum/trophy_manager
|
||||
|
||||
/datum/trophy_manager/ui_state(mob/user)
|
||||
return GLOB.admin_state
|
||||
|
||||
/datum/trophy_manager/ui_close(mob/user)
|
||||
qdel(src)
|
||||
|
||||
/datum/trophy_manager/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "TrophyAdminPanel")
|
||||
ui.open()
|
||||
|
||||
/datum/trophy_manager/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["trophies"] = SSpersistence.trophy_ui_data()
|
||||
return data
|
||||
|
||||
/datum/trophy_manager/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
if (!check_rights(R_ADMIN))
|
||||
return
|
||||
var/mob/user = usr
|
||||
var/datum/trophy_data/trophy = locate(params["ref"]) in SSpersistence.saved_trophies
|
||||
if(!trophy)
|
||||
return
|
||||
switch(action)
|
||||
if("delete")
|
||||
SSpersistence.saved_trophies -= trophy
|
||||
log_admin("[key_name(user)] has deleted a trophy made by [trophy.placer_key].")
|
||||
message_admins(span_notice("[key_name_admin(user)] has deleted trophy made by [trophy.placer_key]."))
|
||||
return TRUE
|
||||
if("edit_message")
|
||||
var/old_message = trophy.message
|
||||
var/new_message = tgui_input_text(user, "New trophy message?", "Message Editing", trophy.message, max_length = MAX_PLAQUE_LEN)
|
||||
if(!new_message)
|
||||
return
|
||||
trophy.message = new_message
|
||||
log_admin("[key_name(user)] has edited the message of trophy made by [trophy.placer_key] from \"[old_message]\" to \"[new_message]\".")
|
||||
return TRUE
|
||||
if("edit_path")
|
||||
var/old_path = trophy.path
|
||||
var/new_path = tgui_input_text(user, "New trophy path?", "Path Editing", trophy.path)
|
||||
if(!new_path)
|
||||
return
|
||||
if(!text2path(new_path))
|
||||
to_chat(user, span_warning("Invalid path selected"))
|
||||
return
|
||||
trophy.path = new_path
|
||||
log_admin("[key_name(user)] has edited the item path of trophy made by [trophy.placer_key] from \"[old_path]\" to \"[new_path]\".")
|
||||
return TRUE
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
//Manual loading, DO NOT USE FOR HARDCODED/MAPPED IN ALBUMS. This is for if an album needs to be loaded mid-round from an ID.
|
||||
/obj/item/storage/photo_album/proc/persistence_load()
|
||||
var/list/data = SSpersistence.GetPhotoAlbums()
|
||||
var/list/data = SSpersistence.get_photo_albums()
|
||||
if(data[persistence_id])
|
||||
populate_from_id_list(data[persistence_id])
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
/obj/structure/sign/picture_frame/Destroy()
|
||||
LAZYREMOVE(SSpersistence.photo_frames, src)
|
||||
if(persistence_id && del_id_on_destroy)
|
||||
SSpersistence.RemovePhotoFrame(persistence_id)
|
||||
SSpersistence.remove_photo_frames(persistence_id)
|
||||
return ..()
|
||||
|
||||
/obj/structure/sign/picture_frame/proc/get_photo_id()
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
//Manual loading, DO NOT USE FOR HARDCODED/MAPPED IN ALBUMS. This is for if an album needs to be loaded mid-round from an ID.
|
||||
/obj/structure/sign/picture_frame/proc/persistence_load()
|
||||
var/list/data = SSpersistence.GetPhotoFrames()
|
||||
var/list/data = SSpersistence.get_photo_frames()
|
||||
if(data[persistence_id])
|
||||
load_from_id(data[persistence_id])
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ GLOBAL_LIST_EMPTY(bunker_passthrough)
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(ckeytobypass)
|
||||
GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
|
||||
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
|
||||
SSpersistence.save_panic_bunker() //we can do this every time, it's okay
|
||||
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
|
||||
@@ -24,7 +24,7 @@ GLOBAL_LIST_EMPTY(bunker_passthrough)
|
||||
return
|
||||
|
||||
GLOB.bunker_passthrough -= ckey(ckeytobypass)
|
||||
SSpersistence.SavePanicBunker()
|
||||
SSpersistence.save_panic_bunker()
|
||||
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
|
||||
@@ -40,12 +40,12 @@ GLOBAL_LIST_EMPTY(bunker_passthrough)
|
||||
GLOB.bunker_passthrough |= ckey(params)
|
||||
|
||||
GLOB.bunker_passthrough[ckey(params)] = world.realtime
|
||||
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
|
||||
SSpersistence.save_panic_bunker() //we can do this every time, it's okay
|
||||
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
return "[params] has been added to the current round's bunker bypass list."
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
/datum/controller/subsystem/persistence/proc/load_panic_bunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
if(fexists(bunker_path))
|
||||
var/list/json = json_decode(file2text(bunker_path))
|
||||
@@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(bunker_passthrough)
|
||||
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
|
||||
GLOB.bunker_passthrough -= ckey
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
|
||||
/datum/controller/subsystem/persistence/proc/save_panic_bunker()
|
||||
var/json_file = file("data/bunker_passthrough.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = GLOB.bunker_passthrough
|
||||
|
||||
@@ -2163,6 +2163,7 @@
|
||||
#include "code\modules\admin\tag.dm"
|
||||
#include "code\modules\admin\team_panel.dm"
|
||||
#include "code\modules\admin\topic.dm"
|
||||
#include "code\modules\admin\trophy_manager.dm"
|
||||
#include "code\modules\admin\whitelist.dm"
|
||||
#include "code\modules\admin\callproc\callproc.dm"
|
||||
#include "code\modules\admin\smites\bad_luck.dm"
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { decodeHtmlEntities } from 'common/string';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Table } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const TrophyAdminPanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { trophies } = data;
|
||||
return (
|
||||
<Window title="Trophies Admin Panel" width={800} height={600}>
|
||||
<Window.Content scrollable>
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell color="label">Path</Table.Cell>
|
||||
<Table.Cell color="label" />
|
||||
<Table.Cell color="label">Message</Table.Cell>
|
||||
<Table.Cell color="label" />
|
||||
<Table.Cell color="label">Placer Key</Table.Cell>
|
||||
<Table.Cell color="label" />
|
||||
</Table.Row>
|
||||
{!!trophies &&
|
||||
trophies.map((trophy) => (
|
||||
<Table.Row key={trophy.ref} className="candystripe">
|
||||
<Table.Cell
|
||||
style={{
|
||||
'word-break': 'break-all',
|
||||
'word-wrap': 'break-word',
|
||||
'color': !trophy.is_valid
|
||||
? 'rgba(255, 0, 0, 0.5)'
|
||||
: 'inherit',
|
||||
}}>
|
||||
{decodeHtmlEntities(trophy.path)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon="edit"
|
||||
tooltip={'Edit path'}
|
||||
tooltipPosition="bottom"
|
||||
onClick={() => act('edit_path', { ref: trophy.ref })}
|
||||
/>
|
||||
</Table.Cell>
|
||||
<Table.Cell
|
||||
style={{
|
||||
'word-break': 'break-all',
|
||||
'word-wrap': 'break-word',
|
||||
}}>
|
||||
{decodeHtmlEntities(trophy.message)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon="edit"
|
||||
tooltip={'Edit message'}
|
||||
tooltipPosition="bottom"
|
||||
onClick={() => act('edit_message', { ref: trophy.ref })}
|
||||
/>
|
||||
</Table.Cell>
|
||||
<Table.Cell
|
||||
style={{
|
||||
'word-break': 'break-all',
|
||||
'word-wrap': 'break-word',
|
||||
}}>
|
||||
{decodeHtmlEntities(trophy.placer_key)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon="trash"
|
||||
tooltip={'Delete trophy'}
|
||||
tooltipPosition="bottom"
|
||||
onClick={() => act('delete', { ref: trophy.ref })}
|
||||
/>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,159 @@
|
||||
import { decodeHtmlEntities } from 'common/string';
|
||||
import { useBackend } from '../backend';
|
||||
import { Icon, Box, Button, Dimmer, Section, Stack } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Trophycase = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Window width={300} height={380}>
|
||||
<Window.Content>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<ShowpieceName />
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<ShowpieceImage />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<ShowpieceDescription />
|
||||
</Stack.Item>
|
||||
<Stack.Divider />
|
||||
<Stack.Item>
|
||||
<HistorianPanel />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const HistorianPanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
has_showpiece,
|
||||
historian_mode,
|
||||
holographic_showpiece,
|
||||
showpiece_description,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section align="left">
|
||||
{!historian_mode && (
|
||||
<Button
|
||||
icon="key"
|
||||
content="Insert key for historian mode"
|
||||
onClick={() => act('insert_key')}
|
||||
/>
|
||||
)}
|
||||
{!!historian_mode && (
|
||||
<div>
|
||||
<Button
|
||||
icon="times"
|
||||
content="Lock historian mode"
|
||||
onClick={() => act('lock')}
|
||||
/>
|
||||
<Button
|
||||
icon="pencil"
|
||||
content="Edit description"
|
||||
disabled={!has_showpiece || holographic_showpiece}
|
||||
onClick={() => act('change_message')}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!!historian_mode && !!holographic_showpiece && (
|
||||
<Box>
|
||||
A holographic trophy is already present. Replace it with a new trophy
|
||||
to create a new recording.
|
||||
</Box>
|
||||
)}
|
||||
{!!historian_mode && !has_showpiece && <Box>No trophies located.</Box>}
|
||||
{!!historian_mode &&
|
||||
!!has_showpiece &&
|
||||
!holographic_showpiece &&
|
||||
!!showpiece_description && (
|
||||
<Box>
|
||||
Recording has begun. Trophy data will be saved overnight, as long as
|
||||
the trophy stays within an intact case.
|
||||
</Box>
|
||||
)}
|
||||
{!!historian_mode &&
|
||||
!!has_showpiece &&
|
||||
!holographic_showpiece &&
|
||||
!showpiece_description && (
|
||||
<Box>
|
||||
New trophy detected. Please record a description to begin archival.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const ShowpieceDescription = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
has_showpiece,
|
||||
holographic_showpiece,
|
||||
historian_mode,
|
||||
max_length,
|
||||
showpiece_description,
|
||||
} = data;
|
||||
return (
|
||||
<Section fill align="center">
|
||||
{!has_showpiece && (
|
||||
<Box fill className="Trophycase-description">
|
||||
<b>This exhibit is empty. History awaits your contribution!</b>
|
||||
</Box>
|
||||
)}
|
||||
{!!holographic_showpiece && <b>{showpiece_description}</b>}
|
||||
{!holographic_showpiece && !!has_showpiece && (
|
||||
<Box fill className="Trophycase-description">
|
||||
{showpiece_description
|
||||
? decodeHtmlEntities(showpiece_description)
|
||||
: "This exhibit is under construction. Get the curator's key to finalize your contribution!"}
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const ShowpieceImage = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const { showpiece_icon } = data;
|
||||
return showpiece_icon ? (
|
||||
<Section align="center">
|
||||
<Box
|
||||
as="img"
|
||||
m={1}
|
||||
src={`data:image/jpeg;base64,${showpiece_icon}`}
|
||||
height="96px"
|
||||
width="96px"
|
||||
style={{
|
||||
'-ms-interpolation-mode': 'nearest-neighbor',
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
) : (
|
||||
<Section align="center">
|
||||
<Box height="96px" width="96px">
|
||||
<Dimmer fontSize="32px">
|
||||
<Icon name="landmark" />
|
||||
</Dimmer>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const ShowpieceName = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const { showpiece_name } = data;
|
||||
return (
|
||||
<Section align="center">
|
||||
<b>
|
||||
{showpiece_name
|
||||
? decodeHtmlEntities(showpiece_name)
|
||||
: 'Under construction.'}
|
||||
</b>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
.Trophycase-description {
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -67,6 +67,7 @@
|
||||
@include meta.load-css('./interfaces/Safe.scss');
|
||||
@include meta.load-css('./interfaces/TachyonArray.scss');
|
||||
@include meta.load-css('./interfaces/Techweb.scss');
|
||||
@include meta.load-css('./interfaces/Trophycase.scss');
|
||||
@include meta.load-css('./interfaces/RequestManager.scss');
|
||||
@include meta.load-css('./interfaces/UtilityModulesPane.scss');
|
||||
@include meta.load-css('./interfaces/Fabricator.scss');
|
||||
|
||||
Reference in New Issue
Block a user