From 76e1c6916fc492c03255513dfba8eb72914fb4e9 Mon Sep 17 00:00:00 2001 From: MrStonedOne Date: Sat, 26 Nov 2016 03:49:18 -0800 Subject: [PATCH] VV refactor --- code/__DEFINES/vv.dm | 21 + code/__HELPERS/mobs.dm | 38 +- code/__HELPERS/unsorted.dm | 5 +- code/_globalvars/lists/typecache.dm | 9 + code/controllers/subsystem.dm | 12 +- code/datums/datumvars.dm | 674 ++++++------ code/game/atoms.dm | 29 +- code/game/atoms_movable.dm | 6 +- code/game/machinery/doors/airlock.dm | 4 +- code/game/objects/objs.dm | 4 + code/modules/admin/admin_ranks.dm | 3 + code/modules/admin/holder2.dm | 3 + code/modules/admin/verbs/debug.dm | 48 +- code/modules/admin/verbs/massmodvar.dm | 647 ++++-------- code/modules/admin/verbs/modifyvariables.dm | 1014 ++++++++----------- code/modules/mob/dead/observer/observer.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 7 + code/modules/mob/mob.dm | 54 +- code/modules/power/cell.dm | 15 +- code/modules/projectiles/guns/energy.dm | 16 +- code/modules/projectiles/guns/magic.dm | 4 +- tgstation.dme | 2 + 22 files changed, 1183 insertions(+), 1434 deletions(-) create mode 100644 code/__DEFINES/vv.dm create mode 100644 code/_globalvars/lists/typecache.dm diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm new file mode 100644 index 00000000000..807e5187b08 --- /dev/null +++ b/code/__DEFINES/vv.dm @@ -0,0 +1,21 @@ +#define VV_NUM "Number" +#define VV_TEXT "Text" +#define VV_MESSAGE "Mutiline Text" +#define VV_ICON "Icon" +#define VV_ATOM_REFERENCE "Atom Reference" +#define VV_DATUM_REFERENCE "Datum Reference" +#define VV_MOB_REFERENCE "Mob Reference" +#define VV_CLIENT "Client" +#define VV_ATOM_TYPE "Atom Typepath" +#define VV_DATUM_TYPE "Datum Typepath" +#define VV_TYPE "Custom Typepath" +#define VV_FILE "File" +#define VV_LIST "List" +#define VV_NEW_ATOM "New Atom" +#define VV_NEW_DATUM "New Datum" +#define VV_NEW_TYPE "New Custom Typepath" +#define VV_NEW_LIST "New List" +#define VV_NULL "NULL" +#define VV_RESTORE_DEFAULT "Restore to Default" +#define VV_MARKED_DATUM "Marked Datum" + diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 960d07cd04d..90aefee507f 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -169,24 +169,30 @@ Proc for attack log creation, because really why not */ /proc/add_logs(mob/user, mob/target, what_done, object=null, addition=null) - var/newhealthtxt = "" - var/coordinates = "" var/turf/attack_location = get_turf(target) - if(attack_location) - coordinates = "([attack_location.x],[attack_location.y],[attack_location.z])" - if(target && isliving(target)) - var/mob/living/L = target - newhealthtxt = " (NEWHP: [L.health])" - if(user && ismob(user)) - user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]") - if(user.mind) - user.mind.attack_log += text("\[[time_stamp()]\] [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]") - if(target && ismob(target)) - target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]") - if(target.mind) - target.mind.attack_log += text("\[[time_stamp()]\] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]") - log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]") + var/is_mob_user = user && typecache_mob[user.type] + var/is_mob_target = target && typecache_mob[target.type] + + var/mob/living/living_target + + + if(target && isliving(target)) + living_target = target + + if(is_mob_user) + var/message = "\[[time_stamp()]\] [user ? "[user.name][(user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has [what_done] [target ? "[target.name][(is_mob_target && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][(living_target) ? " (NEWHP: [living_target.health])" : ""][(attack_location) ? "([attack_location.x],[attack_location.y],[attack_location.z])" : ""]" + user.attack_log += message + if(user.mind) + user.mind.attack_log += message + + if(is_mob_target) + var/message = "\[[time_stamp()]\] [target ? "[target.name][(target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has been [what_done] by [user ? "[user.name][(is_mob_user && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][(living_target) ? " (NEWHP: [living_target.health])" : ""][(attack_location) ? "([attack_location.x],[attack_location.y],[attack_location.z])" : ""]" + target.attack_log += message + if(target.mind) + target.mind.attack_log += message + + log_attack("[user ? "[user.name][(is_mob_user && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(is_mob_target && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][(living_target) ? " (NEWHP: [living_target.health])" : ""][(attack_location) ? "([attack_location.x],[attack_location.y],[attack_location.z])" : ""]") /proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 9e575f3b460..13e34807609 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1262,8 +1262,9 @@ B --><-- A closest_atom = A return closest_atom -/proc/pick_closest_path(value) - var/list/matches = get_fancy_list_of_types() + +proc/pick_closest_path(value) + var/list/matches = get_fancy_list_of_atom_types() if (!isnull(value) && value!="") matches = filter_fancy_list(matches, value) diff --git a/code/_globalvars/lists/typecache.dm b/code/_globalvars/lists/typecache.dm new file mode 100644 index 00000000000..5d2565c7f26 --- /dev/null +++ b/code/_globalvars/lists/typecache.dm @@ -0,0 +1,9 @@ +//please store common type caches here. +//type caches should only be stored here if used in mutiple places or likely to be used in mutiple places. + +//Note: typecache can only replace istype if you know for sure the thing is at least a datum. + +var/list/typecache_mob = typecacheof(list(/mob)) + + + diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index e49316ebe3c..fa7daeda4d3 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -157,8 +157,12 @@ /datum/subsystem/proc/Recover() //this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag -/datum/subsystem/on_varedit(edited_var) - if (edited_var == "can_fire" && can_fire) - next_fire = world.time + wait - ..() +/datum/subsystem/vv_edit_var(var_name, var_value) + switch (var_name) + if ("can_fire") + if (var_value) + next_fire = world.time + wait + if ("queued_priority") //editing this breaks things. + return 0 + . = ..() diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 5b251a3edfa..4a39419d4f2 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,43 +1,53 @@ -// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) var/global/list/internal_byond_list_vars = list("contents" = TRUE, "verbs" = TRUE, "screen" = TRUE, "images" = TRUE) /datum - var/var_edited = 0 //Warrenty void if seal is broken + var/var_edited = FALSE //Warrenty void if seal is broken var/datum/reagents/reagents = null var/fingerprintslast = null -/datum/proc/on_varedit(modified_var) //called whenever a var is edited - var_edited = 1 +/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited + switch(var_name) + if ("vars") + return FALSE + var_edited = TRUE + vars[var_name] = var_value + +/datum/proc/vv_get_var(var_name) + switch(var_name) + if ("vars") + return debug_variable(var_name, list(), 0, src) + return debug_variable(var_name, vars[var_name], 0, src) + +//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() + . = list() + . += "---" + .["Call Proc"] = "?_src_=vars;proc_call=\ref[src]" + .["Mark Object"] = "?_src_=vars;mark_object=\ref[src]" + /datum/proc/on_reagent_change() return + /client/proc/debug_variables(datum/D in world) set category = "Debug" set name = "View Variables" //set src in world - - if(!usr.client || !usr.client.holder) usr << "You need to be an administrator to access this." return - - var/title = "" - var/body = "" - if(!D) return - if(istype(D, /atom)) - var/atom/A = D - title = "[A.name] (\ref[A]) = [A.type]" - - #ifdef VARSICON - if (A.icon) - body += debug_variable("icon", new/icon(A.icon, A.icon_state, A.dir), 0) - #endif + var/islist = FALSE + if (istype(D, /list)) + islist = TRUE + var/title = "" + var/refid = "\ref[D]" var/icon/sprite if(istype(D,/atom)) @@ -46,175 +56,40 @@ var/global/list/internal_byond_list_vars = list("contents" = TRUE, "verbs" = TRU sprite = new /icon(AT.icon, AT.icon_state) usr << browse_rsc(sprite, "view_vars_sprite.png") - title = "[D] (\ref[D]) = [D.type]" - - body += {" "} - - body += "" - - body += "
" + title = "[D] (\ref[D]) = [(islist ? /list : D.type)]" + var/sprite_text if(sprite) - body += "" - - body += "
" - else - body += "
" - - body += "
" + sprite_text = "
" + var/list/atomsnowflake = list() if(istype(D,/atom)) var/atom/A = D if(isliving(A)) - body += "[D]" + atomsnowflake += "[D]" if(A.dir) - body += "
<< [dir2text(A.dir)] >>" + atomsnowflake += "
<< [dir2text(A.dir)] >>" var/mob/living/M = A - body += "
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"]" - body += {" -
- BRUTE:[M.getBruteLoss()] - FIRE:[M.getFireLoss()] - TOXIN:[M.getToxLoss()] - OXY:[M.getOxyLoss()] - CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] - STAMINA:[M.getStaminaLoss()] - - - + atomsnowflake += {" +
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] +
+ BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getBrainLoss()] + STAMINA:[M.getStaminaLoss()] + "} else - body += "[D]" + atomsnowflake += "[D]" if(A.dir) - body += "
<< [dir2text(A.dir)] >>" + atomsnowflake += "
<< [dir2text(A.dir)] >>" else - body += "[D]" + atomsnowflake += "[D]" - body += "" - - body += "
" - - var/formatted_type = text("[D.type]") + var/formatted_type = text("[(islist ? /list : D.type)]") if(length(formatted_type) > 25) var/middle_point = length(formatted_type) / 2 var/splitpoint = findtext(formatted_type,"/",middle_point) @@ -223,146 +98,281 @@ var/global/list/internal_byond_list_vars = list("contents" = TRUE, "verbs" = TRU else formatted_type = "Type too long" //No suitable splitpoint (/) found. - body += "
[formatted_type]" + var/marked + if(holder.marked_datum && holder.marked_datum == D) + marked = "
Marked Object" + var/varedited_line = "" + if(!islist && D.var_edited) + varedited_line = "
Var Edited" - if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D) - body += "
Marked Object" + var/list/dropdownoptions = list() + if (!islist) + dropdownoptions = D.vv_get_dropdown() + var/list/dropdownoptions_html = list() - if(D.var_edited) - body += "
Var Edited" - body += "
" - - body += "
Refresh" - - //if(ismob(D)) - // body += "
Show player panel

