From 17ca3a83582fe025068bae8fbf0e8d4b6cba2f72 Mon Sep 17 00:00:00 2001 From: CHOMPStation2 <58959929+CHOMPStation2@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:02:07 -0700 Subject: [PATCH] [MIRROR] Add ability to adjust your layer/plane (#6726) Co-authored-by: Casey Co-authored-by: Raeschen --- code/modules/mob/living/living_movement.dm | 2 + code/modules/mob/mob.dm | 2598 ++++++++++---------- interface/skin.dmf | 574 ++--- 3 files changed, 1612 insertions(+), 1562 deletions(-) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 9d5b7d3447..a78d771155 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -279,6 +279,8 @@ default behaviour is: is_shifted = FALSE pixel_x = default_pixel_x pixel_y = default_pixel_y + layer = MOB_LAYER + plane = MOB_PLANE // End VOREstation edit if(pulling) // we were pulling a thing and didn't lose it during our move. diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index c80e67b3c3..b91399e538 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,1286 +1,1312 @@ -/mob/Destroy()//This makes sure that mobs withGLOB.clients/keys are not just deleted from the game. - mob_list -= src - dead_mob_list -= src - living_mob_list -= src - unset_machine() - qdel(hud_used) - clear_fullscreen() - if(client) - for(var/obj/screen/movable/spell_master/spell_master in spell_masters) - qdel(spell_master) - remove_screen_obj_references() - client.screen = list() - if(mind && mind.current == src) - spellremove(src) - ghostize() - QDEL_NULL(plane_holder) - ..() - return QDEL_HINT_HARDDEL_NOW - -/mob/proc/remove_screen_obj_references() - hands = null - pullin = null - purged = null - internals = null - i_select = null - m_select = null - healths = null - throw_icon = null - pain = null - item_use_icon = null - gun_move_icon = null - gun_setting_icon = null - spell_masters = null - zone_sel = null - -/mob/Initialize() - mob_list += src - if(stat == DEAD) - dead_mob_list += src - else - living_mob_list += src - lastarea = get_area(src) - set_focus(src) // VOREStation Add - Key Handling - hook_vr("mob_new",list(src)) //VOREStation Code - update_transform() // Some mobs may start bigger or smaller than normal. - return ..() - -/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) - - if(!client && !teleop) return - - if (type) - if((type & VISIBLE_MESSAGE) && (is_blind() || paralysis) )//Vision related - if (!( alt )) - return - else - msg = alt - type = alt_type - if ((type & AUDIBLE_MESSAGE) && is_deaf())//Hearing related - if (!( alt )) - return - else - msg = alt - type = alt_type - if ((type & VISIBLE_MESSAGE) && (sdisabilities & BLIND)) - return - // Added voice muffling for Issue 41. - if(stat == UNCONSCIOUS || sleeping > 0) - to_chat(src, "... You can almost hear someone talking ...") - else - to_chat(src,msg) - if(teleop) - to_chat(teleop, create_text_tag("body", "BODY:", teleop.client) + "[msg]") - return - -// Show a message to all mobs and objects in sight of this one -// This would be for visible actions by the src mob -// message is the message output to anyone who can see e.g. "[src] does something!" -// self_message (optional) is what the src mob sees e.g. "You do something!" -// blind_message (optional) is what blind people will hear e.g. "You hear something!" -/mob/visible_message(var/message, var/self_message, var/blind_message, var/list/exclude_mobs = null, var/range = world.view, var/runemessage) - if(self_message) - if(LAZYLEN(exclude_mobs)) - exclude_mobs |= src - else - exclude_mobs = list(src) - src.show_message(self_message, 1, blind_message, 2) - if(isnull(runemessage)) - runemessage = -1 - . = ..(message, blind_message, exclude_mobs, range, runemessage) // Really not ideal that atom/visible_message has different arg numbering :( - -// Returns an amount of power drawn from the object (-1 if it's not viable). -// If drain_check is set it will not actually drain power, just return a value. -// If surge is set, it will destroy/damage the recipient and not return any power. -// Not sure where to define this, so it can sit here for the rest of time. -/atom/proc/drain_power(var/drain_check,var/surge, var/amount = 0) - return -1 - -// Show a message to all mobs and objects in earshot of this one -// This would be for audible actions by the src mob -// message is the message output to anyone who can hear. -// self_message (optional) is what the src mob hears. -// deaf_message (optional) is what deaf people will see. -// hearing_distance (optional) is the range, how many tiles away the message can be heard. -/mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message, var/radio_message, var/runemessage) - - var/range = hearing_distance || world.view - var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE) - - var/list/hearing_mobs = hear["mobs"] - var/list/hearing_objs = hear["objs"] - - if(isnull(runemessage)) - runemessage = -1 // Symmetry with mob/audible_message, despite the fact this one doesn't call parent. Maybe it should! - - if(radio_message) - for(var/obj/O as anything in hearing_objs) - O.hear_talk(src, list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], radio_message)), null) - else - for(var/obj/O as anything in hearing_objs) - O.show_message(message, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE) - - for(var/mob/M as anything in hearing_mobs) - var/msg = message - if(self_message && M==src) - msg = self_message - M.show_message(msg, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE) - if(runemessage != -1) - M.create_chat_message(src, "[runemessage || message]", FALSE, list("emote"), audible = FALSE) - -/mob/proc/findname(msg) - for(var/mob/M in mob_list) - if (M.real_name == text("[]", msg)) - return M - return 0 - -/mob/proc/Life() -// if(organStructure) -// organStructure.ProcessOrgans() - return - -#define UNBUCKLED 0 -#define PARTIALLY_BUCKLED 1 -#define FULLY_BUCKLED 2 -/mob/proc/buckled() - // Preliminary work for a future buckle rewrite, - // where one might be fully restrained (like an elecrical chair), or merely secured (shuttle chair, keeping you safe but not otherwise restrained from acting) - if(!buckled) - return UNBUCKLED - return restrained() ? FULLY_BUCKLED : PARTIALLY_BUCKLED - -/mob/proc/is_blind() - return ((sdisabilities & BLIND) || blinded || incapacitated(INCAPACITATION_KNOCKOUT)) - -/mob/proc/is_deaf() - return ((sdisabilities & DEAF) || ear_deaf || incapacitated(INCAPACITATION_KNOCKOUT)) - -/mob/proc/is_physically_disabled() - return incapacitated(INCAPACITATION_DISABLED) - -/mob/proc/cannot_stand() - return incapacitated(INCAPACITATION_KNOCKDOWN) - -/mob/proc/incapacitated(var/incapacitation_flags = INCAPACITATION_DEFAULT) - if ((incapacitation_flags & INCAPACITATION_STUNNED) && stunned) - return 1 - - if ((incapacitation_flags & INCAPACITATION_FORCELYING) && (weakened || resting)) - return 1 - - if ((incapacitation_flags & INCAPACITATION_KNOCKOUT) && (stat || paralysis || sleeping || (status_flags & FAKEDEATH))) - return 1 - - if((incapacitation_flags & INCAPACITATION_RESTRAINED) && restrained()) - return 1 - - if((incapacitation_flags & (INCAPACITATION_BUCKLED_PARTIALLY|INCAPACITATION_BUCKLED_FULLY))) - var/buckling = buckled() - if(buckling >= PARTIALLY_BUCKLED && (incapacitation_flags & INCAPACITATION_BUCKLED_PARTIALLY)) - return 1 - if(buckling == FULLY_BUCKLED && (incapacitation_flags & INCAPACITATION_BUCKLED_FULLY)) - return 1 - - return 0 - -#undef UNBUCKLED -#undef PARTIALLY_BUCKLED -#undef FULLY_BUCKLED - -/mob/proc/restrained() - return - -/mob/proc/reset_view(atom/A) - if (client) - if (istype(A, /atom/movable)) - client.perspective = EYE_PERSPECTIVE - client.eye = A - else - if (isturf(loc)) - client.eye = client.mob - client.perspective = MOB_PERSPECTIVE - else - client.perspective = EYE_PERSPECTIVE - client.eye = loc - return TRUE - -/mob/verb/pointed(atom/A as mob|obj|turf in view()) - set name = "Point To" - set category = "Object" - - if(!src || !isturf(src.loc) || !(A in view(src.loc))) - return 0 - if(istype(A, /obj/effect/decal/point)) - return 0 - - var/turf/tile = get_turf(A) - if (!tile) - return 0 - - var/turf/our_tile = get_turf(src) - var/obj/visual = new /obj/effect/decal/point(our_tile) - visual.invisibility = invisibility - visual.plane = ABOVE_PLANE - visual.layer = FLY_LAYER - - animate(visual, - pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, - pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, - time = 1.7, - easing = EASE_OUT) - - QDEL_IN(visual, 2 SECONDS) //Better qdel - - face_atom(A) - return 1 - - -/mob/proc/ret_grab(list/L, flag) - return - -/mob/verb/mode() - set name = "Activate Held Object" - set category = "Object" - set src = usr - - return - -/* -/mob/verb/dump_source() - - var/master = "
"
-	for(var/t in typesof(/area))
-		master += text("[]\n", t)
-		//Foreach goto(26)
-	src << browse(master)
-	return
-*/
-
-/mob/verb/memory()
-	set name = "Notes"
-	set category = "IC"
-	if(mind)
-		mind.show_memory(src)
-	else
-		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
-
-/mob/verb/add_memory(msg as message)
-	set name = "Add Note"
-	set category = "IC"
-
-	msg = sanitize(msg)
-
-	if(mind)
-		mind.store_memory(msg)
-	else
-		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
-
-/mob/proc/store_memory(msg as message, popup, sane = 1)
-	msg = copytext(msg, 1, MAX_MESSAGE_LEN)
-
-	if (sane)
-		msg = sanitize(msg)
-
-	if (length(memory) == 0)
-		memory += msg
-	else
-		memory += "
[msg]" - - if (popup) - memory() - -/mob/proc/update_flavor_text() - set src in usr - if(usr != src) - to_chat(usr, "No.") - var/msg = sanitize(tgui_input_text(usr,"Set the flavor text in your 'examine' verb.","Flavor Text",html_decode(flavor_text), multiline = TRUE, prevent_enter = TRUE), extra = 0) //VOREStation Edit: separating out OOC notes - - if(msg != null) - flavor_text = msg - -/mob/proc/warn_flavor_changed() - if(flavor_text && flavor_text != "") // don't spam people that don't use it! - to_chat(src, "

OOC Warning:

") - to_chat(src, "Your flavor text is likely out of date! Change") - -/mob/proc/print_flavor_text() - if (flavor_text && flavor_text != "") - var/msg = replacetext(flavor_text, "\n", " ") - if(length(msg) <= 40) - return "[msg]" - else - return "[copytext_preserve_html(msg, 1, 37)]... More..." - -/* -/mob/verb/help() - set name = "Help" - src << browse('html/help.html', "window=help") - return -*/ - -/mob/proc/set_respawn_timer(var/time) - // Try to figure out what time to use - - // Special cases, can never respawn - if(ticker?.mode?.deny_respawn) - time = -1 - else if(!config.abandon_allowed) - time = -1 - else if(!config.respawn) - time = -1 - - // Special case for observing before game start - else if(ticker?.current_state <= GAME_STATE_SETTING_UP) - time = 1 MINUTE - - // Wasn't given a time, use the config time - else if(!time) - time = config.respawn_time - - var/keytouse = ckey - // Try harder to find a key to use - if(!keytouse && key) - keytouse = ckey(key) - else if(!keytouse && mind?.key) - keytouse = ckey(mind.key) - - GLOB.respawn_timers[keytouse] = world.time + time - -/mob/observer/dead/set_respawn_timer() - if(config.antag_hud_restricted && has_enabled_antagHUD) - ..(-1) - else - return // Don't set it, no need - -/mob/verb/abandon_mob() - set name = "Return to Menu" - set category = "OOC" - - if(stat != DEAD || !ticker) - to_chat(usr, "You must be dead to use this!") - return - - // Final chance to abort "respawning" - if(mind && timeofdeath) // They had spawned before - var/choice = tgui_alert(usr, "Returning to the menu will prevent your character from being revived in-round. Are you sure?", "Confirmation", list("No, wait", "Yes, leave")) - if(choice == "No, wait") - return - else if(mind.assigned_role) - var/extra_check = tgui_alert(usr, "Do you want to Quit This Round before you return to lobby? This will properly remove you from manifest, as well as prevent resleeving.","Quit This Round",list("Quit Round","Cancel")) - if(extra_check == "Quit Round") - //Update any existing objectives involving this mob. - for(var/datum/objective/O in all_objectives) - if(O.target == src.mind) - if(O.owner && O.owner.current) - to_chat(O.owner.current,"You get the feeling your target is no longer within your reach...") - qdel(O) - - //Resleeving cleanup - if(mind) - SStranscore.leave_round(src) - - //Job slot cleanup - var/job = src.mind.assigned_role - job_master.FreeRole(job) - - //Their objectives cleanup - if(src.mind.objectives.len) - qdel(src.mind.objectives) - src.mind.special_role = null - - //Cut the PDA manifest (ugh) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.medical) - if((R.fields["name"] == src.real_name)) - qdel(R) - for(var/datum/data/record/T in data_core.security) - if((T.fields["name"] == src.real_name)) - qdel(T) - for(var/datum/data/record/G in data_core.general) - if((G.fields["name"] == src.real_name)) - qdel(G) - - //This removes them from being 'active' list on join screen - src.mind.assigned_role = null - to_chat(src,"Your job has been free'd up, and you can rejoin as another character or quit. Thanks for properly quitting round, it helps the server!") - - // Beyond this point, you're going to respawn - to_chat(usr, config.respawn_message) - - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - return - client.screen.Cut() - client.screen += client.void - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - return - - announce_ghost_joinleave(client, 0) - - var/mob/new_player/M = new /mob/new_player() - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - qdel(M) - return - - M.key = key - if(M.mind) - M.mind.reset() - return - -/client/verb/changes() - set name = "Changelog" - set category = "OOC" - // CHOMPedit Start - Better Changelog - //src << browse('html/changelog.html', "window=changes;size=675x650") - //return - - if(!GLOB.changelog_tgui) - GLOB.changelog_tgui = new /datum/changelog() - GLOB.changelog_tgui.tgui_interact(usr) - // CHOMPedit END - if(prefs.lastchangelog != changelog_hash) - prefs.lastchangelog = changelog_hash - SScharacter_setup.queue_preferences_save(prefs) - // winset(src, "rpane.changelog", "background-color=none;font-style=;") //ChompREMOVE - -/mob/verb/observe() - set name = "Observe" - set category = "OOC" - var/is_admin = 0 - - if(client.holder && (client.holder.rights & R_ADMIN|R_EVENT)) - is_admin = 1 - else if(stat != DEAD || istype(src, /mob/new_player)) - to_chat(usr, "You must be observing to use this!") - return - - if(is_admin && stat == DEAD) - is_admin = 0 - - var/list/targets = list() - - - targets += observe_list_format(nuke_disks) - targets += observe_list_format(GLOB.all_singularities) //CHOMP Edit - targets += getmobs() - targets += observe_list_format(sortAtom(mechas_list)) - targets += observe_list_format(SSshuttles.ships) - - client.perspective = EYE_PERSPECTIVE - - var/eye_name = null - - var/ok = "[is_admin ? "Admin Observe" : "Observe"]" - eye_name = tgui_input_list(usr, "Select something to [ok]:", "Select Target", targets) - - if (!eye_name) - return - - var/mob/mob_eye = targets[eye_name] - - if(client && mob_eye) - client.eye = mob_eye - if (is_admin) - client.adminobs = 1 - if(mob_eye == client.mob || client.eye == client.mob) - client.adminobs = 0 - -/mob/verb/cancel_camera() - set name = "Cancel Camera View" - set category = "OOC" - unset_machine() - reset_view(null) - -/mob/Topic(href, href_list) - if(href_list["mach_close"]) - var/t1 = text("window=[href_list["mach_close"]]") - unset_machine() - src << browse(null, t1) - - if(href_list["flavor_more"]) - usr << browse(text("[][]", name, replacetext(flavor_text, "\n", "
")), text("window=[];size=500x200", name)) - onclose(usr, "[name]") - if(href_list["flavor_change"]) - update_flavor_text() -// ..() - return - - -/mob/proc/pull_damage() - return 0 - -/mob/verb/stop_pulling() - - set name = "Stop Pulling" - set category = "IC" - - if(pulling) - if(ishuman(pulling)) - var/mob/living/carbon/human/H = pulling - visible_message(SPAN_WARNING("\The [src] lets go of \the [H]."), SPAN_NOTICE("You let go of \the [H]."), exclude_mobs = list(H)) - if(!H.stat) - to_chat(H, SPAN_WARNING("\The [src] lets go of you.")) - pulling.pulledby = null - pulling = null - if(pullin) - pullin.icon_state = "pull0" - -/mob/proc/start_pulling(var/atom/movable/AM) - - if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! - return - - if (AM.anchored) - to_chat(src, "It won't budge!") - return - - var/mob/M = AM - if(ismob(AM)) - - if(!can_pull_mobs || !can_pull_size) - to_chat(src, "They won't budge!") - return - - if((mob_size < M.mob_size) && (can_pull_mobs != MOB_PULL_LARGER)) - to_chat(src, "[M] is too large for you to move!") - return - - if((mob_size == M.mob_size) && (can_pull_mobs == MOB_PULL_SMALLER)) - to_chat(src, "[M] is too heavy for you to move!") - return - - // If your size is larger than theirs and you have some - // kind of mob pull value AT ALL, you will be able to pull - // them, so don't bother checking that explicitly. - - if(M.grabbed_by.len) - // Only start pulling when nobody else has a grab on them - . = 1 - for(var/obj/item/weapon/grab/G in M.grabbed_by) - if(G.assailant != usr) - . = 0 - else - qdel(G) - if(!.) - to_chat(src, "Somebody has a grip on them!") - return - - if(!iscarbon(src)) - M.LAssailant = null - else - M.LAssailant = usr - - else if(isobj(AM)) - var/obj/I = AM - if(!can_pull_size || can_pull_size < I.w_class) - to_chat(src, "It won't budge!") - return - - if(pulling) - var/pulling_old = pulling - stop_pulling() - // Are we pulling the same thing twice? Just stop pulling. - if(pulling_old == AM) - return - - src.pulling = AM - AM.pulledby = src - - if(pullin) - pullin.icon_state = "pull1" - - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(H.lying) // If they're on the ground we're probably dragging their arms to move them - visible_message(SPAN_WARNING("\The [src] leans down and grips \the [H]'s arms."), SPAN_NOTICE("You lean down and grip \the [H]'s arms."), exclude_mobs = list(H)) - if(!H.stat) - to_chat(H, SPAN_WARNING("\The [src] leans down and grips your arms.")) - else //Otherwise we're probably just holding their arm to lead them somewhere - visible_message(SPAN_WARNING("\The [src] grips \the [H]'s arm."), SPAN_NOTICE("You grip \the [H]'s arm."), exclude_mobs = list(H)) - if(!H.stat) - to_chat(H, SPAN_WARNING("\The [src] grips your arm.")) - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25) //Quieter than hugging/grabbing but we still want some audio feedback - - if(H.pull_damage()) - to_chat(src, "Pulling \the [H] in their current condition would probably be a bad idea.") - - //Attempted fix for people flying away through space when cuffed and dragged. - if(ismob(AM)) - var/mob/pulled = AM - pulled.inertia_dir = 0 - -/mob/proc/can_use_hands() - return - -/mob/proc/is_active() - return (0 >= usr.stat) - -/mob/proc/is_dead() - return stat == DEAD - -/mob/proc/is_mechanical() - if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) - return 1 - return istype(src, /mob/living/silicon) || get_species() == "Machine" - -/mob/proc/is_ready() - return client && !!mind - -/mob/proc/get_gender() - return gender - -/mob/proc/name_gender() - return gender - -/mob/proc/see(message) - if(!is_active()) - return 0 - to_chat(src,message) - return 1 - -/mob/proc/show_viewers(message) - for(var/mob/M in viewers()) - M.see(message) - -/mob/Stat() - ..() - . = (is_client_active(10 MINUTES)) - - if(.) - if(statpanel("Status")) - stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") - if(ticker && ticker.current_state != GAME_STATE_PREGAME) - stat("Station Time", stationtime2text()) - var/date = "[stationdate2text()], [capitalize(world_time_season)]" - stat("Station Date", date) - stat("Round Duration", roundduration2text()) - - if(client.holder) - if(statpanel("Status")) - stat("Location:", "([x], [y], [z]) [loc]") - stat("CPU:","[world.cpu]") - stat("Instances:","[world.contents.len]") - stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") - stat("Keys Held", keys2text(client.move_keys_held | client.mod_keys_held)) - stat("Next Move ADD", dirs2text(client.next_move_dir_add)) - stat("Next Move SUB", dirs2text(client.next_move_dir_sub)) - - if(statpanel("MC")) - stat("Location:", "([x], [y], [z]) [loc]") - stat("CPU:","[world.cpu]") - stat("Instances:","[world.contents.len]") - stat("World Time:", world.time) - stat("Real time of day:", REALTIMEOFDAY) - stat(null) - if(GLOB) - GLOB.stat_entry() - else - stat("Globals:", "ERROR") - if(Master) - Master.stat_entry() - else - stat("Master Controller:", "ERROR") - if(Failsafe) - Failsafe.stat_entry() - else - stat("Failsafe Controller:", "ERROR") - if(Master) - stat(null) - for(var/datum/controller/subsystem/SS in Master.subsystems) - SS.stat_entry() - - // CHOMPedit - Ticket System - //if(statpanel("Tickets")) - //GLOB.ahelp_tickets.stat_entry() - - - if(length(GLOB.sdql2_queries)) - if(statpanel("SDQL2")) - stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj) - for(var/datum/SDQL2_query/Q as anything in GLOB.sdql2_queries) - Q.generate_stat() - - - if(has_mentor_powers(client) || client.holder) // CHOMPedit - Ticket System - if(statpanel("Tickets")) - GLOB.tickets.stat_entry() // CHOMPedit - Ticket System - - if(listed_turf && client) - if(!TurfAdjacent(listed_turf)) - listed_turf = null - else - if(statpanel("Turf")) - stat(listed_turf) - for(var/atom/A in listed_turf) - if(!A.mouse_opacity) - continue - if(A.invisibility > see_invisible) - continue - if(is_type_in_list(A, shouldnt_see)) - continue - if(A.plane > plane) - continue - stat(A) - - -// facing verbs -/mob/proc/canface() -// if(!canmove) return 0 //VOREStation Edit. Redundant check that only affects conscious proning, actual inability to turn and shift around handled by actual inabilities. - if(stat) return 0 - if(anchored) return 0 - if(transforming) return 0 - return 1 - -// Not sure what to call this. Used to check if humans are wearing an AI-controlled exosuit and hence don't need to fall over yet. -/mob/proc/can_stand_overridden() - return 0 - -//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. -/mob/proc/update_canmove() - return canmove - - -/mob/proc/facedir(var/ndir) - if(!canface() || (client && (client.moving || !checkMoveCooldown()))) - DEBUG_INPUT("Denying Facedir for [src] (moving=[client?.moving])") - return 0 - set_dir(ndir) - if(buckled && buckled.buckle_movable) - buckled.set_dir(ndir) - setMoveCooldown(movement_delay()) - return 1 - - -/mob/verb/eastface() - set hidden = 1 - return facedir(client.client_dir(EAST)) - - -/mob/verb/westface() - set hidden = 1 - return facedir(client.client_dir(WEST)) - - -/mob/verb/northface() - set hidden = 1 - return facedir(client.client_dir(NORTH)) - - -/mob/verb/southface() - set hidden = 1 - return facedir(client.client_dir(SOUTH)) - - -//This might need a rename but it should replace the can this mob use things check -/mob/proc/IsAdvancedToolUser() - return 0 - -/mob/proc/Stun(amount) - if(status_flags & CANSTUN) - facing_dir = null - stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun - update_canmove() //updates lying, canmove and icons - return - -/mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" - if(status_flags & CANSTUN) - stunned = max(amount,0) - update_canmove() //updates lying, canmove and icons - return - -/mob/proc/AdjustStunned(amount) - if(status_flags & CANSTUN) - stunned = max(stunned + amount,0) - update_canmove() //updates lying, canmove and icons - return - -/mob/proc/Weaken(amount) - if(status_flags & CANWEAKEN) - facing_dir = null - weakened = max(max(weakened,amount),0) - update_canmove() //updates lying, canmove and icons - return - -/mob/proc/SetWeakened(amount) - if(status_flags & CANWEAKEN) - weakened = max(amount,0) - update_canmove() //can you guess what this does yet? - return - -/mob/proc/AdjustWeakened(amount) - if(status_flags & CANWEAKEN) - weakened = max(weakened + amount,0) - update_canmove() //updates lying, canmove and icons - return - -/mob/proc/Paralyse(amount) - if(status_flags & CANPARALYSE) - facing_dir = null - paralysis = max(max(paralysis,amount),0) - return - -/mob/proc/SetParalysis(amount) - if(status_flags & CANPARALYSE) - paralysis = max(amount,0) - return - -/mob/proc/AdjustParalysis(amount) - if(status_flags & CANPARALYSE) - paralysis = max(paralysis + amount,0) - return - -/mob/proc/Sleeping(amount) - facing_dir = null - sleeping = max(max(sleeping,amount),0) - return - -/mob/proc/SetSleeping(amount) - sleeping = max(amount,0) - return - -/mob/proc/AdjustSleeping(amount) - sleeping = max(sleeping + amount,0) - return - -/mob/proc/Confuse(amount) - confused = max(max(confused,amount),0) - return - -/mob/proc/SetConfused(amount) - confused = max(amount,0) - return - -/mob/proc/AdjustConfused(amount) - confused = max(confused + amount,0) - return - -/mob/proc/Blind(amount) - eye_blind = max(max(eye_blind,amount),0) - return - -/mob/proc/SetBlinded(amount) - eye_blind = max(amount,0) - return - -/mob/proc/AdjustBlinded(amount) - eye_blind = max(eye_blind + amount,0) - return - -/mob/proc/Resting(amount) - facing_dir = null - resting = max(max(resting,amount),0) - update_canmove() - return - -/mob/proc/SetResting(amount) - resting = max(amount,0) - update_canmove() - return - -/mob/proc/AdjustResting(amount) - resting = max(resting + amount,0) - update_canmove() - return - -/mob/proc/AdjustLosebreath(amount) - losebreath = CLAMP(losebreath + amount, 0, 25) - -/mob/proc/SetLosebreath(amount) - losebreath = CLAMP(amount, 0, 25) - -/mob/proc/get_species() - return "" - -/mob/proc/flash_weak_pain() - flick("weak_pain",pain) - -/mob/proc/get_visible_implants(var/class = 0) - var/list/visible_implants = list() - for(var/obj/item/O in embedded) - if(O.w_class > class) - visible_implants += O - return visible_implants - -/mob/proc/embedded_needs_process() - return (embedded.len > 0) - -/mob/proc/yank_out_object() - set category = "Object" - set name = "Yank out object" - set desc = "Remove an embedded item at the cost of bleeding and pain." - set src in view(1) - - if(!isliving(usr) || !usr.checkClickCooldown()) - return - usr.setClickCooldown(20) - - if(usr.stat == 1) - to_chat(usr, "You are unconcious and cannot do that!") - return - - if(usr.restrained()) - to_chat(usr, "You are restrained and cannot do that!") - return - - var/mob/S = src - var/mob/U = usr - var/list/valid_objects = list() - var/self = null - - if(S == U) - self = 1 // Removing object from yourself. - - valid_objects = get_visible_implants(0) - if(!valid_objects.len) - if(self) - to_chat(src, "You have nothing stuck in your body that is large enough to remove.") - else - to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.") - return - - var/obj/item/weapon/selection = tgui_input_list(usr, "What do you want to yank out?", "Embedded objects", valid_objects) - - if(self) - to_chat(src, "You attempt to get a good grip on [selection] in your body.") - else - to_chat(U, "You attempt to get a good grip on [selection] in [S]'s body.") - - if(!do_after(U, 30)) - return - if(!selection || !S || !U) - return - - if(self) - visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") - else - visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.") - valid_objects = get_visible_implants(0) - if(valid_objects.len == 1) //Yanking out last object - removing verb. - src.verbs -= /mob/proc/yank_out_object - clear_alert("embeddedobject") - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - var/obj/item/organ/external/affected - - for(var/obj/item/organ/external/organ in H.organs) //Grab the organ holding the implant. - for(var/obj/item/O in organ.implants) - if(O == selection) - affected = organ - - affected.implants -= selection - H.shock_stage+=20 - affected.take_damage((selection.w_class * 3), 0, 0, 1, "Embedded object extraction") - - if(prob(selection.w_class * 5) && (affected.robotic < ORGAN_ROBOT)) //I'M SO ANEMIC I COULD JUST -DIE-. - var/datum/wound/internal_bleeding/I = new (min(selection.w_class * 5, 15)) - affected.wounds += I - H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 50) - - if (ishuman(U)) - var/mob/living/carbon/human/human_user = U - human_user.bloody_hands(H) - - else if(issilicon(src)) - var/mob/living/silicon/robot/R = src - R.embedded -= selection - R.adjustBruteLoss(5) - R.adjustFireLoss(10) - - selection.forceMove(get_turf(src)) - U.put_in_hands(selection) - - for(var/obj/item/weapon/O in pinned) - if(O == selection) - pinned -= O - if(!pinned.len) - anchored = FALSE - return 1 - -//Check for brain worms in head. -/mob/proc/has_brain_worms() - - for(var/I in contents) - if(istype(I,/mob/living/simple_mob/animal/borer)) - return I - - return 0 - -/mob/proc/updateicon() - return - -// Please always use this proc, never just set the var directly. -/mob/proc/set_stat(var/new_stat) - . = (stat != new_stat) - stat = new_stat - -/mob/verb/face_direction() - - set name = "Face Direction" - set category = "IC" - set src = usr - - set_face_dir() - - if(!facing_dir) - to_chat(usr, "You are now not facing anything.") - else - to_chat(usr, "You are now facing [dir2text(facing_dir)].") - -/mob/proc/set_face_dir(var/newdir) - if(newdir == facing_dir) - facing_dir = null - else if(newdir) - set_dir(newdir) - facing_dir = newdir - else if(facing_dir) - facing_dir = null - else - set_dir(dir) - facing_dir = dir - -/mob/set_dir() - if(facing_dir) - if(!canface() || lying || buckled || restrained()) - facing_dir = null - else if(dir != facing_dir) - return ..(facing_dir) - else - return ..() - -/mob/verb/northfaceperm() - set hidden = 1 - set_face_dir(client.client_dir(NORTH)) - -/mob/verb/southfaceperm() - set hidden = 1 - set_face_dir(client.client_dir(SOUTH)) - -/mob/verb/eastfaceperm() - set hidden = 1 - set_face_dir(client.client_dir(EAST)) - -/mob/verb/westfaceperm() - set hidden = 1 - set_face_dir(client.client_dir(WEST)) - -// Begin VOREstation edit -/mob/verb/shiftnorth() - set hidden = TRUE - if(!canface()) - return FALSE - if(pixel_y <= (default_pixel_y + 16)) - pixel_y++ - is_shifted = TRUE - -/mob/verb/shiftsouth() - set hidden = TRUE - if(!canface()) - return FALSE - if(pixel_y >= (default_pixel_y - 16)) - pixel_y-- - is_shifted = TRUE - -/mob/verb/shiftwest() - set hidden = TRUE - if(!canface()) - return FALSE - if(pixel_x >= (default_pixel_x - 16)) - pixel_x-- - is_shifted = TRUE - -/mob/verb/shifteast() - set hidden = TRUE - if(!canface()) - return FALSE - if(pixel_x <= (default_pixel_x + 16)) - pixel_x++ - is_shifted = TRUE -// End VOREstation edit - -/mob/proc/adjustEarDamage() - return - -/mob/proc/setEarDamage() - return - -// Set client view distance (size of client's screen). Returns TRUE if anything changed. -/mob/proc/set_viewsize(var/new_view = world.view) - if (client && new_view != client.view) - client.view = new_view - return TRUE - return FALSE - -//Throwing stuff - -/mob/proc/toggle_throw_mode() - if (src.in_throw_mode) - throw_mode_off() - else - throw_mode_on() - -/mob/proc/throw_mode_off() - src.in_throw_mode = 0 - if(src.throw_icon) //in case we don't have the HUD and we use the hotkey - src.throw_icon.icon_state = "act_throw_off" - -/mob/proc/throw_mode_on() - src.in_throw_mode = 1 - if(src.throw_icon) - src.throw_icon.icon_state = "act_throw_on" - -/mob/proc/isSynthetic() - return 0 - -/mob/proc/is_muzzled() - return 0 - -//Exploitable Info Update - -/mob/proc/amend_exploitable(var/obj/item/I) - if(istype(I)) - exploit_addons |= I - var/exploitmsg = html_decode("\n" + "Has " + I.name + ".") - exploit_record += exploitmsg - -/client/proc/check_has_body_select() - return mob && mob.hud_used && istype(mob.zone_sel, /obj/screen/zone_sel) - -/client/verb/body_toggle_head() - set name = "body-toggle-head" - set hidden = 1 - toggle_zone_sel(list(BP_HEAD, O_EYES, O_MOUTH)) - -/client/verb/body_r_arm() - set name = "body-r-arm" - set hidden = 1 - toggle_zone_sel(list(BP_R_ARM,BP_R_HAND)) - -/client/verb/body_l_arm() - set name = "body-l-arm" - set hidden = 1 - toggle_zone_sel(list(BP_L_ARM,BP_L_HAND)) - -/client/verb/body_chest() - set name = "body-chest" - set hidden = 1 - toggle_zone_sel(list(BP_TORSO)) - -/client/verb/body_groin() - set name = "body-groin" - set hidden = 1 - toggle_zone_sel(list(BP_GROIN)) - -/client/verb/body_r_leg() - set name = "body-r-leg" - set hidden = 1 - toggle_zone_sel(list(BP_R_LEG,BP_R_FOOT)) - -/client/verb/body_l_leg() - set name = "body-l-leg" - set hidden = 1 - toggle_zone_sel(list(BP_L_LEG,BP_L_FOOT)) - -/client/proc/toggle_zone_sel(list/zones) - if(!check_has_body_select()) - return - var/obj/screen/zone_sel/selector = mob.zone_sel - selector.set_selected_zone(next_in_list(mob.zone_sel.selecting,zones)) - -// This handles setting the client's color variable, which makes everything look a specific color. -// This proc is here so it can be called without needing to check if the client exists, or if the client relogs. -// This is for inheritence since /mob/living will serve most cases. If you need ghosts to use this you'll have to implement that yourself. -/mob/proc/update_client_color() - if(client && client.color) - animate(client, color = null, time = 10) - return - -/mob/proc/swap_hand() - return - -//Throwing stuff -/mob/proc/throw_item(atom/target) - return FALSE - -/mob/proc/will_show_tooltip() - if(alpha <= EFFECTIVE_INVIS) - return FALSE - return TRUE - -/mob/MouseEntered(location, control, params) - if(usr != src && usr.is_preference_enabled(/datum/client_preference/mob_tooltips) && src.will_show_tooltip()) - openToolTip(user = usr, tip_src = src, params = params, title = get_nametag_name(usr), content = get_nametag_desc(usr)) - - ..() - -/mob/MouseDown() - closeToolTip(usr) //No reason not to, really - - ..() - -/mob/MouseExited() - closeToolTip(usr) //No reason not to, really - - ..() - -// Manages a global list of mobs with clients attached, indexed by z-level. -/mob/proc/update_client_z(new_z) // +1 to register, null to unregister. - if(registered_z != new_z) - if(registered_z) - GLOB.players_by_zlevel[registered_z] -= src - if(client) - if(new_z) - GLOB.players_by_zlevel[new_z] += src - registered_z = new_z - else - registered_z = null - -GLOBAL_LIST_EMPTY_TYPED(living_players_by_zlevel, /list) -/mob/living/update_client_z(new_z) - var/precall_reg_z = registered_z - . = ..() // will update registered_z if necessary - if(precall_reg_z != registered_z) // parent did work, let's do work too - if(precall_reg_z) - GLOB.living_players_by_zlevel[precall_reg_z] -= src - if(registered_z) - GLOB.living_players_by_zlevel[registered_z] += src - -/mob/onTransitZ(old_z, new_z) - ..() - update_client_z(new_z) - -/mob/cloak() - . = ..() - if(client && cloaked_selfimage) - client.images += cloaked_selfimage - -/mob/uncloak() - if(client && cloaked_selfimage) - client.images -= cloaked_selfimage - return ..() - -/mob/get_cloaked_selfimage() - var/icon/selficon = getCompoundIcon(src) - selficon.MapColors(0,0,0, 0,0,0, 0,0,0, 1,1,1) //White - var/image/selfimage = image(selficon) - selfimage.color = "#0000FF" - selfimage.alpha = 100 - selfimage.layer = initial(layer) - selfimage.plane = initial(plane) - selfimage.loc = src - - return selfimage - -/mob/proc/GetAltName() - return "" - -/mob/proc/get_ghost(even_if_they_cant_reenter = 0) - if(mind) - return mind.get_ghost(even_if_they_cant_reenter) - -/mob/proc/grab_ghost(force) - if(mind) - return mind.grab_ghost(force = force) +/mob/Destroy()//This makes sure that mobs withGLOB.clients/keys are not just deleted from the game. + mob_list -= src + dead_mob_list -= src + living_mob_list -= src + unset_machine() + qdel(hud_used) + clear_fullscreen() + if(client) + for(var/obj/screen/movable/spell_master/spell_master in spell_masters) + qdel(spell_master) + remove_screen_obj_references() + client.screen = list() + if(mind && mind.current == src) + spellremove(src) + ghostize() + QDEL_NULL(plane_holder) + ..() + return QDEL_HINT_HARDDEL_NOW + +/mob/proc/remove_screen_obj_references() + hands = null + pullin = null + purged = null + internals = null + i_select = null + m_select = null + healths = null + throw_icon = null + pain = null + item_use_icon = null + gun_move_icon = null + gun_setting_icon = null + spell_masters = null + zone_sel = null + +/mob/Initialize() + mob_list += src + if(stat == DEAD) + dead_mob_list += src + else + living_mob_list += src + lastarea = get_area(src) + set_focus(src) // VOREStation Add - Key Handling + hook_vr("mob_new",list(src)) //VOREStation Code + update_transform() // Some mobs may start bigger or smaller than normal. + return ..() + +/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) + + if(!client && !teleop) return + + if (type) + if((type & VISIBLE_MESSAGE) && (is_blind() || paralysis) )//Vision related + if (!( alt )) + return + else + msg = alt + type = alt_type + if ((type & AUDIBLE_MESSAGE) && is_deaf())//Hearing related + if (!( alt )) + return + else + msg = alt + type = alt_type + if ((type & VISIBLE_MESSAGE) && (sdisabilities & BLIND)) + return + // Added voice muffling for Issue 41. + if(stat == UNCONSCIOUS || sleeping > 0) + to_chat(src, "... You can almost hear someone talking ...") + else + to_chat(src,msg) + if(teleop) + to_chat(teleop, create_text_tag("body", "BODY:", teleop.client) + "[msg]") + return + +// Show a message to all mobs and objects in sight of this one +// This would be for visible actions by the src mob +// message is the message output to anyone who can see e.g. "[src] does something!" +// self_message (optional) is what the src mob sees e.g. "You do something!" +// blind_message (optional) is what blind people will hear e.g. "You hear something!" +/mob/visible_message(var/message, var/self_message, var/blind_message, var/list/exclude_mobs = null, var/range = world.view, var/runemessage) + if(self_message) + if(LAZYLEN(exclude_mobs)) + exclude_mobs |= src + else + exclude_mobs = list(src) + src.show_message(self_message, 1, blind_message, 2) + if(isnull(runemessage)) + runemessage = -1 + . = ..(message, blind_message, exclude_mobs, range, runemessage) // Really not ideal that atom/visible_message has different arg numbering :( + +// Returns an amount of power drawn from the object (-1 if it's not viable). +// If drain_check is set it will not actually drain power, just return a value. +// If surge is set, it will destroy/damage the recipient and not return any power. +// Not sure where to define this, so it can sit here for the rest of time. +/atom/proc/drain_power(var/drain_check,var/surge, var/amount = 0) + return -1 + +// Show a message to all mobs and objects in earshot of this one +// This would be for audible actions by the src mob +// message is the message output to anyone who can hear. +// self_message (optional) is what the src mob hears. +// deaf_message (optional) is what deaf people will see. +// hearing_distance (optional) is the range, how many tiles away the message can be heard. +/mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message, var/radio_message, var/runemessage) + + var/range = hearing_distance || world.view + var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE) + + var/list/hearing_mobs = hear["mobs"] + var/list/hearing_objs = hear["objs"] + + if(isnull(runemessage)) + runemessage = -1 // Symmetry with mob/audible_message, despite the fact this one doesn't call parent. Maybe it should! + + if(radio_message) + for(var/obj/O as anything in hearing_objs) + O.hear_talk(src, list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], radio_message)), null) + else + for(var/obj/O as anything in hearing_objs) + O.show_message(message, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE) + + for(var/mob/M as anything in hearing_mobs) + var/msg = message + if(self_message && M==src) + msg = self_message + M.show_message(msg, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE) + if(runemessage != -1) + M.create_chat_message(src, "[runemessage || message]", FALSE, list("emote"), audible = FALSE) + +/mob/proc/findname(msg) + for(var/mob/M in mob_list) + if (M.real_name == text("[]", msg)) + return M + return 0 + +/mob/proc/Life() +// if(organStructure) +// organStructure.ProcessOrgans() + return + +#define UNBUCKLED 0 +#define PARTIALLY_BUCKLED 1 +#define FULLY_BUCKLED 2 +/mob/proc/buckled() + // Preliminary work for a future buckle rewrite, + // where one might be fully restrained (like an elecrical chair), or merely secured (shuttle chair, keeping you safe but not otherwise restrained from acting) + if(!buckled) + return UNBUCKLED + return restrained() ? FULLY_BUCKLED : PARTIALLY_BUCKLED + +/mob/proc/is_blind() + return ((sdisabilities & BLIND) || blinded || incapacitated(INCAPACITATION_KNOCKOUT)) + +/mob/proc/is_deaf() + return ((sdisabilities & DEAF) || ear_deaf || incapacitated(INCAPACITATION_KNOCKOUT)) + +/mob/proc/is_physically_disabled() + return incapacitated(INCAPACITATION_DISABLED) + +/mob/proc/cannot_stand() + return incapacitated(INCAPACITATION_KNOCKDOWN) + +/mob/proc/incapacitated(var/incapacitation_flags = INCAPACITATION_DEFAULT) + if ((incapacitation_flags & INCAPACITATION_STUNNED) && stunned) + return 1 + + if ((incapacitation_flags & INCAPACITATION_FORCELYING) && (weakened || resting)) + return 1 + + if ((incapacitation_flags & INCAPACITATION_KNOCKOUT) && (stat || paralysis || sleeping || (status_flags & FAKEDEATH))) + return 1 + + if((incapacitation_flags & INCAPACITATION_RESTRAINED) && restrained()) + return 1 + + if((incapacitation_flags & (INCAPACITATION_BUCKLED_PARTIALLY|INCAPACITATION_BUCKLED_FULLY))) + var/buckling = buckled() + if(buckling >= PARTIALLY_BUCKLED && (incapacitation_flags & INCAPACITATION_BUCKLED_PARTIALLY)) + return 1 + if(buckling == FULLY_BUCKLED && (incapacitation_flags & INCAPACITATION_BUCKLED_FULLY)) + return 1 + + return 0 + +#undef UNBUCKLED +#undef PARTIALLY_BUCKLED +#undef FULLY_BUCKLED + +/mob/proc/restrained() + return + +/mob/proc/reset_view(atom/A) + if (client) + if (istype(A, /atom/movable)) + client.perspective = EYE_PERSPECTIVE + client.eye = A + else + if (isturf(loc)) + client.eye = client.mob + client.perspective = MOB_PERSPECTIVE + else + client.perspective = EYE_PERSPECTIVE + client.eye = loc + return TRUE + +/mob/verb/pointed(atom/A as mob|obj|turf in view()) + set name = "Point To" + set category = "Object" + + if(!src || !isturf(src.loc) || !(A in view(src.loc))) + return 0 + if(istype(A, /obj/effect/decal/point)) + return 0 + + var/turf/tile = get_turf(A) + if (!tile) + return 0 + + var/turf/our_tile = get_turf(src) + var/obj/visual = new /obj/effect/decal/point(our_tile) + visual.invisibility = invisibility + visual.plane = ABOVE_PLANE + visual.layer = FLY_LAYER + + animate(visual, + pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, + pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, + time = 1.7, + easing = EASE_OUT) + + QDEL_IN(visual, 2 SECONDS) //Better qdel + + face_atom(A) + return 1 + + +/mob/proc/ret_grab(list/L, flag) + return + +/mob/verb/mode() + set name = "Activate Held Object" + set category = "Object" + set src = usr + + return + +/* +/mob/verb/dump_source() + + var/master = "
"
+	for(var/t in typesof(/area))
+		master += text("[]\n", t)
+		//Foreach goto(26)
+	src << browse(master)
+	return
+*/
+
+/mob/verb/memory()
+	set name = "Notes"
+	set category = "IC"
+	if(mind)
+		mind.show_memory(src)
+	else
+		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
+
+/mob/verb/add_memory(msg as message)
+	set name = "Add Note"
+	set category = "IC"
+
+	msg = sanitize(msg)
+
+	if(mind)
+		mind.store_memory(msg)
+	else
+		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
+
+/mob/proc/store_memory(msg as message, popup, sane = 1)
+	msg = copytext(msg, 1, MAX_MESSAGE_LEN)
+
+	if (sane)
+		msg = sanitize(msg)
+
+	if (length(memory) == 0)
+		memory += msg
+	else
+		memory += "
[msg]" + + if (popup) + memory() + +/mob/proc/update_flavor_text() + set src in usr + if(usr != src) + to_chat(usr, "No.") + var/msg = sanitize(tgui_input_text(usr,"Set the flavor text in your 'examine' verb.","Flavor Text",html_decode(flavor_text), multiline = TRUE, prevent_enter = TRUE), extra = 0) //VOREStation Edit: separating out OOC notes + + if(msg != null) + flavor_text = msg + +/mob/proc/warn_flavor_changed() + if(flavor_text && flavor_text != "") // don't spam people that don't use it! + to_chat(src, "

