/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. GLOB.mob_list -= src GLOB.dead_mob_list -= src GLOB.living_mob_list -= src QDEL_NULL(hud_used) if(mind && mind.current == src) spellremove(src) mobspellremove(src) QDEL_LIST(viruses) ghostize() for(var/mob/dead/observer/M in following_mobs) M.following = null following_mobs = null QDEL_LIST_ASSOC_VAL(tkgrabbed_objects) for(var/I in tkgrabbed_objects) qdel(tkgrabbed_objects[I]) tkgrabbed_objects = null if(buckled) buckled.unbuckle_mob() if(viewing_alternate_appearances) for(var/datum/alternate_appearance/AA in viewing_alternate_appearances) AA.viewers -= src viewing_alternate_appearances = null ..() return QDEL_HINT_HARDDEL /mob/Initialize() GLOB.mob_list += src if(stat == DEAD) GLOB.dead_mob_list += src else GLOB.living_mob_list += src prepare_huds() ..() /atom/proc/prepare_huds() hud_list = list() for(var/hud in hud_possible) var/hint = hud_possible[hud] switch(hint) if(HUD_LIST_LIST) hud_list[hud] = list() else var/image/I = image('icons/mob/hud.dmi', src, "") hud_list[hud] = I /mob/proc/generate_name() return name /mob/proc/GetAltName() return "" /mob/proc/Cell() set category = "Admin" set hidden = 1 if(!loc) return 0 var/datum/gas_mixture/environment = loc.return_air() var/t = "Coordinates: [x],[y] \n" t+= "Temperature: [environment.temperature] \n" t+= "Nitrogen: [environment.nitrogen] \n" t+= "Oxygen: [environment.oxygen] \n" t+= "Plasma : [environment.toxins] \n" t+= "Carbon Dioxide: [environment.carbon_dioxide] \n" for(var/datum/gas/trace_gas in environment.trace_gases) to_chat(usr, "[trace_gas.type]: [trace_gas.moles] \n") usr.show_message(t, 1) /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) return if(type) if(type & 1 && !has_vision(information_only=TRUE))//Vision related if(!( alt )) return else msg = alt type = alt_type if(type & 2 && !can_hear())//Hearing related if(!( alt )) return else msg = alt type = alt_type if(type & 1 && !has_vision(information_only=TRUE)) return // Added voice muffling for Issue 41. if(stat == UNCONSCIOUS || (sleeping > 0 && stat != DEAD)) to_chat(src, "... You can almost hear someone talking ...") else to_chat(src, msg) return // Show a message to all mobs 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) for(var/mob/M in get_mobs_in_view(7, src)) if(M.see_invisible < invisibility) continue //can't view the invisible var/msg = message if(self_message && M == src) msg = self_message M.show_message(msg, 1, blind_message, 2) // Show a message to all mobs in sight of this atom // Use for objects performing visible actions // message is output to anyone who can see, e.g. "The [src] does something!" // blind_message (optional) is what blind people will hear e.g. "You hear something!" /atom/proc/visible_message(var/message, var/blind_message) for(var/mob/M in get_mobs_in_view(7, src)) if(!M.client) continue M.show_message(message, 1, blind_message, 2) // Show a message to all mobs 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/range = 7 if(hearing_distance) range = hearing_distance var/msg = message for(var/mob/M in get_mobs_in_view(range, src)) if(self_message && M == src) msg = self_message M.show_message(msg, 2, deaf_message, 1) // based on say code var/omsg = replacetext(message, "[src] ", "") var/list/listening_obj = new for(var/atom/movable/A in view(range, src)) if(istype(A, /mob)) var/mob/M = A for(var/obj/O in M.contents) listening_obj |= O else if(istype(A, /obj)) var/obj/O = A listening_obj |= O for(var/obj/O in listening_obj) O.hear_message(src, omsg) // Show a message to all mobs in earshot of this atom // Use for objects performing audible actions // message is the message output to anyone who can hear. // deaf_message (optional) is what deaf people will see. // hearing_distance (optional) is the range, how many tiles away the message can be heard. /atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance) var/range = 7 if(hearing_distance) range = hearing_distance for(var/mob/M in get_mobs_in_view(range, src)) M.show_message( message, 2, deaf_message, 1) /mob/proc/findname(msg) for(var/mob/M in GLOB.mob_list) if(M.real_name == text("[]", msg)) return M return 0 /mob/proc/movement_delay() return 0 /mob/proc/Life(seconds, times_fired) if(forced_look) if(!isnum(forced_look)) var/atom/A = locateUID(forced_look) if(istype(A)) var/view = client ? client.view : world.view if(get_dist(src, A) > view || !(src in viewers(view, A))) forced_look = null to_chat(src, "Your direction target has left your view, you are no longer facing anything.") return setDir() // handle_typing_indicator() return //This proc is called whenever someone clicks an inventory ui slot. /mob/proc/attack_ui(slot) var/obj/item/W = get_active_hand() if(istype(W)) if(istype(W, /obj/item/clothing)) var/obj/item/clothing/C = W if(C.hardsuit_restrict_helmet) to_chat(src, "You must fasten the helmet to a hardsuit first. (Target the head and use on a hardsuit)")// Stop eva helms equipping. else equip_to_slot_if_possible(C, slot) else equip_to_slot_if_possible(W, slot) else if(!restrained()) W = get_item_by_slot(slot) if(W) W.attack_hand(src) if(ishuman(src) && W == src:head) src:update_hair() src:update_fhair() /mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1) if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob)) return 1 else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob)) return 1 return 0 //This is a SAFE proc. Use this instead of equip_to_slot()! //set del_on_fail to have it delete W if it fails to equip //set disable_warning to disable the 'you are unable to equip that' warning. //unset redraw_mob to prevent the mob from being redrawn at the end. /mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1) if(!istype(W)) return 0 if(!W.mob_can_equip(src, slot, disable_warning)) if(del_on_fail) qdel(W) else if(!disable_warning) to_chat(src, "You are unable to equip that.")//Only print if del_on_fail is false return 0 equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. return 1 //This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task. //In most cases you will want to use equip_to_slot_if_possible() /mob/proc/equip_to_slot(obj/item/W as obj, slot) return //This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such. /mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot) return equip_to_slot_if_possible(W, slot, 1, 1, 0) // Convinience proc. Collects crap that fails to equip either onto the mob's back, or drops it. // Used in job equipping so shit doesn't pile up at the start loc. /mob/living/carbon/human/proc/equip_or_collect(var/obj/item/W, var/slot) if(W.mob_can_equip(src, slot, 1)) //Mob can equip. Equip it. equip_to_slot_or_del(W, slot) else //Mob can't equip it. Put it their backpack or toss it on the floor if(istype(back, /obj/item/storage)) var/obj/item/storage/S = back //Now, B represents a container we can insert W into. S.handle_item_insertion(W,1) return S var/turf/T = get_turf(src) if(istype(T)) W.forceMove(T) return T //The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. var/list/slot_equipment_priority = list( \ slot_back,\ slot_wear_pda,\ slot_wear_id,\ slot_w_uniform,\ slot_wear_suit,\ slot_wear_mask,\ slot_head,\ slot_shoes,\ slot_gloves,\ slot_l_ear,\ slot_r_ear,\ slot_glasses,\ slot_belt,\ slot_s_store,\ slot_tie,\ slot_l_store,\ slot_r_store\ ) //puts the item "W" into an appropriate slot in a human's inventory //returns 0 if it cannot, 1 if successful /mob/proc/equip_to_appropriate_slot(obj/item/W) if(!istype(W)) return 0 for(var/slot in slot_equipment_priority) if(istype(W,/obj/item/storage/) && slot == slot_head) // Storage items should be put on the belt before the head continue if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1 return 1 return 0 /mob/proc/check_for_open_slot(obj/item/W) if(!istype(W)) return 0 var/openslot = 0 for(var/slot in slot_equipment_priority) if(W.mob_check_equip(src, slot, 1) == 1) openslot = 1 break return openslot /obj/item/proc/mob_check_equip(M as mob, slot, disable_warning = 0) if(!M) return 0 if(!slot) return 0 if(ishuman(M)) //START HUMAN var/mob/living/carbon/human/H = M switch(slot) if(slot_l_hand) if(H.l_hand) return 0 return 1 if(slot_r_hand) if(H.r_hand) return 0 return 1 if(slot_wear_mask) if( !(slot_flags & SLOT_MASK) ) return 0 if(H.wear_mask) return 0 return 1 if(slot_back) if( !(slot_flags & SLOT_BACK) ) return 0 if(H.back) if(!(H.back.flags & NODROP)) return 2 else return 0 return 1 if(slot_wear_suit) if( !(slot_flags & SLOT_OCLOTHING) ) return 0 if(H.wear_suit) if(!(H.wear_suit.flags & NODROP)) return 2 else return 0 return 1 if(slot_gloves) if( !(slot_flags & SLOT_GLOVES) ) return 0 if(H.gloves) if(!(H.gloves.flags & NODROP)) return 2 else return 0 return 1 if(slot_shoes) if( !(slot_flags & SLOT_FEET) ) return 0 if(H.shoes) if(!(H.shoes.flags & NODROP)) return 2 else return 0 return 1 if(slot_belt) if(!H.w_uniform) if(!disable_warning) to_chat(H, "You need a jumpsuit before you can attach this [name].") return 0 if( !(slot_flags & SLOT_BELT) ) return 0 if(H.belt) if(!(H.belt.flags & NODROP)) return 2 else return 0 return 1 if(slot_glasses) if( !(slot_flags & SLOT_EYES) ) return 0 if(H.glasses) if(!(H.glasses.flags & NODROP)) return 2 else return 0 return 1 if(slot_head) if( !(slot_flags & SLOT_HEAD) ) return 0 if(H.head) if(!(H.head.flags & NODROP)) return 2 else return 0 return 1 if(slot_l_ear) if( !(slot_flags & slot_l_ear) ) return 0 if(H.l_ear) if(!(H.l_ear.flags & NODROP)) return 2 else return 0 return 1 if(slot_r_ear) if( !(slot_flags & slot_r_ear) ) return 0 if(H.r_ear) if(!(H.r_ear.flags & NODROP)) return 2 else return 0 return 1 if(slot_w_uniform) if( !(slot_flags & SLOT_ICLOTHING) ) return 0 if((FAT in H.mutations) && !(flags_size & ONESIZEFITSALL)) return 0 if(H.w_uniform) if(!(H.w_uniform.flags & NODROP)) return 2 else return 0 return 1 if(slot_wear_id) if(!H.w_uniform) if(!disable_warning) to_chat(H, "You need a jumpsuit before you can attach this [name].") return 0 if( !(slot_flags & SLOT_ID) ) return 0 if(H.wear_id) if(!(H.wear_id.flags & NODROP)) return 2 else return 0 return 1 if(slot_l_store) if(H.l_store) return 0 if(!H.w_uniform) if(!disable_warning) to_chat(H, "You need a jumpsuit before you can attach this [name].") return 0 if(slot_flags & SLOT_DENYPOCKET) return if( w_class <= WEIGHT_CLASS_SMALL || (slot_flags & SLOT_POCKET) ) return 1 if(slot_r_store) if(H.r_store) return 0 if(!H.w_uniform) if(!disable_warning) to_chat(H, "You need a jumpsuit before you can attach this [name].") return 0 if(slot_flags & SLOT_DENYPOCKET) return 0 if( w_class <= WEIGHT_CLASS_SMALL || (slot_flags & SLOT_POCKET) ) return 1 return 0 if(slot_s_store) if(!H.wear_suit) if(!disable_warning) to_chat(H, "You need a suit before you can attach this [name].") return 0 if(!H.wear_suit.allowed) if(!disable_warning) to_chat(usr, "You somehow have a suit with no defined allowed items for suit storage, stop that.") return 0 if(src.w_class > WEIGHT_CLASS_BULKY) if(!disable_warning) to_chat(usr, "The [name] is too big to attach.") return 0 if( istype(src, /obj/item/pda) || istype(src, /obj/item/pen) || is_type_in_list(src, H.wear_suit.allowed) ) if(H.s_store) if(!(H.s_store.flags & NODROP)) return 2 else return 0 else return 1 return 0 if(slot_handcuffed) if(H.handcuffed) return 0 if(!istype(src, /obj/item/restraints/handcuffs)) return 0 return 1 if(slot_legcuffed) if(H.legcuffed) return 0 if(!istype(src, /obj/item/restraints/legcuffs)) return 0 return 1 if(slot_in_backpack) if(H.back && istype(H.back, /obj/item/storage/backpack)) var/obj/item/storage/backpack/B = H.back if(B.contents.len < B.storage_slots && w_class <= B.max_w_class) return 1 return 0 return 0 //Unsupported slot //END HUMAN // If you're looking for `reset_perspective`, that's a synonym for this proc. /mob/proc/reset_perspective(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 1 /mob/living/reset_perspective(atom/A) . = ..() if(.) // Above check means the mob has a client update_sight() if(client.eye != src) var/atom/AT = client.eye AT.get_remote_view_fullscreens(src) else clear_fullscreen("remote_view", 0) update_pipe_vision() /mob/dead/reset_perspective(atom/A) if(client) if(ismob(client.eye) && (client.eye != src)) // Note to self: Use `client.eye` for ghost following in place // of periodic ghost updates var/mob/target = client.eye target.following_mobs -= src . = ..() if(.) // Allows sharing HUDs with ghosts if(hud_used) client.screen = list() hud_used.show_hud(hud_used.hud_version) /mob/setDir(new_dir) if(forced_look) if(isnum(forced_look)) dir = forced_look else var/atom/A = locateUID(forced_look) if(istype(A)) dir = get_cardinal_dir(src, A) return . = ..() /mob/proc/show_inv(mob/user) user.set_machine(src) var/dat = {"
| Left Hand: | [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Empty"] |
| Right Hand: | [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Empty"] |
"
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 = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = sanitize_simple(html_encode(msg), list("\n" = "
"))
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 = input(usr,"Set the flavor text in your 'examine' verb. The flavor text should be a physical descriptor of your character at a glance.","Flavor Text",html_decode(flavor_text)) as message|null
if(msg != null)
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = html_encode(msg)
flavor_text = msg
/mob/proc/print_flavor_text(var/shrink = 1)
if(flavor_text && flavor_text != "")
var/msg = replacetext(flavor_text, "\n", " ")
if(lentext(msg) <= 40 || !shrink)
return "[html_encode(msg)]" //Repeat after me, "I will not give players access to decoded HTML."
else
return "[copytext_preserve_html(msg, 1, 37)]... More..."
/mob/proc/is_dead()
return stat == DEAD
/mob
var/newPlayerType = /mob/new_player
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
if(!abandon_allowed)
to_chat(usr, "Respawning is disabled.")
return
if(stat != DEAD || !SSticker)
to_chat(usr, "You must be dead to use this!")
return
log_game("[key_name(usr)] has respawned.")
to_chat(usr, "Make sure to play a different character, and please roleplay correctly!")
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
return
client.screen.Cut()
client.screen += client.void
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
return
var/mob/new_player/M = new /mob/new_player()
if(!client)
log_game("[key_name(usr)] respawn failed due to disconnect.")
qdel(M)
return
M.key = key
return
/mob/verb/observe()
set name = "Observe"
set category = "OOC"
var/is_admin = 0
if(client.holder && (client.holder.rights & R_ADMIN))
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/names = list()
var/list/namecounts = list()
var/list/creatures = list()
for(var/obj/O in world) //EWWWWWWWWWWWWWWWWWWWWWWWW ~needs to be optimised
if(!O.loc)
continue
if(istype(O, /obj/item/disk/nuclear))
var/name = "Nuclear Disk"
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = O
if(istype(O, /obj/singularity))
var/name = "Singularity"
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = O
for(var/mob/M in sortAtom(GLOB.mob_list))
var/name = M.name
if(names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
creatures[name] = M
client.perspective = EYE_PERSPECTIVE
var/eye_name = null
var/ok = "[is_admin ? "Admin Observe" : "Observe"]"
eye_name = input("Please, select a player!", ok, null, null) as null|anything in creatures
if(!eye_name)
return
var/mob/mob_eye = creatures[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"
reset_perspective(null)
unset_machine()
if(istype(src, /mob/living))
if(src:cameraFollow)
src:cameraFollow = 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["refresh"])
if(machine && in_range(src, usr))
show_inv(machine)
if(!usr.incapacitated() && in_range(src, usr))
if(href_list["item"])
var/slot = text2num(href_list["item"])
var/obj/item/what = get_item_by_slot(slot)
if(what)
usr.stripPanelUnequip(what,src,slot)
else
usr.stripPanelEquip(what,src,slot)
if(usr.machine == src)
if(Adjacent(usr))
show_inv(usr)
else
usr << browse(null,"window=mob\ref[src]")
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
// The src mob is trying to strip an item from someone
// Defined in living.dm
/mob/proc/stripPanelUnequip(obj/item/what, mob/who)
return
// The src mob is trying to place an item on someone
// Defined in living.dm
/mob/proc/stripPanelEquip(obj/item/what, mob/who)
return
/mob/MouseDrop(mob/M as mob)
..()
if(M != usr) return
if(isliving(M))
var/mob/living/L = M
if(L.mob_size <= MOB_SIZE_SMALL)
return // Stops pAI drones and small mobs (borers, parrots, crabs) from stripping people. --DZD
if(!M.can_strip)
return
if(usr == src)
return
if(!Adjacent(usr))
return
if(isLivingSSD(src) && M.client && M.client.send_ssd_warning(src))
return
show_inv(usr)
/mob/proc/can_use_hands()
return
/mob/proc/is_mechanical()
return mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")
/mob/proc/is_ready()
return client && !!mind
/mob/proc/is_in_brig()
if(!loc || !loc.loc)
return 0
// They should be in a cell or the Brig portion of the shuttle.
var/area/A = loc.loc
if(!istype(A, /area/security/prison))
if(!istype(A, /area/shuttle/escape) || loc.name != "Brig floor")
return 0
// If they still have their ID they're not brigged.
for(var/obj/item/card/id/card in src)
return 0
for(var/obj/item/pda/P in src)
if(P.id)
return 0
return 1
/mob/proc/get_gender()
return gender
/mob/proc/is_muzzled()
return 0
/mob/Stat()
..()
show_stat_turf_contents()
statpanel("Status") // We only want alt-clicked turfs to come before Status
if(mob_spell_list && mob_spell_list.len)
for(var/obj/effect/proc_holder/spell/S in mob_spell_list)
add_spell_to_statpanel(S)
if(mind && istype(src, /mob/living) && mind.spell_list && mind.spell_list.len)
for(var/obj/effect/proc_holder/spell/S in mind.spell_list)
add_spell_to_statpanel(S)
if(is_admin(src))
if(statpanel("MC")) //looking at that panel
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
stat("CPU:", "[world.cpu]")
stat("Instances:", "[num2text(world.contents.len, 10)]")
GLOB.stat_entry()
stat("Server Time:", time_stamp())
stat(null)
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()
statpanel("Status") // Switch to the Status panel again, for the sake of the lazy Stat procs
// this function displays the station time in the status panel
/mob/proc/show_stat_station_time()
stat(null, "Round Time: [worldtime2text()]")
stat(null, "Station Time: [station_time_timestamp()]")
// this function displays the shuttles ETA in the status panel if the shuttle has been called
/mob/proc/show_stat_emergency_shuttle_eta()
var/ETA = SSshuttle.emergency.getModeStr()
if(ETA)
stat(null, "[ETA] [SSshuttle.emergency.getTimerStr()]")
/mob/proc/show_stat_turf_contents()
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
statpanel(listed_turf.name, null, listed_turf)
var/list/statpanel_things = list()
for(var/foo in listed_turf)
var/atom/A = foo
if(A.invisibility > see_invisible)
continue
if(is_type_in_list(A, shouldnt_see) || !A.simulated)
continue
statpanel_things += A
statpanel(listed_turf.name, null, statpanel_things)
/mob/proc/add_spell_to_statpanel(var/obj/effect/proc_holder/spell/S)
switch(S.charge_type)
if("recharge")
statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S)
if("charges")
statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S)
if("holdervar")
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S)
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
if(client.moving) return 0
if(world.time < client.move_delay) return 0
if(stat==2) return 0
if(anchored) return 0
if(notransform) return 0
if(restrained()) return 0
return 1
/mob/proc/fall(var/forced)
drop_l_hand()
drop_r_hand()
/mob/proc/facedir(ndir)
if(!canface())
return 0
setDir(ndir)
client.move_delay += movement_delay()
return 1
/mob/verb/eastface()
set hidden = 1
return facedir(EAST)
/mob/verb/westface()
set hidden = 1
return facedir(WEST)
/mob/verb/northface()
set hidden = 1
return facedir(NORTH)
/mob/verb/southface()
set hidden = 1
return facedir(SOUTH)
/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
return FALSE
/mob/proc/swap_hand()
return
/mob/proc/activate_hand(selhand)
return
/mob/dead/observer/verb/respawn()
set name = "Respawn as NPC"
set category = "Ghost"
if(jobban_isbanned(usr, ROLE_SENTIENT))
to_chat(usr, "You are banned from playing as sentient animals.")
return
if(!SSticker || SSticker.current_state < 3)
to_chat(src, "You can't respawn as an NPC before the game starts!")
return
if((usr in GLOB.respawnable_list) && (stat==2 || istype(usr,/mob/dead/observer)))
var/list/creatures = list("Mouse")
for(var/mob/living/L in GLOB.living_mob_list)
if(safe_respawn(L.type) && L.stat!=2)
if(!L.key)
creatures += L
var/picked = input("Please select an NPC to respawn as", "Respawn as NPC") as null|anything in creatures
switch(picked)
if("Mouse")
GLOB.respawnable_list -= usr
become_mouse()
spawn(5)
GLOB.respawnable_list += usr
else
var/mob/living/NPC = picked
if(istype(NPC) && !NPC.key)
GLOB.respawnable_list -= usr
NPC.key = key
spawn(5)
GLOB.respawnable_list += usr
else
to_chat(usr, "You are not dead or you have given up your right to be respawned!")
return
/mob/proc/become_mouse()
var/timedifference = world.time - client.time_died_as_mouse
if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600)
var/timedifference_text
timedifference_text = time2text(mouse_respawn_time * 600 - timedifference,"mm:ss")
to_chat(src, "You may only spawn again as a mouse more than [mouse_respawn_time] minutes after your death. You have [timedifference_text] left.")
return
//find a viable mouse candidate
var/mob/living/simple_animal/mouse/host
var/obj/machinery/atmospherics/unary/vent_pump/vent_found
var/list/found_vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/v in world)
if(!v.welded && v.z == src.z)
found_vents.Add(v)
if(found_vents.len)
vent_found = pick(found_vents)
host = new /mob/living/simple_animal/mouse(vent_found.loc)
else
to_chat(src, "Unable to find any unwelded vents to spawn mice at.")
if(host)
host.ckey = src.ckey
to_chat(host, "You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.")
/mob/proc/assess_threat() //For sec bot threat assessment
return 5
/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/proc/notify_ghost_cloning(message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", sound = 'sound/effects/genetics.ogg', atom/source = null, flashwindow = TRUE)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)
if(flashwindow)
window_flash(ghost.client)
ghost.notify_cloning(message, sound, source)
return ghost
/mob/proc/fakevomit(green = 0, no_text = 0) //for aesthetic vomits that need to be instant and do not stun. -Fox
if(stat==DEAD)
return
var/turf/location = loc
if(istype(location, /turf/simulated))
if(green)
if(!no_text)
visible_message("[src] vomits up some green goo!","You vomit up some green goo!")
location.add_vomit_floor(FALSE, TRUE)
else
if(!no_text)
visible_message("[src] pukes all over [p_them()]self!","You puke all over yourself!")
location.add_vomit_floor(TRUE)
/mob/proc/AddSpell(obj/effect/proc_holder/spell/S)
mob_spell_list += S
S.action.Grant(src)
/mob/proc/RemoveSpell(obj/effect/proc_holder/spell/spell) //To remove a specific spell from a mind
if(!spell)
return
for(var/obj/effect/proc_holder/spell/S in mob_spell_list)
if(istype(S, spell))
qdel(S)
mob_spell_list -= S
//override to avoid rotating pixel_xy on mobs
/mob/shuttleRotate(rotation)
dir = angle2dir(rotation+dir2angle(dir))
/mob/proc/handle_ventcrawl()
return // Only living mobs can ventcrawl
//You can buckle on mobs if you're next to them since most are dense
/mob/buckle_mob(mob/living/M, force = 0)
if(M.buckled)
return 0
var/turf/T = get_turf(src)
if(M.loc != T)
var/old_density = density
density = 0
var/can_step = step_towards(M, T)
density = old_density
if(!can_step)
return 0
return ..()
//Default buckling shift visual for mobs
/mob/post_buckle_mob(mob/living/M)
if(M == buckled_mob) //post buckling
M.pixel_y = initial(M.pixel_y) + 9
if(M.layer < layer)
M.layer = layer + 0.1
else //post unbuckling
M.layer = initial(M.layer)
M.pixel_y = initial(M.pixel_y)
/mob/proc/can_unbuckle(mob/user)
return 1
//Can the mob see reagents inside of containers?
/mob/proc/can_see_reagents()
return 0
//Can this mob leave its location without breaking things terrifically?
/mob/proc/can_safely_leave_loc()
return 1 // Yes, you can
/mob/proc/IsVocal()
return 1
/mob/proc/get_access()
return list() //must return list or IGNORE_ACCESS
/mob/proc/faction_check(mob/target)
for(var/F in faction)
if(F in target.faction)
return 1
return 0
/mob/proc/create_attack_log(text, collapse = TRUE)
LAZYINITLIST(attack_log)
create_log_in_list(attack_log, text, collapse, last_log)
last_log = world.timeofday
/mob/proc/create_debug_log(text, collapse = TRUE)
LAZYINITLIST(debug_log)
create_log_in_list(debug_log, text, collapse, world.timeofday)
/proc/create_log_in_list(list/target, text, collapse = TRUE, last_log)//forgive me code gods for this shitcode proc
//this proc enables lovely stuff like an attack log that looks like this: "[18:20:29-18:20:45]21x John Smith attacked Andrew Jackson with a crowbar."
//That makes the logs easier to read, but because all of this is stored in strings, weird things have to be used to get it all out.
var/new_log = "\[[time_stamp()]] [text]"
if(target.len)//if there are other logs already present
var/previous_log = target[target.len]//get the latest log
var/last_log_is_range = (copytext(previous_log, 10, 11) == "-") //whether the last log is a time range or not. The "-" will be an indicator that it is.
var/x_sign_position = findtext(previous_log, "x")
if(world.timeofday - last_log > 100)//if more than 10 seconds from last log
collapse = 0//don't collapse anyway
//the following checks if the last log has the same contents as the new one
if(last_log_is_range)
if(!(copytext(previous_log, x_sign_position + 13) == text))//the 13 is there because of span classes; you won't see those normally in-game
collapse = 0
else
if(!(copytext(previous_log, 12) == text))
collapse = 0
if(collapse == 1)
var/rep = 0
var/old_timestamp = copytext(previous_log, 2, 10)//copy the first time value. This one doesn't move when it's a timespan, so no biggie
//An attack log entry can either be a time range with multiple occurences of an action or a single one, with just one time stamp
if(last_log_is_range)
rep = text2num(copytext(previous_log, 44, x_sign_position))//get whatever number is right before the 'x'
new_log = "\[[old_timestamp]-[time_stamp()]][rep?rep+1:2]x [text]"
target -= target[target.len]//remove the last log
target += new_log
/mob/vv_get_dropdown()
. = ..()
.["Show player panel"] = "?_src_=vars;mob_player_panel=[UID()]"
.["Give Spell"] = "?_src_=vars;give_spell=[UID()]"
.["Give Martial Art"] = "?_src_=vars;givemartialart=[UID()]"
.["Give Disease"] = "?_src_=vars;give_disease=[UID()]"
.["Toggle Godmode"] = "?_src_=vars;godmode=[UID()]"
.["Toggle Build Mode"] = "?_src_=vars;build_mode=[UID()]"
.["Make 2spooky"] = "?_src_=vars;make_skeleton=[UID()]"
.["Assume Direct Control"] = "?_src_=vars;direct_control=[UID()]"
.["Offer Control to Ghosts"] = "?_src_=vars;offer_control=[UID()]"
.["Drop Everything"] = "?_src_=vars;drop_everything=[UID()]"
.["Regenerate Icons"] = "?_src_=vars;regenerateicons=[UID()]"
.["Add Language"] = "?_src_=vars;addlanguage=[UID()]"
.["Remove Language"] = "?_src_=vars;remlanguage=[UID()]"
.["Add Organ"] = "?_src_=vars;addorgan=[UID()]"
.["Remove Organ"] = "?_src_=vars;remorgan=[UID()]"
.["Fix NanoUI"] = "?_src_=vars;fix_nano=[UID()]"
.["Add Verb"] = "?_src_=vars;addverb=[UID()]"
.["Remove Verb"] = "?_src_=vars;remverb=[UID()]"
.["Gib"] = "?_src_=vars;gib=[UID()]"
/mob/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
while(spintime >= speed)
sleep(speed)
switch(D)
if(NORTH)
D = EAST
if(SOUTH)
D = WEST
if(EAST)
D = SOUTH
if(WEST)
D = NORTH
setDir(D)
spintime -= speed
/mob/proc/is_literate()
return FALSE
/mob/proc/faction_check_mob(mob/target, exact_match)
if(exact_match) //if we need an exact match, we need to do some bullfuckery.
var/list/faction_src = faction.Copy()
var/list/faction_target = target.faction.Copy()
if(!("\ref[src]" in faction_target)) //if they don't have our ref faction, remove it from our factions list.
faction_src -= "\ref[src]" //if we don't do this, we'll never have an exact match.
if(!("\ref[target]" in faction_src))
faction_target -= "\ref[target]" //same thing here.
return faction_check(faction_src, faction_target, TRUE)
return faction_check(faction, target.faction, FALSE)
/proc/faction_check(list/faction_A, list/faction_B, exact_match)
var/list/match_list
if(exact_match)
match_list = faction_A & faction_B //only items in both lists
var/length = LAZYLEN(match_list)
if(length)
return (length == LAZYLEN(faction_A)) //if they're not the same len(gth) or we don't have a len, then this isn't an exact match.
else
match_list = faction_A & faction_B
return LAZYLEN(match_list)
return FALSE
/mob/proc/update_sight()
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
/mob/proc/sync_lighting_plane_alpha()
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
if (L)
L.alpha = lighting_alpha