Files
goonstation-2016/code/mob.dm

2914 lines
87 KiB
Plaintext

/mob
density = 1
layer = MOB_LAYER
animate_movement = 2
soundproofing = 10
var/datum/mind/mind
var/datum/abilityHolder/abilityHolder = null
var/datum/bioHolder/bioHolder = null
var/datum/adventurevars/adventure_variables = new
var/datum/targetable/targeting_spell = null
var/obj/screen/pullin = null
var/obj/screen/internals = null
var/obj/screen/oxygen = null
var/obj/screen/i_select = null
var/obj/screen/m_select = null
var/obj/screen/bodytemp = null
var/obj/screen/healths = null
var/obj/screen/throw_icon = null
var/obj/screen/stamina_bar/stamina_bar = null
var/last_overlay_refresh = 1 // In relation to world time. Used for traitor/nuke ops overlays certain mobs can see.
var/robot_talk_understand = 0
var/list/obj/hallucination/hallucinations = list()
var/last_resist = 0
//var/obj/screen/zone_sel/zone_sel = null
var/datum/hud/zone_sel/zone_sel = null
var/obj/item/device/energy_shield/energy_shield = null
var/custom_gib_handler = null
var/emote_allowed = 1
var/last_emote_time = 0
var/last_emote_wait = 0
var/computer_id = null
var/lastattacker = null
var/lastattacked = null
var/lastattackertime = 0
var/obj/machinery/machine = null
var/other_mobs = null
var/memory = ""
var/atom/movable/pulling = null
var/stat = 0.0
var/next_click = 0
var/transforming = null
var/hand = 0
var/eye_blind = null
var/eye_blurry = null
var/eye_damage = null
var/ear_deaf = null
var/ear_damage = null
var/stuttering = null
var/real_name = null
var/blinded = null
var/druggy = 0
var/asleep = 0
var/sleeping = 0.0
var/resting = 0.0
var/lying = 0.0
var/lying_old = 0
var/canmove = 1.0
var/timeofdeath = 0.0
var/fakeloss = 0
var/fakedead = 0
var/cpr_time = 1.0
var/health = 100
var/max_health = 100
var/bodytemperature = 310.055 // 98.7F / 37C
var/base_body_temp = 310.055
var/temp_tolerance = 15 // iterations between each temperature state
var/thermoregulation_mult = 0.025 // how quickly the body's temperature tries to correct itself, higher = faster
var/innate_temp_resistance = 0.15 // how good the body is at resisting environmental temperature
var/drowsyness = 0.0
var/dizziness = 0
var/is_dizzy = 0
var/is_jittery = 0
var/jitteriness = 0
var/charges = 0.0
var/urine = 0.0
var/nutrition = 0.0
var/paralysis = 0.0
var/stunned = 0.0
var/weakened = 0.0
var/slowed = 0.0
var/last_recovering_msg = 0
var/losebreath = 0.0
var/intent = null
var/shakecamera = 0
var/a_intent = "help"
var/m_intent = "run"
var/lastKnownIP = null
var/obj/stool/buckled = null
var/obj/item/handcuffs/handcuffed = null
var/obj/item/l_hand = null
var/obj/item/r_hand = null
var/obj/item/back = null
var/obj/item/tank/internal = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/ears/ears = null
var/network_device = null
var/Vnetwork = null
var/lastDamageIconUpdate
var/say_language = "english"
var/datum/hud/storage/s_active
var/respawning = 0
var/obj/hud/hud_used = null
var/list/organs = list( )
var/list/grabbed_by = list( )
var/datum/traitHolder/traitHolder
var/inertia_dir = 0
var/footstep = 1
var/music_lastplayed = "null"
var/job = null
var/nodamage = 0
//var/underwear = "No Underwear"
//var/underwear_color = "#FFFFFF"
var/spellshield = 0
var/radiation = 0.0
var/bomberman = 0
var/voice_name = "unidentifiable voice"
var/voice_message = null
var/oldname = null
var/mob/oldmob = null
var/datum/mind/oldmind = null
var/mob/dead/observer/ghost = null
var/twitching = 0
var/attack_alert = 0 // should we message admins when attacking another player?
var/speechverb_say = "says"
var/speechverb_ask = "asks"
var/speechverb_exclaim = "exclaims"
var/speechverb_stammer = "stammers"
var/speechverb_gasp = "gasps"
var/now_pushing = null
//Disease stuff
var/list/resistances = list()
var/list/ailments = list()
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
var/vamp_beingbitten = 0 // Are we being drained by a vampire?
var/atom/eye = null
var/eye_pixel_x = 0
var/eye_pixel_y = 0
var/loc_pixel_x = 0
var/loc_pixel_y = 0
var/icon/cursor = null
var/list/datum/hud/huds = list()
var/client/last_client // actually the current client, used by Logout due to BYOND
var/joined_date = null
mat_changename = 0
mat_changedesc = 0
//Used for combat melee messages (e.g. "Foo punches Bar!")
var/punchMessage = "punches"
var/kickMessage = "kicks"
#ifdef MAP_OVERRIDE_DESTINY
var/last_cryotron_message = 0 // to stop relaymove spam :I
#endif
// mob procs
/mob/New()
traitHolder = new(src)
. = ..()
mobs.Add(src)
/mob/proc/is_spacefaring()
return 0
/mob/Move(a, b, flag)
..()
if (src.s_active && !(s_active.master in src))
src.detach_hud(src.s_active)
src.s_active = null
/mob/disposing()
mobs.Remove(src)
mind = null
ckey = null
client = null
bioHolder = null
pullin = null
internals = null
oxygen = null
i_select = null
m_select = null
bodytemp = null
healths = null
throw_icon = null
zone_sel = null
energy_shield = null
hallucinations = null
buckled = null
handcuffed = null
l_hand = null
r_hand = null
back = null
internal = null
s_active = null
wear_mask = null
ears = null
hud_used = null
organs = null
grabbed_by = null
oldmob = null
oldmind = null
ghost = null
resistances = null
ailments = null
..()
/mob/Login()
// drsingh for cannot read null.address
if (!src || !src.client)
return
if(!src.client.chatOutput.loaded)
//Load custom chat
src.client.chatOutput.start()
src.client.screen = null //ov1 - to make sure we don't keep overlays of our old mob. This is here since logout wont work - when logout is called client is already null
spawn (50)
if (src.client)
src.client.install_macros()
src.last_client = src.client
src.apply_camera(src.client)
src.update_cursor()
src.client.mouse_pointer_icon = src.cursor
logTheThing("diary", null, src, "Login: %target% from [src.client.address]", "access")
src.lastKnownIP = src.client.address
src.computer_id = src.client.computer_id
if (IsGuestKey(src.key))
spawn() alert("Please sign into your BYOND key!")
del(src)
if (config.log_access)
for (var/mob/M in mobs)
if ((!M) || M == src || M.client == null)
continue
else if (M && M.client && M.client.address == src.client.address)
logTheThing("admin", src, M, "has same IP address as %target%")
logTheThing("diary", src, M, "has same IP address as %target%", "access")
if (IP_alerts)
message_admins("<font color='red'><B>Notice: </B><font color='blue'>[key_name(src)] has the same IP address as [key_name(M)]</font>")
else if (M && M.lastKnownIP && M.lastKnownIP == src.client.address && M.ckey != src.ckey && M.key)
logTheThing("diary", src, M, "has same IP address as %target% did (%target% is no longer logged in).", "access")
if (IP_alerts)
message_admins("<font color='red'><B>Notice: </B><font color='blue'>[key_name(src)] has the same IP address as [key_name(M)] did ([key_name(M)] is no longer logged in).</font>")
if (M && M.client && M.client.computer_id == src.client.computer_id)
logTheThing("admin", src, M, "has same computer ID as %target%")
logTheThing("diary", src, M, "has same computer ID as %target%", "access")
message_admins("<font color='red'><B>Notice: </B><font color='blue'>[key_name(src)] has the same <font color='red'><B>computer ID</B><font color='blue'> as [key_name(M)]</font>")
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
else if (M && M.computer_id && M.computer_id == src.client.computer_id && M.ckey != src.ckey && M.key)
logTheThing("diary", src, M, "has same computer ID as %target% did (%target% is no longer logged in).", null, "access")
logTheThing("admin", M, null, "is no longer logged in.")
message_admins("<font color='red'><B>Notice: </B><font color='blue'>[key_name(src)] has the same <font color='red'><B>computer ID</B><font color='blue'> as [key_name(M)] did ([key_name(M)] is no longer logged in).</font>")
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
/* don't get me wrong this was awesome but it's leading to false positives now and we stopped caring about that guy
var/evaderCheck = copytext(lastKnownIP,1, findtext(lastKnownIP, ".", 5))
if (evaderCheck in list("174.50", "69.245", "71.228", "69.247", "71.203", "98.211", "68.53"))
spawn(0)
var/joinstring = "???"
var/list/response = world.Export("http://www.byond.com/members/[src.ckey]?format=text")
if (response && response["CONTENT"])
var/result = html_encode(file2text(response["CONTENT"]))
if (result)
var/pos = findtext(result, "joined = ")
joinstring = copytext(result, pos+14, pos+24)
message_admins("<font color=red>Possible login by That Ban Evader Jerk: [key_name(src)] with IP \"[lastKnownIP]\" and computer ID \[[src.client.computer_id]]. (Regdate: [joinstring])</font>")
logTheThing("admin", src, null, "Possible login by Ban Evader Jerk:. IP: [lastKnownIP], Computer ID: \[[src.client.computer_id]], Regdate: [joinstring]")
logTheThing("diary", src, null, "Possible login by Ban Evader Jerk:. IP: [lastKnownIP], Computer ID: \[[src.client.computer_id]], Regdate: [joinstring]", "admin")
if (!("[src.ckey]" in IRC_alerted_keys))
IRC_alerted_keys += "[src.ckey]"
*/
if (!src.bioHolder) src.bioHolder = new /datum/bioHolder ( src )
world.update_status()
if (!src.hud_used)
src.hud_used = new/obj/hud( src )
else
src.hud_used.dispose()
src.hud_used = new/obj/hud( src )
src.sight |= SEE_SELF
..()
if (src.client)
for (var/datum/hud/hud in src.huds)
hud.add_client(src.client)
src.addOverlaysClient(src.client) //ov1
src.emote_allowed = 1
if (!src.mind)
src.mind = new (src)
if (src.mind && !src.mind.key)
src.mind.key = src.key
if (isobj(src.loc))
var/obj/O = src.loc
if (istype(O))
O.client_login(src)
src.need_update_item_abilities = 1
src.antagonist_overlay_refresh(1, 0)
return
/mob/Logout()
//logTheThing("diary", src, null, "logged out", "access") <- sometimes shits itself and has been known to out traitors. Disabling for now.
src.machine = null
if (src.last_client && !src.key) // lets see if not removing the HUD from disconnecting players helps with the crashes
for (var/datum/hud/hud in src.huds)
hud.remove_client(src.last_client)
..()
return 1
/mob/proc/deliver_move_trigger(ev)
return
/mob/Bump(atom/movable/AM as mob|obj, yes)
if ((!( yes ) || src.now_pushing))
return
src.now_pushing = 1
if (ismob(AM) && istype (AM, /mob/living/carbon/) && istype(src, /mob/living/))
src:viral_transmission(AM,"Contact",1)
if (ismob(AM))
var/mob/tmob = AM
if (!issilicon(AM))
if (tmob.a_intent == "help" && src.a_intent == "help" && tmob.canmove && src.canmove && !tmob.buckled && !src.buckled) // mutual brohugs all around!
var/turf/oldloc = src.loc
var/turf/newloc = tmob.loc
src.set_loc(newloc)
tmob.set_loc(oldloc)
if (istype(tmob.loc, /turf/space))
logTheThing("combat", src, tmob, "trades places with (Help Intent) %target%, pushing them into space.")
else if (locate(/obj/hotspot) in tmob.loc)
logTheThing("combat", src, tmob, "trades places with (Help Intent) %target%, pushing them into a fire.")
deliver_move_trigger("swap")
tmob.deliver_move_trigger("swap")
src.now_pushing = 0
return
if (istype(tmob, /mob/living/carbon/human) && tmob.bioHolder.HasEffect("fat"))
if (prob(40) && !src.bioHolder.HasEffect("fat"))
for(var/mob/M in viewers(src, null))
if (M.client)
boutput(M, "<span style=\"color:red\"><B>[src] fails to push [tmob]'s fat ass out of the way.</B></span>")
src.now_pushing = 0
src.unlock_medal("That's no moon, that's a GOURMAND!", 1)
deliver_move_trigger("bump")
tmob.deliver_move_trigger("bump")
return
src.now_pushing = 0
spawn(0)
..()
if (!istype(AM, /atom/movable))
return
if (!src.now_pushing)
src.now_pushing = 1
if (!AM.anchored)
var/t = get_dir(src, AM)
step(AM, t)
if (istype(AM, /mob/living))
var/mob/victim = AM
deliver_move_trigger("bump")
victim.deliver_move_trigger("bump")
if (victim.buckled && !victim.buckled.anchored)
step(victim.buckled, t)
if (istype(victim.loc, /turf/space))
logTheThing("combat", src, victim, "pushes %target% into space.")
else if (locate(/obj/hotspot) in victim.loc)
logTheThing("combat", src, victim, "pushes %target% into a fire.")
src.now_pushing = null
return
return
// I moved the log entries from human.dm to make them global (Convair880).
/mob/ex_act(severity, last_touched)
logTheThing("combat", src, null, "is hit by an explosion (Severity: [severity]) at [log_loc(src)]. Explosion source last touched by [last_touched]")
return
/mob/proc/projCanHit(datum/projectile/P)
return 1
/mob/proc/attach_hud(datum/hud/hud)
if (!huds.Find(hud))
huds += hud
hud.mobs += src
if (src.client)
hud.add_client(src.client)
/mob/proc/detach_hud(datum/hud/hud)
huds -= hud
hud.mobs -= src
if (src.client)
hud.remove_client(src.client)
/mob/proc/set_eye(atom/new_eye, new_pixel_x = 0, new_pixel_y = 0)
src.eye = new_eye
src.eye_pixel_x = new_pixel_x
src.eye_pixel_y = new_pixel_y
src.update_camera()
/mob/set_loc(atom/new_loc, new_pixel_x = 0, new_pixel_y = 0)
. = ..(new_loc)
src.loc_pixel_x = new_pixel_x
src.loc_pixel_y = new_pixel_y
src.update_camera()
/mob/proc/update_camera()
if (src.client)
apply_camera(src.client)
/mob/proc/apply_camera(client/C)
if (src.eye)
C.eye = src.eye
C.pixel_x = src.eye_pixel_x
C.pixel_y = src.eye_pixel_y
else
C.eye = src
C.pixel_x = src.loc_pixel_x
C.pixel_y = src.loc_pixel_y
/mob/proc/can_strip()
return 1
/mob/proc/set_cursor(icon/cursor)
src.cursor = cursor
if (src.client)
src.client.mouse_pointer_icon = cursor
/mob/proc/update_cursor()
if (src.targeting_spell)
if(client)
src.set_cursor(cursors_selection[client.preferences.target_cursor])
return
else
src.set_cursor('icons/cursors/target/default.dmi')
return
src.set_cursor(null)
// medals
/mob/proc/unlock_medal(title, announce)
return //No medals 4 u
if (!src.client || !src.key)
return
else if (IsGuestKey(src.key))
return
else if (!config || !config.medal_hub || !config.medal_password)
return
var/key = src.key
spawn ()
var/list/unlocks = list()
for(var/A in rewardDB)
var/datum/achievementReward/D = rewardDB[A]
if (D.required_medal == title)
unlocks.Add(D)
var/result = world.SetMedal(title, key, config.medal_hub, config.medal_password)
if (result == 1)
if (announce)
boutput(world, "<span class=\"medal\">[key] earned the [title] medal.</span>")//src.client.stealth ? src.client.fakekey : << seems to be causing trouble
else if (ismob(src) && src.client)
boutput(src, "<span class=\"medal\">You earned the [title] medal.</span>")
if (length(unlocks))
for(var/datum/achievementReward/B in unlocks)
boutput(src, "<FONT FACE=Arial COLOR=gold SIZE=+1>You've unlocked a Reward : [B.title]!</FONT>")
else if (isnull(result) && ismob(src) && src.client)
return
// boutput(src, "<span style=\"color:red\">You would have earned the [title] medal, but there was an error communicating with the BYOND hub.</span>")
/mob/proc/has_medal(var/medal) //This is not spawned because of return values. Make sure the proc that uses it uses spawn or you lock up everything.
if (IsGuestKey(src.key))
return null
else if (!config)
return null
else if (!config.medal_hub || !config.medal_password)
return null
var/result = world.GetMedal(medal, src.key, config.medal_hub, config.medal_password)
return result
/mob/verb/list_medals()
set name = "Medals"
if (IsGuestKey(src.key))
boutput(src, "<span style=\"color:red\">Sorry, you are a guest and cannot have medals.</span>")
return
else if (!config)
boutput(src, "<span style=\"color:red\">Sorry, medal information is currently not available.</span>")
return
else if (!config.medal_hub || !config.medal_password)
boutput(src, "<span style=\"color:red\">Sorry, this server does not have medals enabled.</span>")
return
boutput(src, "Retrieving your medal information...")
spawn ()
var/medals = world.GetMedal("", src.key, config.medal_hub, config.medal_password)
if (isnull(medals))
boutput(src, "<span style=\"color:red\">Sorry, could not contact the BYOND hub for your medal information.</span>")
return
if (!medals)
boutput(src, "<b>You don't have any medals.</b>")
return
medals = params2list(medals)
medals = sortList(medals)
boutput(src, "<b>Medals:</b>")
for (var/medal in medals)
boutput(src, "&emsp;[medal]")
boutput(src, "<b>You have [length(medals)] medal\s.</b>")
/mob/verb/setdnr()
set name = "Set DNR"
set desc = "Set yourself as Do Not Resuscitate."
var/confirm = alert("Set yourself as Do Not Resuscitate (WARNING: This is one-use only and will prevent you from being revived in any manner)", "Set Do Not Resuscitate", "Yes", "Cancel")
if (confirm == "Cancel")
return
if (confirm == "Yes")
if (src.mind)
src.verbs -= list(/mob/verb/setdnr)
src.mind.dnr = 1
boutput(src, "<span style=\"color:red\">DNR status set!</span>")
else
src << alert("There was an error setting this status. Perhaps you are a ghost?")
return
/mob/proc/Cell()
set category = "Admin"
set hidden = 1
if (!loc) return 0
var/datum/gas_mixture/environment = loc.return_air()
//
var/t = "<span style=\"color:blue\">Coordinates: [x],[y]<br></span>"
t+= "<span style=\"color:red\">Temperature: [environment.temperature]<br></span>"
t+= "<span style=\"color:blue\">Nitrogen: [environment.nitrogen]<br></span>"
t+= "<span style=\"color:blue\">Oxygen: [environment.oxygen]<br></span>"
t+= "<span style=\"color:blue\">Plasma : [environment.toxins]<br></span>"
t+= "<span style=\"color:blue\">Carbon Dioxide: [environment.carbon_dioxide]<br></span>"
if (environment.trace_gases)
for(var/datum/gas/trace_gas in environment.trace_gases)
boutput(usr, "<span style=\"color:blue\">[trace_gas.type]: [trace_gas.moles]<br></span>")
else
boutput(usr, "<span style=\"color:blue\">No trace gases.<br></span>")
usr.show_message(t, 1)
/obj/equip_e/proc/process()
return
/obj/equip_e/proc/done()
return
/obj/equip_e/New()
if (!ticker)
qdel(src)
return
spawn(100)
qdel(src)
return
..()
return
/mob/proc/show_message(msg, type, alt, alt_type)
if (!src.client)
return
// We have procs to check for this stuff, you know. Ripped out a bunch of duplicate code, which also fixed earmuffs (Convair880).
if (type)
if ((type & 1) && !src.sight_check(1))
if (!alt)
return
else
msg = alt
type = alt_type
if ((type & 2) && !src.hearing_check(1))
if (!alt)
return
else
msg = alt
type = alt_type
if ((type & 1) && !src.sight_check(1))
return
if (src.stat == 1 || src.sleeping || src.paralysis)
if (prob(20))
boutput(src, "<I>... You can almost hear something ...</I>")
if (istype(src, /mob/living))
for (var/mob/dead/target_observer/observer in src:observers)
boutput(observer, "<I>... You can almost hear something ...</I>")
else
boutput(src, msg)
var/psychic_link = src.get_psychic_link()
if (ismob(psychic_link))
boutput(psychic_link, msg)
if (istype(src, /mob/living))
for (var/mob/dead/target_observer/observer in src:observers)
boutput(observer, msg)
// 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 AIviewers(src))
if (!M.client)
continue
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 AIviewers(src))
if (!M.client)
continue
M.show_message(message, 1, blind_message, 2)
// for things where there are three parties that should recieve different messages (specifically made for surgery):
// viewer_message, the thing visible to everyone except specified targets
// first_message, the thing visible to first_target
// second_message, the thing visible to second_target
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/mob/proc/tri_message(var/viewer_message, var/first_target, var/first_message, var/second_target, var/second_message, var/blind_message)
for (var/mob/M in AIviewers(src))
if (!M.client)
continue
var/msg = viewer_message
if (first_message && M == first_target)
msg = first_message
if (second_message && M == second_target && M != first_target)
msg = second_message
M.show_message(msg, 1, blind_message, 2)
//DEBUG_MESSAGE("<b>[M] recieves message: &quot;[msg]&quot;</b>")
// it was about time we had this instead of just visible_message()
/atom/proc/audible_message(var/message)
for (var/mob/M in all_hearers(null, src))
if (!M.client)
continue
M.show_message(message, 2)
/mob/audible_message(var/message, var/self_message)
for (var/mob/M in all_hearers(null, src))
if (!M.client)
continue
var/msg = message
if (self_message && M==src)
msg = self_message
M.show_message(msg, 2)
/mob/proc/unequip_all()
if (isobserver(src))
var/obj/ecto = new/obj/item/reagent_containers/food/snacks/ectoplasm
ecto.loc = src.loc
return
/mob/living/unequip_all(var/delete_stuff = 0)
for (var/obj/item/W in src)
if (istype(W, /obj/item/parts) && W:holder == src)
continue
src.u_equip(W)
if (W)
W.set_loc(src.loc)
W.dropped(src)
W.layer = initial(W.layer)
if (delete_stuff)
qdel(W)
return
/mob/living/carbon/human/unequip_all(var/delete_stuff = 0)
for (var/obj/item/W in src)
if (istype(W, /obj/item/parts) && W:holder == src)
continue
if (src.organHolder)
if (istype(W, /obj/item/organ/chest) && src.organHolder.chest == W)
continue
if (istype(W, /obj/item/organ/head) && src.organHolder.head == W)
continue
if (istype(W, /obj/item/skull) && src.organHolder.skull == W)
continue
if (istype(W, /obj/item/organ/brain) && src.organHolder.brain == W)
continue
if (istype(W, /obj/item/organ/eye) && (src.organHolder.left_eye == W || src.organHolder.right_eye == W))
continue
if (istype(W, /obj/item/organ/heart) && src.organHolder.heart == W)
continue
if (istype(W, /obj/item/organ/lung) && (src.organHolder.left_lung == W || src.organHolder.right_lung == W))
continue
if (istype(W, /obj/item/clothing/head/butt) && src.organHolder.butt == W)
continue
src.u_equip(W)
if (W)
W.set_loc(src.loc)
W.dropped(src)
W.layer = initial(W.layer)
if (delete_stuff)
qdel(W)
return
/mob/proc/findname(msg)
for(var/mob/M in mobs)
if (M.real_name == text("[]", msg))
return M
return 0
/mob/proc/movement_delay()
return 0
/mob/proc/Life(datum/controller/process/mobs/parent)
return
// for mobs without organs
/mob/proc/TakeDamage(zone, brute, burn, tox, damage_type)
hit_twitch()
src.health -= max(0, brute)
if (!is_heat_resistant())
src.health -= max(0, burn)
/mob/proc/TakeDamageAccountArmor(zone, brute, burn, tox, damage_type)
TakeDamage(zone, brute, burn)
/mob/proc/HealDamage(zone, brute, burn, tox)
health += max(0, brute)
health += max(0, burn)
health += max(0, tox)
health = min(max_health, health)
// less icon caching maybe?!
#define FACE 1
#define BODY 2
#define CLOTHING 4
#define DAMAGE 8
/mob/var/icon_rebuild_flag = 0
/mob/proc/update_icons_if_needed()
if (icon_rebuild_flag & FACE)
update_face()
if (icon_rebuild_flag & BODY)
update_body()
if (icon_rebuild_flag & CLOTHING)
update_clothing()
if (icon_rebuild_flag & DAMAGE)
UpdateDamageIcon()
/mob/proc/set_clothing_icon_dirty()
icon_rebuild_flag |= CLOTHING
/mob/proc/update_clothing()
icon_rebuild_flag &= ~CLOTHING
/mob/proc/set_body_icon_dirty()
icon_rebuild_flag |= BODY
/mob/proc/update_body()
icon_rebuild_flag &= ~BODY
/mob/proc/UpdateDamage()
return
/mob/proc/set_damage_icon_dirty()
icon_rebuild_flag |= DAMAGE
/mob/proc/UpdateDamageIcon()
if (lastDamageIconUpdate && !(world.time - lastDamageIconUpdate))
return
lastDamageIconUpdate = world.time
icon_rebuild_flag &= ~DAMAGE
/mob/proc/set_face_icon_dirty()
icon_rebuild_flag |= FACE
/mob/proc/update_face()
icon_rebuild_flag &= ~FACE
#undef FACE
#undef BODY
#undef CLOTHING
#undef DAMAGE
/mob/proc/death(gibbed)
//Traitor's dead! Oh no!
if (src.mind && src.mind.special_role)
message_admins("<span style=\"color:red\">Antagonist [key_name(src)] ([src.mind.special_role]) died at [log_loc(src)].</span>")
src.timeofdeath = world.time
return ..(gibbed)
/mob/proc/restrained()
if (src.handcuffed)
return 1
/mob/proc/key_down(var/key)
/mob/proc/key_up(var/key)
/mob/proc/click(atom/target, params)
var/list/parameters = params2list(params)
if (src.targeting_spell)
var/datum/targetable/S = src.targeting_spell
src.targeting_spell = null
update_cursor()
if (!S.target_anything && !ismob(target))
src.show_text("You have to target a person.", "red")
if(S.sticky)
src.targeting_spell = S
update_cursor()
return 100
if (!isturf(target.loc) && !isturf(target))
if(S.sticky)
src.targeting_spell = S
update_cursor()
return 100
if (S.check_range && (get_dist(src, target) > S.max_range) )
src.show_text("You are too far away from the target.", "red") // At least tell them why it failed.
if(S.sticky)
src.targeting_spell = S
update_cursor()
return 100
if (!S.can_target_ghosts && ismob(target) && (!isliving(target) || iswraith(target) || isintangible(target)))
src.show_text("It would have no effect on this target.", "red")
if(S.sticky)
src.targeting_spell = S
update_cursor()
return 100
if (!S.castcheck(src))
if(S.sticky)
src.targeting_spell = S
update_cursor()
return 100
actions.interrupt(src, INTERRUPT_ACTION)
spawn
S.handleCast(target)
if(S)
if((S.ignore_sticky_cooldown && !S.cooldowncheck()) || (S.sticky && S.cooldowncheck()))
if(src)
src.targeting_spell = S
src.update_cursor()
return 100
if (abilityHolder)
if (abilityHolder.topBarRendered)
if (abilityHolder.click(target, params))
return 100
if (src.client.holder)
if (("ctrl" in parameters) && ("right" in parameters))
usr.client.debug_variables(target)
//circumvented by some rude hack in client.dm; uncomment if hack ceases to exist
//if (istype(target, /obj/screen/ability))
// target:clicked(params)
if (get_dist(src, target) > 0)
dir = get_dir(src, target)
/mob/proc/action(num)
if(src.abilityHolder)
src.abilityHolder.actionKey(num)
return
/mob/proc/south_east()
return
/mob/proc/drop_item_v()
if (src.stat == 0)
drop_item()
return
/mob/proc/drop_from_slot(var/obj/item/item, var/turf/T)
if (!item)
return
if (!(item in src.contents))
return
if (item.cant_drop)
return
if (item.cant_self_remove && src.l_hand != item && src.r_hand != item)
return
u_equip(item)
src.set_clothing_icon_dirty()
if (!T)
T = src.loc
if (item)
item.set_loc(T)
item.dropped(src)
if (item)
item.layer = initial(item.layer)
T.Entered(item)
return
/mob/proc/drop_item()
var/obj/item/W = src.equipped()
if (istype(W))
var/obj/item/magtractor/origW
if (W.useInnerItem && W.contents.len > 0)
if (istype(W, /obj/item/magtractor))
origW = W
W = pick(W.contents)
if (!W || W.cant_drop) return
u_equip(W)
if (W)
if (istype(src.loc, /obj/vehicle))
var/obj/vehicle/V = src.loc
if (V.throw_dropped_items_overboard == 1)
W.set_loc(get_turf(V))
else
W.set_loc(src.loc)
else if (istype(src.loc, /obj/machinery/bot/mulebot))
W.set_loc(get_turf(src.loc))
else
W.set_loc(src.loc)
W.dropped(src)
if (W)
W.layer = initial(W.layer)
var/turf/T = get_turf(src.loc)
T.Entered(W)
if (origW)
origW.holding = null
actions.stopId("magpickerhold", src)
return 1
return 0
/mob/proc/remove_item(var/obj/O)
if (O)
u_equip(O)
src.set_clothing_icon_dirty()
/mob/proc/equipped()
if (issilicon(src))
if (ishivebot(src)||isrobot(src))
if (src:module_active)
return src:module_active
else
if (src.hand)
return src.l_hand
else
return src.r_hand
return
/mob/proc/swap_hand()
return
/mob/proc/u_equip(W as obj)
// I think this bit is handled by each method of dropping it, and it prevents dropping items in your hands and other procs using u_equip so I'll get rid of it for now.
// if (hasvar(W,"cant_self_remove"))
// if (W:cant_self_remove) return
if (W == src.r_hand)
src.r_hand = null
else if (W == src.l_hand)
src.l_hand = null
else if (W == src.handcuffed)
src.handcuffed = null
else if (W == src.back)
src.back = null
else if (W == src.wear_mask)
src.wear_mask = null
if (src.client)
src.client.screen -= W
set_clothing_icon_dirty()
/mob/proc/ret_grab(obj/list_container/mobl/L as obj, flag)
if (!(locate(/obj/item/grab) in src))
if (!L)
return null
else
return L.container
else
if (!L)
L = new /obj/list_container/mobl( null )
L.container += src
L.master = src
for (var/obj/item/grab/G in src)
if (!G.affecting)
qdel(G)
return
if (!( L.container.Find(G.affecting) ))
L.container += 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/dump_source()
var/master = "<PRE>"
for(var/t in typesof(/area))
master += text("[]<br>", t)
//Foreach goto(26)
src << browse(master)
return
*/
/mob/verb/memory()
set name = "Notes"
// drsingh for cannot execute null.show_memory
if (isnull(mind))
return
mind.show_memory(src)
// for(var/datum/objective/objective in mind.objectives)
//if (istype(objective, /datum/objective/aikill))
// usr << browse('icons/AIobjective.jpg',"window=some;titlebar=1;size=550x400;can_minimize=0;can_resize=0")
// if (istype(objective, /datum/objective/destroy_outpost))
// usr << browse('nukezeta.jpg',"window=some;titlebar=1;size=550x400;can_minimize=0;can_resize=0")
/mob/verb/add_memory(msg as message)
set name = "Add Note"
if (mind.last_memory_time + 10 <= world.time)
mind.last_memory_time = world.time
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = sanitize(msg)
mind.store_memory(msg)
// please note that this store_memory() vvv
// does not store memories in the notes
// it is named the same thing as the mind proc to store notes, but it does not store 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(src.memory) == 0)
src.memory += msg
else
src.memory += "<BR>[msg]"
if (popup)
src.memory()
/mob/proc/recite_miranda()
set name = "Recite Miranda Rights"
if (isnull(src.mind))
return
if (isnull(src.mind.miranda))
src.say_verb("You have the right to remain silent. Anything you say can and will be used against you in a NanoTrasen court of Space Law. You have the right to a rent-an-attorney. If you cannot afford one, a monkey in a suit and funny hat will be appointed to you.")
return
src.say_verb(src.mind.miranda)
/mob/proc/add_miranda()
set name = "Set Miranda Rights"
if (isnull(src.mind))
return
if (src.mind.last_memory_time + 10 <= world.time) // leaving it using this var cause vOv
src.mind.last_memory_time = world.time // why not?
if (isnull(src.mind.miranda))
src.mind.set_miranda("You have the right to remain silent. Anything you say can and will be used against you in a NanoTrasen court of Space Law. You have the right to a rent-an-attorney. If you cannot afford one, a monkey in a suit and funny hat will be appointed to you.")
src.mind.show_miranda(src)
var/new_rights = input(usr, "Change what you will say with the Say Miranda Rights verb.", "Set Miranda Rights", src.mind.miranda) as null|text
if (!new_rights || new_rights == src.mind.miranda)
src.show_text("Miranda rights not changed.", "red")
return
new_rights = copytext(new_rights, 1, MAX_MESSAGE_LEN)
new_rights = sanitize(strip_html(new_rights))
src.mind.set_miranda(new_rights)
logTheThing("telepathy", src, null, "has set their miranda rights quote to: [src.mind.miranda]")
src.show_text("Miranda rights set to \"[src.mind.miranda]\"", "blue")
/mob/verb/help()
set name = "Help"
//src << browse('browserassets/html/admin/help.html', "window=help")
//boutput(src, "<span style=\"color:blue\">Please visit the goonstation wiki at <b>http://wiki.ss13.co</b> for more indepth help.</span>")
return
/mob/verb/hotkeys()
set name = "Hotkeys"
//src << browse('browserassets/html/admin/hotkeys.html', "window=help")
return
/mob/verb/abandon_mob()
set name = "Respawn"
if (!( abandon_allowed ))
return
if ((src.stat != 2 || !( ticker )))
boutput(usr, "<span style=\"color:blue\"><B>You must be dead to use this!</B></span>")
return
logTheThing("diary", usr, null, "used abandon mob.", "game")
//boutput(usr, "<span style=\"color:blue\"><B>Please roleplay correctly!</B></span>")
if (!src.client)
logTheThing("diary", usr, null, "AM failed due to disconnect.", "game")
return
for(var/obj/screen/t in usr.client.screen)
if (t.loc == null)
//t = null
qdel(t)
if (!src.client)
logTheThing("diary", usr, null, "AM failed due to disconnect.", "game")
return
var/mob/new_player/M = new /mob/new_player()
if (!src.client)
logTheThing("diary", usr, null, "AM failed due to disconnect.", "game")
qdel(M)
return
if (src.client && src.client.holder && (src.client.holder.state == 2))
src.client.admin_play()
return
M.key = src.client.key
M.Login()
return
/mob/verb/cmd_rules()
set name = "Rules"
src << browse(rules, "window=rules;size=480x320")
/mob/verb/togglelocaldeadchat()
set desc = "Toggle whether you can hear all chat while dead or just local chat"
set name = "Toggle Deadchat Range"
if (!usr.client) //How could this even happen?
return
usr.client.local_deadchat = !usr.client.local_deadchat
boutput(usr, "<span style=\"color:blue\">[usr.client.local_deadchat ? "Now" : "No longer"] hearing local chat only.</span>")
/mob/verb/succumb()
set hidden = 1
/*
//prevent a suicide if the person is infected with the headspider disease.
for (var/datum/ailment/V in src.ailments)
if (istype(V, /datum/ailment/parasite/headspider) || istype(V, /datum/ailment/parasite/alien_embryo))
boutput(src, "You can't muster the willpower. Something is preventing you from doing it.")
return
*/
//or if they are being drained of blood
if (src.vamp_beingbitten)
boutput(src, "You can't muster the willpower. Something is preventing you from doing it.")
return
if (src.health < 0)
boutput(src, "<span style=\"color:blue\">You have given up life and succumbed to death.</span>")
src.death()
if (!src.suiciding)
src.unlock_medal("Yield", 1)
logTheThing("combat", src, null, "succumbs")
/mob/verb/cancel_camera()
set name = "Cancel Camera View"
src.set_eye(null)
src.machine = null
if (istype(src, /mob/living))
if (src:cameraFollow)
src:cameraFollow = null
else
src.sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
/mob/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if (air_group || (height==0)) return 1
if (istype(mover, /obj/projectile))
return !projCanHit(mover:proj_data)
if (ismob(mover))
var/mob/moving_mob = mover
if ((src.other_mobs && moving_mob.other_mobs))
return 1
return (!mover.density || !src.density || src.lying)
else
return (!mover.density || !src.density || src.lying)
return
/mob/proc/update_inhands()
/mob/proc/put_in_hand(obj/item/I, hand)
return 0
/mob/proc/get_damage()
return src.health
/mob/bullet_act(var/obj/projectile/P)
var/damage = 0
damage = round((P.power*P.proj_data.ks_ratio), 1.0)
var/stun = 0
stun = round((P.power*(1.0-P.proj_data.ks_ratio)), 1.0)
if (src.material) src.material.triggerOnAttacked(src, P.shooter, src, (ismob(P.shooter) ? P.shooter:equipped() : P.shooter))
for(var/atom/A in src)
if (A.material)
A.material.triggerOnAttacked(A, P.shooter, src, (ismob(P.shooter) ? P.shooter:equipped() : P.shooter))
switch(P.proj_data.damage_type)
if (D_KINETIC)
TakeDamage("All", damage, 0)
if (D_PIERCING)
TakeDamage("All", damage / 2, 0)
if (D_SLASHING)
TakeDamage("All", damage, 0)
if (D_ENERGY)
TakeDamage("All", 0, damage)
if (prob(stun))
src.paralysis += stun
else if (prob(90))
src.stunned += stun
else
src.weakened += (stun/2)
src.set_clothing_icon_dirty()
if (D_BURNING)
TakeDamage("All", 0, damage)
if (D_RADIOACTIVE)
src.irradiate(damage)
src.stuttering += stun
src.drowsyness += stun
if (D_TOXIC)
src.take_toxin_damage(damage)
if (!P.proj_data.silentshot)
src.visible_message("<span style=\"color:red\">[src] is hit by the [P]!</span>")
actions.interrupt(src, INTERRUPT_ATTACKED)
return
/mob/proc/can_use_hands()
if (src.handcuffed)
return 0
if (src.buckled && istype(src.buckled, /obj/stool/bed)) // buckling does not restrict hands
return 0
return 1
/mob/proc/is_active()
return (0 >= usr.stat)
/mob/proc/see(message)
if (!src.is_active())
return 0
boutput(src, message)
return 1
/mob/proc/show_viewers(message)
for(var/mob/M in AIviewers())
M.see(message)
/mob/proc/updatehealth()
if (src.nodamage == 0)
src.health = max_health - src.get_oxygen_deprivation() - src.get_toxin_damage() - src.get_burn_damage() - src.get_brute_damage()
else
src.health = max_health
src.stat = 0
/mob/proc/adjustBodyTemp(actual, desired, incrementboost, divisor)
var/temperature = actual
var/difference = abs(actual-desired) // get difference
var/increments = difference * divisor //find how many increments apart they are
var/change = increments*incrementboost // Get the amount to change by (x per increment)
//change = change * 0.10
if (actual < desired) // Too cold
temperature += change
if (actual > desired)
temperature = desired
if (actual > desired) // Too hot
temperature -= change
if (actual < desired)
temperature = desired
return temperature
/mob/proc/gib(give_medal)
if (istype(src, /mob/dead/observer))
var/list/virus = src.ailments
gibs(src.loc, virus)
return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
logTheThing("combat", src, null, "is blown apart")
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
var/bdna = null // For forensics (Convair880).
var/btype = null
if (ishuman(src))
if (src.bioHolder)
bdna = src.bioHolder.Uid // Ditto (Convair880).
btype = src.bioHolder.bloodType
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("gibbed", animation)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
var/mob/dead/observer/newmob = ghostize()
if (!isnull(newmob) && give_medal)
newmob.unlock_medal("Gore Fest", 1)
var/list/viral_list = list()
for (var/datum/ailment_data/AD in src.ailments)
viral_list += AD
if (!custom_gib_handler)
if (iscarbon(src))
var/list/ejectables = list_ejectables()
if (bdna && btype)
. = gibs(src.loc, viral_list, ejectables, bdna, btype) // For forensics (Convair880).
else
. = gibs(src.loc, viral_list, ejectables)
else
. = robogibs(src.loc, viral_list)
else
call(custom_gib_handler)(src.loc, viral_list, list_ejectables(), bdna, btype)
for(var/obj/item/implant/I in src) qdel(I)
if (animation)
animation.master = null
spawn(30)
if (animation) qdel(animation)
qdel(src)
return
/mob/proc/elecgib()
if (istype(src, /mob/dead)) return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
logTheThing("combat", src, null, "is fried")
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
if (ishuman(src))
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("elecgibbed", animation)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
if (!iscarbon(src))
var/list/virus = src.ailments
robogibs(src.loc, virus)
qdel(src)
/mob/proc/firegib()
if (istype(src, /mob/dead)) return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
logTheThing("combat", src, null, "is fried")
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
if (ishuman(src))
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("firegibbed", animation)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
if (!iscarbon(src))
var/list/virus = src.ailments
robogibs(src.loc, virus)
qdel(src)
/mob/proc/partygib(give_medal)
if (istype(src, /mob/dead))
var/list/virus = src.ailments
partygibs(src.loc, virus)
return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
var/bdna = null // For forensics (Convair880).
var/btype = null
if (ishuman(src))
if (src.bioHolder)
bdna = src.bioHolder.Uid // Ditto (Convair880).
btype = src.bioHolder.bloodType
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("gibbed", animation)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
var/list/virus = src.ailments
if (bdna && btype)
partygibs(src.loc, virus, bdna, btype) // For forensics (Convair880).
else
partygibs(src.loc, virus)
playsound(src.loc, "sound/items/bikehorn.ogg", 100, 1)
qdel(src)
/mob/proc/owlgib(give_medal)
if (istype(src, /mob/dead))
var/list/virus = src.ailments
gibs(src.loc, virus)
return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
var/bdna = null // For forensics (Convair880).
var/btype = null
if (ishuman(src))
if (src.bioHolder)
bdna = src.bioHolder.Uid // Ditto (Convair880).
btype = src.bioHolder.bloodType
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("owlgibbed", animation)
var/obj/critter/owl/O = new /obj/critter/owl(src.loc)
O.name = pick("Hooty Mc[src.real_name]", "Professor [src.real_name]", "Screechin' [src.real_name]")
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
var/list/virus = src.ailments
if (bdna && btype)
gibs(src.loc, virus, null, bdna, btype) // For forensics (Convair880).
else
gibs(src.loc, virus)
playsound(src.loc, "sound/misc/hoot.ogg", 100, 1)
qdel(src)
/mob/proc/vaporize(give_medal, forbid_abberation)
if (istype(src, /mob/dead))
return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
if (ishuman(src))
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("disintegrated", animation)
if (prob(20))
new /obj/decal/cleanable/ash(src.loc)
if (!forbid_abberation && prob(50))
new /obj/critter/aberration(src.loc)
else
gibs(src.loc)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
var/datum/effects/system/spark_spread/s = unpool(/datum/effects/system/spark_spread)
s.set_up(2, 1, src.loc)
s.start()
qdel(src)
/mob/proc/implode(give_medal)
if (istype(src, /mob/dead)) return
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
logTheThing("combat", src, null, "implodes")
src.death(1)
var/atom/movable/overlay/animation = null
src.transforming = 1
src.canmove = 0
src.icon = null
src.invisibility = 101
if (ishuman(src))
animation = new(src.loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("implode", animation)
if ((src.mind || src.client) && !istype(src, /mob/living/carbon/human/npc))
ghostize()
playsound(src.loc, "sound/misc/loudcrunch2.ogg", 100, 1)
qdel(src)
/mob/proc/cluwnegib(var/duration = 30)
if(istype(src, /mob/dead)) return
spawn(0) //multicluwne
duration = minmax(duration, 10, 100)
#ifdef DATALOGGER
game_stats.Increment("violence")
#endif
logTheThing("combat", src, null, "is taken by the floor cluwne")
src.transforming = 1
src.canmove = 0
src.anchored = 1
src.mouse_opacity = 0
var/mob/living/carbon/human/cluwne/floor/floorcluwne = new(null)
var/list/cardinals = list(NORTH, SOUTH, WEST, EAST)
var/turf/the_turf = null
while(!the_turf)
if(cardinals.len)
var/C = pick(cardinals)
the_turf = get_step(src, C)
if(the_turf.density)
the_turf = null //Prefer floors
cardinals -= C
else
the_turf = get_turf(src)
break //Well, if we're at null we don't want an infinite loop
if(!the_turf)
src.gib()
return
src.show_text("<span style=\"font-weight:bold; font-style:italic; color:red; font-family:'Comic Sans MS', sans-serif; font-size:200%;\">It's coming!!!</span>")
playsound(the_turf, 'sound/ambience/lavamoon_strange_fx1.ogg', 70, 1)
floorcluwne.loc=the_turf //I actually do want to bypass Entered() and Exit() stuff now tyvm
animate_slide(the_turf, 0, -24, duration)
sleep(duration/2)
if(!floorcluwne)
animate_slide(the_turf, 0, 0, duration)
src.gib()
return
floorcluwne.say("honk honk motherfucker")
floorcluwne.point(src)
sleep(duration/2)
if(!floorcluwne)
animate_slide(the_turf, 0, 0, duration)
src.gib()
return
floorcluwne.visible_message("<span style='font-weight:bold; color:red;'>[floorcluwne] drags [src] beneath \the [the_turf]!</span>")
playsound(floorcluwne.loc, 'sound/weapons/thudswoosh.ogg', 60, 2)
src.set_loc(the_turf)
src.layer=0
animate_slide(the_turf, 0, 0, duration)
spawn(duration+5)
src.death(1)
src.ghostize()
qdel(src)
qdel(floorcluwne)
// Man, there's a lot of possible inventory spaces to store crap. This should get everything under normal circumstances.
// Well, it's hard to account for every possible matryoshka scenario (Convair880).
/mob/proc/get_all_items_on_mob()
if (!src || !ismob(src))
return 0
var/list/L = list()
L += src.contents // Item slots.
for (var/obj/item/storage/S in src.contents) // Backpack, belt, briefcases etc.
var/list/T1 = S.get_all_contents()
for (var/obj/O1 in T1)
if (!L.Find(O1)) L.Add(O1)
for (var/obj/item/gift/G in src.contents)
if (!L.Find(G.gift)) L += G.gift
if (istype(G.gift, /obj/item/storage))
var/obj/item/storage/S2 = G.gift
var/list/T2 = S2.get_all_contents()
for (var/obj/O2 in T2)
if (!L.Find(O2)) L.Add(O2)
for (var/obj/item/storage/backpack/BP in src.contents) // Backpack boxes etc.
for (var/obj/item/storage/S3 in BP.contents)
var/list/T3 = S3.get_all_contents()
for (var/obj/O3 in T3)
if (!L.Find(O3)) L.Add(O3)
for (var/obj/item/gift/G2 in BP.contents)
if (!L.Find(G2.gift)) L += G2.gift
if (istype(G2.gift, /obj/item/storage))
var/obj/item/storage/S4 = G2.gift
var/list/T4 = S4.get_all_contents()
for (var/obj/O4 in T4)
if (!L.Find(O4)) L.Add(O4)
for (var/obj/item/storage/belt/BL in src.contents) // Stealth storage in belts etc.
for (var/obj/item/storage/S5 in BL.contents)
var/list/T5 = S5.get_all_contents()
for (var/obj/O5 in T5)
if (!L.Find(O5)) L.Add(O5)
for (var/obj/item/gift/G3 in BL.contents)
if (!L.Find(G3.gift)) L += G3.gift
if (istype(G3.gift, /obj/item/storage))
var/obj/item/storage/S6 = G3.gift
var/list/T6 = S6.get_all_contents()
for (var/obj/O6 in T6)
if (!L.Find(O6)) L.Add(O6)
for (var/obj/item/storage/box/syndibox/SB in L) // For those "belt-in-stealth storage-in-backpack" situations.
for (var/obj/item/storage/S7 in SB.contents)
var/list/T7 = S7.get_all_contents()
for (var/obj/O7 in T7)
if (!L.Find(O7)) L.Add(O7)
for (var/obj/item/gift/G4 in SB.contents)
if (!L.Find(G4.gift)) L += G4.gift
if (istype(G4.gift, /obj/item/storage))
var/obj/item/storage/S8 = G4.gift
var/list/T8 = S8.get_all_contents()
for (var/obj/O8 in T8)
if (!L.Find(O8)) L.Add(O8)
return L
// Made these three procs use get_all_items_on_mob(). "Steal X" objective should work more reliably as a result (Convair880).
/mob/proc/check_contents_for(A, var/accept_subtypes = 0)
if (!src || !ismob(src) || !A)
return 0
var/list/L = src.get_all_items_on_mob()
if (L && L.len)
for (var/obj/B in L)
if (B.type == A || (accept_subtypes && istype(B, A)))
return 1
return 0
/mob/proc/check_contents_for_num(A, X, var/accept_subtypes = 0)
if (!src || !ismob(src) || !A)
return 0
var/tally = 0
var/list/L = src.get_all_items_on_mob()
if (L && L.len)
for (var/obj/B in L)
if (B.type == A || (accept_subtypes && istype(B, A)))
tally++
if (tally >= X)
return 1
return 0
#define REFRESH "* Refresh list"
/mob/proc/print_contents(var/mob/output_target)
if (!src || !ismob(src) || !output_target || !ismob(output_target))
return
var/list/L = src.get_all_items_on_mob()
if (L && L.len)
var/list/OL = list() // Sorted output list. Could definitely be improved, but is functional enough.
var/list/O_names = list()
var/list/O_namecount = list()
OL.Add(REFRESH)
for (var/obj/O in L)
if (!OL.Find(O))
var/N = O.name
var/N2
if (O.loc == src)
N2 = "mob"
else
N2 = O.loc.name
if (N in O_names)
O_namecount[N]++
N = text("[] #[]", N, O_namecount[N])
else
O_names.Add(N)
O_namecount[N] = 1
var/N3 = "[N2]: [N]"
OL[N3] = O
OL = sortList(OL)
selection
var/IP = input(output_target, "Select item to view fingerprints, cancel to close window.", "[src]'s inventory") as null|anything in OL
if (!IP || !output_target || !ismob(output_target))
return
if (!src || !ismob(src))
output_target.show_text("Target mob doesn't exist anymore.", "red")
return
if (IP == REFRESH)
src.print_contents(output_target)
return
if (isnull(OL[IP]) || !isobj(OL[IP]))
output_target.show_text("Selected object reference is invalid (item deleted?). Try freshing the list.", "red")
goto selection
if (output_target.client)
output_target.client.view_fingerprints(OL[IP])
goto selection
return
#undef REFRESH
// adds a dizziness amount to a mob
// use this rather than directly changing var/dizziness
// since this ensures that the dizzy_process proc is started
// currently only humans get dizzy
// value of dizziness ranges from 0 to 500
// below 100 is not dizzy
/mob/proc/make_dizzy(var/amount)
if (!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
return
dizziness = min(500, dizziness + amount) // store what will be new value
// clamped to max 500
if (dizziness > 100 && !is_dizzy)
spawn(0)
dizzy_process()
// dizzy process - wiggles the client's pixel offset over time
// spawned from make_dizzy(), will terminate automatically when dizziness gets <100
// note dizziness decrements automatically in the mob's Life() proc.
/mob/proc/dizzy_process()
is_dizzy = 1
while(dizziness > 100)
if (client)
var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70
client.pixel_x = amplitude * sin(0.008 * dizziness * world.time)
client.pixel_y = amplitude * cos(0.008 * dizziness * world.time)
sleep(1)
//endwhile - reset the pixel offsets to zero
is_dizzy = 0
if (client)
client.pixel_x = 0
client.pixel_y = 0
// jitteriness - copy+paste of dizziness
/mob/proc/make_jittery(var/amount)
if (!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
return
jitteriness = min(500, jitteriness + amount) // store what will be new value
// clamped to max 500
if (jitteriness > 100 && !is_jittery)
spawn(0)
jittery_process()
// jittery process - shakes the mob's pixel offset randomly
// will terminate automatically when dizziness gets <100
// jitteriness decrements automatically in the mob's Life() proc.
/mob/proc/jittery_process()
var/old_x = pixel_x
var/old_y = pixel_y
is_jittery = 1
while(jitteriness > 100)
// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70
// pixel_x = amplitude * sin(0.008 * jitteriness * world.time)
// pixel_y = amplitude * cos(0.008 * jitteriness * world.time)
var/amplitude = min(4, jitteriness / 100)
pixel_x = old_x + rand(-amplitude, amplitude)
pixel_y = old_y + rand(-amplitude/3, amplitude/3)
sleep(1)
//endwhile - reset the pixel offsets to zero
is_jittery = 0
pixel_x = old_x
pixel_y = old_y
/mob/Stat()
..()
if (src.abilityHolder && !src.abilityHolder.topBarRendered)
abilityHolder.StatAbilities()
statpanel("Status")
if (client.statpanel == "Status")
if (ticker)
if ((!src.client.holder) && (ticker.hide_mode || master_mode == "wizard"))
stat("Game Mode:", "secret")
else
stat("Game Mode:", "[(client.holder && ticker.hide_mode) ? "[master_mode] **HIDDEN**" : "[master_mode]"]")
if (ticker.current_state == GAME_STATE_PREGAME)
var/timeLeftColor
switch (ticker.pregame_timeleft)
if (120 to 999)
timeLeftColor = "green"
if (60 to 120)
timeLeftColor = "#ffb400"
if (0 to 60)
timeLeftColor = "red"
stat("Time To Start:", "<span style='color: [timeLeftColor];'>[ticker.pregame_timeleft]</span>")
stat(null, " ")
if (src.client.holder)
if (!istype(src.loc, /turf) && !isnull(loc))
stat("Co-ordinates:", "([loc.x], [loc.y], [loc.z])")
else
stat("Co-ordinates:", "([x], [y], [z])")
stat("Server Load:", "[world.cpu] ([world.cpu < 90 ? "No" : "Yes"])")
else
stat(world.cpu < 90 ? "Server Load: No" : "Server Load: Yes") //Yes very useful a++
if (ticker && ticker.round_elapsed_ticks)
stat(null, " ")
var/shiftTime = round(ticker.round_elapsed_ticks / 600)
stat("Shift Time:", "[shiftTime] minute[shiftTime == 1 ? "" : "s"]")
if (ticker.mode && istype(ticker.mode, /datum/game_mode/construction))
stat(null, " ")
var/datum/game_mode/construction/C = ticker.mode
stat("Construction time left:", C.human_time_left)
var/datum/construction_controller/E = C.events
if (E.event_delay)
if (E.current_event)
stat("Event in progress:", E.current_event.name)
else
stat("Event cycle starts in:", dstohms(E.event_delay - ticker.round_elapsed_ticks))
else if (E.choose_at)
stat("Next event type:", E.next_event_type)
stat("Estimated event ETA:", dstohms(E.next_event_at - ticker.round_elapsed_ticks))
else if (E.next_event_at)
stat("Next event type:", E.next_event_type)
stat("Event ETA:", dstohms(E.next_event_at - ticker.round_elapsed_ticks))
stat(null, " ")
#ifdef XMAS
stat("Christmas Cheer:", "[christmas_cheer]%")
#endif
if (emergency_shuttle && emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat("Shuttle ETA:", "[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
stat(null, " ")
if (abilityHolder)
abilityHolder.Stat()
if (is_near_gauntlet())
gauntlet_controller.Stat()
if (is_near_colosseum())
colosseum_controller.Stat()
/mob/onVarChanged(variable, oldval, newval)
update_clothing()
/mob/proc/say()
return
/mob/verb/whisper()
return
/mob/verb/say_verb(message as text)
set name = "say"
//&& !src.client.holder
if (src.client && url_regex && url_regex.Find(message))
boutput(src, "<span style=\"color:blue\"><b>Web/BYOND links are not allowed in ingame chat.</b></span>")
boutput(src, "<span style=\"color:red\">&emsp;<b>\"[message]</b>\"</span>")
return
usr.say(message)
if (!dd_hasprefix(message, "*")) // if this is an emote it is logged in emote
logTheThing("say", src, null, "SAY: [message]")
// ghosts now can emote now too so vOv
/* if (istype(src,/mob/living/))
if (copytext(message, 1, 2) != "*") // if this is an emote it is logged in emote
logTheThing("say", src, null, "SAY: [message]")
else logTheThing("say", src, null, "SAY: [message]")
*/
/mob/verb/me_verb(message as text)
set name = "me"
if (src.client && !src.client.holder && url_regex && url_regex.Find(message))
boutput(src, "<span style=\"color:blue\"><b>Web/BYOND links are not allowed in ingame chat.</b></span>")
boutput(src, "<span style=\"color:red\">&emsp;<b>\"[message]</b>\"</span>")
return
src.emote(message, 1)
/* ghost emotes wooo also the logging is already taken care of in the emote() procs vOv
if (istype(src,/mob/living/) && src.stat == 0)
src.emote(message, 1)
logTheThing("say", src, null, "EMOTE: [message]")
else
boutput(src, "<span style=\"color:blue\">You can't emote when you're dead! How would that even work!?</span>")
*/
/mob/proc/say_dead(var/message, wraith = 0)
var/name = src.real_name
var/alt_name = ""
if (!deadchat_allowed)
boutput(usr, "<b>Deadchat is currently disabled.</b>")
return
message = trim(copytext(html_encode(sanitize(message)), 1, MAX_MESSAGE_LEN))
if (!message)
return
if (ishuman(src) && src.name != src.real_name)
if (src:wear_id && src:wear_id:registered && src:wear_id:registered != src.real_name)
alt_name = " (as [src:wear_id:registered])"
else if (!src:wear_id)
alt_name = " (as Unknown)"
else if (istype(src, /mob/dead))
name = "Ghost"
alt_name = " ([src.real_name])"
else if (istype(src, /mob/wraith))
name = "Wraith"
alt_name = " ([src.real_name])"
else if (!istype(src, /mob/living/carbon/human))
name = src.name
#ifdef DATALOGGER
game_stats.ScanText(message)
#endif
message = src.say_quote(message)
//logTheThing("say", src, null, "SAY: [message]")
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name' data-ctx='\ref[src.mind]'>[name]<span class='text-normal'>[alt_name]</span></span> <span class='message'>[message]</span></span>"
for (var/mob/M in mobs)
if (istype(M, /mob/new_player))
continue
if (M.client && M.client.deadchatoff)
continue
//admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
if (M.stat == 2 || istype(M, /mob/wraith) || (M.client && M.client.holder && M.client.deadchat && !M.client.player_mode))
var/thisR = rendered
if (M.client && M.client.holder && src.mind)
thisR = "<span class='adminHearing' data-ctx='[M.client.chatOutput.ctxFlag]'>[rendered]</span>"
boutput(M, thisR)
/mob/proc/say_understands(var/mob/other, var/forced_language)
if (src.stat == 2)
return 1
// else if (istype(other, src.type) || istype(src, other.type))
// return 1
var/L = other.say_language
if (forced_language)
L = forced_language
if (understands_language(L))
return 1
return 0
/*if (isrobot(other) || isAI(other) || (ismonkey(other) && src.bioHolder.HasEffect("monkey_speak")))
return 1
else
. = 0
. += ismonkey(src) ? 1 : 0
. += ismonkey(other) ? 1 : 0
if (. == 1)
return monkeysspeakhuman
else
return 1
return 0*/
/mob/proc/say_quote(var/text)
var/ending = copytext(text, length(text))
var/speechverb = speechverb_say
var/loudness = 0
var/font_accent = null
if (ending == "?")
speechverb = speechverb_ask
else if (ending == "!")
speechverb = speechverb_exclaim
if (src.stuttering)
speechverb = speechverb_stammer
for (var/datum/ailment_data/A in src.ailments)
if (istype(A.master, /datum/ailment/disease/berserker))
if (A.stage > 1)
speechverb = "roars"
if ((src.reagents && src.reagents.get_reagent_amount("ethanol") > 30))
speechverb = "slurs"
if (src.bioHolder)
if (src.bioHolder.HasEffect("loud_voice"))
speechverb = "bellows"
loudness += 1
if (src.bioHolder.HasEffect("quiet_voice"))
speechverb = "murmurs"
loudness -= 1
if (src.bioHolder.HasEffect("unintelligable"))
speechverb = "splutters"
if (src.bioHolder.HasEffect("accent_comic"))
font_accent = "Comic Sans MS"
if (src.bioHolder && src.bioHolder.genetic_stability < 50)
speechverb = "gurgles"
if (src.get_brain_damage() >= 60)
speechverb = "gibbers"
if (src.health <= 20)
speechverb = speechverb_gasp
if (src.stat == 2 || isobserver(src))
speechverb = pick("moans","wails","laments")
if (prob(5))
speechverb = "grumps"
if (text == "" || !text)
return speechverb
if (loudness > 0)
return "[speechverb], \"[font_accent ? "<font face='[font_accent]'>" : null]<big><strong><b>[text]</b></strong></big>[font_accent ? "</font>" : null]\""
else if (loudness < 0)
return "[speechverb], \"[font_accent ? "<font face='[font_accent]'>" : null]<small>[text]</small>[font_accent ? "</font>" : null]\""
else
return "[speechverb], \"[font_accent ? "<font face='[font_accent]'>" : null][text][font_accent ? "</font>" : null]\""
/mob/proc/emote(var/act, var/voluntary = 0)
return
/mob/proc/emote_check(var/voluntary = 1, var/time = 10, var/admin_bypass = 1, var/dead_check = 1)
if (src.emote_allowed)
if (dead_check && src.stat == 2)
src.emote_allowed = 0
return 0
if (world.time >= (src.last_emote_time + src.last_emote_wait))
if (!(src.client && (src.client.holder && admin_bypass)) && voluntary)
src.emote_allowed = 0
src.last_emote_time = world.time
src.last_emote_wait = time
spawn(time)
src.emote_allowed = 1
return 1
else
return 0
else
return 0
/mob/living/carbon/human/proc/JobEquipSpawned(rank)
var/datum/job/JOB = find_job_in_controller_by_string(rank)
if (!JOB)
boutput(src, "<span style=\"color:red\"><b>UH OH, the game couldn't find your job to set it up! Report this to a coder.</b></span>")
return
if (JOB.slot_back)
src.equip_if_possible(new JOB.slot_back(src), slot_back)
if (JOB.slot_back && JOB.items_in_backpack.len)
for (var/X in JOB.items_in_backpack)
src.equip_if_possible(new X(src), slot_in_backpack)
if (JOB.slot_jump)
src.equip_if_possible(new JOB.slot_jump(src), slot_w_uniform)
if (JOB.slot_belt)
src.equip_if_possible(new JOB.slot_belt(src), slot_belt)
if (JOB.slot_foot)
src.equip_if_possible(new JOB.slot_foot(src), slot_shoes)
if (JOB.slot_suit)
src.equip_if_possible(new JOB.slot_suit(src), slot_wear_suit)
if (JOB.slot_ears)
src.equip_if_possible(new JOB.slot_ears(src), slot_ears)
if (JOB.slot_mask)
src.equip_if_possible(new JOB.slot_mask(src), slot_wear_mask)
if (JOB.slot_glov)
src.equip_if_possible(new JOB.slot_glov(src), slot_gloves)
if (JOB.slot_eyes)
src.equip_if_possible(new JOB.slot_eyes(src), slot_glasses)
if (JOB.slot_head)
src.equip_if_possible(new JOB.slot_head(src), slot_head)
if (JOB.slot_poc1)
src.equip_if_possible(new JOB.slot_poc1(src), slot_l_store)
if (JOB.slot_poc2)
src.equip_if_possible(new JOB.slot_poc2(src), slot_r_store)
if (JOB.slot_rhan)
src.equip_if_possible(new JOB.slot_rhan(src), slot_r_hand)
if (JOB.slot_lhan)
src.equip_if_possible(new JOB.slot_lhan(src), slot_l_hand)
JOB.special_setup(src)
update_clothing()
return
/mob/proc/hit_twitch()
if (twitching)
return
twitching = 1
var/which
if (usr)
which = get_dir(usr,src)
else
which = pick(alldirs)
spawn(1)
var/ipx = src.pixel_x
var/ipy = src.pixel_y
switch(which)
if (NORTHEAST) animate(src, pixel_x = ipx + 2, pixel_y = ipy + 2, time = 2,easing = EASE_OUT)
if (NORTH) animate(src, pixel_x = ipx + 0, pixel_y = ipy + 3, time = 2,easing = EASE_OUT)
if (NORTHWEST) animate(src, pixel_x = ipx - 2, pixel_y = ipy + 2, time = 2,easing = EASE_OUT)
if (WEST) animate(src, pixel_x = ipx - 3, pixel_y = ipy + 0, time = 2,easing = EASE_OUT)
if (SOUTHWEST) animate(src, pixel_x = ipx - 2, pixel_y = ipy - 2, time = 2,easing = EASE_OUT)
if (SOUTH) animate(src, pixel_x = ipx + 0, pixel_y = ipy - 3, time = 2,easing = EASE_OUT)
if (SOUTHEAST) animate(src, pixel_x = ipx + 2, pixel_y = ipy - 2, time = 2,easing = EASE_OUT)
if (EAST) animate(src, pixel_x = ipx + 3, pixel_y = ipy + 0, time = 2,easing = EASE_OUT)
else
return
animate(pixel_x = ipx, pixel_y = ipy, time = 2,easing = EASE_IN)
sleep(4)
twitching = 0
/mob/attackby(obj/item/W as obj, mob/user as mob)
actions.interrupt(src, INTERRUPT_ATTACKED)
// why is this not in human/attackby?
if (W.arm_icon && ishuman(src) && (user.zone_sel && user.zone_sel.selecting in list("l_arm","r_arm")) && ((locate(/obj/machinery/optable, src.loc) && src.lying) || (locate(/obj/table, src.loc) && (src.paralysis || src.stat)) || (src.reagents && src.reagents.get_reagent_amount("ethanol") > 100 && src == user)))
var/mob/living/carbon/human/H = src
if (!H.limbs.vars[user.zone_sel.selecting])
W.attach(src,user)
return
var/shielded = 0
if (src.spellshield)
shielded = 1
boutput(user, "<span style=\"color:red\"><b>[src]'s Spell Shield prevents your attack!</b></span>")
else
if (!src.spellshield)
for(var/obj/item/device/shield/S in src)
if (S.active)
shielded = 1
else
if (locate(/obj/item/grab, src))
var/mob/safe = null
if (istype(src.l_hand, /obj/item/grab))
var/obj/item/grab/G = src.l_hand
if ((G.state == 2 && get_dir(src, user) == src.dir))
safe = G.affecting
if (istype(src.r_hand, /obj/item/grab))
var/obj/item/grab/G = src.r_hand
if ((G.state == 2 && get_dir(src, user) == src.dir))
safe = G.affecting
if (safe)
return safe.attackby(W, user)
if ((!( shielded ) || !( W.flags ) & 32))
spawn( 0 )
// drsingh Cannot read null.force
#ifdef DATALOGGER
if (!isnull(W) && W.force)
game_stats.Increment("violence")
#endif
if (!isnull(W))
W.attack(src, user)
if(W && W.force) //Wire: Fix for Cannot read null.force
message_admin_on_attack(user, "uses \a [W.name] on")
return
return
/mob/proc/throw_impacted() //Called when mob hits something after being thrown.
if (throw_count <= 410)
random_brute_damage(src, min((6 + (throw_count / 5)), (src.health - 5) < 0 ? src.health : (src.health - 5)))
src:weakened += 2
else
if (src.gib_flag) return
src.gib_flag = 1
src.gib()
src.throw_count = 0
return
/mob/verb/listen_ooc()
set name = "(Un)Mute OOC"
if (src.client)
src.client.preferences.listen_ooc = !src.client.preferences.listen_ooc
if (src.client.preferences.listen_ooc)
boutput(src, "<span style=\"color:blue\">You are now listening to messages on the OOC channel.</span>")
else
boutput(src, "<span style=\"color:blue\">You are no longer listening to messages on the OOC channel.</span>")
/mob/verb/ooc(msg as text)
if (IsGuestKey(src.key))
boutput(src, "You are not authorized to communicate over these channels.")
return
if (oocban_isbanned(src))
boutput(src, "You are currently banned from using OOC and LOOC, you may appeal at http://forum.ss13.co/index.php")
return
msg = trim(copytext(html_encode(sanitize(msg)), 1, MAX_MESSAGE_LEN))
if (!msg)
return
else if (!src.client.preferences.listen_ooc)
return
else if (!ooc_allowed && !src.client.holder)
boutput(usr, "OOC is currently disabled.")
return
else if (!dooc_allowed && !src.client.holder && (src.client.deadchat != 0))
boutput(usr, "OOC for dead mobs has been turned off.")
return
else if (src.client && src.client.ismuted())
boutput(usr, "You are currently muted and cannot talk in OOC.")
return
else if (findtext(msg, "byond://") && !src.client.holder)
boutput(src, "<B>Advertising other servers is not allowed.</B>")
logTheThing("admin", src, null, "has attempted to advertise in OOC.")
logTheThing("diary", src, null, "has attempted to advertise in OOC.", "admin")
message_admins("[key_name(src)] has attempted to advertise in OOC.")
return
logTheThing("diary", src, null, ": [msg]", "ooc")
#ifdef DATALOGGER
game_stats.ScanText(msg)
#endif
for (var/client/C)
// DEBUGGING
if (!C.preferences)
logTheThing("debug", null, null, "[C] (\ref[C]): client.preferences is null")
if (C.preferences && !C.preferences.listen_ooc)
continue
var ooc_class = ""
var display_name = src.key
if (src.client.stealth || src.client.alt_key)
if (!C.holder)
display_name = src.client.fakekey
else
display_name += " (as [src.client.fakekey])"
if (src.client.holder && (!src.client.stealth || C.holder))
if (src.client.holder.level == LEVEL_BABBY)
ooc_class = "gfartooc"
else
ooc_class = "adminooc"
else if (src.client.mentor)
ooc_class = "mentorooc"
var/rendered = "<span class=\"ooc [ooc_class]\"><span class=\"prefix\">OOC:</span> <span class=\"name\" data-ctx='\ref[src.mind]'>[display_name]:</span> <span class=\"message\">[msg]</span></span>"
if (C.holder)
rendered = "<span class='adminHearing' data-ctx='[C.chatOutput.ctxFlag]'>[rendered]</span>"
boutput(C, rendered)
logTheThing("ooc", src, null, "OOC: [msg]")
/mob/verb/listen_looc()
set name = "(Un)Mute LOOC"
if (src.client)
src.client.preferences.listen_looc = !src.client.preferences.listen_looc
if (src.client.preferences.listen_looc)
boutput(src, "<span style=\"color:blue\">You are now listening to messages on the LOOC channel.</span>")
else
boutput(src, "<span style=\"color:blue\">You are no longer listening to messages on the LOOC channel.</span>")
/mob/verb/looc(msg as text)
if (IsGuestKey(src.key))
boutput(src, "You are not authorized to communicate over these channels.")
return
if (oocban_isbanned(src))
boutput(src, "You are currently banned from using OOC and LOOC, you may appeal at http://forum.ss13.co/index.php")
return
msg = trim(copytext(html_encode(sanitize(msg)), 1, MAX_MESSAGE_LEN))
if (!msg)
return
else if (!src.client.preferences.listen_looc)
return
else if (!looc_allowed && !src.client.holder)
boutput(usr, "LOOC is currently disabled.")
return
else if (!dooc_allowed && !src.client.holder && (src.client.deadchat != 0))
boutput(usr, "LOOC for dead mobs has been turned off.")
return
else if (src.client && src.client.ismuted())
boutput(usr, "You are currently muted and cannot talk in LOOC.")
return
else if (findtext(msg, "byond://") && !src.client.holder)
boutput(src, "<B>Advertising other servers is not allowed.</B>")
logTheThing("admin", src, null, "has attempted to advertise in LOOC.")
logTheThing("diary", src, null, "has attempted to advertise in LOOC.", "admin")
message_admins("[key_name(src)] has attempted to advertise in LOOC.")
return
logTheThing("diary", src, null, ": [msg]", "ooc")
#ifdef DATALOGGER
game_stats.ScanText(msg)
#endif
var/list/recipients = list()
for (var/mob/M in range(LOOC_RANGE))
if (!M.client)
continue
if (M.client.preferences && !M.client.preferences.listen_looc)
continue
recipients += M.client
for (var/mob/M in mobs)
if (!M.client)
continue
if (recipients.Find(M.client))
continue
if (M.client.holder && !M.client.only_local_looc && !M.client.player_mode)
recipients += M.client
for (var/client/C in recipients)
// DEBUGGING
if (!C.preferences)
logTheThing("debug", null, null, "[C] (\ref[C]): client.preferences is null")
if (C.preferences && !C.preferences.listen_ooc)
continue
var looc_class = ""
var display_name = src.key
if (src.client.stealth || src.client.alt_key)
if (!C.holder)
display_name = src.client.fakekey
else
display_name += " (as [src.client.fakekey])"
if (src.client.holder && (!src.client.stealth || C.holder))
if (src.client.holder.level == LEVEL_BABBY)
looc_class = "gfartlooc"
else
looc_class = "adminlooc"
else if (src.client.mentor)
looc_class = "mentorlooc"
var/rendered = "<span class=\"looc [looc_class]\"><span class=\"prefix\">LOOC:</span> <span class=\"name\" data-ctx='\ref[src.mind]'>[display_name]:</span> <span class=\"message\">[msg]</span></span>"
if (C.holder)
rendered = "<span class='adminHearing' data-ctx='[C.chatOutput.ctxFlag]'>[rendered]</span>"
boutput(C, rendered)
logTheThing("ooc", src, null, "LOOC: [msg]")
/mob/proc/full_heal()
src.HealDamage("All", 10000, 10000)
src.drowsyness = 0
src.stuttering = 0
src.losebreath = 0
src.paralysis = 0
src.stunned = 0
src.weakened = 0
src.slowed = 0
src.radiation = 0
src.change_eye_blurry(-INFINITY)
src.take_eye_damage(-INFINITY)
src.take_eye_damage(-INFINITY, 1)
src.take_ear_damage(-INFINITY)
src.take_ear_damage(-INFINITY, 1)
src.take_brain_damage(-120)
src.health = src.max_health
src.buckled = initial(src.buckled)
src.handcuffed = initial(src.handcuffed)
src.bodytemperature = src.base_body_temp
if (src.stat > 1)
src.stat = 0
src.updatehealth()
/mob/proc/infected(var/datum/pathogen/P)
return
/mob/proc/remission(var/datum/pathogen/P)
return
/mob/proc/immunity(var/datum/pathogen/P)
return
/mob/proc/cured(var/datum/pathogen/P)
return
/mob/proc/shock(var/atom/origin, var/wattage, var/zone, var/stun_multiplier = 1, var/ignore_gloves = 0)
return 0
/mob/proc/flash(duration)
return 0
/mob/proc/take_brain_damage(var/amount)
if (!isnum(amount) || amount == 0)
return 1
return 0
/mob/proc/take_toxin_damage(var/amount)
if (!isnum(amount) || amount == 0)
return 1
return 0
/mob/proc/take_oxygen_deprivation(var/amount)
if (!isnum(amount) || amount == 0)
return 1
return 0
/mob/proc/get_eye_damage(var/tempblind = 0)
if (tempblind == 0)
return src.eye_damage
else
return src.eye_blind
/mob/proc/take_eye_damage(var/amount, var/tempblind = 0)
//Shamefully stolen from the welder
// and then from a different proc, to bring this in line with the other damage procs
//
// Then I came along and integrated eye_blind handling (Convair880).
if (!src || !ismob(src) || (!isnum(amount) || amount == 0))
return 0
var/eyeblind = 0
if (tempblind == 0)
src.eye_damage = max(0, src.eye_damage + amount)
else
eyeblind = amount
// Modify eye_damage or eye_blind if prompted, but don't perform more than we absolutely have to.
var/blind_bypass = 0
if (src.bioHolder && src.bioHolder.HasEffect("blind"))
blind_bypass = 1
if (amount > 0 && tempblind == 0 && blind_bypass == 0) // so we don't enter the damage switch thing if we're healing damage
switch (src.eye_damage)
if (10 to 12)
src.change_eye_blurry(rand(3,6))
if (12 to 15)
src.show_text("Your eyes hurt.", "red")
src.change_eye_blurry(rand(6,9))
if (15 to 25)
src.show_text("Your eyes are really starting to hurt.", "red")
src.change_eye_blurry(rand(12,16))
if (prob(src.eye_damage - 15 + 1))
src.show_text("Your eyes are badly damaged!", "red")
eyeblind = 5
src.change_eye_blurry(5)
src.bioHolder.AddEffect("bad_eyesight")
spawn(100)
src.bioHolder.RemoveEffect("bad_eyesight")
if (25 to INFINITY)
src.show_text("<B>Your eyes hurt something fierce!</B>", "red")
if (prob(src.eye_damage - 25 + 1))
src.show_text("<b>You go blind!</b>", "red")
src.bioHolder.AddEffect("blind")
else
src.change_eye_blurry(rand(12,16))
if (eyeblind != 0)
src.eye_blind = max(0, src.eye_blind + eyeblind)
//DEBUG_MESSAGE("Eye damage applied: [amount]. Tempblind: [tempblind == 0 ? "N" : "Y"]")
return 1
/mob/proc/get_eye_blurry()
return src.eye_blurry
// Why not, I suppose. Wraps up the three major eye-related mob vars (Convair880).
/mob/proc/change_eye_blurry(var/amount, var/cap = 0)
if (!src || !ismob(src) || (!isnum(amount) || amount == 0))
return 0
var/upper_cap_default = 150
var/upper_cap = upper_cap_default
if (cap && isnum(cap) && (cap > 0 && cap < upper_cap_default))
if (src.get_eye_blurry() >= cap)
return
else
upper_cap = cap
src.eye_blurry = max(0, min(src.eye_blurry + amount, upper_cap))
//DEBUG_MESSAGE("Amount is [amount], new eye blurry is [src.eye_blurry], cap is [upper_cap]")
return 1
/mob/proc/get_ear_damage(var/tempdeaf = 0)
if (tempdeaf == 0)
return src.ear_damage
else
return src.ear_deaf
// And here's the missing one for ear damage too (Convair880).
/mob/proc/take_ear_damage(var/amount, var/tempdeaf = 0)
if (!src || !ismob(src) || (!isnum(amount) || amount == 0))
return 0
var/eardeaf = 0
if (tempdeaf == 0)
src.ear_damage = max(0, src.ear_damage + amount)
else
eardeaf = amount
// Modify ear_damage or ear_deaf if prompted, but don't perform more than we absolutely have to.
var/deaf_bypass = 0
if (src.bioHolder && src.bioHolder.HasEffect("deaf"))
deaf_bypass = 1
if (amount > 0 && tempdeaf == 0 && deaf_bypass == 0)
switch (src.ear_damage)
if (10 to 12)
eardeaf += 1
if (13 to 15)
boutput(src, "<span style=\"color:red\">Your ears ring a bit!</span>")
eardeaf += rand(2, 3)
if (15 to 24)
boutput(src, "<span style=\"color:red\">Your ears are really starting to hurt!</span>")
eardeaf += src.ear_damage * 0.5
if (25 to INFINITY)
boutput(src, "<span style=\"color:red\"><b>Your ears ring very badly!</b></span>")
if (src.bioHolder && prob(src.ear_damage - 10 + 5))
src.show_text("<b>You go deaf!</b>", "red")
src.bioHolder.AddEffect("deaf")
else
eardeaf += src.ear_damage * 0.75
if (eardeaf != 0)
var/suppress_message = 0
if (!src.get_ear_damage(1) && eardeaf < 0) // We don't have any temporary deafness to begin with and are told to heal it.
suppress_message = 1
if (src.get_ear_damage(1) && (src.get_ear_damage(1) + eardeaf) > 0) // We already have temporary deafness and are adding to it.
suppress_message = 1
src.ear_deaf = max(0, src.ear_deaf + eardeaf)
if (src.ear_deaf == 0 && deaf_bypass == 0 && suppress_message == 0)
boutput(src, "<span style=\"color:blue\">The ringing in your ears subsides enough to let you hear again.</span>")
else if (eardeaf > 0 && deaf_bypass == 0 && suppress_message == 0)
boutput(src, "<span style=\"color:red\">The ringing overpowers your ability to hear momentarily.</span>")
//DEBUG_MESSAGE("Ear damage applied: [amount]. Tempdeaf: [tempdeaf == 0 ? "N" : "Y"]")
return 1
// No natural healing can occur if ear damage is above this threshold. Didn't want to make it yet another mob parent var.
/mob/proc/get_ear_damage_natural_healing_threshold()
return max(0, src.max_health / 4)
/mob/proc/lose_breath(var/amount)
if (!isnum(amount) || amount == 0)
return 1
return 0
/mob/proc/change_misstep_chance(var/amount)
if (!isnum(amount) || amount == 0)
return 1
return 0
/mob/proc/get_brain_damage()
return 0
/mob/proc/get_brute_damage()
return 0
/mob/proc/get_burn_damage()
return 0
/mob/proc/get_toxin_damage()
return 0
/mob/proc/get_oxygen_deprivation()
return 0
/mob/proc/get_radiation()
return radiation
/mob/proc/hotkey(var/key)
if (isobj(src.loc))
var/obj/O = src.loc
O.hotkey(src, key)
/mob/UpdateName()
if (src.real_name)
src.name = "[name_prefix(null, 1)][src.real_name][name_suffix(null, 1)]"
else
src.name = "[name_prefix(null, 1)][initial(src.name)][name_suffix(null, 1)]"
/mob/proc/protected_from_space()
return 0
/mob/proc/list_ejectables()
return list()
/mob/proc/get_valid_target_zones()
return list()
/mob/proc/message_admin_on_attack(var/mob/attacker, var/attack_type = "attacks")
//Due to how attacking is set up we will need
if(!attacker.attack_alert || !src.key || attacker == src || src.stat == 2) return //Only send the alert if we're hitting an actual, living person who isn't ourselves
message_attack("[key_name(attacker)] [attack_type] [key_name(src)] shortly after spawning!")
/mob/proc/temporary_attack_alert(var/time = 600)
//Only start the clock if there's time and we're not already alerting about attacks
if(attack_alert || !time) return
attack_alert = 1
spawn(time) attack_alert = 0
/mob/proc/heard_say(var/mob/other)
return
/mob/proc/add_ability_holder(holder_type)
if (abilityHolder && istype(abilityHolder, /datum/abilityHolder/composite))
var/datum/abilityHolder/composite/C = abilityHolder
C.addHolder(holder_type)
return C.getHolder(holder_type)
else if (abilityHolder)
var/datum/abilityHolder/T = abilityHolder
var/datum/abilityHolder/composite/C = new(src)
C.holders = list(T)
C.addHolder(holder_type)
return C.getHolder(holder_type)
else
abilityHolder = new holder_type(src)
return abilityHolder
/mob/proc/get_ability_holder(holder_type)
if (abilityHolder && istype(abilityHolder, /datum/abilityHolder/composite))
var/datum/abilityHolder/composite/C = abilityHolder
return C.getHolder(holder_type)
else if (abilityHolder && abilityHolder.type == holder_type)
return abilityHolder
return null
/mob/proc/remove_ability_holder(var/datum/abilityHolder/H)
if (abilityHolder && istype(abilityHolder, /datum/abilityHolder/composite))
var/datum/abilityHolder/composite/C = abilityHolder
return C.removeHolder(H)
else if (abilityHolder && abilityHolder == H)
abilityHolder = null
/mob/proc/add_existing_ability_holder(var/datum/abilityHolder/H)
if (H.owner != src)
H.owner = src
if (abilityHolder && istype(abilityHolder, /datum/abilityHolder/composite))
var/datum/abilityHolder/composite/C = abilityHolder
C.addHolderInstance(H)
return H
else if (abilityHolder)
var/datum/abilityHolder/T = abilityHolder
var/datum/abilityHolder/composite/C = new(src)
C.holders = list(T, H)
return H
else
abilityHolder = H
return H
/mob/proc/lastgasp()
return
/mob/proc/item_attack_message(var/mob/T, var/obj/item/S, var/d_zone)
if (d_zone)
return "<span style=\"color:red\"><B>[src] attacks [T] in the [d_zone] with [S]!</B></span>"
else
return "<span style=\"color:red\"><B>[src] attacks [T] with [S]!</B></span>"
/mob/proc/get_age_pitch()
if (!src.bioHolder || !src.bioHolder.age) return
if (src.reagents && src.reagents.has_reagent("helium"))
return 1.0 + 0.5*(60 - src.bioHolder.age)/80
else
return 1.0 + 0.5*(30 - src.bioHolder.age)/80
/mob/proc/understands_language(var/langname)
if (langname == say_language)
return 1
if (langname == "english" || !langname)
return 1
if (langname == "monkey" && (monkeysspeakhuman || (bioHolder && bioHolder.HasEffect("monkey_speak"))))
return 1
return 0
/mob/proc/get_language_id(var/forced_language = null)
var/language = say_language
if (forced_language)
language = forced_language
return language
/mob/proc/process_language(var/message, var/forced_language = null)
var/datum/language/L = languages.language_cache[get_language_id(forced_language)]
if (!L)
L = languages.language_cache["english"]
return L.get_messages(message)
/mob/proc/get_special_language(var/secure_mode)
return null
/mob/proc/on_reagent_react(var/datum/reagents/R, var/method = 1, var/react_volume = null)
/mob/proc/HealBleeding(var/amt)
/mob/proc/find_in_equipment(var/eqtype)
return null
/mob/proc/find_in_hands(var/eqtype)
return null
/mob/proc/is_in_hands(var/obj/O)
return 0
/mob/proc/does_it_metabolize()
return 0
/mob/proc/isBlindImmune()
return 0
/mob/proc/canRideMailchutes()
return 0
/mob/proc/choose_name(var/retries = 3)
var/newname
for (retries, retries > 0, retries--)
newname = input(src, "Would you like to change your name to something else?", "Name Change", src.real_name) as null|text
if (!newname)
if (src.client && src.client.preferences && src.client.preferences.real_name)
src.real_name = src.client.preferences.real_name
else
src.real_name = random_name(src.gender)
src.name = src.real_name
else
newname = strip_html(newname, 32, 1)
if (!length(newname) || length(newname <= 3) || copytext(newname,1,2) == " ")
src.show_text("That name was too short after removing bad characters from it. Please choose a different name.", "red")
continue
else
if (alert(src, "Use the name [newname]?", newname, "Yes", "No") == "Yes")
src.real_name = newname
src.name = newname
return 1
else
continue
if (!newname)
if (src.client && src.client.preferences && src.client.preferences.real_name)
src.real_name = src.client.preferences.real_name
else
src.real_name = random_name(src.gender)
src.name = src.real_name
/mob/proc/set_mutantrace(var/mutantrace_type)
return
/proc/random_name(var/gen = MALE)
var/return_name
if (gen == MALE)
return_name = capitalize(pick(first_names_male) + " " + capitalize(pick(last_names)))
else if (gen == FEMALE)
return_name = capitalize(pick(first_names_female) + " " + capitalize(pick(last_names)))
else
return_name = capitalize(pick(first_names_male + first_names_female) + " " + capitalize(pick(last_names)))
return return_name