Improved VV and callproc implementation

This commit is contained in:
GinjaNinja32
2015-07-02 09:26:10 +01:00
parent a006089b2a
commit 4e6b316a9e
8 changed files with 454 additions and 534 deletions

View File

@@ -0,0 +1,93 @@
// Keep these two together, they *must* be defined on both
// If /client ever becomes /datum/client or similar, they can be merged
/client/proc/get_view_variables_header()
return "<b>[src]</b>"
/datum/proc/get_view_variables_header()
return "<b>[src]</b>"
/atom/get_view_variables_header()
return {"
<a href='?_src_=vars;datumedit=\ref[src];varnameedit=name'><b>[src]</b></a>
<br><font size='1'>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=left'><<</a>
<a href='?_src_=vars;datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=right'>>></a>
</font>
"}
/mob/living/get_view_variables_header()
return {"
<a href='?_src_=vars;rename=\ref[src]'><b>[src]</b></a><font size='1'>
<br><a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=right'>>></a>
<br><a href='?_src_=vars;datumedit=\ref[src];varnameedit=ckey'>[ckey ? ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=\ref[src];varnameedit=real_name'>[real_name ? real_name : "No real name"]</a>
<br>
BRUTE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brute'>[getBruteLoss()]</a>
FIRE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=fire'>[getFireLoss()]</a>
TOXIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=toxin'>[getToxLoss()]</a>
OXY:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=oxygen'>[getOxyLoss()]</a>
CLONE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=clone'>[getCloneLoss()]</a>
BRAIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brain'>[getBrainLoss()]</a>
</font>
"}
// Same for these as for get_view_variables_header() above
/client/proc/get_view_variables_options()
return ""
/datum/proc/get_view_variables_options()
return ""
/mob/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;mob_player_panel=\ref[src]'>Show player panel</option>
<option>---</option>
<option value='?_src_=vars;give_spell=\ref[src]'>Give Spell</option>
<option value='?_src_=vars;give_disease2=\ref[src]'>Give Disease</option>
<option value='?_src_=vars;give_disease=\ref[src]'>Give TG-style Disease</option>
<option value='?_src_=vars;godmode=\ref[src]'>Toggle Godmode</option>
<option value='?_src_=vars;build_mode=\ref[src]'>Toggle Build Mode</option>
<option value='?_src_=vars;ninja=\ref[src]'>Make Space Ninja</option>
<option value='?_src_=vars;make_skeleton=\ref[src]'>Make 2spooky</option>
<option value='?_src_=vars;direct_control=\ref[src]'>Assume Direct Control</option>
<option value='?_src_=vars;drop_everything=\ref[src]'>Drop Everything</option>
<option value='?_src_=vars;regenerateicons=\ref[src]'>Regenerate Icons</option>
<option value='?_src_=vars;addlanguage=\ref[src]'>Add Language</option>
<option value='?_src_=vars;remlanguage=\ref[src]'>Remove Language</option>
<option value='?_src_=vars;addorgan=\ref[src]'>Add Organ</option>
<option value='?_src_=vars;remorgan=\ref[src]'>Remove Organ</option>
<option value='?_src_=vars;fix_nano=\ref[src]'>Fix NanoUI</option>
<option value='?_src_=vars;addverb=\ref[src]'>Add Verb</option>
<option value='?_src_=vars;remverb=\ref[src]'>Remove Verb</option>
<option value>---</option>
<option value='?_src_=vars;gib=\ref[src]'>Gib</option>
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}
/mob/living/carbon/human/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;setspecies=\ref[src]'>Set Species</option>
<option value='?_src_=vars;makeai=\ref[src]'>Make AI</option>
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
<option value='?_src_=vars;makeslime=\ref[src]'>Make slime</option>
"}
/obj/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;delall=\ref[src]'>Delete all of type</option>
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}
/turf/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}

View File

