diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm
new file mode 100644
index 0000000000..f2674a631d
--- /dev/null
+++ b/code/datums/verbs.dm
@@ -0,0 +1,101 @@
+/datum/verbs
+ var/name
+ var/list/children
+ var/datum/verbs/parent
+ var/list/verblist
+ var/abstract = FALSE
+
+//returns the master list for verbs of a type
+/datum/verbs/proc/GetList()
+ CRASH("Abstract verblist for [type]")
+
+//modify outlist for each entry in Generate_list
+/datum/verbs/proc/HandleVerb(list/outlist, atom/verb/verbpath, ...)
+
+/datum/verbs/New()
+ var/mainlist = GetList()
+ var/ourentry = mainlist[type]
+ children = list()
+ verblist = list()
+ if (ourentry)
+ if (!islist(ourentry)) //some of our childern already loaded
+ qdel(src)
+ CRASH("Verb double load: [type]")
+ Add_children(ourentry)
+
+ mainlist[type] = src
+
+ Load_verbs(type, typesof("[type]/verb"))
+
+ var/datum/verbs/parent = mainlist[parent_type]
+ if (!parent)
+ mainlist[parent_type] = list(src)
+ else if (islist(parent))
+ parent += src
+ else
+ parent.Add_children(list(src))
+
+/datum/verbs/proc/Set_parent(datum/verbs/_parent)
+ parent = _parent
+ if (abstract)
+ parent.Add_children(children)
+ var/list/verblistoftypes = list()
+ for(var/thing in verblist)
+ LAZYADD(verblistoftypes[verblist[thing]], thing)
+
+ for(var/verbparenttype in verblistoftypes)
+ parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
+
+/datum/verbs/proc/Add_children(list/kids)
+ if (abstract && parent)
+ parent.Add_children(kids)
+ return
+
+ for(var/thing in kids)
+ var/datum/verbs/item = thing
+ item.Set_parent(src)
+ if (!item.abstract)
+ children += item
+
+/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs)
+ if (abstract && parent)
+ parent.Load_verbs(verb_parent_type, verbs)
+ return
+
+ for (var/verbpath in verbs)
+ verblist[verbpath] = verb_parent_type
+
+/datum/verbs/proc/Generate_list(...)
+ . = list()
+ if (length(children))
+ for (var/thing in children)
+ var/datum/verbs/child = thing
+ var/list/childlist = child.Generate_list(arglist(args))
+ if (childlist)
+ var/childname = "[child]"
+ if (childname == "[child.type]")
+ var/list/tree = splittext(childname, "/")
+ childname = tree[tree.len]
+ .[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
+ . += childlist
+
+ for (var/thing in verblist)
+ var/atom/verb/verbpath = thing
+ if (!verbpath)
+ stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
+ var/list/entry = list()
+ entry["parent"] = "[type]"
+ entry["name"] = verbpath.desc
+ if (copytext(verbpath.name,1,2) == "@")
+ entry["command"] = copytext(verbpath.name,2)
+ else
+ entry["command"] = replacetext(verbpath.name, " ", "-")
+
+ HandleVerb(arglist(list(entry, verbpath) + args))
+ .[verbpath] = entry
+
+/world/proc/LoadVerbs(verb_type)
+ if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs)
+ CRASH("Invalid verb_type: [verb_type]")
+ for (var/typepath in subtypesof(verb_type))
+ new typepath()
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index b08f0542a0..9a7376c9eb 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -182,7 +182,10 @@
/obj/proc/check_uplink_validity()
return 1
-/obj/proc/on_mob_move(dir, mob)
+/obj/proc/on_mob_move(dir, mob, oldLoc)
+ return
+
+/obj/proc/on_mob_turn(dir, mob)
return
/obj/vv_get_dropdown()
diff --git a/code/modules/admin/adminmenu.dm b/code/modules/admin/adminmenu.dm
index 8954244da4..aa654ab252 100644
--- a/code/modules/admin/adminmenu.dm
+++ b/code/modules/admin/adminmenu.dm
@@ -1,8 +1,8 @@
-/datum/menu/Admin/Generate_list(client/C)
+/datum/verbs/menu/Admin/Generate_list(client/C)
if (C.holder)
. = ..()
-/datum/menu/Admin/verb/playerpanel()
+/datum/verbs/menu/Admin/verb/playerpanel()
set name = "Player Panel"
set desc = "Player Panel"
set category = "Admin"
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index fc21e9e0d2..5fad078e19 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -353,9 +353,9 @@ GLOBAL_LIST(external_rsc_urls)
hook_vr("client_new",list(src))
- var/list/topmenus = GLOB.menulist[/datum/menu]
+ var/list/topmenus = GLOB.menulist[/datum/verbs/menu]
for (var/thing in topmenus)
- var/datum/menu/topmenu = thing
+ var/datum/verbs/menu/topmenu = thing
var/topmenuname = "[topmenu]"
if (topmenuname == "[topmenu.type]")
var/list/tree = splittext(topmenuname, "/")
@@ -364,13 +364,13 @@ GLOBAL_LIST(external_rsc_urls)
var/list/entries = topmenu.Generate_list(src)
for (var/child in entries)
winset(src, "[url_encode(child)]", "[entries[child]]")
- if (!ispath(child, /datum/menu))
+ if (!ispath(child, /datum/verbs/menu))
var/atom/verb/verbpath = child
if (copytext(verbpath.name,1,2) != "@")
new child(src)
for (var/thing in prefs.menuoptions)
- var/datum/menu/menuitem = GLOB.menulist[thing]
+ var/datum/verbs/menu/menuitem = GLOB.menulist[thing]
if (menuitem)
menuitem.Load_checked(src)
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index eb244937e6..943999aecc 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -1,29 +1,29 @@
//this works as is to create a single checked item, but has no back end code for toggleing the check yet
#define TOGGLE_CHECKBOX(PARENT, CHILD) PARENT/CHILD/abstract = TRUE;PARENT/CHILD/checkbox = CHECKBOX_TOGGLE;PARENT/CHILD/verb/CHILD
-
-//Example usage TOGGLE_CHECKBOX(datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
-
+
+//Example usage TOGGLE_CHECKBOX(datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
+
//override because we don't want to save preferences twice.
-/datum/menu/Settings/Set_checked(client/C, verbpath)
+/datum/verbs/menu/Settings/Set_checked(client/C, verbpath)
if (checkbox == CHECKBOX_GROUP)
C.prefs.menuoptions[type] = verbpath
else if (checkbox == CHECKBOX_TOGGLE)
var/checked = Get_checked(C)
C.prefs.menuoptions[type] = !checked
winset(C, "[verbpath]", "is-checked = [!checked]")
-
-/datum/menu/Settings/verb/setup_character()
+
+/datum/verbs/menu/Settings/verb/setup_character()
set name = "Game Preferences"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Open Game Preferences Window"
usr.client.prefs.current_tab = 1
usr.client.prefs.ShowChoices(usr)
//toggles
-/datum/menu/Settings/Ghost/chatterbox
+/datum/verbs/menu/Settings/Ghost/chatterbox
name = "Chat Box Spam"
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
set name = "Show/Hide GhostEars"
set category = "Preferences"
set desc = "See All Speech"
@@ -31,10 +31,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTEARS
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
set name = "Show/Hide GhostSight"
set category = "Preferences"
set desc = "See All Emotes"
@@ -42,10 +42,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTSIGHT
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
set name = "Show/Hide GhostWhispers"
set category = "Preferences"
set desc = "See All Whispers"
@@ -53,10 +53,10 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTWHISPER
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
set name = "Show/Hide GhostRadio"
set category = "Preferences"
set desc = "See All Radio Chatter"
@@ -64,60 +64,60 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)()
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTRADIO
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
- set name = "Show/Hide GhostPDA"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
+ set name = "Show/Hide GhostPDA"
set category = "Preferences"
set desc = "See All PDA Messages"
usr.client.prefs.chat_toggles ^= CHAT_GHOSTPDA
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTPDA
-/datum/menu/Settings/Ghost/chatterbox/Events
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events
name = "Events"
-
-//please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)()
- set name = "Toggle Deathrattle"
+
+//please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)()
+ set name = "Toggle Deathrattle"
set category = "Preferences"
set desc = "Death"
usr.client.prefs.toggles ^= DISABLE_DEATHRATTLE
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.")
SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments.
-/datum/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_DEATHRATTLE)
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)()
- set name = "Toggle Arrivalrattle"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)()
+ set name = "Toggle Arrivalrattle"
set category = "Preferences"
set desc = "New Player Arrival"
usr.client.prefs.toggles ^= DISABLE_ARRIVALRATTLE
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
-/datum/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_ARRIVALRATTLE)
-TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost, togglemidroundantag)()
- set name = "Toggle Midround Antagonist"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost, togglemidroundantag)()
+ set name = "Toggle Midround Antagonist"
set category = "Preferences"
set desc = "Midround Antagonist"
usr.client.prefs.toggles ^= MIDROUND_ANTAG
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.")
SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[usr.client.prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
+/datum/verbs/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
return C.prefs.toggles & MIDROUND_ANTAG
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)()
- set name = "Hear/Silence LobbyMusic"
- set category = "Preferences"
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggletitlemusic)()
+ set name = "Hear/Silence LobbyMusic"
+ set category = "Preferences"
set desc = "Hear Music In Lobby"
usr.client.prefs.toggles ^= SOUND_LOBBY
usr.client.prefs.save_preferences()
@@ -125,33 +125,33 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)()
to_chat(usr, "You will now hear music in the game lobby.")
if(isnewplayer(usr))
usr.client.playtitlemusic()
- else
+ else
to_chat(usr, "You will no longer hear music in the game lobby.")
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[usr.client.prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
return C.prefs.toggles & SOUND_LOBBY
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, togglemidis)()
- set name = "Hear/Silence Midis"
- set category = "Preferences"
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglemidis)()
+ set name = "Hear/Silence Midis"
+ set category = "Preferences"
set desc = "Hear Admin Triggered Sounds (Midis)"
usr.client.prefs.toggles ^= SOUND_MIDI
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_MIDI)
to_chat(usr, "You will now hear any sounds uploaded by admins.")
- else
+ else
to_chat(usr, "You will no longer hear sounds uploaded by admins")
usr.stop_sound_channel(CHANNEL_ADMIN)
SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[usr.client.prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/togglemidis/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/togglemidis/Get_checked(client/C)
return C.prefs.toggles & SOUND_MIDI
-
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)()
+
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_instruments)()
set name = "Hear/Silence Instruments"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear In-game Instruments"
usr.client.prefs.toggles ^= SOUND_INSTRUMENTS
usr.client.prefs.save_preferences()
@@ -160,57 +160,57 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)()
else
to_chat(usr, "You will no longer hear musical instruments.")
SSblackbox.add_details("preferences_verb","Toggle Instruments|[usr.client.prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
return C.prefs.toggles & SOUND_INSTRUMENTS
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, Toggle_Soundscape)()
- set name = "Hear/Silence Ambience"
- set category = "Preferences"
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, Toggle_Soundscape)()
+ set name = "Hear/Silence Ambience"
+ set category = "Preferences"
set desc = "Hear Ambient Sound Effects"
usr.client.prefs.toggles ^= SOUND_AMBIENCE
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_AMBIENCE)
to_chat(usr, "You will now hear ambient sounds.")
- else
+ else
to_chat(usr, "You will no longer hear ambient sounds.")
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
SSblackbox.add_details("preferences_verb","Toggle Ambience|[usr.client.prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
return C.prefs.toggles & SOUND_AMBIENCE
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_ship_ambience)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_ship_ambience)()
set name = "Hear/Silence Ship Ambience"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear Ship Ambience Roar"
usr.client.prefs.toggles ^= SOUND_SHIP_AMBIENCE
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE)
to_chat(usr, "You will now hear ship ambience.")
- else
+ else
to_chat(usr, "You will no longer hear ship ambience.")
usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)
usr.client.ambience_playing = 0
SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
-/datum/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
return C.prefs.toggles & SOUND_SHIP_AMBIENCE
-
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_announcement_sound)()
+
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_announcement_sound)()
set name = "Hear/Silence Announcements"
- set category = "Preferences"
+ set category = "Preferences"
set desc = "Hear Announcement Sound"
usr.client.prefs.toggles ^= SOUND_ANNOUNCEMENTS
to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].")
usr.client.prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
return C.prefs.toggles & SOUND_ANNOUNCEMENTS
-TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
set name = "Hear/Silence Prayer Sounds"
set category = "Preferences"
set desc = "Hear Prayer Sounds"
@@ -218,14 +218,14 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
usr.client.prefs.save_preferences()
if(usr.client.prefs.toggles & SOUND_PRAYERS)
to_chat(usr, "You will now hear prayer sounds.")
- else
+ else
to_chat(usr, "You will no longer prayer sounds.")
SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[usr.client.prefs.toggles & SOUND_PRAYERS]")
-/datum/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
+/datum/verbs/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
return C.prefs.toggles & SOUND_PRAYERS
-/datum/menu/Settings/Sound/verb/stop_client_sounds()
+/datum/verbs/menu/Settings/Sound/verb/stop_client_sounds()
set name = "Stop Sounds"
set category = "Preferences"
set desc = "Stop Current Sounds"
@@ -233,7 +233,7 @@ TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)()
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)()
+TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)()
set name = "Show/Hide OOC"
set category = "Preferences"
set desc = "Show OOC Chat"
@@ -241,171 +241,171 @@ TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)()
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[usr.client.prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/datum/menu/Settings/listen_ooc/Get_checked(client/C)
+/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_OOC
-
-GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
- "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
- "ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \
- "ghost_dcyan","ghost_grey","ghost_dyellow","ghost_dpink", "ghost_purpleswirl","ghost_funkypurp","ghost_pinksherbert","ghost_blazeit",\
- "ghost_mellow","ghost_rainbow","ghost_camo","ghost_fire", "catghost"))
-/client/proc/pick_form()
- if(!is_content_unlocked())
- alert("This setting is for accounts with BYOND premium only.")
- return
- var/new_form = input(src, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_forms
- if(new_form)
- prefs.ghost_form = new_form
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_icon(new_form)
-
-GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON))
-
-/client/proc/pick_ghost_orbit()
- if(!is_content_unlocked())
- alert("This setting is for accounts with BYOND premium only.")
- return
- var/new_orbit = input(src, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_orbits
- if(new_orbit)
- prefs.ghost_orbit = new_orbit
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.ghost_orbit = new_orbit
-
-/client/proc/pick_ghost_accs()
- var/new_ghost_accs = alert("Do you want your ghost to show full accessories where possible, hide accessories but still use the directional sprites where possible, or also ignore the directions and stick to the default sprites?",,"full accessories", "only directional sprites", "default sprites")
- if(new_ghost_accs)
- switch(new_ghost_accs)
- if("full accessories")
- prefs.ghost_accs = GHOST_ACCS_FULL
- if("only directional sprites")
- prefs.ghost_accs = GHOST_ACCS_DIR
- if("default sprites")
- prefs.ghost_accs = GHOST_ACCS_NONE
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_icon()
-
-/client/verb/pick_ghost_customization()
- set name = "Ghost Customization"
- set category = "Preferences"
- set desc = "Customize your ghastly appearance."
- if(is_content_unlocked())
- switch(alert("Which setting do you want to change?",,"Ghost Form","Ghost Orbit","Ghost Accessories"))
- if("Ghost Form")
- pick_form()
- if("Ghost Orbit")
- pick_ghost_orbit()
- if("Ghost Accessories")
- pick_ghost_accs()
- else
- pick_ghost_accs()
-
-/client/verb/pick_ghost_others()
- set name = "Ghosts of Others"
- set category = "Preferences"
- set desc = "Change display settings for the ghosts of other players."
- var/new_ghost_others = alert("Do you want the ghosts of others to show up as their own setting, as their default sprites or always as the default white ghost?",,"Their Setting", "Default Sprites", "White Ghost")
- if(new_ghost_others)
- switch(new_ghost_others)
- if("Their Setting")
- prefs.ghost_others = GHOST_OTHERS_THEIR_SETTING
- if("Default Sprites")
- prefs.ghost_others = GHOST_OTHERS_DEFAULT_SPRITE
- if("White Ghost")
- prefs.ghost_others = GHOST_OTHERS_SIMPLE
- prefs.save_preferences()
- if(isobserver(mob))
- var/mob/dead/observer/O = mob
- O.update_sight()
-
-/client/verb/toggle_intent_style()
- set name = "Toggle Intent Selection Style"
- set category = "Preferences"
- set desc = "Toggle between directly clicking the desired intent or clicking to rotate through."
- prefs.toggles ^= INTENT_STYLE
- to_chat(src, "[(prefs.toggles & INTENT_STYLE) ? "Clicking directly on intents selects them." : "Clicking on intents rotates selection clockwise."]")
- prefs.save_preferences()
+
+GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
+ "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
+ "ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \
+ "ghost_dcyan","ghost_grey","ghost_dyellow","ghost_dpink", "ghost_purpleswirl","ghost_funkypurp","ghost_pinksherbert","ghost_blazeit",\
+ "ghost_mellow","ghost_rainbow","ghost_camo","ghost_fire", "catghost"))
+/client/proc/pick_form()
+ if(!is_content_unlocked())
+ alert("This setting is for accounts with BYOND premium only.")
+ return
+ var/new_form = input(src, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_forms
+ if(new_form)
+ prefs.ghost_form = new_form
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_icon(new_form)
+
+GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON))
+
+/client/proc/pick_ghost_orbit()
+ if(!is_content_unlocked())
+ alert("This setting is for accounts with BYOND premium only.")
+ return
+ var/new_orbit = input(src, "Thanks for supporting BYOND - Choose your ghostly orbit:","Thanks for supporting BYOND",null) as null|anything in GLOB.ghost_orbits
+ if(new_orbit)
+ prefs.ghost_orbit = new_orbit
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.ghost_orbit = new_orbit
+
+/client/proc/pick_ghost_accs()
+ var/new_ghost_accs = alert("Do you want your ghost to show full accessories where possible, hide accessories but still use the directional sprites where possible, or also ignore the directions and stick to the default sprites?",,"full accessories", "only directional sprites", "default sprites")
+ if(new_ghost_accs)
+ switch(new_ghost_accs)
+ if("full accessories")
+ prefs.ghost_accs = GHOST_ACCS_FULL
+ if("only directional sprites")
+ prefs.ghost_accs = GHOST_ACCS_DIR
+ if("default sprites")
+ prefs.ghost_accs = GHOST_ACCS_NONE
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_icon()
+
+/client/verb/pick_ghost_customization()
+ set name = "Ghost Customization"
+ set category = "Preferences"
+ set desc = "Customize your ghastly appearance."
+ if(is_content_unlocked())
+ switch(alert("Which setting do you want to change?",,"Ghost Form","Ghost Orbit","Ghost Accessories"))
+ if("Ghost Form")
+ pick_form()
+ if("Ghost Orbit")
+ pick_ghost_orbit()
+ if("Ghost Accessories")
+ pick_ghost_accs()
+ else
+ pick_ghost_accs()
+
+/client/verb/pick_ghost_others()
+ set name = "Ghosts of Others"
+ set category = "Preferences"
+ set desc = "Change display settings for the ghosts of other players."
+ var/new_ghost_others = alert("Do you want the ghosts of others to show up as their own setting, as their default sprites or always as the default white ghost?",,"Their Setting", "Default Sprites", "White Ghost")
+ if(new_ghost_others)
+ switch(new_ghost_others)
+ if("Their Setting")
+ prefs.ghost_others = GHOST_OTHERS_THEIR_SETTING
+ if("Default Sprites")
+ prefs.ghost_others = GHOST_OTHERS_DEFAULT_SPRITE
+ if("White Ghost")
+ prefs.ghost_others = GHOST_OTHERS_SIMPLE
+ prefs.save_preferences()
+ if(isobserver(mob))
+ var/mob/dead/observer/O = mob
+ O.update_sight()
+
+/client/verb/toggle_intent_style()
+ set name = "Toggle Intent Selection Style"
+ set category = "Preferences"
+ set desc = "Toggle between directly clicking the desired intent or clicking to rotate through."
+ prefs.toggles ^= INTENT_STYLE
+ to_chat(src, "[(prefs.toggles & INTENT_STYLE) ? "Clicking directly on intents selects them." : "Clicking on intents rotates selection clockwise."]")
+ prefs.save_preferences()
SSblackbox.add_details("preferences_verb","Toggle Intent Selection|[prefs.toggles & INTENT_STYLE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/verb/toggle_ghost_hud_pref()
- set name = "Toggle Ghost HUD"
- set category = "Preferences"
- set desc = "Hide/Show Ghost HUD"
-
- prefs.ghost_hud = !prefs.ghost_hud
- to_chat(src, "Ghost HUD will now be [prefs.ghost_hud ? "visible" : "hidden"].")
- prefs.save_preferences()
- if(isobserver(mob))
- mob.hud_used.show_hud()
+
+/client/verb/toggle_ghost_hud_pref()
+ set name = "Toggle Ghost HUD"
+ set category = "Preferences"
+ set desc = "Hide/Show Ghost HUD"
+
+ prefs.ghost_hud = !prefs.ghost_hud
+ to_chat(src, "Ghost HUD will now be [prefs.ghost_hud ? "visible" : "hidden"].")
+ prefs.save_preferences()
+ if(isobserver(mob))
+ mob.hud_used.show_hud()
SSblackbox.add_details("preferences_verb","Toggle Ghost HUD|[prefs.ghost_hud]")
-
-/client/verb/toggle_inquisition() // warning: unexpected inquisition
- set name = "Toggle Inquisitiveness"
- set desc = "Sets whether your ghost examines everything on click by default"
- set category = "Preferences"
-
- prefs.inquisitive_ghost = !prefs.inquisitive_ghost
- prefs.save_preferences()
- if(prefs.inquisitive_ghost)
- to_chat(src, "You will now examine everything you click on.")
- else
- to_chat(src, "You will no longer examine things you click on.")
+
+/client/verb/toggle_inquisition() // warning: unexpected inquisition
+ set name = "Toggle Inquisitiveness"
+ set desc = "Sets whether your ghost examines everything on click by default"
+ set category = "Preferences"
+
+ prefs.inquisitive_ghost = !prefs.inquisitive_ghost
+ prefs.save_preferences()
+ if(prefs.inquisitive_ghost)
+ to_chat(src, "You will now examine everything you click on.")
+ else
+ to_chat(src, "You will no longer examine things you click on.")
SSblackbox.add_details("preferences_verb","Toggle Ghost Inquisitiveness|[prefs.inquisitive_ghost]")
-
-//Admin Preferences
-/client/proc/toggleadminhelpsound()
- set name = "Hear/Silence Adminhelps"
- set category = "Preferences"
- set desc = "Toggle hearing a notification when admin PMs are received"
- if(!holder)
- return
- prefs.toggles ^= SOUND_ADMINHELP
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
+
+//Admin Preferences
+/client/proc/toggleadminhelpsound()
+ set name = "Hear/Silence Adminhelps"
+ set category = "Preferences"
+ set desc = "Toggle hearing a notification when admin PMs are received"
+ if(!holder)
+ return
+ prefs.toggles ^= SOUND_ADMINHELP
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
SSblackbox.add_details("admin_toggle","Toggle Adminhelp Sound|[prefs.toggles & SOUND_ADMINHELP]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-/client/proc/toggleannouncelogin()
- set name = "Do/Don't Announce Login"
- set category = "Preferences"
- set desc = "Toggle if you want an announcement to admins when you login during a round"
- if(!holder)
- return
- prefs.toggles ^= ANNOUNCE_LOGIN
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login.")
+
+/client/proc/toggleannouncelogin()
+ set name = "Do/Don't Announce Login"
+ set category = "Preferences"
+ set desc = "Toggle if you want an announcement to admins when you login during a round"
+ if(!holder)
+ return
+ prefs.toggles ^= ANNOUNCE_LOGIN
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login.")
SSblackbox.add_details("admin_toggle","Toggle Login Announcement|[prefs.toggles & ANNOUNCE_LOGIN]") //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 Radio Chatter"
- set category = "Preferences"
- set desc = "Toggle seeing radiochatter from nearby radios and speakers"
- if(!holder) return
- prefs.chat_toggles ^= CHAT_RADIO
- prefs.save_preferences()
- to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
+
+/client/proc/toggle_hear_radio()
+ set name = "Show/Hide Radio Chatter"
+ set category = "Preferences"
+ set desc = "Toggle seeing radiochatter from nearby radios and speakers"
+ if(!holder) return
+ prefs.chat_toggles ^= CHAT_RADIO
+ prefs.save_preferences()
+ to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
SSblackbox.add_details("admin_toggle","Toggle Radio Chatter|[prefs.chat_toggles & CHAT_RADIO]") //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.chat_toggles ^= CHAT_DEAD
- prefs.save_preferences()
- to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
+
+/client/proc/deadchat()
+ set name = "Show/Hide Deadchat"
+ set category = "Preferences"
+ set desc ="Toggles seeing deadchat"
+ prefs.chat_toggles ^= CHAT_DEAD
+ prefs.save_preferences()
+ to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
SSblackbox.add_details("admin_toggle","Toggle Deadchat Visibility|[prefs.chat_toggles & CHAT_DEAD]") //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.chat_toggles ^= CHAT_PRAYER
- prefs.save_preferences()
- to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
+
+/client/proc/toggleprayers()
+ set name = "Show/Hide Prayers"
+ set category = "Preferences"
+ set desc = "Toggles seeing prayers"
+ prefs.chat_toggles ^= CHAT_PRAYER
+ prefs.save_preferences()
+ to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
SSblackbox.add_details("admin_toggle","Toggle Prayer Visibility|[prefs.chat_toggles & CHAT_PRAYER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
+
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 5b1f43d58c..374ff4bd22 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -57,3 +57,13 @@
nutrition -= HUNGER_FACTOR/10
if((disabilities & FAT) && m_intent == MOVE_INTENT_RUN && bodytemperature <= 360)
bodytemperature += 2
+
+/mob/living/carbon/Moved(oldLoc, Dir)
+ . = ..()
+ for(var/obj/O in internal_organs)
+ O.on_mob_move(dir, src, oldLoc)
+
+/mob/living/carbon/setDir(newdir)
+ . = ..()
+ for(var/obj/O in internal_organs)
+ O.on_mob_turn(newdir, src)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 43d8a924a1..9d6ab8410c 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -178,11 +178,18 @@
if(mob.throwing)
mob.throwing.finalize(FALSE)
- for(var/obj/O in mob)
- O.on_mob_move(direct, src)
-
return .
+/mob/Moved(oldLoc, dir)
+ . = ..()
+ for(var/obj/O in contents)
+ O.on_mob_move(dir, src, oldLoc)
+
+/mob/setDir(newDir)
+ . = ..()
+ for(var/obj/O in contents)
+ O.on_mob_turn(newDir, src)
+
///Process_Grab()
///Called by client/Move()
@@ -209,10 +216,10 @@
return
var/mob/living/L = mob
switch(L.incorporeal_move)
- if(INCORPOREAL_MOVE_BASIC)
+ if(INCORPOREAL_MOVE_BASIC)
L.loc = get_step(L, direct)
L.setDir(direct)
- if(INCORPOREAL_MOVE_SHADOW)
+ if(INCORPOREAL_MOVE_SHADOW)
if(prob(50))
var/locx
var/locy
@@ -242,15 +249,15 @@
L.loc = locate(locx,locy,mobloc.z)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
- new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
+ new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
limit--
if(limit<=0)
break
else
- new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
+ new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
L.loc = get_step(L, direct)
L.setDir(direct)
- if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
+ if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
var/turf/open/floor/stepTurf = get_step(L, direct)
for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
to_chat(L, "[S] bars your passage!")
@@ -295,12 +302,12 @@
return A
else
var/atom/movable/AM = A
- if(AM == buckled)
+ if(AM == buckled)
continue
- if(ismob(AM))
- var/mob/M = AM
- if(M.buckled)
- continue
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.buckled)
+ continue
if(!AM.CanPass(src) || AM.density)
if(AM.anchored)
return AM
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index f72458af4e..687e3396bd 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -190,6 +190,18 @@
build_path = /obj/item/organ/eyes/robotic/shield
category = list("Misc", "Medical Designs")
+/datum/design/cyberimp_gloweyes
+ name = "Luminescent Eyes"
+ desc = "A pair of cybernetic eyes that can emit multicolored light"
+ id = "ci-gloweyes"
+ req_tech = list("materials" = 3, "biotech" = 3, "engineering" = 4)
+ build_type = PROTOLATHE | MECHFAB
+ construction_time = 40
+ materials = list(MAT_METAL = 600, MAT_GLASS = 1000)
+ build_path = /obj/item/organ/eyes/robotic/glow
+ category = list("Misc", "Medical Designs")
+
+
/datum/design/cyberimp_breather
name = "Breathing Tube Implant"
desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked."
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 83b70d33d9..f91ef8f547 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -132,3 +132,176 @@
/obj/item/organ/eyes/robotic/shield/emp_act(severity)
return
+
+#define RGB2EYECOLORSTRING(definitionvar) ("[copytext(definitionvar,2,3)][copytext(definitionvar,4,5)][copytext(definitionvar,6,7)]")
+
+/obj/item/organ/eyes/robotic/glow
+ name = "High Luminosity Eyes"
+ desc = "Special glowing eyes, used by snowflakes who want to be special."
+ origin_tech = "material=3;biotech=3;engineering=3;magnets=4"
+ eye_color = "000"
+ actions_types = list(/datum/action/item_action/organ_action/use, /datum/action/item_action/organ_action/toggle)
+ var/current_color_string = "#ffffff"
+ var/active = FALSE
+ var/max_light_beam_distance = 5
+ var/light_beam_distance = 5
+ var/light_object_range = 1
+ var/light_object_power = 2
+ var/list/obj/effect/abstract/eye_lighting/eye_lighting
+ var/obj/effect/abstract/eye_lighting/on_mob
+ var/image/mob_overlay
+
+/obj/item/organ/eyes/robotic/glow/Initialize()
+ . = ..()
+ mob_overlay = image('icons/mob/human_face.dmi', "eyes_glow_gs")
+
+/obj/item/organ/eyes/robotic/glow/Destroy()
+ terminate_effects()
+ . = ..()
+
+/obj/item/organ/eyes/robotic/glow/Remove()
+ terminate_effects()
+ . = ..()
+
+/obj/item/organ/eyes/robotic/glow/proc/terminate_effects()
+ if(owner && active)
+ deactivate()
+ active = FALSE
+ clear_visuals(TRUE)
+ STOP_PROCESSING(SSfastprocess, src)
+
+/obj/item/organ/eyes/robotic/glow/ui_action_click(owner, action)
+ if(istype(action, /datum/action/item_action/organ_action/toggle))
+ toggle_active()
+ else if(istype(action, /datum/action/item_action/organ_action/use))
+ prompt_for_controls(owner)
+
+/obj/item/organ/eyes/robotic/glow/proc/toggle_active()
+ if(active)
+ deactivate()
+ else
+ activate()
+
+/obj/item/organ/eyes/robotic/glow/proc/prompt_for_controls(mob/user)
+ var/C = input(owner, "Select Color", "Select color", "#ffffff") as null|color
+ if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user)
+ return
+ var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
+
+ set_distance(Clamp(range, 0, max_light_beam_distance))
+ assume_rgb(C)
+
+/obj/item/organ/eyes/robotic/glow/proc/assume_rgb(newcolor)
+ current_color_string = newcolor
+ eye_color = RGB2EYECOLORSTRING(current_color_string)
+ sync_light_effects()
+ cycle_mob_overlay()
+ if(!QDELETED(owner) && ishuman(owner)) //Other carbon mobs don't have eye color.
+ owner.dna.species.handle_body(owner)
+
+/obj/item/organ/eyes/robotic/glow/proc/cycle_mob_overlay()
+ remove_mob_overlay()
+ mob_overlay.color = current_color_string
+ add_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/add_mob_overlay()
+ if(!QDELETED(owner))
+ owner.add_overlay(mob_overlay)
+
+/obj/item/organ/eyes/robotic/glow/proc/remove_mob_overlay()
+ if(!QDELETED(owner))
+ owner.cut_overlay(mob_overlay)
+
+/obj/item/organ/eyes/robotic/glow/emp_act()
+ if(active)
+ deactivate(silent = TRUE)
+
+/obj/item/organ/eyes/robotic/glow/on_mob_move()
+ if(QDELETED(owner) || !active)
+ return
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/on_mob_turn()
+ if(QDELETED(owner) || !active)
+ return
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/proc/activate(silent = FALSE)
+ start_visuals()
+ if(!silent)
+ to_chat(owner, "Your [src] clicks and makes a whining noise, before shooting out a beam of light!")
+ active = TRUE
+ cycle_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/deactivate(silent = FALSE)
+ clear_visuals()
+ if(!silent)
+ to_chat(owner, "Your [src] shuts off!")
+ active = FALSE
+ remove_mob_overlay()
+
+/obj/item/organ/eyes/robotic/glow/proc/update_visuals()
+ if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob)
+ regenerate_light_effects()
+ var/turf/scanfrom = get_turf(owner)
+ var/scandir = owner.dir
+ if(!istype(scanfrom))
+ clear_visuals()
+ var/turf/scanning = scanfrom
+ var/stop = FALSE
+ on_mob.forceMove(scanning)
+ for(var/i in 1 to light_beam_distance)
+ scanning = get_step(scanning, scandir)
+ if(scanning.opacity || scanning.has_opaque_atom)
+ stop = TRUE
+ var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i)
+ if(stop)
+ L.forceMove(src)
+ else
+ L.forceMove(scanning)
+
+/obj/item/organ/eyes/robotic/glow/proc/clear_visuals(delete_everything = FALSE)
+ if(delete_everything)
+ QDEL_LIST(eye_lighting)
+ QDEL_NULL(on_mob)
+ else
+ for(var/i in eye_lighting)
+ var/obj/effect/abstract/eye_lighting/L = i
+ L.forceMove(src)
+ if(!QDELETED(on_mob))
+ on_mob.forceMove(src)
+
+/obj/item/organ/eyes/robotic/glow/proc/start_visuals()
+ if(!islist(eye_lighting))
+ regenerate_light_effects()
+ if((eye_lighting.len < light_beam_distance) || !on_mob)
+ regenerate_light_effects()
+ sync_light_effects()
+ update_visuals()
+
+/obj/item/organ/eyes/robotic/glow/proc/set_distance(dist)
+ light_beam_distance = dist
+ regenerate_light_effects()
+
+/obj/item/organ/eyes/robotic/glow/proc/regenerate_light_effects()
+ clear_visuals(TRUE)
+ on_mob = new(src)
+ for(var/i in 1 to light_beam_distance)
+ LAZYADD(eye_lighting,new /obj/effect/abstract/eye_lighting(src))
+ sync_light_effects()
+
+/obj/item/organ/eyes/robotic/glow/proc/sync_light_effects()
+ for(var/I in eye_lighting)
+ var/obj/effect/abstract/eye_lighting/L = I
+ L.set_light(light_object_range, light_object_power, current_color_string)
+ if(on_mob)
+ on_mob.set_light(1, 1, current_color_string)
+
+/obj/effect/abstract/eye_lighting
+ var/obj/item/organ/eyes/robotic/glow/parent
+
+/obj/effect/abstract/eye_lighting/Initialize()
+ . = ..()
+ parent = loc
+ if(!istype(parent))
+ return INITIALIZE_HINT_QDEL
diff --git a/code/world.dm b/code/world.dm
index b7beb52d4d..4800975f6b 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -34,7 +34,7 @@
load_motd()
load_admins()
// load_mentors()
- load_menu()
+ LoadVerbs(/datum/verbs/menu)
if(config.usewhitelist)
load_whitelist()
LoadBans()
diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi
index e1dbb99158..1d8098c92b 100644
Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ
diff --git a/interface/menu.dm b/interface/menu.dm
index 4bebd5b202..a2220d529f 100644
--- a/interface/menu.dm
+++ b/interface/menu.dm
@@ -1,5 +1,5 @@
/*
-/datum/menu/Example/verb/Example()
+/datum/verbs/menu/Example/verb/Example()
set name = "" //if this starts with @ the verb is not created and name becomes the command to invoke.
set desc = "" //desc is the text given to this entry in the menu
//You can not use src in these verbs. It will be the menu at compile time, but the client at runtime.
@@ -7,126 +7,44 @@
GLOBAL_LIST_EMPTY(menulist)
-/world/proc/load_menu()
- for (var/typepath in subtypesof(/datum/menu))
- new typepath()
-
-/datum/menu
- var/name
- var/list/children
- var/datum/menu/myparent
- var/list/verblist
+/datum/verbs/menu
var/checkbox = CHECKBOX_NONE //checkbox type.
var/default //default checked type.
//Set to true to append our children to our parent,
//Rather then add us as a node (used for having more then one checkgroups in the same menu)
- var/abstract = FALSE
-/datum/menu/New()
- var/ourentry = GLOB.menulist[type]
- children = list()
- verblist = list()
- if (ourentry)
- if (islist(ourentry)) //some of our childern already loaded
- Add_children(ourentry)
- else
- stack_trace("Menu item double load: [type]")
- qdel(src)
- return
+/datum/verbs/menu/GetList()
+ return GLOB.menulist
- GLOB.menulist[type] = src
+/datum/verbs/menu/Generate_list()
+ . = ..()
+ for(var/I in .)
+ .[I] = list2params(.[I])
- Load_verbs(type, typesof("[type]/verb"))
+/datum/verbs/menu/HandleVerb(list/entry, verbpath, client/C)
+ var/datum/verbs/menu/verb_true_parent = GLOB.menulist[verblist[verbpath]]
+ var/true_checkbox = verb_true_parent.checkbox
+ if (true_checkbox != CHECKBOX_NONE)
+ var/checkedverb = verb_true_parent.Get_checked(C)
+ if (true_checkbox == CHECKBOX_GROUP)
+ if (verbpath == checkedverb)
+ entry["is-checked"] = TRUE
+ else
+ entry["is-checked"] = FALSE
+ else if (true_checkbox == CHECKBOX_TOGGLE)
+ entry["is-checked"] = checkedverb
- var/datum/menu/parent = GLOB.menulist[parent_type]
- if (!parent)
- GLOB.menulist[parent_type] = list(src)
- else if (islist(parent))
- parent += src
- else
- parent.Add_children(list(src))
+ entry["command"] = ".updatemenuchecked \"[verb_true_parent.type]\" \"[verbpath]\"\n[entry["command"]]"
+ entry["can-check"] = TRUE
+ entry["group"] = "[verb_true_parent.type]"
-/datum/menu/proc/Set_parent(datum/menu/parent)
- myparent = parent
- if (abstract)
- myparent.Add_children(children)
- var/list/verblistoftypes = list()
- for(var/thing in verblist)
- LAZYADD(verblistoftypes[verblist[thing]], thing)
-
- for(var/verbparenttype in verblistoftypes)
- myparent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
-
-/datum/menu/proc/Add_children(list/kids)
- if (abstract && myparent)
- myparent.Add_children(kids)
- return
-
- for(var/thing in kids)
- var/datum/menu/menuitem = thing
- menuitem.Set_parent(src)
- if (!menuitem.abstract)
- children += menuitem
-
-/datum/menu/proc/Load_verbs(verb_parent_type, list/verbs)
- if (abstract && myparent)
- myparent.Load_verbs(verb_parent_type, verbs)
- return
-
- for (var/verbpath in verbs)
- verblist[verbpath] = verb_parent_type
-
-/datum/menu/proc/Generate_list(client/C)
- . = list()
- if (length(children))
- for (var/thing in children)
- var/datum/menu/child = thing
- var/list/childlist = child.Generate_list(C)
- if (childlist)
- var/childname = "[child]"
- if (childname == "[child.type]")
- var/list/tree = splittext(childname, "/")
- childname = tree[tree.len]
- .[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
- . += childlist
-
-
-
- for (var/thing in verblist)
- var/atom/verb/verbpath = thing
- if (!verbpath)
- stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
- var/list/entry = list()
- entry["parent"] = "[type]"
- entry["name"] = verbpath.desc
- if (copytext(verbpath.name,1,2) == "@")
- entry["command"] = copytext(verbpath.name,2)
- else
- entry["command"] = replacetext(verbpath.name, " ", "-")
- var/datum/menu/verb_true_parent = GLOB.menulist[verblist[verbpath]]
- var/true_checkbox = verb_true_parent.checkbox
- if (true_checkbox != CHECKBOX_NONE)
- var/checkedverb = verb_true_parent.Get_checked(C)
- if (true_checkbox == CHECKBOX_GROUP)
- if (verbpath == checkedverb)
- entry["is-checked"] = TRUE
- else
- entry["is-checked"] = FALSE
- else if (true_checkbox == CHECKBOX_TOGGLE)
- entry["is-checked"] = checkedverb
-
- entry["command"] = ".updatemenuchecked \"[verb_true_parent.type]\" \"[verbpath]\"\n[entry["command"]]"
- entry["can-check"] = TRUE
- entry["group"] = "[verb_true_parent.type]"
- .[verbpath] = list2params(entry)
-
-/datum/menu/proc/Get_checked(client/C)
+/datum/verbs/menu/proc/Get_checked(client/C)
return C.prefs.menuoptions[type] || default || FALSE
-/datum/menu/proc/Load_checked(client/C) //Loads the checked menu item into a new client. Used by icon menus to invoke the checked item.
+/datum/verbs/menu/proc/Load_checked(client/C) //Loads the checked menu item into a new client. Used by icon menus to invoke the checked item.
return
-/datum/menu/proc/Set_checked(client/C, verbpath)
+/datum/verbs/menu/proc/Set_checked(client/C, verbpath)
if (checkbox == CHECKBOX_GROUP)
C.prefs.menuoptions[type] = verbpath
C.prefs.save_preferences()
@@ -142,7 +60,7 @@ GLOBAL_LIST_EMPTY(menulist)
verbpath = text2path(verbpath)
if (!menutype || !verbpath)
return
- var/datum/menu/M = GLOB.menulist[menutype]
+ var/datum/verbs/menu/M = GLOB.menulist[menutype]
if (!M)
return
if (!(verbpath in typesof("[menutype]/verb")))
@@ -150,7 +68,7 @@ GLOBAL_LIST_EMPTY(menulist)
M.Set_checked(src, verbpath)
-/datum/menu/Icon/Load_checked(client/C) //So we can be lazy, we invoke the "checked" menu item on menu load.
+/datum/verbs/menu/Icon/Load_checked(client/C) //So we can be lazy, we invoke the "checked" menu item on menu load.
var/atom/verb/verbpath = Get_checked(C)
if (!verbpath || !(verbpath in typesof("[type]/verb")))
return
@@ -159,45 +77,45 @@ GLOBAL_LIST_EMPTY(menulist)
else
winset(C, null, "command = [replacetext(verbpath.name, " ", "-")]")
-/datum/menu/Icon/Size
+/datum/verbs/menu/Icon/Size
checkbox = CHECKBOX_GROUP
- default = /datum/menu/Icon/Size/verb/iconstretchtofit
+ default = /datum/verbs/menu/Icon/Size/verb/iconstretchtofit
-/datum/menu/Icon/Size/verb/iconstretchtofit()
+/datum/verbs/menu/Icon/Size/verb/iconstretchtofit()
set name = "@.winset \"mapwindow.map.icon-size=0\""
set desc = "&Auto (stretch-to-fit)"
-/datum/menu/Icon/Size/verb/icon96()
+/datum/verbs/menu/Icon/Size/verb/icon96()
set name = "@.winset \"mapwindow.map.icon-size=96\""
set desc = "&96x96 (3x)"
-/datum/menu/Icon/Size/verb/icon64()
+/datum/verbs/menu/Icon/Size/verb/icon64()
set name = "@.winset \"mapwindow.map.icon-size=64\""
set desc = "&64x64 (2x)"
-/datum/menu/Icon/Size/verb/icon48()
+/datum/verbs/menu/Icon/Size/verb/icon48()
set name = "@.winset \"mapwindow.map.icon-size=48\""
set desc = "&48x48 (1.5x)"
-/datum/menu/Icon/Size/verb/icon32()
+/datum/verbs/menu/Icon/Size/verb/icon32()
set name = "@.winset \"mapwindow.map.icon-size=32\""
set desc = "&32x32 (1x)"
-/datum/menu/Icon/Scaling
+/datum/verbs/menu/Icon/Scaling
checkbox = CHECKBOX_GROUP
name = "Scaling Mode"
- default = /datum/menu/Icon/Scaling/verb/NN
+ default = /datum/verbs/menu/Icon/Scaling/verb/NN
-/datum/menu/Icon/Scaling/verb/NN()
+/datum/verbs/menu/Icon/Scaling/verb/NN()
set name = "@.winset \"mapwindow.map.zoom-mode=distort\""
set desc = "Nearest Neighbor"
-/datum/menu/Icon/Scaling/verb/PS()
+/datum/verbs/menu/Icon/Scaling/verb/PS()
set name = "@.winset \"mapwindow.map.zoom-mode=normal\""
set desc = "Point Sampling"
-/datum/menu/Icon/Scaling/verb/BL()
+/datum/verbs/menu/Icon/Scaling/verb/BL()
set name = "@.winset \"mapwindow.map.zoom-mode=blur\""
set desc = "Bilinear"
diff --git a/tgstation.dme b/tgstation.dme
index 6b33ed56be..2cc7ae8937 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -264,6 +264,7 @@
#include "code\datums\ruins.dm"
#include "code\datums\shuttles.dm"
#include "code\datums\soullink.dm"
+#include "code\datums\verbs.dm"
#include "code\datums\votablemap.dm"
#include "code\datums\antagonists\antag_datum.dm"
#include "code\datums\antagonists\datum_clockcult.dm"