diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index a53db2764de..13d91141c5d 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -24,3 +24,55 @@
#define VV_VISIBLE_ATOM "Visible Atom"
#define VV_INSIDE_VISIBLE_ATOM "Inside a Visible Atom"
#define VV_VISIBLE_TURF "Visible Turf"
+
+// VV href keys
+#define VV_HK_TARGET "target"
+
+// /datum
+#define VV_HK_PROC_CALL "proc_call"
+#define VV_HK_MARK_OBJECT "mark_object"
+#define VV_HK_DELETE "delete"
+#define VV_HK_MODIFY_TRAITS "traitmod"
+#define VV_HK_JUMP_TO "jump_to"
+#define VV_HK_TRAITMOD "traitmod"
+#define VV_HK_ADDCOMPONENT "addcomponent"
+#define VV_HK_REMOVECOMPONENT "removecomponent"
+#define VV_HK_MASSREMOVECOMPONENT "massremovecomponent"
+
+// /atom
+#define VV_HK_MANIPULATE_COLOR_MATRIX "manipcolours"
+#define VV_HK_ADDREAGENT "addreagent"
+#define VV_HK_EDITREAGENTS "editreagents"
+#define VV_HK_EXPLODE "explode"
+#define VV_HK_EMP "emp"
+
+// /obj
+#define VV_HK_DELALL "delall"
+#define VV_HK_MAKESPEEDY "makespeedy"
+#define VV_HK_MAKENORMALSPEED "makenormalspeed"
+#define VV_HK_MODIFYARMOR "modifyarmor"
+
+// /mob
+#define VV_HK_MOB_PLAYER_PANEL "mob_player_panel"
+#define VV_HK_GIVE_SPELL "give_spell"
+#define VV_HK_GIVEMARTIALART "givemartialart"
+#define VV_HK_GIVE_DISEASE "give_disease"
+#define VV_HK_GODMODE "godmode"
+#define VV_HK_BUILD_MODE "build_mode"
+#define VV_HK_MAKE_SKELETON "make_skeleton"
+#define VV_HK_HALLUCINATE "hallucinate"
+#define VV_HK_DIRECT_CONTROL "direct_control"
+#define VV_HK_OFFER_CONTROL "offer_control"
+#define VV_HK_DROP_EVERYTHING "drop_everything"
+#define VV_HK_REGENERATEICONS "regenerateicons"
+#define VV_HK_ADDLANGUAGE "addlanguage"
+#define VV_HK_REMLANGUAGE "remlanguage"
+#define VV_HK_ADDORGAN "addorgan"
+#define VV_HK_REMORGAN "remorgan"
+#define VV_HK_ADDVERB "addverb"
+#define VV_HK_REMVERB "remverb"
+#define VV_HK_GIB "gib"
+
+#define GET_VV_TARGET locateUID(href_list[VV_HK_TARGET])
+
+#define VV_DROPDOWN_OPTION(href_key, name) . += ""
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index f341062de18..9896ec71369 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -81,27 +81,61 @@
//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down
//add seperaters by doing . += "---"
/datum/proc/vv_get_dropdown()
+ SHOULD_CALL_PARENT(TRUE)
+
+ . = list()
+
+ VV_DROPDOWN_OPTION("", "---")
+ VV_DROPDOWN_OPTION(VV_HK_PROC_CALL, "Call Proc")
+ VV_DROPDOWN_OPTION(VV_HK_MARK_OBJECT, "Mark Object")
+ VV_DROPDOWN_OPTION(VV_HK_JUMP_TO, "Jump to Object")
+ VV_DROPDOWN_OPTION(VV_HK_DELETE, "Delete")
+ VV_DROPDOWN_OPTION(VV_HK_TRAITMOD, "Modify Traits")
+ VV_DROPDOWN_OPTION(VV_HK_ADDCOMPONENT, "Add Component/Element")
+ VV_DROPDOWN_OPTION(VV_HK_REMOVECOMPONENT, "Remove Component/Element")
+ VV_DROPDOWN_OPTION(VV_HK_MASSREMOVECOMPONENT, "Mass Remove Component/Element")
+ VV_DROPDOWN_OPTION("", "---")
+
+/**
+ * This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks!
+ * href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables!
+ * This proc is for "high level" actions like admin heal/set species/etc/etc. The low level debugging things should go in admin/view_variables/topic_basic.dm in case this runtimes.
+ */
+/datum/proc/vv_do_topic(list/href_list)
+ if(!usr || !usr.client || !usr.client.holder || !check_rights(R_VAREDIT))
+ return FALSE //This is VV, not to be called by anything else.
+ if(href_list[VV_HK_MODIFY_TRAITS])
+ usr.client.holder.modify_traits(src)
+
+ return TRUE
+
+/datum/proc/vv_get_header()
. = list()
- . += "---"
- .["Call Proc"] = "byond://?_src_=vars;proc_call=[UID()]"
- .["Mark Object"] = "byond://?_src_=vars;mark_object=[UID()]"
- .["Jump to Object"] = "byond://?_src_=vars;jump_to=[UID()]"
- .["Delete"] = "byond://?_src_=vars;delete=[UID()]"
- .["Modify Traits"] = "byond://?_src_=vars;traitmod=[UID()]"
- .["Add Component/Element"] = "byond://?_src_=vars;addcomponent=[UID()]"
- .["Remove Component/Element"] = "byond://?_src_=vars;removecomponent=[UID()]"
- .["Mass Remove Component/Element"] = "byond://?_src_=vars;massremovecomponent=[UID()]"
- . += "---"
/client/vv_get_dropdown()
- . = list()
- .["Manipulate Colour Matrix"] = "byond://?_src_=vars;manipcolours=[UID()]"
- . += "---"
- .["Call Proc"] = "byond://?_src_=vars;proc_call=[UID()]"
- .["Mark Object"] = "byond://?_src_=vars;mark_object=[UID()]"
- .["Delete"] = "byond://?_src_=vars;delete=[UID()]"
- .["Modify Traits"] = "byond://?_src_=vars;traitmod=[UID()]"
- . += "---"
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_MANIPULATE_COLOR_MATRIX, "Manipulate Color Matrix")
+ VV_DROPDOWN_OPTION("", "---")
+ VV_DROPDOWN_OPTION(VV_HK_PROC_CALL, "Call Proc")
+ VV_DROPDOWN_OPTION(VV_HK_MARK_OBJECT, "Mark Object")
+ VV_DROPDOWN_OPTION(VV_HK_DELETE, "Delete")
+ VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRAITS, "Modify Traits")
+ VV_DROPDOWN_OPTION("", "---")
+
+/client/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list[VV_HK_MANIPULATE_COLOR_MATRIX])
+ if(!check_rights(R_DEBUG))
+ return
+
+ message_admins("[key_name_admin(usr)] is manipulating the colour matrix for [src]")
+ var/datum/ui_module/colour_matrix_tester/CMT = new(target=src)
+ CMT.ui_interact(usr)
/client/proc/debug_variables(datum/D in world)
set name = "\[Admin\] View Variables"
@@ -150,34 +184,7 @@
if(sprite)
sprite_text = "
"
-
- var/list/atomsnowflake = list()
- if(isatom(D))
- var/atom/A = D
- if(isliving(A))
- var/mob/living/L = A
- atomsnowflake += "[L]"
- if(L.dir)
- atomsnowflake += " << [dir2text(L.dir)] >>"
- atomsnowflake += {"
- [L.ckey ? L.ckey : "No ckey"] / [L.real_name ? L.real_name : "No real name"]
-
- BRUTE:[L.getBruteLoss()]
- FIRE:[L.getFireLoss()]
- TOXIN:[L.getToxLoss()]
- OXY:[L.getOxyLoss()]
- CLONE:[L.getCloneLoss()]
- BRAIN:[L.getBrainLoss()]
- STAMINA:[L.getStaminaLoss()]
-
- "}
- else
- atomsnowflake += "[A]"
- if(A.dir)
- atomsnowflake += " << [dir2text(A.dir)] >>"
- else
- atomsnowflake += "[D]"
-
+ var/list/header = islist ? list("/list") : D.vv_get_header()
var/formatted_type = "[type]"
if(length(formatted_type) > 25)
@@ -205,7 +212,7 @@
varedited_line += " Var Edited"
- var/dropdownoptions = list()
+ var/list/dropdownoptions = list()
if(islist)
dropdownoptions = list(
"---",
@@ -218,16 +225,6 @@
else
dropdownoptions = D.vv_get_dropdown()
-
- var/list/dropdownoptions_html = list()
- for(var/name in dropdownoptions)
- var/link = dropdownoptions[name]
- if(link)
- dropdownoptions_html += ""
- else
- dropdownoptions_html += ""
-
-
var/list/names = list()
if(!islist)
for(var/V in D.vars)
@@ -395,7 +392,7 @@
|
[sprite_text]
- [atomsnowflake.Join()]
+ [header.Join()]
|
@@ -416,7 +413,7 @@
onmouseclick="this.focus()"
style="background-color:#ffffff">
- [dropdownoptions_html.Join()]
+ [dropdownoptions.Join()]
@@ -599,838 +596,19 @@
if(href_list["Vars"])
debug_variables(locateUID(href_list["Vars"]))
- //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
- else if(href_list["rename"])
- if(!check_rights(R_ADMIN)) return
+ var/target = GET_VV_TARGET
+ vv_core_topics(target, href_list, href)
+ if(isdatum(target))
+ var/datum/D = target
+ D.vv_do_topic(href_list)
- var/mob/M = locateUID(href_list["rename"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- var/new_name = reject_bad_name(sanitize(copytext_char(input(usr, "What would you like to name this mob?", "Input a name", M.real_name) as text|null, 1, MAX_NAME_LEN)), allow_numbers = TRUE)
- if(!new_name || !M) return
-
- message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
- M.rename_character(M.real_name, new_name)
- href_list["datumrefresh"] = href_list["rename"]
-
- else if(href_list["varnameedit"] && href_list["datumedit"])
- if(!check_rights(R_VAREDIT)) return
-
- var/D = locateUID(href_list["datumedit"])
- if(!istype(D,/datum) && !isclient(D))
- 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["togbit"])
- if(!check_rights(R_VAREDIT)) return
-
- var/atom/D = locateUID(href_list["subject"])
- if(!istype(D,/datum) && !isclient(D))
- to_chat(usr, "This can only be used on instances of types /client or /datum")
- return
- if(!(href_list["var"] in D.vars))
- to_chat(usr, "Unable to find variable specified.")
- return
- var/value = D.vars[href_list["var"]]
- value ^= 1 << text2num(href_list["togbit"])
-
- D.vars[href_list["var"]] = value
-
- else if(href_list["varnamechange"] && href_list["datumchange"])
- if(!check_rights(R_VAREDIT)) return
-
- var/D = locateUID(href_list["datumchange"])
- if(!istype(D,/datum) && !isclient(D))
- 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"])
- if(!check_rights(R_VAREDIT)) return
-
- var/atom/A = locateUID(href_list["datummass"])
- if(!istype(A))
- to_chat(usr, "This can only be used on instances of type /atom")
- return
-
- cmd_mass_modify_object_variables(A, href_list["varnamemass"])
-
-
- else if(href_list["mob_player_panel"])
- if(!check_rights(R_ADMIN|R_MOD)) return
-
- var/mob/M = locateUID(href_list["mob_player_panel"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- src.holder.show_player_panel(M)
- href_list["datumrefresh"] = href_list["mob_player_panel"]
-
- else if(href_list["give_spell"])
- if(!check_rights(R_SERVER|R_EVENT)) return
-
- var/mob/M = locateUID(href_list["give_spell"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- src.give_spell(M)
- href_list["datumrefresh"] = href_list["give_spell"]
-
- else if(href_list["givemartialart"])
- if(!check_rights(R_SERVER|R_EVENT)) return
-
- var/mob/living/carbon/C = locateUID(href_list["givemartialart"])
- if(!istype(C))
- to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
- return
-
- var/list/artpaths = subtypesof(/datum/martial_art)
- var/list/artnames = list()
- for(var/i in artpaths)
- var/datum/martial_art/M = i
- artnames[initial(M.name)] = M
-
- var/result = input(usr, "Choose the martial art to teach", "JUDO CHOP") as null|anything in artnames
- if(!usr)
- return
- if(QDELETED(C))
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- if(result)
- var/chosenart = artnames[result]
- var/datum/martial_art/MA = new chosenart
- MA.teach(C)
-
- href_list["datumrefresh"] = href_list["givemartialart"]
-
- else if(href_list["give_disease"])
- if(!check_rights(R_SERVER|R_EVENT)) return
-
- var/mob/M = locateUID(href_list["give_disease"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- src.give_disease(M)
- href_list["datumrefresh"] = href_list["give_spell"]
-
- else if(href_list["godmode"])
- if(!check_rights(R_EVENT)) return
-
- var/mob/M = locateUID(href_list["godmode"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- src.cmd_admin_godmode(M)
- href_list["datumrefresh"] = href_list["godmode"]
-
- else if(href_list["gib"])
- if(!check_rights(R_ADMIN|R_EVENT)) return
-
- var/mob/M = locateUID(href_list["gib"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- src.cmd_admin_gib(M)
-
- else if(href_list["build_mode"])
- if(!check_rights(R_BUILDMODE)) return
-
- var/mob/M = locateUID(href_list["build_mode"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- togglebuildmode(M)
- href_list["datumrefresh"] = href_list["build_mode"]
-
- else if(href_list["drop_everything"])
- if(!check_rights(R_DEBUG|R_ADMIN)) return
-
- var/mob/M = locateUID(href_list["drop_everything"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- if(usr.client)
- usr.client.cmd_admin_drop_everything(M)
-
- else if(href_list["direct_control"])
- if(!check_rights(R_DEBUG|R_ADMIN)) return
-
- var/mob/M = locateUID(href_list["direct_control"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- if(usr.client)
- usr.client.cmd_assume_direct_control(M)
-
- else if(href_list["make_skeleton"])
- if(!check_rights(R_SERVER|R_EVENT)) return
-
- var/mob/living/carbon/human/H = locateUID(href_list["make_skeleton"])
- if(!istype(H))
- to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
- return
-
- var/confirm = alert("Are you sure you want to turn this mob into a skeleton?","Confirm Skeleton Transformation","Yes","No")
- if(confirm != "Yes")
- return
-
- H.makeSkeleton()
- message_admins("[key_name(usr)] has turned [key_name(H)] into a skeleton")
- log_admin("[key_name_admin(usr)] has turned [key_name_admin(H)] into a skeleton")
- href_list["datumrefresh"] = href_list["make_skeleton"]
-
- else if(href_list["hallucinate"])
- if(!check_rights(R_SERVER | R_EVENT))
- return
-
- var/mob/living/carbon/human/C = locateUID(href_list["hallucinate"])
- if(!istype(C))
- to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
- return
-
- var/haltype = tgui_input_list(usr, "Select Hallucination Type", "Hallucinate", (subtypesof(/obj/effect/hallucination) + subtypesof(/datum/hallucination_manager)))
- if(!haltype)
- return
- C.invoke_hallucination(haltype)
- message_admins("[key_name(usr)] has given [key_name(C)] the [haltype] hallucination")
- log_admin("[key_name_admin(usr)] has given [key_name_admin(C)] the [haltype] hallucination")
- href_list["datumrefresh"] = href_list["hallucinate"]
-
- else if(href_list["offer_control"])
- if(!check_rights(R_ADMIN)) return
-
- var/mob/M = locateUID(href_list["offer_control"])
- if(!istype(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
- offer_control(M)
-
- else if(href_list["delete"])
- if(!check_rights(R_DEBUG, 0))
- return
-
- var/datum/D = locateUID(href_list["delete"])
- if(!D)
- to_chat(usr, "Unable to locate item!")
- admin_delete(D)
- href_list["datumrefresh"] = href_list["delete"]
-
- else if(href_list["delall"])
- if(!check_rights(R_DEBUG|R_SERVER)) return
-
- var/obj/O = locateUID(href_list["delall"])
- if(!isobj(O))
- to_chat(usr, "This can only be used on instances of type /obj")
- return
-
- var/action_type = alert("Strict type ([O.type]) or type and all subtypes?", null,"Strict type","Type and subtypes","Cancel")
- if(action_type == "Cancel" || !action_type)
- return
-
- if(alert("Are you really sure you want to delete all objects of type [O.type]?", null,"Yes","No") != "Yes")
- return
-
- if(alert("Second confirmation required. Delete?", null,"Yes","No") != "Yes")
- return
-
- var/O_type = O.type
- switch(action_type)
- if("Strict type")
- var/i = 0
- for(var/obj/Obj in world)
- if(Obj.type == O_type)
- i++
- qdel(Obj)
- if(!i)
- to_chat(usr, "No objects of this type exist")
- return
- log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)")
- message_admins("[key_name_admin(usr)] deleted all objects of type [O_type] ([i] objects deleted)")
- if("Type and subtypes")
- var/i = 0
- for(var/obj/Obj in world)
- if(istype(Obj,O_type))
- i++
- qdel(Obj)
- if(!i)
- to_chat(usr, "No objects of this type exist")
- return
- log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)")
- message_admins("[key_name_admin(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)")
-
- else if(href_list["makespeedy"])
- if(!check_rights(R_DEBUG|R_ADMIN))
- return
- var/obj/A = locateUID(href_list["makespeedy"])
- if(!istype(A))
- return
- A.var_edited = TRUE
- A.makeSpeedProcess()
- log_admin("[key_name(usr)] has made [A] speed process")
- message_admins("[key_name(usr)] has made [A] speed process")
- return TRUE
-
- else if(href_list["makenormalspeed"])
- if(!check_rights(R_DEBUG|R_ADMIN))
- return
- var/obj/A = locateUID(href_list["makenormalspeed"])
- if(!istype(A))
- return
- A.var_edited = TRUE
- A.makeNormalProcess()
- log_admin("[key_name(usr)] has made [A] process normally")
- message_admins("[key_name(usr)] has made [A] process normally")
- return TRUE
-
- else if(href_list["modifyarmor"])
- if(!check_rights(R_DEBUG|R_ADMIN))
- return
- var/obj/A = locateUID(href_list["modifyarmor"])
- if(!istype(A))
- return
- A.var_edited = TRUE
- var/list/armorlist = A.armor.getList()
- var/list/displaylist
-
- var/result
- do
- displaylist = list()
- for(var/key in armorlist)
- displaylist += "[key] = [armorlist[key]]"
- result = input(usr, "Select an armor type to modify..", "Modify armor") as null|anything in displaylist + "(ADD ALL)" + "(SET ALL)" + "(DONE)"
-
- if(result == "(DONE)")
- break
- else if(result == "(ADD ALL)" || result == "(SET ALL)")
- var/new_amount = input(usr, result == "(ADD ALL)" ? "Enter armor to add to all types:" : "Enter new armor value for all types:", "Modify all types") as num|null
- if(isnull(new_amount))
- continue
- var/proper_amount = text2num(new_amount)
- if(isnull(proper_amount))
- continue
- for(var/key in armorlist)
- armorlist[key] = (result == "(ADD ALL)" ? armorlist[key] : 0) + proper_amount
- else if(result)
- var/list/fields = splittext(result, " = ")
- if(length(fields) != 2)
- continue
- var/type = fields[1]
- if(isnull(armorlist[type]))
- continue
- var/new_amount = input(usr, "Enter new armor value for [type]:", "Modify [type]") as num|null
- if(isnull(new_amount))
- continue
- var/proper_amount = text2num(new_amount)
- if(isnull(proper_amount))
- continue
- armorlist[type] = proper_amount
- while(result)
-
- if(!result || !A)
- return TRUE
-
- A.armor = A.armor.setRating(armorlist[MELEE], armorlist[BULLET], armorlist[LASER], armorlist[ENERGY], armorlist[BOMB], armorlist[RAD], armorlist[FIRE], armorlist[ACID], armorlist[MAGIC])
-
- log_admin("[key_name(usr)] modified the armor on [A] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
- message_admins("[key_name(usr)] modified the armor on [A] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
- return TRUE
-
- else if(href_list["addreagent"]) /* Made on /TG/, credit to them. */
- if(!check_rights(R_DEBUG|R_ADMIN)) return
-
- var/atom/A = locateUID(href_list["addreagent"])
-
- if(!A.reagents)
- var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
- if(amount)
- A.create_reagents(amount)
-
- if(A.reagents)
- var/chosen_id
- var/list/reagent_options = sortAssoc(GLOB.chemical_reagents_list)
- switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
- if("Enter ID")
- var/valid_id
- while(!valid_id)
- chosen_id = stripped_input(usr, "Enter the ID of the reagent you want to add.")
- if(!chosen_id) //Get me out of here!
- break
- for(var/ID in reagent_options)
- if(ID == chosen_id)
- valid_id = 1
- if(!valid_id)
- to_chat(usr, "A reagent with that ID doesn't exist!")
- if("Choose ID")
- chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_options
- if(chosen_id)
- var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
- if(amount)
- A.reagents.add_reagent(chosen_id, amount)
- log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
- message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
-
- else if(href_list["editreagents"])
- if(!check_rights(R_DEBUG|R_ADMIN))
- return
-
- var/atom/A = locateUID(href_list["editreagents"])
-
- try_open_reagent_editor(A)
-
- else if(href_list["explode"])
- if(!check_rights(R_DEBUG|R_EVENT)) return
-
- var/atom/A = locateUID(href_list["explode"])
- if(!isobj(A) && !ismob(A) && !isturf(A))
- to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf")
- return
-
- src.cmd_admin_explosion(A)
- href_list["datumrefresh"] = href_list["explode"]
-
- else if(href_list["emp"])
- if(!check_rights(R_DEBUG|R_EVENT)) return
-
- var/atom/A = locateUID(href_list["emp"])
- if(!isobj(A) && !ismob(A) && !isturf(A))
- to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf")
- return
-
- src.cmd_admin_emp(A)
- href_list["datumrefresh"] = href_list["emp"]
-
- else if(href_list["mark_object"])
- if(!check_rights(0)) return
-
- var/datum/D = locateUID(href_list["mark_object"])
- 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"]
-
- else if(href_list["proc_call"])
- if(!check_rights(R_PROCCALL))
- return
-
- var/T = locateUID(href_list["proc_call"])
-
- if(T)
- callproc_datum(T)
-
- else if(href_list["jump_to"])
- if(!check_rights(R_ADMIN))
- return
-
- var/atom/A = locateUID(href_list["jump_to"])
- var/turf/T = get_turf(A)
- if(T)
- usr.client.jumptoturf(T)
- href_list["datumrefresh"] = href_list["jump_to"]
-
-
- else if(href_list["rotatedatum"])
- if(!check_rights(R_DEBUG|R_ADMIN)) return
-
- var/atom/A = locateUID(href_list["rotatedatum"])
- if(!istype(A))
- to_chat(usr, "This can only be done to instances of type /atom")
- return
-
- switch(href_list["rotatedir"])
- if("right") A.dir = turn(A.dir, -45)
- if("left") A.dir = turn(A.dir, 45)
-
- message_admins("[key_name_admin(usr)] has rotated \the [A]")
- log_admin("[key_name(usr)] has rotated \the [A]")
- href_list["datumrefresh"] = href_list["rotatedatum"]
-
- else if(href_list["addlanguage"])
- if(!check_rights(R_SPAWN)) return
-
- var/mob/H = locateUID(href_list["addlanguage"])
- if(!istype(H))
- to_chat(usr, "This can only be done to instances of type /mob")
- return
-
- var/new_language = input("Please choose a language to add.","Language",null) as null|anything in GLOB.all_languages
-
- if(!new_language)
- return
-
- if(!H)
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- if(H.add_language(new_language, TRUE))
- to_chat(usr, "Added [new_language] to [H].")
- message_admins("[key_name_admin(usr)] has given [key_name_admin(H)] the language [new_language]")
- log_admin("[key_name(usr)] has given [key_name(H)] the language [new_language]")
- else
- to_chat(usr, "Mob already knows that language.")
-
- else if(href_list["remlanguage"])
- if(!check_rights(R_SPAWN)) return
-
- var/mob/H = locateUID(href_list["remlanguage"])
- if(!istype(H))
- to_chat(usr, "This can only be done to instances of type /mob")
- return
-
- if(!length(H.languages))
- to_chat(usr, "This mob knows no languages.")
- return
-
- var/datum/language/rem_language = input("Please choose a language to remove.","Language",null) as null|anything in H.languages
-
- if(!rem_language)
- return
-
- if(!H)
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- if(H.remove_language(rem_language.name, TRUE))
- to_chat(usr, "Removed [rem_language] from [H].")
- message_admins("[key_name_admin(usr)] has removed language [rem_language] from [key_name_admin(H)]")
- log_admin("[key_name(usr)] has removed language [rem_language] from [key_name(H)]")
- else
- to_chat(usr, "Mob doesn't know that language.")
-
- else if(href_list["addverb"])
- if(!check_rights(R_DEBUG)) return
-
- var/mob/living/H = locateUID(href_list["addverb"])
-
- if(!istype(H))
- to_chat(usr, "This can only be done to instances of type /mob/living")
- return
- var/list/possibleverbs = list()
- possibleverbs += "Cancel" // One for the top...
- possibleverbs += typesof(/mob/proc,/mob/verb,/mob/living/proc,/mob/living/verb)
- switch(H.type)
- if(/mob/living/carbon/human)
- possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc)
- if(/mob/living/silicon/robot)
- 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)
- possibleverbs -= H.verbs
- possibleverbs += "Cancel" // ...And one for the bottom
-
- var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs
- if(!H)
- to_chat(usr, "Mob doesn't exist anymore")
- return
- if(!verb || verb == "Cancel")
- return
- else
- add_verb(H, verb)
- message_admins("[key_name_admin(usr)] has given [key_name_admin(H)] the verb [verb]")
- log_admin("[key_name(usr)] has given [key_name(H)] the verb [verb]")
-
- else if(href_list["remverb"])
- if(!check_rights(R_DEBUG)) return
-
- var/mob/H = locateUID(href_list["remverb"])
-
- if(!istype(H))
- to_chat(usr, "This can only be done to instances of type /mob")
- return
- var/verb = input("Please choose a verb to remove.","Verbs",null) as null|anything in H.verbs
- if(!H)
- to_chat(usr, "Mob doesn't exist anymore")
- return
- if(!verb)
- return
- else
- remove_verb(H, verb)
- message_admins("[key_name_admin(usr)] has removed verb [verb] from [key_name_admin(H)]")
- log_admin("[key_name(usr)] has removed verb [verb] from [key_name(H)]")
-
- else if(href_list["addorgan"])
- if(!check_rights(R_SPAWN)) return
-
- var/mob/living/carbon/M = locateUID(href_list["addorgan"])
- if(!istype(M))
- to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
- return
-
- var/new_organ = tgui_input_list(usr, "Please choose an organ to add.", "Organ", subtypesof(/obj/item/organ))
- if(!new_organ)
- return
-
- if(!M)
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- if(locateUID(new_organ) in M.internal_organs)
- to_chat(usr, "Mob already has that organ.")
- return
- var/obj/item/organ/internal/organ = new new_organ
- organ.insert(M)
- message_admins("[key_name_admin(usr)] has given [key_name_admin(M)] the organ [new_organ]")
- log_admin("[key_name(usr)] has given [key_name(M)] the organ [new_organ]")
-
- else if(href_list["remorgan"])
- if(!check_rights(R_SPAWN)) return
-
- var/mob/living/carbon/M = locateUID(href_list["remorgan"])
- if(!istype(M))
- to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
- return
-
- var/obj/item/organ/internal/rem_organ = tgui_input_list(usr, "Please choose an organ to remove.", "Organ", M.internal_organs)
-
- if(!M)
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- if(!(rem_organ in M.internal_organs))
- to_chat(usr, "Mob does not have that organ.")
- return
-
- to_chat(usr, "Removed [rem_organ] from [M].")
- rem_organ.remove(M)
- message_admins("[key_name_admin(usr)] has removed the organ [rem_organ] from [key_name_admin(M)]")
- log_admin("[key_name(usr)] has removed the organ [rem_organ] from [key_name(M)]")
- qdel(rem_organ)
-
- else if(href_list["regenerateicons"])
- if(!check_rights(0)) return
-
- var/mob/M = locateUID(href_list["regenerateicons"])
- if(!ismob(M))
- to_chat(usr, "This can only be done to instances of type /mob")
- return
- M.regenerate_icons()
-
- else if(href_list["adjustDamage"] && href_list["mobToDamage"])
- if(!check_rights(R_DEBUG|R_ADMIN|R_EVENT)) return
-
- var/mob/living/L = locateUID(href_list["mobToDamage"])
- if(!istype(L)) return
-
- var/Text = href_list["adjustDamage"]
-
- var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num
-
- if(!L)
- to_chat(usr, "Mob doesn't exist anymore")
- return
-
- switch(Text)
- if("brute")
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- H.adjustBruteLoss(amount, robotic = TRUE)
- else
- L.adjustBruteLoss(amount)
- if("fire")
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- H.adjustFireLoss(amount, robotic = TRUE)
- else
- L.adjustFireLoss(amount)
- if("toxin")
- L.adjustToxLoss(amount)
- if("oxygen")
- L.adjustOxyLoss(amount)
- if("brain")
- L.adjustBrainLoss(amount)
- if("clone")
- L.adjustCloneLoss(amount)
- if("stamina")
- L.adjustStaminaLoss(amount)
- else
- to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
- return
-
- if(amount != 0)
- log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]")
- message_admins("[key_name_admin(usr)] dealt [amount] amount of [Text] damage to [L]")
- href_list["datumrefresh"] = href_list["mobToDamage"]
-
- else if(href_list["traitmod"])
- if(!check_rights(NONE))
- return
- var/datum/A = locateUID(href_list["traitmod"])
- if(!istype(A))
- return
- holder.modify_traits(A)
-
- if(href_list["addcomponent"])
- if(!check_rights(NONE))
- return
- var/datum/target = locateUID(href_list["addcomponent"])
- if(!target)
- return
- var/list/names = list()
- var/list/componentsubtypes = sortList(subtypesof(/datum/component), GLOBAL_PROC_REF(cmp_typepaths_asc))
- names += "---Components---"
- names += componentsubtypes
- names += "---Elements---"
- names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
-
- var/result = tgui_input_list(usr, "Choose a component/element to add", "Add Component", names)
- if(isnull(result))
- return
- if(!usr || result == "---Components---" || result == "---Elements---")
- return
-
- if(QDELETED(src))
- to_chat(usr, "That thing doesn't exist anymore!", confidential = TRUE)
- return
-
- var/list/lst = get_callproc_args()
- if(!lst)
- return
-
- var/datumname = "error"
- lst.Insert(1, result)
- if(result in componentsubtypes)
- datumname = "component"
- target._AddComponent(lst)
- else
- datumname = "element"
- target._AddElement(lst)
- log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(target)].")
- message_admins("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(target)].")
- if(href_list["removecomponent"] || href_list["massremovecomponent"])
- if(!check_rights(NONE))
- return
- var/datum/target = href_list["removecomponent"] ? locateUID(href_list["removecomponent"]) : locateUID(href_list["massremovecomponent"])
- if(!target)
- return
- var/mass_remove = href_list["massremovecomponent"]
- var/list/components = target.datum_components.Copy()
- var/list/names = list()
- names += "---Components---"
- if(length(components))
- names += sortList(components, GLOBAL_PROC_REF(cmp_typepaths_asc))
- names += "---Elements---"
- // We have to list every element here because there is no way to know what element is on this object without doing some sort of hack.
- names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
- var/path = tgui_input_list(usr, "Choose a component/element to remove. All elements listed here may not be on the datum.", "Remove element", names)
- if(isnull(path))
- return
- if(!usr || path == "---Components---" || path == "---Elements---")
- return
- if(QDELETED(src))
- to_chat(usr, "That thing doesn't exist anymore!")
- return
- var/list/targets_to_remove_from = list(target)
- if(mass_remove)
- var/method = vv_subtype_prompt(target.type)
- targets_to_remove_from = get_all_of_type(target.type, method)
-
- if(alert(usr, "Are you sure you want to mass-delete [path] on [target.type]?", "Mass Remove Confirmation", "Yes", "No") == "No")
- return
-
- var/list/ele_list = list()
- if(ispath(path, /datum/element))
- ele_list = get_callproc_args()
- ele_list.Insert(1, path)
- for(var/datum/target_to_remove_from as anything in targets_to_remove_from)
- if(ispath(path, /datum/element))
- target._RemoveElement(ele_list)
- else
- var/list/components_actual = target_to_remove_from.GetComponents(path)
- for(var/to_delete in components_actual)
- qdel(to_delete)
-
- message_admins("[key_name_admin(usr)] has [mass_remove ? "mass" : ""] removed [path] component from [mass_remove ? target.type : key_name_admin(target)].")
+ // Refresh the VV if something asked us to
if(href_list["datumrefresh"])
var/datum/DAT = locateUID(href_list["datumrefresh"])
if(!istype(DAT, /datum) && !isclient(DAT))
return
src.debug_variables(DAT)
- if(href_list["manipcolours"])
- if(!check_rights(R_DEBUG))
- return
-
- var/datum/target = locateUID(href_list["manipcolours"])
- if(!(isatom(target) || isclient(target)))
- to_chat(usr, "This can only be used on atoms and clients")
- return
-
- message_admins("[key_name_admin(usr)] is manipulating the colour matrix for [target]")
- var/datum/ui_module/colour_matrix_tester/CMT = new(target=target)
- CMT.ui_interact(usr)
-
- if(href_list["grantdeadchatcontrol"])
- if(!check_rights(R_EVENT))
- return
-
- var/atom/movable/A = locateUID(href_list["grantdeadchatcontrol"])
- if(!istype(A))
- return
-
- if(!GLOB.dsay_enabled)
- // TODO verify what happens when deadchat is muted
- to_chat(usr, "Deadchat is globally muted, un-mute deadchat before enabling this.")
- return
-
- if(A.GetComponent(/datum/component/deadchat_control))
- to_chat(usr, "[A] is already under deadchat control!")
- return
-
- var/control_mode = input(usr, "Please select the control mode","Deadchat Control", null) as null|anything in list("democracy", "anarchy")
-
- var/selected_mode
- switch(control_mode)
- if("democracy")
- selected_mode = DEADCHAT_DEMOCRACY_MODE
- if("anarchy")
- selected_mode = DEADCHAT_ANARCHY_MODE
- else
- return
-
- var/cooldown = input(usr, "Please enter a cooldown time in seconds. For democracy, it's the time between actions (must be greater than zero). For anarchy, it's the time between each user's actions, or -1 for no cooldown.", "Cooldown", null) as null|num
- if(isnull(cooldown) || (cooldown == -1 && selected_mode == DEADCHAT_DEMOCRACY_MODE))
- return
- if(cooldown < 0 && selected_mode == DEADCHAT_DEMOCRACY_MODE)
- to_chat(usr, "The cooldown for democracy mode must be greater than zero.")
- return
- if(cooldown == -1)
- cooldown = 0
- else
- cooldown = cooldown SECONDS
-
- A.deadchat_plays(selected_mode, cooldown)
- message_admins("[key_name_admin(usr)] provided deadchat control to [A].")
-
- if(href_list["removedeadchatcontrol"])
- if(!check_rights(R_EVENT))
- return
-
- var/atom/movable/A = locateUID(href_list["removedeadchatcontrol"])
- if(!istype(A))
- return
-
- if(!A.GetComponent(/datum/component/deadchat_control))
- to_chat(usr, "[A] is not currently under deadchat control!")
- return
-
- A.stop_deadchat_plays()
- message_admins("[key_name_admin(usr)] removed deadchat control from [A].")
-
/client/proc/view_var_Topic_list(href, href_list, hsrc)
if(href_list["VarsList"])
debug_variables(locate(href_list["VarsList"]))
diff --git a/code/datums/vv_core_topics.dm b/code/datums/vv_core_topics.dm
new file mode 100644
index 00000000000..b7b5e9ec96c
--- /dev/null
+++ b/code/datums/vv_core_topics.dm
@@ -0,0 +1,136 @@
+/// Core topics are VV topics which should work even if the code responsible
+/// for processing vv topics for that datum is runtiming. They're kept separately
+/// from [/datum/proc/vv_do_topic] for that reason.
+/client/proc/vv_core_topics(datum/target, href_list)
+ if(href_list[VV_HK_JUMP_TO])
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/turf/T = get_turf(target)
+ if(T)
+ jumptoturf(T)
+ href_list["datumrefresh"] = target.UID()
+ if(href_list["varnameedit"] && href_list["datumedit"])
+ if(!check_rights(R_VAREDIT)) return
+
+ var/D = locateUID(href_list["datumedit"])
+ if(!istype(D,/datum) && !isclient(D))
+ to_chat(usr, "This can only be used on instances of types /client or /datum.")
+ return
+
+ modify_variables(D, href_list["varnameedit"], 1)
+ if(href_list["varnamechange"] && href_list["datumchange"])
+ if(!check_rights(R_VAREDIT)) return
+
+ var/D = locateUID(href_list["datumchange"])
+ if(!istype(D,/datum) && !isclient(D))
+ to_chat(usr, "This can only be used on instances of types /client or /datum.")
+ return
+
+ modify_variables(D, href_list["varnamechange"], 0)
+ if(href_list["varnamemass"] && href_list["datummass"])
+ if(!check_rights(R_VAREDIT)) return
+
+ var/atom/A = locateUID(href_list["datummass"])
+ if(!istype(A))
+ to_chat(usr, "This can only be used on instances of type /atom.")
+ return
+
+ cmd_mass_modify_object_variables(A, href_list["varnamemass"])
+ if(href_list[VV_HK_DELETE])
+ if(!check_rights(R_DEBUG, 0))
+ return
+
+ admin_delete(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_MARK_OBJECT])
+ if(!check_rights(0)) return
+
+ if(!istype(target))
+ to_chat(usr, "This can only be done to instances of type /datum.")
+ return
+
+ src.holder.marked_datum = target
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_PROC_CALL])
+ if(!check_rights(R_PROCCALL))
+ return
+
+ if(target)
+ callproc_datum(target)
+ if(href_list[VV_HK_ADDCOMPONENT])
+ if(!check_rights(NONE))
+ return
+
+ var/list/names = list()
+ var/list/componentsubtypes = sortList(subtypesof(/datum/component), GLOBAL_PROC_REF(cmp_typepaths_asc))
+ names += "---Components---"
+ names += componentsubtypes
+ names += "---Elements---"
+ names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
+
+ var/result = tgui_input_list(usr, "Choose a component/element to add", "Add Component", names)
+ if(isnull(result))
+ return
+ if(!usr || result == "---Components---" || result == "---Elements---")
+ return
+
+ if(QDELETED(src))
+ to_chat(usr, "That thing doesn't exist anymore!", confidential = TRUE)
+ return
+
+ var/list/lst = get_callproc_args()
+ if(!lst)
+ return
+
+ var/datumname = "error"
+ lst.Insert(1, result)
+ if(result in componentsubtypes)
+ datumname = "component"
+ target._AddComponent(lst)
+ else
+ datumname = "element"
+ target._AddElement(lst)
+ log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(target)].")
+ message_admins("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(target)].")
+ if(href_list[VV_HK_REMOVECOMPONENT] || href_list[VV_HK_MASSREMOVECOMPONENT])
+ if(!check_rights(NONE))
+ return
+ var/mass_remove = href_list[VV_HK_MASSREMOVECOMPONENT]
+ var/list/components = target.datum_components.Copy()
+ var/list/names = list()
+ names += "---Components---"
+ if(length(components))
+ names += sortList(components, GLOBAL_PROC_REF(cmp_typepaths_asc))
+ names += "---Elements---"
+ // We have to list every element here because there is no way to know what element is on this object without doing some sort of hack.
+ names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
+ var/path = tgui_input_list(usr, "Choose a component/element to remove. All elements listed here may not be on the datum.", "Remove element", names)
+ if(isnull(path))
+ return
+ if(!usr || path == "---Components---" || path == "---Elements---")
+ return
+ if(QDELETED(src))
+ to_chat(usr, "That thing doesn't exist anymore!")
+ return
+ var/list/targets_to_remove_from = list(target)
+ if(mass_remove)
+ var/method = vv_subtype_prompt(target.type)
+ targets_to_remove_from = get_all_of_type(target.type, method)
+
+ if(tgui_alert(usr, "Are you sure you want to mass-delete [path] on [target.type]?", "Mass Remove Confirmation", list("Yes", "No")) != "Yes")
+ return
+
+ var/list/ele_list = list()
+ if(ispath(path, /datum/element))
+ ele_list = get_callproc_args()
+ ele_list.Insert(1, path)
+ for(var/datum/target_to_remove_from as anything in targets_to_remove_from)
+ if(ispath(path, /datum/element))
+ target._RemoveElement(ele_list)
+ else
+ var/list/components_actual = target_to_remove_from.GetComponents(path)
+ for(var/to_delete in components_actual)
+ qdel(to_delete)
+
+ message_admins("[key_name_admin(usr)] has [mass_remove ? "mass" : ""] removed [path] component from [mass_remove ? target.type : key_name_admin(target)].")
diff --git a/code/game/atom_vv.dm b/code/game/atom_vv.dm
new file mode 100644
index 00000000000..d3feb00216d
--- /dev/null
+++ b/code/game/atom_vv.dm
@@ -0,0 +1,99 @@
+/atom/vv_edit_var(var_name, var_value)
+ . = ..()
+ switch(var_name)
+ if("light_power", "light_range", "light_color")
+ update_light()
+ if("color")
+ add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
+
+/atom/vv_get_dropdown()
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_MANIPULATE_COLOR_MATRIX, "Manipulate Colour Matrix")
+ var/turf/curturf = get_turf(src)
+ if(curturf)
+ . += ""
+ VV_DROPDOWN_OPTION(VV_HK_ADDREAGENT, "Add reagent")
+ VV_DROPDOWN_OPTION(VV_HK_EDITREAGENTS, "Edit reagents")
+ VV_DROPDOWN_OPTION(VV_HK_EXPLODE, "Trigger explosion")
+ VV_DROPDOWN_OPTION(VV_HK_EMP, "Trigger EM pulse")
+
+/atom/vv_get_header()
+ . = ..()
+ . += "[src]"
+ if(dir)
+ . += "
<< [dir2text(dir)] >>"
+
+/atom/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list["rotatedatum"])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ switch(href_list["rotatedir"])
+ if("right") dir = turn(dir, -45)
+ if("left") dir = turn(dir, 45)
+
+ message_admins("[key_name_admin(usr)] has rotated \the [src]")
+ log_admin("[key_name(usr)] has rotated \the [src]")
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_EXPLODE])
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
+
+ usr.client.cmd_admin_explosion(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_EMP])
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
+
+ usr.client.cmd_admin_emp(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_ADDREAGENT]) /* Made on /TG/, credit to them. */
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ if(!reagents)
+ var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num
+ if(amount)
+ create_reagents(amount)
+
+ if(reagents)
+ var/chosen_id
+ var/list/reagent_options = sortAssoc(GLOB.chemical_reagents_list)
+ switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
+ if("Enter ID")
+ var/valid_id
+ while(!valid_id)
+ chosen_id = stripped_input(usr, "Enter the ID of the reagent you want to add.")
+ if(!chosen_id) //Get me out of here!
+ break
+ for(var/ID in reagent_options)
+ if(ID == chosen_id)
+ valid_id = 1
+ if(!valid_id)
+ to_chat(usr, "A reagent with that ID doesn't exist!")
+ if("Choose ID")
+ chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_options
+ if(chosen_id)
+ var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num
+ if(amount)
+ reagents.add_reagent(chosen_id, amount)
+ log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [src]")
+ message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [src]")
+ if(href_list[VV_HK_EDITREAGENTS])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ usr.client.try_open_reagent_editor(src)
+ if(href_list[VV_HK_MANIPULATE_COLOR_MATRIX])
+ if(!check_rights(R_DEBUG))
+ return
+
+ message_admins("[key_name_admin(usr)] is manipulating the colour matrix for [src]")
+ var/datum/ui_module/colour_matrix_tester/CMT = new(target=src)
+ CMT.ui_interact(usr)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index c0cb695e5e5..31df2551846 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -505,7 +505,7 @@
*
* Arguments:
* - updates: A set of bitflags dictating what should be updated. Defaults to [ALL]
- *
+ *
* Supported bitflags: UPDATE_NAME, UPDATE_DESC, UPDATE_ICON
*/
/atom/proc/update_appearance(updates=ALL)
@@ -540,7 +540,7 @@
*
* Arguments:
* - updates: A set of bitflags dictating what should be updated. Defaults to [ALL]
- *
+ *
* Supported bitflags: UPDATE_ICON_STATE, UPDATE_OVERLAYS
*/
/atom/proc/update_icon(updates=ALL)
@@ -1258,25 +1258,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
return
-/atom/vv_edit_var(var_name, var_value)
- . = ..()
- switch(var_name)
- if("light_power", "light_range", "light_color")
- update_light()
- if("color")
- add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
-
-/atom/vv_get_dropdown()
- . = ..()
- .["Manipulate Colour Matrix"] = "byond://?_src_=vars;manipcolours=[UID()]"
- var/turf/curturf = get_turf(src)
- if(curturf)
- .["Jump to turf"] = "byond://?_src_=holder;adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]"
- .["Add reagent"] = "byond://?_src_=vars;addreagent=[UID()]"
- .["Edit reagents"] = "byond://?_src_=vars;editreagents=[UID()]"
- .["Trigger explosion"] = "byond://?_src_=vars;explode=[UID()]"
- .["Trigger EM pulse"] = "byond://?_src_=vars;emp=[UID()]"
-
/atom/proc/AllowDrop()
return FALSE
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 609b1a30234..5890ac77d51 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -961,14 +961,6 @@
/atom/movable/proc/stop_deadchat_plays()
DeleteComponent(/datum/component/deadchat_control)
-/atom/movable/vv_get_dropdown()
- . = ..()
- if(!GetComponent(/datum/component/deadchat_control))
- .["Give deadchat control"] = "byond://?_src_=vars;grantdeadchatcontrol=[UID()]"
- else
- .["Remove deadchat control"] = "byond://?_src_=vars;removedeadchatcontrol=[UID()]"
-
-
//Update the screentip to reflect what we're hovering over
/atom/movable/MouseEntered(location, control, params)
if(invisibility > usr.see_invisible)
diff --git a/code/game/movable_vv.dm b/code/game/movable_vv.dm
new file mode 100644
index 00000000000..0762a4e9e63
--- /dev/null
+++ b/code/game/movable_vv.dm
@@ -0,0 +1,67 @@
+#define VV_HK_GIVE_DEADCHAT_CONTROL "grantdeadchatcontrol"
+#define VV_HK_REMOVE_DEADCHAT_CONTROL "removedeadchatcontrol"
+
+/atom/movable/vv_get_dropdown()
+ . = ..()
+ if(!GetComponent(/datum/component/deadchat_control))
+ VV_DROPDOWN_OPTION(VV_HK_GIVE_DEADCHAT_CONTROL, "Give deadchat control")
+ else
+ VV_DROPDOWN_OPTION(VV_HK_REMOVE_DEADCHAT_CONTROL, "Remove deadchat control")
+
+/atom/movable/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list[VV_HK_GIVE_DEADCHAT_CONTROL])
+ if(!check_rights(R_EVENT))
+ return
+
+ if(!GLOB.dsay_enabled)
+ // TODO verify what happens when deadchat is muted
+ to_chat(usr, "Deadchat is globally muted, un-mute deadchat before enabling this.")
+ return
+
+ if(GetComponent(/datum/component/deadchat_control))
+ to_chat(usr, "[src] is already under deadchat control!")
+ return
+
+ var/control_mode = tgui_input_list(usr, "Please select the control mode", "Deadchat Control", list("Democracy", "Anarchy"))
+
+ var/selected_mode
+ switch(control_mode)
+ if("Democracy")
+ selected_mode = DEADCHAT_DEMOCRACY_MODE
+ if("Anarchy")
+ selected_mode = DEADCHAT_ANARCHY_MODE
+ else
+ return
+
+ var/cooldown = tgui_input_number(usr, "Please enter a cooldown time in seconds. For Democracy, it's the time between actions (must be greater than zero). For Anarchy, it's the time between each user's actions, or -1 for no cooldown.", "Cooldown")
+ if(isnull(cooldown) || (cooldown == -1 && selected_mode == DEADCHAT_DEMOCRACY_MODE))
+ return
+ if(cooldown < 0 && selected_mode == DEADCHAT_DEMOCRACY_MODE)
+ to_chat(usr, "The cooldown for Democracy mode must be greater than zero.")
+ return
+ if(cooldown == -1)
+ cooldown = 0
+ else
+ cooldown = cooldown SECONDS
+
+ deadchat_plays(selected_mode, cooldown)
+ message_admins("[key_name_admin(usr)] provided deadchat control to [src].")
+
+ if(href_list[VV_HK_REMOVE_DEADCHAT_CONTROL])
+ if(!check_rights(R_EVENT))
+ return
+
+ if(!GetComponent(/datum/component/deadchat_control))
+ to_chat(usr, "[src] is not currently under deadchat control!")
+ return
+
+ stop_deadchat_plays()
+ message_admins("[key_name_admin(usr)] removed deadchat control from [src].")
+
+#undef VV_HK_GIVE_DEADCHAT_CONTROL
+#undef VV_HK_REMOVE_DEADCHAT_CONTROL
diff --git a/code/game/objects/obj_vv.dm b/code/game/objects/obj_vv.dm
new file mode 100644
index 00000000000..c492a24843d
--- /dev/null
+++ b/code/game/objects/obj_vv.dm
@@ -0,0 +1,120 @@
+/obj/vv_get_dropdown()
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_DELALL, "Delete all of type")
+ if(!speed_process)
+ VV_DROPDOWN_OPTION(VV_HK_MAKESPEEDY, "Make speed process")
+ else
+ VV_DROPDOWN_OPTION(VV_HK_MAKENORMALSPEED, "Make normal process")
+ VV_DROPDOWN_OPTION(VV_HK_MODIFYARMOR, "Modify armor values")
+
+/obj/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list[VV_HK_DELALL])
+ if(!check_rights(R_DEBUG|R_SERVER))
+ return
+
+ var/action_type = tgui_alert(usr, "Strict type ([type]) or type and all subtypes?", "Select", list("Strict type", "Type and Subtypes", "Cancel"))
+ if(action_type == "Cancel" || !action_type)
+ return
+
+ if(tgui_alert(usr, "Are you really sure you want to delete all objects of type [type]?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+
+ if(tgui_alert("Second confirmation required. Delete?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+
+ var/O_type = type
+ switch(action_type)
+ if("Strict type")
+ var/i = 0
+ for(var/obj/Obj in world)
+ if(Obj.type == O_type)
+ i++
+ qdel(Obj)
+ if(!i)
+ to_chat(usr, "No objects of this type exist.")
+ return
+ log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)")
+ message_admins("[key_name_admin(usr)] deleted all objects of type [O_type] ([i] objects deleted)")
+ if("Type and Subtypes")
+ var/i = 0
+ for(var/obj/Obj in world)
+ if(istype(Obj, O_type))
+ i++
+ qdel(Obj)
+ if(!i)
+ to_chat(usr, "No objects of this type exist.")
+ return
+ log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)")
+ message_admins("[key_name_admin(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)")
+
+ if(href_list[VV_HK_MAKESPEEDY])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ var_edited = TRUE
+ makeSpeedProcess()
+ log_admin("[key_name(usr)] has made [src] speed process")
+ message_admins("[key_name(usr)] has made [src] speed process")
+ if(href_list[VV_HK_MAKENORMALSPEED])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ var_edited = TRUE
+ makeNormalProcess()
+ log_admin("[key_name(usr)] has made [src] process normally")
+ message_admins("[key_name(usr)] has made [src] process normally")
+ if(href_list[VV_HK_MODIFYARMOR])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ var_edited = TRUE
+ var/list/armorlist = armor.getList()
+ var/list/displaylist
+
+ var/result
+ do
+ displaylist = list()
+ for(var/key in armorlist)
+ displaylist += "[key] = [armorlist[key]]"
+ result = input(usr, "Select an armor type to modify..", "Modify armor") as null|anything in displaylist + "(ADD ALL)" + "(SET ALL)" + "(DONE)"
+
+ if(result == "(DONE)")
+ break
+ else if(result == "(ADD ALL)" || result == "(SET ALL)")
+ var/new_amount = tgui_input_number(usr, result == "(ADD ALL)" ? "Enter armor to add to all types:" : "Enter new armor value for all types:", "Modify all types")
+ if(isnull(new_amount))
+ continue
+ var/proper_amount = text2num(new_amount)
+ if(isnull(proper_amount))
+ continue
+ for(var/key in armorlist)
+ armorlist[key] = (result == "(ADD ALL)" ? armorlist[key] : 0) + proper_amount
+ else if(result)
+ var/list/fields = splittext(result, " = ")
+ if(length(fields) != 2)
+ continue
+ var/type = fields[1]
+ if(isnull(armorlist[type]))
+ continue
+ var/new_amount = tgui_input_number(usr, "Enter new armor value for [type]:", "Modify [type]")
+ if(isnull(new_amount))
+ continue
+ var/proper_amount = text2num(new_amount)
+ if(isnull(proper_amount))
+ continue
+ armorlist[type] = proper_amount
+ while(result)
+
+ if(!result || !QDELETED(src))
+ return TRUE
+
+ armor = armor.setRating(armorlist[MELEE], armorlist[BULLET], armorlist[LASER], armorlist[ENERGY], armorlist[BOMB], armorlist[RAD], armorlist[FIRE], armorlist[ACID], armorlist[MAGIC])
+
+ log_admin("[key_name(usr)] modified the armor on [src] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
+ message_admins("[key_name(usr)] modified the armor on [src] to: melee = [armorlist[MELEE]], bullet = [armorlist[BULLET]], laser = [armorlist[LASER]], energy = [armorlist[ENERGY]], bomb = [armorlist[BOMB]], rad = [armorlist[RAD]], fire = [armorlist[FIRE]], acid = [armorlist[ACID]], magic = [armorlist[MAGIC]]")
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 66661d0d0d4..56535a23a42 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -236,15 +236,6 @@
START_PROCESSING(SSobj, src)
STOP_PROCESSING(SSfastprocess, src)
-/obj/vv_get_dropdown()
- . = ..()
- .["Delete all of type"] = "byond://?_src_=vars;delall=[UID()]"
- if(!speed_process)
- .["Make speed process"] = "byond://?_src_=vars;makespeedy=[UID()]"
- else
- .["Make normal process"] = "byond://?_src_=vars;makenormalspeed=[UID()]"
- .["Modify armor values"] = "byond://?_src_=vars;modifyarmor=[UID()]"
-
/obj/proc/check_uplink_validity()
return TRUE
diff --git a/code/modules/mob/living/carbon/carbon_procs.dm b/code/modules/mob/living/carbon/carbon_procs.dm
index 544f7337b19..25b9887143f 100644
--- a/code/modules/mob/living/carbon/carbon_procs.dm
+++ b/code/modules/mob/living/carbon/carbon_procs.dm
@@ -1454,3 +1454,78 @@ so that different stomachs can handle things in different ways VB*/
/mob/living/carbon/proc/get_thermal_protection() // Xenos got nothin
return 0
+
+/mob/living/carbon/vv_get_dropdown()
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_GIVEMARTIALART, "Give Martial Art")
+ VV_DROPDOWN_OPTION(VV_HK_ADDORGAN, "Add Organ")
+ VV_DROPDOWN_OPTION(VV_HK_REMORGAN, "Remove Organ")
+
+/mob/living/carbon/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list[VV_HK_GIVEMARTIALART])
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
+
+ var/list/artpaths = subtypesof(/datum/martial_art)
+ var/list/artnames = list()
+ for(var/i in artpaths)
+ var/datum/martial_art/M = i
+ artnames[initial(M.name)] = M
+
+ var/result = tgui_input_list(usr, "Choose the martial art to teach", "JUDO CHOP", artnames)
+ if(!usr)
+ return
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ if(result)
+ var/chosenart = artnames[result]
+ var/datum/martial_art/MA = new chosenart
+ MA.teach(src)
+
+ href_list["datumrefresh"] = UID()
+ else if(href_list[VV_HK_ADDORGAN])
+ if(!check_rights(R_SPAWN))
+ return
+
+ var/new_organ = tgui_input_list(usr, "Please choose an organ to add.", "Organ", subtypesof(/obj/item/organ))
+ if(!new_organ)
+ return
+
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ if(locateUID(new_organ) in internal_organs)
+ to_chat(usr, "Mob already has that organ.")
+ return
+ var/obj/item/organ/internal/organ = new new_organ
+ organ.insert(src)
+ message_admins("[key_name_admin(usr)] has given [key_name_admin(src)] the organ [new_organ]")
+ log_admin("[key_name(usr)] has given [key_name(src)] the organ [new_organ]")
+
+ else if(href_list[VV_HK_REMORGAN])
+ if(!check_rights(R_SPAWN)) return
+
+ var/obj/item/organ/internal/rem_organ = tgui_input_list(usr, "Please choose an organ to remove.", "Organ", internal_organs)
+
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ if(!(rem_organ in internal_organs))
+ to_chat(usr, "Mob does not have that organ.")
+ return
+
+ to_chat(usr, "Removed [rem_organ] from [src].")
+ rem_organ.remove(src)
+ message_admins("[key_name_admin(usr)] has removed the organ [rem_organ] from [key_name_admin(src)]")
+ log_admin("[key_name(usr)] has removed the organ [rem_organ] from [key_name(src)]")
+ qdel(rem_organ)
diff --git a/code/modules/mob/living/carbon/human/human_vv.dm b/code/modules/mob/living/carbon/human/human_vv.dm
new file mode 100644
index 00000000000..9592dc2e963
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/human_vv.dm
@@ -0,0 +1,35 @@
+/mob/living/carbon/human/vv_get_dropdown()
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_MAKE_SKELETON, "Make 2spooky")
+ VV_DROPDOWN_OPTION(VV_HK_HALLUCINATE, "Hallucinate")
+
+/mob/living/carbon/human/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list[VV_HK_MAKE_SKELETON])
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
+
+ if(tgui_alert(usr, "Are you sure you want to turn this mob into a skeleton?", "Confirm Skeleton Transformation", list("Yes", "No")) != "Yes")
+ return
+
+ makeSkeleton()
+ message_admins("[key_name(usr)] has turned [key_name(src)] into a skeleton")
+ log_admin("[key_name_admin(usr)] has turned [key_name_admin(src)] into a skeleton")
+ href_list["datumrefresh"] = UID()
+
+ if(href_list[VV_HK_HALLUCINATE])
+ if(!check_rights(R_SERVER | R_EVENT))
+ return
+
+ var/haltype = tgui_input_list(usr, "Select Hallucination Type", "Hallucinate", (subtypesof(/obj/effect/hallucination) + subtypesof(/datum/hallucination_manager)))
+ if(!haltype)
+ return
+ invoke_hallucination(haltype)
+ message_admins("[key_name(usr)] has given [key_name(src)] the [haltype] hallucination")
+ log_admin("[key_name_admin(usr)] has given [key_name_admin(src)] the [haltype] hallucination")
+ href_list["datumrefresh"] = UID()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index fed9832c338..4a83de3e4d5 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1152,6 +1152,68 @@
if(A.light_range > 0)
A.extinguish_light(force)
+/mob/living/vv_get_header()
+ . = ..()
+ . += {"
+
+ BRUTE:[getBruteLoss()]
+ FIRE:[getFireLoss()]
+ TOXIN:[getToxLoss()]
+ OXY:[getOxyLoss()]
+ CLONE:[getCloneLoss()]
+ BRAIN:[getBrainLoss()]
+ STAMINA:[getStaminaLoss()]
+
+ "}
+
+/mob/living/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ if(href_list["adjustDamage"])
+ if(!check_rights(R_DEBUG|R_ADMIN|R_EVENT)) return
+
+ var/Text = href_list["adjustDamage"]
+ var/amount = tgui_input_number(usr, "Deal how much damage to mob? (Negative values here heal)", "Adjust [Text]loss")
+
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ switch(Text)
+ if("brute")
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ H.adjustBruteLoss(amount, robotic = TRUE)
+ else
+ adjustBruteLoss(amount)
+ if("fire")
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ H.adjustFireLoss(amount, robotic = TRUE)
+ else
+ adjustFireLoss(amount)
+ if("toxin")
+ adjustToxLoss(amount)
+ if("oxygen")
+ adjustOxyLoss(amount)
+ if("brain")
+ adjustBrainLoss(amount)
+ if("clone")
+ adjustCloneLoss(amount)
+ if("stamina")
+ adjustStaminaLoss(amount)
+ else
+ to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[src]")
+ return
+
+ if(amount != 0)
+ log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [src]")
+ message_admins("[key_name_admin(usr)] dealt [amount] amount of [Text] damage to [src]")
+ href_list["datumrefresh"] = UID()
+
/mob/living/vv_edit_var(var_name, var_value)
switch(var_name)
if("stat")
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index e37d3851545..affbb0a34b3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1294,34 +1294,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
target += new_log
-/mob/vv_get_dropdown()
- . = ..()
- .["Show player panel"] = "byond://?_src_=vars;mob_player_panel=[UID()]"
-
- .["Give Spell"] = "byond://?_src_=vars;give_spell=[UID()]"
- .["Give Martial Art"] = "byond://?_src_=vars;givemartialart=[UID()]"
- .["Give Disease"] = "byond://?_src_=vars;give_disease=[UID()]"
- .["Toggle Godmode"] = "byond://?_src_=vars;godmode=[UID()]"
- .["Toggle Build Mode"] = "byond://?_src_=vars;build_mode=[UID()]"
-
- .["Make 2spooky"] = "byond://?_src_=vars;make_skeleton=[UID()]"
- .["Hallucinate"] = "byond://?_src_=vars;hallucinate=[UID()]"
-
- .["Assume Direct Control"] = "byond://?_src_=vars;direct_control=[UID()]"
- .["Offer Control to Ghosts"] = "byond://?_src_=vars;offer_control=[UID()]"
- .["Drop Everything"] = "byond://?_src_=vars;drop_everything=[UID()]"
-
- .["Regenerate Icons"] = "byond://?_src_=vars;regenerateicons=[UID()]"
- .["Add Language"] = "byond://?_src_=vars;addlanguage=[UID()]"
- .["Remove Language"] = "byond://?_src_=vars;remlanguage=[UID()]"
- .["Add Organ"] = "byond://?_src_=vars;addorgan=[UID()]"
- .["Remove Organ"] = "byond://?_src_=vars;remorgan=[UID()]"
-
- .["Add Verb"] = "byond://?_src_=vars;addverb=[UID()]"
- .["Remove Verb"] = "byond://?_src_=vars;remverb=[UID()]"
-
- .["Gib"] = "byond://?_src_=vars;gib=[UID()]"
-
///Can this mob resist (default FALSE)
/mob/proc/can_resist()
return FALSE //overridden in living.dm
diff --git a/code/modules/mob/mob_vv.dm b/code/modules/mob/mob_vv.dm
new file mode 100644
index 00000000000..5610695825a
--- /dev/null
+++ b/code/modules/mob/mob_vv.dm
@@ -0,0 +1,180 @@
+/mob/vv_get_header()
+ . = ..()
+ . += "
[ckey ? ckey : "No ckey"] / [real_name ? real_name : "No real name"]"
+
+/mob/vv_get_dropdown()
+ . = ..()
+
+ VV_DROPDOWN_OPTION(VV_HK_MOB_PLAYER_PANEL, "Show player panel")
+ VV_DROPDOWN_OPTION(VV_HK_GIVE_SPELL, "Give Spell")
+ VV_DROPDOWN_OPTION(VV_HK_GIVE_DISEASE, "Give Disease")
+ VV_DROPDOWN_OPTION(VV_HK_GODMODE, "Toggle Godmode")
+ VV_DROPDOWN_OPTION(VV_HK_BUILD_MODE, "Toggle Build Mode")
+ VV_DROPDOWN_OPTION(VV_HK_DIRECT_CONTROL, "Assume Direct Control")
+ VV_DROPDOWN_OPTION(VV_HK_OFFER_CONTROL, "Offer Control to Ghosts")
+ VV_DROPDOWN_OPTION(VV_HK_DROP_EVERYTHING, "Drop Everything")
+ VV_DROPDOWN_OPTION(VV_HK_REGENERATEICONS, "Regenerate Icons")
+ VV_DROPDOWN_OPTION(VV_HK_ADDLANGUAGE, "Add Language")
+ VV_DROPDOWN_OPTION(VV_HK_REMLANGUAGE, "Remove Language")
+ VV_DROPDOWN_OPTION(VV_HK_ADDVERB, "Add Verb")
+ VV_DROPDOWN_OPTION(VV_HK_REMVERB, "Remove Verb")
+ VV_DROPDOWN_OPTION(VV_HK_GIB, "Gib")
+
+/mob/vv_do_topic(list/href_list)
+ . = ..()
+
+ if(!.)
+ return
+
+ //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
+ if(href_list["rename"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/new_name = reject_bad_name(sanitize(copytext_char(input(usr, "What would you like to name this mob?", "Input a name", real_name) as text|null, 1, MAX_NAME_LEN)), allow_numbers = TRUE)
+ if(!new_name || QDELETED(src))
+ return
+
+ message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(src)] to [new_name].")
+ rename_character(real_name, new_name)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_MOB_PLAYER_PANEL])
+ if(!check_rights(R_ADMIN|R_MOD))
+ return
+
+ usr.client.holder.show_player_panel(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_GIVE_SPELL])
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
+
+ usr.client.give_spell(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_GIVE_DISEASE])
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
+
+ usr.client.give_disease(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_GODMODE])
+ if(!check_rights(R_EVENT))
+ return
+
+ usr.client.cmd_admin_godmode(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_GIB])
+ if(!check_rights(R_ADMIN|R_EVENT))
+ return
+
+ usr.client.cmd_admin_gib(src)
+ if(href_list[VV_HK_BUILD_MODE])
+ if(!check_rights(R_BUILDMODE))
+ return
+
+ togglebuildmode(src)
+ href_list["datumrefresh"] = UID()
+ if(href_list[VV_HK_DROP_EVERYTHING])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ if(usr.client)
+ usr.client.cmd_admin_drop_everything(src)
+ if(href_list[VV_HK_DIRECT_CONTROL])
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
+ if(usr.client)
+ usr.client.cmd_assume_direct_control(src)
+ if(href_list[VV_HK_OFFER_CONTROL])
+ if(!check_rights(R_ADMIN))
+ return
+
+ offer_control(src)
+ if(href_list[VV_HK_REGENERATEICONS])
+ if(!check_rights(0))
+ return
+
+ regenerate_icons()
+ if(href_list[VV_HK_ADDLANGUAGE])
+ if(!check_rights(R_SPAWN))
+ return
+
+ var/new_language = tgui_input_list(usr, "Please choose a language to add.", "Language", GLOB.all_languages)
+
+ if(!new_language)
+ return
+
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ if(add_language(new_language, TRUE))
+ to_chat(usr, "Added [new_language] to [src].")
+ message_admins("[key_name_admin(usr)] has given [key_name_admin(src)] the language [new_language]")
+ log_admin("[key_name(usr)] has given [key_name(src)] the language [new_language]")
+ else
+ to_chat(usr, "Mob already knows that language.")
+ if(href_list[VV_HK_REMLANGUAGE])
+ if(!check_rights(R_SPAWN))
+ return
+
+ if(!length(languages))
+ to_chat(usr, "This mob knows no languages.")
+ return
+
+ var/datum/language/rem_language = tgui_input_list(usr, "Please choose a language to remove.", "Language", src.languages)
+
+ if(!rem_language)
+ return
+
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+
+ if(remove_language(rem_language.name, TRUE))
+ to_chat(usr, "Removed [rem_language] from [src].")
+ message_admins("[key_name_admin(usr)] has removed language [rem_language] from [key_name_admin(src)]")
+ log_admin("[key_name(usr)] has removed language [rem_language] from [key_name(src)]")
+ else
+ to_chat(usr, "Mob doesn't know that language.")
+ if(href_list[VV_HK_ADDVERB])
+ if(!check_rights(R_DEBUG))
+ return
+
+ var/list/possibleverbs = list()
+ possibleverbs += "Cancel" // One for the top...
+ possibleverbs += typesof(/mob/proc, /mob/verb, /mob/living/proc, /mob/living/verb)
+ switch(type) // Horrid
+ if(/mob/living/carbon/human)
+ possibleverbs += typesof(/mob/living/carbon/proc, /mob/living/carbon/verb, /mob/living/carbon/human/verb, /mob/living/carbon/human/proc)
+ if(/mob/living/silicon/robot)
+ 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)
+ possibleverbs -= verbs
+ possibleverbs += "Cancel" // ...And one for the bottom
+
+ var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+ if(!verb || verb == "Cancel")
+ return
+ else
+ add_verb(src, verb)
+ message_admins("[key_name_admin(usr)] has given [key_name_admin(src)] the verb [verb]")
+ log_admin("[key_name(usr)] has given [key_name(src)] the verb [verb]")
+ if(href_list[VV_HK_REMVERB])
+ if(!check_rights(R_DEBUG))
+ return
+
+ var/verb = tgui_input_list(usr, "Please choose a verb to remove.", "Verbs", src.verbs)
+ if(QDELETED(src))
+ to_chat(usr, "Mob doesn't exist anymore.")
+ return
+ if(!verb)
+ return
+ else
+ remove_verb(src, verb)
+ message_admins("[key_name_admin(usr)] has removed verb [verb] from [key_name_admin(src)]")
+ log_admin("[key_name(usr)] has removed verb [verb] from [key_name(src)]")
diff --git a/paradise.dme b/paradise.dme
index 5a18e18b41b..ed3cb27b1fb 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -443,6 +443,7 @@
#include "code\datums\tgs_event_handler.dm"
#include "code\datums\verb_callbacks.dm"
#include "code\datums\vision_override.dm"
+#include "code\datums\vv_core_topics.dm"
#include "code\datums\actions\action.dm"
#include "code\datums\actions\generic_action.dm"
#include "code\datums\actions\innate_action.dm"
@@ -796,9 +797,11 @@
#include "code\defines\procs\radio_procs.dm"
#include "code\defines\procs\records.dm"
#include "code\game\alternate_appearance.dm"
+#include "code\game\atom_vv.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
#include "code\game\data_huds.dm"
+#include "code\game\movable_vv.dm"
#include "code\game\shuttle_engines.dm"
#include "code\game\sound.dm"
#include "code\game\world.dm"
@@ -1097,6 +1100,7 @@
#include "code\game\objects\items.dm"
#include "code\game\objects\mail.dm"
#include "code\game\objects\obj_defense.dm"
+#include "code\game\objects\obj_vv.dm"
#include "code\game\objects\objs.dm"
#include "code\game\objects\structures.dm"
#include "code\game\objects\effects\alien_acid.dm"
@@ -2349,6 +2353,7 @@
#include "code\modules\mob\mob_update_icons_base.dm"
#include "code\modules\mob\mob_update_status_base.dm"
#include "code\modules\mob\mob_vars.dm"
+#include "code\modules\mob\mob_vv.dm"
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\typing_indicator.dm"
#include "code\modules\mob\camera\camera_mob.dm"
@@ -2464,6 +2469,7 @@
#include "code\modules\mob\living\carbon\human\human_stripping.dm"
#include "code\modules\mob\living\carbon\human\human_update_icons.dm"
#include "code\modules\mob\living\carbon\human\human_update_status.dm"
+#include "code\modules\mob\living\carbon\human\human_vv.dm"
#include "code\modules\mob\living\carbon\human\npcs.dm"
#include "code\modules\mob\living\carbon\human\physiology.dm"
#include "code\modules\mob\living\carbon\human\species\_species.dm"