" - - body += {"
-
" - - body += "

" - - body += "E - Edit, tries to determine the variable type by itself.
" - body += "C - Change, asks you for the var type first.
" - body += "M - Mass modify: changes this variable for all objects of this type.

" - - body += "
Search:

" - - body += "
    " + for (var/name in dropdownoptions) + var/link = dropdownoptions[name] + if (link) + dropdownoptions_html += "" + else + dropdownoptions_html += "" var/list/names = list() - for (var/V in D.vars) - names += V + if (!islist) + for (var/V in D.vars) + names += V sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. - names = sortList(names) + var/list/variable_html = list() + if (islist) + var/list/L = D + for (var/i in 1 to L.len) + variable_html += debug_variable(i, L[L[i]], 0, D) + else - for (var/V in names) - body += debug_variable(V, D.vars[V], 0, D) + names = sortList(names) + for (var/V in names) + variable_html += D.vv_get_var(V) - body += "
" + var/html = {" + + + [title] + + + + +
+ + + + + +
+ + + + +
+ [sprite_text] +
+ [atomsnowflake.Join()] +
+
+
+ [formatted_type] + [marked] + [varedited_line] +
+
+
+ Refresh +
+ +
+
+
+
+
+ + E - Edit, tries to determine the variable type by itself.
+ C - Change, asks you for the var type first.
+ M - Mass modify: changes this variable for all objects of this type.
+
+
+ + + + + +
+
+ Search: +
+
+ +
+
+
    + [variable_html.Join()] +
