Merge branch 'incremental_tg' r5200 into bs12_with_tgport

Conflicts:
	baystation12.dme
	code/__HELPERS/global_lists.dm
	code/__HELPERS/type2type.dm
	code/__HELPERS/unsorted.dm
	code/datums/datumvars.dm
	code/datums/disease.dm
	code/datums/organs/organ_external.dm
	code/datums/supplypacks.dm
	code/defines/obj.dm
	code/game/area/areas.dm
	code/game/atoms.dm
	code/game/gamemodes/cult/cult_structures.dm
	code/game/gamemodes/cult/runes.dm
	code/game/gamemodes/events.dm
	code/game/gamemodes/events/ninja_equipment.dm
	code/game/gamemodes/events/space_ninja.dm
	code/game/gamemodes/game_mode.dm
	code/game/gamemodes/gameticker.dm
	code/game/hud.dm
	code/game/jobs/access.dm
	code/game/jobs/job/civilian.dm
	code/game/machinery/alarm.dm
	code/game/machinery/cloning.dm
	code/game/machinery/computer/cloning.dm
	code/game/machinery/computer/medical.dm
	code/game/machinery/computer/syndicate_shuttle.dm
	code/game/machinery/telecomms/broadcaster.dm
	code/game/machinery/telecomms/machine_interactions.dm
	code/game/objects/effects/decals/contraband.dm
	code/game/objects/effects/signs.dm
	code/game/objects/items/devices/PDA/PDA.dm
	code/game/objects/items/devices/PDA/cart.dm
	code/game/objects/items/weapons/photography.dm
	code/game/objects/structures/door_assembly.dm
	code/game/objects/structures/window.dm
	code/game/sound.dm
	code/game/verbs/ooc.dm
	code/global.dm
	code/modules/DetectiveWork/detective_work.dm
	code/modules/DetectiveWork/evidence.dm
	code/modules/DetectiveWork/footprints_and_rag.dm
	code/modules/DetectiveWork/scanner.dm
	code/modules/admin/player_panel.dm
	code/modules/admin/verbs/adminhelp.dm
	code/modules/admin/verbs/adminpm.dm
	code/modules/awaymissions/gateway.dm
	code/modules/client/client defines.dm
	code/modules/client/client procs.dm
	code/modules/client/preferences.dm
	code/modules/clothing/spacesuits/rig.dm
	code/modules/mining/machine_processing.dm
	code/modules/mining/machine_stacking.dm
	code/modules/mining/mint.dm
	code/modules/mining/ores_coins.dm
	code/modules/mining/satchel_ore_boxdm.dm
	code/modules/mob/living/carbon/alien/alien.dm
	code/modules/mob/living/carbon/carbon.dm
	code/modules/mob/living/carbon/carbon_defines.dm
	code/modules/mob/living/carbon/human/human_damage.dm
	code/modules/mob/living/carbon/human/life.dm
	code/modules/mob/living/carbon/human/update_icons.dm
	code/modules/mob/living/living.dm
	code/modules/mob/living/say.dm
	code/modules/mob/mob.dm
	code/modules/mob/mob_cleanup.dm
	code/modules/mob/mob_defines.dm
	code/modules/mob/mob_transformation_simple.dm
	code/modules/mob/new_player/login.dm
	code/modules/mob/new_player/new_player.dm
	code/modules/mob/new_player/preferences_setup.dm
	code/modules/mob/new_player/savefile.dm
	code/modules/mob/new_player/sprite_accessories.dm
	code/modules/paperwork/folders.dm
	code/modules/paperwork/paper.dm
	code/modules/paperwork/photocopier.dm
	code/modules/projectiles/guns/energy/special.dm
	code/modules/projectiles/guns/projectile/automatic.dm
	code/setup.dm
	code/unused/mining/datum_processing_recipe.dm
	code/unused/powerarmor/powerarmor.dm
	code/world.dm
	html/changelog.html
	icons/effects/96x96.dmi
	icons/mob/head.dmi
	icons/mob/items_lefthand.dmi
	icons/mob/items_righthand.dmi
	icons/mob/suit.dmi
	icons/obj/clothing/hats.dmi
	icons/obj/clothing/suits.dmi
	icons/obj/hydroponics.dmi
	icons/obj/items.dmi
	icons/turf/areas.dmi
	icons/turf/walls.dmi
	maps/RandomZLevels/fileList.txt
	maps/RandomZLevels/spacebattle.dmm

