From 7cc7778131ac17bc93f77dad82c270603d37efb2 Mon Sep 17 00:00:00 2001
From: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>
Date: Mon, 23 Sep 2024 21:26:17 +0200
Subject: [PATCH] Various VV work and fixes (#19288)
Refactored various procs used by VV: Header generation, dropdown menu
generation, moved various things around, some defines.
Fixed VV to be able to edit associative lists.
Fixed VV to be able to make a list ex nihilo on a var.
Removed various dropdown menus that didn't exist anymore and were doing
nothing.
Fixed add verb option to not wipe the already existing verbs of the mob.
Fixed a runtime error on some lists view building that were not handled
correctly.
Fixed an issue with build mode not having the correct permissions for
devs.
Fixed an issue with editing a list referenced by a key in another list
via the edit referenced object option.
Added DF_VAR_EDITED flag.
---
aurorastation.dme | 2 +
code/__DEFINES/_flags.dm | 1 +
code/__DEFINES/vv.dm | 15 +++
code/datums/datum.dm | 11 --
code/datums/datumvars.dm | 30 +++++
code/modules/admin/admin_verbs.dm | 2 +-
code/modules/admin/verbs/modifyvariables.dm | 13 ++-
code/modules/admin/view_variables/helpers.dm | 103 ++++++++----------
code/modules/admin/view_variables/topic.dm | 24 ++--
.../admin/view_variables/view_variables.dm | 57 +++++-----
html/changelogs/fluffyghost-vvandfixes.yml | 66 +++++++++++
11 files changed, 212 insertions(+), 112 deletions(-)
create mode 100644 code/__DEFINES/vv.dm
create mode 100644 code/datums/datumvars.dm
create mode 100644 html/changelogs/fluffyghost-vvandfixes.yml
diff --git a/aurorastation.dme b/aurorastation.dme
index 55e1e7d7a92..f13ba16a605 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -151,6 +151,7 @@
#include "code\__DEFINES\turfs.dm"
#include "code\__DEFINES\typeids.dm"
#include "code\__DEFINES\verbs.dm"
+#include "code\__DEFINES\vv.dm"
#include "code\__DEFINES\webhook.dm"
#include "code\__DEFINES\wires.dm"
#include "code\__DEFINES\xenoarch.dm"
@@ -422,6 +423,7 @@
#include "code\datums\category.dm"
#include "code\datums\computerfiles.dm"
#include "code\datums\datum.dm"
+#include "code\datums\datumvars.dm"
#include "code\datums\feedback.dm"
#include "code\datums\late_choices.dm"
#include "code\datums\local_network.dm"
diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm
index 0b7ecadf5b1..79d9e700376 100644
--- a/code/__DEFINES/_flags.dm
+++ b/code/__DEFINES/_flags.dm
@@ -5,6 +5,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
// for /datum/var/datum_flags
#define DF_USE_TAG (1<<0)
+#define DF_VAR_EDITED (1<<1)
#define DF_ISPROCESSING (1<<2)
///Whether /atom/Initialize() has already run for the object
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
new file mode 100644
index 00000000000..8fd54b4a159
--- /dev/null
+++ b/code/__DEFINES/vv.dm
@@ -0,0 +1,15 @@
+//#define IS_VALID_ASSOC_KEY(V) (istext(V) || ispath(V) || isdatum(V) || islist(V))
+#define IS_VALID_ASSOC_KEY(V) (!isnum(V)) //hhmmm..
+
+// vv_do_basic() keys
+#define VV_HK_BASIC_EDIT "datumedit"
+#define VV_HK_BASIC_CHANGE "datumchange"
+//This differs from TG
+#define VV_HK_BASIC_MASSEDIT "datummass"
+
+// /datum
+#define VV_HK_CALLPROC "proc_call"
+#define VV_HK_MARK "mark"
+
+//Helpers for vv_get_dropdown() - yes this is different from the tg one, cope
+#define VV_DROPDOWN_OPTION(href_key, name) . += ""
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 4d5b9bc2535..79b3621ca32 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -148,17 +148,6 @@
for(var/target in _signal_procs)
UnregisterSignal(target, _signal_procs[target])
-/datum/proc/can_vv_get(var_name)
- return TRUE
-
-/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
- if(var_name == NAMEOF(src, vars))
- return FALSE
- if(!can_vv_get(var_name))
- return FALSE
- vars[var_name] = var_value
- return TRUE
-
///Generate a tag for this /datum, if it implements one
///Should be called as early as possible, best would be in New, to avoid weakref mistargets
///Really just don't use this, you don't need it, global lists will do just fine MOST of the time
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
new file mode 100644
index 00000000000..943313fed8c
--- /dev/null
+++ b/code/datums/datumvars.dm
@@ -0,0 +1,30 @@
+/datum/proc/can_vv_get(var_name)
+ return TRUE
+
+/// Called when a var is edited with the new value to change to
+/datum/proc/vv_edit_var(var_name, var_value)
+ if(var_name == NAMEOF(src, vars))
+ return FALSE
+ if(!can_vv_get(var_name)) //This if block does not exist in tgstation code
+ return FALSE
+ vars[var_name] = var_value
+ datum_flags |= DF_VAR_EDITED
+ return TRUE
+
+/**
+ * Gets all the dropdown options in the vv menu.
+ * When overriding, make sure to call . = ..() first and appent to the result, that way parent items are always at the top and child items are further down.
+ * Add seperators by doing VV_DROPDOWN_OPTION("", "---")
+ */
+/datum/proc/vv_get_dropdown()
+ SHOULD_CALL_PARENT(TRUE)
+
+ . = list()
+ VV_DROPDOWN_OPTION("", "---")
+ VV_DROPDOWN_OPTION(VV_HK_CALLPROC, "Call Proc")
+ VV_DROPDOWN_OPTION(VV_HK_MARK, "Mark Object")
+
+/datum/proc/vv_get_header()
+ . = list()
+ if(("name" in vars) && !isatom(src))
+ . += "[vars["name"]] "
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index b0ce4ee642a..bf14c5ef1f1 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -744,7 +744,7 @@ var/list/admin_verbs_cciaa = list(
set name = "Toggle Build Mode Self"
set category = "Special Verbs"
- if(!check_rights(R_ADMIN))
+ if(!check_rights(R_ADMIN|R_SPAWN))
return
var/datum/click_handler/handler = mob.GetClickHandler()
if(handler.type == /datum/click_handler/build_mode)
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index 967f4585917..5c00a049d44 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -165,7 +165,13 @@ var/list/VVdynamic_lock = list(
/client/proc/mod_list(var/list/L, atom/O, original_name, objectvar)
if(!check_rights(R_VAREDIT|R_DEV)) return
- if(!istype(L,/list)) to_chat(src, "Not a List.")
+ if(!islist(L))
+ //May the omnissiah forgive me for this
+ if(tgui_alert(usr, "Not a list, make it a list?", "Make list", list("Yes", "No")) == "Yes")
+ O.vars[objectvar] = list()
+ L = O.vars[objectvar]
+ else
+ return
if(L.len > 1000)
var/confirm = alert(src, "The list you're trying to edit is very long, continuing may crash the server.", "Warning", "Continue", "Abort")
@@ -314,7 +320,10 @@ var/list/VVdynamic_lock = list(
L[L.Find(variable)] = variable
if("edit referenced object")
- modify_variables(variable)
+ if(islist(L?[variable]))
+ mod_list(L[variable], O, original_name, objectvar)
+ else
+ modify_variables(variable)
if("DELETE FROM LIST")
world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[variable]")]"
diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm
index 514316691c4..5ba0756622d 100644
--- a/code/modules/admin/view_variables/helpers.dm
+++ b/code/modules/admin/view_variables/helpers.dm
@@ -1,8 +1,6 @@
-/datum/proc/get_view_variables_header()
- return "[src]"
-
-/atom/get_view_variables_header()
- return {"
+/atom/vv_get_header()
+ . = ..()
+ . += {"
[src] <<
@@ -11,10 +9,10 @@
"}
-/mob/living/get_view_variables_header()
- return {"
- [src]
- <<[dir2text(dir)]>>
+/mob/living/vv_get_header()
+ . = ..()
+ . += {"
+
[ckey ? ckey : "No ckey"] / [real_name ? real_name : "No real name"]
BRUTE:[getBruteLoss()]
@@ -26,60 +24,47 @@
"}
-/datum/proc/get_view_variables_options()
- return ""
+/mob/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION("mob_player_panel", "Show player panel")
+ VV_DROPDOWN_OPTION("", "---")
+ VV_DROPDOWN_OPTION("give_spell", "Give Spell")
+ VV_DROPDOWN_OPTION("godmode", "Toggle Godmode")
-/mob/get_view_variables_options()
- return ..() + {"
-
-
-
-
-
-
-
+ VV_DROPDOWN_OPTION("make_skeleton", "Make 2spooky")
-
-
+ VV_DROPDOWN_OPTION("direct_control", "Assume Direct Control")
+ VV_DROPDOWN_OPTION("drop_everything", "Drop Everything")
-
-
+ VV_DROPDOWN_OPTION("regenerateicons", "Regenerate Icons")
+ VV_DROPDOWN_OPTION("addlanguage", "Add Language")
+ VV_DROPDOWN_OPTION("remlanguage", "Remove Language")
+ VV_DROPDOWN_OPTION("addorgan", "Add Organ")
+ VV_DROPDOWN_OPTION("remorgan", "Remove Organ")
-
-
-
-
-
+ VV_DROPDOWN_OPTION("addverb", "Add Verb")
+ VV_DROPDOWN_OPTION("remverb", "Remove Verb")
+ VV_DROPDOWN_OPTION("", "---")
+ VV_DROPDOWN_OPTION("gib", "Gib")
+ VV_DROPDOWN_OPTION("dust", "Turn to dust")
+ VV_DROPDOWN_OPTION("explode", "Trigger explosion")
+ VV_DROPDOWN_OPTION("emp", "Trigger EM pulse")
-
+/mob/living/carbon/human/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION("setspecies", "Set Species")
+ VV_DROPDOWN_OPTION("makeai", "Make AI")
+ VV_DROPDOWN_OPTION("makerobot", "Make cyborg")
+ VV_DROPDOWN_OPTION("makemonkey", "Make monkey")
+ VV_DROPDOWN_OPTION("makeslime", "Make slime")
-
-
-
-
-
-
-
- "}
+/obj/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION("delall", "Delete all of type")
+ VV_DROPDOWN_OPTION("explode", "Trigger explosion")
+ VV_DROPDOWN_OPTION("emp", "Trigger EM pulse")
-/mob/living/carbon/human/get_view_variables_options()
- return ..() + {"
-
-
-
-
-
- "}
-
-/obj/get_view_variables_options()
- return ..() + {"
-
-
-
- "}
-
-/turf/get_view_variables_options()
- return ..() + {"
-
-
- "}
+/turf/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION("explode", "Trigger explosion")
+ VV_DROPDOWN_OPTION("emp", "Trigger EM pulse")
diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm
index 3dab1edd738..036a7dbc9e3 100644
--- a/code/modules/admin/view_variables/topic.dm
+++ b/code/modules/admin/view_variables/topic.dm
@@ -29,30 +29,30 @@
href_list["datumrefresh"] = href_list["rename"]
- else if(href_list["varnameedit"] && href_list["datumedit"])
+ else if(href_list["varnameedit"] && href_list[VV_HK_BASIC_EDIT])
if(!check_rights(R_VAREDIT|R_DEV)) return
- var/D = locate(href_list["datumedit"])
+ var/D = locate(href_list[VV_HK_BASIC_EDIT])
if(!istype(D,/datum) && !istype(D,/client))
to_chat(usr, "This can only be used on instances of types /client or /datum")
return
modify_variables(D, href_list["varnameedit"], 1)
- else if(href_list["varnamechange"] && href_list["datumchange"])
+ else if(href_list["varnamechange"] && href_list[VV_HK_BASIC_CHANGE])
if(!check_rights(R_VAREDIT|R_DEV)) return
- var/D = locate(href_list["datumchange"])
+ var/D = locate(href_list[VV_HK_BASIC_CHANGE])
if(!istype(D,/datum) && !istype(D,/client))
to_chat(usr, "This can only be used on instances of types /client or /datum")
return
modify_variables(D, href_list["varnamechange"], 0)
- else if(href_list["varnamemass"] && href_list["datummass"])
+ else if(href_list["varnamemass"] && href_list[VV_HK_BASIC_MASSEDIT])
if(!check_rights(R_VAREDIT|R_DEV)) return
- var/atom/A = locate(href_list["datummass"])
+ var/atom/A = locate(href_list[VV_HK_BASIC_MASSEDIT])
if(!istype(A))
to_chat(usr, "This can only be used on instances of type /atom")
return
@@ -230,16 +230,16 @@
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
- else if(href_list["mark_object"])
+ else if(href_list[VV_HK_MARK])
if(!check_rights(0)) return
- var/datum/D = locate(href_list["mark_object"])
+ var/datum/D = locate(href_list[VV_HK_MARK])
if(!istype(D))
to_chat(usr, "This can only be done to instances of type /datum")
return
src.holder.marked_datum = D
- href_list["datumrefresh"] = href_list["mark_object"]
+ href_list["datumrefresh"] = href_list[VV_HK_MARK]
else if(href_list["rotatedatum"])
if(!check_rights(0)) return
@@ -395,7 +395,7 @@
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb)
if(/mob/living/silicon/ai)
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb)
- remove_verb(H, H.verbs)
+ possibleverbs -= H.verbs
possibleverbs += "Cancel" // ...And one for the bottom
var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs
@@ -507,8 +507,8 @@
message_admins(SPAN_NOTICE("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]"))
href_list["datumrefresh"] = href_list["mobToDamage"]
- else if(href_list["call_proc"])
- var/datum/D = locate(href_list["call_proc"])
+ else if(href_list[VV_HK_CALLPROC])
+ var/datum/D = locate(href_list[VV_HK_CALLPROC])
if(istype(D) || istype(D, /client)) // can call on clients too, not just datums
callproc_targetpicked(1, D)
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index 87d517314df..2b36c8c3639 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -5,8 +5,6 @@
/var/list/view_variables_hide_vars = list("bound_x", "bound_y", "bound_height", "bound_width", "bounds", "parent_type", "step_x", "step_y", "step_size")
// Variables not to expand the lists of. Vars is pointless to expand, and overlays/underlays cannot be expanded.
/var/list/view_variables_dont_expand = list("overlays", "underlays", "vars", "screen", "our_overlays", "priority_overlays", "queued_overlays")
-// Variables that runtime if you try to test associativity of the lists they contain by indexing
-/var/list/view_variables_no_assoc = list("verbs", "contents", "vis_contents")
// Acceptable 'in world', as VV would be incredibly hampered otherwise
/client/proc/debug_variables(datum/D in world)
@@ -14,31 +12,37 @@
set name = "View Variables"
debug_variables_open(D)
-/client/proc/debug_variables_open(var/datum/D, var/search = "")
+/client/proc/debug_variables_open(datum/thing, search = "")
if(!check_rights(0))
return
- if(!D)
+ if(!thing)
return
var/static/list/blacklist = list(/datum/configuration)
- if(is_type_in_list(D,blacklist))
+ if(is_type_in_list(thing,blacklist))
return
+ var/islist = islist(thing) || (!isdatum(thing) && hascall(thing, "Cut")) // Some special lists dont count as lists, but can be detected by if they have list procs
+
var/icon/sprite
- if(istype(D, /atom))
- var/atom/A = D
+ if(istype(thing, /atom))
+ var/atom/A = thing
if(A.icon && A.icon_state)
sprite = icon(A.icon, A.icon_state)
send_rsc(usr, sprite, "view_vars_sprite.png")
send_rsc(usr, 'code/js/view_variables.js', "view_variables.js")
+ var/list/header = islist ? list("/list") : thing.vv_get_header()
+
+ var/list/dropdownoptions = thing.vv_get_dropdown()
+
var/html = {"
- [D] ([REF(D)] - [D.type])
+ [thing] ([REF(thing)] - [thing.type])