Files
VOREStation/code/modules/mob/mob.dm
Cameron653 28175d86c7 Late September Sync (#579)
* Elevators aren't bottomless voids!

* Updates changelog

* Sombrero Code

* Fixes #2365

* Adds changelog

* Sleeper is evil.

* no message

* Changelog

* Stops observers from leaving prints on the ground.

No more spooking the mortals, ghosts.

* Allows autotraitor in secret to start with 0 players

* Adds changelog

* Makes diona slightly less slow

* Adds changelog

* Bowling Shirts

* Updates changelog

* Adds a missing description

* Flat Cap Changes and Hair Bow

* Fixed Error

* Adds an in-hand

* Lower Torso cannot be amputated

* Smoke works, adds changelog

* Updates changelog

* Makes Unathi Voidsuits Less Fat

* Medical related fixes

* Fuzzy Cuffs

* Tube Top

* Made Icons for Security Suit Less Gaunt

* Revert "Medical related fixes"

This reverts commit d7c59520e6.

* Just the fix to random med item now

* Adds organ fixing

* Fixes Evening Glove Coloring

* HAZMAT Suits

* Changes Unathi sprite slightly

* Tweaks skirt pathing

* Corrects changelog

* Adds changelog

* Construction Voidsuits

* makes people bleed real good

* adderino changeling

* Biohazard Voidsuit

* Revert "Revert "Adds hub passwordu""

* Explosive implants should no longer gib on limbs.

* Adds space penguins and space geese.

* Revert "Revert "Revert "Adds hub passwordu"""

* Makes flash rounds respect eye protection

* Water > Fire

* There's plenty lying around, I think

* Naming inconsistencies fixed

The short naming of central command has been really inconsistent across
the game's files. This has always annoyed the shit out of me.

CentComm and Centcomm and Centcom are now all CentCom, specifically with
that capitalization. Why one M instead of two M's? Because Comm with two
'M's = Communications. Hence, Telecomms, NOT Telecoms. Telecoms is
incorrect. CentCom was also chosen because CentCom with one M and this
casing is most found throughout the game's files.

Speaking of Telecomms, I corrected one instance in the game where it's
Telecom. Like I said, this is not correct. There was only one
inconsistency.

Likewise, Nanotrasen has been changed to NanoTrasen. Nanotrasen only
appears 20 times, where NanoTrasen appears 62. NanoTrasen is clearly the
preferred, correct naming.

* Almost forgot plural of Telecomm

* Finalizes work, adds designs to research.

* Press Vest

* Removes Mags/Shells, Adds Recorder and Flashlight

* Fixes spans.

* Raises the number of players needed to start Ninja

* Still needs to fix internal bleeding

* Allows Wirer To Attach to Toolbelts

* Fixes #393

* Tweaks FBP temperature

* Corrects Changelog

* Fixes some Advanced Egun oversights

* Embiggens the laser carbine and the lasercannon.

* Messenger Bags

* Health analyzers detect appendicitis

* Custom Circuit Additions & Fixes
Adds Med Scanner and Advanced Med Scanner circuits.
Clock circuit is now functional.
Five second delay will delay for five seconds and not one second.
Renaming circuitry now respects ability to do so (e.g. being alive).
Firing circuit can now be obtained by science normally.
Examining inside assembly cases now requires adjacency.

* More Additions
You can now cancel inputting on a text or numberpad.
Zero is now displayed properly on the UI and not be shown as null.
The small and medium assemblies now have real sprites.
Total health percentage for med scanners and advanced med scanners now reports a proper percentage and not 1 or 0.
The constant memory chip now can be set by using it in hand, making it usable.
The constant memory chip now accepts refs as data to store.  To use, select 'ref' when using inhand, then hit it against the thing you want to store.

* Allows Chemists to View Medical Records on their PDA

* Refactors splinting

* Refactors the forceMove() drop.

Makes dropping a its proc instead, cleaning up forceMove() handling.

* Replaces ORGAN_SPLINTED

* Supportive suits now only loop through bad organs

* Adds changelog

* Lasercannon tweaks

* Bloodloss tweak

* Adds hawaii shirt

Attachable to any uniform, works like suit jackets.

* Changelog cause why not

At this rate I'll forget how to do those otherwise

* Adds randomized alohas

Also some color matrix helpers from TG

* Appendicitis doesn't cancel itself out.

* Removes debug stuff

* Radsuit Sprite Changes

* Allows us to actually use the messenger bags

* Fixes spelling mistake

* Ported ventcrawling from vg.

* Fixes changelog errors

* Updates changelog

* Tweaks vent crawling.

The ability to ventcrawl is now checked by the /handle_ventcrawl() proc, making it possible to properly check before and after the do_after() call.
Moves various checks into the base can_ventcrawl proc.
Now lists the first object that prevents a mob from ventcrawling, making it easier to correct the exception list.
Removes the issmall() check, instead checks if the crawling mob has the relevant verb. Fixes #14081.

* Suit Storage Items

* Adds in IB removal

* More Circuit Things
Adds Locomotion circuit, which makes the machine move in a given direction.
Adds Signaler circuit, which can send and receive signals from a signaler.
Adds a new tool, the Debugger, which lets one directly set data in a specific pin.  It can also pulse activation pins.
Adds ability to define custom cooldown times for each component.
Smoke generator now has a 30 second cooldown.
Cleans up some code somewhat.

* Adds design for locomotion circuit.

* Cleans up code

* Even more sprites by Mechoid.
Fixes abs to rel converter.

* Black Messenger Bag

* Powersink fix

* Even More Sodding Circuits
Adds new RNG circuit, to make random numbers each time.
Adds new Concatenating circuit, so you can make lots of small strings into one big one.
Adds new light and advanced light circuit.  Basic just has a normal light that can be toggled.  Advanced allows it to be any color using RGB, and a brightness between 0 and 6.
New sprites for the debugger and wirer, by Mechoid.
Hopefully finally fixes smoke generator from being unobtainable.

* Adds basic circuit kit and spare circuit tools to Tech Storage.

* Part the first

* Changelog

* Allows robots to be constructed with prosthetic limbs as well as borg limbs.

* Map change

* Secbelt can hold stun revolvers and eguns

* Voidsuit Sprite Changes

* Tweaks burst laser

* Lasers, energy projectiles, and muzzle flashes now produce light.

It's a bit wonky due to lighting only updating once every half-second,
but it's very much functional, at least on my desktop.

* Adds bridge bunnies

* Slightly cleans up the occupation screen, adds uniform to locker

* Map Changes

* Adds Changelog

* Fixes stuff

* Allows jobbanning of cargo department jobs

* Re-adds balance changes to heavy lasers.

They got changed by accident when I did the laser light show.
Also, adds changelogs for my last couple changes, because I'm an
    idiot and forgot them.

* Fixed missing sprite

* Dress Loadout Additions

* I Can't Believe It's Not Circuits (it is)
Fixes numberpad and letterpad pulsing.
Debugger and Constant chip can now have null written to it.
Adds new sound output, with two types so far.  One being the 'beeper' type, which can do things like buzz, ping, beep, etc.  The second type is a securitron speaker, which allows us to get closer to building a functioning Beepsky.

* Adds EPv2 Circuit
Adds a circuit that allows it to send and receive EPv2 messages, allowing for a more robust transmission of data that signalers cannot deliver.  Bonus: Communicators can send text messages to custom machines using this.

* Updates changelog

* Fixes not being able to put things in medkits.

* Technomancer Tweaks

Cost for various spells and equipment adjusted greatly.  In general, things are cheaper, and everything should now be in multiples of 25, so no points are wasted.
The default jumpsuit for Technomancers is now heavily insulated, protecting them from tasers, batons, and perhaps unfortunate lightning strikes.
Instability between 31 and 50 made less harsh.
Wards made with a scepter of enhancement will break the cloak of anyone invisible that it can see.
Fire aura buffed, increased rate of heating as well as temperature cap for both non-scepter and scepter effects.
Reflect spell made more forgiving for the Technomancer, lasting longer before expiring.
Projectile spells should be able to hit people more reliably.

* Shotgun Reloading Tweak
Adds ability to hit a shotgun or similar weapon with a container containing ammo, to load said ammo into the shotgun one at a time automatically, instead of having to play inventory tetris, as requested by some people.

* Use sanitizeName for the guest pass terminal name input to prevent excessively long names.

* Circuit UI and Assembly Tweaks
Adds new drone assembly, which has stats between the medium and large assembly.  Sprites by Mechoid.
Assemblies now have a light UI when examined while opened, which displays what's inside, as well as how close to the cap for parts or complexity you are getting.  Click the names of a component to open the wiring interface for that component.  You can also rename each component from the UI.  Bonus:  Having multiple components of the same name will no longer appear as one component.
Adds ability to rename the assembly, using the new UI.

* Revert "Ported ventcrawling from vg."

* Re-adds a nice, useful macro

* Fixes #2431

* Tweaks Riot armor

* Fixes a typo in the DNA Modifier

* Ripped Jeans (And White Shorts)

* Adds shanking

* Adds changelog

* Removes a stray world <<

* Ported ventcrawling from vg.

* Tweaks vent crawling.

The ability to ventcrawl is now checked by the /handle_ventcrawl() proc, making it possible to properly check before and after the do_after() call.
Moves various checks into the base can_ventcrawl proc.
Now lists the first object that prevents a mob from ventcrawling, making it easier to correct the exception list.
Removes the issmall() check, instead checks if the crawling mob has the relevant verb. Fixes #14081.

* Long, time-consuming not one-line fix

* Makes cigs branded too

Description of cig/cigbutt would reveal its brand for dastardly murdersolving revelations.

* Adding a article

* The door hacker now only pings the user

* Removes implants from Deathsquad

* Adds the ability to apply pressure to bleeding wounds

* Shoes

* EVA rigs should use their default sprites on Taj and Unathi

* Fixing some errors

* Update loadout_xeno.dm

* Delete back_vr.dmi

* Add files via upload
2016-09-24 14:12:43 -04:00

1015 lines
26 KiB
Plaintext

/mob/Destroy()//This makes sure that mobs with 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()
for(var/atom/movable/AM in client.screen)
qdel(AM)
client.screen = list()
if(mind && mind.current == src)
spellremove(src)
ghostize()
..()
/mob/proc/remove_screen_obj_references()
hands = null
pullin = null
purged = null
internals = null
oxygen = null
i_select = null
m_select = null
toxin = null
fire = null
bodytemp = null
healths = null
throw_icon = null
nutrition_icon = null
pressure = null
pain = null
item_use_icon = null
gun_move_icon = null
gun_setting_icon = null
spell_masters = null
zone_sel = null
/mob/New()
mob_list += src
if(stat == DEAD)
dead_mob_list += src
else
living_mob_list += src
hook_vr("mob_new",list(src)) //VOREStation Code
..()
/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) && ((sdisabilities & BLIND) || blinded || paralysis) )//Vision related
if (!( alt ))
return
else
msg = alt
type = alt_type
if ((type & 2) && ((sdisabilities & DEAF) || ear_deaf))//Hearing related
if (!( alt ))
return
else
msg = alt
type = alt_type
if ((type & 1) && (sdisabilities & BLIND))
return
// Added voice muffling for Issue 41.
if(stat == UNCONSCIOUS || sleeping > 0)
src << "<I>... You can almost hear someone talking ...</I>"
else
src << 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/see = get_mobs_or_objects_in_view(world.view,src) | viewers(world.view,src)
for(var/I in see)
if(isobj(I))
//spawn(0)
//if(I) //It's possible that it could be deleted in the meantime.
var/obj/O = I
O.show_message( message, 1, blind_message, 2)
else if(ismob(I))
var/mob/M = I
if(self_message && M==src)
M.show_message( self_message, 1, blind_message, 2)
else if(M.see_invisible >= invisibility) // Cannot view the invisible
M.show_message( message, 1, blind_message, 2)
else if (blind_message)
M.show_message(blind_message, 2)
// 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/range = world.view
if(hearing_distance)
range = hearing_distance
var/list/hear = get_mobs_or_objects_in_view(range,src)
for(var/I in hear)
if(isobj(I))
spawn(0)
if(I) //It's possible that it could be deleted in the meantime.
var/obj/O = I
O.show_message( message, 2, deaf_message, 1)
else if(ismob(I))
var/mob/M = I
var/msg = message
if(self_message && M==src)
msg = self_message
M.show_message( msg, 2, deaf_message, 1)
/mob/proc/findname(msg)
for(var/mob/M in mob_list)
if (M.real_name == text("[]", msg))
return M
return 0
/mob/proc/movement_delay()
return 0
/mob/proc/Life()
// if(organStructure)
// organStructure.ProcessOrgans()
//handle_typing_indicator() //You said the typing indicator would be fine. The test determined that was a lie.
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_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
/mob/proc/show_inv(mob/user as mob)
return
//mob verbs are faster than object verbs. See http://www.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine()
/mob/verb/examinate(atom/A as mob|obj|turf in view())
set name = "Examine"
set category = "IC"
if((is_blind(src) || usr.stat) && !isobserver(src))
src << "<span class='notice'>Something is there but you can't see it.</span>"
return 1
face_atom(A)
A.examine(src)
/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/tile = get_turf(A)
if (!tile)
return 0
var/obj/P = new /obj/effect/decal/point(tile)
P.invisibility = invisibility
spawn (20)
if(P)
qdel(P) // qdel
face_atom(A)
return 1
/mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag)
return
/mob/verb/mode()
set name = "Activate Held Object"
set category = "Object"
set src = usr
return
/*
/mob/verb/dump_source()
var/master = "<PRE>"
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
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
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 += "<BR>[msg]"
if (popup)
memory()
/mob/proc/update_flavor_text()
set src in usr
if(usr != src)
usr << "No."
var/msg = sanitize(input(usr,"Set the flavor text in your 'examine' verb. Can also be used for OOC notes about your character.","Flavor Text",html_decode(flavor_text)) as message|null, extra = 0)
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!
src << "<h2 class='alert'>OOC Warning:</h2>"
src << "<span class='alert'>Your flavor text is likely out of date! <a href='byond://?src=\ref[src];flavor_change=1'>Change</a></span>"
/mob/proc/print_flavor_text()
if (flavor_text && flavor_text != "")
var/msg = replacetext(flavor_text, "\n", " ")
if(lentext(msg) <= 40)
return "\blue [msg]"
else
return "\blue [copytext_preserve_html(msg, 1, 37)]... <a href='byond://?src=\ref[src];flavor_more=1'>More...</a>"
/*
/mob/verb/help()
set name = "Help"
src << browse('html/help.html', "window=help")
return
*/
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
if (!( config.abandon_allowed ))
usr << "<span class='notice'>Respawn is disabled.</span>"
return
if ((stat != 2 || !( ticker )))
usr << "<span class='notice'><B>You must be dead to use this!</B></span>"
return
if (ticker.mode.deny_respawn) //BS12 EDIT
usr << "<span class='notice'>Respawn is disabled for this roundtype.</span>"
return
else
var/deathtime = world.time - src.timeofdeath
if(istype(src,/mob/observer/dead))
var/mob/observer/dead/G = src
if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
usr << "\blue <B>Upon using the antagHUD you forfeighted the ability to join the round.</B>"
return
var/deathtimeminutes = round(deathtime / 600)
var/pluralcheck = "minute"
if(deathtimeminutes == 0)
pluralcheck = ""
else if(deathtimeminutes == 1)
pluralcheck = " [deathtimeminutes] minute and"
else if(deathtimeminutes > 1)
pluralcheck = " [deathtimeminutes] minutes and"
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
usr << "You have been dead for[pluralcheck] [deathtimeseconds] seconds."
if (deathtime < (600)) //VOREStation Edit
usr << "You must wait 60 seconds to respawn!" //VOREStation Edit
return
else
usr << "You can respawn now, enjoy your new life!"
log_game("[usr.name]/[usr.key] used abandon mob.")
usr << "\blue <B>Make sure to play a different character, and please roleplay correctly!</B>"
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"
getFiles(
'html/88x31.png',
'html/bug-minus.png',
'html/cross-circle.png',
'html/hard-hat-exclamation.png',
'html/image-minus.png',
'html/image-plus.png',
'html/map-pencil.png',
'html/music-minus.png',
'html/music-plus.png',
'html/tick-circle.png',
'html/wrench-screwdriver.png',
'html/spell-check.png',
'html/burn-exclamation.png',
'html/chevron.png',
'html/chevron-expand.png',
'html/changelog.css',
'html/changelog.js',
'html/changelog.html'
)
src << browse('html/changelog.html', "window=changes;size=675x650")
if(prefs.lastchangelog != changelog_hash)
prefs.lastchangelog = changelog_hash
prefs.save_preferences()
winset(src, "rpane.changelog", "background-color=none;font-style=;")
/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))
usr << "\blue 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/weapon/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(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"
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("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", name, replacetext(flavor_text, "\n", "<BR>")), text("window=[];size=500x200", name))
onclose(usr, "[name]")
if(href_list["flavor_change"])
update_flavor_text()
// ..()
return
/mob/proc/pull_damage()
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.health - H.halloss <= config.health_threshold_softcrit)
for(var/name in H.organs_by_name)
var/obj/item/organ/external/e = H.organs_by_name[name]
if(e && H.lying)
if(((e.status & ORGAN_BROKEN && !(e.splinted)) || e.status & ORGAN_BLEEDING) && (H.getBruteLoss() + H.getFireLoss() >= 100))
return 1
break
return 0
/mob/MouseDrop(mob/M as mob)
..()
if(M != usr) return
if(usr == src) return
if(!Adjacent(usr)) return
if(istype(M,/mob/living/silicon/ai)) return
show_inv(usr)
/mob/verb/stop_pulling()
set name = "Stop Pulling"
set category = "IC"
if(pulling)
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)
src << "<span class='warning'>It won't budge!</span>"
return
var/mob/M = AM
if(ismob(AM))
if(!can_pull_mobs || !can_pull_size)
src << "<span class='warning'>They won't budge!</span>"
return
if((mob_size < M.mob_size) && (can_pull_mobs != MOB_PULL_LARGER))
src << "<span class='warning'>[M] is too large for you to move!</span>"
return
if((mob_size == M.mob_size) && (can_pull_mobs == MOB_PULL_SMALLER))
src << "<span class='warning'>[M] is too heavy for you to move!</span>"
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(!.)
src << "<span class='warning'>Somebody has a grip on them!</span>"
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)
src << "<span class='warning'>It won't budge!</span>"
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.pull_damage())
src << "\red <B>Pulling \the [H] in their current condition would probably be a bad idea.</B>"
//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/see(message)
if(!is_active())
return 0
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") && ticker && ticker.current_state != GAME_STATE_PREGAME)
stat("Station Time", stationtime2text())
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]")
if(statpanel("Processes"))
if(processScheduler)
processScheduler.statProcesses()
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
if(statpanel("Turf"))
stat("\icon[listed_turf]", listed_turf.name)
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
stat(A)
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
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.moving || world.time < client.move_delay)
return 0
set_dir(ndir)
if(buckled && buckled.buckle_movable)
buckled.set_dir(ndir)
client.move_delay += 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
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)
return
/mob/proc/AdjustStunned(amount)
if(status_flags & CANSTUN)
stunned = max(stunned + amount,0)
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() //updates lying, canmove and icons
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/Resting(amount)
facing_dir = null
resting = max(max(resting,amount),0)
return
/mob/proc/SetResting(amount)
resting = max(amount,0)
return
/mob/proc/AdjustResting(amount)
resting = max(resting + amount,0)
return
/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.canClick())
return
usr.setClickCooldown(20)
if(usr.stat == 1)
usr << "You are unconcious and cannot do that!"
return
if(usr.restrained())
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)
src << "You have nothing stuck in your body that is large enough to remove."
else
U << "[src] has nothing stuck in their wounds that is large enough to remove."
return
var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects
if(self)
src << "<span class='warning'>You attempt to get a good grip on [selection] in your body.</span>"
else
U << "<span class='warning'>You attempt to get a good grip on [selection] in [S]'s body.</span>"
if(!do_after(U, 30))
return
if(!selection || !S || !U)
return
if(self)
visible_message("<span class='warning'><b>[src] rips [selection] out of their body.</b></span>","<span class='warning'><b>You rip [selection] out of your body.</b></span>")
else
visible_message("<span class='warning'><b>[usr] rips [selection] out of [src]'s body.</b></span>","<span class='warning'><b>[usr] rips [selection] out of your body.</b></span>")
valid_objects = get_visible_implants(0)
if(valid_objects.len == 1) //Yanking out last object - removing verb.
src.verbs -= /mob/proc/yank_out_object
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 < 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!", 1)
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 = 0
return 1
//Check for brain worms in head.
/mob/proc/has_brain_worms()
for(var/I in contents)
if(istype(I,/mob/living/simple_animal/borer))
return I
return 0
/mob/proc/updateicon()
return
/mob/verb/face_direction()
set name = "Face Direction"
set category = "IC"
set src = usr
set_face_dir()
if(!facing_dir)
usr << "You are now not facing anything."
else
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))
/mob/proc/adjustEarDamage()
return
/mob/proc/setEarDamage()
return
//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