OOC Warning:

") + to_chat(src, "Your flavor text is likely out of date! Change") + +/mob/proc/print_flavor_text() + if (flavor_text && flavor_text != "") + var/msg = replacetext(flavor_text, "\n", " ") + if(length(msg) <= 40) + return "[msg]" + else + return "[copytext_preserve_html(msg, 1, 37)]... More..." + +/* +/mob/verb/help() + set name = "Help" + src << browse('html/help.html', "window=help") + return +*/ + +/mob/proc/set_respawn_timer(var/time) + // Try to figure out what time to use + + // Special cases, can never respawn + if(ticker?.mode?.deny_respawn) + time = -1 + else if(!config.abandon_allowed) + time = -1 + else if(!config.respawn) + time = -1 + + // Special case for observing before game start + else if(ticker?.current_state <= GAME_STATE_SETTING_UP) + time = 1 MINUTE + + // Wasn't given a time, use the config time + else if(!time) + time = config.respawn_time + + var/keytouse = ckey + // Try harder to find a key to use + if(!keytouse && key) + keytouse = ckey(key) + else if(!keytouse && mind?.key) + keytouse = ckey(mind.key) + + GLOB.respawn_timers[keytouse] = world.time + time + +/mob/observer/dead/set_respawn_timer() + if(config.antag_hud_restricted && has_enabled_antagHUD) + ..(-1) + else + return // Don't set it, no need + +/mob/verb/abandon_mob() + set name = "Return to Menu" + set category = "OOC" + + if(stat != DEAD || !ticker) + to_chat(usr, "You must be dead to use this!") + return + + // Final chance to abort "respawning" + if(mind && timeofdeath) // They had spawned before + var/choice = tgui_alert(usr, "Returning to the menu will prevent your character from being revived in-round. Are you sure?", "Confirmation", list("No, wait", "Yes, leave")) + if(choice == "No, wait") + return + else if(mind.assigned_role) + var/extra_check = tgui_alert(usr, "Do you want to Quit This Round before you return to lobby? This will properly remove you from manifest, as well as prevent resleeving.","Quit This Round",list("Quit Round","Cancel")) + if(extra_check == "Quit Round") + //Update any existing objectives involving this mob. + for(var/datum/objective/O in all_objectives) + if(O.target == src.mind) + if(O.owner && O.owner.current) + to_chat(O.owner.current,"You get the feeling your target is no longer within your reach...") + qdel(O) + + //Resleeving cleanup + if(mind) + SStranscore.leave_round(src) + + //Job slot cleanup + var/job = src.mind.assigned_role + job_master.FreeRole(job) + + //Their objectives cleanup + if(src.mind.objectives.len) + qdel(src.mind.objectives) + src.mind.special_role = null + + //Cut the PDA manifest (ugh) + if(PDA_Manifest.len) + PDA_Manifest.Cut() + for(var/datum/data/record/R in data_core.medical) + if((R.fields["name"] == src.real_name)) + qdel(R) + for(var/datum/data/record/T in data_core.security) + if((T.fields["name"] == src.real_name)) + qdel(T) + for(var/datum/data/record/G in data_core.general) + if((G.fields["name"] == src.real_name)) + qdel(G) + + //This removes them from being 'active' list on join screen + src.mind.assigned_role = null + to_chat(src,"Your job has been free'd up, and you can rejoin as another character or quit. Thanks for properly quitting round, it helps the server!") + + // Beyond this point, you're going to respawn + to_chat(usr, config.respawn_message) + + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + return + client.screen.Cut() + client.screen += client.void + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + return + + announce_ghost_joinleave(client, 0) + + var/mob/new_player/M = new /mob/new_player() + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + qdel(M) + return + + M.key = key + if(M.mind) + M.mind.reset() + return + +/client/verb/changes() + set name = "Changelog" + set category = "OOC" + // CHOMPedit Start - Better Changelog + //src << browse('html/changelog.html', "window=changes;size=675x650") + //return + + if(!GLOB.changelog_tgui) + GLOB.changelog_tgui = new /datum/changelog() + GLOB.changelog_tgui.tgui_interact(usr) + // CHOMPedit END + if(prefs.lastchangelog != changelog_hash) + prefs.lastchangelog = changelog_hash + SScharacter_setup.queue_preferences_save(prefs) + // winset(src, "rpane.changelog", "background-color=none;font-style=;") //ChompREMOVE + +/mob/verb/observe() + set name = "Observe" + set category = "OOC" + var/is_admin = 0 + + if(client.holder && (client.holder.rights & R_ADMIN|R_EVENT)) + is_admin = 1 + else if(stat != DEAD || istype(src, /mob/new_player)) + to_chat(usr, "You must be observing to use this!") + return + + if(is_admin && stat == DEAD) + is_admin = 0 + + var/list/targets = list() + + + targets += observe_list_format(nuke_disks) + targets += observe_list_format(GLOB.all_singularities) //CHOMP Edit + targets += getmobs() + targets += observe_list_format(sortAtom(mechas_list)) + targets += observe_list_format(SSshuttles.ships) + + client.perspective = EYE_PERSPECTIVE + + var/eye_name = null + + var/ok = "[is_admin ? "Admin Observe" : "Observe"]" + eye_name = tgui_input_list(usr, "Select something to [ok]:", "Select Target", targets) + + if (!eye_name) + return + + var/mob/mob_eye = targets[eye_name] + + if(client && mob_eye) + client.eye = mob_eye + if (is_admin) + client.adminobs = 1 + if(mob_eye == client.mob || client.eye == client.mob) + client.adminobs = 0 + +/mob/verb/cancel_camera() + set name = "Cancel Camera View" + set category = "OOC" + unset_machine() + reset_view(null) + +/mob/Topic(href, href_list) + if(href_list["mach_close"]) + var/t1 = text("window=[href_list["mach_close"]]") + unset_machine() + src << browse(null, t1) + + if(href_list["flavor_more"]) + usr << browse(text("[][]", name, replacetext(flavor_text, "\n", "
")), text("window=[];size=500x200", name)) + onclose(usr, "[name]") + if(href_list["flavor_change"]) + update_flavor_text() +// ..() + return + + +/mob/proc/pull_damage() + return 0 + +/mob/verb/stop_pulling() + + set name = "Stop Pulling" + set category = "IC" + + if(pulling) + if(ishuman(pulling)) + var/mob/living/carbon/human/H = pulling + visible_message(SPAN_WARNING("\The [src] lets go of \the [H]."), SPAN_NOTICE("You let go of \the [H]."), exclude_mobs = list(H)) + if(!H.stat) + to_chat(H, SPAN_WARNING("\The [src] lets go of you.")) + pulling.pulledby = null + pulling = null + if(pullin) + pullin.icon_state = "pull0" + +/mob/proc/start_pulling(var/atom/movable/AM) + + if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! + return + + if (AM.anchored) + to_chat(src, "It won't budge!") + return + + var/mob/M = AM + if(ismob(AM)) + + if(!can_pull_mobs || !can_pull_size) + to_chat(src, "They won't budge!") + return + + if((mob_size < M.mob_size) && (can_pull_mobs != MOB_PULL_LARGER)) + to_chat(src, "[M] is too large for you to move!") + return + + if((mob_size == M.mob_size) && (can_pull_mobs == MOB_PULL_SMALLER)) + to_chat(src, "[M] is too heavy for you to move!") + return + + // If your size is larger than theirs and you have some + // kind of mob pull value AT ALL, you will be able to pull + // them, so don't bother checking that explicitly. + + if(M.grabbed_by.len) + // Only start pulling when nobody else has a grab on them + . = 1 + for(var/obj/item/weapon/grab/G in M.grabbed_by) + if(G.assailant != usr) + . = 0 + else + qdel(G) + if(!.) + to_chat(src, "Somebody has a grip on them!") + return + + if(!iscarbon(src)) + M.LAssailant = null + else + M.LAssailant = usr + + else if(isobj(AM)) + var/obj/I = AM + if(!can_pull_size || can_pull_size < I.w_class) + to_chat(src, "It won't budge!") + return + + if(pulling) + var/pulling_old = pulling + stop_pulling() + // Are we pulling the same thing twice? Just stop pulling. + if(pulling_old == AM) + return + + src.pulling = AM + AM.pulledby = src + + if(pullin) + pullin.icon_state = "pull1" + + if(ishuman(AM)) + var/mob/living/carbon/human/H = AM + if(H.lying) // If they're on the ground we're probably dragging their arms to move them + visible_message(SPAN_WARNING("\The [src] leans down and grips \the [H]'s arms."), SPAN_NOTICE("You lean down and grip \the [H]'s arms."), exclude_mobs = list(H)) + if(!H.stat) + to_chat(H, SPAN_WARNING("\The [src] leans down and grips your arms.")) + else //Otherwise we're probably just holding their arm to lead them somewhere + visible_message(SPAN_WARNING("\The [src] grips \the [H]'s arm."), SPAN_NOTICE("You grip \the [H]'s arm."), exclude_mobs = list(H)) + if(!H.stat) + to_chat(H, SPAN_WARNING("\The [src] grips your arm.")) + playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25) //Quieter than hugging/grabbing but we still want some audio feedback + + if(H.pull_damage()) + to_chat(src, "Pulling \the [H] in their current condition would probably be a bad idea.") + + //Attempted fix for people flying away through space when cuffed and dragged. + if(ismob(AM)) + var/mob/pulled = AM + pulled.inertia_dir = 0 + +/mob/proc/can_use_hands() + return + +/mob/proc/is_active() + return (0 >= usr.stat) + +/mob/proc/is_dead() + return stat == DEAD + +/mob/proc/is_mechanical() + if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) + return 1 + return istype(src, /mob/living/silicon) || get_species() == "Machine" + +/mob/proc/is_ready() + return client && !!mind + +/mob/proc/get_gender() + return gender + +/mob/proc/name_gender() + return gender + +/mob/proc/see(message) + if(!is_active()) + return 0 + to_chat(src,message) + return 1 + +/mob/proc/show_viewers(message) + for(var/mob/M in viewers()) + M.see(message) + +/mob/Stat() + ..() + . = (is_client_active(10 MINUTES)) + + if(.) + if(statpanel("Status")) + stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") + if(ticker && ticker.current_state != GAME_STATE_PREGAME) + stat("Station Time", stationtime2text()) + var/date = "[stationdate2text()], [capitalize(world_time_season)]" + stat("Station Date", date) + stat("Round Duration", roundduration2text()) + + if(client.holder) + if(statpanel("Status")) + stat("Location:", "([x], [y], [z]) [loc]") + stat("CPU:","[world.cpu]") + stat("Instances:","[world.contents.len]") + stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") + stat("Keys Held", keys2text(client.move_keys_held | client.mod_keys_held)) + stat("Next Move ADD", dirs2text(client.next_move_dir_add)) + stat("Next Move SUB", dirs2text(client.next_move_dir_sub)) + + if(statpanel("MC")) + stat("Location:", "([x], [y], [z]) [loc]") + stat("CPU:","[world.cpu]") + stat("Instances:","[world.contents.len]") + stat("World Time:", world.time) + stat("Real time of day:", REALTIMEOFDAY) + stat(null) + if(GLOB) + GLOB.stat_entry() + else + stat("Globals:", "ERROR") + if(Master) + Master.stat_entry() + else + stat("Master Controller:", "ERROR") + if(Failsafe) + Failsafe.stat_entry() + else + stat("Failsafe Controller:", "ERROR") + if(Master) + stat(null) + for(var/datum/controller/subsystem/SS in Master.subsystems) + SS.stat_entry() + + // CHOMPedit - Ticket System + //if(statpanel("Tickets")) + //GLOB.ahelp_tickets.stat_entry() + + + if(length(GLOB.sdql2_queries)) + if(statpanel("SDQL2")) + stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj) + for(var/datum/SDQL2_query/Q as anything in GLOB.sdql2_queries) + Q.generate_stat() + + if(has_mentor_powers(client) || client.holder) // CHOMPedit - Ticket System + if(statpanel("Tickets")) + GLOB.tickets.stat_entry() // CHOMPedit - Ticket System + + if(listed_turf && client) + if(!TurfAdjacent(listed_turf)) + listed_turf = null + else + if(statpanel("Turf")) + stat(listed_turf) + for(var/atom/A in listed_turf) + if(!A.mouse_opacity) + continue + if(A.invisibility > see_invisible) + continue + if(is_type_in_list(A, shouldnt_see)) + continue + if(A.plane > plane) + continue + stat(A) + + +// facing verbs +/mob/proc/canface() +// if(!canmove) return 0 //VOREStation Edit. Redundant check that only affects conscious proning, actual inability to turn and shift around handled by actual inabilities. + if(stat) return 0 + if(anchored) return 0 + if(transforming) return 0 + return 1 + +// Not sure what to call this. Used to check if humans are wearing an AI-controlled exosuit and hence don't need to fall over yet. +/mob/proc/can_stand_overridden() + return 0 + +//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. +/mob/proc/update_canmove() + return canmove + + +/mob/proc/facedir(var/ndir) + if(!canface() || (client && (client.moving || !checkMoveCooldown()))) + DEBUG_INPUT("Denying Facedir for [src] (moving=[client?.moving])") + return 0 + set_dir(ndir) + if(buckled && buckled.buckle_movable) + buckled.set_dir(ndir) + setMoveCooldown(movement_delay()) + return 1 + + +/mob/verb/eastface() + set hidden = 1 + return facedir(client.client_dir(EAST)) + + +/mob/verb/westface() + set hidden = 1 + return facedir(client.client_dir(WEST)) + + +/mob/verb/northface() + set hidden = 1 + return facedir(client.client_dir(NORTH)) + + +/mob/verb/southface() + set hidden = 1 + return facedir(client.client_dir(SOUTH)) + + +//This might need a rename but it should replace the can this mob use things check +/mob/proc/IsAdvancedToolUser() + return 0 + +/mob/proc/Stun(amount) + if(status_flags & CANSTUN) + facing_dir = null + stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun + update_canmove() //updates lying, canmove and icons + return + +/mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" + if(status_flags & CANSTUN) + stunned = max(amount,0) + update_canmove() //updates lying, canmove and icons + return + +/mob/proc/AdjustStunned(amount) + if(status_flags & CANSTUN) + stunned = max(stunned + amount,0) + update_canmove() //updates lying, canmove and icons + return + +/mob/proc/Weaken(amount) + if(status_flags & CANWEAKEN) + facing_dir = null + weakened = max(max(weakened,amount),0) + update_canmove() //updates lying, canmove and icons + return + +/mob/proc/SetWeakened(amount) + if(status_flags & CANWEAKEN) + weakened = max(amount,0) + update_canmove() //can you guess what this does yet? + return + +/mob/proc/AdjustWeakened(amount) + if(status_flags & CANWEAKEN) + weakened = max(weakened + amount,0) + update_canmove() //updates lying, canmove and icons + return + +/mob/proc/Paralyse(amount) + if(status_flags & CANPARALYSE) + facing_dir = null + paralysis = max(max(paralysis,amount),0) + return + +/mob/proc/SetParalysis(amount) + if(status_flags & CANPARALYSE) + paralysis = max(amount,0) + return + +/mob/proc/AdjustParalysis(amount) + if(status_flags & CANPARALYSE) + paralysis = max(paralysis + amount,0) + return + +/mob/proc/Sleeping(amount) + facing_dir = null + sleeping = max(max(sleeping,amount),0) + return + +/mob/proc/SetSleeping(amount) + sleeping = max(amount,0) + return + +/mob/proc/AdjustSleeping(amount) + sleeping = max(sleeping + amount,0) + return + +/mob/proc/Confuse(amount) + confused = max(max(confused,amount),0) + return + +/mob/proc/SetConfused(amount) + confused = max(amount,0) + return + +/mob/proc/AdjustConfused(amount) + confused = max(confused + amount,0) + return + +/mob/proc/Blind(amount) + eye_blind = max(max(eye_blind,amount),0) + return + +/mob/proc/SetBlinded(amount) + eye_blind = max(amount,0) + return + +/mob/proc/AdjustBlinded(amount) + eye_blind = max(eye_blind + amount,0) + return + +/mob/proc/Resting(amount) + facing_dir = null + resting = max(max(resting,amount),0) + update_canmove() + return + +/mob/proc/SetResting(amount) + resting = max(amount,0) + update_canmove() + return + +/mob/proc/AdjustResting(amount) + resting = max(resting + amount,0) + update_canmove() + return + +/mob/proc/AdjustLosebreath(amount) + losebreath = CLAMP(losebreath + amount, 0, 25) + +/mob/proc/SetLosebreath(amount) + losebreath = CLAMP(amount, 0, 25) + +/mob/proc/get_species() + return "" + +/mob/proc/flash_weak_pain() + flick("weak_pain",pain) + +/mob/proc/get_visible_implants(var/class = 0) + var/list/visible_implants = list() + for(var/obj/item/O in embedded) + if(O.w_class > class) + visible_implants += O + return visible_implants + +/mob/proc/embedded_needs_process() + return (embedded.len > 0) + +/mob/proc/yank_out_object() + set category = "Object" + set name = "Yank out object" + set desc = "Remove an embedded item at the cost of bleeding and pain." + set src in view(1) + + if(!isliving(usr) || !usr.checkClickCooldown()) + return + usr.setClickCooldown(20) + + if(usr.stat == 1) + to_chat(usr, "You are unconcious and cannot do that!") + return + + if(usr.restrained()) + to_chat(usr, "You are restrained and cannot do that!") + return + + var/mob/S = src + var/mob/U = usr + var/list/valid_objects = list() + var/self = null + + if(S == U) + self = 1 // Removing object from yourself. + + valid_objects = get_visible_implants(0) + if(!valid_objects.len) + if(self) + to_chat(src, "You have nothing stuck in your body that is large enough to remove.") + else + to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.") + return + + var/obj/item/weapon/selection = tgui_input_list(usr, "What do you want to yank out?", "Embedded objects", valid_objects) + + if(self) + to_chat(src, "You attempt to get a good grip on [selection] in your body.") + else + to_chat(U, "You attempt to get a good grip on [selection] in [S]'s body.") + + if(!do_after(U, 30)) + return + if(!selection || !S || !U) + return + + if(self) + visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") + else + visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.") + valid_objects = get_visible_implants(0) + if(valid_objects.len == 1) //Yanking out last object - removing verb. + src.verbs -= /mob/proc/yank_out_object + clear_alert("embeddedobject") + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + var/obj/item/organ/external/affected + + for(var/obj/item/organ/external/organ in H.organs) //Grab the organ holding the implant. + for(var/obj/item/O in organ.implants) + if(O == selection) + affected = organ + + affected.implants -= selection + H.shock_stage+=20 + affected.take_damage((selection.w_class * 3), 0, 0, 1, "Embedded object extraction") + + if(prob(selection.w_class * 5) && (affected.robotic < ORGAN_ROBOT)) //I'M SO ANEMIC I COULD JUST -DIE-. + var/datum/wound/internal_bleeding/I = new (min(selection.w_class * 5, 15)) + affected.wounds += I + H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 50) + + if (ishuman(U)) + var/mob/living/carbon/human/human_user = U + human_user.bloody_hands(H) + + else if(issilicon(src)) + var/mob/living/silicon/robot/R = src + R.embedded -= selection + R.adjustBruteLoss(5) + R.adjustFireLoss(10) + + selection.forceMove(get_turf(src)) + U.put_in_hands(selection) + + for(var/obj/item/weapon/O in pinned) + if(O == selection) + pinned -= O + if(!pinned.len) + anchored = FALSE + return 1 + +//Check for brain worms in head. +/mob/proc/has_brain_worms() + + for(var/I in contents) + if(istype(I,/mob/living/simple_mob/animal/borer)) + return I + + return 0 + +/mob/proc/updateicon() + return + +// Please always use this proc, never just set the var directly. +/mob/proc/set_stat(var/new_stat) + . = (stat != new_stat) + stat = new_stat + +/mob/verb/face_direction() + + set name = "Face Direction" + set category = "IC" + set src = usr + + set_face_dir() + + if(!facing_dir) + to_chat(usr, "You are now not facing anything.") + else + to_chat(usr, "You are now facing [dir2text(facing_dir)].") + +/mob/proc/set_face_dir(var/newdir) + if(newdir == facing_dir) + facing_dir = null + else if(newdir) + set_dir(newdir) + facing_dir = newdir + else if(facing_dir) + facing_dir = null + else + set_dir(dir) + facing_dir = dir + +/mob/set_dir() + if(facing_dir) + if(!canface() || lying || buckled || restrained()) + facing_dir = null + else if(dir != facing_dir) + return ..(facing_dir) + else + return ..() + +/mob/verb/northfaceperm() + set hidden = 1 + set_face_dir(client.client_dir(NORTH)) + +/mob/verb/southfaceperm() + set hidden = 1 + set_face_dir(client.client_dir(SOUTH)) + +/mob/verb/eastfaceperm() + set hidden = 1 + set_face_dir(client.client_dir(EAST)) + +/mob/verb/westfaceperm() + set hidden = 1 + set_face_dir(client.client_dir(WEST)) + +// Begin VOREstation edit +/mob/verb/shiftnorth() + set hidden = TRUE + if(!canface()) + return FALSE + if(pixel_y <= (default_pixel_y + 16)) + pixel_y++ + is_shifted = TRUE + +/mob/verb/shiftsouth() + set hidden = TRUE + if(!canface()) + return FALSE + if(pixel_y >= (default_pixel_y - 16)) + pixel_y-- + is_shifted = TRUE + +/mob/verb/shiftwest() + set hidden = TRUE + if(!canface()) + return FALSE + if(pixel_x >= (default_pixel_x - 16)) + pixel_x-- + is_shifted = TRUE + +/mob/verb/shifteast() + set hidden = TRUE + if(!canface()) + return FALSE + if(pixel_x <= (default_pixel_x + 16)) + pixel_x++ + is_shifted = TRUE + +/mob/verb/planeup() + set hidden = TRUE + if(!canface()) + return FALSE + if(plane >= MOB_PLANE + 3) //Don't bother going too high! + return + if(layer == MOB_LAYER) //Become higher + layer = ABOVE_MOB_LAYER + plane += 1 //Increase the plane + if(plane == MOB_PLANE) //Return to normal + layer = MOB_LAYER + is_shifted = TRUE + +/mob/verb/planedown() + set hidden = TRUE + if(!canface()) + return FALSE + if(plane <= MOB_PLANE - 3) //Don't bother going too low! + return + if(layer == MOB_LAYER) //Become lower + layer = BELOW_MOB_LAYER + plane -= 1 //Decrease the plane + if(plane == MOB_PLANE) //Return to normal + layer = MOB_LAYER + is_shifted = TRUE + +// End VOREstation edit + +/mob/proc/adjustEarDamage() + return + +/mob/proc/setEarDamage() + return + +// Set client view distance (size of client's screen). Returns TRUE if anything changed. +/mob/proc/set_viewsize(var/new_view = world.view) + if (client && new_view != client.view) + client.view = new_view + return TRUE + return FALSE + +//Throwing stuff + +/mob/proc/toggle_throw_mode() + if (src.in_throw_mode) + throw_mode_off() + else + throw_mode_on() + +/mob/proc/throw_mode_off() + src.in_throw_mode = 0 + if(src.throw_icon) //in case we don't have the HUD and we use the hotkey + src.throw_icon.icon_state = "act_throw_off" + +/mob/proc/throw_mode_on() + src.in_throw_mode = 1 + if(src.throw_icon) + src.throw_icon.icon_state = "act_throw_on" + +/mob/proc/isSynthetic() + return 0 + +/mob/proc/is_muzzled() + return 0 + +//Exploitable Info Update + +/mob/proc/amend_exploitable(var/obj/item/I) + if(istype(I)) + exploit_addons |= I + var/exploitmsg = html_decode("\n" + "Has " + I.name + ".") + exploit_record += exploitmsg + +/client/proc/check_has_body_select() + return mob && mob.hud_used && istype(mob.zone_sel, /obj/screen/zone_sel) + +/client/verb/body_toggle_head() + set name = "body-toggle-head" + set hidden = 1 + toggle_zone_sel(list(BP_HEAD, O_EYES, O_MOUTH)) + +/client/verb/body_r_arm() + set name = "body-r-arm" + set hidden = 1 + toggle_zone_sel(list(BP_R_ARM,BP_R_HAND)) + +/client/verb/body_l_arm() + set name = "body-l-arm" + set hidden = 1 + toggle_zone_sel(list(BP_L_ARM,BP_L_HAND)) + +/client/verb/body_chest() + set name = "body-chest" + set hidden = 1 + toggle_zone_sel(list(BP_TORSO)) + +/client/verb/body_groin() + set name = "body-groin" + set hidden = 1 + toggle_zone_sel(list(BP_GROIN)) + +/client/verb/body_r_leg() + set name = "body-r-leg" + set hidden = 1 + toggle_zone_sel(list(BP_R_LEG,BP_R_FOOT)) + +/client/verb/body_l_leg() + set name = "body-l-leg" + set hidden = 1 + toggle_zone_sel(list(BP_L_LEG,BP_L_FOOT)) + +/client/proc/toggle_zone_sel(list/zones) + if(!check_has_body_select()) + return + var/obj/screen/zone_sel/selector = mob.zone_sel + selector.set_selected_zone(next_in_list(mob.zone_sel.selecting,zones)) + +// This handles setting the client's color variable, which makes everything look a specific color. +// This proc is here so it can be called without needing to check if the client exists, or if the client relogs. +// This is for inheritence since /mob/living will serve most cases. If you need ghosts to use this you'll have to implement that yourself. +/mob/proc/update_client_color() + if(client && client.color) + animate(client, color = null, time = 10) + return + +/mob/proc/swap_hand() + return + +//Throwing stuff +/mob/proc/throw_item(atom/target) + return FALSE + +/mob/proc/will_show_tooltip() + if(alpha <= EFFECTIVE_INVIS) + return FALSE + return TRUE + +/mob/MouseEntered(location, control, params) + if(usr != src && usr.is_preference_enabled(/datum/client_preference/mob_tooltips) && src.will_show_tooltip()) + openToolTip(user = usr, tip_src = src, params = params, title = get_nametag_name(usr), content = get_nametag_desc(usr)) + + ..() + +/mob/MouseDown() + closeToolTip(usr) //No reason not to, really + + ..() + +/mob/MouseExited() + closeToolTip(usr) //No reason not to, really + + ..() + +// Manages a global list of mobs with clients attached, indexed by z-level. +/mob/proc/update_client_z(new_z) // +1 to register, null to unregister. + if(registered_z != new_z) + if(registered_z) + GLOB.players_by_zlevel[registered_z] -= src + if(client) + if(new_z) + GLOB.players_by_zlevel[new_z] += src + registered_z = new_z + else + registered_z = null + +GLOBAL_LIST_EMPTY_TYPED(living_players_by_zlevel, /list) +/mob/living/update_client_z(new_z) + var/precall_reg_z = registered_z + . = ..() // will update registered_z if necessary + if(precall_reg_z != registered_z) // parent did work, let's do work too + if(precall_reg_z) + GLOB.living_players_by_zlevel[precall_reg_z] -= src + if(registered_z) + GLOB.living_players_by_zlevel[registered_z] += src + +/mob/onTransitZ(old_z, new_z) + ..() + update_client_z(new_z) + +/mob/cloak() + . = ..() + if(client && cloaked_selfimage) + client.images += cloaked_selfimage + +/mob/uncloak() + if(client && cloaked_selfimage) + client.images -= cloaked_selfimage + return ..() + +/mob/get_cloaked_selfimage() + var/icon/selficon = getCompoundIcon(src) + selficon.MapColors(0,0,0, 0,0,0, 0,0,0, 1,1,1) //White + var/image/selfimage = image(selficon) + selfimage.color = "#0000FF" + selfimage.alpha = 100 + selfimage.layer = initial(layer) + selfimage.plane = initial(plane) + selfimage.loc = src + + return selfimage + +/mob/proc/GetAltName() + return "" + +/mob/proc/get_ghost(even_if_they_cant_reenter = 0) + if(mind) + return mind.get_ghost(even_if_they_cant_reenter) + +/mob/proc/grab_ghost(force) + if(mind) + return mind.grab_ghost(force = force) diff --git a/interface/skin.dmf b/interface/skin.dmf index b44b9331fa..697bda534f 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1,5 +1,5 @@ macro "borghotkeymode" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=borgmacro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5\"" elem @@ -20,58 +20,58 @@ macro "borghotkeymode" elem name = "Alt+UP" command = "KeyUp Alt" - elem + elem name = "NORTHEAST" command = ".northeast" - elem + elem name = "SOUTHEAST" command = ".southeast" - elem + elem name = "SOUTHWEST" command = ".southwest" - elem + elem name = "NORTHWEST" command = ".northwest" - elem + elem name = "ALT+WEST" command = "westfaceperm" - elem + elem name = "CTRL+WEST" command = "westface" - elem + elem name = "West" command = "KeyDown West" elem name = "West+UP" command = "KeyUp West" - elem + elem name = "ALT+NORTH" command = "northfaceperm" - elem + elem name = "CTRL+NORTH" command = "northface" - elem + elem name = "North" command = "KeyDown North" elem name = "North+UP" command = "KeyUp North" - elem + elem name = "ALT+EAST" command = "eastfaceperm" - elem + elem name = "CTRL+EAST" command = "eastface" - elem + elem name = "East" command = "KeyDown East" elem name = "East+UP" command = "KeyUp East" - elem + elem name = "ALT+SOUTH" command = "southfaceperm" - elem + elem name = "CTRL+SOUTH" command = "southface" elem @@ -83,91 +83,91 @@ macro "borghotkeymode" elem name = "CTRL+SHIFT+NORTH" command = "shiftnorth" - elem + elem name = "CTRL+SHIFT+SOUTH" command = "shiftsouth" - elem + elem name = "CTRL+SHIFT+WEST" command = "shiftwest" - elem + elem name = "CTRL+SHIFT+EAST" command = "shifteast" - elem + elem name = "INSERT" command = "a-intent right" - elem + elem name = "DELETE" command = "delete-key-pressed" - elem + elem name = "1" command = "toggle-module 1" - elem + elem name = "CTRL+1" command = "toggle-module 1" - elem + elem name = "2" command = "toggle-module 2" - elem + elem name = "CTRL+2" command = "toggle-module 2" - elem + elem name = "3" command = "toggle-module 3" - elem + elem name = "CTRL+3" command = "toggle-module 3" - elem + elem name = "4" command = "a-intent left" - elem + elem name = "CTRL+4" command = "a-intent left" - elem + elem name = "5" command = ".me" - elem + elem name = "6" command = ".Subtle" - elem + elem name = "A" command = "KeyDown A" elem name = "A+UP" command = "KeyUp A" - elem + elem name = "D" command = "KeyDown D" elem name = "D+UP" command = "KeyUp D" - elem + elem name = "F" command = "a-intent left" - elem + elem name = "CTRL+F" command = "a-intent left" - elem + elem name = "G" command = "a-intent right" - elem + elem name = "CTRL+G" command = "a-intent right" - elem + elem name = "J" command = "toggle-gun-mode" - elem + elem name = "CTRL+J" command = "toggle-gun-mode" - elem + elem name = "Q" command = "unequip-module" - elem + elem name = "CTRL+Q" command = "unequip-module" - elem + elem name = "R" command = ".southwest" - elem + elem name = "CTRL+R" command = ".southwest" elem "s_key" @@ -176,7 +176,7 @@ macro "borghotkeymode" elem name = "S+UP" command = "KeyUp S" - elem + elem name = "T" command = ".say" elem "w_key" @@ -185,90 +185,96 @@ macro "borghotkeymode" elem name = "W+UP" command = "KeyUp W" - elem + elem name = "X" command = ".northeast" - elem + elem name = "CTRL+X" command = ".northeast" - elem + elem name = "Y" command = ".Whisper" - elem + elem name = "CTRL+Y" command = ".Whisper" - elem + elem name = "Z" command = "Activate-Held-Object" - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" - elem + elem name = "U" command = "Rest" - elem + elem name = "NUMPAD1" command = "body-r-leg" - elem + elem name = "NUMPAD2" command = "body-groin" - elem + elem name = "NUMPAD3" command = "body-l-leg" - elem + elem name = "NUMPAD4" command = "body-r-arm" - elem + elem name = "NUMPAD5" command = "body-chest" - elem + elem name = "NUMPAD6" command = "body-l-arm" - elem + elem name = "NUMPAD8" command = "body-toggle-head" - elem + elem name = "F1" command = "request-help" - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" - elem + elem name = "F2" command = "ooc" - elem + elem name = "F2+REP" command = ".screenshot auto" - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" - elem + elem name = "F3" command = ".say" - elem + elem name = "F4" command = ".me" - elem + elem name = "F5" command = "asay" - elem + elem name = "F6" command = "Player-Panel-New" - elem + elem name = "F7" command = "Admin-PM" - elem + elem name = "F8" command = "Invisimin" - elem + elem name = "F12" command = "F12" + elem + name = "CTRL+SHIFT+ADD" + command = "planeup" + elem + name = "CTRL+SHIFT+SUBTRACT" + command = "planedown" macro "macro" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=hotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true\"" - elem + elem name = "Shift" command = "KeyDown Shift" elem @@ -286,58 +292,58 @@ macro "macro" elem name = "Alt+UP" command = "KeyUp Alt" - elem + elem name = "NORTHEAST" command = ".northeast" - elem + elem name = "SOUTHEAST" command = ".southeast" - elem + elem name = "SOUTHWEST" command = ".southwest" - elem + elem name = "NORTHWEST" command = ".northwest" - elem + elem name = "ALT+WEST" command = "westfaceperm" - elem + elem name = "CTRL+WEST" command = "westface" - elem + elem name = "West" command = "KeyDown West" elem name = "West+UP" command = "KeyUp West" - elem + elem name = "ALT+NORTH" command = "northfaceperm" - elem + elem name = "CTRL+NORTH" command = "northface" - elem + elem name = "North" command = "KeyDown North" elem name = "North+UP" command = "KeyUp North" - elem + elem name = "ALT+EAST" command = "eastfaceperm" - elem + elem name = "CTRL+EAST" command = "eastface" - elem + elem name = "East" command = "KeyDown East" elem name = "East+UP" command = "KeyUp East" - elem + elem name = "ALT+SOUTH" command = "southfaceperm" - elem + elem name = "CTRL+SOUTH" command = "southface" elem @@ -349,150 +355,156 @@ macro "macro" elem name = "CTRL+SHIFT+NORTH" command = "shiftnorth" - elem + elem name = "CTRL+SHIFT+SOUTH" command = "shiftsouth" - elem + elem name = "CTRL+SHIFT+WEST" command = "shiftwest" - elem + elem name = "CTRL+SHIFT+EAST" command = "shifteast" - elem + elem name = "INSERT" command = "a-intent right" - elem + elem name = "DELETE" command = "delete-key-pressed" - elem + elem name = "CTRL+1" command = "a-intent help" - elem + elem name = "CTRL+2" command = "a-intent disarm" - elem + elem name = "CTRL+3" command = "a-intent grab" - elem + elem name = "CTRL+4" command = "a-intent harm" - elem + elem name = "CTRL+A" command = "KeyDown A" elem name = "CTRL+A+UP" command = "KeyUp A" - elem + elem name = "CTRL+D" command = "KeyDown D" elem name = "CTRL+D+UP" command = "KeyUp D" - elem + elem name = "CTRL+E" command = "quick-equip" - elem + elem name = "CTRL+F" command = "a-intent left" - elem + elem name = "CTRL+G" command = "a-intent right" - elem + elem name = "CTRL+Q" command = ".northwest" - elem + elem name = "CTRL+R" command = ".southwest" - elem + elem name = "CTRL+S" command = "KeyDown S" elem name = "CTRL+S+UP" command = "KeyUp S" - elem + elem name = "CTRL+W" command = "KeyDown W" elem name = "CTRL+W+UP" command = "KeyUp W" - elem + elem name = "CTRL+X" command = ".northeast" - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" - elem + elem name = "CTRL+U" command = "Rest" - elem + elem name = "CTRL+B" command = "Resist" - elem + elem name = "CTRL+NUMPAD1" command = "body-r-leg" - elem + elem name = "CTRL+NUMPAD2" command = "body-groin" - elem + elem name = "CTRL+NUMPAD3" command = "body-l-leg" - elem + elem name = "CTRL+NUMPAD4" command = "body-r-arm" - elem + elem name = "CTRL+NUMPAD5" command = "body-chest" - elem + elem name = "CTRL+NUMPAD6" command = "body-l-arm" - elem + elem name = "CTRL+NUMPAD8" command = "body-toggle-head" - elem + elem name = "F1" command = "request-help" - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" - elem + elem name = "F2" command = "ooc" - elem + elem name = "F2+REP" command = ".screenshot auto" - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" - elem + elem name = "F3" command = ".say" - elem + elem name = "F4" command = ".me" - elem + elem name = "F5" command = "asay" - elem + elem name = "F6" command = "Player-Panel-New" - elem + elem name = "F7" command = "Admin-PM" - elem + elem name = "F8" command = "Invisimin" - elem + elem name = "F12" command = "F12" + elem + name = "CTRL+SHIFT+ADD" + command = "planeup" + elem + name = "CTRL+SHIFT+SUBTRACT" + command = "planedown" macro "hotkeymode" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=macro hotkey_toggle.is-checked=false input.focus=true\"" - elem + elem name = "Shift" command = "KeyDown Shift" elem @@ -510,58 +522,58 @@ macro "hotkeymode" elem name = "Alt+UP" command = "KeyUp Alt" - elem + elem name = "NORTHEAST" command = ".northeast" - elem + elem name = "SOUTHEAST" command = ".southeast" - elem + elem name = "SOUTHWEST" command = ".southwest" - elem + elem name = "NORTHWEST" command = ".northwest" - elem + elem name = "ALT+WEST" command = "westfaceperm" - elem + elem name = "CTRL+WEST" command = "westface" - elem + elem name = "West" command = "KeyDown West" elem name = "West+UP" command = "KeyUp West" - elem + elem name = "ALT+NORTH" command = "northfaceperm" - elem + elem name = "CTRL+NORTH" command = "northface" - elem + elem name = "North" command = "KeyDown North" elem name = "North+UP" command = "KeyUp North" - elem + elem name = "ALT+EAST" command = "eastfaceperm" - elem + elem name = "CTRL+EAST" command = "eastface" - elem + elem name = "East" command = "KeyDown East" elem name = "East+UP" command = "KeyUp East" - elem + elem name = "ALT+SOUTH" command = "southfaceperm" - elem + elem name = "CTRL+SOUTH" command = "southface" elem @@ -573,103 +585,103 @@ macro "hotkeymode" elem name = "CTRL+SHIFT+NORTH" command = "shiftnorth" - elem + elem name = "CTRL+SHIFT+SOUTH" command = "shiftsouth" - elem + elem name = "CTRL+SHIFT+WEST" command = "shiftwest" - elem + elem name = "CTRL+SHIFT+EAST" command = "shifteast" - elem + elem name = "INSERT" command = "a-intent right" - elem + elem name = "DELETE" command = "delete-key-pressed" - elem + elem name = "1" command = "a-intent help" - elem + elem name = "CTRL+1" command = "a-intent help" - elem + elem name = "2" command = "a-intent disarm" - elem + elem name = "CTRL+2" command = "a-intent disarm" - elem + elem name = "3" command = "a-intent grab" - elem + elem name = "CTRL+3" command = "a-intent grab" - elem + elem name = "4" command = "a-intent harm" - elem + elem name = "CTRL+4" command = "a-intent harm" - elem + elem name = "5" command = ".me" - elem + elem name = "6" command = ".Subtle" - elem + elem name = "A" command = "KeyDown A" elem name = "A+UP" command = "KeyUp A" - elem + elem name = "D" command = "KeyDown D" elem name = "D+UP" command = "KeyUp D" - elem + elem name = "E" command = "quick-equip" - elem + elem name = "CTRL+E" command = "quick-equip" - elem + elem name = "F" command = "a-intent left" - elem + elem name = "CTRL+F" command = "a-intent left" - elem + elem name = "G" command = "a-intent right" - elem + elem name = "CTRL+G" command = "a-intent right" - elem + elem name = "H" command = "holster" - elem + elem name = "CTRL+H" command = "holster" - elem + elem name = "J" command = "toggle-gun-mode" - elem + elem name = "CTRL+J" command = "toggle-gun-mode" - elem + elem name = "Q" command = ".northwest" - elem + elem name = "CTRL+Q" command = ".northwest" - elem + elem name = "R" command = ".southwest" - elem + elem name = "CTRL+R" command = ".southwest" elem "s_key" @@ -678,7 +690,7 @@ macro "hotkeymode" elem name = "S+UP" command = "KeyUp S" - elem + elem name = "T" command = ".say" elem "w_key" @@ -687,90 +699,96 @@ macro "hotkeymode" elem name = "W+UP" command = "KeyUp W" - elem + elem name = "X" command = ".northeast" - elem + elem name = "CTRL+X" command = ".northeast" - elem + elem name = "Y" command = ".Whisper" - elem + elem name = "CTRL+Y" command = ".Whisper" - elem + elem name = "Z" command = "Activate-Held-Object" - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" - elem + elem name = "U" command = "Rest" - elem + elem name = "B" command = "Resist" - elem + elem name = "NUMPAD1" command = "body-r-leg" - elem + elem name = "NUMPAD2" command = "body-groin" - elem + elem name = "NUMPAD3" command = "body-l-leg" - elem + elem name = "NUMPAD4" command = "body-r-arm" - elem + elem name = "NUMPAD5" command = "body-chest" - elem + elem name = "NUMPAD6" command = "body-l-arm" - elem + elem name = "NUMPAD8" command = "body-toggle-head" - elem + elem name = "F1" command = "request-help" - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" - elem + elem name = "F2" command = "ooc" - elem + elem name = "F2+REP" command = ".screenshot auto" - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" - elem + elem name = "F3" command = ".say" - elem + elem name = "F4" command = ".me" - elem + elem name = "F5" command = "asay" - elem + elem name = "F6" command = "Player-Panel-New" - elem + elem name = "F7" command = "Admin-PM" - elem + elem name = "F8" command = "Invisimin" - elem + elem name = "F12" command = "F12" + elem + name = "CTRL+SHIFT+ADD" + command = "planeup" + elem + name = "CTRL+SHIFT+SUBTRACT" + command = "planedown" macro "borgmacro" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0\"" elem @@ -791,58 +809,58 @@ macro "borgmacro" elem name = "Alt+UP" command = "KeyUp Alt" - elem + elem name = "NORTHEAST" command = ".northeast" - elem + elem name = "SOUTHEAST" command = ".southeast" - elem + elem name = "SOUTHWEST" command = ".southwest" - elem + elem name = "NORTHWEST" command = ".northwest" - elem + elem name = "ALT+WEST" command = "westfaceperm" - elem + elem name = "CTRL+WEST" command = "westface" - elem + elem name = "West" command = "KeyDown West" elem name = "West+UP" command = "KeyUp West" - elem + elem name = "ALT+NORTH" command = "northfaceperm" - elem + elem name = "CTRL+NORTH" command = "northface" - elem + elem name = "North" command = "KeyDown North" elem name = "North+UP" command = "KeyUp North" - elem + elem name = "ALT+EAST" command = "eastfaceperm" - elem + elem name = "CTRL+EAST" command = "eastface" - elem + elem name = "East" command = "KeyDown East" elem name = "East+UP" command = "KeyUp East" - elem + elem name = "ALT+SOUTH" command = "southfaceperm" - elem + elem name = "CTRL+SOUTH" command = "southface" elem @@ -854,176 +872,181 @@ macro "borgmacro" elem name = "CTRL+SHIFT+NORTH" command = "shiftnorth" - elem + elem name = "CTRL+SHIFT+SOUTH" command = "shiftsouth" - elem + elem name = "CTRL+SHIFT+WEST" command = "shiftwest" - elem + elem name = "CTRL+SHIFT+EAST" command = "shifteast" - elem + elem name = "INSERT" command = "a-intent right" - elem + elem name = "DELETE" command = "delete-key-pressed" - elem + elem name = "CTRL+1" command = "toggle-module 1" - elem + elem name = "CTRL+2" command = "toggle-module 2" - elem + elem name = "CTRL+3" command = "toggle-module 3" - elem + elem name = "CTRL+4" command = "a-intent left" - elem + elem name = "CTRL+A" command = "KeyDown A" elem name = "CTRL+A+UP" command = "KeyUp A" - elem + elem name = "CTRL+D" command = "KeyDown D" elem name = "CTRL+D+UP" command = "KeyUp D" - elem + elem name = "CTRL+F" command = "a-intent left" - elem + elem name = "CTRL+G" command = "a-intent right" - elem + elem name = "CTRL+Q" command = ".northwest" - elem + elem name = "CTRL+R" command = ".southwest" - elem + elem name = "CTRL+S" command = "KeyDown S" elem name = "CTRL+S+UP" command = "KeyUp S" - elem + elem name = "CTRL+W" command = "KeyDown W" elem name = "CTRL+W+UP" command = "KeyUp W" - elem + elem name = "CTRL+X" command = ".northeast" - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" - elem + elem name = "CTRL+U" command = "Rest" - elem + elem name = "CTRL+NUMPAD1" command = "body-r-leg" - elem + elem name = "CTRL+NUMPAD2" command = "body-groin" - elem + elem name = "CTRL+NUMPAD3" command = "body-l-leg" - elem + elem name = "CTRL+NUMPAD4" command = "body-r-arm" - elem + elem name = "CTRL+NUMPAD5" command = "body-chest" - elem + elem name = "CTRL+NUMPAD6" command = "body-l-arm" - elem + elem name = "CTRL+NUMPAD8" command = "body-toggle-head" - elem + elem name = "F1" command = "request-help" - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" - elem + elem name = "F2" command = "ooc" - elem + elem name = "F2+REP" command = ".screenshot auto" - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" - elem + elem name = "F3" command = ".say" - elem + elem name = "F4" command = ".me" - elem + elem name = "F5" command = "asay" - elem + elem name = "F6" command = "Player-Panel-New" - elem + elem name = "F7" command = "Admin-PM" - elem + elem name = "F8" command = "Invisimin" - elem + elem name = "F12" command = "F12" - + elem + name = "CTRL+SHIFT+ADD" + command = "planeup" + elem + name = "CTRL+SHIFT+SUBTRACT" + command = "planedown" menu "menu" - elem + elem name = "&File" command = "" saved-params = "is-checked" - elem + elem name = "&Quick screenshot\tF2" command = ".screenshot auto" category = "&File" saved-params = "is-checked" - elem + elem name = "&Save screenshot as...\tShift+F2" command = ".screenshot" category = "&File" saved-params = "is-checked" - elem + elem name = "&Reconnect" command = ".reconnect" category = "&File" saved-params = "is-checked" - elem + elem name = "&Check ping" command = ".ping" category = "&File" saved-params = "is-checked" - elem + elem name = "" command = "" category = "&File" saved-params = "is-checked" - elem + elem name = "&Quit" command = ".quit" category = "&File" saved-params = "is-checked" - elem + elem name = "&Icons" command = "" saved-params = "is-checked" @@ -1070,7 +1093,7 @@ menu "menu" can-check = true group = "size" saved-params = "is-checked" - elem + elem name = "" command = "" category = "&Icons" @@ -1081,7 +1104,7 @@ menu "menu" category = "&Icons" can-check = true saved-params = "is-checked" - elem + elem name = "&Scaling" command = "" saved-params = "is-checked" @@ -1106,16 +1129,16 @@ menu "menu" can-check = true group = "scale" saved-params = "is-checked" - elem + elem name = "&Help" command = "" saved-params = "is-checked" - elem + elem name = "&Admin help\tF1" command = "request-help" category = "&Help" saved-params = "is-checked" - elem + elem name = "&Hotkeys" command = "hotkeys-help" category = "&Help" @@ -1525,4 +1548,3 @@ window "text_editor" border = line saved-params = "" multi-line = true -