Signed-off-by: Cael_Aislinn <cael_aislinn@yahoo.com.au>
This commit is contained in:
Cael_Aislinn
2013-01-07 00:23:22 +10:00
338 changed files with 21863 additions and 19941 deletions
+3 -19
View File
@@ -4,41 +4,25 @@
////////////////
var/datum/admins/holder = null
var/buildmode = 0
var/seeprayers = 1
var/muted = 0
var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
var/warned = 0
/////////
//OTHER//
/////////
var/listen_ooc = 1
var/datum/preferences/prefs = null
var/move_delay = 1
var/moving = null
var/adminobs = null
var/deadchat = 1
var/changes = 0
var/area = null
var/played = 0
var/be_alien = 0 //Check if that guy wants to be an alien
var/be_pai = 1 //Consider client when searching for players to recruit as a pAI
var/be_syndicate = 1 //Consider client for late-game autotraitor
var/be_spaceninja = 0
var/activeslot = 1 //Default active slot!
var/STFU_ghosts //80+ people rounds are fun to admin when text flies faster than airport security
var/STFU_radio //80+ people rounds are fun to admin when text flies faster than airport security
var/STFU_atklog = 0
///////////////
//SOUND STUFF//
///////////////
var/canplaysound = 1
var/ambience_playing= null
var/no_ambi = 0 //Toggle Ambience
var/midis = 1 //Toggle Midis
var/played = 0
////////////
//SECURITY//
+66 -5
View File
@@ -47,12 +47,15 @@
//Logs all hrefs
if(config && config.log_hrefs && href_logfile)
href_logfile << "<small>[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr])</small> || [href]<br>"
href_logfile << "<small>[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]<br>"
if(view_var_Topic(href,href_list,hsrc)) //Until viewvars can be rewritten as datum/admins/Topic()
return
switch(href_list["_src_"])
if("holder") hsrc = holder
if("usr") hsrc = mob
if("prefs") return prefs.process_link(usr,href_list)
if("vars") return view_var_Topic(href,href_list,hsrc)
..() //redirect to [locate(hsrc)]/Topic()
..() //redirect to hsrc.Topic()
/client/proc/handle_spam_prevention(var/message, var/mute_type)
if(config.automute_on && !holder && src.last_message == message)
@@ -109,6 +112,14 @@
admins += src
holder.owner = src
//preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum)
prefs = preferences_datums[ckey]
if(!prefs)
prefs = new /datum/preferences(src)
preferences_datums[ckey] = prefs
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
. = ..() //calls mob.Login()
if(custom_event_msg && custom_event_msg != "")
@@ -127,6 +138,11 @@
log_client_to_db()
send_resources()
if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates.
winset(src, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
//////////////
//DISCONNECT//
@@ -192,4 +208,49 @@
//3000 frames = 5 minutes
/client/proc/is_afk(duration=3000)
if(inactivity > duration) return inactivity
return 0
return 0
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
/client/proc/send_resources()
getFiles(
'html/search.js',
'html/panels.css',
'icons/pda_icons/pda_atmos.png',
'icons/pda_icons/pda_back.png',
'icons/pda_icons/pda_bell.png',
'icons/pda_icons/pda_blank.png',
'icons/pda_icons/pda_boom.png',
'icons/pda_icons/pda_bucket.png',
'icons/pda_icons/pda_crate.png',
'icons/pda_icons/pda_cuffs.png',
'icons/pda_icons/pda_eject.png',
'icons/pda_icons/pda_exit.png',
'icons/pda_icons/pda_flashlight.png',
'icons/pda_icons/pda_honk.png',
'icons/pda_icons/pda_mail.png',
'icons/pda_icons/pda_medical.png',
'icons/pda_icons/pda_menu.png',
'icons/pda_icons/pda_mule.png',
'icons/pda_icons/pda_notes.png',
'icons/pda_icons/pda_power.png',
'icons/pda_icons/pda_rdoor.png',
'icons/pda_icons/pda_reagent.png',
'icons/pda_icons/pda_refresh.png',
'icons/pda_icons/pda_scanner.png',
'icons/pda_icons/pda_signaler.png',
'icons/pda_icons/pda_status.png',
'icons/spideros_icons/sos_1.png',
'icons/spideros_icons/sos_2.png',
'icons/spideros_icons/sos_3.png',
'icons/spideros_icons/sos_4.png',
'icons/spideros_icons/sos_5.png',
'icons/spideros_icons/sos_6.png',
'icons/spideros_icons/sos_7.png',
'icons/spideros_icons/sos_8.png',
'icons/spideros_icons/sos_9.png',
'icons/spideros_icons/sos_10.png',
'icons/spideros_icons/sos_11.png',
'icons/spideros_icons/sos_12.png',
'icons/spideros_icons/sos_13.png',
'icons/spideros_icons/sos_14.png'
)
File diff suppressed because it is too large Load Diff
+211
View File
@@ -0,0 +1,211 @@
#define SAVEFILE_VERSION_MIN 8
#define SAVEFILE_VERSION_MAX 8
//handles converting savefiles to new formats
//MAKE SURE YOU KEEP THIS UP TO DATE!
//If the sanity checks are capable of handling any issues. Only increase SAVEFILE_VERSION_MAX,
//this will mean that savefile_version will still be over SAVEFILE_VERSION_MIN, meaning
//this savefile update doesn't run everytime we load from the savefile.
//This is mainly for format changes, such as the bitflags in toggles changing order or something.
//if a file can't be updated, return 0 to delete it and start again
//if a file was updated, return 1
/datum/preferences/proc/savefile_update()
if(savefile_version < 8) //lazily delete everything + additional files so they can be saved in the new format
for(var/ckey in preferences_datums)
var/datum/preferences/D = preferences_datums[ckey]
if(D == src)
var/delpath = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/"
if(delpath && fexists(delpath))
fdel(delpath)
break
return 0
if(savefile_version == SAVEFILE_VERSION_MAX) //update successful.
save_preferences()
save_character()
return 1
return 0
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey) return
path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]"
savefile_version = SAVEFILE_VERSION_MAX
/datum/preferences/proc/load_preferences()
if(!path) return 0
if(!fexists(path)) return 0
var/savefile/S = new /savefile(path)
if(!S) return 0
S.cd = "/"
S["version"] >> savefile_version
//Conversion
if(!savefile_version || !isnum(savefile_version) || savefile_version < SAVEFILE_VERSION_MIN || savefile_version > SAVEFILE_VERSION_MAX)
if(!savefile_update()) //handles updates
savefile_version = SAVEFILE_VERSION_MAX
save_preferences()
save_character()
return 0
//general preferences
S["ooccolor"] >> ooccolor
S["lastchangelog"] >> lastchangelog
S["UI_style"] >> UI_style
S["be_special"] >> be_special
S["default_slot"] >> default_slot
S["toggles"] >> toggles
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, list("Midnight","Orange","old"), initial(UI_style))
be_special = sanitize_integer(be_special, 0, 65535, initial(be_special))
default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
return 1
/datum/preferences/proc/save_preferences()
if(!path) return 0
var/savefile/S = new /savefile(path)
if(!S) return 0
S.cd = "/"
S["version"] << savefile_version
//general preferences
S["ooccolor"] << ooccolor
S["lastchangelog"] << lastchangelog
S["UI_style"] << UI_style
S["be_special"] << be_special
S["default_slot"] << default_slot
S["toggles"] << toggles
return 1
/datum/preferences/proc/load_character(slot)
if(!path) return 0
if(!fexists(path)) return 0
var/savefile/S = new /savefile(path)
if(!S) return 0
S.cd = "/"
if(!slot) slot = default_slot
slot = sanitize_integer(slot, 1, MAX_SAVE_SLOTS, initial(default_slot))
if(slot != default_slot)
default_slot = slot
S["default_slot"] << slot
S.cd = "/character[slot]"
//Character
S["OOC_Notes"] >> metadata
S["real_name"] >> real_name
S["name_is_always_random"] >> be_random_name
S["gender"] >> gender
S["age"] >> age
//colors to be consolidated into hex strings (requires some work with dna code)
S["hair_red"] >> r_hair
S["hair_green"] >> g_hair
S["hair_blue"] >> b_hair
S["facial_red"] >> r_facial
S["facial_green"] >> g_facial
S["facial_blue"] >> b_facial
S["skin_tone"] >> s_tone
S["hair_style_name"] >> h_style
S["facial_style_name"] >> f_style
S["eyes_red"] >> r_eyes
S["eyes_green"] >> g_eyes
S["eyes_blue"] >> b_eyes
S["underwear"] >> underwear
S["backbag"] >> backbag
//Jobs
S["userandomjob"] >> userandomjob
S["job_civilian_high"] >> job_civilian_high
S["job_civilian_med"] >> job_civilian_med
S["job_civilian_low"] >> job_civilian_low
S["job_medsci_high"] >> job_medsci_high
S["job_medsci_med"] >> job_medsci_med
S["job_medsci_low"] >> job_medsci_low
S["job_engsec_high"] >> job_engsec_high
S["job_engsec_med"] >> job_engsec_med
S["job_engsec_low"] >> job_engsec_low
//Sanitize
metadata = sanitize_text(metadata, initial(metadata))
real_name = reject_bad_name(real_name)
if(!real_name) real_name = random_name()
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
gender = sanitize_gender(gender)
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair))
g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair))
b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair))
r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial))
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
userandomjob = sanitize_integer(userandomjob, 0, 1, initial(userandomjob))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med))
job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low))
job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high))
job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med))
job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low))
job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high))
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
return 1
/datum/preferences/proc/save_character()
if(!path) return 0
var/savefile/S = new /savefile(path)
if(!S) return 0
S.cd = "/character[default_slot]"
//Character
S["OOC_Notes"] << metadata
S["real_name"] << real_name
S["name_is_always_random"] << be_random_name
S["gender"] << gender
S["age"] << age
S["hair_red"] << r_hair
S["hair_green"] << g_hair
S["hair_blue"] << b_hair
S["facial_red"] << r_facial
S["facial_green"] << g_facial
S["facial_blue"] << b_facial
S["skin_tone"] << s_tone
S["hair_style_name"] << h_style
S["facial_style_name"] << f_style
S["eyes_red"] << r_eyes
S["eyes_green"] << g_eyes
S["eyes_blue"] << b_eyes
S["underwear"] << underwear
S["backbag"] << backbag
//Jobs
S["userandomjob"] << userandomjob
S["job_civilian_high"] << job_civilian_high
S["job_civilian_med"] << job_civilian_med
S["job_civilian_low"] << job_civilian_low
S["job_medsci_high"] << job_medsci_high
S["job_medsci_med"] << job_medsci_med
S["job_medsci_low"] << job_medsci_low
S["job_engsec_high"] << job_engsec_high
S["job_engsec_med"] << job_engsec_med
S["job_engsec_low"] << job_engsec_low
return 1
#undef SAVEFILE_VERSION_MAX
#undef SAVEFILE_VERSION_MIN
+122
View File
@@ -0,0 +1,122 @@
//toggles
/client/verb/toggle_ghost_ears()
set name = "Show/Hide GhostEars"
set category = "Preferences"
set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs"
prefs.toggles ^= CHAT_GHOSTEARS
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"]."
prefs.save_preferences()
feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_sight()
set name = "Show/Hide GhostSight"
set category = "Preferences"
set desc = ".Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
prefs.toggles ^= CHAT_GHOSTSIGHT
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"]."
prefs.save_preferences()
feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_hear_radio()
set name = "Show/Hide RadioChatter"
set category = "Preferences"
set desc = "Toggle seeing radiochatter from nearby radios and speakers"
if(!holder) return
prefs.toggles ^= CHAT_RADIO
prefs.save_preferences()
usr << "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers"
feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleadminhelpsound()
set name = "Hear/Silence Adminhelps"
set category = "Preferences"
set desc = "Toggle hearing a notification when admin PMs are recieved"
if(!holder) return
prefs.toggles ^= SOUND_ADMINHELP
prefs.save_preferences()
usr << "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive."
feedback_add_details("admin_verb","AHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/deadchat()
set name = "Show/Hide Deadchat"
set category = "Preferences"
set desc ="Toggles seeing deadchat"
prefs.toggles ^= CHAT_DEAD
prefs.save_preferences()
src << "You will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat."
feedback_add_details("admin_verb","TDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleprayers()
set name = "Show/Hide Prayers"
set category = "Preferences"
set desc = "Toggles seeing prayers"
prefs.toggles ^= CHAT_PRAYER
prefs.save_preferences()
src << "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat."
feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggletitlemusic()
set name = "Hear/Silence LobbyMusic"
set category = "Preferences"
set desc = "Toggles hearing the GameLobby music"
prefs.toggles ^= SOUND_LOBBY
prefs.save_preferences()
if(prefs.toggles & SOUND_LOBBY)
src << "You will now hear music in the game lobby."
if(istype(mob, /mob/new_player))
playtitlemusic()
else
src << "You will no longer hear music in the game lobby."
if(istype(mob, /mob/new_player))
src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jamsz
feedback_add_details("admin_verb","TLobby") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglemidis()
set name = "Hear/Silence Midis"
set category = "Preferences"
set desc = "Toggles hearing sounds uploaded by admins"
prefs.toggles ^= SOUND_MIDI
prefs.save_preferences()
if(prefs.toggles & SOUND_MIDI)
src << "You will now hear any sounds uploaded by admins."
var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = 777)
break_sound.priority = 250
src << break_sound //breaks the client's sound output on channel 777
else
src << "You will no longer hear sounds uploaded by admins; any currently playing midis have been disabled."
feedback_add_details("admin_verb","TMidi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/listen_ooc()
set name = "Show/Hide OOC"
set category = "Preferences"
set desc = "Toggles seeing OutOfCharacter chat"
prefs.toggles ^= CHAT_OOC
prefs.save_preferences()
src << "You will [(prefs.toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel."
feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful
set name = "Hear/Silence Ambience"
set category = "Preferences"
set desc = "Toggles hearing ambient sound effects"
prefs.toggles ^= SOUND_AMBIENCE
prefs.save_preferences()
if(prefs.toggles & SOUND_AMBIENCE)
src << "You will now hear ambient sounds."
else
src << "You will no longer hear ambient sounds."
src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)
src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
feedback_add_details("admin_verb","TAmbi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//be special
/client/verb/toggle_be_special(role in be_special_flags)
set name = "Toggle SpecialRole Candidacy"
set category = "Preferences"
set desc = "Toggles which special roles you would like to be a candidate for, during events."
var/role_flag = be_special_flags[role]
if(!role_flag) return
prefs.be_special ^= role_flag
prefs.save_preferences()
src << "You will [(prefs.be_special & role_flag) ? "now" : "no longer"] be considered for [role] events (where possible)."
feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!