- "} + + +"} - html += "" + usr << browse(html, "window=variables[refid];size=475x650") - usr << browse(html, "window=variables\ref[D];size=475x650") -/client/proc/debug_variable(name, value, level, datum/DA = null) +#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) +/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) var/html = "" - if(DA) - html += "
  • (E) (C) (M) " + if (istype(DA, /list)) + var/index = name + name = DA[name] //name is really the index until this line + html += "
  • (E) (C) (-) " + else + html += "
  • (E) (C) (M) " else html += "
  • " if (isnull(value)) - html += "[html_encode(name)] = null" + html += "[VV_HTML_ENCODE(name)] = null" else if (istext(value)) - html += "[html_encode(name)] = \"[html_encode(value)]\"" + html += "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" else if (isicon(value)) #ifdef VARSICON @@ -370,9 +380,9 @@ body var/rnd = rand(1,10000) var/rname = "tmp\ref[I][rnd].png" usr << browse_rsc(I, rname) - html += "[html_encode(name)] = ([value]) " + html += "[VV_HTML_ENCODE(name)] = ([value]) " #else - html += "[html_encode(name)] = /icon ([value])" + html += "[VV_HTML_ENCODE(name)] = /icon ([value])" #endif /* else if (istype(value, /image)) @@ -387,53 +397,53 @@ body #endif */ else if (isfile(value)) - html += "[html_encode(name)] = '[value]'" + html += "[VV_HTML_ENCODE(name)] = '[value]'" else if (istype(value, /client)) var/client/C = value - html += "[html_encode(name)] \ref[value] = [C] [C.type]" + html += "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]" else if (istype(value, /datum)) var/datum/D = value - html += "[html_encode(name)] \ref[value] = [D.type]" + html += "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" else if (istype(value, /list)) var/list/L = value - html += "[html_encode(name)] = /list ([L.len])" + if (internal_byond_list_vars[name]) + html += "[html_encode(name)] = /list ([L.len])" + else + html += "[VV_HTML_ENCODE(name)] = /list ([L.len])" - if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500)) + if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > 500)) name = "[name]" //Needs to be a string or it will go out of bounds in the internal_byond_list_vars array html += "" else - html += "[html_encode(name)] = [html_encode(value)]" + html += "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" html += "
  • " return html +#undef VV_HTML_ENCODE + /client/proc/view_var_Topic(href, href_list, hsrc) - //This should all be moved over to datum/admins/Topic() or something ~Carn if( (usr.client != src) || !src.holder ) return if(href_list["Vars"]) @@ -550,12 +560,56 @@ body if(!check_rights(0)) return - var/atom/A = locate(href_list["datummass"]) - if(!istype(A)) - usr << "This can only be used on instances of type /atom" + var/datum/D = locate(href_list["datummass"]) + if(!istype(D)) + usr << "This can only be used on instances of type /datum" return - cmd_mass_modify_object_variables(A, href_list["varnamemass"]) + cmd_mass_modify_object_variables(D, href_list["varnamemass"]) + + else if(href_list["listedit"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listedit"]) + if (!istype(L)) + usr << "This can only be used on instances of type /list" + return + + mod_list(L, null, "list", "contents", index, autodetect_class = TRUE) + + else if(href_list["listchange"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listedit"]) + if (!istype(L)) + usr << "This can only be used on instances of type /list" + return + + mod_list(L, null, "list", "contents", index, autodetect_class = FALSE) + + else if(href_list["listremove"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listedit"]) + if (!istype(L)) + usr << "This can only be used on instances of type /list" + return + + var/variable = L[index] + var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No") + if (prompt != "Yes") + return + L.Cut(index, index+1) + world.log << "### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]" + log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") + message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") + else if(href_list["give_spell"]) if(!check_rights(0)) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 77070de904c..b2ba48da39e 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -448,14 +448,6 @@ var/list/blood_splatter_icons = list() /atom/proc/setDir(newdir) dir = newdir -/atom/on_varedit(modified_var) - ..() - if(!Debug2) - admin_spawned = TRUE - switch(modified_var) - if("color") - add_atom_colour(color, ADMIN_COLOUR_PRIORITY) - /atom/proc/mech_melee_attack(obj/mecha/M) return @@ -518,3 +510,24 @@ var/list/blood_splatter_icons = list() color = C return +/atom/vv_edit_var(var_name, var_value) + if(!Debug2) + admin_spawned = TRUE + switch(var_name) + if("luminosity") + src.SetLuminosity(var_value) + return//prevent normal setting of this value + . = ..() + switch(var_name) + if("color") + add_atom_colour(color, ADMIN_COLOUR_PRIORITY) + +/atom/vv_get_dropdown() + . = ..() + . += "---" + var/turf/curturf = get_turf(src) + .["Jump to"] = "?_src_=holder;adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]" + .["Add reagent"] = "?_src_=vars;addreagent=\ref[src]" + .["Trigger EM pulse"] = "?_src_=vars;emp=\ref[src]" + .["Trigger explosion"] = "?_src_=vars;explode=\ref[src]" + diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 7c7814d6b5f..6c36b7b6b76 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -350,7 +350,6 @@ return - /atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y) if(!no_effect && (visual_effect_icon || used_item)) do_item_attack_animation(A, visual_effect_icon, used_item) @@ -409,3 +408,8 @@ // And animate the attack! animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) + +/atom/movable/vv_get_dropdown() + . = ..() + . -= "Jump to" + .["Follow"] = "?_src_=holder;adminplayerobservefollow=\ref[src]" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 6b30d8f48f0..3db006968d5 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -143,9 +143,9 @@ var/list/airlock_overlays = list() FoundDoor.cyclelinkedairlock = src cyclelinkedairlock = FoundDoor -/obj/machinery/door/airlock/on_varedit(varname) +/obj/machinery/door/airlock/vv_edit_var(var_name) . = ..() - switch (varname) + switch (var_name) if ("cyclelinkeddir") cyclelinkairlock() diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 33e05becc96..05ddecfda1d 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -183,3 +183,7 @@ /obj/proc/on_mob_move(dir, mob) return + +/obj/vv_get_dropdown() + . = ..() + .["Delete all of type"] = "?_src_=vars;delall=\ref[src]" diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 9673701d8b6..16a651eecff 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -23,6 +23,9 @@ var/list/admin_ranks = list() //list of all admin_rank datums adds = init_adds subs = init_subs +/datum/admin_rank/vv_edit_var(var_name, var_value) + return FALSE + /proc/admin_keyword_to_flag(word, previous_rights=0) var/flag = 0 switch(ckey(word)) diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index bef00ab9145..09933969fc0 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -56,6 +56,9 @@ var/list/admin_datums = list() return 1 //we have all the rights they have and more return 0 +/datum/admins/vv_edit_var(var_name, var_value) + return FALSE //nice try trialmin + /* checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags) if rights_required == 0, then it simply checks if they are an admin. diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 4e05299cc6f..40948e4b02b 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -358,26 +358,56 @@ var/list/TYPES_SHORTCUTS = list( /obj/item/weapon/reagent_containers/food/drinks = "DRINK", //longest paths comes first /obj/item/weapon/reagent_containers/food = "FOOD", /obj/item/weapon/reagent_containers = "REAGENT_CONTAINERS", - /obj/machinery/atmospherics = "ATMOS", + /obj/item/weapon = "WEAPON", + /obj/machinery/atmospherics = "ATMOS_MECH", /obj/machinery/portable_atmospherics = "PORT_ATMOS", /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/missile_rack = "MECHA_MISSILE_RACK", /obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP", /obj/item/organ = "ORGAN", + /obj/item = "ITEM", + /obj/machinery = "MACHINERY", + /obj/effect = "EFFECT", + /obj = "O", + /datum = "D", + /turf/open = "OPEN", + /turf/closed = "CLOSED", + /turf = "T", + /mob/living/carbon = "CARBON", + /mob/living/simple_animal = "SIMPLE", + /mob/living = "LIVING", + /mob = "M" ) -var/global/list/g_fancy_list_of_types = null -/proc/get_fancy_list_of_types() - if (isnull(g_fancy_list_of_types)) //init - var/list/temp = sortList(subtypesof(/atom) - typesof(/area) - /atom/movable) - g_fancy_list_of_types = new(temp.len) + +/proc/get_fancy_list_of_atom_types() + var/static/list/pre_generated_list + if (!pre_generated_list) //init + var/list/temp = sortList(typesof(/atom)) + pre_generated_list = new(temp.len) for(var/type in temp) var/typename = "[type]" for (var/tn in TYPES_SHORTCUTS) if (copytext(typename,1, length("[tn]/")+1)=="[tn]/" /*findtextEx(typename,"[tn]/",1,2)*/ ) typename = TYPES_SHORTCUTS[tn]+copytext(typename,length("[tn]/")) break - g_fancy_list_of_types[typename] = type - return g_fancy_list_of_types + pre_generated_list[typename] = type + return pre_generated_list + + +/proc/get_fancy_list_of_datum_types() + var/static/list/pre_generated_list + if (!pre_generated_list) //init + var/list/temp = sortList(typesof(/datum) - typesof(/atom)) + pre_generated_list = new(temp.len) + for(var/type in temp) + var/typename = "[type]" + for (var/tn in TYPES_SHORTCUTS) + if (copytext(typename,1, length("[tn]/")+1)=="[tn]/" /*findtextEx(typename,"[tn]/",1,2)*/ ) + typename = TYPES_SHORTCUTS[tn]+copytext(typename,length("[tn]/")) + break + pre_generated_list[typename] = type + return pre_generated_list + /proc/filter_fancy_list(list/L, filter as text) var/list/matches = new @@ -392,7 +422,7 @@ var/global/list/g_fancy_list_of_types = null set category = "Debug" set name = "Del-All" - var/list/matches = get_fancy_list_of_types() + var/list/matches = get_fancy_list_of_atom_types() if (!isnull(object) && object!="") matches = filter_fancy_list(matches, object) diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm index b4a6821c09b..1bb380bbe29 100644 --- a/code/modules/admin/verbs/massmodvar.dm +++ b/code/modules/admin/verbs/massmodvar.dm @@ -23,26 +23,21 @@ src.massmodify_variables(A, var_name, method) feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/massmodify_variables(atom/O, var_name = "", method = 0) +/client/proc/massmodify_variables(datum/O, var_name = "", method = 0) if(!check_rights(R_VAREDIT)) return - - for(var/p in forbidden_varedit_object_types) - if( istype(O,p) ) - usr << "It is forbidden to edit this object's variables." - return - - var/list/names = list() - for (var/V in O.vars) - names += V - - names = sortList(names) + if(!istype(O)) + return var/variable = "" - if(!var_name) - variable = input("Which var?","Var") as null|anything in names + var/list/names = list() + for (var/V in O.vars) + names += V + + names = sortList(names) + + variable = input("Which var?", "Var") as null|anything in names else variable = var_name @@ -50,10 +45,9 @@ return var/default var/var_value = O.vars[variable] - var/dir if(variable in VVckey_edit) - usr << "It's forbidden to mass-modify ckeys. I'll crash everyone's client you dummy." + src << "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy." return if(variable in VVlocked) if(!check_rights(R_DEBUG)) @@ -61,137 +55,77 @@ if(variable in VVicon_edit_lock) if(!check_rights(R_FUN|R_DEBUG)) return + if(variable in VVpixelmovement) + if(!check_rights(R_DEBUG)) + return + var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT", "Continue", "ABORT") + if (prompt != "Continue") + return - if(isnull(var_value)) - usr << "Unable to determine variable type." - - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - default = "num" - setDir(1) - - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - default = "list" + default = vv_get_class(var_value) + if(isnull(default)) + src << "Unable to determine variable type." else - usr << "Variable appears to be FILE." - default = "file" + src << "Variable appears to be [uppertext(default)]." - usr << "Variable contains: [var_value]" - if(dir) - switch(var_value) - if(1) - setDir("NORTH") - if(2) - setDir("SOUTH") - if(4) - setDir("EAST") - if(8) - setDir("WEST") - if(5) - setDir("NORTHEAST") - if(6) - setDir("SOUTHEAST") - if(9) - setDir("NORTHWEST") - if(10) - setDir("SOUTHWEST") - else - setDir(null) - if(dir) - usr << "If a direction, direction is: [dir]" + src << "Variable contains: [var_value]" - var/class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","icon","file","edit referenced object","restore to default") + if(default == VV_NUM) + var/dir_text = "" + if(dir < 0 && dir < 16) + if(dir & 1) + dir_text += "NORTH" + if(dir & 2) + dir_text += "SOUTH" + if(dir & 4) + dir_text += "EAST" + if(dir & 8) + dir_text += "WEST" - if(!class) + if(dir_text) + src << "If a direction, direction is: [dir_text]" + + var/value = vv_get_value(default_class = default) + var/new_value = value["value"] + var/class = value["class"] + + if(!class || !new_value == null && class != VV_NULL) return - var/original_name + if (class == VV_MESSAGE) + class = VV_TEXT - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name + if (value["type"]) + class = VV_NEW_TYPE + + var/original_name = "[O]" + + var/rejected = 0 + var/accepted = 0 switch(class) + if(VV_RESTORE_DEFAULT) + src << "Finding items" + var/list/items = get_all_of_type(O.type, !method) + for(var/thing in items) + if (!thing) + continue + var/datum/D = thing + if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE) + accepted++ + else + rejected++ + CHECK_TICK - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/new_value = input("Enter new text:","Text",O.vars[variable]) as message|null - if(new_value == null) return - + if(VV_TEXT) var/process_vars = 0 var/unique = 0 if(findtext(new_value,"\[")) - process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") + process_vars = alert(usr, "\[] detected in string, process as variables?", "Process Variables?", "Yes", "No") if(process_vars == "Yes") process_vars = 1 - unique = alert(usr,"Process vars unique to each instance, or same for all?","Variable Association","Unique","Same") + unique = alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", "Unique", "Same") if(unique == "Unique") unique = 1 else @@ -202,337 +136,148 @@ var/pre_processing = new_value var/list/varsvars = list() - if(process_vars) + if(process_vars && !unique) varsvars = string2listofvars(new_value, O) if(varsvars.len) for(var/V in varsvars) new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]") - O.vars[variable] = new_value + src << "Finding items" + var/list/items = get_all_of_type(O.type, !method) + for(var/thing in items) + if (!thing) + continue + var/datum/D = thing + if(process_vars && unique) + new_value = pre_processing + for(var/V in varsvars) + new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]") - //Convert the string vars for anything that's not O - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - new_value = pre_processing //reset new_value, ready to convert it uniquely for the next iteration - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[M.vars[V]]") - else - new_value = O.vars[variable] //We already processed the non-unique form for O, reuse it - - M.vars[variable] = new_value - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - new_value = pre_processing - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[A.vars[V]]") - else - new_value = O.vars[variable] - - A.vars[variable] = new_value - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - new_value = pre_processing - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[A.vars[V]]") - else - new_value = O.vars[variable] - - A.vars[variable] = new_value - CHECK_TICK - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - new_value = pre_processing - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[M.vars[V]]") - else - new_value = O.vars[variable] - - M.vars[variable] = new_value - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - new_value = pre_processing - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[A.vars[V]]") - else - new_value = O.vars[variable] - - A.vars[variable] = new_value - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - new_value = pre_processing - - if(process_vars) - if(unique) - for(var/V in varsvars) - new_value = replacetext(new_value,"\[[V]]","[A.vars[V]]") - else - new_value = O.vars[variable] - - A.vars[variable] = new_value - CHECK_TICK - - if("num") - var/new_value = input("Enter new number:","Num",\ - O.vars[variable]) as num|null - if(new_value == null) return - - if(variable=="luminosity") - O.SetLuminosity(new_value) - else - O.vars[variable] = new_value - - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - if(variable=="luminosity") - M.SetLuminosity(new_value) - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - if(variable=="luminosity") - A.SetLuminosity(new_value) - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - if(variable=="luminosity") - A.SetLuminosity(new_value) - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - if(variable=="luminosity") - M.SetLuminosity(new_value) - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - if(variable=="luminosity") - A.SetLuminosity(new_value) - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - if(variable=="luminosity") - A.SetLuminosity(new_value) - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("type") - var/new_value - new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("file") - var/new_value = input("Pick file:","File",O.vars[variable]) as null|file - if(new_value == null) return - O.vars[variable] = new_value - - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("icon") - var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(ismob(O)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isobj(O)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if(method) - if(ismob(O)) - for(var/mob/M in mob_list) - if(istype(M,O.type)) - M.on_varedit(variable) + if (D.vv_edit_var(variable, new_value) != FALSE) + accepted++ + else + rejected++ CHECK_TICK - else if(isobj(O)) - for(var/obj/A in world) - if(istype(A,O.type)) - A.on_varedit(variable) + if (VV_NEW_TYPE) + var/many = alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", "One", "Many", "Cancel") + if (many == "Cancel") + return + if (many == "Many") + many = TRUE + else + many = FALSE + + var/type = value["type"] + src << "Finding items" + var/list/items = get_all_of_type(O.type, !method) + for(var/thing in items) + if (!thing) + continue + var/datum/D = thing + if(many && !new_value) + new_value = new type() + + if (D.vv_edit_var(variable, new_value) != FALSE) + accepted++ + else + rejected++ + new_value = null CHECK_TICK - else if(isturf(O)) - for(var/turf/A in block(locate(1,1,1),locate(world.maxx,world.maxy,world.maxz))) - if(istype(A,O.type)) - A.on_varedit(variable) + else + src << "Finding items" + var/list/items = get_all_of_type(O.type, !method) + for(var/thing in items) + if (!thing) + continue + var/datum/D = thing + if (D.vv_edit_var(variable, new_value) != FALSE) + accepted++ + else + rejected++ CHECK_TICK + + var/count = rejected+accepted + if (!accepted) + if (!rejected) + src << "No objects found" + else + src << "Every object rejected your edit" + //return + + if (rejected) + src << "[rejected] out of [count] objects rejected your edit" + + world.log << "### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])" + log_admin("[key_name(src)] mass modified [accepted] [original_name]' [variable] to [O.vars[variable]]") + message_admins("[key_name_admin(src)] mass modified [accepted] [original_name]' [variable] to [O.vars[variable]]") + + +/proc/get_all_of_type(var/T, stricttype = FALSE) + var/list/typecache = list() + typecache[T] = 1 + if (!stricttype) + typecache = typecacheof(typecache) + . = list() + if (ispath(T, /mob)) + for(var/mob/thing in mob_list) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /obj/machinery/door)) + for(var/obj/machinery/door/thing in airlocks) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /obj/machinery)) + for(var/obj/machinery/thing in machines) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /obj)) + for(var/obj/thing in world) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /atom/movable)) + for(var/atom/movable/thing in world) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /turf)) + for(var/turf/thing in world) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /atom)) + for(var/atom/thing in world) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /client)) + for(var/client/thing in clients) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /datum)) + for(var/datum/thing) + if (typecache[thing.type]) + . += thing + CHECK_TICK + else - if(ismob(O)) - for(var/mob/M in mob_list) - if(M.type == O.type) - M.on_varedit(variable) - CHECK_TICK + for(var/datum/thing in world) + if (typecache[thing.type]) + . += thing + CHECK_TICK - else if(isobj(O)) - for(var/obj/A in world) - if(A.type == O.type) - A.on_varedit(variable) - CHECK_TICK - - else if(isturf(O)) - for(var/turf/A in world) - if(A.type == O.type) - A.on_varedit(variable) - CHECK_TICK - - world.log << "### MassVarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" - log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]") \ No newline at end of file diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index 29c0661f8bd..f57d546c8d8 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -1,88 +1,200 @@ -var/list/forbidden_varedit_object_types = list( - /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea. - /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering - /datum/feedback_variable, //Prevents people messing with feedback gathering - /datum/admin_rank //editing my own rank? it's more likely than you think - ) - -var/list/VVlocked = list("vars", "var_edited", "client", "virus", "viruses", "cuffed", "last_eaten", "unlock_content", "step_x", "step_y", "force_ending") +var/list/VVlocked = list("vars", "var_edited", "client", "virus", "viruses", "cuffed", "last_eaten", "unlock_content", "force_ending") var/list/VVicon_edit_lock = list("icon", "icon_state", "overlays", "underlays", "resize") var/list/VVckey_edit = list("key", "ckey") +var/list/VVpixelmovement = list("step_x", "step_y", "bound_height", "bound_width", "bound_x", "bound_y") -/* -/client/proc/cmd_modify_object_variables(obj/O as obj|mob|turf|area in world) - set category = "Debug" - set name = "Edit Variables" - set desc="(target) Edit a target item's variables" - src.modify_variables(O) - feedback_add_details("admin_verb","EDITV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -*/ -/client/proc/cmd_modify_ticker_variables() - set category = "Debug" - set name = "Edit Ticker Variables" +/client/proc/vv_get_class(var/var_value) + if(isnull(var_value)) + . = VV_NULL - if (ticker == null) - src << "Game hasn't started yet." + else if (isnum(var_value)) + . = VV_NUM + + else if (istext(var_value)) + if (findtext(var_value, "\n")) + . = VV_MESSAGE + else + . = VV_TEXT + + else if (isicon(var_value)) + . = VV_ICON + + else if (ismob(var_value)) + . = VV_MOB_REFERENCE + + else if (isloc(var_value)) + . = VV_ATOM_REFERENCE + + else if (istype(var_value,/client)) + . = VV_CLIENT + + else if (istype(var_value, /datum)) + . = VV_DATUM_REFERENCE + + else if (ispath(var_value)) + if (ispath(var_value, /atom)) + . = VV_ATOM_TYPE + else if (ispath(var_value, /datum)) + . = VV_DATUM_TYPE + else + . = VV_TYPE + + else if (istype(var_value,/list)) + . = VV_LIST + + else if (isfile(var_value)) + . = VV_FILE else - src.modify_variables(ticker) - feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + . = VV_NULL -/client/proc/mod_list_add_ass(atom/O) //haha +/client/proc/vv_get_value(class, default_class, current_value, restricted_classes, extra_classes) + . = list("class" = class, "value" = null) + if (!class) + var/list/classes = list ( + VV_NUM, + VV_TEXT, + VV_MESSAGE, + VV_ICON, + VV_ATOM_REFERENCE, + //#ifdef TESTING + //VV_DATUM_REFERENCE, + //#endif TESTING + VV_MOB_REFERENCE, + VV_CLIENT, + VV_ATOM_TYPE, + VV_DATUM_TYPE, + VV_TYPE, + VV_FILE, + VV_NEW_ATOM, + VV_NEW_DATUM, + VV_NEW_TYPE, + VV_NEW_LIST, + VV_NULL, + VV_RESTORE_DEFAULT + ) - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum") + if(holder && holder.marked_datum && !(VV_MARKED_DATUM in restricted_classes)) + classes += "[VV_MARKED_DATUM] ([holder.marked_datum.type])" + if (restricted_classes) + classes -= restricted_classes - if(!class) + if (extra_classes) + classes += extra_classes + + .["class"] = input(src, "What kind of data?", "Variable Type", default_class) as null|anything in classes + if (holder && holder.marked_datum && .["class"] == "[VV_MARKED_DATUM] ([holder.marked_datum.type])") + .["class"] = VV_MARKED_DATUM + + + switch(.["class"]) + if (VV_TEXT) + .["value"] = input("Enter new text:", "Text", current_value) as null|text + if (.["value"] == null) + .["class"] = null + return + if (VV_MESSAGE) + .["value"] = input("Enter new text:", "Text", current_value) as null|message + if (.["value"] == null) + .["class"] = null + return + if (VV_NUM) + .["value"] = input("Enter new number:", "Num", current_value) as null|num + if (.["value"] == null) + .["class"] = null + return + if (VV_ATOM_TYPE) + .["value"] = input("Enter type:", "Type", current_value) as null|anything in get_fancy_list_of_atom_types() + if (.["value"] == null) + .["class"] = null + return + if (VV_DATUM_TYPE) + .["value"] = input("Enter type:", "Type", current_value) as null|anything in get_fancy_list_of_datum_types() + if (.["value"] == null) + .["class"] = null + return + if (VV_TYPE) + var/type = current_value + do + type = input("Enter type:", "Type", type) as null|text + if (!type) + break + type = text2path(type) + while(!type) + if (!type) + .["class"] = null + return + .["value"] = type + if (VV_ATOM_REFERENCE) + .["value"] = input("Select reference:", "Reference", current_value) as null|mob|obj|turf|area in world + if (.["value"] == null) + .["class"] = null + return + if (VV_MOB_REFERENCE) + .["value"] = input("Select reference:", "Reference", current_value) as null|mob in world + if (.["value"] == null) + .["class"] = null + return + if (VV_CLIENT) + .["value"] = input("Select reference:", "Reference", current_value) as null|anything in clients + if (.["value"] == null) + .["class"] = null + return + if (VV_FILE) + .["value"] = input("Pick file:", "File") as null|file + if (.["value"] == null) + .["class"] = null + return + if (VV_ICON) + .["value"] = input("Pick icon:", "Icon") as null|icon + if (.["value"] == null) + .["class"] = null + return + if (VV_MARKED_DATUM) + .["value"] = holder.marked_datum + if (.["value"] == null) + .["class"] = null + return + if (VV_NEW_ATOM) + var/type = input("Enter type:", "Type", current_value) as null|anything in get_fancy_list_of_atom_types() + if (!type) + .["class"] = null + return + .["value"] = new type() + .["type"] = type + if (VV_NEW_DATUM) + var/type = input("Enter type:", "Type", current_value) as null|anything in get_fancy_list_of_datum_types() + if (!type) + .["class"] = null + return + .["value"] = new type() + .["type"] = type + if (VV_NEW_TYPE) + var/type = current_value + do + type = input("Enter type:", "Type", type) as null|text + if (!type) + break + type = text2path(type) + while(!type) + if (!type) + .["class"] = null + return + .["value"] = new type() + .["type"] = type + if (VV_NEW_LIST) + .["value"] = list() + .["type"] = /list + +/client/proc/mod_list_add_ass(atom/O) //hehe + + var/list/L = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT)) + var/class = L["class"] + if (!class) return + var/var_value = L["value"] - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as null|message - - if("num") - var_value = input("Enter new number:","Num") as null|num - - if("type") - var_value = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as null|mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as null|mob in world - - if("file") - var_value = input("Pick file:","File") as null|file - - if("icon") - var_value = input("Pick icon:","Icon") as null|icon - - if("marked datum") - var_value = holder.marked_datum - - if("new atom") - var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - var_value = new type() - - if("new datum") - var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf,/client)) - var_value = new type() - - if(!var_value) return - - if(istext(var_value)) + if(class == VV_TEXT || class == VV_MESSAGE) if(findtext(var_value,"\[")) var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") if(process_vars == "Yes") @@ -94,123 +206,216 @@ var/list/VVckey_edit = list("key", "ckey") /client/proc/mod_list_add(list/L, atom/O, original_name, objectvar) - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum") - - if(!class) + var/list/LL = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT)) + var/class = LL["class"] + if (!class) return + var/var_value = LL["value"] - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as message - - if("num") - var_value = input("Enter new number:","Num") as num - - if("type") - var_value = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as mob in world - - if("file") - var_value = input("Pick file:","File") as file - - if("icon") - var_value = input("Pick icon:","Icon") as icon - - if("marked datum") - var_value = holder.marked_datum - - if("new atom") - var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - var_value = new type() - - if("new datum") - var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf,/client)) - var_value = new type() - - if(!var_value) return - - if(istext(var_value)) - if(findtext(var_value,"\[")) + if(class == VV_TEXT || class == VV_MESSAGE) + if(O && findtext(var_value,"\[")) var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") if(process_vars == "Yes") var/list/varsvars = string2listofvars(var_value, O) for(var/V in varsvars) var_value = replacetext(var_value,"\[[V]]","[O.vars[V]]") - L += var_value - switch(alert("Would you like to associate a var with the list entry?",,"Yes","No")) + var/list/newlist = L.Copy() + newlist += var_value + + switch(alert("Would you like to associate a value with the list entry?",,"Yes","No")) if("Yes") - L[var_value] = mod_list_add_ass(O) //haha - O.on_varedit(objectvar) - world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: ADDED=[var_value]" + newlist[var_value] = mod_list_add_ass(O) //hehe + if (O) + if (O.vv_edit_var(objectvar, newlist) == FALSE) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: ADDED=[var_value]" log_admin("[key_name(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]") message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]") -/client/proc/mod_list(list/L, atom/O, original_name, objectvar) +/client/proc/mod_list(list/L, atom/O, original_name, objectvar, index, autodetect_class = FALSE) if(!check_rights(R_VAREDIT)) return - if(!istype(L,/list)) + if(!istype(L, /list)) src << "Not a List." + 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") if(confirm != "Continue") return - var/assoc = 0 - if(L.len > 0) - var/a = L[1] - if(istext(a) && L[a] != null) - assoc = 1 //This is pretty weak test but i can't think of anything else - usr << "List appears to be associative." + var/list/names = null - if(!assoc) - names = sortList(L) + for (var/i in 1 to L.len) + names["#[i] [L[i]] = [L[L[i]]]"] = i + if (!index) + var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + "(CLEAR NULLS)" + "(CLEAR DUPES)" + "(SHUFFLE)" + + if(variable == null) + return + + if(variable == "(ADD VAR)") + mod_list_add(L, O, original_name, objectvar) + return + + if(variable == "(CLEAR NULLS)") + L = L.Copy() + listclearnulls(L) + if (!O.vv_edit_var(objectvar, L)) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS" + log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR NULLS") + message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR NULLS") + return + + if(variable == "(CLEAR DUPES)") + L = uniqueList(L) + if (!O.vv_edit_var(objectvar, L)) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES" + log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR DUPES") + message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR DUPES") + return + + if(variable == "(SHUFFLE)") + L = shuffle(L) + if (!O.vv_edit_var(objectvar, L)) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE" + log_admin("[key_name(src)] modified [original_name]'s [objectvar]: SHUFFLE") + message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: SHUFFLE") + return + + index = names[variable] + - var/variable var/assoc_key - if(assoc) - variable = input("Which var?","Var") as null|anything in L + "(ADD VAR)" + "(CLEAR NULLS)" - else - variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + "(CLEAR NULLS)" - - if(variable == "(ADD VAR)") - mod_list_add(L, O, original_name, objectvar) + if (index == null) return - - if(variable == "(CLEAR NULLS)") - listclearnulls(L) + var/assoc = 0 + var/prompt = alert(src, "Do you want to edit the key or it's assigned value?", "Associated List", "Key", "Assigned Value", "Cancel") + if (prompt == "Cancel") return - - if(assoc) - assoc_key = variable - variable = L[assoc_key] - - if(!assoc && !variable || assoc && !assoc_key) - return - + if (prompt == "Assigned Value") + assoc = 1 + assoc_key = L[index] var/default + var/variable + if (assoc) + variable = L[assoc_key] + else + variable = L[index] - var/dir + default = vv_get_class(variable) + + src << "Variable appears to be [uppertext(default)]." + + src << "Variable contains: [L[index]]" + + if(default == VV_NUM) + var/dir_text = "" + if(dir < 0 && dir < 16) + if(dir & 1) + dir_text += "NORTH" + if(dir & 2) + dir_text += "SOUTH" + if(dir & 4) + dir_text += "EAST" + if(dir & 8) + dir_text += "WEST" + + if(dir_text) + usr << "If a direction, direction is: [dir_text]" + + var/original_var + if(assoc) + original_var = L[assoc_key] + else + original_var = L[index] + if (O) + L = L.Copy() + var/class + if(autodetect_class) + if (default == VV_TEXT) + default = VV_MESSAGE + class = default + var/list/LL = vv_get_value(default_class = default, current_value = original_var, restricted_classes = list(VV_RESTORE_DEFAULT), extra_classes = list(VV_LIST, "DELETE FROM LIST")) + class = LL["class"] + if (!class) + return + var/new_var = LL["value"] + + if(class == VV_MESSAGE) + class = VV_TEXT + + switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. + if(VV_LIST) + mod_list(variable, O, original_name, objectvar) + + if("DELETE FROM LIST") + L.Cut(index, index+1) + if (O) + if (O.vv_edit_var(objectvar, L)) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]" + log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]") + message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]") + return + + if(VV_TEXT) + if(O && findtext(new_var,"\[")) + var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") + if(process_vars == "Yes") + var/list/varsvars = string2listofvars(new_var, O) + for(var/V in varsvars) + new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]") + + + if(assoc) + L[assoc_key] = new_var + else + L[index] = new_var + if (O) + if (O.vv_edit_var(objectvar, L) == FALSE) + src << "Your edit was rejected by the object." + return + world.log << "### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]" + log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") + message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]") + +/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) + if(!check_rights(R_VAREDIT)) + return + + var/class + var/variable + var/var_value + + if(param_var_name) + if(!param_var_name in O.vars) + src << "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])" + return + variable = param_var_name + + else + var/list/names = list() + for (var/V in O.vars) + names += V + + names = sortList(names) + + variable = input("Which var?","Var") as null|anything in names + if(!variable) + return + + var_value = O.vars[variable] if(variable in VVlocked) if(!check_rights(R_DEBUG)) @@ -221,400 +426,70 @@ var/list/VVckey_edit = list("key", "ckey") if(variable in VVicon_edit_lock) if(!check_rights(R_FUN|R_DEBUG)) return - - if(isnull(variable)) - usr << "Unable to determine variable type." - - else if(isnum(variable)) - usr << "Variable appears to be NUM." - default = "num" - setDir(1) - - else if(istext(variable)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(variable)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(variable)) - usr << "Variable appears to be ICON." - variable = "\icon[variable]" - default = "icon" - - else if(istype(variable,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else if(istype(variable,/atom) || istype(variable,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(variable,/list)) - usr << "Variable appears to be LIST." - default = "list" - - else - usr << "Variable appears to be FILE." - default = "file" - - usr << "Variable contains: [variable]" - if(dir) - switch(variable) - if(1) - setDir("NORTH") - if(2) - setDir("SOUTH") - if(4) - setDir("EAST") - if(8) - setDir("WEST") - if(5) - setDir("NORTHEAST") - if(6) - setDir("SOUTHEAST") - if(9) - setDir("NORTHWEST") - if(10) - setDir("SOUTHWEST") - else - setDir(null) - - if(dir) - usr << "If a direction, direction is: [dir]" - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "DELETE FROM LIST") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/original_var - if(assoc) - original_var = L[assoc_key] - else - original_var = L[L.Find(variable)] - - var/new_var - switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. - - if("list") - mod_list(variable, O, original_name, objectvar) - - if("restore to default") - new_var = initial(variable) - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("edit referenced object") - modify_variables(variable) - - if("DELETE FROM LIST") - world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[variable]")]" - log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[variable]") - message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[variable]") - L -= variable - O.on_varedit(objectvar) + if(variable in VVpixelmovement) + if(!check_rights(R_DEBUG)) + return + var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT", "Continue", "ABORT") + if (prompt != "Continue") return - if("text") - new_var = input("Enter new text:","Text") as message - if(findtext(new_var,"\[")) - var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") - if(process_vars == "Yes") - var/list/varsvars = string2listofvars(new_var, O) - for(var/V in varsvars) - new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]") - - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("num") - new_var = input("Enter new number:","Num") as num - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("type") - new_var = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("reference") - new_var = input("Select reference:","Reference") as mob|obj|turf|area in world - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("mob reference") - new_var = input("Select reference:","Reference") as mob in world - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("file") - new_var = input("Pick file:","File") as file - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("icon") - new_var = input("Pick icon:","Icon") as icon - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("marked datum") - new_var = holder.marked_datum - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("new atom") - var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - new_var = new type() - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("new datum") - var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf,/client)) - new_var = new type() - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - O.on_varedit(objectvar) - world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: [original_var]=[new_var]" - log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") - message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]") - -/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) - if(!check_rights(R_VAREDIT)) - return - - if(is_type_in_list(O, forbidden_varedit_object_types)) - usr << "It is forbidden to edit this object's variables." - return - - if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key")) - usr << "You cannot edit ckeys on client objects." - return - - var/class - var/variable - var/var_value - - if(param_var_name) - if(!param_var_name in O.vars) - src << "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])" - return - - if(param_var_name in VVlocked) - if(!check_rights(R_DEBUG)) - return - if(param_var_name in VVckey_edit) - if(!check_rights(R_SPAWN|R_DEBUG)) - return - if(param_var_name in VVicon_edit_lock) - if(!check_rights(R_FUN|R_DEBUG)) - return - - variable = param_var_name - - var_value = O.vars[variable] - - if(autodetect_class) - if(isnull(var_value)) - usr << "Unable to determine variable type." - class = null - autodetect_class = null - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - class = "num" - setDir(1) - - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - class = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - class = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - class = "icon" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - class = "cancel" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - class = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - class = "list" - - else - usr << "Variable appears to be FILE." - class = "file" + var/default = vv_get_class(var_value) + if(isnull(default)) + src << "Unable to determine variable type." else + src << "Variable appears to be [uppertext(default)]." - var/list/names = list() - for (var/V in O.vars) - names += V + src << "Variable contains: [var_value]" - names = sortList(names) + if(default == VV_NUM) + var/dir_text = "" + if(dir < 0 && dir < 16) + if(dir & 1) + dir_text += "NORTH" + if(dir & 2) + dir_text += "SOUTH" + if(dir & 4) + dir_text += "EAST" + if(dir & 8) + dir_text += "WEST" - variable = input("Which var?","Var") as null|anything in names - if(!variable) - return - var_value = O.vars[variable] + if(dir_text) + src << "If a direction, direction is: [dir_text]" - if(variable in VVlocked) - if(!check_rights(R_DEBUG)) - return - if(variable in VVckey_edit) - if(!check_rights(R_SPAWN|R_DEBUG)) - return - if(variable in VVicon_edit_lock) - if(!check_rights(R_FUN|R_DEBUG)) - return + if(autodetect_class) + if (default == VV_TEXT) + default = VV_MESSAGE + class = default - if(!autodetect_class) + var/list/value = vv_get_value(class, default, var_value, extra_classes = list(VV_LIST)) + class = value["class"] - var/dir - var/default - if(isnull(var_value)) - usr << "Unable to determine variable type." + if (!class) + return + var/var_new = value["value"] - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - default = "num" - setDir(1) + if(class == VV_MESSAGE) + class = VV_TEXT - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - default = "list" - - else - usr << "Variable appears to be FILE." - default = "file" - - usr << "Variable contains: [var_value]" - if(dir) - switch(var_value) - if(1) - setDir("NORTH") - if(2) - setDir("SOUTH") - if(4) - setDir("EAST") - if(8) - setDir("WEST") - if(5) - setDir("NORTHEAST") - if(6) - setDir("SOUTHEAST") - if(9) - setDir("NORTHWEST") - if(10) - setDir("SOUTHWEST") - else - setDir(null) - if(dir) - usr << "If a direction, direction is: [dir]" - - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum", "marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "new atom", "new datum") - - if(!class) - return - - var/original_name - - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name + var/original_name = "[O]" if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") class = "marked datum" switch(class) + if(VV_LIST) + if(!istype(var_value,/list)) + mod_list(list(), O, original_name, variable) - if("list") - if(!istype(O.vars[variable],/list)) - var/listchange = alert(usr,"Force change to empty list?","Change to list?","Yes","No") - if(listchange == "Yes") - O.vars[variable] = list() //Unlike all other VV operations, the type change must be set here, not at the end of setting data. Hence the warning - mod_list(O.vars[variable], O, original_name, variable) + mod_list(var_value, O, original_name, variable) return - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message - if(var_new==null) return + if(VV_RESTORE_DEFAULT) + var_new = initial(O.vars[variable]) + if(VV_TEXT) if(findtext(var_new,"\[")) var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No") if(process_vars == "Yes") @@ -622,75 +497,10 @@ var/list/VVckey_edit = list("key", "ckey") for(var/V in varsvars) var_new = replacetext(var_new,"\[[V]]","[O.vars[V]]") - O.vars[variable] = var_new - if("num") - if(variable=="luminosity") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - O.SetLuminosity(var_new) - else if(variable=="stat") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life - dead_mob_list -= O - living_mob_list += O - if((O.vars[variable] < 2) && (var_new == 2))//Kill he - living_mob_list -= O - dead_mob_list += O - O.vars[variable] = var_new - else - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new==null) return - O.vars[variable] = var_new - - if("type") - var/target_path = input("Enter type:", "Type", O.vars[variable]) as null|text - if(!target_path) - return - var/var_new = text2path(target_path) - if(!ispath(var_new)) - var_new = pick_closest_path(target_path) - if(!var_new) - return - O.vars[variable] = var_new - - if("reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world - if(var_new==null) return - O.vars[variable] = var_new - - if("mob reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world - if(var_new==null) return - O.vars[variable] = var_new - - if("file") - var/var_new = input("Pick file:","File",O.vars[variable]) as null|file - if(var_new==null) return - O.vars[variable] = var_new - - if("icon") - var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(var_new==null) return - O.vars[variable] = var_new - - if("marked datum") - O.vars[variable] = holder.marked_datum - - if("new atom") - var/type = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - var/var_new = new type() - if(var_new==null) return - O.vars[variable] = var_new - - if("new datum") - var/type = input("Enter type:","Type") as null|anything in (typesof(/datum)-typesof(/obj,/mob,/area,/turf,/client)) - var/var_new = new type() - if(var_new==null) return - O.vars[variable] = var_new - - O.on_varedit(variable) + if (O.vv_edit_var(variable, var_new) == FALSE) + src << "Your edit was rejected by the object." + return world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 5b8038c6b03..f63a99da1d8 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -679,7 +679,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/is_literate() return 1 -/mob/dead/observer/on_varedit(var_name) +/mob/dead/observer/vv_edit_var(var_name, var_value) . = ..() switch(var_name) if("icon") diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8a0f39643a4..34a0f460d6d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -763,3 +763,10 @@ for(var/X in internal_organs) var/obj/item/organ/I = X I.Insert(src) + +/mob/living/carbon/vv_get_dropdown() + . = ..() + . += "---" + .["Make AI"] = "?_src_=vars;makeai=\ref[src]" + .["Modify bodypart"] = "" + .["Modify organs"] = "?_src_=vars;editorgans=\ref[src]" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index f272edc05c7..41c4cc591db 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -852,31 +852,40 @@ var/next_mob_id = 0 /mob/proc/update_health_hud() return -/mob/living/on_varedit(modified_var) - switch(modified_var) +/mob/living/vv_edit_var(var_name, var_value) + switch(var_name) + if("stat") + if((stat == 2) && (var_value < 2))//Bringing the dead back to life + dead_mob_list -= src + living_mob_list += src + if((stat < 2) && (var_value == 2))//Kill he + living_mob_list -= src + dead_mob_list += src + . = ..() + switch(var_name) if("weakened") - SetWeakened(weakened) + SetWeakened(var_value) if("stunned") - SetStunned(stunned) + SetStunned(var_value) if("paralysis") - SetParalysis(paralysis) + SetParalysis(var_value) if("sleeping") - SetSleeping(sleeping) + SetSleeping(var_value) if("eye_blind") - set_blindness(eye_blind) + set_blindness(var_value) if("eye_damage") - set_eye_damage(eye_damage) + set_eye_damage(var_value) if("eye_blurry") - set_blurriness(eye_blurry) + set_blurriness(var_value) if("ear_deaf") - setEarDamage(-1, ear_deaf) + setEarDamage(-1, var_value) if("ear_damage") - setEarDamage(ear_damage, -1) + setEarDamage(var_value, -1) if("maxHealth") updatehealth() if("resize") update_transform() - ..() + /mob/proc/is_literate() return 0 @@ -886,3 +895,24 @@ var/next_mob_id = 0 /mob/proc/get_idcard() return + +/mob/vv_get_dropdown() + . = ..() + . += "---" + .["Gib"] = "?_src_=vars;gib=\ref[src]" + .["Give Spell"] = "?_src_=vars;give_spell=\ref[src]" + .["Remove Spell"] = "?_src_=vars;remove_spell=\ref[src]" + .["Give Disease"] = "?_src_=vars;give_disease=\ref[src]" + .["Toggle Godmode"] = "?_src_=vars;godmode=\ref[src]" + .["Drop Everything"] = "?_src_=vars;drop_everything=\ref[src]" + .["Regenerate Icons"] = "?_src_=vars;regenerateicons=\ref[src]" + .["Make Space Ninja"] = "?_src_=vars;ninja=\ref[src]" + .["Show player panel"] = "?_src_=vars;mob_player_panel=\ref[src]" + .["Toggle Build Mode"] = "?_src_=vars;build_mode=\ref[src]" + .["Assume Direct Control"] = "?_src_=vars;direct_control=\ref[src]" + .["Offer Control to Ghosts"] = "?_src_=vars;offer_control=\ref[src]" + +/mob/vv_get_var(var_name) + switch(var_name) + if ("attack_log") + return debug_variable(var_name, attack_log, 0, src, FALSE) \ No newline at end of file diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index d0812512d89..ed6f7b3cac1 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -30,13 +30,14 @@ STOP_PROCESSING(SSobj, src) return ..() -/obj/item/weapon/stock_parts/cell/on_varedit(modified_var) - if(modified_var == "self_recharge") - if(self_recharge) - START_PROCESSING(SSobj, src) - else - STOP_PROCESSING(SSobj, src) - ..() +/obj/item/weapon/stock_parts/cell/vv_edit_var(var_name, var_value) + switch(var_name) + if("self_recharge") + if(var_value) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + . = ..() /obj/item/weapon/stock_parts/cell/process() if(self_recharge) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index b5d19b27743..746ba7436b2 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -167,11 +167,13 @@ playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1) return (OXYLOSS) -/obj/item/weapon/gun/energy/on_varedit(modified_var) - if(modified_var == "selfcharge") - if(selfcharge) - START_PROCESSING(SSobj, src) - else - STOP_PROCESSING(SSobj, src) - ..() + +/obj/item/weapon/gun/energy/vv_edit_var(var_name, var_value) + switch(var_name) + if("selfcharge") + if(var_value) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + . = ..() diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index aae34edbd4f..b5b241c41d2 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -79,8 +79,8 @@ playsound(loc, fire_sound, 50, 1, -1) return (FIRELOSS) -/obj/item/weapon/gun/magic/on_varedit(varname) +/obj/item/weapon/gun/magic/vv_edit_var(var_name, var_value) . = ..() - switch (varname) + switch (var_name) if ("charges") recharge_newshot() \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 9e9aa46d19b..cdf9fc819f8 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -54,6 +54,7 @@ #include "code\__DEFINES\tablecrafting.dm" #include "code\__DEFINES\tgui.dm" #include "code\__DEFINES\tick.dm" +#include "code\__DEFINES\vv.dm" #include "code\__DEFINES\wires.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" @@ -94,6 +95,7 @@ #include "code\_globalvars\lists\names.dm" #include "code\_globalvars\lists\objects.dm" #include "code\_globalvars\lists\poll_ignore.dm" +#include "code\_globalvars\lists\typecache.dm" #include "code\_onclick\adjacent.dm" #include "code\_onclick\ai.dm" #include "code\_onclick\autoclick.dm"