mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Moves throw mode procs up to /mob level, clicking on a non-turf or an atom that is not in a turf cancels throw mode.
1029 lines
27 KiB
Plaintext
1029 lines
27 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
|
|
qdel(hud_used)
|
|
if(mind && mind.current == src)
|
|
spellremove(src)
|
|
for(var/infection in viruses)
|
|
qdel(infection)
|
|
ghostize()
|
|
..()
|
|
|
|
/mob/New()
|
|
mob_list += src
|
|
if(stat == DEAD)
|
|
dead_mob_list += src
|
|
else
|
|
living_mob_list += src
|
|
..()
|
|
|
|
/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 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 viewers(src))
|
|
if(self_message && M==src)
|
|
M.show_message(self_message, 1, blind_message, 2)
|
|
else if(M.see_invisible < invisibility) // Cannot view the invisible, but you can hear it.
|
|
if(blind_message)
|
|
M.show_message(blind_message, 2)
|
|
else
|
|
M.show_message(message, 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 viewers(src))
|
|
M.show_message( message, 1, 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 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)
|
|
|
|
// 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 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
|
|
|
|
|
|
/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
|
|
|
|
// This is not needed short of simple_animal and carbon/alien / carbon/human, who reimplement it.
|
|
/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)
|
|
if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) )))
|
|
if (!( L ))
|
|
return null
|
|
else
|
|
return L.container
|
|
else
|
|
if (!( L ))
|
|
L = new /obj/effect/list_container/mobl( null )
|
|
L.container += src
|
|
L.master = src
|
|
if (istype(l_hand, /obj/item/weapon/grab))
|
|
var/obj/item/weapon/grab/G = l_hand
|
|
if (!( L.container.Find(G.affecting) ))
|
|
L.container += G.affecting
|
|
if (G.affecting)
|
|
G.affecting.ret_grab(L, 1)
|
|
if (istype(r_hand, /obj/item/weapon/grab))
|
|
var/obj/item/weapon/grab/G = r_hand
|
|
if (!( L.container.Find(G.affecting) ))
|
|
L.container += G.affecting
|
|
if (G.affecting)
|
|
G.affecting.ret_grab(L, 1)
|
|
if (!( flag ))
|
|
if (L.master == src)
|
|
var/list/temp = list( )
|
|
temp += L.container
|
|
//L = null
|
|
qdel(L)
|
|
return temp
|
|
else
|
|
return L.container
|
|
return
|
|
|
|
/mob/verb/mode()
|
|
set name = "Activate Held Object"
|
|
set category = "Object"
|
|
set src = usr
|
|
|
|
if(istype(loc,/obj/mecha)) return
|
|
|
|
if(hand)
|
|
var/obj/item/W = l_hand
|
|
if (W)
|
|
W.attack_self(src)
|
|
update_inv_l_hand()
|
|
else
|
|
var/obj/item/W = r_hand
|
|
if (W)
|
|
W.attack_self(src)
|
|
update_inv_r_hand()
|
|
if(next_move < world.time)
|
|
next_move = world.time + 2
|
|
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/dead/observer))
|
|
var/mob/dead/observer/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 < 18000)
|
|
usr << "You must wait 30 minutes to respawn!"
|
|
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()
|
|
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
|
|
|
|
if(istype(O, /obj/machinery/bot))
|
|
var/name = "BOT: [O.name]"
|
|
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.status & ORGAN_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)
|
|
usr << "<span class='notice'>It won't budge!</span>"
|
|
return
|
|
|
|
var/mob/M = AM
|
|
if(ismob(AM))
|
|
if(!iscarbon(src))
|
|
M.LAssailant = null
|
|
else
|
|
M.LAssailant = usr
|
|
|
|
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()
|
|
..()
|
|
|
|
if(client && client.holder)
|
|
if(statpanel("Status"))
|
|
statpanel("Status","Location:","([x], [y], [z])")
|
|
statpanel("Status","CPU:","[world.cpu]")
|
|
statpanel("Status","Instances:","[world.contents.len]")
|
|
if(statpanel("Status") && processScheduler && processScheduler.getIsRunning())
|
|
for(var/datum/controller/process/P in processScheduler.processes)
|
|
statpanel("Status",P.getStatName(), P.getTickTime())
|
|
else
|
|
statpanel("Status","processScheduler is not running.")
|
|
|
|
if(listed_turf && client)
|
|
if(!TurfAdjacent(listed_turf))
|
|
listed_turf = null
|
|
else
|
|
statpanel(listed_turf.name, null, 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
|
|
statpanel(listed_turf.name, null, A)
|
|
|
|
// facing verbs
|
|
/mob/proc/canface()
|
|
if(!canmove) return 0
|
|
if(stat) return 0
|
|
if(anchored) return 0
|
|
if(monkeyizing) return 0
|
|
return 1
|
|
|
|
//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()
|
|
if(istype(buckled, /obj/vehicle))
|
|
var/obj/vehicle/V = buckled
|
|
if(stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH))
|
|
lying = 1
|
|
canmove = 0
|
|
pixel_y = V.mob_offset_y - 5
|
|
else
|
|
if(buckled.buckle_lying != -1) lying = buckled.buckle_lying
|
|
canmove = 1
|
|
pixel_y = V.mob_offset_y
|
|
else if(buckled)
|
|
anchored = 1
|
|
canmove = 0
|
|
if(istype(buckled))
|
|
if(buckled.buckle_lying != -1)
|
|
lying = buckled.buckle_lying
|
|
if(buckled.buckle_movable)
|
|
anchored = 0
|
|
canmove = 1
|
|
|
|
else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH))
|
|
lying = 1
|
|
canmove = 0
|
|
else if(stunned)
|
|
canmove = 0
|
|
else if(captured)
|
|
anchored = 1
|
|
canmove = 0
|
|
lying = 0
|
|
else
|
|
lying = 0
|
|
canmove = 1
|
|
|
|
if(lying)
|
|
density = 0
|
|
drop_l_hand()
|
|
drop_r_hand()
|
|
else
|
|
density = 1
|
|
|
|
for(var/obj/item/weapon/grab/G in grabbed_by)
|
|
if(G.state >= GRAB_AGGRESSIVE)
|
|
canmove = 0
|
|
break
|
|
|
|
//Temporarily moved here from the various life() procs
|
|
//I'm fixing stuff incrementally so this will likely find a better home.
|
|
//It just makes sense for now. ~Carn
|
|
if( update_icon ) //forces a full overlay update
|
|
update_icon = 0
|
|
regenerate_icons()
|
|
else if( lying != lying_prev )
|
|
update_icons()
|
|
|
|
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(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)
|
|
|
|
|
|
//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/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.next_move > world.time)
|
|
return
|
|
usr.next_move = world.time + 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)) //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)
|
|
|
|
selection.loc = get_turf(src)
|
|
if(!(U.l_hand && U.r_hand))
|
|
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
|
|
|
|
/mob/living/proc/handle_statuses()
|
|
handle_stunned()
|
|
handle_weakened()
|
|
handle_stuttering()
|
|
handle_silent()
|
|
handle_drugged()
|
|
handle_slurring()
|
|
|
|
/mob/living/proc/handle_stunned()
|
|
if(stunned)
|
|
AdjustStunned(-1)
|
|
return stunned
|
|
|
|
/mob/living/proc/handle_weakened()
|
|
if(weakened)
|
|
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
|
|
return weakened
|
|
|
|
/mob/living/proc/handle_stuttering()
|
|
if(stuttering)
|
|
stuttering = max(stuttering-1, 0)
|
|
return stuttering
|
|
|
|
/mob/living/proc/handle_silent()
|
|
if(silent)
|
|
silent = max(silent-1, 0)
|
|
return silent
|
|
|
|
/mob/living/proc/handle_drugged()
|
|
if(druggy)
|
|
druggy = max(druggy-1, 0)
|
|
return druggy
|
|
|
|
/mob/living/proc/handle_slurring()
|
|
if(slurring)
|
|
slurring = max(slurring-1, 0)
|
|
return slurring
|
|
|
|
/mob/living/proc/handle_paralysed() // Currently only used by simple_animal.dm, treated as a special case in other mobs
|
|
if(paralysis)
|
|
AdjustParalysis(-1)
|
|
return paralysis
|
|
|
|
//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(NORTH)
|
|
|
|
/mob/verb/southfaceperm()
|
|
set hidden = 1
|
|
set_face_dir(SOUTH)
|
|
|
|
/mob/verb/eastfaceperm()
|
|
set hidden = 1
|
|
set_face_dir(EAST)
|
|
|
|
/mob/verb/westfaceperm()
|
|
set hidden = 1
|
|
set_face_dir(WEST)
|
|
|
|
//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" |