@@ -0,0 +1,545 @@
/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"])
debug_variables(locate(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_VAREDIT)) return
var/mob/M = locate(href_list["rename"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
var/new_name = sanitize(input(usr,"What would you like to name this mob?","Input a name",M.real_name) as text|null, MAX_NAME_LEN)
if( !new_name || !M ) return
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
M.fully_replace_character_name(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 = locate(href_list["datumedit"])
if(!istype(D,/datum) && !istype(D,/client))
usr << "This can only be used on instances of types /client or /datum"
return
modify_variables(D, href_list["varnameedit"], 1)
else if(href_list["varnamechange"] && href_list["datumchange"])
if(!check_rights(R_VAREDIT)) return
var/D = locate(href_list["datumchange"])
if(!istype(D,/datum) && !istype(D,/client))
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 = locate(href_list["datummass"])
if(!istype(A))
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(0)) return
var/mob/M = locate(href_list["mob_player_panel"])
if(!istype(M))
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_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_spell"])
if(!istype(M))
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["give_disease"])
if(!check_rights(R_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_disease"])
if(!istype(M))
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["give_disease2"])
if(!check_rights(R_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_disease2"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_disease2(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["godmode"])
if(!check_rights(R_REJUVINATE)) return
var/mob/M = locate(href_list["godmode"])
if(!istype(M))
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(0)) return
var/mob/M = locate(href_list["gib"])
if(!istype(M))
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 = locate(href_list["build_mode"])
if(!istype(M))
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 = locate(href_list["drop_everything"])
if(!istype(M))
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(0)) return
var/mob/M = locate(href_list["direct_control"])
if(!istype(M))
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_FUN)) return
var/mob/living/carbon/human/H = locate(href_list["make_skeleton"])
if(!istype(H))
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
H.ChangeToSkeleton()
href_list["datumrefresh"] = href_list["make_skeleton"]
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER)) return
var/obj/O = locate(href_list["delall"])
if(!isobj(O))
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?",,"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]?",,"Yes","No") != "Yes")
return
if(alert("Second confirmation required. Delete?",,"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)
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("<span class='notice'>[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)</span>")
if("Type and subtypes")
var/i = 0
for(var/obj/Obj in world)
if(istype(Obj,O_type))
i++
qdel(Obj)
if(!i)
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("<span class='notice'>[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)</span>")
else if(href_list["explode"])
if(!check_rights(R_DEBUG|R_FUN)) return
var/atom/A = locate(href_list["explode"])
if(!isobj(A) && !ismob(A) && !isturf(A))
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_FUN)) return
var/atom/A = locate(href_list["emp"])
if(!isobj(A) && !ismob(A) && !isturf(A))
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 = locate(href_list["mark_object"])
if(!istype(D))
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["rotatedatum"])
if(!check_rights(0)) return
var/atom/A = locate(href_list["rotatedatum"])
if(!istype(A))
usr << "This can only be done to instances of type /atom"
return
switch(href_list["rotatedir"])
if("right") A.set_dir(turn(A.dir, -45))
if("left") A.set_dir(turn(A.dir, 45))
href_list["datumrefresh"] = href_list["rotatedatum"]
else if(href_list["makemonkey"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makemonkey"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
else if(href_list["makerobot"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makerobot"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makealien"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeslime"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeslime"=href_list["makeslime"]))
else if(href_list["makeai"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeai"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if(href_list["setspecies"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["setspecies"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
var/new_species = input("Please choose a new species.","Species",null) as null|anything in all_species
if(!H)
usr << "Mob doesn't exist anymore"
return
if(H.set_species(new_species))
usr << "Set species of [H] to [H.species]."
else
usr << "Failed! Something went wrong."
else if(href_list["addlanguage"])
if(!check_rights(R_SPAWN)) return
var/mob/H = locate(href_list["addlanguage"])
if(!istype(H))
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 all_languages
if(!new_language)
return
if(!H)
usr << "Mob doesn't exist anymore"
return
if(H.add_language(new_language))
usr << "Added [new_language] to [H]."
else
usr << "Mob already knows that language."
else if(href_list["remlanguage"])
if(!check_rights(R_SPAWN)) return
var/mob/H = locate(href_list["remlanguage"])
if(!istype(H))
usr << "This can only be done to instances of type /mob"
return
if(!H.languages.len)
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)
usr << "Mob doesn't exist anymore"
return
if(H.remove_language(rem_language.name))
usr << "Removed [rem_language] from [H]."
else
usr << "Mob doesn't know that language."
else if(href_list["addverb"])
if(!check_rights(R_DEBUG)) return
var/mob/living/H = locate(href_list["addverb"])
if(!istype(H))
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)
usr << "Mob doesn't exist anymore"
return
if(!verb || verb == "Cancel")
return
else
H.verbs += verb
else if(href_list["remverb"])
if(!check_rights(R_DEBUG)) return
var/mob/H = locate(href_list["remverb"])
if(!istype(H))
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)
usr << "Mob doesn't exist anymore"
return
if(!verb)
return
else
H.verbs -= verb
else if(href_list["addorgan"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/M = locate(href_list["addorgan"])
if(!istype(M))
usr << "This can only be done to instances of type /mob/living/carbon"
return
var/new_organ = input("Please choose an organ to add.","Organ",null) as null|anything in typesof(/obj/item/organ)-/obj/item/organ
if(!new_organ) return
if(!M)
usr << "Mob doesn't exist anymore"
return
if(locate(new_organ) in M.internal_organs)
usr << "Mob already has that organ."
return
new new_organ(M)
else if(href_list["remorgan"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/M = locate(href_list["remorgan"])
if(!istype(M))
usr << "This can only be done to instances of type /mob/living/carbon"
return
var/obj/item/organ/rem_organ = input("Please choose an organ to remove.","Organ",null) as null|anything in M.internal_organs
if(!M)
usr << "Mob doesn't exist anymore"
return
if(!(locate(rem_organ) in M.internal_organs))
usr << "Mob does not have that organ."
return
usr << "Removed [rem_organ] from [M]."
rem_organ.removed()
qdel(rem_organ)
else if(href_list["fix_nano"])
if(!check_rights(R_DEBUG)) return
var/mob/H = locate(href_list["fix_nano"])
if(!istype(H) || !H.client)
usr << "This can only be done on mobs with clients"
return
nanomanager.send_resources(H.client)
usr << "Resource files sent"
H << "Your NanoUI Resource files have been refreshed"
log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ")
else if(href_list["regenerateicons"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["regenerateicons"])
if(!ismob(M))
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_FUN)) return
var/mob/living/L = locate(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)
usr << "Mob doesn't exist anymore"
return
switch(Text)
if("brute") L.adjustBruteLoss(amount)
if("fire") L.adjustFireLoss(amount)
if("toxin") L.adjustToxLoss(amount)
if("oxygen")L.adjustOxyLoss(amount)
if("brain") L.adjustBrainLoss(amount)
if("clone") L.adjustCloneLoss(amount)
else
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("<span class='notice'>[key_name(usr)] dealt [amount] amount of [Text] damage to [L]</span>")
href_list["datumrefresh"] = href_list["mobToDamage"]
else if(href_list["call_proc"])
var/datum/D = locate(href_list["call_proc"])
if(istype(D) || istype(D, /client)) // can call on clients too, not just datums
callproc_targetpicked(1, D)
if(href_list["datumrefresh"])
var/datum/DAT = locate(href_list["datumrefresh"])
if(istype(DAT, /datum) || istype(DAT, /client))
debug_variables(DAT)
return

View File

@@ -0,0 +1,160 @@
// Variables to not even show in the list.
// step_* and bound_* are here because they literally break the game and do nothing else.
// parent_type is here because it's pointless to show in VV.
/var/list/view_variables_hide_vars = list("bound_x", "bound_y", "bound_height", "bound_width", "bounds", "parent_type", "step_x", "step_y", "step_size")
// Variables not to expand the lists of. Vars is pointless to expand, and overlays/underlays cannot be expanded.
/var/list/view_variables_dont_expand = list("overlays", "underlays", "vars")
/client/proc/debug_variables(datum/D in world)
set category = "Debug"
set name = "View Variables"
if(!check_rights(0))
return
if(!D)
return
var/icon/sprite
if(istype(D, /atom))
var/atom/A = D
if(A.icon && A.icon_state)
sprite = icon(A.icon, A.icon_state)
usr << browse_rsc(sprite, "view_vars_sprite.png")
usr << browse_rsc('code/js/view_variables.js', "view_variables.js")
var/html = {"
<html>
<head>
<script src='view_variables.js'></script>
<title>[D] (\ref[D] - [D.type])</title>
<style>
body { font-family: Verdana, sans-serif; font-size: 9pt; }
.value { font-family: "Courier New", monospace; font-size: 8pt; }
</style>
</head>
<body onload='selectTextField(); updateSearch()'; onkeyup='updateSearch()'>
<div align='center'>
<table width='100%'><tr>
<td width='50%'>
<table align='center' width='100%'><tr>
[sprite ? "<td><img src='view_vars_sprite.png'></td>" : ""]
<td><div align='center'>[D.get_view_variables_header()]</div></td>
</tr></table>
<div align='center'>
<b><font size='1'>[replacetext("[D.type]", "/", "/<wbr>")]</font></b>
[holder.marked_datum == D ? "<br/><font size='1' color='red'><b>Marked Object</b></font>" : ""]
</div>
</td>
<td width='50%'>
<div align='center'>
<a href='?_src_=vars;datumrefresh=\ref[D]'>Refresh</a>
<form>
<select name='file'
size='1'
onchange='loadPage(this.form.elements\[0\])'
target='_parent._top'
onmouseclick='this.focus()'
style='background-color:#ffffff'>
<option>Select option</option>
<option />
<option value='?_src_=vars;mark_object=\ref[D]'>Mark Object</option>
<option value='?_src_=vars;call_proc=\ref[D]'>Call Proc</option>
[D.get_view_variables_options()]
</select>
</form>
</div>
</td>
</tr></table>
</div>
<hr/>
<font size='1'>
<b>E</b> - Edit, tries to determine the variable type by itself.<br/>
<b>C</b> - Change, asks you for the var type first.<br/>
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br/>
</font>
<hr/>
<table width='100%'><tr>
<td width='20%'>
<div align='center'>
<b>Search:</b>
</div>
</td>
<td width='80%'>
<input type='text'
id='filter'
name='filter_text'
value=''
style='width:100%;' />
</td>
</tr></table>
<hr/>
<ol id='vars'>
[make_view_variables_var_list(D)]
</ol>
</body>
</html>
"}
usr << browse(html, "window=variables\ref[D];size=475x650")
/proc/make_view_variables_var_list(datum/D)
. = ""
var/list/variables = list()
for(var/x in D.vars)
if(x in view_variables_hide_vars)
continue
variables += x
variables = sortList(variables)
for(var/x in variables)
. += make_view_variables_var_entry(D, x, D.vars[x])
/proc/make_view_variables_var_entry(datum/D, varname, value, level=0)
var/ecm = null
var/vtext = null
var/extra = null
if(D)
ecm = {"
(<a href='?_src_=vars;datumedit=\ref[D];varnameedit=[varname]'>E</a>)
(<a href='?_src_=vars;datumchange=\ref[D];varnamechange=[varname]'>C</a>)
(<a href='?_src_=vars;datummass=\ref[D];varnamemass=[varname]'>M</a>)
"}
if(isnull(value))
vtext = "null"
else if(istext(value))
vtext = "\"[value]\""
else if(isicon(value))
vtext = "[value]"
else if(isfile(value))
vtext = "'[value]'"
else if(istype(value, /datum))
var/datum/DA = value
if("[DA]" == "[DA.type]" || !"[DA]")
vtext = "<a href='?_src_=vars;Vars=\ref[DA]'>\ref[DA]</a> - [DA.type]"
else
vtext = "<a href='?_src_=vars;Vars=\ref[DA]'>\ref[DA]</a> - [DA] ([DA.type])"
else if(istype(value, /client))
var/client/C = value
vtext = "<a href='?_src_=vars;Vars=\ref[C]'>\ref[C]</a> - [C] ([C.type])"
else if(islist(value))
var/list/L = value
vtext = "/list ([L.len])"
if(!(varname in view_variables_dont_expand) && L.len > 0 && L.len < 100)
extra = "<ul>"
var/index = 1
for (var/entry in L)
if(istext(entry))
extra += make_view_variables_var_entry(null, entry, L[entry], level+1)
else
extra += make_view_variables_var_entry(null, index, L[index], level+1)
index++
extra += "</ul>"
else
vtext = "[value]"
return "<li>[ecm][varname] = <span class='value'>[vtext]</span>[extra]</li>"