Artifacts Panel (#27729)

* artifact_panel

* sanity

* varedit

* fixes

* init order fix

* better archiving

* derp

* okgood

* finishing touches
This commit is contained in:
DeityLink
2020-09-06 03:24:42 +02:00
committed by GitHub
parent 2d0871dc03
commit 1d6c038c9b
25 changed files with 285 additions and 11 deletions

View File

@@ -3,7 +3,7 @@ var/datum/subsystem/xenoarch/SSxenoarch
/datum/subsystem/xenoarch
name = "Xenoarch"
init_order = SS_INIT_MORE_INIT
init_order = SS_INIT_XENOARCH
flags = SS_NO_FIRE
var/list/artifact_spawning_turfs = list()
@@ -15,6 +15,7 @@ var/datum/subsystem/xenoarch/SSxenoarch
/datum/subsystem/xenoarch/Initialize(timeofday)
SetupXenoarch()
..()

View File

@@ -1198,6 +1198,10 @@ var/list/arcane_tomes = list()
..()
qdel(src)
/obj/item/weapon/bloodcult_pamphlet/oneuse/Destroy()
new /datum/artifact_postmortem_data(src)
..()
//Jaunter: creates a pylon on spawn, lets you teleport to it on use
/obj/item/weapon/bloodcult_jaunter
name = "test jaunter"

View File

@@ -106,6 +106,7 @@
attached = null //Reset attached cable
/obj/machinery/singularity_beacon/Destroy()
new /datum/artifact_postmortem_data(src,TRUE)//we only archive those that were excavated
if(active)
deactivate()
if(cell)

View File

@@ -19,6 +19,10 @@
var/selfdestructing = FALSE
var/ready= TRUE
/obj/machinery/syndicate_beacon/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/machinery/syndicate_beacon/attack_hand(var/mob/user)
if(isobserver(user))
to_chat(user, "<span class='rose'>Your ghostly hand goes right through!</span>")

View File

@@ -7,6 +7,10 @@
w_class = 1
var/genomes_to_give = 10 //seeing as the new changeling won't have had a whole round to prepare, they get some genomes free
/obj/item/changeling_vial/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/item/changeling_vial/attack_self(mob/user as mob)
if(ishuman(user) && !(isantagbanned(user) || jobban_isbanned(user, CHANGELING)))
var/mob/living/carbon/human/H = user

View File

@@ -14,6 +14,7 @@
var/obj/structure/ore_box/OB //The orebox contained within
/obj/structure/bed/chair/vehicle/gigadrill/Destroy()
new /datum/artifact_postmortem_data(src)
if(OB)
OB.forceMove(get_turf(src))
OB = null

View File

@@ -88,6 +88,7 @@ var/list/admin_verbs_admin = list(
/client/proc/credits_panel, /*allows you to customize the roundend credits before they happen*/
/client/proc/persistence_panel, /*lets you check out the kind of shit that will persist to the next round and say "holy fuck no"*/
/client/proc/diseases_panel,
/client/proc/artifacts_panel,
/client/proc/climate_panel
)
var/list/admin_verbs_ban = list(

View File

@@ -0,0 +1,175 @@
//Something to remember destroyed artifacts without keeping the atom floating in nullspace
/datum/artifact_postmortem_data
var/artifact_id = "<error>-000"
var/turf/last_loc = null
var/artifact_type = null
var/primary_effect = ""
var/secondary_effect = ""
/datum/artifact_postmortem_data/New(var/atom/artifact,var/ignore = FALSE,var/error = FALSE)
if (!artifact)
if (!error)//if we know we're generating an corrupted archive, just return so we can fill in the data manually afterwards.
qdel(src)
return
var/found = FALSE
for(var/ID in excavated_large_artifacts)
if (excavated_large_artifacts[ID] == artifact)
excavated_large_artifacts -= ID
artifact_id = ID
found = TRUE
if (!found)
if (ignore)
qdel(src)
return
else
artifact_id = generate_artifact_id()
last_loc = get_turf(artifact)
artifact_type = artifact.type
if (istype(artifact, /obj/machinery/artifact))
var/obj/machinery/artifact/A = artifact
if (A.primary_effect)
primary_effect = A.primary_effect.effecttype
if (A.secondary_effect)
secondary_effect = A.secondary_effect.effecttype
destroyed_large_artifacts[artifact_id] = src
////////////////////////The Actual Panel//////////////////////////////////////
/datum/admins/proc/artifacts_panel()
if (!(SSxenoarch?.initialized))
to_chat(usr,"<span class='danger'>The Xenoarch subsystem hasn't initialized yet!</span>")
else if (!SSxenoarch?.artifact_spawning_turfs.len)
to_chat(usr,"<span class='danger'>The Xenoarch subsystem seems to not have spawned any large artifact in the map. Lack of valid asteroid turfs?</span>")
var/dat = {"<html>
<head>
<style>
table,h2 {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
}
td, th {
border: 1px solid #dddddd;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
</head>
<body>
<h2 style="text-align:center">Artifact Panel</h2>
<table>
<tr>
<th style="width:1%">Artifact ID</th>
<th style="width:1%">Status</th>
<th style="width:3%">Type</th>
<th style="width:1%">Primary Effect</th>
<th style="width:1%">Secondary Effect</th>
</tr>
"}
//First we list every large artifact that exists currently in the world.
//non-anomaly artifacts such as Mysterious Cloning Pod and Replicator that were admin-spawned won't appear here as they do not have an Artifact ID, unless they get analyzed later.
var/list/artifacts_checked_already = list()
for(var/ID in excavated_large_artifacts)
artifacts_checked_already += ID
var/atom/A = excavated_large_artifacts[ID]
if (!(A?.loc))
if (!(ID in destroyed_large_artifacts))
var/datum/artifact_postmortem_data/corrupted = new(null, FALSE, TRUE)
corrupted.artifact_id = ID
corrupted.last_loc = "not_a_turf"
corrupted.artifact_type = "error: no postmortem artifact data generated"
corrupted.primary_effect = ""
corrupted.secondary_effect = ""
destroyed_large_artifacts[ID] += corrupted
continue
var/turf/T = get_turf(A)
var/prim = ""
var/sec = ""
if (istype(A, /obj/machinery/artifact))
var/obj/machinery/artifact/artifact = A
if (artifact.primary_effect)
prim = artifact.primary_effect.effecttype
if (artifact.secondary_effect)
sec = artifact.secondary_effect.effecttype
dat += {"<tr>
<td>[ID]</td>
<td><font color='green'><b>Excavated</b><font> [istype(T)?"(<a href='?src=\ref[src];artifactpanel_jumpto=\ref[T]'>[T.x],[T.y],[T.z]</a>)":"(Unknown)"]</td>
<td>[A.type] <a href='?_src_=vars;Vars=\ref[A]'>\[VV\]</a> <a href='?_src_=vars;mark_object=\ref[A]'>\[mark datum\]</a></td>
<td>[prim]</td>
<td>[sec]</td>
</tr>
"}
//Next we list every large artifact that got destroyed
for(var/ID in destroyed_large_artifacts)
var/datum/artifact_postmortem_data/data = destroyed_large_artifacts[ID]
if (!istype(data))
continue
var/turf/T = data.last_loc
dat += {"<tr>
<td>[data.artifact_id]</td>
<td><font color='red'><b>Destroyed</b><font> [istype(T)?"(<a href='?src=\ref[src];artifactpanel_jumpto=\ref[T]'>[T.x],[T.y],[T.z]</a>)":"(Unknown)"]</td>
<td>[data.artifact_type]</td>
<td>[data.primary_effect]</td>
<td>[data.secondary_effect]</td>
</tr>
"}
for(var/ID in razed_large_artifacts)
var/datum/artifact_postmortem_data/data = razed_large_artifacts[ID]
if (!istype(data))
continue
var/turf/T = data.last_loc
dat += {"<tr>
<td>[data.artifact_id]</td>
<td><font color='red'><b>Razed</b><font> [istype(T)?"(<a href='?src=\ref[src];artifactpanel_jumpto=\ref[T]'>[T.x],[T.y],[T.z]</a>)":"(Unknown)"]</td>
<td>[data.artifact_type]</td>
<td>[data.primary_effect]</td>
<td>[data.secondary_effect]</td>
</tr>
"}
//Finally we list every large artifact still buried on the asteroid
for(var/obj/structure/boulder/boulder in boulders)
if (!boulder.artifact_find)
continue
var/turf/T = get_turf(boulder)
var/datum/artifact_find/A = boulder.artifact_find
dat += {"<tr>
<td>[A.artifact_id]</td>
<td><b>Boulder</b> [istype(T)?"(<a href='?src=\ref[src];artifactpanel_jumpto=\ref[T]'>[T.x],[T.y],[T.z]</a>)":"(Unknown)"]</td>
<td>[A.artifact_find_type]</td>
<td>[(A.artifact_find_type == /obj/machinery/artifact) ? "???":""]</td>
<td>[(A.artifact_find_type == /obj/machinery/artifact) ? "???":""]</td>
</tr>
"}
if (SSxenoarch)
for (var/turf/unsimulated/mineral/M in SSxenoarch.artifact_spawning_turfs)
if (!istype(M))
continue
if (!M.artifact_find)
continue
var/datum/artifact_find/A = M.artifact_find
dat += {"<tr>
<td>[A.artifact_id]</td>
<td><b>Buried</b> <a href='?src=\ref[src];artifactpanel_jumpto=\ref[M]'>([M.x],[M.y],[M.z])</a></td>
<td>[A.artifact_find_type]</td>
<td>[(A.artifact_find_type == /obj/machinery/artifact) ? "???":""]</td>
<td>[(A.artifact_find_type == /obj/machinery/artifact) ? "???":""]</td>
</tr>
"}
dat += {"</table>
</body>
</html>
"}
usr << browse(dat, "window=artifactspanel;size=840x450")

View File

@@ -609,6 +609,23 @@
O.manual_stop_follow(O.locked_to)
O.forceMove(get_turf(dish))
else if(href_list["artifactpanel_jumpto"])
if(!check_rights(R_ADMIN))
return
var/turf/T = locate(href_list["artifactpanel_jumpto"])
var/client/C = usr.client
if(!isobserver(usr))
C.admin_ghost()
sleep(2)
if(!isobserver(C.mob))
return
var/mob/dead/observer/O = C.mob
if(O.locked_to)
O.manual_stop_follow(O.locked_to)
O.forceMove(T)
else if(href_list["climate_timeleft"])
if(!check_rights(R_ADMIN))
return

View File

@@ -1347,7 +1347,14 @@ client/proc/check_convertables()
holder.diseases_panel()
log_admin("[key_name(usr)] checked the Diseases Panel.")
feedback_add_details("admin_verb","DIS")
return
/client/proc/artifacts_panel()
set name = "Artifacts Panel"
set category = "Admin"
if(holder)
holder.artifacts_panel()
log_admin("[key_name(usr)] checked the Artifacts Panel.")
feedback_add_details("admin_verb","ART")
/client/proc/climate_panel()
set name = "Climate Panel"

View File

@@ -367,6 +367,10 @@
hitsound_added = 'sound/weapons/slice.ogg'
attack_verb_override = "claws"
/obj/item/clothing/gloves/warping_claws/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/item/clothing/gloves/warping_claws/dexterity_check()
return FALSE

View File

@@ -11,6 +11,10 @@
var/infinite = 0 //by default the mask is destroyed after one use
var/blood_to_give = 300 //seeing as the new vampire won't have had a whole round to prepare, they get some blood free
/obj/item/clothing/mask/stone/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/item/clothing/mask/stone/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0)
if(spikes_out)
to_chat(M, "<span class='warning'>You can't get the mask over your face with its stone spikes in the way!</span>")

View File

@@ -481,6 +481,14 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
//destroyed artifacts have weird, unpleasant effects
//make sure to destroy them before changing the turf though
if(artifact_find && artifact_fail)
var/datum/artifact_postmortem_data/destroyed = new(null, FALSE, TRUE)
destroyed.artifact_id = artifact_find.artifact_id
destroyed.last_loc = src
destroyed.artifact_type = artifact_find.artifact_find_type
if (artifact_find.artifact_find_type == /obj/machinery/artifact)
destroyed.primary_effect = "???"
destroyed.secondary_effect = "???"
razed_large_artifacts[artifact_find.artifact_id] += destroyed
ArtifactRepercussion(src, usr, "", "[artifact_find.artifact_find_type]")
if(artifact_fail && !mineral)

View File

@@ -38,6 +38,10 @@
..()
update_icon()
/mob/living/simple_animal/hostile/roboduck/Destroy()
new /datum/artifact_postmortem_data(src,TRUE)//we only archive those that were excavated
..()
/mob/living/simple_animal/hostile/roboduck/update_icon()
if(angered)
icon_state = "[initial(icon_state)]_hostile"

View File

@@ -50,6 +50,8 @@ var/list/all_generated_artifact_ids = list()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Boulders - sometimes turn up after excavating turf - excavate further to try and find large xenoarch finds
var/list/boulders = list()
/obj/structure/boulder
name = "rocky debris"
desc = "Leftover rock from an excavation. May or may not contain an artifact, but if it does you better use a small pickaxe, lest you destroy it along with the debris."
@@ -64,12 +66,14 @@ var/list/all_generated_artifact_ids = list()
var/datum/artifact_find/artifact_find
/obj/structure/boulder/Destroy()
..()
boulders -= src
geological_data = null
artifact_find = null
..()
/obj/structure/boulder/New()
..()
boulders += src
icon_state = "boulder[rand(1,4)]"
excavation_level = rand(5,50)
@@ -112,14 +116,26 @@ var/list/all_generated_artifact_ids = list()
if(excavation_level > 100)
//failure
src.visible_message("<span class='danger'>\The [src] suddenly crumbles away.</span>")
to_chat(user, "<span class='rose'>\The [src] has disintegrated under your onslaught, any secrets it was holding are long gone.</span>")
visible_message("<span class='danger'>\The [src] suddenly crumbles away.</span>")
if(artifact_find)//destroyed artifacts have weird, unpleasant effects
var/datum/artifact_postmortem_data/destroyed = new(null, FALSE, TRUE)
destroyed.artifact_id = artifact_find.artifact_id
destroyed.last_loc = get_turf(src)
destroyed.artifact_type = artifact_find.artifact_find_type
if (artifact_find.artifact_find_type == /obj/machinery/artifact)
destroyed.primary_effect = "???"
destroyed.secondary_effect = "???"
razed_large_artifacts[artifact_find.artifact_id] += destroyed
to_chat(user, "<span class='red'>As \the [src] disintegrates under your onslaught...</span>")//continued by the message from ArtifactRepercussion()
ArtifactRepercussion(src, usr, "", "[artifact_find.artifact_find_type]")
else
to_chat(user, "<span class='rose'>\The [src] has disintegrated under your onslaught.</span>")
qdel(src)
return
if(prob(excavation_level))
//success
src.visible_message("<span class='danger'>[src] suddenly crumbles away.</span>")
visible_message("<span class='danger'>[src] suddenly crumbles away.</span>")
if(artifact_find)
var/spawn_type = artifact_find.artifact_find_type
if (spawn_type == /obj/machinery/artifact)
@@ -132,7 +148,6 @@ var/list/all_generated_artifact_ids = list()
qdel(src)
else
busy = 0
return
/obj/structure/boulder/attack_construct(var/mob/user)
if (!Adjacent(user))

View File

@@ -16,6 +16,11 @@
machine_flags = WRENCHMOVE
/obj/machinery/auto_cloner/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/machinery/auto_cloner/New()
..()

View File

@@ -56,6 +56,7 @@
/obj/machinery/communication/Destroy()
for(var/stone in contents)
qdel(stone)
new /datum/artifact_postmortem_data(src)
..()
/obj/machinery/communication/proc/get_active_stones()

View File

@@ -17,6 +17,7 @@
"It's mesmerizing to behold.")
/obj/structure/crystal/Destroy()
new /datum/artifact_postmortem_data(src)
src.visible_message("<span class='danger'>[src] shatters!</span>")
src.investigation_log(I_ARTIFACT, "|| shattered by [key_name(usr)].")
if(prob(75))

View File

@@ -12,6 +12,7 @@
set_light(3,5,LIGHT_COLOR_RED)
/obj/structure/essence_printer/Destroy()
new /datum/artifact_postmortem_data(src)
if(bound_soul)
bound_soul.lazy_unregister_event(/lazy_event/on_death, src, .proc/print)
bound_soul = null

View File

@@ -10,6 +10,10 @@
density = 1
layer = ABOVE_OBJ_LAYER
/obj/machinery/giga_drill/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/machinery/giga_drill/attack_hand(mob/user as mob)
if(active)
active = 0

View File

@@ -8,6 +8,10 @@
step_in = 1
wreckage = /obj/effect/decal/mecha_wreckage/hoverpod
/obj/mecha/working/hoverpod/Destroy()
new /datum/artifact_postmortem_data(src)
..()
//duplicate of parent proc, but without space drifting
/obj/mecha/working/hoverpod/dyndomove(direction)
stopMechWalking()

View File

@@ -17,6 +17,10 @@
var/list/construction = list()
var/list/spawning_types = list()
/obj/machinery/replicator/Destroy()
new /datum/artifact_postmortem_data(src)
..()
/obj/machinery/replicator/New()
..()
@@ -58,7 +62,7 @@
/obj/item/weapon/handcuffs,
/obj/item/weapon/hatchet,
/obj/item/device/hailer,
/obj/item/weapon/storage/fancy/donut_box,
/obj/item/weapon/storage/fancy/donut_box,
/obj/item/clothing/accessory/holomap_chip, //Too far?
//Toys
@@ -93,7 +97,7 @@
/obj/item/pizzabox/vegetable,
/obj/item/pizzabox/mushroom,
/obj/item/weapon/beartrap,
/obj/item/stack/package_wrap/syndie,
/obj/item/stack/package_wrap/syndie,
/obj/item/device/handtv,
/obj/item/device/wormhole_jaunter,
/obj/item/mounted/poster,

View File

@@ -1,4 +1,6 @@
var/list/excavated_large_artifacts = list()
var/list/destroyed_large_artifacts = list()
var/list/razed_large_artifacts = list()//destroyed while still inside a rock wall/boulder
/obj/machinery/artifact
name = "alien artifact"
@@ -210,13 +212,13 @@ var/list/excavated_large_artifacts = list()
secondary_effect.UpdateMove()
/obj/machinery/artifact/Destroy()
new /datum/artifact_postmortem_data(src)
qdel(primary_effect); primary_effect = null
qdel(secondary_effect); secondary_effect = null
qdel(on_attackby); on_attackby = null
qdel(on_explode); on_explode = null
qdel(on_projectile); on_projectile = null
excavated_large_artifacts -= artifact_id
..()
/proc/ArtifactRepercussion(var/atom/source, var/mob/mob_cause = null, var/other_cause = "", var/artifact_type = "")

View File

@@ -101,6 +101,7 @@
set_frequency(frequency) //also broadcasts
/obj/machinery/power/supermatter/Destroy()
new /datum/artifact_postmortem_data(src,TRUE)//we only archive those that were excavated
qdel(radio)
radio = null
radio_controller.remove_object(src, frequency)

View File

@@ -1254,6 +1254,7 @@
#include "code\modules\admin\admin_memo.dm"
#include "code\modules\admin\admin_ranks.dm"
#include "code\modules\admin\admin_verbs.dm"
#include "code\modules\admin\artifacts_panel.dm"
#include "code\modules\admin\banappearance.dm"
#include "code\modules\admin\banjob.dm"
#include "code\modules\admin\banooc.dm"