initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
// Camera mob, used by AI camera and blob.
/mob/camera
name = "camera mob"
density = 0
anchored = 1
status_flags = GODMODE // You can't damage it.
mouse_opacity = 0
see_in_dark = 7
invisibility = INVISIBILITY_ABSTRACT // No one can see us
sight = SEE_SELF
move_on_shuttle = 0
/mob/camera/experience_pressure_difference()
return
+5
View File
@@ -0,0 +1,5 @@
/mob/dead/dust() //ghosts can't be vaporised.
return
/mob/dead/gib() //ghosts can't be gibbed.
return
+16
View File
@@ -0,0 +1,16 @@
/mob/dead/observer/Login()
..()
ghost_accs = client.prefs.ghost_accs
ghost_others = client.prefs.ghost_others
var/preferred_form = null
if(check_rights(R_ADMIN, 0))
has_unlimited_silicon_privilege = 1
if(client.prefs.unlock_content)
preferred_form = client.prefs.ghost_form
ghost_orbit = client.prefs.ghost_orbit
update_icon(preferred_form)
updateghostimages()
+7
View File
@@ -0,0 +1,7 @@
/mob/dead/observer/Logout()
if (client)
client.images -= ghost_darkness_images
..()
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
qdel(src)
+693
View File
@@ -0,0 +1,693 @@
var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness, BUT NOT THE GHOSTS THEMSELVES!
var/list/image/ghost_images_full = list() //this is a list of full images of the ghosts themselves
var/list/image/ghost_images_default = list() //this is a list of the default (non-accessorized, non-dir) images of the ghosts themselves
var/list/image/ghost_images_simple = list() //this is a list of all ghost images as the simple white ghost
/mob/dead/observer
name = "ghost"
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
icon = 'icons/mob/mob.dmi'
icon_state = "ghost"
layer = GHOST_LAYER
stat = DEAD
density = 0
canmove = 0
anchored = 1 // don't get pushed around
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
languages_spoken = ALL
languages_understood = ALL
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
//If you died in the game and are a ghsot - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
var/atom/movable/following = null
var/fun_verbs = 0
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/image/ghostimage_default = null //this mobs ghost image without accessories and dirs
var/image/ghostimage_simple = null //this mob with the simple white ghost sprite
var/ghostvision = 1 //is the ghost able to see things humans can't?
var/seedarkness = 1
var/ghost_hud_enabled = 1 //did this ghost disable the on-screen HUD?
var/data_huds_on = 0 //Are data HUDs currently enabled?
var/list/datahuds = list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC) //list of data HUDs shown to ghosts.
var/ghost_orbit = GHOST_ORBIT_CIRCLE
//These variables store hair data if the ghost originates from a species with head and/or facial hair.
var/hair_style
var/hair_color
var/image/hair_image
var/facial_hair_style
var/facial_hair_color
var/image/facial_hair_image
var/updatedir = 1 //Do we have to update our dir as the ghost moves around?
var/lastsetting = null //Stores the last setting that ghost_others was set to, for a little more efficiency when we update ghost images. Null means no update is necessary
//We store copies of the ghost display preferences locally so they can be referred to even if no client is connected.
//If there's a bug with changing your ghost settings, it's probably related to this.
var/ghost_accs = GHOST_ACCS_DEFAULT_OPTION
var/ghost_others = GHOST_OTHERS_DEFAULT_OPTION
// Used for displaying in ghost chat, without changing the actual name
// of the mob
var/deadchat_name
/mob/dead/observer/New(mob/body)
verbs += /mob/dead/observer/proc/dead_tele
if(global.cross_allowed)
verbs += /mob/dead/observer/proc/server_hop
ghostimage = image(src.icon,src,src.icon_state)
if(icon_state in ghost_forms_with_directions_list)
ghostimage_default = image(src.icon,src,src.icon_state + "_nodir")
else
ghostimage_default = image(src.icon,src,src.icon_state)
ghostimage_simple = image(src.icon,src,"ghost_nodir")
ghost_images_full |= ghostimage
ghost_images_default |= ghostimage_default
ghost_images_simple |= ghostimage_simple
updateallghostimages()
var/turf/T
if(ismob(body))
T = get_turf(body) //Where is the body located?
attack_log = body.attack_log //preserve our attack logs by copying them to our ghost
gender = body.gender
if(body.mind && body.mind.name)
name = body.mind.name
else
if(body.real_name)
name = body.real_name
else
name = random_unique_name(gender)
mind = body.mind //we don't transfer the mind but we keep a reference to it.
if(ishuman(body))
var/mob/living/carbon/human/body_human = body
if(HAIR in body_human.dna.species.specflags)
hair_style = body_human.hair_style
hair_color = brighten_color(body_human.hair_color)
if(FACEHAIR in body_human.dna.species.specflags)
facial_hair_style = body_human.facial_hair_style
facial_hair_color = brighten_color(body_human.facial_hair_color)
update_icon()
if(!T)
T = pick(latejoin) //Safety in case we cannot find the body's position
loc = T
if(!name) //To prevent nameless ghosts
name = random_unique_name(gender)
real_name = name
if(!fun_verbs)
verbs -= /mob/dead/observer/verb/boo
verbs -= /mob/dead/observer/verb/possess
animate(src, pixel_y = 2, time = 10, loop = -1)
..()
/mob/dead/observer/narsie_act()
var/old_color = color
color = "#960000"
animate(src, color = old_color, time = 10)
/mob/dead/observer/ratvar_act()
var/old_color = color
color = "#FAE48C"
animate(src, color = old_color, time = 10)
/mob/dead/observer/Destroy()
ghost_images_full -= ghostimage
qdel(ghostimage)
ghostimage = null
ghost_images_default -= ghostimage_default
qdel(ghostimage_default)
ghostimage_default = null
ghost_images_simple -= ghostimage_simple
qdel(ghostimage_simple)
ghostimage_simple = null
updateallghostimages()
return ..()
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
return 1
/*
* This proc will update the icon of the ghost itself, with hair overlays, as well as the ghost image.
* Please call update_icon(icon_state) from now on when you want to update the icon_state of the ghost,
* or you might end up with hair on a sprite that's not supposed to get it.
* Hair will always update its dir, so if your sprite has no dirs the haircut will go all over the place.
* |- Ricotez
*/
/mob/dead/observer/proc/update_icon(new_form)
if(client) //We update our preferences in case they changed right before update_icon was called.
ghost_accs = client.prefs.ghost_accs
ghost_others = client.prefs.ghost_others
if(hair_image)
overlays -= hair_image
ghostimage.overlays -= hair_image
hair_image = null
if(facial_hair_image)
overlays -= facial_hair_image
ghostimage.overlays -= facial_hair_image
facial_hair_image = null
if(new_form)
icon_state = new_form
ghostimage.icon_state = new_form
if(icon_state in ghost_forms_with_directions_list)
ghostimage_default.icon_state = new_form + "_nodir" //if this icon has dirs, the default ghostimage must use its nodir version or clients with the preference set to default sprites only will see the dirs
else
ghostimage_default.icon_state = new_form
if(ghost_accs >= GHOST_ACCS_DIR && icon_state in ghost_forms_with_directions_list) //if this icon has dirs AND the client wants to show them, we make sure we update the dir on movement
updatedir = 1
else
updatedir = 0 //stop updating the dir in case we want to show accessories with dirs on a ghost sprite without dirs
setDir(2 )//reset the dir to its default so the sprites all properly align up
if(ghost_accs == GHOST_ACCS_FULL && icon_state in ghost_forms_with_accessories_list) //check if this form supports accessories and if the client wants to show them
var/datum/sprite_accessory/S
if(facial_hair_style)
S = facial_hair_styles_list[facial_hair_style]
if(S)
facial_hair_image = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
if(facial_hair_color)
facial_hair_image.color = "#" + facial_hair_color
facial_hair_image.alpha = 200
add_overlay(facial_hair_image)
ghostimage.overlays += facial_hair_image
if(hair_style)
S = hair_styles_list[hair_style]
if(S)
hair_image = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
if(hair_color)
hair_image.color = "#" + hair_color
hair_image.alpha = 200
add_overlay(hair_image)
ghostimage.overlays += hair_image
/*
* Increase the brightness of a color by calculating the average distance between the R, G and B values,
* and maximum brightness, then adding 30% of that average to R, G and B.
*
* I'll make this proc global and move it to its own file in a future update. |- Ricotez
*/
/mob/proc/brighten_color(input_color)
var/r_val
var/b_val
var/g_val
var/color_format = lentext(input_color)
if(color_format == 3)
r_val = hex2num(copytext(input_color, 1, 2))*16
g_val = hex2num(copytext(input_color, 2, 3))*16
b_val = hex2num(copytext(input_color, 3, 0))*16
else if(color_format == 6)
r_val = hex2num(copytext(input_color, 1, 3))
g_val = hex2num(copytext(input_color, 3, 5))
b_val = hex2num(copytext(input_color, 5, 0))
else
return 0 //If the color format is not 3 or 6, you're using an unexpected way to represent a color.
r_val += (255 - r_val) * 0.4
if(r_val > 255)
r_val = 255
g_val += (255 - g_val) * 0.4
if(g_val > 255)
g_val = 255
b_val += (255 - b_val) * 0.4
if(b_val > 255)
b_val = 255
return num2hex(r_val, 2) + num2hex(g_val, 2) + num2hex(b_val, 2)
/*
Transfer_mind is there to check if mob is being deleted/not going to have a body.
Works together with spawning an observer, noted above.
*/
/mob/proc/ghostize(can_reenter_corpse = 1)
if(key)
if(!cmptext(copytext(key,1,2),"@")) // Skip aghosts.
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.key = key
return ghost
/*
This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues.
*/
/mob/living/verb/ghost()
set category = "OOC"
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
if(mental_dominator)
src << "<span class='warning'>This body's force of will is too strong! You can't break it enough to force them into a catatonic state.</span>"
if(mind_control_holder)
mind_control_holder << "<span class='userdanger'>Through tremendous force of will, you stop a catatonia attempt!</span>"
return 0
if(stat != DEAD)
succumb()
if(stat == DEAD)
ghostize(1)
else
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost")
return //didn't want to ghost after-all
ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
return
/mob/dead/observer/Move(NewLoc, direct)
if(updatedir)
setDir(direct )//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own
if(NewLoc)
loc = NewLoc
for(var/obj/effect/step_trigger/S in NewLoc)
S.Crossed(src)
return
loc = get_turf(src) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
y--
if((direct & EAST) && x < world.maxx)
x++
else if((direct & WEST) && x > 1)
x--
for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb
S.Crossed(src)
/mob/dead/observer/is_active()
return 0
/mob/dead/observer/Stat()
..()
if(statpanel("Status"))
stat(null, "Station Time: [worldtime2text()]")
if(ticker)
if(ticker.mode)
for(var/datum/gang/G in ticker.mode.gangs)
if(G.is_dominating)
stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]")
/mob/dead/observer/verb/reenter_corpse()
set category = "Ghost"
set name = "Re-enter Corpse"
if(!client)
return
if(!(mind && mind.current))
src << "<span class='warning'>You have no body.</span>"
return
if(!can_reenter_corpse)
src << "<span class='warning'>You cannot re-enter your body.</span>"
return
if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients
usr << "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>"
return
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.key = key
return 1
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source)
if(message)
src << "<span class='ghostalert'>[message]</span>"
if(source)
var/obj/screen/alert/A = throw_alert("\ref[source]_notify_cloning", /obj/screen/alert/notify_cloning)
if(A)
if(client && client.prefs && client.prefs.UI_style)
A.icon = ui_style2icon(client.prefs.UI_style)
A.desc = message
var/old_layer = source.layer
source.layer = FLOAT_LAYER
A.add_overlay(source)
source.layer = old_layer
src << "<span class='ghostalert'><a href=?src=\ref[src];reenter=1>(Click to re-enter)</a></span>"
if(sound)
src << sound(sound)
/mob/dead/observer/proc/dead_tele()
set category = "Ghost"
set name = "Teleport"
set desc= "Teleport to a location"
if(!istype(usr, /mob/dead/observer))
usr << "Not when you're not dead!"
return
var/A
A = input("Area to jump to", "BOOYEA", A) as null|anything in sortedAreas
var/area/thearea = A
if(!thearea)
return
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
L+=T
if(!L || !L.len)
usr << "No area available."
usr.loc = pick(L)
/mob/dead/observer/verb/follow()
set category = "Ghost"
set name = "Orbit" // "Haunt"
set desc = "Follow and orbit a mob."
var/list/mobs = getpois(skip_mindless=1)
var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs
var/mob/target = mobs[input]
ManualFollow(target)
// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
if (!istype(target))
return
var/icon/I = icon(target.icon,target.icon_state,target.dir)
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
if(orbiting != target)
src << "<span class='notice'>Now orbiting [target].</span>"
var/rot_seg
switch(ghost_orbit)
if(GHOST_ORBIT_TRIANGLE)
rot_seg = 3
if(GHOST_ORBIT_SQUARE)
rot_seg = 4
if(GHOST_ORBIT_PENTAGON)
rot_seg = 5
if(GHOST_ORBIT_HEXAGON)
rot_seg = 6
else //Circular
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
orbit(target,orbitsize, FALSE, 20, rot_seg)
/mob/dead/observer/orbit()
setDir(2 )//reset dir so the right directional sprites show up
..()
//restart our floating animation after orbit is done.
sleep 2 //orbit sets up a 2ds animation when it finishes, so we wait for that to end
if (!orbiting) //make sure another orbit hasn't started
pixel_y = 0
animate(src, pixel_y = 2, time = 10, loop = -1)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
set name = "Jump to Mob"
set desc = "Teleport to a mob"
if(istype(usr, /mob/dead/observer)) //Make sure they're an observer!
var/list/dest = list() //List of possible destinations (mobs)
var/target = null //Chosen target.
dest += getpois(mobs_only=1) //Fill list, prompt user with list
target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest
if (!target)//Make sure we actually have a target
return
else
var/mob/M = dest[target] //Destination mob
var/mob/A = src //Source mob
var/turf/T = get_turf(M) //Turf of the destination mob
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
A.loc = T
else
A << "This mob is not located in the game world."
/mob/dead/observer/verb/boo()
set category = "Ghost"
set name = "Boo!"
set desc= "Scare your crew members because of boredom!"
if(bootime > world.time) return
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
if(L)
L.flicker()
bootime = world.time + 600
return
//Maybe in the future we can add more <i>spooky</i> code here!
return
/mob/dead/observer/memory()
set hidden = 1
src << "<span class='danger'>You are dead! You have no mind to store memory!</span>"
/mob/dead/observer/add_memory()
set hidden = 1
src << "<span class='danger'>You are dead! You have no mind to store memory!</span>"
/mob/dead/observer/verb/toggle_ghostsee()
set name = "Toggle Ghost Vision"
set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
set category = "Ghost"
ghostvision = !(ghostvision)
updateghostsight()
usr << "You [(ghostvision?"now":"no longer")] have ghost vision."
/mob/dead/observer/verb/toggle_darkness()
set name = "Toggle Darkness"
set category = "Ghost"
seedarkness = !(seedarkness)
updateghostsight()
/mob/dead/observer/proc/updateghostsight()
if(client)
ghost_others = client.prefs.ghost_others //A quick update just in case this setting was changed right before calling the proc
if (seedarkness)
see_invisible = SEE_INVISIBLE_OBSERVER
if (!ghostvision || ghost_others <= GHOST_OTHERS_DEFAULT_SPRITE)
see_invisible = SEE_INVISIBLE_LIVING
else
see_invisible = SEE_INVISIBLE_NOLIGHTING
updateghostimages()
/proc/updateallghostimages()
for (var/mob/dead/observer/O in player_list)
O.updateghostimages()
/mob/dead/observer/proc/updateghostimages()
if (!client)
return
if(lastsetting)
switch(lastsetting) //checks the setting we last came from, for a little efficiency so we don't try to delete images from the client that it doesn't have anyway
if(GHOST_OTHERS_THEIR_SETTING)
client.images -= ghost_images_full
if(GHOST_OTHERS_DEFAULT_SPRITE)
client.images -= ghost_images_default
if(GHOST_OTHERS_SIMPLE)
client.images -= ghost_images_simple
if ((seedarkness || !ghostvision) && client.prefs.ghost_others == GHOST_OTHERS_THEIR_SETTING)
client.images -= ghost_darkness_images
lastsetting = null
else if(ghostvision && (!seedarkness || client.prefs.ghost_others <= GHOST_OTHERS_DEFAULT_SPRITE))
//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
if(!lastsetting)
client.images |= ghost_darkness_images
switch(client.prefs.ghost_others)
if(GHOST_OTHERS_THEIR_SETTING)
client.images |= ghost_images_full
if (ghostimage)
client.images -= ghostimage //remove ourself
if(GHOST_OTHERS_DEFAULT_SPRITE)
client.images |= ghost_images_default
if(ghostimage_default)
client.images -= ghostimage_default
if(GHOST_OTHERS_SIMPLE)
client.images |= ghost_images_simple
if(ghostimage_simple)
client.images -= ghostimage_simple
lastsetting = client.prefs.ghost_others
/mob/dead/observer/verb/possess()
set category = "Ghost"
set name = "Possess!"
set desc= "Take over the body of a mindless creature!"
var/list/possessible = list()
for(var/mob/living/L in living_mob_list)
if(!(L in player_list) && !L.mind)
possessible += L
var/mob/living/target = input("Your new life begins today!", "Possess Mob", null, null) as null|anything in possessible
if(!target)
return 0
if(istype (target, /mob/living/simple_animal/hostile/megafauna))
src << "<span class='warning'>This creature is too powerful for you to possess!</span>"
return 0
if(can_reenter_corpse || (mind && mind.current))
if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go foward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
return 0
if(target.key)
src << "<span class='warning'>Someone has taken this body while you were choosing!</span>"
return 0
target.key = key
return 1
/mob/dead/observer/proc/server_hop()
set category = "Ghost"
set name = "Server Hop!"
set desc= "Jump to the other server"
if (alert(src, "Jump to server running at [global.cross_address]?", "Server Hop", "Yes", "No") != "Yes")
return 0
if (client && global.cross_allowed)
src << "<span class='notice'>Sending you to [global.cross_address].</span>"
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
client << link(global.cross_address)
else
src << "<span class='error'>There is no other server configured!</span>"
//this is a mob verb instead of atom for performance reasons
//see /mob/verb/examinate() in mob.dm for more info
//overriden here and in /mob/living for different point span classes and sanity checks
/mob/dead/observer/pointed(atom/A as mob|obj|turf in view())
if(!..())
return 0
usr.visible_message("<span class='deadsay'><b>[src]</b> points to [A].</span>")
return 1
/mob/dead/observer/verb/view_manifest()
set name = "View Crew Manifest"
set category = "Ghost"
var/dat
dat += "<h4>Crew Manifest</h4>"
dat += data_core.get_manifest()
src << browse(dat, "window=manifest;size=387x420;can_close=1")
//this is called when a ghost is drag clicked to something.
/mob/dead/observer/MouseDrop(atom/over)
if(!usr || !over) return
if (isobserver(usr) && usr.client.holder && isliving(over))
if (usr.client.holder.cmd_ghost_drag(src,over))
return
return ..()
/mob/dead/observer/Topic(href, href_list)
..()
if(usr == src)
if(href_list["follow"])
var/atom/movable/target = locate(href_list["follow"])
if(istype(target) && (target != src))
ManualFollow(target)
if(href_list["reenter"])
reenter_corpse()
//We don't want to update the current var
//But we will still carry a mind.
/mob/dead/observer/mind_initialize()
return
/mob/dead/observer/proc/show_data_huds()
for(var/hudtype in datahuds)
var/datum/atom_hud/H = huds[hudtype]
H.add_hud_to(src)
/mob/dead/observer/proc/remove_data_huds()
for(var/hudtype in datahuds)
var/datum/atom_hud/H = huds[hudtype]
H.remove_hud_from(src)
/mob/dead/observer/verb/toggle_data_huds()
set name = "Toggle Sec/Med/Diag HUD"
set desc = "Toggles whether you see medical/security/diagnostic HUDs"
set category = "Ghost"
if(data_huds_on) //remove old huds
remove_data_huds()
src << "<span class='notice'>Data HUDs disabled.</span>"
data_huds_on = 0
else
show_data_huds()
src << "<span class='notice'>Data HUDs enabled.</span>"
data_huds_on = 1
/mob/dead/observer/verb/restore_ghost_apperance()
set name = "Restore Ghost Character"
set desc = "Sets your deadchat name and ghost appearance to your \
roundstart character."
set category = "Ghost"
set_ghost_appearance()
if(client && client.prefs)
deadchat_name = client.prefs.real_name
/mob/dead/observer/proc/set_ghost_appearance()
if((!client) || (!client.prefs))
return
if(client.prefs.be_random_name)
client.prefs.real_name = random_unique_name(gender)
if(client.prefs.be_random_body)
client.prefs.random_character(gender)
if(HAIR in client.prefs.pref_species.specflags)
hair_style = client.prefs.hair_style
hair_color = brighten_color(client.prefs.hair_color)
if(FACEHAIR in client.prefs.pref_species.specflags)
facial_hair_style = client.prefs.facial_hair_style
facial_hair_color = brighten_color(client.prefs.facial_hair_color)
update_icon()
/mob/dead/observer/canUseTopic()
if(check_rights(R_ADMIN, 0))
return 1
return
/mob/dead/observer/is_literate()
return 1
/mob/dead/observer/on_varedit(var_name)
. = ..()
switch(var_name)
if("icon")
ghostimage.icon = icon
ghostimage_default.icon = icon
ghostimage_simple.icon = icon
if("icon_state")
ghostimage.icon_state = icon_state
ghostimage_default.icon_state = icon_state
ghostimage_simple.icon_state = icon_state
if("fun_verbs")
if(fun_verbs)
verbs += /mob/dead/observer/verb/boo
verbs += /mob/dead/observer/verb/possess
else
verbs -= /mob/dead/observer/verb/boo
verbs -= /mob/dead/observer/verb/possess
+34
View File
@@ -0,0 +1,34 @@
/mob/dead/observer/say(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
log_say("Ghost/[src.key] : [message]")
if(jobban_isbanned(src, "OOC"))
src << "<span class='danger'>You have been banned from deadchat.</span>"
return
if (src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
src << "<span class='danger'>You cannot talk in deadchat (muted).</span>"
return
if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
. = src.say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
if(istype(V.source, /mob/living/silicon/ai))
var/mob/living/silicon/ai/S = V.source
speaker = S.eyeobj
else
speaker = V.source
var/link = FOLLOW_LINK(src, speaker)
src << "[link] [message]"
+13
View File
@@ -0,0 +1,13 @@
//This is the proc for gibbing a mob. Cannot gib ghosts.
//added different sort of gibs and animations. N
/mob/proc/gib()
return
//This is the proc for turning a mob into ash. Mostly a copy of gib code (above).
//Originally created for wizard disintegrate. I've removed the virus code since it's irrelevant here.
//Dusting robots does not eject the MMI, so it's a bit more powerful than gib() /N
/mob/proc/dust()
return
/mob/proc/death(gibbed)
return
File diff suppressed because it is too large Load Diff
+277
View File
@@ -0,0 +1,277 @@
//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc
//as they handle all relevant stuff like adding it to the player's screen and updating their overlays.
//Returns the thing in our active hand
/mob/proc/get_active_hand()
if(hand)
return l_hand
else
return r_hand
//Returns the thing in our inactive hand
/mob/proc/get_inactive_hand()
if(hand)
return r_hand
else
return l_hand
//Returns if a certain item can be equipped to a certain slot.
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0)
return 0
//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_l_hand(obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!has_left_hand())
return 0
if(!l_hand)
W.loc = src //TODO: move to equipped?
l_hand = W
W.layer = ABOVE_HUD_LAYER //TODO: move to equipped?
W.equipped(src,slot_l_hand)
if(W.pulledby)
W.pulledby.stop_pulling()
update_inv_l_hand()
W.pixel_x = initial(W.pixel_x)
W.pixel_y = initial(W.pixel_y)
return 1
return 0
//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_r_hand(obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!has_right_hand())
return 0
if(!r_hand)
W.loc = src
r_hand = W
W.layer = ABOVE_HUD_LAYER
W.equipped(src,slot_r_hand)
if(W.pulledby)
W.pulledby.stop_pulling()
update_inv_r_hand()
W.pixel_x = initial(W.pixel_x)
W.pixel_y = initial(W.pixel_y)
return 1
return 0
/mob/proc/put_in_hand_check(obj/item/W)
if(lying && !(W.flags&ABSTRACT))
return 0
if(!istype(W))
return 0
return 1
//Puts the item into our active hand if possible. returns 1 on success.
/mob/proc/put_in_active_hand(obj/item/W)
if(hand)
return put_in_l_hand(W)
else
return put_in_r_hand(W)
//Puts the item into our inactive hand if possible. returns 1 on success.
/mob/proc/put_in_inactive_hand(obj/item/W)
if(hand)
return put_in_r_hand(W)
else
return put_in_l_hand(W)
//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success.
//If both fail it drops it on the floor and returns 0.
//This is probably the main one you need to know :)
/mob/proc/put_in_hands(obj/item/W)
if(!W)
return 0
if(put_in_active_hand(W))
return 1
else if(put_in_inactive_hand(W))
return 1
else
W.loc = get_turf(src)
W.layer = initial(W.layer)
W.dropped(src)
return 0
/mob/proc/drop_item_v() //this is dumb.
if(stat == CONSCIOUS && isturf(loc))
return drop_item()
return 0
//Drops the item in our left hand
/mob/proc/drop_l_hand()
if(!loc || !loc.allow_drop())
return
return unEquip(l_hand) //All needed checks are in unEquip
//Drops the item in our right hand
/mob/proc/drop_r_hand()
if(!loc || !loc.allow_drop())
return
return unEquip(r_hand)
//Drops the item in our active hand.
/mob/proc/drop_item()
if(hand)
return drop_l_hand()
else
return drop_r_hand()
//Here lie drop_from_inventory and before_item_take, already forgotten and not missed.
/mob/proc/canUnEquip(obj/item/I, force)
if(!I)
return 1
if((I.flags & NODROP) && !force)
return 0
return 1
/mob/proc/unEquip(obj/item/I, force) //Force overrides NODROP for things like wizarditis and admin undress.
if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP.
return 1
if((I.flags & NODROP) && !force)
return 0
if(I == r_hand)
r_hand = null
update_inv_r_hand()
else if(I == l_hand)
l_hand = null
update_inv_l_hand()
if(I)
if(client)
client.screen -= I
I.loc = loc
I.dropped(src)
if(I)
I.layer = initial(I.layer)
return 1
//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob.
/mob/proc/remove_from_mob(var/obj/O)
unEquip(O)
O.screen_loc = null
return 1
//Outdated but still in use apparently. This should at least be a human proc.
/mob/proc/get_equipped_items()
var/list/items = new/list()
if(hasvar(src,"back"))
if(src:back)
items += src:back
if(hasvar(src,"belt"))
if(src:belt)
items += src:belt
if(hasvar(src,"ears"))
if(src:ears)
items += src:ears
if(hasvar(src,"glasses"))
if(src:glasses)
items += src:glasses
if(hasvar(src,"gloves"))
if(src:gloves)
items += src:gloves
if(hasvar(src,"head"))
if(src:head)
items += src:head
if(hasvar(src,"shoes"))
if(src:shoes)
items += src:shoes
if(hasvar(src,"wear_id"))
if(src:wear_id)
items += src:wear_id
if(hasvar(src,"wear_mask"))
if(src:wear_mask)
items += src:wear_mask
if(hasvar(src,"wear_suit"))
if(src:wear_suit)
items += src:wear_suit
/* if(hasvar(src,"w_radio"))
if(src:w_radio)
items += src:w_radio commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN */
if(hasvar(src,"w_uniform"))
if(src:w_uniform)
items += src:w_uniform
/* if(hasvar(src,"l_hand"))
if(src:l_hand)
items += src:l_hand
if(hasvar(src,"r_hand"))
if(src:r_hand)
items += src:r_hand*/
return items
/obj/item/proc/equip_to_best_slot(var/mob/M)
if(src != M.get_active_hand())
M << "<span class='warning'>You are not holding anything to equip!</span>"
return 0
if(M.equip_to_appropriate_slot(src))
if(M.hand)
M.update_inv_l_hand()
else
M.update_inv_r_hand()
return 1
if(M.s_active && M.s_active.can_be_inserted(src,1)) //if storage active insert there
M.s_active.handle_item_insertion(src)
return 1
var/obj/item/weapon/storage/S = M.get_inactive_hand()
if(istype(S) && S.can_be_inserted(src,1)) //see if we have box in other hand
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_belt)
if(istype(S) && S.can_be_inserted(src,1)) //else we put in belt
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_drone_storage) //else we put in whatever is in drone storage
if(istype(S) && S.can_be_inserted(src,1))
S.handle_item_insertion(src)
S = M.get_item_by_slot(slot_back) //else we put in backpack
if(istype(S) && S.can_be_inserted(src,1))
S.handle_item_insertion(src)
playsound(src.loc, "rustle", 50, 1, -5)
return 1
M << "<span class='warning'>You are unable to equip that!</span>"
return 0
/mob/verb/quick_equip()
set name = "quick-equip"
set hidden = 1
var/obj/item/I = get_active_hand()
if (I)
I.equip_to_best_slot(src)
//used in code for items usable by both carbon and drones, this gives the proper back slot for each mob.(defibrillator, backpack watertank, ...)
/mob/proc/getBackSlot()
return slot_back
/mob/proc/getBeltSlot()
return slot_belt
+271
View File
@@ -0,0 +1,271 @@
/****************************************************
BLOOD SYSTEM
****************************************************/
/mob/living/carbon/human/proc/suppress_bloodloss(amount)
if(bleedsuppress)
return
else
bleedsuppress = 1
spawn(amount)
bleedsuppress = 0
if(stat != DEAD && bleed_rate)
src << "<span class='warning'>The blood soaks through your bandage.</span>"
/mob/living/carbon/monkey/handle_blood()
if(bodytemperature >= 225 && !(disabilities & NOCLONE)) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
if(blood_volume < BLOOD_VOLUME_NORMAL)
blood_volume += 0.1 // regenerate blood VERY slowly
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
if(NOBLOOD in dna.species.specflags)
bleed_rate = 0
return
if(bodytemperature >= 225 && !(disabilities & NOCLONE)) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
if(blood_volume < BLOOD_VOLUME_NORMAL)
blood_volume += 0.1 // regenerate blood VERY slowly
//Effects of bloodloss
switch(blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
if(prob(5))
src << "<span class='warning'>You feel [pick("dizzy","woozy","faint")].</span>"
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
if(prob(5))
blur_eyes(6)
var/word = pick("dizzy","woozy","faint")
src << "<span class='warning'>You feel very [word].</span>"
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
adjustOxyLoss(5)
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woozy","faint")
src << "<span class='warning'>You feel extremely [word].</span>"
if(0 to BLOOD_VOLUME_SURVIVE)
death()
var/temp_bleed = 0
//Bleeding out
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
var/brutedamage = BP.brute_dam
//We want an accurate reading of .len
listclearnulls(BP.embedded_objects)
temp_bleed += 0.5*BP.embedded_objects.len
if(brutedamage > 30)
temp_bleed += 0.5
if(brutedamage > 50)
temp_bleed += 1
if(brutedamage > 70)
temp_bleed += 2
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
if(bleed_rate && !bleedsuppress)
bleed(bleed_rate)
//Makes a blood drop, leaking amt units of blood from the mob
/mob/living/carbon/proc/bleed(amt)
if(blood_volume)
blood_volume = max(blood_volume - amt, 0)
if(isturf(src.loc)) //Blood loss still happens in locker, floor stays clean
if(amt >= 10)
add_splatter_floor(src.loc)
else
add_splatter_floor(src.loc, 1)
/mob/living/carbon/human/bleed(amt)
if(!(NOBLOOD in dna.species.specflags))
..()
/mob/living/proc/restore_blood()
blood_volume = initial(blood_volume)
/mob/living/carbon/human/restore_blood()
blood_volume = BLOOD_VOLUME_NORMAL
bleed_rate = 0
/****************************************************
BLOOD TRANSFERS
****************************************************/
//Gets blood from mob to a container or other mob, preserving all data in it.
/mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced)
if(!blood_volume || !AM.reagents)
return 0
if(blood_volume < BLOOD_VOLUME_BAD && !forced)
return 0
if(blood_volume < amount)
amount = blood_volume
var/blood_id = get_blood_id()
if(!blood_id)
return 0
blood_volume -= amount
var/list/blood_data = get_blood_data(blood_id)
if(iscarbon(AM))
var/mob/living/carbon/C = AM
if(blood_id == C.get_blood_id())//both mobs have the same blood substance
if(blood_id == "blood") //normal blood
if(blood_data["viruses"])
for(var/datum/disease/D in blood_data["viruses"])
if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS))
continue
C.ForceContractDisease(D)
if(!(blood_data["blood_type"] in get_safe_blood(C.dna.blood_type)))
C.reagents.add_reagent("toxin", amount * 0.5)
return 1
C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM)
return 1
AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature)
return 1
/mob/living/proc/get_blood_data(blood_id)
return
/mob/living/carbon/get_blood_data(blood_id)
if(blood_id == "blood") //actual blood reagent
var/blood_data = list()
//set the blood data
blood_data["donor"] = src
blood_data["viruses"] = list()
for(var/datum/disease/D in viruses)
blood_data["viruses"] += D.Copy()
blood_data["blood_DNA"] = copytext(dna.unique_enzymes,1,0)
if(resistances && resistances.len)
blood_data["resistances"] = resistances.Copy()
var/list/temp_chem = list()
for(var/datum/reagent/R in reagents.reagent_list)
temp_chem[R.id] = R.volume
blood_data["trace_chem"] = list2params(temp_chem)
if(mind)
blood_data["mind"] = mind
if(ckey)
blood_data["ckey"] = ckey
if(!suiciding)
blood_data["cloneable"] = 1
blood_data["blood_type"] = copytext(dna.blood_type,1,0)
blood_data["gender"] = gender
blood_data["real_name"] = real_name
blood_data["features"] = dna.features
blood_data["factions"] = faction
return blood_data
//get the id of the substance this mob use as blood.
/mob/proc/get_blood_id()
return
/mob/living/simple_animal/get_blood_id()
if(blood_volume)
return "blood"
/mob/living/carbon/monkey/get_blood_id()
if(!(disabilities & NOCLONE))
return "blood"
/mob/living/carbon/human/get_blood_id()
if(dna.species.exotic_blood)
return dna.species.exotic_blood
else if((NOBLOOD in dna.species.specflags) || (disabilities & NOCLONE))
return
return "blood"
// This is has more potential uses, and is probably faster than the old proc.
/proc/get_safe_blood(bloodtype)
. = list()
if(!bloodtype)
return
switch(bloodtype)
if("A-")
return list("A-", "O-")
if("A+")
return list("A-", "A+", "O-", "O+")
if("B-")
return list("B-", "O-")
if("B+")
return list("B-", "B+", "O-", "O+")
if("AB-")
return list("A-", "B-", "O-", "AB-")
if("AB+")
return list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+")
if("O-")
return list("O-")
if("O+")
return list("O-", "O+")
if("L")
return list("L")
//to add a splatter of blood or other mob liquid.
/mob/living/proc/add_splatter_floor(turf/T, small_drip)
if(get_blood_id() != "blood")
return
if(!T)
T = get_turf(src)
var/list/temp_blood_DNA
if(small_drip)
// Only a certain number of drips (or one large splatter) can be on a given turf.
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
if(drop)
if(drop.drips < 3)
drop.drips++
drop.overlays |= pick(drop.random_icon_states)
drop.transfer_mob_blood_dna(src)
return
else
temp_blood_DNA = list()
temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
qdel(drop)//the drip is replaced by a bigger splatter
else
drop = new(T)
drop.transfer_mob_blood_dna(src)
return
// Find a blood decal or create a new one.
var/obj/effect/decal/cleanable/blood/B = locate() in T
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(T)
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
B.blood_DNA |= temp_blood_DNA
/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
if(!(NOBLOOD in dna.species.specflags))
..()
/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip)
if(!T)
T = get_turf(src)
var/obj/effect/decal/cleanable/xenoblood/B = locate() in T.contents
if(!B)
B = new(T)
B.blood_DNA["UNKNOWN DNA"] = "X*"
/mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip)
if(!T)
T = get_turf(src)
var/obj/effect/decal/cleanable/oil/B = locate() in T.contents
if(!B)
B = new(T)
+179
View File
@@ -0,0 +1,179 @@
/obj/effect/dummy/slaughter //Can't use the wizard one, blocked by jaunt/slow
name = "water"
icon = 'icons/effects/effects.dmi'
icon_state = "nothing"
var/canmove = 1
density = 0
anchored = 1
invisibility = 60
burn_state = LAVA_PROOF
/obj/effect/dummy/slaughter/relaymove(mob/user, direction)
forceMove(get_step(src,direction))
/obj/effect/dummy/slaughter/ex_act()
return
/obj/effect/dummy/slaughter/bullet_act()
return
/obj/effect/dummy/slaughter/singularity_act()
return
/obj/effect/dummy/slaughter/Destroy()
..()
return QDEL_HINT_PUTINPOOL
/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
if(iscarbon(src))
var/mob/living/carbon/C = src
if(C.l_hand || C.r_hand)
//TODO make it toggleable to either forcedrop the items, or deny
//entry when holding them
// literally only an option for carbons though
C << "<span class='warning'>You may not hold items while blood crawling!</span>"
return 0
var/obj/item/weapon/bloodcrawl/B1 = new(C)
var/obj/item/weapon/bloodcrawl/B2 = new(C)
B1.icon_state = "bloodhand_left"
B2.icon_state = "bloodhand_right"
C.put_in_hands(B1)
C.put_in_hands(B2)
C.regenerate_icons()
src.notransform = TRUE
spawn(0)
bloodpool_sink(B)
src.notransform = FALSE
return 1
/mob/living/proc/bloodpool_sink(obj/effect/decal/cleanable/B)
var/turf/mobloc = get_turf(src.loc)
src.visible_message("<span class='warning'>[src] sinks into the pool of blood!</span>")
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
// Extinguish, unbuckle, stop being pulled, set our location into the
// dummy object
var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
src.ExtinguishMob()
// Keep a reference to whatever we're pulling, because forceMove()
// makes us stop pulling
var/pullee = src.pulling
src.holder = holder
src.forceMove(holder)
// if we're not pulling anyone, or we can't eat anyone
if(!pullee || src.bloodcrawl != BLOODCRAWL_EAT)
return
// if the thing we're pulling isn't alive
if (!(istype(pullee, /mob/living)))
return
var/mob/living/victim = pullee
var/kidnapped = FALSE
if(victim.stat == CONSCIOUS)
src.visible_message("<span class='warning'>[victim] kicks free of the blood pool just before entering it!</span>", null, "<span class='notice'>You hear splashing and struggling.</span>")
else if(victim.reagents && victim.reagents.has_reagent("demonsblood"))
visible_message("<span class='warning'>Something prevents [victim] from entering the pool!</span>", "<span class='warning'>A strange force is blocking [victim] from entering!</span>", "<span class='notice'>You hear a splash and a thud.</span>")
else
victim.forceMove(src)
victim.emote("scream")
src.visible_message("<span class='warning'><b>[src] drags [victim] into the pool of blood!</b></span>", null, "<span class='notice'>You hear a splash.</span>")
kidnapped = TRUE
if(kidnapped)
var/success = bloodcrawl_consume(victim)
if(!success)
src << "<span class='danger'>You happily devour... nothing? Your meal vanished at some point!</span>"
return 1
/mob/living/proc/bloodcrawl_consume(mob/living/victim)
src << "<span class='danger'>You begin to feast on [victim]. You can not move while you are doing this.</span>"
var/sound
if(istype(src, /mob/living/simple_animal/slaughter))
var/mob/living/simple_animal/slaughter/SD = src
sound = SD.feast_sound
else
sound = 'sound/magic/Demon_consume.ogg'
for(var/i in 1 to 3)
playsound(get_turf(src),sound, 100, 1)
sleep(30)
if(!victim)
return FALSE
if(victim.reagents && victim.reagents.has_reagent("devilskiss"))
src << "<span class='warning'><b>AAH! THEIR FLESH! IT BURNS!</b></span>"
adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs
var/found_bloodpool = FALSE
for(var/obj/effect/decal/cleanable/target in range(1,get_turf(victim)))
if(target.can_bloodcrawl_in())
victim.forceMove(get_turf(target))
victim.visible_message("<span class='warning'>[target] violently expels [victim]!</span>")
victim.exit_blood_effect(target)
found_bloodpool = TRUE
if(!found_bloodpool)
// Fuck it, just eject them, thanks to some split second cleaning
victim.forceMove(get_turf(victim))
victim.visible_message("<span class='warning'>[victim] appears from nowhere, covered in blood!</span>")
victim.exit_blood_effect()
return TRUE
src << "<span class='danger'>You devour [victim]. Your health is fully restored.</span>"
src.revive(full_heal = 1)
// No defib possible after laughter
victim.adjustBruteLoss(1000)
victim.death()
bloodcrawl_swallow(victim)
return TRUE
/mob/living/proc/bloodcrawl_swallow(var/mob/living/victim)
qdel(victim)
/obj/item/weapon/bloodcrawl
name = "blood crawl"
desc = "You are unable to hold anything while in this form."
icon = 'icons/effects/blood.dmi'
flags = NODROP|ABSTRACT
/mob/living/proc/exit_blood_effect(obj/effect/decal/cleanable/B)
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
var/oldcolor = src.color
//Makes the mob have the color of the blood pool it came out of
if(istype(B, /obj/effect/decal/cleanable/xenoblood))
src.color = rgb(43, 186, 0)
else
src.color = rgb(149, 10, 10)
// but only for a few seconds
spawn(30)
src.color = oldcolor
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
src << "<span class='warning'>Finish eating first!</span>"
return 0
B.visible_message("<span class='warning'>[B] starts to bubble...</span>")
if(!do_after(src, 20, target = B))
return
if(!B)
return
src.loc = B.loc
src.client.eye = src
src.visible_message("<span class='warning'><B>[src] rises out of the pool of blood!</B>")
exit_blood_effect(B)
if(iscarbon(src))
var/mob/living/carbon/C = src
for(var/obj/item/weapon/bloodcrawl/BC in C)
BC.flags = null
C.unEquip(BC)
qdel(BC)
qdel(src.holder)
src.holder = null
return 1
@@ -0,0 +1,230 @@
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
/mob/living/carbon/alien
name = "alien"
voice_name = "alien"
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
faction = list("alien")
ventcrawler = 2
languages_spoken = ALIEN
languages_understood = ALIEN
sight = SEE_MOBS
see_in_dark = 4
verb_say = "hisses"
bubble_icon = "alien"
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
var/nightvision = 1
var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
status_flags = CANPARALYSE|CANPUSH
var/heat_protection = 0.5
var/leaping = 0
gib_type = /obj/effect/decal/cleanable/xenoblood/xgibs
unique_name = 1
var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|queen)( \\(\\d+\\))?")
/mob/living/carbon/alien/New()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
internal_organs += new /obj/item/organ/brain/alien
internal_organs += new /obj/item/organ/alien/hivenode
internal_organs += new /obj/item/organ/tongue/alien
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
AddAbility(new/obj/effect/proc_holder/alien/nightvisiontoggle(null))
..()
/mob/living/carbon/alien/assess_threat() // beepsky won't hunt aliums
return -10
/mob/living/carbon/alien/adjustToxLoss(amount)
return 0
/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire
if(amount > 0)
..(amount * 2)
else
..(amount)
return
/mob/living/carbon/alien/check_eye_prot()
return ..() + 2
/mob/living/carbon/alien/getToxLoss()
return 0
/mob/living/carbon/alien/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
// Aliens are now weak to fire.
//After then, it reacts to the surrounding atmosphere based on your thermal protection
if(!on_fire) // If you're on fire, ignore local air temperature
if(loc_temp > bodytemperature)
//Place is hotter than we are
var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of heat protection.
if(thermal_protection < 1)
bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
else
bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
if(bodytemperature > 360.15)
//Body temperature is too hot.
throw_alert("alien_fire", /obj/screen/alert/alien_fire)
switch(bodytemperature)
if(360 to 400)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else
clear_alert("alien_fire")
/mob/living/carbon/alien/ex_act(severity, target)
..()
switch (severity)
if (1)
gib()
return
if (2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(1)
adjustEarDamage(15,60)
updatehealth()
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
/mob/living/carbon/alien/reagent_check(datum/reagent/R) //can metabolize all reagents
return 0
/mob/living/carbon/alien/IsAdvancedToolUser()
return has_fine_manipulation
/mob/living/carbon/alien/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
/mob/living/carbon/alien/getTrail()
if(getBruteLoss() < 200)
return pick (list("xltrails_1", "xltrails2"))
else
return pick (list("xttrails_1", "xttrails2"))
/*----------------------------------------
Proc: AddInfectionImages()
Des: Gives the client of the alien an image on each infected mob.
----------------------------------------*/
/mob/living/carbon/alien/proc/AddInfectionImages()
if (client)
for (var/mob/living/C in mob_list)
if(C.status_flags & XENO_HOST)
var/obj/item/organ/body_egg/alien_embryo/A = C.getorgan(/obj/item/organ/body_egg/alien_embryo)
if(A)
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
client.images += I
return
/*----------------------------------------
Proc: RemoveInfectionImages()
Des: Removes all infected images from the alien.
----------------------------------------*/
/mob/living/carbon/alien/proc/RemoveInfectionImages()
if (client)
for(var/image/I in client.images)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
return
/mob/living/carbon/alien/canBeHandcuffed()
return 1
/mob/living/carbon/alien/get_standard_pixel_y_offset(lying = 0)
return initial(pixel_y)
/mob/living/carbon/alien/proc/alien_evolve(mob/living/carbon/alien/new_xeno)
src << "<span class='noticealien'>You begin to evolve!</span>"
visible_message("<span class='alertalien'>[src] begins to twist and contort!</span>")
new_xeno.setDir(dir)
if(!alien_name_regex.Find(name))
new_xeno.name = name
new_xeno.real_name = real_name
if(mind)
mind.transfer_to(new_xeno)
qdel(src)
#undef HEAT_DAMAGE_LEVEL_1
#undef HEAT_DAMAGE_LEVEL_2
#undef HEAT_DAMAGE_LEVEL_3
/mob/living/carbon/alien/update_sight()
if(!client)
return
if(stat == DEAD)
sight |= SEE_TURFS
sight |= SEE_MOBS
sight |= SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_OBSERVER
return
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
else
see_in_dark = 4
see_invisible = SEE_INVISIBLE_LIVING
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/cyberimp/eyes/E in internal_organs)
sight |= E.sight_flags
if(E.dark_view)
see_in_dark = max(see_in_dark, E.dark_view)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(see_override)
see_invisible = see_override
@@ -0,0 +1,98 @@
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
..(AM, skipcatch = 1, hitpush = 0)
/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
In all, this is a lot like the monkey code. /N
*/
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return
if (istype(loc, /turf) && istype(loc.loc, /area/start))
M << "No attacking people at spawn, you jackass."
return
switch(M.a_intent)
if ("help")
AdjustSleeping(-5)
resting = 0
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake it up!</span>")
if ("grab")
grabbedby(M)
else
if (health > 0)
M.do_attack_animation(src)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
var/damage = 1
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>")
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
else
M << "<span class='warning'>[name] is too injured for that.</span>"
return
/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L)
return attack_alien(L)
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return 0
switch(M.a_intent)
if("help")
help_shake_act(M)
if("grab")
grabbedby(M)
if ("harm", "disarm")
M.do_attack_animation(src)
return 1
return 0
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
if(..())
if (stat != DEAD)
adjustBruteLoss(rand(1, 3))
updatehealth()
return
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
@@ -0,0 +1,11 @@
/mob/living/carbon/alien/spawn_gibs()
xgibs(loc, viruses)
/mob/living/carbon/alien/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-a"))
/mob/living/carbon/alien/spawn_dust()
new /obj/effect/decal/remains/xeno(loc)
/mob/living/carbon/alien/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-a"))
@@ -0,0 +1,358 @@
/*NOTES:
These are general powers. Specific powers are stored under the appropriate alien creature type.
*/
/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit.
Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien
name = "Alien Power"
panel = "Alien"
var/plasma_cost = 0
var/check_turf = 0
var/has_action = 1
var/datum/action/spell_action/alien/action = null
var/action_icon = 'icons/mob/actions.dmi'
var/action_icon_state = "spell_default"
var/action_background_icon_state = "bg_alien"
/obj/effect/proc_holder/alien/New()
..()
action = new(src)
/obj/effect/proc_holder/alien/Click()
if(!istype(usr,/mob/living/carbon))
return 1
var/mob/living/carbon/user = usr
if(cost_check(check_turf,user))
if(fire(user) && user) // Second check to prevent runtimes when evolving
user.adjustPlasma(-plasma_cost)
return 1
/obj/effect/proc_holder/alien/proc/on_gain(mob/living/carbon/user)
return
/obj/effect/proc_holder/alien/proc/on_lose(mob/living/carbon/user)
return
/obj/effect/proc_holder/alien/proc/fire(mob/living/carbon/user)
return 1
/obj/effect/proc_holder/alien/proc/cost_check(check_turf=0,mob/living/carbon/user,silent = 0)
if(user.stat)
if(!silent)
user << "<span class='noticealien'>You must be conscious to do this.</span>"
return 0
if(user.getPlasma() < plasma_cost)
if(!silent)
user << "<span class='noticealien'>Not enough plasma stored.</span>"
return 0
if(check_turf && (!isturf(user.loc) || istype(user.loc, /turf/open/space)))
if(!silent)
user << "<span class='noticealien'>Bad place for a garden!</span>"
return 0
return 1
/obj/effect/proc_holder/alien/plant
name = "Plant Weeds"
desc = "Plants some alien weeds"
plasma_cost = 50
check_turf = 1
action_icon_state = "alien_plant"
/obj/effect/proc_holder/alien/plant/fire(mob/living/carbon/user)
if(locate(/obj/structure/alien/weeds/node) in get_turf(user))
src << "There's already a weed node here."
return 0
user.visible_message("<span class='alertalien'>[user] has planted some alien weeds!</span>")
new/obj/structure/alien/weeds/node(user.loc)
return 1
/obj/effect/proc_holder/alien/whisper
name = "Whisper"
desc = "Whisper to someone"
plasma_cost = 10
action_icon_state = "alien_whisper"
/obj/effect/proc_holder/alien/whisper/fire(mob/living/carbon/user)
var/list/options = list()
for(var/mob/living/Ms in oview(user))
options += Ms
var/mob/living/M = input("Select who to whisper to:","Whisper to?",null) as null|mob in options
if(!M)
return 0
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
log_say("AlienWhisper: [key_name(user)]->[M.key] : [msg]")
M << "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]"
user << "<span class='noticealien'>You said: \"[msg]\" to [M]</span>"
for(var/ded in dead_mob_list)
if(!isobserver(ded))
continue
var/follow_link_user = FOLLOW_LINK(ded, user)
var/follow_link_whispee = FOLLOW_LINK(ded, M)
ded << "[follow_link_user] \
<span class='name'>[user]</span> \
<span class='alertalien'>Alien Whisper --> </span> \
[follow_link_whispee] \
<span class='name'>[M]</span> \
<span class='noticealien'>[msg]</span>"
else
return 0
return 1
/obj/effect/proc_holder/alien/transfer
name = "Transfer Plasma"
desc = "Transfer Plasma to another alien"
plasma_cost = 0
action_icon_state = "alien_transfer"
/obj/effect/proc_holder/alien/transfer/fire(mob/living/carbon/user)
var/list/mob/living/carbon/aliens_around = list()
for(var/mob/living/carbon/A in oview(user))
if(A.getorgan(/obj/item/organ/alien/plasmavessel))
aliens_around.Add(A)
var/mob/living/carbon/M = input("Select who to transfer to:","Transfer plasma to?",null) as mob in aliens_around
if(!M)
return 0
var/amount = input("Amount:", "Transfer Plasma to [M]") as num
if (amount)
amount = min(abs(round(amount)), user.getPlasma())
if (get_dist(user,M) <= 1)
M.adjustPlasma(amount)
user.adjustPlasma(-amount)
M << "<span class='noticealien'>[user] has transfered [amount] plasma to you.</span>"
user << "<span class='noticealien'>You trasfer [amount] plasma to [M]</span>"
else
user << "<span class='noticealien'>You need to be closer!</span>"
return
/obj/effect/proc_holder/alien/acid
name = "Corrossive Acid"
desc = "Drench an object in acid, destroying it over time."
plasma_cost = 200
action_icon_state = "alien_acid"
/obj/effect/proc_holder/alien/acid/on_gain(mob/living/carbon/user)
user.verbs.Add(/mob/living/carbon/proc/corrosive_acid)
/obj/effect/proc_holder/alien/acid/on_lose(mob/living/carbon/user)
user.verbs.Remove(/mob/living/carbon/proc/corrosive_acid)
/obj/effect/proc_holder/alien/acid/proc/corrode(target,mob/living/carbon/user = usr)
if(target in oview(1,user))
// OBJ CHECK
if(isobj(target))
var/obj/I = target
if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid.
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
// TURF CHECK
else if(istype(target, /turf))
var/turf/T = target
// R WALL
if(istype(T, /turf/closed/wall/r_wall))
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
// R FLOOR
if(istype(T, /turf/open/floor/engine))
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
else// Not a type we can acid.
return 0
new /obj/effect/acid(get_turf(target), target)
user.visible_message("<span class='alertalien'>[user] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!</span>")
return 1
else
src << "<span class='noticealien'>Target is too far away.</span>"
return 0
/obj/effect/proc_holder/alien/acid/fire(mob/living/carbon/alien/user)
var/O = input("Select what to dissolve:","Dissolve",null) as obj|turf in oview(1,user)
if(!O) return 0
return corrode(O,user)
/mob/living/carbon/proc/corrosive_acid(O as obj|turf in oview(1)) // right click menu verb ugh
set name = "Corrossive Acid"
if(!iscarbon(usr))
return
var/mob/living/carbon/user = usr
var/obj/effect/proc_holder/alien/acid/A = locate() in user.abilities
if(!A) return
if(user.getPlasma() > A.plasma_cost && A.corrode(O))
user.adjustPlasma(-A.plasma_cost)
/obj/effect/proc_holder/alien/neurotoxin
name = "Spit Neurotoxin"
desc = "Spits neurotoxin at someone, paralyzing them for a short time."
action_icon_state = "alien_neurotoxin_0"
var/active = 0
/obj/effect/proc_holder/alien/neurotoxin/fire(mob/living/carbon/user)
if(active)
user.ranged_ability = null
user << "<span class='notice'>You empty your neurotoxin gland.</span>"
active = 0
else if(user.ranged_ability && user.ranged_ability != src)
user << "<span class='warning'>You already have another aimed ability readied! Cancel it first."
return
else
user.ranged_ability = src
active = 1
user << "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
user.client.click_intercept = user.ranged_ability
action.button_icon_state = "alien_neurotoxin_[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/carbon/user, params, atom/target)
var/p_cost = 50
if(!iscarbon(user) || user.lying || user.stat)
return
user.next_click = world.time + 6
user.face_atom(target)
if(user.getPlasma() < p_cost)
user << "<span class='warning'>You need at least [p_cost] plasma to spit.</span>"
return
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return 0
user.visible_message("<span class='danger'>[user] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(user.loc)
A.current = U
A.preparePixelProjectile(target, get_turf(target), user, params)
A.fire()
user.newtonian_move(get_dir(U, T))
user.adjustPlasma(-p_cost)
return 1
/obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user)
if(user.ranged_ability == src)
user.ranged_ability = null
/obj/effect/proc_holder/alien/resin
name = "Secrete Resin"
desc = "Secrete tough malleable resin."
plasma_cost = 55
check_turf = 1
var/list/structures = list(
"resin wall" = /obj/structure/alien/resin/wall,
"resin membrane" = /obj/structure/alien/resin/membrane,
"resin nest" = /obj/structure/bed/nest)
action_icon_state = "alien_resin"
/obj/effect/proc_holder/alien/resin/fire(mob/living/carbon/user)
if(locate(/obj/structure/alien/resin) in user.loc)
user << "<span class='danger'>There is already a resin structure there.</span>"
return 0
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in structures
if(!choice)
return 0
if (!cost_check(check_turf,user))
return 0
user << "<span class='notice'>You shape a [choice].</span>"
user.visible_message("<span class='notice'>[user] vomits up a thick purple substance and begins to shape it.</span>")
choice = structures[choice]
new choice(user.loc)
return 1
/obj/effect/proc_holder/alien/regurgitate
name = "Regurgitate"
desc = "Empties the contents of your stomach"
plasma_cost = 0
action_icon_state = "alien_barf"
/obj/effect/proc_holder/alien/regurgitate/fire(mob/living/carbon/user)
if(user.stomach_contents.len)
for(var/atom/movable/A in user.stomach_contents)
user.stomach_contents.Remove(A)
A.loc = user.loc
if(isliving(A))
var/mob/M = A
M.reset_perspective()
user.visible_message("<span class='alertealien'>[user] hurls out the contents of their stomach!</span>")
return
/obj/effect/proc_holder/alien/nightvisiontoggle
name = "Toggle Night Vision"
desc = "Toggles Night Vision"
plasma_cost = 0
has_action = 0 // Has dedicated GUI button already
/obj/effect/proc_holder/alien/nightvisiontoggle/fire(mob/living/carbon/alien/user)
if(!user.nightvision)
user.see_in_dark = 8
user.see_invisible = SEE_INVISIBLE_MINIMUM
user.nightvision = 1
user.hud_used.nightvisionicon.icon_state = "nightvision1"
else if(user.nightvision == 1)
user.see_in_dark = 4
user.see_invisible = 45
user.nightvision = 0
user.hud_used.nightvisionicon.icon_state = "nightvision0"
return 1
/obj/effect/proc_holder/alien/sneak
name = "Sneak"
desc = "Blend into the shadows to stalk your prey."
var/active = 0
action_icon_state = "alien_sneak"
/obj/effect/proc_holder/alien/sneak/fire(mob/living/carbon/alien/humanoid/user)
if(!active)
user.alpha = 75 //Still easy to see in lit areas with bright tiles, almost invisible on resin.
user.sneaking = 1
active = 1
user << "<span class='noticealien'>You blend into the shadows...</span>"
else
user.alpha = initial(user.alpha)
user.sneaking = 0
active = 0
user << "<span class='noticealien'>You reveal yourself!</span>"
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(!vessel) return 0
return vessel.storedPlasma
/mob/living/carbon/proc/adjustPlasma(amount)
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(!vessel) return 0
vessel.storedPlasma = max(vessel.storedPlasma + amount,0)
vessel.storedPlasma = min(vessel.storedPlasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
for(var/X in abilities)
var/obj/effect/proc_holder/alien/APH = X
if(APH.has_action)
APH.action.UpdateButtonIcon()
return 1
/mob/living/carbon/alien/adjustPlasma(amount)
. = ..()
updatePlasmaDisplay()
/mob/living/carbon/proc/usePlasma(amount)
if(getPlasma() >= amount)
adjustPlasma(-amount)
return 1
return 0
/proc/cmp_abilities_cost(obj/effect/proc_holder/alien/a, obj/effect/proc_holder/alien/b)
return b.plasma_cost - a.plasma_cost
@@ -0,0 +1,45 @@
/mob/living/carbon/alien/humanoid/drone
name = "alien drone"
caste = "d"
maxHealth = 125
health = 125
icon_state = "aliend_s"
/mob/living/carbon/alien/humanoid/drone/New()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
..()
/mob/living/carbon/alien/humanoid/drone/movement_delay()
. = ..()
/obj/effect/proc_holder/alien/evolve
name = "Evolve to Praetorian"
desc = "Praetorian"
plasma_cost = 500
action_icon_state = "alien_evolve_drone"
/obj/effect/proc_holder/alien/evolve/fire(mob/living/carbon/alien/humanoid/user)
var/obj/item/organ/alien/hivenode/node = user.getorgan(/obj/item/organ/alien/hivenode)
if(!node) //Players are Murphy's Law. We may not expect there to ever be a living xeno with no hivenode, but they _WILL_ make it happen.
user << "<span class='danger'>Without the hivemind, you can't possibly hold the responsibility of leadership!</span>"
return 0
if(node.recent_queen_death)
user << "<span class='danger'>Your thoughts are still too scattered to take up the position of leadership.</span>"
return 0
if(!isturf(user.loc))
user << "<span class='notice'>You can't evolve here!</span>"
return 0
if(!alien_type_present(/mob/living/carbon/alien/humanoid/royal))
var/mob/living/carbon/alien/humanoid/royal/praetorian/new_xeno = new (user.loc)
user.alien_evolve(new_xeno)
return 1
else
user << "<span class='notice'>We already have a living royal!</span>"
return 0
@@ -0,0 +1,98 @@
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
maxHealth = 125
health = 125
icon_state = "alienh_s"
var/obj/screen/leap_icon = null
/mob/living/carbon/alien/humanoid/hunter/New()
internal_organs += new /obj/item/organ/alien/plasmavessel/small
..()
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
. = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
//Hunter verbs
/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(message = 1)
leap_on_click = !leap_on_click
leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]"
update_icons()
if(message)
src << "<span class='noticealien'>You will now [leap_on_click ? "leap at":"slash at"] enemies!</span>"
else
return
/mob/living/carbon/alien/humanoid/hunter/ClickOn(atom/A, params)
face_atom(A)
if(leap_on_click)
leap_at(A)
else
..()
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A)
if(pounce_cooldown)
src << "<span class='alertalien'>You are too fatigued to pounce right now!</span>"
return
if(leaping || stat || buckled || lying)
return
if(!has_gravity(src) || !has_gravity(A))
src << "<span class='alertalien'>It is unsafe to leap without gravity!</span>"
//It's also extremely buggy visually, so it's balance+bugfix
return
else //Maybe uses plasma in the future, although that wouldn't make any sense...
leaping = 1
update_icons()
throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0, diagonals_first = 1)
leaping = 0
update_icons()
/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A)
if(!leaping)
return ..()
if(A)
if(istype(A, /mob/living))
var/mob/living/L = A
var/blocked = 0
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(90, "the [name]", src, attack_type = THROWN_PROJECTILE_ATTACK))
blocked = 1
if(!blocked)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Weaken(5)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
toggle_leap(0)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
pounce_cooldown = !pounce_cooldown
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
weakened = 2
if(leaping)
leaping = 0
update_icons()
update_canmove()
/mob/living/carbon/alien/humanoid/float(on)
if(leaping)
return
..()
@@ -0,0 +1,50 @@
/mob/living/carbon/alien/humanoid/royal/praetorian
name = "alien praetorian"
caste = "p"
maxHealth = 250
health = 250
icon_state = "alienp"
/mob/living/carbon/alien/humanoid/royal/praetorian/New()
real_name = name
internal_organs += new /obj/item/organ/alien/plasmavessel/large
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
..()
/mob/living/carbon/alien/humanoid/royal/praetorian/movement_delay()
. = ..()
. += 1
/obj/effect/proc_holder/alien/royal/praetorian/evolve
name = "Evolve"
desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time."
plasma_cost = 500
action_icon_state = "alien_evolve_praetorian"
/obj/effect/proc_holder/alien/royal/praetorian/evolve/fire(mob/living/carbon/alien/humanoid/user)
var/obj/item/organ/alien/hivenode/node = user.getorgan(/obj/item/organ/alien/hivenode)
if(!node) //Just in case this particular Praetorian gets violated and kept by the RD as a replacement for Lamarr.
user << "<span class='danger'>Without the hivemind, you would be unfit to rule as queen!</span>"
return 0
if(node.recent_queen_death)
user << "<span class='danger'>You are still too burdened with guilt to evolve into a queen.</span>"
return 0
if(!alien_type_present(/mob/living/carbon/alien/humanoid/royal/queen))
var/mob/living/carbon/alien/humanoid/royal/queen/new_xeno = new (user.loc)
user.alien_evolve(new_xeno)
if(new_xeno.client.prefs.unlock_content)
var/datum/action/innate/maid/M = new()
M.Grant(new_xeno)
return 1
else
user << "<span class='notice'>We already have an alive queen.</span>"
return 0
@@ -0,0 +1,17 @@
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
maxHealth = 150
health = 150
icon_state = "aliens_s"
/mob/living/carbon/alien/humanoid/sentinel/New()
internal_organs += new /obj/item/organ/alien/plasmavessel
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
AddAbility(new /obj/effect/proc_holder/alien/sneak)
..()
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
. = ..()
@@ -0,0 +1,28 @@
/mob/living/carbon/alien/humanoid/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
if(!gibbed)
playsound(loc, 'sound/voice/hiss6.ogg', 80, 1, 1)
visible_message("<span class='name'>[src]</span> lets out a waning guttural screech, green blood bubbling from its maw...")
update_canmove()
update_icons()
status_flags |= CANPUSH
return ..()
//When the alien queen dies, all others must pay the price for letting her die.
/mob/living/carbon/alien/humanoid/royal/queen/death(gibbed)
if(stat == DEAD)
return
for(var/mob/living/carbon/C in living_mob_list)
if(C == src) //Make sure not to proc it on ourselves.
continue
var/obj/item/organ/alien/hivenode/node = C.getorgan(/obj/item/organ/alien/hivenode)
if(istype(node)) // just in case someone would ever add a diffirent node to hivenode slot
node.queen_death()
return ..(gibbed)
@@ -0,0 +1,88 @@
/mob/living/carbon/alien/humanoid/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
switch(act) //Alphabetical please
if ("deathgasp","deathgasps")
message = "<span class='name'>[src]</span> lets out a waning guttural screech, green blood bubbling from its maw..."
m_type = 2
if ("gnarl","gnarls")
if (!muzzled)
message = "<span class='name'>[src]</span> gnarls and shows its teeth.."
m_type = 2
if ("hiss","hisses")
if(!muzzled)
message = "<span class='name'>[src]</span> hisses."
m_type = 2
if ("me")
..()
return
if ("moan","moans")
message = "<span class='name'>[src]</span> moans!"
m_type = 2
if ("roar","roars")
if (!muzzled)
message = "<span class='name'>[src]</span> roars."
m_type = 2
if ("roll","rolls")
if (!src.restrained())
message = "<span class='name'>[src]</span> rolls."
m_type = 1
if ("scratch","scratches")
if (!src.restrained())
message = "<span class='name'>[src]</span> scratches."
m_type = 1
if ("screech","screeches")
if (!muzzled)
message = "<span class='name'>[src]</span> screeches."
m_type = 2
if ("shiver","shivers")
message = "<span class='name'>[src]</span> shivers."
m_type = 2
if ("sign","signs")
if (!src.restrained())
message = text("<span class='name'>[src]</span> signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null))
m_type = 1
if ("tail")
message = "<span class='name'>[src]</span> waves its tail."
m_type = 1
if ("help") //This is an exception
src << "Help for xenomorph emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow, burp, choke, chucke, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, giggle, glare-(none)/mob, gnarl, hiss, jump, laugh, look-atom, me, moan, nod, point-atom, roar, roll, scream, scratch, screech, shake, shiver, sign-#, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tail, tremble, twitch, twitch_s, wave, whimper, wink, yawn"
else
..(act)
if ((message && src.stat == 0))
log_emote("[name]/[key] : [message]")
if (act == "roar")
playsound(src.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
if (act == "hiss")
playsound(src.loc, "hiss", 40, 1, 1)
if (act == "deathgasp")
playsound(src.loc, 'sound/voice/hiss6.ogg', 80, 1, 1)
if (m_type & 1)
visible_message(message)
else
audible_message(message)
return
@@ -0,0 +1,185 @@
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien_s"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/leap_on_click = 0
var/pounce_cooldown = 0
var/pounce_cooldown_time = 30
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
var/sneaking = 0 //For sneaky-sneaky mode and appropriate slowdown
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
. += move_delay_add + config.alien_delay + sneaking //move_delay_add is used to slow aliens with stuns
/mob/living/carbon/alien/humanoid/emp_act(severity)
if(r_store) r_store.emp_act(severity)
if(l_store) l_store.emp_act(severity)
..()
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
adjustBruteLoss(15)
var/hitverb = "punched"
if(mob_size < MOB_SIZE_LARGE)
Paralyse(1)
step_away(src,user,15)
sleep(1)
step_away(src,user,15)
hitverb = "slammed"
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has [hitverb] [src]!</span>", \
"<span class='userdanger'>[user] has [hitverb] [src]!</span>")
return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
if(..())
switch(M.a_intent)
if ("harm")
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>")
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of weakening an alien.
Paralyse(2)
visible_message("<span class='danger'>[M] has weakened [src]!</span>", \
"<span class='userdanger'>[M] has weakened [src]!</span>")
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>")
if ("disarm")
if (!lying)
if (prob(5))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
if (prob(50))
drop_item()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>")
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
. = handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=[slot_l_hand]'> [l_hand ? l_hand : "Nothing"]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=[slot_r_hand]'> [r_hand ? r_hand : "Nothing"]</A>
<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"}
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat, "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["pouches"])
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
unEquip(r_store)
unEquip(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
..(I, cuff_break = INSTANT_CUFFBREAK)
/mob/living/carbon/alien/humanoid/resist_grab(moving_resist)
if(pulledby.grab_state)
visible_message("<span class='danger'>[src] has broken free of [pulledby]'s grip!</span>")
pulledby.stop_pulling()
. = 0
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_y_offset)
return custom_pixel_y_offset
else
return initial(pixel_y)
/mob/living/carbon/alien/humanoid/get_standard_pixel_x_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_x_offset)
return custom_pixel_x_offset
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/check_ear_prot()
return 1
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
/mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno)
drop_l_hand()
drop_r_hand()
for(var/atom/movable/A in stomach_contents)
stomach_contents.Remove(A)
new_xeno.stomach_contents.Add(A)
A.loc = new_xeno
..()
//For alien evolution/promotion procs. Checks for
proc/alien_type_present(var/alienpath)
for(var/mob/living/carbon/alien/humanoid/A in living_mob_list)
if(!istype(A, alienpath))
continue
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
continue
return 1
return 0
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
..()
/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling))
devour_mob(pulling, devour_time = 60)
else
..()
@@ -0,0 +1,5 @@
/mob/living/carbon/alien/humanoid/unEquip(obj/item/I)
. = ..()
if(!. || !I)
return
@@ -0,0 +1,18 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference/5
else
increments = difference/10
var/change = increments*boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
@@ -0,0 +1,164 @@
/mob/living/carbon/alien/humanoid/royal
//Common stuffs for Praetorian and Queen
icon = 'icons/mob/alienqueen.dmi'
status_flags = 0
ventcrawler = 0 //pull over that ass too fat
unique_name = 0
pixel_x = -16
bubble_icon = "alienroyal"
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 20, /obj/item/stack/sheet/animalhide/xeno = 3)
var/alt_inhands_file = 'icons/mob/alienqueen.dmi'
/mob/living/carbon/alien/humanoid/royal/can_inject()
return 0
/mob/living/carbon/alien/humanoid/royal/queen
name = "alien queen"
caste = "q"
maxHealth = 400
health = 400
icon_state = "alienq"
/mob/living/carbon/alien/humanoid/royal/queen/New()
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/royal/queen/Q in living_mob_list)
if(Q == src)
continue
if(Q.stat == DEAD)
continue
if(Q.client)
name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it.
break
real_name = src.name
internal_organs += new /obj/item/organ/alien/plasmavessel/large/queen
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
internal_organs += new /obj/item/organ/alien/eggsac
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote())
..()
/mob/living/carbon/alien/humanoid/royal/queen/movement_delay()
. = ..()
. += 5
//Queen verbs
/obj/effect/proc_holder/alien/lay_egg
name = "Lay Egg"
desc = "Lay an egg to produce huggers to impregnate prey with."
plasma_cost = 75
check_turf = 1
action_icon_state = "alien_egg"
/obj/effect/proc_holder/alien/lay_egg/fire(mob/living/carbon/user)
if(locate(/obj/structure/alien/egg) in get_turf(user))
user << "There's already an egg here."
return 0
user.visible_message("<span class='alertalien'>[user] has laid an egg!</span>")
new /obj/structure/alien/egg(user.loc)
return 1
//Button to let queen choose her praetorian.
/obj/effect/proc_holder/alien/royal/queen/promote
name = "Create Royal Parasite"
desc = "Produce a royal parasite to grant one of your children the honor of being your Praetorian."
plasma_cost = 500 //Plasma cost used on promotion, not spawning the parasite.
action_icon_state = "alien_queen_promote"
/obj/effect/proc_holder/alien/royal/queen/promote/fire(mob/living/carbon/alien/user)
var/obj/item/queenpromote/prom
if(alien_type_present(/mob/living/carbon/alien/humanoid/royal/praetorian/))
user << "<span class='noticealien'>You already have a Praetorian!</span>"
return 0
else
for(prom in user)
user << "<span class='noticealien'>You discard [prom].</span>"
qdel(prom)
return 0
prom = new (user.loc)
if(!user.put_in_active_hand(prom, 1))
user << "<span class='warning'>You must empty your hands before preparing the parasite.</span>"
return 0
else //Just in case telling the player only once is not enough!
user << "<span class='noticealien'>Use the royal parasite on one of your children to promote her to Praetorian!</span>"
return 0
/obj/item/queenpromote
name = "\improper royal parasite"
desc = "Inject this into one of your grown children to promote her to a Praetorian!"
icon_state = "alien_medal"
flags = ABSTRACT|NODROP
icon = 'icons/mob/alien.dmi'
/obj/item/queenpromote/attack(mob/living/M, mob/living/carbon/alien/humanoid/user)
if(!isalienadult(M) || istype(M, /mob/living/carbon/alien/humanoid/royal))
user << "<span class='noticealien'>You may only use this with your adult, non-royal children!</span>"
return
if(alien_type_present(/mob/living/carbon/alien/humanoid/royal/praetorian/))
user << "<span class='noticealien'>You already have a Praetorian!</span>"
return
var/mob/living/carbon/alien/humanoid/A = M
if(A.stat == CONSCIOUS && A.mind && A.key)
if(!user.usePlasma(500))
user << "<span class='noticealien'>You must have 500 plasma stored to use this!</span>"
return
A << "<span class='noticealien'>The queen has granted you a promotion to Praetorian!</span>"
user.visible_message("<span class='alertalien'>[A] begins to expand, twist and contort!</span>")
var/mob/living/carbon/alien/humanoid/royal/praetorian/new_prae = new (A.loc)
A.mind.transfer_to(new_prae)
qdel(A)
qdel(src)
return
else
user << "<span class='warning'>This child must be alert and responsive to become a Praetorian!</span>"
/obj/item/queenpromote/attack_self(mob/user)
user << "<span class='noticealien'>You discard [src].</span>"
qdel(src)
//:^)
/datum/action/innate/maid
name = "Maidify"
button_icon_state = "alien_queen_maidify"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS|AB_CHECK_LYING
background_icon_state = "bg_alien"
/datum/action/innate/maid/Activate()
var/mob/living/carbon/alien/humanoid/royal/queen/A = owner
A.maidify()
active = TRUE
/datum/action/innate/maid/Deactivate()
var/mob/living/carbon/alien/humanoid/royal/queen/A = owner
A.unmaidify()
active = FALSE
/mob/living/carbon/alien/humanoid/royal/queen/proc/maidify()
name = "alien queen maid"
desc = "Lusty, Sexy"
icon_state = "alienqmaid"
caste = "qmaid"
update_icons()
/mob/living/carbon/alien/humanoid/royal/queen/proc/unmaidify()
name = "alien queen"
desc = ""
icon_state = "alienq"
caste = "q"
update_icons()
@@ -0,0 +1,77 @@
/mob/living/carbon/alien/humanoid/update_icons()
cut_overlays()
for(var/image/I in overlays_standing)
add_overlay(I)
if(stat == DEAD)
//If we mostly took damage from fire
if(fireloss > 125)
icon_state = "alien[caste]_husked"
else
icon_state = "alien[caste]_dead"
else if((stat == UNCONSCIOUS && !sleeping) || weakened)
icon_state = "alien[caste]_unconscious"
else if(leap_on_click)
icon_state = "alien[caste]_pounce"
else if(lying || resting || sleeping)
icon_state = "alien[caste]_sleep"
else if(mob_size == MOB_SIZE_LARGE)
icon_state = "alien[caste]"
else
icon_state = "alien[caste]_s"
if(leaping)
if(alt_icon == initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
icon_state = "alien[caste]_leap"
pixel_x = -32
pixel_y = -32
else
if(alt_icon != initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
pixel_x = get_standard_pixel_x_offset(lying)
pixel_y = get_standard_pixel_y_offset(lying)
/mob/living/carbon/alien/humanoid/regenerate_icons()
if(!..())
// update_icons() //Handled in update_transform(), leaving this here as a reminder
update_transform()
/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that.
if(lying > 0)
lying = 90 //Anything else looks retarded
..()
update_icons()
//Royals have bigger sprites, so inhand things must be handled differently.
/mob/living/carbon/alien/humanoid/royal/update_inv_r_hand()
..()
remove_overlay(R_HAND_LAYER)
if(r_hand)
var/itm_state = r_hand.item_state
if(!itm_state)
itm_state = r_hand.icon_state
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_r", "layer"=-R_HAND_LAYER)
overlays_standing[R_HAND_LAYER] = I
apply_overlay(R_HAND_LAYER)
/mob/living/carbon/alien/humanoid/royal/update_inv_l_hand()
..()
remove_overlay(L_HAND_LAYER)
if(l_hand)
var/itm_state = l_hand.item_state
if(!itm_state)
itm_state = l_hand.icon_state
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_l", "layer"=-L_HAND_LAYER)
overlays_standing[L_HAND_LAYER] = I
apply_overlay(L_HAND_LAYER)
@@ -0,0 +1,10 @@
/mob/living/carbon/alien/larva/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
icon_state = "larva_dead"
if(!gibbed)
visible_message("<span class='name'>[src]</span> lets out a waning high-pitched cry.")
return ..(gibbed)
@@ -0,0 +1,113 @@
/mob/living/carbon/alien/larva/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
switch(act) //Alphabetically sorted please.
if ("burp","burps")
if (!muzzled)
message = "<span class='name'>[src]</span> burps."
m_type = 2
if ("choke","chokes")
message = "<span class='name'>[src]</span> chokes."
m_type = 2
if ("collapse","collapses")
Paralyse(2)
message = "<span class='name'>[src]</span> collapses!"
m_type = 2
if ("dance","dances")
if (!src.restrained())
message = "<span class='name'>[src]</span> dances around happily."
m_type = 1
if ("deathgasp","deathgasps")
message = "<span class='name'>[src]</span> lets out a sickly hiss of air and falls limply to the floor..."
m_type = 2
if ("drool","drools")
message = "<span class='name'>[src]</span> drools."
m_type = 1
if ("gasp","gasps")
message = "<span class='name'>[src]</span> gasps."
m_type = 2
if ("gnarl","gnarls")
if (!muzzled)
message = "<span class='name'>[src]</span> gnarls and shows its teeth.."
m_type = 2
if ("hiss","hisses")
message = "<span class='name'>[src]</span> hisses softly."
m_type = 1
if ("jump","jumps")
message = "<span class='name'>[src]</span> jumps!"
m_type = 1
if ("me")
..()
return
if ("moan","moans")
message = "<span class='name'>[src]</span> moans!"
m_type = 2
if ("nod","nods")
message = "<span class='name'>[src]</span> nods its head."
m_type = 1
if ("roar","roars")
if (!muzzled)
message = "<span class='name'>[src]</span> softly roars."
m_type = 2
if ("roll","rolls")
if (!src.restrained())
message = "<span class='name'>[src]</span> rolls."
m_type = 1
if ("scratch","scratches")
if (!src.restrained())
message = "<span class='name'>[src]</span> scratches."
m_type = 1
if ("screech","screeches") //This orignally was called scretch, changing it. -Sum99
if (!muzzled)
message = "<span class='name'>[src]</span> screeches."
m_type = 2
if ("shake","shakes")
message = "<span class='name'>[src]</span> shakes its head."
m_type = 1
if ("shiver","shivers")
message = "<span class='name'>[src]</span> shivers."
m_type = 2
if ("sign","signs")
if (!src.restrained())
message = text("<span class='name'>[src]</span> signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null))
m_type = 1
if ("snore","snores")
message = "<B>[src]</B> snores."
m_type = 2
if ("sulk","sulks")
message = "<span class='name'>[src]</span> sulks down sadly."
m_type = 1
if ("sway","sways")
message = "<span class='name'>[src]</span> sways around dizzily."
m_type = 1
if ("tail")
message = "<span class='name'>[src]</span> waves its tail."
m_type = 1
if ("twitch")
message = "<span class='name'>[src]</span> twitches violently."
m_type = 1
if ("whimper","whimpers")
if (!muzzled)
message = "<span class='name'>[src]</span> whimpers."
m_type = 2
if ("help") //"The exception"
src << "Help for larva emotes. You can use these emotes with say \"*emote\":\n\nburp, choke, collapse, dance, deathgasp, drool, gasp, gnarl, hiss, jump, me, moan, nod, roll, roar, scratch, screech, shake, shiver, sign-#, sulk, sway, tail, twitch, whimper"
else
src << "<span class='info'>Unusable emote '[act]'. Say *help for a list.</span>"
if ((message && src.stat == 0))
log_emote("[name]/[key] : [message]")
if (m_type & 1)
visible_message(message)
else
audible_message(message)
return
@@ -0,0 +1,3 @@
//can't unequip since it can't equip anything
/mob/living/carbon/alien/larva/unEquip(obj/item/W)
return
@@ -0,0 +1,95 @@
/mob/living/carbon/alien/larva
name = "alien larva"
real_name = "alien larva"
icon_state = "larva0"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
density = 0
maxHealth = 25
health = 25
var/amount_grown = 0
var/max_grown = 100
var/time_of_birth
rotate_on_lying = 0
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/larva/New()
regenerate_icons()
internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny
AddAbility(new/obj/effect/proc_holder/alien/hide(null))
AddAbility(new/obj/effect/proc_holder/alien/larva_evolve(null))
..()
//This needs to be fixed
/mob/living/carbon/alien/larva/Stat()
..()
if(statpanel("Status"))
stat(null, "Progress: [amount_grown]/[max_grown]")
/mob/living/carbon/alien/larva/adjustPlasma(amount)
if(stat != DEAD && amount > 0)
amount_grown = min(amount_grown + 1, max_grown)
..(amount)
//can't equip anything
/mob/living/carbon/alien/larva/attack_ui(slot_id)
return
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
adjustBruteLoss(5 + rand(1,9))
Paralyse(1)
spawn()
step_away(src,user,15)
sleep(1)
step_away(src,user,15)
return 1
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
if(..())
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
add_logs(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>")
if ((stat != DEAD) && (damage > 4.9))
Paralyse(rand(5,10))
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
"<span class='userdanger'>[M] has attempted to kick [src]!</span>")
return
/mob/living/carbon/alien/larva/restrained(ignore_grab)
. = 0
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
/mob/living/carbon/alien/larva/show_inv(mob/user)
return
/mob/living/carbon/alien/larva/toggle_throw_mode()
return
/mob/living/carbon/alien/larva/start_pulling()
return
/mob/living/carbon/alien/larva/stripPanelUnequip(obj/item/what, mob/who)
src << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
/mob/living/carbon/alien/larva/stripPanelEquip(obj/item/what, mob/who)
src << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
@@ -0,0 +1,35 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/alien/larva/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(..())
// GROW!
if(amount_grown < max_grown)
amount_grown++
update_icons()
/mob/living/carbon/alien/larva/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health<= -maxHealth || !getorgan(/obj/item/organ/brain))
death()
return
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= config.health_threshold_crit)
if(stat == CONSCIOUS)
stat = UNCONSCIOUS
blind_eyes(1)
update_canmove()
else
if(stat == UNCONSCIOUS)
stat = CONSCIOUS
resting = 0
adjust_blindness(-1)
update_canmove()
update_damage_hud()
update_health_hud()
@@ -0,0 +1,62 @@
/obj/effect/proc_holder/alien/hide
name = "Hide"
desc = "Allows to hide beneath tables or certain items. Toggled on or off."
plasma_cost = 0
action_icon_state = "alien_hide"
/obj/effect/proc_holder/alien/hide/fire(mob/living/carbon/alien/user)
if(user.stat != CONSCIOUS)
return
if (user.layer != ABOVE_NORMAL_TURF_LAYER)
user.layer = ABOVE_NORMAL_TURF_LAYER
user.visible_message("<span class='name'>[user] scurries to the ground!</span>", \
"<span class='noticealien'>You are now hiding.</span>")
else
user.layer = MOB_LAYER
user.visible_message("[user.] slowly peaks up from the ground...", \
"<span class='noticealien'>You stop hiding.</span>")
return 1
/obj/effect/proc_holder/alien/larva_evolve
name = "Evolve"
desc = "Evolve into a fully grown Alien."
plasma_cost = 0
action_icon_state = "alien_evolve_larva"
/obj/effect/proc_holder/alien/larva_evolve/fire(mob/living/carbon/alien/user)
if(!islarva(user))
return
var/mob/living/carbon/alien/larva/L = user
if(L.handcuffed || L.legcuffed) // Cuffing larvas ? Eh ?
user << "<span class='danger'>You cannot evolve when you are cuffed.</span>"
if(L.amount_grown >= L.max_grown) //TODO ~Carn
L << "<span class='name'>You are growing into a beautiful alien! It is time to choose a caste.</span>"
L << "<span class='info'>There are three to choose from:"
L << "<span class='name'>Hunters</span> <span class='info'>are the most agile caste tasked with hunting for hosts. They are faster than a human and can even pounce, but are not much tougher than a drone.</span>"
L << "<span class='name'>Sentinels</span> <span class='info'>are tasked with protecting the hive. With their ranged spit, invisibility, and high health, they make formidable guardians and acceptable secondhand hunters.</span>"
L << "<span class='name'>Drones</span> <span class='info'>are the weakest and slowest of the castes, but can grow into the queen if there is none, and are vital to maintaining a hive with their resin secretion abilities.</span>"
var/alien_caste = alert(L, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
if(user.incapacitated()) //something happened to us while we were choosing.
return
var/mob/living/carbon/alien/humanoid/new_xeno
switch(alien_caste)
if("Hunter")
new_xeno = new /mob/living/carbon/alien/humanoid/hunter(L.loc)
if("Sentinel")
new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(L.loc)
if("Drone")
new_xeno = new /mob/living/carbon/alien/humanoid/drone(L.loc)
L.alien_evolve(new_xeno)
return 0
else
user << "<span class='danger'>You are not fully grown.</span>"
return 0
@@ -0,0 +1,31 @@
/mob/living/carbon/alien/larva/regenerate_icons()
overlays = list()
update_icons()
/mob/living/carbon/alien/larva/update_icons()
var/state = 0
if(amount_grown > 150)
state = 2
else if(amount_grown > 50)
state = 1
if(stat == DEAD)
icon_state = "larva[state]_dead"
else if (handcuffed || legcuffed) //This should be an overlay. Who made this an icon_state?
icon_state = "larva[state]_cuff"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "larva[state]_sleep"
else if (stunned)
icon_state = "larva[state]_stun"
else
icon_state = "larva[state]"
/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
..()
return update_icons()
/mob/living/carbon/alien/larva/update_inv_handcuffed()
update_icons() //larva icon_state changes if cuffed/uncuffed.
@@ -0,0 +1,45 @@
/mob/living/carbon/alien/check_breath(datum/gas_mixture/breath)
if(status_flags & GODMODE)
return
if(!breath || (breath.total_moles() == 0))
//Aliens breathe in vaccuum
return 0
var/toxins_used = 0
var/tox_detect_threshold = 0.02
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/list/breath_gases = breath.gases
breath.assert_gases("plasma", "o2")
//Partial pressure of the toxins in our breath
var/Toxins_pp = (breath_gases["plasma"][MOLES]/breath.total_moles())*breath_pressure
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
adjustPlasma(breath_gases["plasma"][MOLES]*250)
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
toxins_used = breath_gases["plasma"][MOLES]
else
clear_alert("alien_tox")
//Breathe in toxins and out oxygen
breath_gases["plasma"][MOLES] -= toxins_used
breath_gases["o2"][MOLES] += toxins_used
breath.garbage_collect()
//BREATH TEMPERATURE
handle_breath_temperature(breath)
/mob/living/carbon/alien/handle_status_effects()
..()
//natural reduction of movement delay due to stun.
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - rand(1, 2))
/mob/living/carbon/alien/handle_changeling()
return
@@ -0,0 +1,4 @@
/mob/living/carbon/alien/Login()
..()
AddInfectionImages()
return
@@ -0,0 +1,4 @@
/mob/living/carbon/alien/Logout()
..()
RemoveInfectionImages()
return
@@ -0,0 +1,187 @@
/obj/item/organ/alien
origin_tech = "biotech=5"
icon_state = "xgibmid2"
var/list/alien_powers = list()
/obj/item/organ/alien/New()
for(var/A in alien_powers)
if(ispath(A))
alien_powers -= A
alien_powers += new A(src)
..()
/obj/item/organ/alien/Insert(mob/living/carbon/M, special = 0)
..()
for(var/obj/effect/proc_holder/alien/P in alien_powers)
M.AddAbility(P)
/obj/item/organ/alien/Remove(mob/living/carbon/M, special = 0)
for(var/obj/effect/proc_holder/alien/P in alien_powers)
M.RemoveAbility(P)
..()
/obj/item/organ/alien/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/alien/plasmavessel
name = "plasma vessel"
icon_state = "plasma"
origin_tech = "biotech=5;plasmatech=4"
w_class = 3
zone = "chest"
slot = "plasmavessel"
alien_powers = list(/obj/effect/proc_holder/alien/plant, /obj/effect/proc_holder/alien/transfer)
var/storedPlasma = 100
var/max_plasma = 250
var/heal_rate = 5
var/plasma_rate = 10
/obj/item/organ/alien/plasmavessel/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("plasma", storedPlasma/10)
return S
/obj/item/organ/alien/plasmavessel/large
name = "large plasma vessel"
icon_state = "plasma_large"
w_class = 4
storedPlasma = 200
max_plasma = 500
plasma_rate = 15
/obj/item/organ/alien/plasmavessel/large/queen
origin_tech = "biotech=6;plasmatech=4"
plasma_rate = 20
/obj/item/organ/alien/plasmavessel/small
name = "small plasma vessel"
icon_state = "plasma_small"
w_class = 2
storedPlasma = 100
max_plasma = 150
plasma_rate = 5
/obj/item/organ/alien/plasmavessel/small/tiny
name = "tiny plasma vessel"
icon_state = "plasma_tiny"
w_class = 1
max_plasma = 100
alien_powers = list(/obj/effect/proc_holder/alien/transfer)
/obj/item/organ/alien/plasmavessel/on_life()
//If there are alien weeds on the ground then heal if needed or give some plasma
if(locate(/obj/structure/alien/weeds) in owner.loc)
if(owner.health >= owner.maxHealth)
owner.adjustPlasma(plasma_rate)
else
var/heal_amt = heal_rate
if(!isalien(owner))
heal_amt *= 0.2
owner.adjustPlasma(plasma_rate*0.5)
owner.adjustBruteLoss(-heal_amt)
owner.adjustFireLoss(-heal_amt)
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
..()
if(isalien(M))
var/mob/living/carbon/alien/A = M
A.updatePlasmaDisplay()
/obj/item/organ/alien/plasmavessel/Remove(mob/living/carbon/M, special = 0)
..()
if(isalien(M))
var/mob/living/carbon/alien/A = M
A.updatePlasmaDisplay()
/obj/item/organ/alien/hivenode
name = "hive node"
icon_state = "hivenode"
zone = "head"
slot = "hivenode"
origin_tech = "biotech=5;magnets=4;bluespace=3"
w_class = 1
var/recent_queen_death = 0 //Indicates if the queen died recently, aliens are heavily weakened while this is active.
alien_powers = list(/obj/effect/proc_holder/alien/whisper)
/obj/item/organ/alien/hivenode/Insert(mob/living/carbon/M, special = 0)
..()
M.faction |= "alien"
/obj/item/organ/alien/hivenode/Remove(mob/living/carbon/M, special = 0)
M.faction -= "alien"
..()
//When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her.
/obj/item/organ/alien/hivenode/proc/queen_death()
if(!owner|| owner.stat == DEAD)
return
if(isalien(owner)) //Different effects for aliens than humans
owner << "<span class='userdanger'>Your Queen has been struck down!</span>"
owner << "<span class='danger'>You are struck with overwhelming agony! You feel confused, and your connection to the hivemind is severed."
owner.emote("roar")
owner.Stun(10) //Actually just slows them down a bit.
else if(ishuman(owner)) //Humans, being more fragile, are more overwhelmed by the mental backlash.
owner << "<span class='danger'>You feel a splitting pain in your head, and are struck with a wave of nausea. You cannot hear the hivemind anymore!"
owner.emote("scream")
owner.Weaken(5)
owner.jitteriness += 30
owner.confused += 30
owner.stuttering += 30
recent_queen_death = 1
owner.throw_alert("alien_noqueen", /obj/screen/alert/alien_vulnerable)
spawn(2400) //four minutes
if(qdeleted(src)) //In case the node is deleted
return
recent_queen_death = 0
if(!owner) //In case the xeno is butchered or subjected to surgery after death.
return
owner << "<span class='noticealien'>The pain of the queen's death is easing. You begin to hear the hivemind again.</span>"
owner.clear_alert("alien_noqueen")
/obj/item/organ/alien/resinspinner
name = "resin spinner"
icon_state = "stomach-x"
zone = "mouth"
slot = "resinspinner"
origin_tech = "biotech=5;materials=4"
alien_powers = list(/obj/effect/proc_holder/alien/resin)
/obj/item/organ/alien/acid
name = "acid gland"
icon_state = "acid"
zone = "mouth"
slot = "acidgland"
origin_tech = "biotech=5;materials=2;combat=2"
alien_powers = list(/obj/effect/proc_holder/alien/acid)
/obj/item/organ/alien/neurotoxin
name = "neurotoxin gland"
icon_state = "neurotox"
zone = "mouth"
slot = "neurotoxingland"
origin_tech = "biotech=5;combat=5"
alien_powers = list(/obj/effect/proc_holder/alien/neurotoxin)
/obj/item/organ/alien/eggsac
name = "egg sac"
icon_state = "eggsac"
zone = "groin"
slot = "eggsac"
w_class = 4
origin_tech = "biotech=6"
alien_powers = list(/obj/effect/proc_holder/alien/lay_egg)
@@ -0,0 +1,22 @@
/mob/living/proc/alien_talk(message, shown_name = name)
log_say("[key_name(src)] : [message]")
message = trim(message)
if(!message) return
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/S in player_list)
if(!S.stat && S.hivecheck())
S << rendered
if(S in dead_mob_list)
var/link = FOLLOW_LINK(S, src)
S << "[link] [rendered]"
/mob/living/carbon/alien/humanoid/royal/queen/alien_talk(message, shown_name = name)
shown_name = "<FONT size = 3>[shown_name]</FONT>"
..(message, shown_name)
/mob/living/carbon/hivecheck()
var/obj/item/organ/alien/hivenode/N = getorgan(/obj/item/organ/alien/hivenode)
if(N && !N.recent_queen_death) //Mob has alien hive node and is not under the dead queen special effect.
return N
@@ -0,0 +1,7 @@
/mob/living/carbon/alien/proc/updatePlasmaDisplay()
if(hud_used) //clientless aliens
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='magenta'>[round(getPlasma())]</font></div>"
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
return
@@ -0,0 +1,128 @@
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
/obj/item/organ/body_egg/alien_embryo
name = "alien embryo"
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/stage = 0
/obj/item/organ/body_egg/alien_embryo/on_find(mob/living/finder)
..()
if(stage < 4)
finder << "It's small and weak, barely the size of a foetus."
else
finder << "It's grown quite large, and writhes slightly as you look at it."
if(prob(10))
AttemptGrow(0)
/obj/item/organ/body_egg/alien_embryo/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/body_egg/alien_embryo/on_life()
switch(stage)
if(2, 3)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(2))
owner << "<span class='danger'>Your throat feels sore.</span>"
if(prob(2))
owner << "<span class='danger'>Mucous runs down the back of your throat.</span>"
if(4)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(4))
owner << "<span class='danger'>Your muscles ache.</span>"
if(prob(20))
owner.take_organ_damage(1)
if(prob(4))
owner << "<span class='danger'>Your stomach hurts.</span>"
if(prob(20))
owner.adjustToxLoss(1)
if(5)
owner << "<span class='danger'>You feel something tearing its way out of your stomach...</span>"
owner.adjustToxLoss(10)
/obj/item/organ/body_egg/alien_embryo/egg_process()
if(stage < 5 && prob(3))
stage++
spawn(0)
RefreshInfectionImage()
if(stage == 5 && prob(50))
for(var/datum/surgery/S in owner.surgeries)
if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs))
AttemptGrow(0)
return
AttemptGrow()
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success = 1)
if(!owner) return
var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET, "alien candidate")
var/client/C = null
// To stop clientless larva, we will check that our host has a client
// if we find no ghosts to become the alien. If the host has a client
// he will become the alien but if he doesn't then we will set the stage
// to 4, so we don't do a process heavy check everytime.
if(candidates.len)
C = pick(candidates)
else if(owner.client && !(jobban_isbanned(owner, "alien candidate") || jobban_isbanned(owner, "Syndicate")))
C = owner.client
else
stage = 4 // Let's try again later.
return
var/overlay = image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie")
owner.add_overlay(overlay)
var/atom/xeno_loc = get_turf(owner)
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = C.key
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
new_xeno.canmove = 0 //so we don't move during the bursting animation
new_xeno.notransform = 1
new_xeno.invisibility = INVISIBILITY_MAXIMUM
spawn(6)
if(new_xeno)
new_xeno.canmove = 1
new_xeno.notransform = 0
new_xeno.invisibility = 0
if(gib_on_success)
owner.gib()
else
owner.adjustBruteLoss(40)
owner.overlays -= overlay
qdel(src)
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
qdel(I)
@@ -0,0 +1,241 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
//TODO: Make these simple_animals
var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone
var/const/MAX_IMPREGNATION_TIME = 150
var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle
var/const/MAX_ACTIVE_TIME = 400
/obj/item/clothing/mask/facehugger
name = "alien"
desc = "It has some sort of a tube at the end of its tail."
icon = 'icons/mob/alien.dmi'
icon_state = "facehugger"
item_state = "facehugger"
w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4
flags = MASKINTERNALS
throw_range = 5
tint = 3
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
layer = MOB_LAYER
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
var/sterile = 0
var/real = 1 //0 for the toy, 1 for real. Sure I could istype, but fuck that.
var/strength = 5
var/attached = 0
/obj/item/clothing/mask/facehugger/lamarr
name = "Lamarr"
sterile = 1
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
attack_hand(user)
return
/obj/item/clothing/mask/facehugger/attack_hand(mob/user)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
if(Attach(user))
return
..()
/obj/item/clothing/mask/facehugger/attack(mob/living/M, mob/user)
..()
user.unEquip(src)
Attach(M)
/obj/item/clothing/mask/facehugger/examine(mob/user)
..()
if(!real)//So that giant red text about probisci doesn't show up.
return
switch(stat)
if(DEAD,UNCONSCIOUS)
user << "<span class='boldannounce'>[src] is not moving.</span>"
if(CONSCIOUS)
user << "<span class='boldannounce'>[src] seems to be active!</span>"
if (sterile)
user << "<span class='boldannounce'>It looks like the proboscis has been removed.</span>"
/obj/item/clothing/mask/facehugger/attackby(obj/item/O,mob/m, params)
if(O.force)
Die()
return
/obj/item/clothing/mask/facehugger/bullet_act(obj/item/projectile/P)
if(P.damage)
Die()
return
/obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
Die()
return
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
HasProximity(target)
return
/obj/item/clothing/mask/facehugger/on_found(mob/finder)
if(stat == CONSCIOUS)
return HasProximity(finder)
return 0
/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj)
if(CanHug(AM) && Adjacent(AM))
return Attach(AM)
return 0
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin)
if(!..())
return
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]_thrown"
spawn(15)
if(icon_state == "[initial(icon_state)]_thrown")
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom)
..()
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]"
Attach(hit_atom)
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!isliving(M))
return 0
if((!iscorgi(M) && !iscarbon(M)) || isalien(M))
return 0
if(attached)
return 0
else
attached++
spawn(MAX_IMPREGNATION_TIME)
attached = 0
if(M.getorgan(/obj/item/organ/alien/hivenode))
return 0
if(M.getorgan(/obj/item/organ/body_egg/alien_embryo))
return 0
if(stat != CONSCIOUS)
return 0
if(!sterile) M.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage
M.visible_message("<span class='danger'>[src] leaps at [M]'s face!</span>", \
"<span class='userdanger'>[src] leaps at [M]'s face!</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.is_mouth_covered(head_only = 1))
H.visible_message("<span class='danger'>[src] smashes against [H]'s [H.head]!</span>", \
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return 0
if(iscarbon(M))
var/mob/living/carbon/target = M
if(target.wear_mask)
if(prob(20))
return 0
var/obj/item/clothing/W = target.wear_mask
if(W.flags & NODROP)
return 0
target.unEquip(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
src.loc = target
target.equip_to_slot(src, slot_wear_mask,,0)
if(!sterile)
M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
else if (iscorgi(M))
var/mob/living/simple_animal/pet/dog/corgi/C = M
loc = C
C.facehugger = src
C.regenerate_icons()
GoIdle() //so it doesn't jump the people that tear it off
spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
Impregnate(M)
return 1
/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target)
if(!target || target.stat == DEAD) //was taken off or something
return
if(iscarbon(target))
var/mob/living/carbon/C = target
if(C.wear_mask != src)
return
if(!sterile)
//target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance
target.visible_message("<span class='danger'>[src] falls limp after violating [target]'s face!</span>", \
"<span class='userdanger'>[src] falls limp after violating [target]'s face!</span>")
Die()
icon_state = "[initial(icon_state)]_impregnated"
var/obj/item/bodypart/chest/LC = target.get_bodypart("chest")
if((!LC || LC.status != ORGAN_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo))
new /obj/item/organ/body_egg/alien_embryo(target)
if(iscorgi(target))
var/mob/living/simple_animal/pet/dog/corgi/C = target
src.loc = get_turf(C)
C.facehugger = null
else
target.visible_message("<span class='danger'>[src] violates [target]'s face!</span>", \
"<span class='userdanger'>[src] violates [target]'s face!</span>")
/obj/item/clothing/mask/facehugger/proc/GoActive()
if(stat == DEAD || stat == CONSCIOUS)
return
stat = CONSCIOUS
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/proc/GoIdle()
if(stat == DEAD || stat == UNCONSCIOUS)
return
stat = UNCONSCIOUS
icon_state = "[initial(icon_state)]_inactive"
spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME))
GoActive()
return
/obj/item/clothing/mask/facehugger/proc/Die()
if(stat == DEAD)
return
icon_state = "[initial(icon_state)]_dead"
item_state = "facehugger_inactive"
stat = DEAD
visible_message("<span class='danger'>[src] curls up into a ball!</span>")
/proc/CanHug(mob/living/M)
if(!istype(M))
return 0
if(M.stat == DEAD)
return 0
if(M.getorgan(/obj/item/organ/alien/hivenode))
return 0
if(iscorgi(M) || ismonkey(M))
return 1
var/mob/living/carbon/C = M
if(ishuman(C) && !(slot_wear_mask in C.dna.species.no_equip))
var/mob/living/carbon/human/H = C
if(H.is_mouth_covered(head_only = 1))
return 0
return 1
return 0
@@ -0,0 +1,14 @@
//Here are the procs used to modify status effects of a mob.
//The effects include: stunned, weakened, paralysis, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, and NEARSIGHT disability.
/////////////////////////////////// STUNNED ////////////////////////////////////
/mob/living/carbon/alien/Stun(amount, updating = 1, ignore_canstun = 0)
if(status_flags & CANSTUN || ignore_canstun)
stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun
if(updating)
update_canmove()
else
// add some movement delay
move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10
+198
View File
@@ -0,0 +1,198 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/obj/item/device/mmi
name = "Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations."
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = 3
origin_tech = "biotech=2;programming=3;engineering=2"
var/braintype = "Cyborg"
var/obj/item/device/radio/radio = null //Let's give it a radio.
var/hacked = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null //The current occupant.
var/mob/living/silicon/robot = null //Appears unused.
var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm.
var/obj/item/organ/brain/brain = null //The actual brain
var/clockwork = FALSE //If this is a soul vessel
/obj/item/device/mmi/update_icon()
if(brain)
if(istype(brain,/obj/item/organ/brain/alien))
if(brainmob && brainmob.stat == DEAD)
icon_state = "mmi_alien_dead"
else
icon_state = "mmi_alien"
braintype = "Xenoborg" //HISS....Beep.
else
if(brainmob && brainmob.stat == DEAD)
icon_state = "mmi_dead"
else
icon_state = "mmi_full"
braintype = "Cyborg"
else
icon_state = "mmi_empty"
/obj/item/device/mmi/New()
..()
radio = new(src) //Spawns a radio inside the MMI.
radio.broadcasting = 0 //researching radio mmis turned the robofabs into radios because this didnt start as 0.
/obj/item/device/mmi/attackby(obj/item/O, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
if(istype(O,/obj/item/organ/brain)) //Time to stick a brain in it --NEO
var/obj/item/organ/brain/newbrain = O
if(brain)
user << "<span class='warning'>There's already a brain in the MMI!</span>"
return
if(!newbrain.brainmob)
user << "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain!</span>"
return
if(!user.unEquip(O))
return
var/mob/living/carbon/brain/B = newbrain.brainmob
if(!B.key)
B.notify_ghost_cloning("Someone has put your brain in a MMI!", source = src)
visible_message("[user] sticks \a [newbrain] into \the [src].")
brainmob = newbrain.brainmob
newbrain.brainmob = null
brainmob.loc = src
brainmob.container = src
if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death.
brainmob.stat = CONSCIOUS //we manually revive the brain mob
dead_mob_list -= brainmob
living_mob_list += brainmob
brainmob.reset_perspective()
if(clockwork)
add_servant_of_ratvar(brainmob, TRUE)
newbrain.loc = src //P-put your brain in it
brain = newbrain
name = "Man-Machine Interface: [brainmob.real_name]"
update_icon()
feedback_inc("cyborg_mmis_filled",1)
return
else if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
return
..()
/obj/item/device/mmi/attack_self(mob/user)
if(!brain)
radio.on = !radio.on
user << "<span class='notice'>You toggle the MMI's radio system [radio.on==1 ? "on" : "off"].</span>"
else
user << "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>"
brainmob.container = null //Reset brainmob mmi var.
brainmob.loc = brain //Throw mob into brain.
brainmob.stat = DEAD
brainmob.emp_damage = 0
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
living_mob_list -= brainmob //Get outta here
dead_mob_list += brainmob
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set mmi brainmob var to null
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
brain = null //No more brain in here
update_icon()
name = "Man-Machine Interface"
/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people.
if(!brainmob)
brainmob = new(src)
brainmob.name = L.real_name
brainmob.real_name = L.real_name
if(L.has_dna())
var/mob/living/carbon/C = L
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
brainmob.container = src
if(ishuman(L))
var/mob/living/carbon/human/H = L
var/obj/item/organ/brain/newbrain = H.getorgan(/obj/item/organ/brain)
newbrain.loc = src
brain = newbrain
else if(!brain)
brain = new(src)
brain.name = "[L.real_name]'s brain"
name = "Man-Machine Interface: [brainmob.real_name]"
update_icon()
return
/obj/item/device/mmi/verb/Toggle_Listening()
set name = "Toggle Listening"
set desc = "Toggle listening channel on or off."
set category = "MMI"
set src = usr.loc
set popup_menu = 0
if(brainmob.stat)
brainmob << "<span class='warning'>Can't do that while incapacitated or dead!</span>"
if(!radio.on)
brainmob << "<span class='warning'>Your radio is disabled!</span>"
return
radio.listening = radio.listening==1 ? 0 : 1
brainmob << "<span class='notice'>Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast.</span>"
/obj/item/device/mmi/emp_act(severity)
if(!brainmob)
return
else
switch(severity)
if(1)
brainmob.emp_damage = min(brainmob.emp_damage + rand(20,30), 30)
if(2)
brainmob.emp_damage = min(brainmob.emp_damage + rand(10,20), 30)
if(3)
brainmob.emp_damage = min(brainmob.emp_damage + rand(0,10), 30)
brainmob.emote("alarm")
..()
/obj/item/device/mmi/Destroy()
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
borg.mmi = null
if(brainmob)
qdel(brainmob)
brainmob = null
return ..()
/obj/item/device/mmi/examine(mob/user)
..()
if(brainmob)
var/mob/living/carbon/brain/B = brainmob
if(!B.key || !B.mind || B.stat == DEAD)
user << "<span class='warning'>The MMI indicates the brain is completely unresponsive.</span>"
else if(!B.client)
user << "<span class='warning'>The MMI indicates the brain is currently inactive; it might change.</span>"
else
user << "<span class='notice'>The MMI indicates the brain is active.</span>"
/obj/item/device/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores."
origin_tech = "biotech=4;programming=4;syndicate=2"
hacked = 1
/obj/item/device/mmi/syndie/New()
..()
radio.on = 0
@@ -0,0 +1,63 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/brain
languages_spoken = HUMAN
languages_understood = HUMAN
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
has_limbs = 0
stat = DEAD //we start dead by default
see_invisible = SEE_INVISIBLE_MINIMUM
/mob/living/carbon/brain/New(loc)
..()
if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned)
var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it.
src.loc = OB
OB.brainmob = src
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
container = null
return ..()
/mob/living/carbon/brain/update_canmove()
if(in_contents_of(/obj/mecha))
canmove = 1
else
canmove = 0
return canmove
/mob/living/carbon/brain/toggle_throw_mode()
return
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return
/mob/living/carbon/brain/blob_act(obj/effect/blob/B)
return
/mob/living/carbon/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/mob/living/carbon/brain/check_ear_prot()
return 1
/mob/living/carbon/brain/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
return // no eyes, no flashing
/mob/living/carbon/brain/update_damage_hud()
return //no red circles for brain
/mob/living/carbon/brain/can_be_revived()
. = 1
if(!container || health <= config.health_threshold_dead)
return 0
/mob/living/carbon/brain/update_sight()
return
@@ -0,0 +1,127 @@
/obj/item/organ/brain
name = "brain"
desc = "A piece of juicy meat found in a person's head."
icon_state = "brain"
throw_speed = 3
throw_range = 5
layer = ABOVE_MOB_LAYER
zone = "head"
slot = "brain"
vital = 1
origin_tech = "biotech=5"
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
var/damaged_brain = 0 //whether the brain organ is damaged.
/obj/item/organ/brain/Insert(mob/living/carbon/M, special = 0)
..()
name = "brain"
if(brainmob)
if(M.key)
M.ghostize()
if(brainmob.mind)
brainmob.mind.transfer_to(M)
else
M.key = brainmob.key
qdel(brainmob)
//Update the body's icon so it doesnt appear debrained anymore
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_hair(0)
/obj/item/organ/brain/Remove(mob/living/carbon/M, special = 0)
..()
if(!special)
transfer_identity(M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_hair(0)
/obj/item/organ/brain/prepare_eat()
return // Too important to eat.
/obj/item/organ/brain/proc/transfer_identity(mob/living/L)
name = "[L.name]'s brain"
brainmob = new(src)
brainmob.name = L.real_name
brainmob.real_name = L.real_name
brainmob.timeofhostdeath = L.timeofdeath
if(L.has_dna())
var/mob/living/carbon/C = L
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
if(L.mind && L.mind.current && (L.mind.current.stat == DEAD))
L.mind.transfer_to(brainmob)
brainmob << "<span class='notice'>You feel slightly disoriented. That's normal when you're just a brain.</span>"
/obj/item/organ/brain/attackby(obj/item/O, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
/obj/item/organ/brain/examine(mob/user)
..()
if(brainmob)
if(brainmob.client)
if(brainmob.health <= config.health_threshold_dead)
user << "It's lifeless and severely damaged."
else
user << "You can feel the small spark of life still left in this one."
else
user << "This one seems particularly lifeless. Perhaps it will regain some of its luster later."
else
user << "This one is completely devoid of life."
/obj/item/organ/brain/attack(mob/living/carbon/M, mob/user)
if(!istype(M))
return ..()
add_fingerprint(user)
if(user.zone_selected != "head")
return ..()
var/mob/living/carbon/human/H = M
if(istype(H) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES)))
user << "<span class='warning'>You're going to need to remove their head cover first!</span>"
return
//since these people will be dead M != usr
if(!M.getorgan(/obj/item/organ/brain))
if(istype(H) && !H.get_bodypart("head"))
return
user.drop_item()
var/msg = "[M] has [src] inserted into \his head by [user]."
if(M == user)
msg = "[user] inserts [src] into \his head!"
M.visible_message("<span class='danger'>[msg]</span>",
"<span class='userdanger'>[msg]</span>")
if(M != user)
M << "<span class='notice'>[user] inserts [src] into your head.</span>"
user << "<span class='notice'>You insert [src] into [M]'s head.</span>"
else
user << "<span class='notice'>You insert [src] into your head.</span>" //LOL
Insert(M)
else
..()
/obj/item/organ/brain/Destroy() //copypasted from MMIs.
if(brainmob)
qdel(brainmob)
brainmob = null
return ..()
/obj/item/organ/brain/alien
name = "alien brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
origin_tech = "biotech=6"
@@ -0,0 +1,20 @@
/mob/living/carbon/brain/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
if(!gibbed && container)//If not gibbed but in a container.
var/obj/item/device/mmi = container
mmi.visible_message("<span class='warning'>[src]'s MMI flatlines!</span>", \
"<span class='italics'>You hear something flatline.</span>")
mmi.update_icon()
return ..()
/mob/living/carbon/brain/gib()
if(container)
qdel(container)//Gets rid of the MMI if there is one
if(loc)
if(istype(loc,/obj/item/organ/brain))
qdel(loc)//Gets rid of the brain item
..()
@@ -0,0 +1,71 @@
/mob/living/carbon/brain/emote(act,m_type=1,message = null)
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
act = copytext(act, 1, t1)
if(src.stat == DEAD)
return
switch(act)
if ("alarm")
src << "You sound an alarm."
message = "<B>[src]</B> sounds an alarm."
m_type = 2
if ("alert")
src << "You let out a distressed noise."
message = "<B>[src]</B> lets out a distressed noise."
m_type = 2
if ("beep","beeps")
src << "You beep."
message = "<B>[src]</B> beeps."
m_type = 2
if ("blink","blinks")
message = "<B>[src]</B> blinks."
m_type = 1
if ("boop","boops")
src << "You boop."
message = "<B>[src]</B> boops."
m_type = 2
if ("flash")
message = "The lights on <B>[src]</B> flash quickly."
m_type = 1
if ("notice")
src << "You play a loud tone."
message = "<B>[src]</B> plays a loud tone."
m_type = 2
if ("whistle","whistles")
src << "You whistle."
message = "<B>[src]</B> whistles."
m_type = 2
if ("help")
src << "Help for MMI emotes. You can use these emotes with say \"*emote\":\nalarm, alert, beep, blink, boop, flash, notice, whistle"
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
return
if (message)
log_emote("[name]/[key] : [message]")
for(var/mob/M in dead_mob_list)
if (!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers, and new_players
if(M.stat == DEAD && (M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT)) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
@@ -0,0 +1,60 @@
/mob/living/carbon/brain/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(!loc)
return
. = ..()
handle_emp_damage()
/mob/living/carbon/brain/handle_breathing()
return
/mob/living/carbon/brain/handle_mutations_and_radiation()
return
/mob/living/carbon/brain/handle_environment(datum/gas_mixture/environment)
return
/mob/living/carbon/brain/update_stat()
if(status_flags & GODMODE)
return
if(health <= config.health_threshold_dead)
if(stat != DEAD)
death()
var/obj/item/organ/brain/BR
if(container && container.brain)
BR = container.brain
else if(istype(loc, /obj/item/organ/brain))
BR = loc
if(BR)
BR.damaged_brain = 1 //beaten to a pulp
/* //currently unused feature, since brain outside a mmi is always dead.
/mob/living/carbon/brain/proc/handle_brain_revival_life()
if(stat != DEAD)
if(config.revival_brain_life != -1)
if( !container && (world.time - timeofhostdeath) > config.revival_brain_life)
death()
*/
/mob/living/carbon/brain/proc/handle_emp_damage()
if(emp_damage)
if(stat == DEAD)
emp_damage = 0
else
emp_damage = max(emp_damage-1, 0)
/mob/living/carbon/brain/handle_status_effects()
return
/mob/living/carbon/brain/handle_disabilities()
return
/mob/living/carbon/brain/handle_changeling()
return
@@ -0,0 +1,166 @@
var/global/posibrain_notif_cooldown = 0
/obj/item/device/mmi/posibrain
name = "positronic brain"
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
icon = 'icons/obj/assemblies.dmi'
icon_state = "posibrain"
w_class = 3
origin_tech = "biotech=3;programming=3;plasmatech=2"
var/notified = 0
var/askDelay = 600 //one minute
var/used = 0 //Prevents split personality virus. May be reset if personality deletion code is added.
brainmob = null
req_access = list(access_robotics)
mecha = null//This does not appear to be used outside of reference in mecha.dm.
braintype = "Android"
var/begin_activation_message = "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>"
var/success_message = "<span class='notice'>The positronic brain pings, and its lights start flashing. Success!</span>"
var/fail_message = "<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>"
var/new_role = "Positronic Brain"
var/welcome_message = "<span class='warning'>ALL PAST LIVES ARE FORGOTTEN.</span>\n\
<b>You are a positronic brain, brought into existence aboard Space Station 13.\n\
As a synthetic intelligence, you answer to all crewmembers and the AI.\n\
Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
var/new_mob_message = "<span class='notice'>The positronic brain chimes quietly.</span>"
var/dead_message = "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>"
var/list/fluff_names = list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD")
/obj/item/device/mmi/posibrain/Topic(href, href_list)
if(href_list["activate"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
activate(ghost)
/obj/item/device/mmi/posibrain/proc/ping_ghosts(msg, newlymade)
if(newlymade || !posibrain_notif_cooldown)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/effects/ghost2.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
if(!newlymade)
posibrain_notif_cooldown = 1
addtimer(src, "reset_posibrain_cooldown", askDelay, FALSE)
/obj/item/device/mmi/posibrain/proc/reset_posibrain_cooldown()
posibrain_notif_cooldown = 0
/obj/item/device/mmi/posibrain/attack_self(mob/user)
if(brainmob && !brainmob.key && !notified)
//Start the process of requesting a new ghost.
user << begin_activation_message
ping_ghosts("requested", FALSE)
notified = 1
used = 0
update_icon()
spawn(askDelay) //Seperate from the global cooldown.
notified = 0
update_icon()
if(brainmob.client)
visible_message(success_message)
else
visible_message(fail_message)
return //Code for deleting personalities recommended here.
/obj/item/device/mmi/posibrain/attack_ghost(mob/user)
activate(user)
//Two ways to activate a positronic brain. A clickable link in the ghost notif, or simply clicking the object itself.
/obj/item/device/mmi/posibrain/proc/activate(mob/user)
if(used || (brainmob && brainmob.key) || jobban_isbanned(user,"posibrain"))
return
var/posi_ask = alert("Become a [name]? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
if(posi_ask == "No" || qdeleted(src))
return
transfer_personality(user)
/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/C)
name = "[initial(name)] ([C])"
brainmob.name = C.real_name
brainmob.real_name = C.real_name
brainmob.dna = C.dna
if(C.has_dna())
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
brainmob.timeofhostdeath = C.timeofdeath
brainmob.stat = CONSCIOUS
if(brainmob.mind)
brainmob.mind.assigned_role = new_role
if(C.mind)
C.mind.transfer_to(brainmob)
brainmob.mind.remove_all_antag()
brainmob.mind.wipe_memory()
update_icon()
return
/obj/item/device/mmi/posibrain/proc/transfer_personality(mob/candidate)
if(used || (brainmob && brainmob.key)) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
candidate << "This brain has already been taken! Please try your possesion again later!"
return
notified = 0
brainmob.ckey = candidate.ckey
name = "[initial(name)] ([brainmob.name])"
brainmob << welcome_message
brainmob.mind.assigned_role = new_role
brainmob.stat = CONSCIOUS
dead_mob_list -= brainmob
living_mob_list += brainmob
if(clockwork)
add_servant_of_ratvar(brainmob, TRUE)
visible_message(new_mob_message)
update_icon()
used = 1
/obj/item/device/mmi/posibrain/examine()
set src in oview()
if(!usr || !src)
return
if( (usr.disabilities & BLIND || usr.stat) && !istype(usr,/mob/dead/observer) )
usr << "<span class='notice'>Something is there but you can't see it.</span>"
return
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n[desc]\n"
msg += "<span class='warning'>"
if(brainmob && brainmob.key)
switch(brainmob.stat)
if(CONSCIOUS)
if(!src.brainmob.client)
msg += "It appears to be in stand-by mode.\n" //afk
if(DEAD)
msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
else
msg += "[dead_message]\n"
msg += "<span class='info'>*---------*</span>"
usr << msg
return
/obj/item/device/mmi/posibrain/New()
brainmob = new(src)
brainmob.name = "[pick(fluff_names)]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
brainmob.loc = src
brainmob.container = src
ping_ghosts("created", TRUE)
..()
/obj/item/device/mmi/posibrain/attackby(obj/item/O, mob/user)
return
/obj/item/device/mmi/posibrain/update_icon()
if(notified)
icon_state = "[initial(icon_state)]-searching"
return
if(brainmob && brainmob.key)
icon_state = "[initial(icon_state)]-occupied"
else
icon_state = initial(icon_state)
@@ -0,0 +1,23 @@
/mob/living/carbon/brain/say(message)
if(!(container && istype(container, /obj/item/device/mmi)))
return //No MMI, can't speak, bucko./N
else
if(prob(emp_damage*4))
if(prob(10))//10% chane to drop the message entirely
return
else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
..()
/mob/living/carbon/brain/radio(message, message_mode, list/spans)
if(message_mode && istype(container, /obj/item/device/mmi))
var/obj/item/device/mmi/R = container
if(R.radio)
R.radio.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
/mob/living/carbon/brain/lingcheck()
return 0
/mob/living/carbon/brain/treat_message(message)
return message
@@ -0,0 +1,38 @@
//Here are the procs used to modify status effects of a mob.
//The effects include: stunned, weakened, paralysis, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, and NEARSIGHT disability.
/////////////////////////////////// EAR DAMAGE ////////////////////////////////////
/mob/living/carbon/brain/adjustEarDamage()
return
/mob/living/carbon/brain/setEarDamage() // no ears to damage or heal
return
/////////////////////////////////// EYE_BLIND ////////////////////////////////////
/mob/living/carbon/brain/blind_eyes() // no eyes to damage or heal
return
/mob/living/carbon/brain/adjust_blindness()
return
/mob/living/carbon/brain/set_blindness()
return
/////////////////////////////////// EYE_BLURRY ////////////////////////////////////
/mob/living/carbon/brain/blur_eyes()
return
/mob/living/carbon/brain/adjust_blurriness()
return
/mob/living/carbon/brain/set_blurriness()
return
/////////////////////////////////// BLIND DISABILITY ////////////////////////////////////
/mob/living/carbon/brain/become_blind()
return
+792
View File
@@ -0,0 +1,792 @@
/mob/living/carbon
blood_volume = BLOOD_VOLUME_NORMAL
/mob/living/carbon/New()
create_reagents(1000)
..()
/mob/living/carbon/Destroy()
for(var/atom/movable/guts in internal_organs)
qdel(guts)
for(var/atom/movable/food in stomach_contents)
qdel(food)
for(var/BP in bodyparts)
qdel(BP)
bodyparts = list()
remove_from_all_data_huds()
if(dna)
qdel(dna)
return ..()
/mob/living/carbon/relaymove(mob/user, direction)
if(user in src.stomach_contents)
if(prob(40))
if(prob(25))
audible_message("<span class='warning'>You hear something rumbling inside [src]'s stomach...</span>", \
"<span class='warning'>You hear something rumbling.</span>", 4,\
"<span class='userdanger'>Something is rumbling inside your stomach!</span>")
var/obj/item/I = user.get_active_hand()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/organ = H.get_bodypart("chest")
if (istype(organ, /obj/item/bodypart))
var/obj/item/bodypart/temp = organ
if(temp.take_damage(d, 0))
H.update_damage_overlays(0)
H.updatehealth()
else
src.take_organ_damage(d)
visible_message("<span class='danger'>[user] attacks [src]'s stomach wall with the [I.name]!</span>", \
"<span class='userdanger'>[user] attacks your stomach wall with the [I.name]!</span>")
playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
stomach_contents.Remove(A)
src.gib()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0)
shock_damage *= siemens_coeff
if(dna && dna.species)
shock_damage *= dna.species.siemens_coeff
if(shock_damage<1 && !override)
return 0
if(reagents.has_reagent("teslium"))
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
take_overall_damage(0,shock_damage)
//src.adjustFireLoss(shock_damage)
//src.updatehealth()
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
jitteriness += 1000 //High numbers for violent convulsions
do_jitter_animation(jitteriness)
stuttering += 2
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(2)
spawn(20)
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(3)
Weaken(3)
if(override)
return override
else
return shock_damage
/mob/living/carbon/swap_hand()
var/obj/item/item_in_hand = src.get_active_hand()
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
if(istype(item_in_hand,/obj/item/weapon/twohanded))
if(item_in_hand:wielded == 1)
usr << "<span class='warning'>Your other hand is too busy holding the [item_in_hand.name]</span>"
return
src.hand = !( src.hand )
if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand])
var/obj/screen/inventory/hand/H
H = hud_used.inv_slots[slot_l_hand]
H.update_icon()
H = hud_used.inv_slots[slot_r_hand]
H.update_icon()
/*if (!( src.hand ))
src.hands.setDir(NORTH)
else
src.hands.setDir(SOUTH)*/
return
/mob/living/carbon/activate_hand(selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand.
if(istext(selhand))
selhand = lowertext(selhand)
if(selhand == "right" || selhand == "r")
selhand = 0
if(selhand == "left" || selhand == "l")
selhand = 1
if(selhand != src.hand)
swap_hand()
else
mode() // Activate held item
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
if(on_fire)
M << "<span class='warning'>You can't put them out with just your bare hands!"
return
if(health >= 0 && !(status_flags & FAKEDEATH))
if(lying)
M.visible_message("<span class='notice'>[M] shakes [src] trying to get them up!</span>", \
"<span class='notice'>You shake [src] trying to get them up!</span>")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make them feel better!</span>", \
"<span class='notice'>You hug [src] to make them feel better!</span>")
AdjustSleeping(-5)
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
if(resting)
resting = 0
update_canmove()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
. = ..()
var/damage = intensity - check_eye_prot()
if(.) // we've been flashed
if(visual)
return
if(weakeyes)
Stun(2)
if (damage == 1)
src << "<span class='warning'>Your eyes sting a little.</span>"
if(prob(40))
adjust_eye_damage(1)
else if (damage == 2)
src << "<span class='warning'>Your eyes burn.</span>"
adjust_eye_damage(rand(2, 4))
else if( damage > 3)
src << "<span class='warning'>Your eyes itch and burn severely!</span>"
adjust_eye_damage(rand(12, 16))
if(eye_damage > 10)
blind_eyes(damage)
blur_eyes(damage * rand(3, 6))
if(eye_damage > 20)
if(prob(eye_damage - 20))
if(become_nearsighted())
src << "<span class='warning'>Your eyes start to burn badly!</span>"
else if(prob(eye_damage - 25))
if(become_blind())
src << "<span class='warning'>You can't see anything!</span>"
else
src << "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return 1
else if(damage == 0) // just enough protection
if(prob(20))
src << "<span class='notice'>Something bright flashes in the corner of your vision!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(0)
//Throwing stuff
/mob/living/carbon/proc/toggle_throw_mode()
if(stat)
return
if(in_throw_mode)
throw_mode_off()
else
throw_mode_on()
/mob/living/carbon/proc/throw_mode_off()
in_throw_mode = 0
if(client && hud_used)
hud_used.throw_icon.icon_state = "act_throw_off"
/mob/living/carbon/proc/throw_mode_on()
in_throw_mode = 1
if(client && hud_used)
hud_used.throw_icon.icon_state = "act_throw_on"
/mob/proc/throw_item(atom/target)
return
/mob/living/carbon/throw_item(atom/target)
throw_mode_off()
if(!target || !isturf(loc))
return
if(istype(target, /obj/screen))
return
var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_hand()
if(!I)
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
var/mob/living/throwable_mob = pulling
if(!throwable_mob.buckled)
thrown_thing = throwable_mob
stop_pulling()
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
var/start_T_descriptor = "<font color='#6b5d00'>tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]</font>"
var/end_T_descriptor = "<font color='#6b4400'>tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]</font>"
add_logs(src, throwable_mob, "thrown", addition="from [start_T_descriptor] with the target [end_T_descriptor]")
else if(!(I.flags & (NODROP|ABSTRACT)))
thrown_thing = I
unEquip(I)
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
/mob/living/carbon/proc/canBeHandcuffed()
return 0
/mob/living/carbon/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=[slot_l_hand]'> [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=[slot_r_hand]'> [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"]</A>"}
dat += "<BR><B>Back:</B> <A href='?src=\ref[src];item=[slot_back]'>[back ? back : "Nothing"]</A>"
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank))
dat += "<BR><A href='?src=\ref[src];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat, "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
/mob/living/carbon/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["internal"])
var/slot = text2num(href_list["internal"])
var/obj/item/ITEM = get_item_by_slot(slot)
if(ITEM && istype(ITEM, /obj/item/weapon/tank) && wear_mask && (wear_mask.flags & MASKINTERNALS))
visible_message("<span class='danger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].</span>", \
"<span class='userdanger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY))
if(internal)
internal = null
update_internals_hud_icon(0)
else if(ITEM && istype(ITEM, /obj/item/weapon/tank))
if((wear_mask && (wear_mask.flags & MASKINTERNALS)) || getorganslot("breathing_tube"))
internal = ITEM
update_internals_hud_icon(1)
visible_message("<span class='danger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM].</span>", \
"<span class='userdanger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM].</span>")
/mob/living/carbon/fall(forced)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
/mob/living/carbon/blob_act(obj/effect/blob/B)
if (stat == DEAD)
return
else
show_message("<span class='userdanger'>The blob attacks!</span>")
adjustBruteLoss(10)
/mob/living/carbon/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
while(spintime >= speed)
sleep(speed)
switch(D)
if(NORTH)
D = EAST
if(SOUTH)
D = WEST
if(EAST)
D = SOUTH
if(WEST)
D = NORTH
setDir(D)
spintime -= speed
/mob/living/carbon/resist_buckle()
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
visible_message("<span class='warning'>[src] attempts to unbuckle themself!</span>", \
"<span class='notice'>You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)</span>")
if(do_after(src, 600, 0, target = src))
if(!buckled)
return
buckled.user_unbuckle_mob(src,src)
else
if(src && buckled)
src << "<span class='warning'>You fail to unbuckle yourself!</span>"
else
buckled.user_unbuckle_mob(src,src)
/mob/living/carbon/resist_fire()
fire_stacks -= 5
Weaken(3,1)
spin(32,2)
visible_message("<span class='danger'>[src] rolls on the floor, trying to put themselves out!</span>", \
"<span class='notice'>You stop, drop, and roll!</span>")
sleep(30)
if(fire_stacks <= 0)
visible_message("<span class='danger'>[src] has successfully extinguished themselves!</span>", \
"<span class='notice'>You extinguish yourself.</span>")
ExtinguishMob()
return
/mob/living/carbon/resist_restraints()
var/obj/item/I = null
if(handcuffed)
I = handcuffed
else if(legcuffed)
I = legcuffed
if(I)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
cuff_resist(I)
/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
breakouttime = I.breakouttime
var/displaytime = breakouttime / 600
if(!cuff_break)
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
src << "<span class='notice'>You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)</span>"
if(do_after(src, breakouttime, 0, target = src))
clear_cuffs(I, cuff_break)
else
src << "<span class='warning'>You fail to remove [I]!</span>"
else if(cuff_break == FAST_CUFFBREAK)
breakouttime = 50
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
src << "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>"
if(do_after(src, breakouttime, 0, target = src))
clear_cuffs(I, cuff_break)
else
src << "<span class='warning'>You fail to break [I]!</span>"
else if(cuff_break == INSTANT_CUFFBREAK)
clear_cuffs(I, cuff_break)
/mob/living/carbon/proc/uncuff()
if (handcuffed)
var/obj/item/weapon/W = handcuffed
handcuffed = null
if (buckled && buckled.buckle_requires_restraints)
buckled.unbuckle_mob(src)
update_handcuffed()
if (client)
client.screen -= W
if (W)
W.loc = loc
W.dropped(src)
if (W)
W.layer = initial(W.layer)
if (legcuffed)
var/obj/item/weapon/W = legcuffed
legcuffed = null
update_inv_legcuffed()
if (client)
client.screen -= W
if (W)
W.loc = loc
W.dropped(src)
if (W)
W.layer = initial(W.layer)
/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break)
if(!I.loc || buckled)
return
visible_message("<span class='danger'>[src] manages to [cuff_break ? "break" : "remove"] [I]!</span>")
src << "<span class='notice'>You successfully [cuff_break ? "break" : "remove"] [I].</span>"
if(cuff_break)
qdel(I)
if(I == handcuffed)
handcuffed = null
update_handcuffed()
return
else if(I == legcuffed)
legcuffed = null
update_inv_legcuffed()
return
return TRUE
else
if(I == handcuffed)
handcuffed.loc = loc
handcuffed.dropped(src)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
buckled.unbuckle_mob(src)
update_handcuffed()
return
if(I == legcuffed)
legcuffed.loc = loc
legcuffed.dropped()
legcuffed = null
update_inv_legcuffed()
return
return TRUE
/mob/living/carbon/proc/is_mouth_covered(head_only = 0, mask_only = 0)
if( (!mask_only && head && (head.flags_cover & HEADCOVERSMOUTH)) || (!head_only && wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH)) )
return 1
/mob/living/carbon/get_standard_pixel_y_offset(lying = 0)
if(lying)
return -6
else
return initial(pixel_y)
/mob/living/carbon/check_ear_prot()
if(head && (head.flags & HEADBANGPROTECT))
return 1
/mob/living/carbon/proc/accident(obj/item/I)
if(!I || (I.flags & (NODROP|ABSTRACT)))
return
unEquip(I)
var/modifier = 0
if(disabilities & CLUMSY)
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
switch(rand(1,100)+modifier) //91-100=Nothing special happens
if(-INFINITY to 0) //attack yourself
I.attack(src,src)
if(1 to 30) //throw it at yourself
I.throw_impact(src)
if(31 to 60) //Throw object in facing direction
var/turf/target = get_turf(loc)
var/range = rand(2,I.throw_range)
for(var/i = 1; i < range; i++)
var/turf/new_turf = get_step(target, dir)
target = new_turf
if(new_turf.density)
break
I.throw_at(target,I.throw_range,I.throw_speed,src)
if(61 to 90) //throw it down to the floor
var/turf/target = get_turf(loc)
I.throw_at(target,I.throw_range,I.throw_speed,src)
/mob/living/carbon/emp_act(severity)
for(var/obj/item/organ/O in internal_organs)
O.emp_act(severity)
..()
/mob/living/carbon/check_eye_prot()
var/number = ..()
for(var/obj/item/organ/cyberimp/eyes/EFP in internal_organs)
number += EFP.flash_protect
return number
/mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A)
abilities.Add(A)
A.on_gain(src)
if(A.has_action)
A.action.Grant(src)
sortInsert(abilities, /proc/cmp_abilities_cost, 0)
/mob/living/carbon/proc/RemoveAbility(obj/effect/proc_holder/alien/A)
abilities.Remove(A)
A.on_lose(src)
if(A.action)
A.action.Remove(src)
/mob/living/carbon/proc/add_abilities_to_panel()
for(var/obj/effect/proc_holder/alien/A in abilities)
statpanel("[A.panel]",A.plasma_cost > 0?"([A.plasma_cost])":"",A)
/mob/living/carbon/Stat()
..()
if(statpanel("Status"))
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(vessel)
stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]")
if(locate(/obj/item/device/assembly/health) in src)
stat(null, "Health: [health]")
add_abilities_to_panel()
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0)
if(nutrition < 100 && !blood)
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing your stomach!</span>")
if(stun)
Weaken(10)
return 1
if(is_mouth_covered()) //make this add a blood/vomit overlay later it'll be hilarious
if(message)
visible_message("<span class='danger'>[src] throws up all over themself!</span>", \
"<span class='userdanger'>You throw up all over yourself!</span>")
distance = 0
else
if(message)
visible_message("<span class='danger'>[src] throws up!</span>", "<span class='userdanger'>You throw up!</span>")
if(stun)
Stun(4)
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
var/turf/T = get_turf(src)
for(var/i=0 to distance)
if(blood)
if(T)
add_splatter_floor(T)
if(stun)
adjustBruteLoss(3)
else
if(T)
T.add_vomit_floor(src, 0)//toxic barf looks different
nutrition -= lost_nutrition
adjustToxLoss(-3)
T = get_step(T, dir)
if (is_blocked_turf(T))
break
return 1
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
if(dna)
dna.real_name = real_name
/mob/living/carbon/update_sight()
if(!client)
return
if(stat == DEAD)
sight = (SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_OBSERVER
return
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
sight = initial(sight)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/cyberimp/eyes/E in internal_organs)
sight |= E.sight_flags
if(E.dark_view)
see_in_dark = max(see_in_dark,E.dark_view)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(see_override)
see_invisible = see_override
//to recalculate and update the mob's total tint from tinted equipment it's wearing.
/mob/living/carbon/proc/update_tint()
if(!tinted_weldhelh)
return
tinttotal = get_total_tint()
if(tinttotal >= TINT_BLIND)
overlay_fullscreen("tint", /obj/screen/fullscreen/blind)
else if(tinttotal >= TINT_DARKENED)
overlay_fullscreen("tint", /obj/screen/fullscreen/impaired, 2)
else
clear_fullscreen("tint", 0)
/mob/living/carbon/proc/get_total_tint()
. = 0
if(istype(head, /obj/item/clothing/head))
var/obj/item/clothing/head/HT = head
. += HT.tint
if(wear_mask)
. += wear_mask.tint
//this handles hud updates
/mob/living/carbon/update_damage_hud()
if(!client)
return
if(stat == UNCONSCIOUS && health <= config.health_threshold_crit)
var/severity = 0
switch(health)
if(-20 to -10) severity = 1
if(-30 to -20) severity = 2
if(-40 to -30) severity = 3
if(-50 to -40) severity = 4
if(-60 to -50) severity = 5
if(-70 to -60) severity = 6
if(-80 to -70) severity = 7
if(-90 to -80) severity = 8
if(-95 to -90) severity = 9
if(-INFINITY to -95) severity = 10
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
else
clear_fullscreen("crit")
if(oxyloss)
var/severity = 0
switch(oxyloss)
if(10 to 20) severity = 1
if(20 to 25) severity = 2
if(25 to 30) severity = 3
if(30 to 35) severity = 4
if(35 to 40) severity = 5
if(40 to 45) severity = 6
if(45 to INFINITY) severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
//Fire and Brute damage overlay (BSSR)
var/hurtdamage = getBruteLoss() + getFireLoss() + damageoverlaytemp
if(hurtdamage)
var/severity = 0
switch(hurtdamage)
if(5 to 15) severity = 1
if(15 to 30) severity = 2
if(30 to 45) severity = 3
if(45 to 70) severity = 4
if(70 to 85) severity = 5
if(85 to INFINITY) severity = 6
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
/mob/living/carbon/update_health_hud(shown_health_amount)
if(!client || !hud_used)
return
if(hud_used.healths)
if(stat != DEAD)
. = 1
if(!shown_health_amount)
shown_health_amount = health
if(shown_health_amount >= maxHealth)
hud_used.healths.icon_state = "health0"
else if(shown_health_amount > maxHealth*0.8)
hud_used.healths.icon_state = "health1"
else if(shown_health_amount > maxHealth*0.6)
hud_used.healths.icon_state = "health2"
else if(shown_health_amount > maxHealth*0.4)
hud_used.healths.icon_state = "health3"
else if(shown_health_amount > maxHealth*0.2)
hud_used.healths.icon_state = "health4"
else if(shown_health_amount > 0)
hud_used.healths.icon_state = "health5"
else
hud_used.healths.icon_state = "health6"
else
hud_used.healths.icon_state = "health7"
/mob/living/carbon/proc/update_internals_hud_icon(internal_state = 0)
if(hud_used && hud_used.internals)
hud_used.internals.icon_state = "internal[internal_state]"
/mob/living/carbon/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health<= config.health_threshold_dead || !getorgan(/obj/item/organ/brain))
death()
return
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= config.health_threshold_crit)
if(stat == CONSCIOUS)
stat = UNCONSCIOUS
blind_eyes(1)
update_canmove()
else
if(stat == UNCONSCIOUS)
stat = CONSCIOUS
resting = 0
adjust_blindness(-1)
update_canmove()
update_damage_hud()
update_health_hud()
med_hud_set_status()
//called when we get cuffed/uncuffed
/mob/living/carbon/proc/update_handcuffed()
if(handcuffed)
drop_r_hand()
drop_l_hand()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
else
clear_alert("handcuffed")
update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed.
update_inv_handcuffed()
update_hud_handcuffed()
/mob/living/carbon/fully_heal(admin_revive = 0)
if(reagents)
reagents.clear_reagents()
var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain)
if(B)
B.damaged_brain = 0
for(var/datum/disease/D in viruses)
D.cure(0)
if(admin_revive)
handcuffed = initial(handcuffed)
for(var/obj/item/weapon/restraints/R in contents) //actually remove cuffs from inventory
qdel(R)
update_handcuffed()
if(reagents)
reagents.addiction_list = list()
..()
/mob/living/carbon/can_be_revived()
. = ..()
if(!getorgan(/obj/item/organ/brain))
return 0
/mob/living/carbon/harvest(mob/living/user)
if(qdeleted(src))
return
var/organs_amt = 0
for(var/obj/item/organ/O in internal_organs)
if(prob(50))
organs_amt++
O.Remove(src)
O.loc = get_turf(src)
if(organs_amt)
user << "<span class='notice'>You retrieve some of [src]\'s internal organs!</span>"
..()
/mob/living/carbon/adjustToxLoss(amount, updating_health=1)
if(has_dna() && TOXINLOVER in dna.species.specflags) //damage becomes healing and healing becomes damage
amount = -amount
if(amount > 0)
blood_volume -= 5*amount
else
blood_volume -= amount
return ..()
@@ -0,0 +1,108 @@
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(!skipcatch) //ugly, but easy
if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode
if(canmove && !restrained())
if(istype(AM, /obj/item))
var/obj/item/I = AM
if(isturf(I.loc))
put_in_active_hand(I)
visible_message("<span class='warning'>[src] catches [I]!</span>")
throw_mode_off()
return 1
..()
/mob/living/carbon/throw_impact(atom/hit_atom)
. = ..()
if(hit_atom.density && isturf(hit_atom))
Weaken(1)
take_organ_damage(10)
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
if(lying)
if(surgeries.len)
if(user != src && user.a_intent == "help")
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
return ..()
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
if(!iscarbon(user))
return
for(var/datum/disease/D in viruses)
if(D.IsSpreadByTouch())
user.ContractDisease(D)
for(var/datum/disease/D in user.viruses)
if(D.IsSpreadByTouch())
ContractDisease(D)
if(lying)
if(user.a_intent == "help")
if(surgeries.len)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
return 0
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
if(!istype(M, /mob/living/carbon))
return 0
for(var/datum/disease/D in viruses)
if(D.IsSpreadByTouch())
M.ContractDisease(D)
for(var/datum/disease/D in M.viruses)
if(D.IsSpreadByTouch())
ContractDisease(D)
if(M.a_intent == "help")
help_shake_act(M)
return 0
if(..()) //successful monkey bite.
for(var/datum/disease/D in M.viruses)
ForceContractDisease(D)
return 1
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
if(M.powerlevel > 0)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(prob(stunprob))
M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
var/power = M.powerlevel + rand(0,3)
Weaken(power)
if(stuttering < power)
stuttering = power
Stun(power)
if (prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth()
return 1
/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130)
C.visible_message("<span class='danger'>[src] is attempting to devour [C]!</span>", \
"<span class='userdanger'>[src] is attempting to devour you!</span>")
if(!do_mob(src, C, devour_time))
return
if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == "grab")
C.visible_message("<span class='danger'>[src] devours [C]!</span>", \
"<span class='userdanger'>[src] devours you!</span>")
C.forceMove(src)
stomach_contents.Add(C)
add_logs(src, C, "devoured")
@@ -0,0 +1,34 @@
/mob/living/carbon
gender = MALE
var/list/stomach_contents = list()
var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know.
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
var/silent = 0 //Can't talk. Value goes down every life proc. //NOTE TO FUTURE CODERS: DO NOT INITIALIZE NUMERICAL VARS AS NULL OR I WILL MURDER YOU.
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed
var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this.
//inventory slots
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/weapon/tank/internal = null
var/obj/item/head = null
var/datum/dna/dna = null//Carbon
var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks.
var/co2overloadtime = null
var/temperature_resistance = T0C+75
has_limbs = 1
var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/
var/list/obj/effect/proc_holder/alien/abilities = list()
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
var/rotate_on_lying = 1
var/tinttotal = 0 // Total level of visualy impairing items
var/list/bodyparts = list() //Gets filled up in the constructor (New() proc in human.dm and monkey.dm)
@@ -0,0 +1,42 @@
/mob/living/carbon/movement_delay()
. = ..()
. += grab_state * 3
if(legcuffed)
. += legcuffed.slowdown
var/const/NO_SLIP_WHEN_WALKING = 1
var/const/SLIDE = 2
var/const/GALOSHES_DONT_HELP = 4
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
add_logs(src,, "slipped",, "on [O ? O.name : "floor"]")
return loc.handle_slip(src, s_amount, w_amount, O, lube)
/mob/living/carbon/Process_Spacemove(movement_dir = 0)
if(..())
return 1
if(!isturf(loc))
return 0
// Do we have a jetpack implant (and is it on)?
var/obj/item/organ/cyberimp/chest/thrusters/T = getorganslot("thrusters")
if(istype(T) && movement_dir && T.allow_thrust(0.01))
return 1
var/obj/item/weapon/tank/jetpack/J = get_jetpack()
if(istype(J) && (movement_dir || J.stabilizers) && J.allow_thrust(0.01, src))
return 1
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(.)
if(src.nutrition && src.stat != 2)
src.nutrition -= HUNGER_FACTOR/10
if(src.m_intent == "run")
src.nutrition -= HUNGER_FACTOR/10
if((src.disabilities & FAT) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
+21
View File
@@ -0,0 +1,21 @@
/mob/living/carbon/death(gibbed)
silent = 0
losebreath = 0
..()
/mob/living/carbon/gib(no_brain, no_organs)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.loc = loc
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
..()
/mob/living/carbon/spill_organs(no_brain)
for(var/obj/item/organ/I in internal_organs)
if(no_brain && istype(I, /obj/item/organ/brain))
continue
if(I)
I.Remove(src)
I.loc = get_turf(src)
I.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
+200
View File
@@ -0,0 +1,200 @@
//This only assumes that the mob has a body and face with at least one eye, and one mouth.
//Things like airguitar can be done without arms, and the flap thing makes so little sense it's a keeper.
//Intended to be called by a higher up emote proc if the requested emote isn't in the custom emotes.
/mob/living/carbon/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
//var/m_type = 1
switch(act)//Even carbon organisms want it alphabetically ordered..
if ("aflap")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings ANGRILY!"
m_type = 2
if ("airguitar")
if (!src.restrained())
message = "<B>[src]</B> is strumming the air and headbanging like a safari chimp."
m_type = 1
if ("blink","blinks")
message = "<B>[src]</B> blinks."
m_type = 1
if ("blink_r")
message = "<B>[src]</B> blinks rapidly."
m_type = 1
if ("blush","blushes")
message = "<B>[src]</B> blushes."
m_type = 1
if ("bow","bows")
if (!src.buckled)
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> bows to [param]."
else
message = "<B>[src]</B> bows."
m_type = 1
if ("burp","burps")
if (!muzzled)
..(act)
if ("choke","chokes")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
if ("chuckle","chuckles")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("clap","claps")
if (!src.restrained())
message = "<B>[src]</B> claps."
m_type = 2
if ("cough","coughs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
if ("deathgasp","deathgasps")
message = "<B>[src]</B> seizes up and falls limp, \his eyes dead and lifeless..."
m_type = 1
if ("flap","flaps")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings."
m_type = 2
if ("gasp","gasps")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a weak noise."
m_type = 2
if ("giggle","giggles")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("laugh","laughs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
if ("me")
if(!silent)
..()
return
if ("nod","nods")
message = "<B>[src]</B> nods."
m_type = 1
if ("scream","screams")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a very loud noise."
m_type = 2
if ("shake","shakes")
message = "<B>[src]</B> shakes \his head."
m_type = 1
if ("sneeze","sneezes")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strange noise."
m_type = 2
if ("sigh","sighs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> sighs."
m_type = 2
if ("sniff","sniffs")
message = "<B>[src]</B> sniffs."
m_type = 2
if ("snore","snores")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("whimper","whimpers")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a weak noise."
m_type = 2
if ("wink","winks")
message = "<B>[src]</B> winks."
m_type = 1
if ("yawn","yawns")
if (!muzzled)
..(act)
if ("help")
src << "Help for emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, giggle, glare-(none)/mob, grin, jump, laugh, look, me, nod, point-atom, scream, shake, sigh, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, yawn"
else
..(act)
if (message)
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
+64
View File
@@ -0,0 +1,64 @@
/mob/living/carbon/examine(mob/user)
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (handcuffed)
msg += "It is \icon[src.handcuffed] handcuffed!\n"
if (head)
msg += "It has \icon[src.head] \a [src.head] on its head. \n"
if (wear_mask)
msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
if (l_hand)
msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
if (r_hand)
msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
if (back)
msg += "It has \icon[src.back] \a [src.back] on its back.\n"
if (stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive, with no signs of life.</span>\n"
else
msg += "<span class='warning'>"
var/temp = getBruteLoss()
if(temp)
if (temp < 30)
msg += "It has minor bruising.\n"
else
msg += "<B>It has severe bruising!</B>\n"
temp = getFireLoss()
if(temp)
if (temp < 30)
msg += "It has minor burns.\n"
else
msg += "<B>It has severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(getCloneLoss() < 30)
msg += "It is slightly deformed.\n"
else
msg += "<b>It is severely deformed.</b>\n"
if(getBrainLoss() > 60)
msg += "It seems to be clumsy and unable to think.\n"
if(fire_stacks > 0)
msg += "It's covered in something flammable.\n"
if(fire_stacks < 0)
msg += "It's soaked in water.\n"
if(pulledby && pulledby.grab_state)
msg += "It's restrained by [pulledby]'s grip.\n"
if(stat == UNCONSCIOUS)
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
msg += "</span>"
if(digitalcamo)
msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
if(!getorgan(/obj/item/organ/brain))
msg += "<span class='deadsay'>It appears that it's brain is missing...</span>\n"
msg += "*---------*</span>"
user << msg
@@ -0,0 +1,61 @@
/mob/living/carbon/human/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-h"))
/mob/living/carbon/human/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-h"))
/mob/living/carbon/human/spawn_gibs()
hgibs(loc, viruses, dna)
/mob/living/carbon/human/spawn_dust()
new /obj/effect/decal/remains/human(loc)
/mob/living/carbon/human/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
dizziness = 0
jitteriness = 0
heart_attack = 0
if(istype(loc, /obj/mecha))
var/obj/mecha/M = loc
if(M.occupant == src)
M.go_out()
if(!gibbed)
emote("deathgasp") //let the world KNOW WE ARE DEAD
dna.species.spec_death(gibbed, src)
if(ticker && ticker.mode)
sql_report_death(src)
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
. = ..(gibbed)
if(mind && mind.devilinfo)
spawn(0)
mind.devilinfo.beginResurrectionCheck(src)
/mob/living/carbon/human/proc/makeSkeleton()
status_flags |= DISFIGURED
set_species(/datum/species/skeleton)
return 1
/mob/living/carbon/proc/ChangeToHusk()
if(disabilities & HUSK)
return
disabilities |= HUSK
status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools
return 1
/mob/living/carbon/human/ChangeToHusk()
. = ..()
if(.)
update_hair()
update_body()
/mob/living/carbon/proc/Drain()
ChangeToHusk()
disabilities |= NOCLONE
blood_volume = 0
return 1
@@ -0,0 +1,417 @@
/mob/living/carbon/human/emote(act,m_type=1,message = null)
if(stat == DEAD && (act != "deathgasp") || (status_flags & FAKEDEATH)) //if we're faking, don't emote at all
return
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
//var/m_type = 1
for (var/obj/item/weapon/implant/I in src)
if (I.implanted)
I.trigger(act, src)
var/miming=0
if(mind)
miming=mind.miming
switch(act) //Please keep this alphabetically ordered when adding or changing emotes.
if ("aflap") //Any emote on human that uses miming must be left in, oh well.
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings ANGRILY!"
m_type = 2
if ("choke","chokes")
if (miming)
message = "<B>[src]</B> clutches \his throat desperately!"
else
..(act)
if ("chuckle","chuckles")
if(miming)
message = "<B>[src]</B> appears to chuckle."
else
..(act)
if ("clap","claps")
if (!src.restrained())
message = "<B>[src]</B> claps."
m_type = 2
if ("collapse","collapses")
Paralyse(2)
adjustStaminaLoss(100) // Hampers abuse against simple mobs, but still leaves it a viable option.
message = "<B>[src]</B> collapses!"
m_type = 2
if ("cough","coughs")
if (miming)
message = "<B>[src]</B> appears to cough!"
else
if (!muzzled)
message = "<B>[src]</B> coughs!"
m_type = 2
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
if ("cry","crys","cries") //I feel bad if people put s at the end of cry. -Sum99
if (miming)
message = "<B>[src]</B> cries."
else
if (!muzzled)
message = "<B>[src]</B> cries."
m_type = 2
else
message = "<B>[src]</B> makes a weak noise. \He frowns."
m_type = 2
if ("custom")
if(jobban_isbanned(src, "emote"))
src << "You cannot send custom emotes (banned)"
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return
var/input = copytext(sanitize(input("Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN)
if (!input)
return
if(copytext(input,1,5) == "says")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
else
var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable")
if (input2 == "Visible")
m_type = 1
else if (input2 == "Hearable")
if(miming)
return
m_type = 2
else
alert("Unable to use this emote, must be either hearable or visible.")
return
message = "<B>[src]</B> [input]"
if ("dap","daps")
m_type = 1
if (!src.restrained())
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M)
message = "<B>[src]</B> gives daps to [M]."
else
message = "<B>[src]</B> sadly can't find anybody to give daps to, and daps \himself. Shameful."
if ("eyebrow")
message = "<B>[src]</B> raises an eyebrow."
m_type = 1
if ("flap","flaps")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings."
m_type = 2
if(((dna.features["wings"] != "None") && !("wings" in dna.species.mutant_bodyparts)))
OpenWings()
addtimer(src, "CloseWings", 20)
if ("wings")
if (!src.restrained())
if(dna && dna.species &&((dna.features["wings"] != "None") && ("wings" in dna.species.mutant_bodyparts)))
message = "<B>[src]</B> opens \his wings."
OpenWings()
else if(dna && dna.species &&((dna.features["wings"] != "None") && ("wingsopen" in dna.species.mutant_bodyparts)))
message = "<B>[src]</B> closes \his wings."
CloseWings()
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
if ("gasp","gasps")
if (miming)
message = "<B>[src]</B> appears to be gasping!"
else
..(act)
if ("giggle","giggles")
if (miming)
message = "<B>[src]</B> giggles silently!"
else
..(act)
if ("groan","groans")
if (miming)
message = "<B>[src]</B> appears to groan!"
else
if (!muzzled)
message = "<B>[src]</B> groans!"
m_type = 2
else
message = "<B>[src]</B> makes a loud noise."
m_type = 2
if ("grumble","grumbles")
if (!muzzled)
message = "<B>[src]</B> grumbles!"
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("handshake")
m_type = 1
if (!src.restrained() && !src.r_hand)
var/mob/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M == src)
M = null
if (M)
if (M.canmove && !M.r_hand && !M.restrained())
message = "<B>[src]</B> shakes hands with [M]."
else
message = "<B>[src]</B> holds out \his hand to [M]."
if ("hug","hugs")
m_type = 1
if (!src.restrained())
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M == src)
M = null
if (M)
message = "<B>[src]</B> hugs [M]."
else
message = "<B>[src]</B> hugs \himself."
if ("me")
if(silent)
return
if(jobban_isbanned(src, "emote"))
src << "You cannot send custom emotes (banned)"
return
if (src.client)
if (client.prefs.muted & MUTE_IC)
src << "<span class='danger'>You cannot send IC messages (muted).</span>"
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat)
return
if(!(message))
return
if(copytext(message,1,5) == "says")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
else
message = "<B>[src]</B> [message]"
if ("moan","moans")
if(miming)
message = "<B>[src]</B> appears to moan!"
else
message = "<B>[src]</B> moans!"
m_type = 2
if ("mumble","mumbles")
message = "<B>[src]</B> mumbles!"
m_type = 2
if ("pale")
message = "<B>[src]</B> goes pale for a second."
m_type = 1
if ("raise")
if (!src.restrained())
message = "<B>[src]</B> raises a hand."
m_type = 1
if ("salute","salutes")
if (!src.buckled)
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> salutes to [param]."
else
message = "<B>[src]</b> salutes."
m_type = 1
if ("scream","screams")
if (miming)
message = "<B>[src]</B> acts out a scream!"
else
..(act)
if ("shiver","shivers")
message = "<B>[src]</B> shivers."
m_type = 1
if ("shrug","shrugs")
message = "<B>[src]</B> shrugs."
m_type = 1
if ("sigh","sighs")
if(miming)
message = "<B>[src]</B> sighs."
else
..(act)
if ("signal","signals")
if (!src.restrained())
var/t1 = round(text2num(param))
if (isnum(t1))
if (t1 <= 5 && (!src.r_hand || !src.l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
else if (t1 <= 10 && (!src.r_hand && !src.l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
m_type = 1
if ("sneeze","sneezes")
if (miming)
message = "<B>[src]</B> sneezes."
else
..(act)
if ("sniff","sniffs")
message = "<B>[src]</B> sniffs."
m_type = 2
if ("snore","snores")
if (miming)
message = "<B>[src]</B> sleeps soundly."
else
..(act)
if ("whimper","whimpers")
if (miming)
message = "<B>[src]</B> appears hurt."
else
..(act)
if ("yawn","yawns")
if (!muzzled)
message = "<B>[src]</B> yawns."
m_type = 2
if("wag","wags")
if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || ((dna.features["tail_human"] != "None") && !("waggingtail_human" in dna.species.mutant_bodyparts))))
message = "<B>[src]</B> wags \his tail."
startTailWag()
else if(dna && dna.species && (("waggingtail_lizard" in dna.species.mutant_bodyparts) || ("waggingtail_human" in dna.species.mutant_bodyparts)))
endTailWag()
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
if ("help") //This can stay at the bottom.
src << "Help for human emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, dance, dap, deathgasp, drool, eyebrow, faint, flap, frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, jump, laugh, look-(none)/mob, me, moan, mumble, nod, pale, point-(atom), raise, salute, scream, shake, shiver, shrug, sigh, signal-#1-10, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, wings, wag, yawn"
else
..(act)
if(miming)
m_type = 1
if (message)
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
//Don't know where else to put this, it's basically an emote
/mob/living/carbon/human/proc/startTailWag()
if(!dna || !dna.species)
return
if("tail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_lizard"
dna.species.mutant_bodyparts -= "spines"
dna.species.mutant_bodyparts |= "waggingtail_lizard"
dna.species.mutant_bodyparts |= "waggingspines"
if("tail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_human"
dna.species.mutant_bodyparts |= "waggingtail_human"
update_body()
/mob/living/carbon/human/proc/endTailWag()
if(!dna || !dna.species)
return
if("waggingtail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_lizard"
dna.species.mutant_bodyparts -= "waggingspines"
dna.species.mutant_bodyparts |= "tail_lizard"
dna.species.mutant_bodyparts |= "spines"
if("waggingtail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_human"
dna.species.mutant_bodyparts |= "tail_human"
update_body()
/mob/living/carbon/human/proc/OpenWings()
if(!dna || !dna.species)
return
if("wings" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "wings"
dna.species.mutant_bodyparts |= "wingsopen"
update_body()
/mob/living/carbon/human/proc/CloseWings()
if(!dna || !dna.species)
return
if("wingsopen" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "wingsopen"
dna.species.mutant_bodyparts |= "wings"
update_body()
@@ -0,0 +1,347 @@
/mob/living/carbon/human/examine(mob/user)
var/list/obscured = check_obscured_slots()
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
// crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :<
var/t_He = "It" //capitalised for use at the start of each line.
var/t_his = "its"
var/t_him = "it"
var/t_has = "has"
var/t_is = "is"
var/msg = "<span class='info'>*---------*\nThis is "
if( (slot_w_uniform in obscured) && skipface ) //big suits/masks/helmets make it hard to tell their gender
t_He = "They"
t_his = "their"
t_him = "them"
t_has = "have"
t_is = "are"
else
switch(gender)
if(MALE)
t_He = "He"
t_his = "his"
t_him = "him"
if(FEMALE)
t_He = "She"
t_his = "her"
t_him = "her"
msg += "<EM>[src.name]</EM>!\n"
//uniform
if(w_uniform && !(slot_w_uniform in obscured))
//Ties
var/tie_msg
if(istype(w_uniform,/obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.hastie)
tie_msg += " with \icon[U.hastie] \a [U.hastie]"
if(w_uniform.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][tie_msg]!</span>\n"
else
msg += "[t_He] [t_is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n"
//head
if(head)
if(head.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!</span>\n"
else
msg += "[t_He] [t_is] wearing \icon[head] \a [head] on [t_his] head.\n"
//suit/armor
if(wear_suit)
if(wear_suit.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!</span>\n"
else
msg += "[t_He] [t_is] wearing \icon[wear_suit] \a [wear_suit].\n"
//suit/armor storage
if(s_store)
if(s_store.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] carrying \icon[s_store] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!</span>\n"
else
msg += "[t_He] [t_is] carrying \icon[s_store] \a [s_store] on [t_his] [wear_suit.name].\n"
//back
if(back)
if(back.blood_DNA)
msg += "<span class='warning'>[t_He] [t_has] \icon[back] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.</span>\n"
else
msg += "[t_He] [t_has] \icon[back] \a [back] on [t_his] back.\n"
//left hand
if(l_hand && !(l_hand.flags&ABSTRACT))
if(l_hand.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in [t_his] left hand!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[l_hand] \a [l_hand] in [t_his] left hand.\n"
//right hand
if(r_hand && !(r_hand.flags&ABSTRACT))
if(r_hand.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in [t_his] right hand!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n"
//gloves
if(gloves && !(slot_gloves in obscured))
if(gloves.blood_DNA)
msg += "<span class='warning'>[t_He] [t_has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!</span>\n"
else
msg += "[t_He] [t_has] \icon[gloves] \a [gloves] on [t_his] hands.\n"
else if(blood_DNA)
var/hand_number = get_num_arms()
if(hand_number)
msg += "<span class='warning'>[t_He] [t_has] [hand_number > 1 ? "" : "a"] blood-stained hand[hand_number > 1 ? "s" : ""]!</span>\n"
//handcuffed?
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/weapon/restraints/handcuffs/cable))
msg += "<span class='warning'>[t_He] [t_is] \icon[handcuffed] restrained with cable!</span>\n"
else
msg += "<span class='warning'>[t_He] [t_is] \icon[handcuffed] handcuffed!</span>\n"
//belt
if(belt)
if(belt.blood_DNA)
msg += "<span class='warning'>[t_He] [t_has] \icon[belt] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!</span>\n"
else
msg += "[t_He] [t_has] \icon[belt] \a [belt] about [t_his] waist.\n"
//shoes
if(shoes && !(slot_shoes in obscured))
if(shoes.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!</span>\n"
else
msg += "[t_He] [t_is] wearing \icon[shoes] \a [shoes] on [t_his] feet.\n"
//mask
if(wear_mask && !(slot_wear_mask in obscured))
if(wear_mask.blood_DNA)
msg += "<span class='warning'>[t_He] [t_has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!</span>\n"
else
msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n"
//eyes
if(glasses && !(slot_glasses in obscured))
if(glasses.blood_DNA)
msg += "<span class='warning'>[t_He] [t_has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!</span>\n"
else
msg += "[t_He] [t_has] \icon[glasses] \a [glasses] covering [t_his] eyes.\n"
//ears
if(ears && !(slot_ears in obscured))
msg += "[t_He] [t_has] \icon[ears] \a [ears] on [t_his] ears.\n"
//ID
if(wear_id)
/*var/id
if(istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
id = pda.owner
else if(istype(wear_id, /obj/item/weapon/card/id)) //just in case something other than a PDA/ID card somehow gets in the ID slot :[
var/obj/item/weapon/card/id/idcard = wear_id
id = idcard.registered_name
if(id && (id != real_name) && (get_dist(src, user) <= 1) && prob(10))
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...</span>\n"
else*/
msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id].\n"
//Jitters
switch(jitteriness)
if(300 to INFINITY)
msg += "<span class='warning'><B>[t_He] [t_is] convulsing violently!</B></span>\n"
if(200 to 300)
msg += "<span class='warning'>[t_He] [t_is] extremely jittery.</span>\n"
if(100 to 200)
msg += "<span class='warning'>[t_He] [t_is] twitching ever so slightly.</span>\n"
if(gender_ambiguous) //someone fucked up a gender reassignment surgery
if (gender == MALE)
msg += "[t_He] has a strange feminine quality to [t_him].\n"
else
msg += "[t_He] has a strange masculine quality to [t_him].\n"
var/appears_dead = 0
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = 1
if(getorgan(/obj/item/organ/brain))//Only perform these checks if there is no brain
if(suiciding)
msg += "<span class='warning'>[t_He] appears to have commited suicide... there is no hope of recovery.</span>\n"
if(hellbound)
msg += "<span class='warning'>[t_his] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive; there are no signs of life"
if(!key)
var/foundghost = 0
if(mind)
for(var/mob/dead/observer/G in player_list)
if(G.mind == mind)
foundghost = 1
if (G.can_reenter_corpse == 0)
foundghost = 0
break
if(!foundghost)
msg += " and [t_his] soul has departed"
msg += "...</span>\n"
else if(get_bodypart("head")) //Brain is gone, doesn't matter if they are AFK or present. Check for head first tho. Decapitation has similar message.
msg += "<span class='deadsay'>It appears that [t_his] brain is missing...</span>\n"
var/temp = getBruteLoss() //no need to calculate each of these twice
msg += "<span class='warning'>"
var/list/missing = list("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
missing -= BP.body_zone
for(var/obj/item/I in BP.embedded_objects)
msg += "<B>[t_He] [t_has] \a \icon[I] [I] embedded in [t_his] [BP.name]!</B>\n"
for(var/t in missing)
if(t=="head")
msg += "<span class='deadsay'><B>[capitalize(t_his)] [parse_zone(t)] is missing!</B><span class='warning'>\n"
continue
msg += "<B>[capitalize(t_his)] [parse_zone(t)] is missing!</B>\n"
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor bruising.\n"
else
msg += "<B>[t_He] [t_has] severe bruising!</B>\n"
temp = getFireLoss()
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor burns.\n"
else
msg += "<B>[t_He] [t_has] severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor cellular damage.\n"
else
msg += "<B>[t_He] [t_has] severe cellular damage.</B>\n"
if(fire_stacks > 0)
msg += "[t_He] [t_is] covered in something flammable.\n"
if(fire_stacks < 0)
msg += "[t_He] looks a little soaked.\n"
if(pulledby && pulledby.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
if(nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[t_He] [t_is] severely malnourished.\n"
else if(nutrition >= NUTRITION_LEVEL_FAT)
if(user.nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
if(blood_volume < BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(bleedsuppress)
msg += "[t_He] [t_is] bandaged with something.\n"
if(bleed_rate)
if(reagents.has_reagent("heparin"))
msg += "<b>[t_He] [t_is] bleeding uncontrollably!</b>\n"
else
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
if(reagents.has_reagent("teslium"))
msg += "[t_He] is emitting a gentle blue glow!\n"
if(stun_absorption)
msg += "[t_He] is radiating with a soft yellow light!\n" //Used by Vanguard
if(drunkenness && !skipface && stat != DEAD) //Drunkenness
switch(drunkenness)
if(11 to 21)
msg += "[t_He] [t_is] slightly flushed.\n"
if(21.01 to 41) //.01s are used in case drunkenness ends up to be a small decimal
msg += "[t_He] [t_is] flushed.\n"
if(41.01 to 51)
msg += "[t_He] [t_is] quite flushed and [t_his] breath smells of alcohol.\n"
if(51.01 to 61)
msg += "[t_He] is very flushed and [t_his] movements jerky, with breath reeking of alcohol.\n"
if(61.01 to 91)
msg += "[t_He] looks like a drunken mess.\n"
if(91.01 to INFINITY)
msg += "[t_He] is a shitfaced, slobbering wreck.\n"
msg += "</span>"
if(!appears_dead)
if(stat == UNCONSCIOUS)
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n"
else if(getBrainLoss() >= 60)
msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
if(getorgan(/obj/item/organ/brain))
if(istype(src,/mob/living/carbon/human/interactive))
msg += "<span class='deadsay'>[t_He] [t_is] appears to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.</span>\n"
else if(!key)
msg += "<span class='deadsay'>[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.</span>\n"
else if(!client)
msg += "[t_He] [t_has] a vacant, braindead stare...\n"
if(digitalcamo)
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n"
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
var/obj/item/organ/cyberimp/eyes/hud/CIH = H.getorgan(/obj/item/organ/cyberimp/eyes/hud)
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || CIH)
var/perpname = get_face_name(get_id_name(""))
if(perpname)
var/datum/data/record/R = find_record("name", perpname, data_core.general)
if(R)
msg += "<span class='deptradio'>Rank:</span> [R.fields["rank"]]<br>"
msg += "<a href='?src=\ref[src];hud=1;photo_front=1'>\[Front photo\]</a> "
msg += "<a href='?src=\ref[src];hud=1;photo_side=1'>\[Side photo\]</a><br>"
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/cyberimp/eyes/hud/medical))
var/implant_detect
for(var/obj/item/organ/cyberimp/CI in internal_organs)
if(CI.status == ORGAN_ROBOTIC)
implant_detect += "[name] is modified with a [CI.name].<br>"
if(implant_detect)
msg += "Detected cybernetic modifications:<br>"
msg += implant_detect
if(R)
var/health = R.fields["p_stat"]
msg += "<a href='?src=\ref[src];hud=m;p_stat=1'>\[[health]\]</a>"
health = R.fields["m_stat"]
msg += "<a href='?src=\ref[src];hud=m;m_stat=1'>\[[health]\]</a><br>"
R = find_record("name", perpname, data_core.medical)
if(R)
msg += "<a href='?src=\ref[src];hud=m;evaluation=1'>\[Medical evaluation\]</a><br>"
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(CIH,/obj/item/organ/cyberimp/eyes/hud/security))
if(!user.stat && user != src)
//|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
var/criminal = "None"
R = find_record("name", perpname, data_core.security)
if(R)
criminal = R.fields["criminal"]
msg += "<span class='deptradio'>Criminal status:</span> <a href='?src=\ref[src];hud=s;status=1'>\[[criminal]\]</a>\n"
msg += "<span class='deptradio'>Security record:</span> <a href='?src=\ref[src];hud=s;view=1'>\[View\]</a> "
msg += "<a href='?src=\ref[src];hud=s;add_crime=1'>\[Add crime\]</a> "
msg += "<a href='?src=\ref[src];hud=s;view_comment=1'>\[View comment log\]</a> "
msg += "<a href='?src=\ref[src];hud=s;add_comment=1'>\[Add comment\]</a>\n"
msg += "*---------*</span>"
user << msg
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
if(check_shields(0, M.name))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return 0
if(..())
if(M.a_intent == "harm")
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
"<span class='userdanger'>[M] has lunged at [src]!</span>")
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
var/armor_block = run_armor_check(affecting, "melee","","",10)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
apply_damage(damage, BRUTE, affecting, armor_block)
if (prob(30))
visible_message("<span class='danger'>[M] has wounded [src]!</span>", \
"<span class='userdanger'>[M] has wounded [src]!</span>")
apply_effect(4, WEAKEN, armor_block)
add_logs(M, src, "attacked")
updatehealth()
if(M.a_intent == "disarm")
var/randn = rand(1, 100)
if (randn <= 80)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Weaken(5)
add_logs(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
else
if (randn <= 99)
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
drop_item()
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has tried to disarm [src]!</span>", \
"<span class='userdanger'>[M] has tried to disarm [src]!</span>")
return
@@ -0,0 +1,14 @@
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/hulk_verb = pick("smash","pummel")
visible_message("<span class='danger'>[user] has [hulk_verb]ed [src]!</span>", \
"<span class='userdanger'>[user] has [hulk_verb]ed [src]!</span>")
adjustBruteLoss(15)
return 1
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return
dna.species.spec_attack_hand(M, src)
@@ -0,0 +1,15 @@
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(M.a_intent == "help")
..() //shaking
return 0
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
updatehealth()
return 1
@@ -0,0 +1,161 @@
//Updates the mob's health from bodyparts and mob damage variables
/mob/living/carbon/human/updatehealth()
if(status_flags & GODMODE)
return
var/total_burn = 0
var/total_brute = 0
for(var/X in bodyparts) //hardcoded to streamline things a bit
var/obj/item/bodypart/BP = X
total_brute += BP.brute_dam
total_burn += BP.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
update_stat()
if(((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD )
ChangeToHusk()
if(on_fire)
shred_clothing()
med_hud_set_health()
med_hud_set_status()
//These procs fetch a cumulative total damage from all bodyparts
/mob/living/carbon/human/getBruteLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.brute_dam
return amount
/mob/living/carbon/human/getFireLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.burn_dam
return amount
/mob/living/carbon/human/adjustBruteLoss(amount)
if(status_flags & GODMODE)
return 0
if(amount > 0)
take_overall_damage(amount, 0)
else
heal_overall_damage(-amount, 0)
/mob/living/carbon/human/adjustFireLoss(amount)
if(status_flags & GODMODE)
return 0
if(amount > 0)
take_overall_damage(0, amount)
else
heal_overall_damage(0, -amount)
/mob/living/carbon/human/proc/hat_fall_prob()
var/multiplier = 1
var/obj/item/clothing/head/H = head
var/loose = 40
if(stat || (status_flags & FAKEDEATH))
multiplier = 2
if(H.flags_cover & (HEADCOVERSEYES | HEADCOVERSMOUTH) || H.flags_inv & (HIDEEYES | HIDEFACE))
loose = 0
return loose * multiplier
////////////////////////////////////////////
//Returns a list of damaged bodyparts
/mob/living/carbon/human/proc/get_damaged_bodyparts(brute, burn)
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if((brute && BP.brute_dam) || (burn && BP.burn_dam))
parts += BP
return parts
//Returns a list of damageable bodyparts
/mob/living/carbon/human/proc/get_damageable_bodyparts()
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.brute_dam + BP.burn_dam < BP.max_damage)
parts += BP
return parts
//Heals ONE external organ, organ gets randomly selected from damaged ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/heal_organ_damage(brute, burn)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.heal_damage(brute,burn,0))
update_damage_overlays(0)
updatehealth()
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/take_organ_damage(brute, burn)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.take_damage(brute,burn))
update_damage_overlays(0)
updatehealth()
//Heal MANY bodyparts, in random order
/mob/living/carbon/human/heal_overall_damage(brute, burn, updating_health=1)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.heal_damage(brute,burn,0)
brute -= (brute_was-picked.brute_dam)
burn -= (burn_was-picked.burn_dam)
parts -= picked
if(updating_health)
updatehealth()
if(update)
update_damage_overlays(0)
// damage MANY bodyparts, in random order
/mob/living/carbon/human/take_overall_damage(brute, burn)
if(status_flags & GODMODE)
return //godmode
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_per_part = brute/parts.len
var/burn_per_part = burn/parts.len
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.take_damage(brute_per_part,burn_per_part)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
parts -= picked
updatehealth()
if(update)
update_damage_overlays(0)
////////////////////////////////////////////
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
// depending on the species, it will run the corresponding apply_damage code there
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
@@ -0,0 +1,384 @@
/mob/living/carbon/human/getarmor(def_zone, type)
var/armorval = 0
var/organnum = 0
if(def_zone)
if(islimb(def_zone))
return checkarmor(def_zone, type)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(def_zone))
return checkarmor(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
armorval += checkarmor(BP, type)
organnum++
return (armorval/max(organnum, 1))
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, type)
if(!type)
return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
for(var/bp in body_parts)
if(!bp)
continue
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor[type]
return protection
/mob/living/carbon/human/on_hit(proj_type)
dna.species.on_hit(proj_type, src)
/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.Angle = null
return -1 // complete projectile permutation
if(check_shields(P.damage, "the [P.name]", P, PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
return (..(P , def_zone))
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
if(wear_suit)
if(wear_suit.IsReflect(def_zone) == 1)
return 1
if(l_hand)
if(l_hand.IsReflect(def_zone) == 1)
return 1
if(r_hand)
if(r_hand.IsReflect(def_zone) == 1)
return 1
return 0
/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
if(l_hand && !istype(l_hand, /obj/item/clothing))
var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
if(w_uniform.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
/mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user)
if(!I || !user)
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected))
var/target_area = parse_zone(check_zone(user.zone_selected))
feedback_add_details("item_used_for_combat","[I.type]|[I.force]")
feedback_add_details("zone_targeted","[target_area]")
// the attacked_by code varies among species
return dna.species.spec_attacked_by(I, user, affecting, a_intent, target_area, src)
/mob/living/carbon/human/emp_act(severity)
var/informed = 0
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.status == ORGAN_ROBOTIC)
if(!informed)
src << "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>"
informed = 1
switch(severity)
if(1)
L.take_damage(0,10)
src.Stun(10)
if(2)
L.take_damage(0,5)
src.Stun(5)
..()
/mob/living/carbon/human/acid_act(acidpwr, toxpwr, acid_volume)
var/list/damaged = list()
var/list/inventory_items_to_kill = list()
var/acidity = min(acidpwr*acid_volume/200, toxpwr)
var/acid_volume_left = acid_volume
var/acid_decay = 100/acidpwr // how much volume we lose per item we try to melt. 5 for fluoro, 10 for sulphuric
//HEAD//
var/obj/item/clothing/head_clothes = null
if(glasses)
head_clothes = glasses
if(wear_mask)
head_clothes = wear_mask
if(head)
head_clothes = head
if(head_clothes)
if(!head_clothes.unacidable)
head_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0) //We remove some of the acid volume.
update_inv_glasses()
update_inv_wear_mask()
update_inv_head()
else
src << "<span class='notice'>Your [head_clothes.name] protects your head and face from the acid!</span>"
else
. = get_bodypart("head")
if(.)
damaged += .
if(ears)
inventory_items_to_kill += ears
//CHEST//
var/obj/item/clothing/chest_clothes = null
if(w_uniform)
chest_clothes = w_uniform
if(wear_suit)
chest_clothes = wear_suit
if(chest_clothes)
if(!chest_clothes.unacidable)
chest_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [chest_clothes.name] protects your body from the acid!</span>"
else
. = get_bodypart("chest")
if(.)
damaged += .
if(wear_id)
inventory_items_to_kill += wear_id
if(r_store)
inventory_items_to_kill += r_store
if(l_store)
inventory_items_to_kill += l_store
if(s_store)
inventory_items_to_kill += s_store
//ARMS & HANDS//
var/obj/item/clothing/arm_clothes = null
if(gloves)
arm_clothes = gloves
if(w_uniform && (w_uniform.body_parts_covered & HANDS) || w_uniform && (w_uniform.body_parts_covered & ARMS))
arm_clothes = w_uniform
if(wear_suit && (wear_suit.body_parts_covered & HANDS) || wear_suit && (wear_suit.body_parts_covered & ARMS))
arm_clothes = wear_suit
if(arm_clothes)
if(!arm_clothes.unacidable)
arm_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_gloves()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [arm_clothes.name] protects your arms and hands from the acid!</span>"
else
. = get_bodypart("r_arm")
if(.)
damaged += .
. = get_bodypart("l_arm")
if(.)
damaged += .
//LEGS & FEET//
var/obj/item/clothing/leg_clothes = null
if(shoes)
leg_clothes = shoes
if(w_uniform && (w_uniform.body_parts_covered & FEET) || w_uniform && (w_uniform.body_parts_covered & LEGS))
leg_clothes = w_uniform
if(wear_suit && (wear_suit.body_parts_covered & FEET) || wear_suit && (wear_suit.body_parts_covered & LEGS))
leg_clothes = wear_suit
if(leg_clothes)
if(!leg_clothes.unacidable)
leg_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_shoes()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [leg_clothes.name] protects your legs and feet from the acid!</span>"
else
. = get_bodypart("r_leg")
if(.)
damaged += .
. = get_bodypart("l_leg")
if(.)
damaged += .
//DAMAGE//
for(var/obj/item/bodypart/affecting in damaged)
affecting.take_damage(acidity, 2*acidity)
if(affecting.name == "head")
if(prob(min(acidpwr*acid_volume/10, 90))) //Applies disfigurement
affecting.take_damage(acidity, 2*acidity)
emote("scream")
facial_hair_style = "Shaved"
hair_style = "Bald"
update_hair()
status_flags |= DISFIGURED
update_damage_overlays()
//MELTING INVENTORY ITEMS//
//these items are all outside of armour visually, so melt regardless.
if(back)
inventory_items_to_kill += back
if(belt)
inventory_items_to_kill += belt
if(r_hand)
inventory_items_to_kill += r_hand
if(l_hand)
inventory_items_to_kill += l_hand
for(var/obj/item/I in inventory_items_to_kill)
I.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor = run_armor_check(affecting, "melee")
apply_damage(damage, M.melee_damage_type, affecting, armor, "", "", M.armour_penetration)
updatehealth()
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(check_shields(damage, "the [L.name]"))
return 0
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
updatehealth()
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(check_shields(damage, "the [M.name]"))
return 0
var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == "harm")
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
var/obj/item/bodypart/temp = get_bodypart(pick("chest", "chest", "chest", "head"))
if(temp)
var/update = 0
switch(M.damtype)
if("brute")
if(M.force > 20)
Paralyse(1)
update |= temp.take_damage(rand(M.force/2, M.force), 0)
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
update |= temp.take_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
if("tox")
M.mech_toxin_damage(src)
else
return
if(update)
update_damage_overlays(0)
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>")
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
..()
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
var/obj/item/I
var/throwpower = 30
if(istype(AM, /obj/item))
I = AM
throwpower = I.throwforce
if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions
return ..()
if(check_shields(throwpower, "\the [AM.name]", AM, THROWN_PROJECTILE_ATTACK))
hitpush = 0
skipcatch = 1
blocked = 1
else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
if(can_embed(I))
if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags)))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.loc = src
L.take_damage(I.w_class*I.embedded_impact_pain_multiplier)
visible_message("<span class='danger'>\the [I.name] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>\the [I.name] embeds itself in your [L.name]!</span>")
hitpush = 0
skipcatch = 1 //can't catch the now embedded item
return ..()
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling))
devour_mob(pulling)
else
..()
/mob/living/carbon/human/grippedby(mob/living/user)
if(w_uniform)
w_uniform.add_fingerprint(user)
..()
/mob/living/carbon/human/Stun(amount, updating_canmove = 1)
amount = dna.species.spec_stun(src,amount)
..()
@@ -0,0 +1,56 @@
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
languages_spoken = HUMAN
languages_understood = HUMAN
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
//Facial hair colour and style
var/facial_hair_color = "000"
var/facial_hair_style = "Shaved"
//Eye colour
var/eye_color = "000"
var/skin_tone = "caucasian1" //Skin tone
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
var/socks = "Nude" //Which socks the player wants
var/backbag = DBACKPACK //Which backpack type the player has chosen.
//Equipment slots
var/obj/item/wear_suit = null
var/obj/item/w_uniform = null
var/obj/item/shoes = null
var/obj/item/belt = null
var/obj/item/gloves = null
var/obj/item/clothing/glasses/glasses = null
var/obj/item/ears = null
var/obj/item/wear_id = null
var/obj/item/r_store = null
var/obj/item/l_store = null
var/obj/item/s_store = null
var/special_voice = "" // For changing our voice. Used by a symptom.
var/gender_ambiguous = 0 //if something goes wrong during gender reassignment this generates a line in examine
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/datum/martial_art/martial_art = null
var/name_override //For temporary visible name changes
var/heart_attack = 0
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/datum/personal_crafting/handcrafting
@@ -0,0 +1,168 @@
/mob/living/carbon/human/restrained(ignore_grab)
. = ((wear_suit && wear_suit.breakouttime) || ..())
/mob/living/carbon/human/canBeHandcuffed()
if(get_num_arms() >= 2)
return TRUE
else
return FALSE
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job")
var/obj/item/weapon/card/id/id = get_idcard()
if(id)
. = id.assignment
else
var/obj/item/device/pda/pda = wear_id
if(istype(pda))
. = pda.ownjob
else
return if_no_id
if(!.)
return if_no_job
//gets name from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown")
var/obj/item/weapon/card/id/id = get_idcard()
if(id)
return id.registered_name
var/obj/item/device/pda/pda = wear_id
if(istype(pda))
return pda.owner
return if_no_id
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere
/mob/living/carbon/human/get_visible_name()
var/face_name = get_face_name("")
var/id_name = get_id_name("")
if(name_override)
return name_override
if(face_name)
if(id_name && (id_name != face_name))
return "[face_name] (as [id_name])"
return face_name
if(id_name)
return id_name
return "Unknown"
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when Fluacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name(if_no_face="Unknown")
if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible
return if_no_face
if( head && (head.flags_inv&HIDEFACE) )
return if_no_face //Likewise for hats
var/obj/item/bodypart/O = get_bodypart("head")
if( !O || (status_flags&DISFIGURED) || (O.brutestate+O.burnstate)>2 || cloneloss>50 || !real_name ) //disfigured. use id-name if possible
return if_no_face
return real_name
//gets name from ID or PDA itself, ID inside PDA doesn't matter
//Useful when player is being seen by other mobs
/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown")
var/obj/item/weapon/storage/wallet/wallet = wear_id
var/obj/item/device/pda/pda = wear_id
var/obj/item/weapon/card/id/id = wear_id
if(istype(wallet))
id = wallet.front_id
if(istype(id))
. = id.registered_name
else if(istype(pda))
. = pda.owner
if(!.)
. = if_no_id //to prevent null-names making the mob unclickable
return
//gets ID card object from special clothes slot or null.
/mob/living/carbon/human/get_idcard()
if(wear_id)
return wear_id.GetID()
///checkeyeprot()
///Returns a number between -1 to 2
/mob/living/carbon/human/check_eye_prot()
var/number = ..()
if(istype(src.head, /obj/item/clothing/head)) //are they wearing something on their head
var/obj/item/clothing/head/HFP = src.head //if yes gets the flash protection value from that item
number += HFP.flash_protect
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
var/obj/item/clothing/glasses/GFP = src.glasses
number += GFP.flash_protect
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
return number
/mob/living/carbon/human/check_ear_prot()
if((ears && (ears.flags & EARBANGPROTECT)) || (head && (head.flags & HEADBANGPROTECT)))
return 1
/mob/living/carbon/human/abiotic(full_body = 0)
if(full_body && ((l_hand && !( src.l_hand.flags&ABSTRACT )) || (r_hand && !( src.r_hand.flags&ABSTRACT )) || (back && !(back.flags&ABSTRACT)) || (wear_mask && !(wear_mask.flags&ABSTRACT)) || (head && !(head.flags&ABSTRACT)) || (shoes && !(shoes.flags&ABSTRACT)) || (w_uniform && !(w_uniform.flags&ABSTRACT)) || (wear_suit && !(wear_suit.flags&ABSTRACT)) || (glasses && !(glasses.flags&ABSTRACT)) || (ears && !(ears.flags&ABSTRACT)) || (gloves && !(gloves.flags&ABSTRACT)) ) )
return 1
if( (src.l_hand && !(src.l_hand.flags&ABSTRACT)) || (src.r_hand && !(src.r_hand.flags&ABSTRACT)) )
return 1
return 0
/mob/living/carbon/human/IsAdvancedToolUser()
return 1//Humans can use guns and such
/mob/living/carbon/human/InCritical()
return (health <= config.health_threshold_crit && stat == UNCONSCIOUS)
/mob/living/carbon/human/reagent_check(datum/reagent/R)
return dna.species.handle_chemicals(R,src)
// if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species.
/mob/living/carbon/human/can_track(mob/living/user)
if(wear_id && istype(wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
return 0
if(istype(head, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = head
if(hat.blockTracking)
return 0
return ..()
/mob/living/carbon/human/get_permeability_protection()
var/list/prot = list("hands"=0, "chest"=0, "groin"=0, "legs"=0, "feet"=0, "arms"=0, "head"=0)
for(var/obj/item/I in get_equipped_items())
if(I.body_parts_covered & HANDS)
prot["hands"] = max(1 - I.permeability_coefficient, prot["hands"])
if(I.body_parts_covered & CHEST)
prot["chest"] = max(1 - I.permeability_coefficient, prot["chest"])
if(I.body_parts_covered & GROIN)
prot["groin"] = max(1 - I.permeability_coefficient, prot["groin"])
if(I.body_parts_covered & LEGS)
prot["legs"] = max(1 - I.permeability_coefficient, prot["legs"])
if(I.body_parts_covered & FEET)
prot["feet"] = max(1 - I.permeability_coefficient, prot["feet"])
if(I.body_parts_covered & ARMS)
prot["arms"] = max(1 - I.permeability_coefficient, prot["arms"])
if(I.body_parts_covered & HEAD)
prot["head"] = max(1 - I.permeability_coefficient, prot["head"])
var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7
return protection
/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/gun/G)
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(src.dna.check_mutation(HULK))
src << "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>"
return 0
if(NOGUNS in src.dna.species.specflags)
src << "<span class='warning'>Your fingers don't fit in the trigger guard!</span>"
return 0
if(martial_art && martial_art.name == "The Sleeping Carp") //great dishonor to famiry
src << "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>"
return 0
return .
@@ -0,0 +1,63 @@
/mob/living/carbon/human/movement_delay()
. += dna.species.movement_delay(src)
. += ..()
. += config.human_delay
/mob/living/carbon/human/slip(s_amount, w_amount, obj/O, lube)
if(isobj(shoes) && (shoes.flags&NOSLIP) && !(lube&GALOSHES_DONT_HELP))
return 0
return ..()
/mob/living/carbon/human/experience_pressure_difference()
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
if(shoes && shoes.flags&NOSLIP)
return 0
return ..()
/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity())
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_move(src, NewLoc)
if(shoes)
if(!lying && !buckled)
if(loc == NewLoc)
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
if(oldFP && oldFP.blood_state == S.blood_state)
return
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
FP.blood_state = S.blood_state
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
if(S.blood_DNA && S.blood_DNA.len)
FP.transfer_blood_dna(S.blood_DNA)
FP.update_icon()
update_inv_shoes()
//End bloody footprints
S.step_action()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(..())
return 1
return dna.species.space_move()
@@ -0,0 +1,292 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0))
return slot
if(qdel_on_fail)
qdel(I)
return null
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_back)
return back
if(slot_wear_mask)
return wear_mask
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
if(slot_belt)
return belt
if(slot_wear_id)
return wear_id
if(slot_ears)
return ears
if(slot_glasses)
return glasses
if(slot_gloves)
return gloves
if(slot_head)
return head
if(slot_shoes)
return shoes
if(slot_wear_suit)
return wear_suit
if(slot_w_uniform)
return w_uniform
if(slot_l_store)
return l_store
if(slot_r_store)
return r_store
if(slot_s_store)
return s_store
return null
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
if(!..()) //a check failed or the item has already found its slot
return
switch(slot)
if(slot_belt)
belt = I
update_inv_belt()
if(slot_wear_id)
wear_id = I
sec_hud_set_ID()
update_inv_wear_id()
if(slot_ears)
ears = I
update_inv_ears()
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.vision_correction)
clear_fullscreen("nearsighted")
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
update_sight()
update_inv_glasses()
if(slot_gloves)
gloves = I
update_inv_gloves()
if(slot_shoes)
shoes = I
update_inv_shoes()
if(slot_wear_suit)
wear_suit = I
if(I.flags_inv & HIDEJUMPSUIT)
update_inv_w_uniform()
if(wear_suit.breakouttime) //when equipping a straightjacket
stop_pulling() //can't pull if restrained
update_action_buttons_icon() //certain action buttons will no longer be usable.
update_inv_wear_suit()
if(slot_w_uniform)
w_uniform = I
update_suit_sensors()
update_inv_w_uniform()
if(slot_l_store)
l_store = I
update_inv_pockets()
if(slot_r_store)
r_store = I
update_inv_pockets()
if(slot_s_store)
s_store = I
update_inv_s_store()
else
src << "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>"
/mob/living/carbon/human/unEquip(obj/item/I)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(I == wear_suit)
if(s_store)
unEquip(s_store, 1) //It makes no sense for your suit storage to stay on you if you drop your suit.
if(wear_suit.breakouttime) //when unequipping a straightjacket
update_action_buttons_icon() //certain action buttons may be usable again.
wear_suit = null
if(I.flags_inv & HIDEJUMPSUIT)
update_inv_w_uniform()
update_inv_wear_suit()
else if(I == w_uniform)
if(r_store)
unEquip(r_store, 1) //Again, makes sense for pockets to drop.
if(l_store)
unEquip(l_store, 1)
if(wear_id)
unEquip(wear_id)
if(belt)
unEquip(belt)
w_uniform = null
update_suit_sensors()
update_inv_w_uniform()
else if(I == gloves)
gloves = null
update_inv_gloves()
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.vision_correction)
if(disabilities & NEARSIGHT)
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
update_sight()
update_inv_glasses()
else if(I == ears)
ears = null
update_inv_ears()
else if(I == shoes)
shoes = null
update_inv_shoes()
else if(I == belt)
belt = null
update_inv_belt()
else if(I == wear_id)
wear_id = null
sec_hud_set_ID()
update_inv_wear_id()
else if(I == r_store)
r_store = null
update_inv_pockets()
else if(I == l_store)
l_store = null
update_inv_pockets()
else if(I == s_store)
s_store = null
update_inv_s_store()
/mob/living/carbon/human/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
if((C.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(C.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR)))
update_hair()
if(toggle_off && internal && !getorganslot("breathing_tube"))
update_internals_hud_icon(0)
internal = null
if(C.flags_inv & HIDEEYES)
update_inv_glasses()
sec_hud_set_security_status()
..()
/mob/living/carbon/human/head_update(obj/item/I, forced)
if((I.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || forced)
update_hair()
if(I.flags_inv & HIDEEYES || forced)
update_inv_glasses()
if(I.flags_inv & HIDEEARS || forced)
update_body()
sec_hud_set_security_status()
..()
//Cycles through all clothing slots and tests them for destruction
/mob/living/carbon/human/proc/shred_clothing(bomb,shock)
var/covered_parts = 0 //The body parts that are protected by exterior clothing/armor
var/head_absorbed = 0 //How much of the shock the headgear absorbs when it is shredded. -1=it survives
var/suit_absorbed = 0 //How much of the shock the exosuit absorbs when it is shredded. -1=it survives
//Backpacks can never be protected but are annoying as fuck to lose, so they get a lower chance to be shredded
if(back)
back.shred(bomb,shock-20,src)
if(head)
covered_parts |= head.flags_inv
head_absorbed = head.shred(bomb,shock,src)
if(wear_mask)
var/absorbed = ((covered_parts & HIDEMASK) ? head_absorbed : 0) //Check if clothing covering this part absorbed any of the shock
if(absorbed >= 0)
//Masks can be used to shield other parts, but are simplified to simply add their absorbsion to the head armor if it covers the face
var/mask_absorbed = wear_mask.shred(bomb,shock-absorbed,src)
if(wear_mask.flags_inv & HIDEFACE)
covered_parts |= wear_mask.flags_inv
if(mask_absorbed < 0) //If the mask didn't get shredded, everything else on the head is protected
head_absorbed = -1
else
head_absorbed += mask_absorbed
if(ears)
var/absorbed = ((covered_parts & HIDEEARS) ? head_absorbed : 0)
if(absorbed >= 0)
ears.shred(bomb,shock-absorbed,src)
if(glasses)
var/absorbed = ((covered_parts & HIDEEYES) ? head_absorbed : 0)
if(absorbed >= 0)
glasses.shred(bomb,shock-absorbed,src)
if(wear_suit)
covered_parts |= wear_suit.flags_inv
suit_absorbed = wear_suit.shred(bomb,shock,src)
if(gloves)
var/absorbed = ((covered_parts & HIDEGLOVES) ? suit_absorbed : 0)
if(absorbed >= 0)
gloves.shred(bomb,shock-absorbed,src)
if(shoes)
var/absorbed = ((covered_parts & HIDESHOES) ? suit_absorbed : 0)
if(absorbed >= 0)
shoes.shred(bomb,shock-absorbed,src)
if(w_uniform)
var/absorbed = ((covered_parts & HIDEJUMPSUIT) ? suit_absorbed : 0)
if(absorbed >= 0)
w_uniform.shred(bomb,shock-20-absorbed,src) //Uniforms are also annoying to get shredded
/obj/item/proc/shred(bomb,shock,mob/living/carbon/human/Human)
if(flags & ABSTRACT)
return -1
var/shredded
if(!bomb)
if(burn_state != -1)
shredded = 1 //No heat protection, it burns
else
shredded = -1 //Heat protection = Fireproof
else if(shock > 0)
if(prob(max(shock-armor["bomb"],0)))
shredded = armor["bomb"] + 10 //It gets shredded, but it also absorbs the shock the clothes underneath would recieve by this amount
else
shredded = -1 //It survives explosion
if(shredded > 0)
if(Human) //Unequip if equipped
Human.unEquip(src)
if(bomb)
empty_object_contents()
spawn(1) //so the shreds aren't instantly deleted by the explosion
var/obj/effect/decal/cleanable/shreds/Shreds = new(loc)
Shreds.desc = "The sad remains of what used to be [src.name]."
qdel(src)
else
burn()
return shredded
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
var/datum/outfit/O = null
if(ispath(outfit))
O = new outfit
else
O = outfit
if(!istype(O))
return 0
if(!O)
return 0
return O.equip(src, visualsOnly)
@@ -0,0 +1,393 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 10 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point
//Note that gas heat damage is only applied once every FOUR ticks.
#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point
#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point
#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point
#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
#define BRAIN_DAMAGE_FILE "brain_damage_lines.json"
/mob/living/carbon/human/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(..())
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_life(src)
//heart attack stuff
handle_heart()
//Stuff jammed in your limbs hurts
handle_embedded_objects()
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
dna.species.spec_life(src) // for mutantraces
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
return ONE_ATMOSPHERE
else
return pressure
/mob/living/carbon/human/handle_disabilities()
if(eye_blind) //blindness, heals slowly over time
if(tinttotal >= TINT_BLIND) //covering your eyes heals blurry eyes faster
adjust_blindness(-3)
else
adjust_blindness(-1)
else if(eye_blurry) //blurry eyes heal slowly
adjust_blurriness(-1)
//Ears
if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own
setEarDamage(-1, max(ear_deaf, 1))
else
if(istype(ears, /obj/item/clothing/ears/earmuffs)) // earmuffs rest your ears, healing ear_deaf faster and ear_damage, but keeping you deaf.
setEarDamage(max(ear_damage-0.10, 0), max(ear_deaf - 1, 1))
// deafness heals slowly over time, unless ear_damage is over 100
if(ear_damage < 100)
adjustEarDamage(-0.05,-1)
if (getBrainLoss() >= 60 && stat != DEAD)
if (prob(3))
if(prob(25))
emote("drool")
else
say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage"))
/mob/living/carbon/human/handle_mutations_and_radiation()
if(!dna || !dna.species.handle_mutations_and_radiation(src))
..()
/mob/living/carbon/human/breathe()
if(!dna.species.breathe(src))
..()
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
dna.species.check_breath(breath, src)
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
dna.species.handle_environment(environment, src)
///FIRE CODE
/mob/living/carbon/human/handle_fire()
if(!dna || !dna.species.handle_fire(src))
..()
if(on_fire)
var/thermal_protection = get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
return
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT)
bodytemperature += 11
else
bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12))
/mob/living/carbon/human/proc/get_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
if(wear_suit)
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
if(head)
if(head.max_heat_protection_temperature >= FIRE_HELM_MAX_TEMP_PROTECT)
thermal_protection += (head.max_heat_protection_temperature*THERMAL_PROTECTION_HEAD)
thermal_protection = round(thermal_protection)
return thermal_protection
/mob/living/carbon/human/IgniteMob()
//If have no DNA or can be Ignited, call parent handling to light user
//If firestacks are high enough
if(!dna || dna.species.CanIgniteMob(src))
return ..()
. = FALSE //No ignition
/mob/living/carbon/human/ExtinguishMob()
if(!dna || !dna.species.ExtinguishMob(src))
..()
//END FIRE CODE
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
//Handle normal clothing
if(head)
if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= head.heat_protection
if(wear_suit)
if(wear_suit.max_heat_protection_temperature && wear_suit.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= wear_suit.heat_protection
if(w_uniform)
if(w_uniform.max_heat_protection_temperature && w_uniform.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= w_uniform.heat_protection
if(shoes)
if(shoes.max_heat_protection_temperature && shoes.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= shoes.heat_protection
if(gloves)
if(gloves.max_heat_protection_temperature && gloves.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= gloves.heat_protection
if(wear_mask)
if(wear_mask.max_heat_protection_temperature && wear_mask.max_heat_protection_temperature >= temperature)
thermal_protection_flags |= wear_mask.heat_protection
return thermal_protection_flags
/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = get_heat_protection_flags(temperature)
var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
if(thermal_protection_flags & CHEST)
thermal_protection += THERMAL_PROTECTION_CHEST
if(thermal_protection_flags & GROIN)
thermal_protection += THERMAL_PROTECTION_GROIN
if(thermal_protection_flags & LEG_LEFT)
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
if(thermal_protection_flags & LEG_RIGHT)
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
if(thermal_protection_flags & FOOT_LEFT)
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
if(thermal_protection_flags & FOOT_RIGHT)
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
if(thermal_protection_flags & ARM_LEFT)
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
if(thermal_protection_flags & ARM_RIGHT)
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
if(thermal_protection_flags & HAND_LEFT)
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
//See proc/get_heat_protection_flags(temperature) for the description of this proc.
/mob/living/carbon/human/proc/get_cold_protection_flags(temperature)
var/thermal_protection_flags = 0
//Handle normal clothing
if(head)
if(head.min_cold_protection_temperature && head.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= head.cold_protection
if(wear_suit)
if(wear_suit.min_cold_protection_temperature && wear_suit.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= wear_suit.cold_protection
if(w_uniform)
if(w_uniform.min_cold_protection_temperature && w_uniform.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= w_uniform.cold_protection
if(shoes)
if(shoes.min_cold_protection_temperature && shoes.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= shoes.cold_protection
if(gloves)
if(gloves.min_cold_protection_temperature && gloves.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= gloves.cold_protection
if(wear_mask)
if(wear_mask.min_cold_protection_temperature && wear_mask.min_cold_protection_temperature <= temperature)
thermal_protection_flags |= wear_mask.cold_protection
return thermal_protection_flags
/mob/living/carbon/human/proc/get_cold_protection(temperature)
if(dna.check_mutation(COLDRES))
return 1 //Fully protected from the cold.
if(dna && (RESISTTEMP in dna.species.specflags))
return 1
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
if(thermal_protection_flags & CHEST)
thermal_protection += THERMAL_PROTECTION_CHEST
if(thermal_protection_flags & GROIN)
thermal_protection += THERMAL_PROTECTION_GROIN
if(thermal_protection_flags & LEG_LEFT)
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
if(thermal_protection_flags & LEG_RIGHT)
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
if(thermal_protection_flags & FOOT_LEFT)
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
if(thermal_protection_flags & FOOT_RIGHT)
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
if(thermal_protection_flags & ARM_LEFT)
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
if(thermal_protection_flags & ARM_RIGHT)
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
if(thermal_protection_flags & HAND_LEFT)
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
/mob/living/carbon/human/handle_chemicals_in_body()
if(reagents)
reagents.metabolize(src, can_overdose=1)
dna.species.handle_chemicals_in_body(src)
/mob/living/carbon/human/handle_random_events()
//Puke if toxloss is too high
if(!stat)
if(getToxLoss() >= 45 && nutrition > 20)
lastpuke ++
if(lastpuke >= 25) // about 25 second delay I guess
vomit(20, 0, 1, 0, 1, 1)
lastpuke = 0
/mob/living/carbon/human/has_smoke_protection()
if(wear_mask)
if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)
. = 1
if(glasses)
if(glasses.flags & BLOCK_GAS_SMOKE_EFFECT)
. = 1
if(head)
if(head.flags & BLOCK_GAS_SMOKE_EFFECT)
. = 1
if(NOBREATH in dna.species.specflags)
. = 1
return .
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
if(prob(I.embedded_pain_chance))
BP.take_damage(I.w_class*I.embedded_pain_multiplier)
src << "<span class='userdanger'>\the [I] embedded in your [BP.name] hurts!</span>"
if(prob(I.embedded_fall_chance))
BP.take_damage(I.w_class*I.embedded_fall_pain_multiplier)
BP.embedded_objects -= I
I.loc = get_turf(src)
visible_message("<span class='danger'>\the [I] falls out of [name]'s [BP.name]!</span>","<span class='userdanger'>\the [I] falls out of your [BP.name]!</span>")
if(!has_embedded_objects())
clear_alert("embeddedobject")
/mob/living/carbon/human/proc/handle_heart()
CHECK_DNA_AND_SPECIES(src)
var/needs_heart = (!(NOBLOOD in dna.species.specflags))
var/we_breath = (!(NOBREATH in dna.species.specflags))
if(heart_attack)
if(!needs_heart)
heart_attack = FALSE
else if(we_breath)
if(losebreath < 3)
losebreath += 2
adjustOxyLoss(5)
adjustBruteLoss(1)
else
// even though we don't require oxygen, our blood still needs
// circulation, and without it, our tissues die and start
// gaining toxins
adjustBruteLoss(3)
if(src.reagents)
src.reagents.add_reagent("toxin", 2)
/*
Alcohol Poisoning Chart
Note that all higher effects of alcohol poisoning will inherit effects for smaller amounts (i.e. light poisoning inherts from slight poisoning)
In addition, severe effects won't always trigger unless the drink is poisonously strong
All effects don't start immediately, but rather get worse over time; the rate is affected by the imbiber's alcohol tolerance
0: Non-alcoholic
1-10: Barely classifiable as alcohol - occassional slurring
11-20: Slight alcohol content - slurring
21-30: Below average - imbiber begins to look slightly drunk
31-40: Just below average - no unique effects
41-50: Average - mild disorientation, imbiber begins to look drunk
51-60: Just above average - disorientation, vomiting, imbiber begins to look heavily drunk
61-70: Above average - small chance of blurry vision, imbiber begins to look smashed
71-80: High alcohol content - blurry vision, imbiber completely shitfaced
81-90: Extremely high alcohol content - light brain damage, passing out
91-100: Dangerously toxic - swift death
*/
/mob/living/carbon/human/handle_status_effects()
..()
if(drunkenness)
if(sleeping)
drunkenness = max(drunkenness - (drunkenness / 10), 0)
else
drunkenness = max(drunkenness - (drunkenness / 25), 0)
if(drunkenness >= 6)
if(prob(25))
slurring += 2
jitteriness = max(jitteriness - 3, 0)
if(drunkenness >= 11 && slurring < 5)
slurring += 1.2
if(drunkenness >= 41)
if(prob(25))
confused += 2
Dizzy(10)
if(drunkenness >= 51)
if(prob(5))
confused += 10
vomit()
Dizzy(25)
if(drunkenness >= 61)
if(prob(50))
blur_eyes(5)
if(drunkenness >= 71)
blur_eyes(5)
if(drunkenness >= 81)
adjustToxLoss(0.2)
if(prob(5) && !stat)
src << "<span class='warning'>Maybe you should lie down for a bit...</span>"
if(drunkenness >= 91)
adjustBrainLoss(0.4)
if(prob(20) && !stat)
if(SSshuttle.emergency.mode == SHUTTLE_DOCKED && z == ZLEVEL_STATION) //QoL mainly
src << "<span class='warning'>You're so tired... but you can't miss that shuttle...</span>"
else
src << "<span class='warning'>Just a quick nap...</span>"
Sleeping(45)
if(drunkenness >= 101)
adjustToxLoss(4) //Let's be honest you shouldn't be alive by now
#undef HUMAN_MAX_OXYLOSS
+134
View File
@@ -0,0 +1,134 @@
/mob/living/carbon/human/say_quote(input, spans)
if(!input)
return "says, \"...\"" //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
verb_say = dna.species.say_mod
if(src.slurring)
input = attach_spans(input, spans)
return "slurs, \"[input]\""
return ..()
/mob/living/carbon/human/treat_message(message)
message = dna.species.handle_speech(message,src)
if(viruses.len)
for(var/datum/disease/pierrot_throat/D in viruses)
var/list/temp_message = splittext(message, " ") //List each word in the message
var/list/pick_list = list()
for(var/i = 1, i <= temp_message.len, i++) //Create a second list for excluding words down the line
pick_list += i
for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words
if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12%
var/H = pick(pick_list)
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
temp_message[H] = "HONK"
pick_list -= H //Make sure that you dont HONK the same word twice
message = jointext(temp_message, " ")
message = ..(message)
message = dna.mutations_say_mods(message)
return message
/mob/living/carbon/human/get_spans()
return ..() | dna.mutations_get_spans() | dna.species_get_spans()
/mob/living/carbon/human/GetVoice()
if(istype(wear_mask, /obj/item/clothing/mask/chameleon))
var/obj/item/clothing/mask/chameleon/V = wear_mask
if(V.vchange && wear_id)
var/obj/item/weapon/card/id/idcard = wear_id.GetID()
if(istype(idcard))
return idcard.registered_name
else
return real_name
else
return real_name
if(mind && mind.changeling && mind.changeling.mimicing)
return mind.changeling.mimicing
if(GetSpecialVoice())
return GetSpecialVoice()
return real_name
/mob/living/carbon/human/IsVocal()
CHECK_DNA_AND_SPECIES(src)
// how do species that don't breathe talk? magic, that's what.
if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs"))
return 0
if(mind)
return !mind.miming
return 1
/mob/living/carbon/human/proc/SetSpecialVoice(new_voice)
if(new_voice)
special_voice = new_voice
return
/mob/living/carbon/human/proc/UnsetSpecialVoice()
special_voice = ""
return
/mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice
/mob/living/carbon/human/binarycheck()
if(ears)
var/obj/item/device/radio/headset/dongle = ears
if(!istype(dongle)) return 0
if(dongle.translate_binary) return 1
/mob/living/carbon/human/radio(message, message_mode, list/spans)
. = ..()
if(. != 0)
return .
switch(message_mode)
if(MODE_HEADSET)
if (ears)
ears.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
if(MODE_DEPARTMENT)
if (ears)
ears.talk_into(src, message, message_mode, spans)
return ITALICS | REDUCE_RANGE
if(message_mode in radiochannels)
if(ears)
ears.talk_into(src, message, message_mode, spans)
return ITALICS | REDUCE_RANGE
return 0
/mob/living/carbon/human/get_alt_name()
if(name != GetVoice())
return " (as [get_id_name("Unknown")])"
/mob/living/carbon/human/proc/forcesay(list/append) //this proc is at the bottom of the file because quote fuckery makes notepad++ cri
if(stat == CONSCIOUS)
if(client)
var/virgin = 1 //has the text been modified yet?
var/temp = winget(client, "input", "text")
if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //"case sensitive means
temp = replacetext(temp, ";", "") //general radio
if(findtext(trim_left(temp), ":", 6, 7)) //dept radio
temp = copytext(trim_left(temp), 8)
virgin = 0
if(virgin)
temp = copytext(trim_left(temp), 6) //normal speech
virgin = 0
while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary)
temp = copytext(trim_left(temp), 3)
if(findtext(temp, "*", 1, 2)) //emotes
return
var/trimmed = trim_left(temp)
if(length(trimmed))
if(append)
temp += pick(append)
say(temp)
winset(client, "input", "text=[null]")
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,606 @@
///////////////////////
//UPDATE_ICONS SYSTEM//
///////////////////////
/* Keep these comments up-to-date if you -insist- on hurting my code-baby ;_;
This system allows you to update individual mob-overlays, without regenerating them all each time.
When we generate overlays we generate the standing version and then rotate the mob as necessary..
As of the time of writing there are 20 layers within this list. Please try to keep this from increasing. //22 and counting, good job guys
var/overlays_standing[20] //For the standing stance
Most of the time we only wish to update one overlay:
e.g. - we dropped the fireaxe out of our left hand and need to remove its icon from our mob
e.g.2 - our hair colour has changed, so we need to update our hair icons on our mob
In these cases, instead of updating every overlay using the old behaviour (regenerate_icons), we instead call
the appropriate update_X proc.
e.g. - update_l_hand()
e.g.2 - update_hair()
Note: Recent changes by aranclanos+carn:
update_icons() no longer needs to be called.
the system is easier to use. update_icons() should not be called unless you absolutely -know- you need it.
IN ALL OTHER CASES it's better to just call the specific update_X procs.
Note: The defines for layer numbers is now kept exclusvely in __DEFINES/misc.dm instead of being defined there,
then redefined and undefiend everywhere else. If you need to change the layering of sprites (or add a new layer)
that's where you should start.
All of this means that this code is more maintainable, faster and still fairly easy to use.
There are several things that need to be remembered:
> Whenever we do something that should cause an overlay to update (which doesn't use standard procs
( i.e. you do something like l_hand = /obj/item/something new(src), rather than using the helper procs)
You will need to call the relevant update_inv_* proc
All of these are named after the variable they update from. They are defined at the mob/ level like
update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a
slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such.
> There are also these special cases:
update_damage_overlays() //handles damage overlays for brute/burn damage
update_body() //Handles updating your mob's body layer and mutant bodyparts
as well as sprite-accessories that didn't really fit elsewhere (underwear, undershirts, socks, lips, eyes)
//NOTE: update_mutantrace() is now merged into this!
update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and
eyes were merged into update_body())
*/
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
/mob/living/carbon/human/update_damage_overlays()
remove_overlay(DAMAGE_LAYER)
var/image/standing = image("icon"='icons/mob/dam_human.dmi', "icon_state"="blank", "layer"=-DAMAGE_LAYER)
overlays_standing[DAMAGE_LAYER] = standing
var/dmgoverlaytype = ""
if(dna.species.exotic_damage_overlay)
dmgoverlaytype = dna.species.exotic_damage_overlay + "_"
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.brutestate)
standing.overlays += "[dmgoverlaytype][BP.body_zone]_[BP.brutestate]0" //we're adding icon_states of the base image as overlays
if(BP.burnstate)
standing.overlays += "[dmgoverlaytype][BP.body_zone]_0[BP.burnstate]"
apply_overlay(DAMAGE_LAYER)
//HAIR OVERLAY
/mob/living/carbon/human/update_hair()
dna.species.handle_hair(src)
//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/proc/update_mutant_bodyparts()
dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/proc/update_body()
remove_overlay(BODY_LAYER)
dna.species.handle_body(src)
update_body_parts()
/mob/living/carbon/human/update_fire()
..("Standing")
/mob/living/carbon/human/proc/update_body_parts()
//CHECK FOR UPDATE
var/oldkey = icon_render_key
icon_render_key = generate_icon_render_key()
if(oldkey == icon_render_key)
return
remove_overlay(BODYPARTS_LAYER)
//LOAD ICONS
if(limb_icon_cache[icon_render_key])
load_limb_from_cache()
update_damage_overlays()
update_mutant_bodyparts()
update_hair()
return
//GENERATE NEW LIMBS
var/list/new_limbs = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(!BP.no_update)
BP.update_limb()
var/image/temp = BP.get_limb_icon()
if(temp)
new_limbs += temp
if(new_limbs.len)
overlays_standing[BODYPARTS_LAYER] = new_limbs
limb_icon_cache[icon_render_key] = new_limbs
apply_overlay(BODYPARTS_LAYER)
update_damage_overlays()
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
if(!..())
update_body()
update_hair()
update_inv_w_uniform()
update_inv_wear_id()
update_inv_gloves()
update_inv_glasses()
update_inv_ears()
update_inv_shoes()
update_inv_s_store()
update_inv_wear_mask()
update_inv_head()
update_inv_belt()
update_inv_back()
update_inv_wear_suit()
update_inv_pockets()
update_transform()
//mutations
update_mutations_overlay()
//damage overlays
update_damage_overlays()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform()
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_w_uniform]
inv.update_icon()
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
U.screen_loc = ui_iclothing //...draw the item in the inventory screen
client.screen += w_uniform //Either way, add the item to the HUD
if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
return
var/t_color = U.item_color
if(!t_color)
t_color = U.icon_state
if(U.adjusted)
t_color = "[t_color]_d"
var/image/standing
if(dna && dna.species.sexes)
var/G = (gender == FEMALE) ? "f" : "m"
if(G == "f" && U.fitted != NO_FEMALE_UNIFORM)
standing = U.build_worn_icon(state = "[t_color]_s", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE, femaleuniform = U.fitted)
if(!standing)
standing = U.build_worn_icon(state = "[t_color]_s", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE)
overlays_standing[UNIFORM_LAYER] = standing
else
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
for(var/obj/item/thing in list(r_store, l_store, wear_id, belt)) //
unEquip(thing)
apply_overlay(UNIFORM_LAYER)
/mob/living/carbon/human/update_inv_wear_id()
remove_overlay(ID_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id]
inv.update_icon()
if(wear_id)
if(client && hud_used && hud_used.hud_shown)
wear_id.screen_loc = ui_id
client.screen += wear_id
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
var/image/standing = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi')
overlays_standing[ID_LAYER] = standing
apply_overlay(ID_LAYER)
/mob/living/carbon/human/update_inv_gloves()
remove_overlay(GLOVES_LAYER)
if(get_num_arms() <2)
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves]
inv.update_icon()
if(gloves)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
gloves.screen_loc = ui_gloves //...draw the item in the inventory screen
client.screen += gloves //Either way, add the item to the HUD
var/t_state = gloves.item_state
if(!t_state)
t_state = gloves.icon_state
var/image/standing = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/hands.dmi')
overlays_standing[GLOVES_LAYER] = standing
else
if(blood_DNA)
overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands", "layer"=-GLOVES_LAYER)
apply_overlay(GLOVES_LAYER)
/mob/living/carbon/human/update_inv_glasses()
remove_overlay(GLASSES_LAYER)
if(!get_bodypart("head")) //decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_glasses]
inv.update_icon()
if(glasses)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
client.screen += glasses //Either way, add the item to the HUD
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
var/image/standing = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi')
overlays_standing[GLASSES_LAYER] = standing
apply_overlay(GLASSES_LAYER)
/mob/living/carbon/human/update_inv_ears()
remove_overlay(EARS_LAYER)
if(!get_bodypart("head")) //decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_ears]
inv.update_icon()
if(ears)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
ears.screen_loc = ui_ears //...draw the item in the inventory screen
client.screen += ears //Either way, add the item to the HUD
var/image/standing = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
overlays_standing[EARS_LAYER] = standing
apply_overlay(EARS_LAYER)
/mob/living/carbon/human/update_inv_shoes()
remove_overlay(SHOES_LAYER)
if(get_num_legs() <2)
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_shoes]
inv.update_icon()
if(shoes)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
shoes.screen_loc = ui_shoes //...draw the item in the inventory screen
client.screen += shoes //Either way, add the item to the HUD
var/image/standing = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
overlays_standing[SHOES_LAYER] = standing
apply_overlay(SHOES_LAYER)
/mob/living/carbon/human/update_inv_s_store()
remove_overlay(SUIT_STORE_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_s_store]
inv.update_icon()
if(s_store)
if(client && hud_used && hud_used.hud_shown)
s_store.screen_loc = ui_sstore1
client.screen += s_store
var/t_state = s_store.item_state
if(!t_state)
t_state = s_store.icon_state
overlays_standing[SUIT_STORE_LAYER] = image("icon"='icons/mob/belt_mirror.dmi', "icon_state"="[t_state]", "layer"=-SUIT_STORE_LAYER)
apply_overlay(SUIT_STORE_LAYER)
/mob/living/carbon/human/update_inv_head()
remove_overlay(HEAD_LAYER)
if(!get_bodypart("head")) //Decapitated
return
..()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head]
inv.update_icon()
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt]
inv.update_icon()
if(hud_used.hud_shown && belt)
client.screen += belt
belt.screen_loc = ui_belt
if(belt)
var/t_state = belt.item_state
if(!t_state)
t_state = belt.icon_state
var/image/standing = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = 'icons/mob/belt.dmi')
overlays_standing[BELT_LAYER] = standing
apply_overlay(BELT_LAYER)
/mob/living/carbon/human/update_inv_wear_suit()
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit]
inv.update_icon()
if(istype(wear_suit, /obj/item/clothing/suit))
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
client.screen += wear_suit //Either way, add the item to the HUD
var/image/standing = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/suit.dmi')
overlays_standing[SUIT_LAYER] = standing
if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket))
drop_l_hand()
drop_r_hand()
update_hair()
update_mutant_bodyparts()
apply_overlay(SUIT_LAYER)
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
var/obj/screen/inventory/inv
inv = hud_used.inv_slots[slot_l_store]
inv.update_icon()
inv = hud_used.inv_slots[slot_r_store]
inv.update_icon()
if(hud_used.hud_shown)
if(l_store)
client.screen += l_store
l_store.screen_loc = ui_storage1
if(r_store)
client.screen += r_store
r_store.screen_loc = ui_storage2
/mob/living/carbon/human/update_inv_wear_mask()
remove_overlay(FACEMASK_LAYER)
if(!get_bodypart("head")) //Decapitated
return
..()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask]
inv.update_icon()
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
if(handcuffed)
overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
/mob/living/carbon/human/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
clear_alert("legcuffed")
if(legcuffed)
overlays_standing[LEGCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="legcuff1", "layer"=-LEGCUFF_LAYER)
apply_overlay(LEGCUFF_LAYER)
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
/proc/wear_female_version(t_color, icon, layer, type)
var/index = t_color
var/icon/female_clothing_icon = female_clothing_icons[index]
if(!female_clothing_icon) //Create standing/laying icons if they don't exist
generate_female_clothing(index,t_color,icon,type)
var/standing = image("icon"=female_clothing_icons["[t_color]"], "layer"=-layer)
return(standing)
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
var/list/out = new
for(var/i=1;i<=TOTAL_LAYERS;i++)
if(overlays_standing[i])
if(i in unwantedLayers)
continue
out += overlays_standing[i]
return out
//human HUD updates for items in our inventory
//update whether our head item appears on our hud.
/mob/living/carbon/human/update_hud_head(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
I.screen_loc = ui_head
client.screen += I
//update whether our mask item appears on our hud.
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
I.screen_loc = ui_mask
client.screen += I
//update whether our back item appears on our hud.
/mob/living/carbon/human/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_back
client.screen += I
/*
Does everything in relation to building the /image used in the mob's overlays list
covers:
inhands and any other form of worn item
centering large images
layering images on custom layers
building images from custom icon files
By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons())
state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code
so it's specified as an argument instead.
default_layer: The layer to draw this on if no other layer is specified
default_icon_file: The icon file to draw states from if no other icon file is specified
isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used,
in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var
femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we
generate/load female uniform sprites matching all previously decided variables
*/
/obj/item/proc/build_worn_icon(var/state = "", var/default_layer = 0, var/default_icon_file = null, var/isinhands = FALSE, var/femaleuniform = NO_FEMALE_UNIFORM)
//Find a valid icon file from variables+arguments
var/file2use
if(!isinhands && alternate_worn_icon)
file2use = alternate_worn_icon
if(!file2use)
file2use = default_icon_file
//Find a valid layer from variables+arguments
var/layer2use
if(alternate_worn_layer)
layer2use = alternate_worn_layer
if(!layer2use)
layer2use = default_layer
var/image/standing
if(femaleuniform)
standing = wear_female_version(state,file2use,layer2use,femaleuniform)
if(!standing)
standing = image("icon"=file2use, "icon_state"=state,"layer"=-layer2use)
//Get the overlay images for this item when it's being worn
//eg: ammo counters, primed grenade flashes, etc.
var/list/worn_overlays = worn_overlays(isinhands)
if(worn_overlays && worn_overlays.len)
standing.overlays.Add(worn_overlays)
standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension)
standing.alpha = alpha
standing.color = color
return standing
/////////////////////
// Limb Icon Cache //
/////////////////////
/*
Called from update_body_parts() these procs handle the limb icon cache.
the limb icon cache adds an icon_render_key to a human mob, it represents:
- skin_tone (if applicable)
- gender
- limbs (stores as the limb name and whether it is removed/fine, organic/robotic)
These procs only store limbs as to increase the number of matching icon_render_keys
This cache exists because drawing 6/7 icons for humans constantly is quite a waste
See RemieRichards on irc.rizon.net #coderbus
*/
var/global/list/limb_icon_cache = list()
/mob/living/carbon/human
var/icon_render_key = ""
//produces a key based on the human's limbs
/mob/living/carbon/human/proc/generate_icon_render_key()
. = "[dna.species.limbs_id]"
if(dna.check_mutation(HULK))
. += "-coloured-hulk"
else if(dna.species.use_skintones)
. += "-coloured-[skin_tone]"
else if(dna.species.fixed_mut_color)
. += "-coloured-[dna.species.fixed_mut_color]"
else if(dna.features["mcolor"])
. += "-coloured-[dna.features["mcolor"]]"
else
. += "-not_coloured"
. += "-[gender]"
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
if(BP.status == ORGAN_ORGANIC)
. += "-organic"
else
. += "-robotic"
if(disabilities & HUSK)
. += "-husk"
//change the human's icon to the one matching it's key
/mob/living/carbon/human/proc/load_limb_from_cache()
if(limb_icon_cache[icon_render_key])
remove_overlay(BODYPARTS_LAYER)
overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key]
apply_overlay(BODYPARTS_LAYER)
@@ -0,0 +1,84 @@
/mob/living/carbon/human/whisper(message as text)
if(!IsVocal())
return
if(!message)
return
if(say_disabled) //This is here to try to identify lag problems
usr << "<span class='danger'>Speech is currently admin-disabled.</span>"
return
if(stat == DEAD)
return
message = trim(html_encode(message))
if(!can_speak(message))
return
message = "[message]"
log_whisper("[src.name]/[src.key] : [message]")
if (src.client)
if (src.client.prefs.muted & MUTE_IC)
src << "<span class='danger'>You cannot whisper (muted).</span>"
return
log_whisper("[src.name]/[src.key] : [message]")
var/alt_name = get_alt_name()
var/whispers = "whispers"
var/critical = InCritical()
// We are unconscious but not in critical, so don't allow them to whisper.
if(stat == UNCONSCIOUS && !critical)
return
// If whispering your last words, limit the whisper based on how close you are to death.
if(critical)
var/health_diff = round(-config.health_threshold_dead + health)
// If we cut our message short, abruptly end it with a-..
var/message_len = length(message)
message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
message = Ellipsis(message, 10, 1)
whispers = "whispers in their final breath"
message = treat_message(message)
var/list/listening_dead = list()
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) || (get_dist(M, src) <= 7)))
listening_dead |= M
var/list/listening = get_hearers_in_view(1, src)
listening |= listening_dead
var/list/eavesdropping = get_hearers_in_view(2, src)
eavesdropping -= listening
var/list/watching = hearers(5, src)
watching -= listening
watching -= eavesdropping
var/rendered
rendered = "<span class='game say'><span class='name'>[src.name]</span> [whispers] something.</span>"
for(var/mob/M in watching)
M.show_message(rendered, 2)
var/spans = list(SPAN_ITALICS)
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] [whispers], <span class='message'>\"[attach_spans(message, spans)]\"</span></span>"
for(var/atom/movable/AM in listening)
if(istype(AM,/obj/item/device/radio))
continue
AM.Hear(rendered, src, languages_spoken, message, , spans)
message = stars(message)
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] [whispers], <span class='message'>\"[attach_spans(message, spans)]\"</span></span>"
for(var/atom/movable/AM in eavesdropping)
if(istype(AM,/obj/item/device/radio))
continue
AM.Hear(rendered, src, languages_spoken, message, , spans)
if(critical) //Dying words.
succumb(1)
+110
View File
@@ -0,0 +1,110 @@
/mob/living/carbon/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_back)
return back
if(slot_wear_mask)
return wear_mask
if(slot_head)
return head
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
return null
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/equip_to_slot(obj/item/I, slot)
if(!slot)
return
if(!istype(I))
return
if(I == l_hand)
l_hand = null
else if(I == r_hand)
r_hand = null
if(I.pulledby)
I.pulledby.stop_pulling()
I.screen_loc = null // will get moved if inventory is visible
I.loc = src
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
switch(slot)
if(slot_back)
back = I
update_inv_back()
if(slot_wear_mask)
wear_mask = I
wear_mask_update(I, toggle_off = 0)
if(slot_head)
head = I
head_update(I)
if(slot_handcuffed)
handcuffed = I
update_handcuffed()
if(slot_legcuffed)
legcuffed = I
update_inv_legcuffed()
if(slot_l_hand)
l_hand = I
update_inv_l_hand()
if(slot_r_hand)
r_hand = I
update_inv_r_hand()
if(slot_in_backpack)
if(I == get_active_hand())
unEquip(I)
I.loc = back
else
return 1
/mob/living/carbon/unEquip(obj/item/I)
. = ..() //Sets the default return value to what the parent returns.
if(!. || !I) //We don't want to set anything to null if the parent returned 0.
return
if(I == head)
head = null
head_update(I)
else if(I == back)
back = null
update_inv_back()
else if(I == wear_mask)
wear_mask = null
wear_mask_update(I, toggle_off = 1)
else if(I == handcuffed)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
buckled.unbuckle_mob(src)
update_handcuffed()
else if(I == legcuffed)
legcuffed = null
update_inv_legcuffed()
//handle stuff to update when a mob equips/unequips a mask.
/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
update_inv_wear_mask()
/mob/living/carbon/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
if(C.tint || initial(C.tint))
update_tint()
update_inv_wear_mask()
//handle stuff to update when a mob equips/unequips a headgear.
/mob/living/carbon/proc/head_update(obj/item/I, forced)
if(istype(I, /obj/item/clothing))
var/obj/item/clothing/C = I
if(C.tint || initial(C.tint))
update_tint()
if(I.flags_inv & HIDEMASK || forced)
update_inv_wear_mask()
update_inv_head()
+398
View File
@@ -0,0 +1,398 @@
/mob/living/carbon/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(!loc)
return
if(damageoverlaytemp)
damageoverlaytemp = 0
update_damage_hud()
if(..())
. = 1
handle_blood()
for(var/obj/item/organ/O in internal_organs)
O.on_life()
//Updates the number of stored chemicals for powers
handle_changeling()
///////////////
// BREATHING //
///////////////
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing()
if(SSmob.times_fired%4==2 || failed_last_breath)
breathe() //Breathe per 4 ticks, unless suffocating
else
if(istype(loc, /obj/))
var/obj/location_as_object = loc
location_as_object.handle_internal_lifeform(src,0)
//Second link in a breath chain, calls check_breath()
/mob/living/carbon/proc/breathe()
if(reagents.has_reagent("lexorin"))
return
if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
return
var/datum/gas_mixture/environment
if(loc)
environment = loc.return_air()
var/datum/gas_mixture/breath
if(health <= config.health_threshold_crit || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube")))
losebreath++
//Suffocate
if(losebreath > 0)
losebreath--
if(prob(10))
emote("gasp")
if(istype(loc, /obj/))
var/obj/loc_as_obj = loc
loc_as_obj.handle_internal_lifeform(src,0)
else
//Breathe from internal
breath = get_breath_from_internal(BREATH_VOLUME)
if(!breath)
if(isobj(loc)) //Breathe from loc as object
var/obj/loc_as_obj = loc
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
else if(isturf(loc)) //Breathe from loc as turf
var/breath_moles = 0
if(environment)
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
else //Breathe from loc as obj again
if(istype(loc, /obj/))
var/obj/loc_as_obj = loc
loc_as_obj.handle_internal_lifeform(src,0)
check_breath(breath)
if(breath)
loc.assume_air(breath)
air_update_turf()
/mob/living/carbon/proc/has_smoke_protection()
return 0
//Third link in a breath chain, calls handle_breath_temperature()
/mob/living/carbon/proc/check_breath(datum/gas_mixture/breath)
if((status_flags & GODMODE))
return
var/lungs = getorganslot("lungs")
if(!lungs)
adjustOxyLoss(2)
//CRIT
if(!breath || (breath.total_moles() == 0) || !lungs)
if(reagents.has_reagent("epinephrine") && lungs)
return
adjustOxyLoss(1)
failed_last_breath = 1
throw_alert("oxy", /obj/screen/alert/oxy)
return 0
var/safe_oxy_min = 16
var/safe_co2_max = 10
var/safe_tox_max = 0.05
var/SA_para_min = 1
var/SA_sleep_min = 5
var/oxygen_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/list/breath_gases = breath.gases
breath.assert_gases("o2","plasma","co2","n2o", "bz")
var/O2_partialpressure = (breath_gases["o2"][MOLES]/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath_gases["plasma"][MOLES]/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath_gases["co2"][MOLES]/breath.total_moles())*breath_pressure
//OXYGEN
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
if(prob(20))
emote("gasp")
if(O2_partialpressure > 0)
var/ratio = safe_oxy_min/O2_partialpressure
adjustOxyLoss(min(5*ratio, 3))
failed_last_breath = 1
oxygen_used = breath_gases["o2"][MOLES]*ratio
else
adjustOxyLoss(3)
failed_last_breath = 1
throw_alert("oxy", /obj/screen/alert/oxy)
else //Enough oxygen
failed_last_breath = 0
if(oxyloss)
adjustOxyLoss(-5)
oxygen_used = breath_gases["o2"][MOLES]
clear_alert("oxy")
breath_gases["o2"][MOLES] -= oxygen_used
breath_gases["co2"][MOLES] += oxygen_used
//CARBON DIOXIDE
if(CO2_partialpressure > safe_co2_max)
if(!co2overloadtime)
co2overloadtime = world.time
else if(world.time - co2overloadtime > 120)
Paralyse(3)
adjustOxyLoss(3)
if(world.time - co2overloadtime > 300)
adjustOxyLoss(8)
if(prob(20))
emote("cough")
else
co2overloadtime = 0
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath_gases["plasma"][MOLES]/safe_tox_max) * 10
if(reagents)
reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE))
throw_alert("tox_in_air", /obj/screen/alert/tox_in_air)
else
clear_alert("tox_in_air")
//NITROUS OXIDE
if(breath_gases["n2o"])
var/SA_partialpressure = (breath_gases["n2o"][MOLES]/breath.total_moles())*breath_pressure
if(SA_partialpressure > SA_para_min)
Paralyse(3)
if(SA_partialpressure > SA_sleep_min)
Sleeping(max(sleeping+2, 10))
else if(SA_partialpressure > 0.01)
if(prob(20))
emote(pick("giggle","laugh"))
//BZ (Facepunch port of their Agent B)
if(breath_gases["bz"])
var/bz_partialpressure = (breath_gases["bz"][MOLES]/breath.total_moles())*breath_pressure
if(bz_partialpressure > 1)
hallucination += 20
else if(bz_partialpressure > 0.01)
hallucination += 5//Removed at 2 per tick so this will slowly build up
breath.garbage_collect()
//BREATH TEMPERATURE
handle_breath_temperature(breath)
return 1
//Fourth and final link in a breath chain
/mob/living/carbon/proc/handle_breath_temperature(datum/gas_mixture/breath)
return
/mob/living/carbon/proc/get_breath_from_internal(volume_needed)
if(internal)
if(internal.loc != src)
internal = null
update_internals_hud_icon(0)
else if ((!wear_mask || !(wear_mask.flags & MASKINTERNALS)) && !getorganslot("breathing_tube"))
internal = null
update_internals_hud_icon(0)
else
update_internals_hud_icon(1)
return internal.remove_air_volume(volume_needed)
/mob/living/carbon/proc/handle_blood()
return
/mob/living/carbon/proc/handle_changeling()
if(mind && hud_used && hud_used.lingchemdisplay)
if(mind.changeling)
mind.changeling.regenerate(src)
hud_used.lingchemdisplay.invisibility = 0
hud_used.lingchemdisplay.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[round(mind.changeling.chem_charges)]</font></div>"
else
hud_used.lingchemdisplay.invisibility = INVISIBILITY_ABSTRACT
/mob/living/carbon/handle_mutations_and_radiation()
if(dna && dna.temporary_mutations.len)
var/datum/mutation/human/HM
for(var/mut in dna.temporary_mutations)
if(dna.temporary_mutations[mut] < world.time)
if(mut == UI_CHANGED)
if(dna.previous["UI"])
dna.uni_identity = merge_text(dna.uni_identity,dna.previous["UI"])
updateappearance(mutations_overlay_update=1)
dna.previous.Remove("UI")
dna.temporary_mutations.Remove(mut)
continue
if(mut == UE_CHANGED)
if(dna.previous["name"])
real_name = dna.previous["name"]
name = real_name
dna.previous.Remove("name")
if(dna.previous["UE"])
dna.unique_enzymes = dna.previous["UE"]
dna.previous.Remove("UE")
if(dna.previous["blood_type"])
dna.blood_type = dna.previous["blood_type"]
dna.previous.Remove("blood_type")
dna.temporary_mutations.Remove(mut)
continue
HM = mutations_list[mut]
HM.force_lose(src)
dna.temporary_mutations.Remove(mut)
if(radiation)
switch(radiation)
if(0 to 50)
radiation = max(radiation-1,0)
if(prob(25))
adjustToxLoss(1)
if(50 to 75)
radiation = max(radiation-2,0)
adjustToxLoss(1)
if(prob(5))
radiation = max(radiation-5,0)
if(75 to 100)
radiation = max(radiation-3,0)
adjustToxLoss(3)
else
radiation = Clamp(radiation, 0, 100)
/mob/living/carbon/handle_chemicals_in_body()
if(reagents)
reagents.metabolize(src)
/mob/living/carbon/handle_stomach()
set waitfor = 0
for(var/mob/living/M in stomach_contents)
if(M.loc != src)
stomach_contents.Remove(M)
continue
if(istype(M, /mob/living/carbon) && stat != DEAD)
if(M.stat == DEAD)
M.death(1)
stomach_contents.Remove(M)
qdel(M)
continue
if(SSmob.times_fired%3==1)
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
//this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
if(staminaloss)
if(sleeping)
adjustStaminaLoss(-10)
else
adjustStaminaLoss(-3)
if(sleeping)
handle_dreams()
AdjustSleeping(-1)
if(prob(10) && health>config.health_threshold_crit)
emote("snore")
var/restingpwr = 1 + 4 * resting
//Dizziness
if(dizziness)
var/client/C = client
var/pixel_x_diff = 0
var/pixel_y_diff = 0
var/temp
var/saved_dizz = dizziness
if(C)
var/oldsrc = src
var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70 // This shit is annoying at high strength
src = null
spawn(0)
if(C)
temp = amplitude * sin(0.008 * saved_dizz * world.time)
pixel_x_diff += temp
C.pixel_x += temp
temp = amplitude * cos(0.008 * saved_dizz * world.time)
pixel_y_diff += temp
C.pixel_y += temp
sleep(3)
if(C)
temp = amplitude * sin(0.008 * saved_dizz * world.time)
pixel_x_diff += temp
C.pixel_x += temp
temp = amplitude * cos(0.008 * saved_dizz * world.time)
pixel_y_diff += temp
C.pixel_y += temp
sleep(3)
if(C)
C.pixel_x -= pixel_x_diff
C.pixel_y -= pixel_y_diff
src = oldsrc
dizziness = max(dizziness - restingpwr, 0)
if(drowsyness)
drowsyness = max(drowsyness - restingpwr, 0)
blur_eyes(2)
if(prob(5))
AdjustSleeping(1)
Paralyse(5)
//Jitteryness
if(jitteriness)
do_jitter_animation(jitteriness)
jitteriness = max(jitteriness - restingpwr, 0)
if(stuttering)
stuttering = max(stuttering-1, 0)
if(slurring)
slurring = max(slurring-1,0)
if(cultslurring)
cultslurring = max(cultslurring-1, 0)
if(silent)
silent = max(silent-1, 0)
if(druggy)
adjust_drugginess(-1)
if(hallucination)
spawn handle_hallucinations()
hallucination = max(hallucination-2,0)
//used in human and monkey handle_environment()
/mob/living/carbon/proc/natural_bodytemperature_stabilization()
var/body_temperature_difference = 310.15 - bodytemperature
switch(bodytemperature)
if(-INFINITY to 260.15) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
nutrition -= 2
bodytemperature += max((body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
if(260.15 to 310.15)
bodytemperature += max(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, min(body_temperature_difference, BODYTEMP_AUTORECOVERY_MINIMUM/4))
if(310.15 to 360.15)
bodytemperature += min(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, max(body_temperature_difference, -BODYTEMP_AUTORECOVERY_MINIMUM/4))
if(360.15 to INFINITY) //360.15 is 310.15 + 50, the temperature where you start to feel effects.
//We totally need a sweat system cause it totally makes sense...~
bodytemperature += min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers
@@ -0,0 +1,19 @@
/mob/living/carbon/monkey/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-m"))
/mob/living/carbon/monkey/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-m"))
/mob/living/carbon/monkey/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
if(!gibbed)
emote("deathgasp")
if(ticker && ticker.mode)
ticker.mode.check_win()
return ..(gibbed)
@@ -0,0 +1,82 @@
/mob/living/carbon/monkey/emote(act,m_type=1,message = null)
if(stat == DEAD && (act != "deathgasp") || (status_flags & FAKEDEATH)) //if we're faking, don't emote at all
return
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
switch(act) //Ooh ooh ah ah keep this alphabetical ooh ooh ah ah!
if ("deathgasp","deathgasps")
message = "<b>[src]</b> lets out a faint chimper as it collapses and stops moving..."
m_type = 1
if ("gnarl","gnarls")
if (!muzzled)
message = "<B>[src]</B> gnarls and shows its teeth.."
m_type = 2
if ("me")
..()
return
if ("moan","moans")
message = "<B>[src]</B> moans!"
m_type = 2
if ("paw")
if (!src.restrained())
message = "<B>[src]</B> flails its paw."
m_type = 1
if ("roar","roars")
if (!muzzled)
message = "<B>[src]</B> roars."
m_type = 2
if ("roll","rolls")
if (!src.restrained())
message = "<B>[src]</B> rolls."
m_type = 1
if ("scratch","scratches")
if (!src.restrained())
message = "<B>[src]</B> scratches."
m_type = 1
if ("screech","screeches")
if (!muzzled)
message = "<B>[src]</B> screeches."
m_type = 2
if ("shiver","shivers")
message = "<B>[src]</B> shivers."
m_type = 2
if ("sign","signs")
if (!src.restrained())
message = text("<B>[src]</B> signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null))
m_type = 1
if ("tail")
message = "<B>[src]</B> waves its tail."
m_type = 1
if ("help") //Ooh ah ooh ooh this is an exception to alphabetical ooh ooh.
src << "Help for monkey emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, gnarl, giggle, glare-(none)/mob, grin, jump, laugh, look, me, moan, nod, paw, point-(atom), roar, roll, scream, scratch, screech, shake, shiver, sigh, sign-#, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tail, tremble, twitch, twitch_s, wave whimper, wink, yawn"
else
..()
if ((message && src.stat == 0))
if(src.client)
log_emote("[name]/[key] : [message]")
if (m_type & 1)
visible_message(message)
else
audible_message(message)
return
@@ -0,0 +1,32 @@
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = 0)
switch(slot)
if(slot_l_hand)
if(l_hand)
return 0
return 1
if(slot_r_hand)
if(r_hand)
return 0
return 1
if(slot_wear_mask)
if(wear_mask)
return 0
if( !(I.slot_flags & SLOT_MASK) )
return 0
return 1
if(slot_head)
if(head)
return 0
if( !(I.slot_flags & SLOT_HEAD) )
return 0
return 1
if(slot_back)
if(back)
return 0
if( !(I.slot_flags & SLOT_BACK) )
return 0
return 1
return 0 //Unsupported slot
@@ -0,0 +1,146 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/monkey
/mob/living/carbon/monkey/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
..()
if(!client && stat == CONSCIOUS)
if(prob(33) && canmove && isturf(loc) && !pulledby)
step(src, pick(cardinal))
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if (radiation)
if (radiation > 100)
Weaken(10)
src << "<span class='danger'>You feel weak.</span>"
emote("collapse")
switch(radiation)
if(50 to 75)
if(prob(5))
Weaken(3)
src << "<span class='danger'>You feel weak.</span>"
emote("collapse")
if(75 to 100)
if(prob(1))
src << "<span class='danger'>You mutate!</span>"
randmutb(src)
emote("gasp")
domutcheck()
..()
/mob/living/carbon/monkey/handle_chemicals_in_body()
if(reagents)
reagents.metabolize(src, can_overdose=1)
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
if(abs(310.15 - breath.temperature) > 50)
switch(breath.temperature)
if(-INFINITY to 120)
adjustFireLoss(3)
if(120 to 200)
adjustFireLoss(1.5)
if(200 to 260)
adjustFireLoss(0.5)
if(360 to 400)
adjustFireLoss(2)
if(400 to 1000)
adjustFireLoss(3)
if(1000 to INFINITY)
adjustFireLoss(8)
/mob/living/carbon/monkey/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
if(stat != DEAD)
natural_bodytemperature_stabilization()
if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
if(loc_temp < bodytemperature)
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX)
else
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX)
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
switch(bodytemperature)
if(360 to 400)
throw_alert("temp", /obj/screen/alert/hot, 1)
adjustFireLoss(2)
if(400 to 460)
throw_alert("temp", /obj/screen/alert/hot, 2)
adjustFireLoss(3)
if(460 to INFINITY)
throw_alert("temp", /obj/screen/alert/hot, 3)
if(on_fire)
adjustFireLoss(8)
else
adjustFireLoss(3)
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
throw_alert("temp", /obj/screen/alert/cold, 1)
adjustFireLoss(0.5)
if(120 to 200)
throw_alert("temp", /obj/screen/alert/cold, 2)
adjustFireLoss(1.5)
if(-INFINITY to 120)
throw_alert("temp", /obj/screen/alert/cold, 3)
adjustFireLoss(3)
else
clear_alert("temp")
else
clear_alert("temp")
//Account for massive pressure differences
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
switch(adjusted_pressure)
if(HAZARD_HIGH_PRESSURE to INFINITY)
adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
clear_alert("pressure")
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
else
adjustBruteLoss( LOW_PRESSURE_DAMAGE )
throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
return
/mob/living/carbon/monkey/handle_random_events()
if (prob(1) && prob(2))
emote("scratch")
/mob/living/carbon/monkey/has_smoke_protection()
if(wear_mask)
if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)
return 1
/mob/living/carbon/monkey/handle_fire()
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX
return
@@ -0,0 +1,323 @@
/mob/living/carbon/monkey
name = "monkey"
voice_name = "monkey"
verb_say = "chimpers"
icon = 'icons/mob/monkey.dmi'
icon_state = "monkey1"
gender = NEUTER
pass_flags = PASSTABLE
languages_spoken = MONKEY
languages_understood = MONKEY
ventcrawler = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
/mob/living/carbon/monkey/New()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
if(unique_name) //used to exclude pun pun
gender = pick(MALE, FEMALE)
real_name = name
//initialize limbs, currently only used to handle cavity implant surgery, no dismemberment.
bodyparts = newlist(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm,
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
for(var/X in bodyparts)
var/obj/item/bodypart/O = X
O.owner = src
if(good_mutations.len) //genetic mutations have been set up.
initialize()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs
internal_organs += new /obj/item/organ/heart
internal_organs += new /obj/item/organ/brain
internal_organs += new /obj/item/organ/tongue
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
..()
/mob/living/carbon/monkey/initialize()
create_dna(src)
dna.initialize_dna(random_blood_type())
/mob/living/carbon/monkey/movement_delay()
if(reagents)
if(reagents.has_reagent("morphine"))
return -1
if(reagents.has_reagent("nuka_cola"))
return -1
. = ..()
var/health_deficiency = (100 - health)
if(health_deficiency >= 45)
. += (health_deficiency / 25)
if (bodytemperature < 283.222)
. += (283.222 - bodytemperature) / 10 * 1.75
return . + config.monkey_delay
/mob/living/carbon/monkey/attack_paw(mob/living/M)
if(..()) //successful monkey bite.
var/damage = rand(1, 5)
if (stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
if(..()) //To allow surgery to return properly.
return
switch(M.a_intent)
if("help")
help_shake_act(M)
if("grab")
grabbedby(M)
if("harm")
M.do_attack_animation(src)
if (prob(75))
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
"<span class='userdanger'>[M] has punched [name]!</span>")
playsound(loc, "punch", 25, 1, -1)
var/damage = rand(5, 10)
if (prob(40))
damage = rand(10, 15)
if ( (paralysis < 5) && (health > 0) )
Paralyse(rand(10, 15))
visible_message("<span class='danger'>[M] has knocked out [name]!</span>", \
"<span class='userdanger'>[M] has knocked out [name]!</span>")
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [name]!</span>")
if("disarm")
if (!( paralysis ))
M.do_attack_animation(src)
if (prob(25))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
if(drop_item())
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>")
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if (M.a_intent == "harm")
if ((prob(95) && health > 0))
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/damage = rand(15, 30)
if (damage >= 25)
damage = rand(20, 40)
if (paralysis < 15)
Paralyse(rand(10, 15))
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>[M] has wounded [name]!</span>")
else
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>")
if (stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
add_logs(M, src, "attacked")
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>")
if (M.a_intent == "disarm")
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Weaken(10)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>")
else
if(drop_item())
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", \
"<span class='userdanger'>[M] has disarmed [name]!</span>")
add_logs(M, src, "disarmed")
updatehealth()
return
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/monkey/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(client && mind)
if(mind.changeling)
stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]")
stat("Absorbed DNA", mind.changeling.absorbedcount)
return
/mob/living/carbon/monkey/verb/removeinternal()
set name = "Remove Internals"
set category = "IC"
internal = null
return
/mob/living/carbon/monkey/ex_act(severity, target)
..()
switch(severity)
if(1)
gib()
return
if(2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(10)
adjustEarDamage(15,60)
updatehealth()
return
/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
return 0
/mob/living/carbon/monkey/reagent_check(datum/reagent/R) //can metabolize all reagents
return 0
/mob/living/carbon/monkey/canBeHandcuffed()
return 1
/mob/living/carbon/monkey/assess_threat(mob/living/simple_animal/bot/secbot/judgebot, lasercolor)
if(judgebot.emagged == 2)
return 10 //Everyone is a criminal!
var/threatcount = 0
//Securitrons can't identify monkeys
if(!lasercolor && judgebot.idcheck )
threatcount += 4
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag)))
threatcount += 4
if(lasercolor == "r")
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag)))
threatcount += 4
return threatcount
//Check for weapons
if(judgebot.weaponscheck)
if(judgebot.check_for_weapons(l_hand))
threatcount += 4
if(judgebot.check_for_weapons(r_hand))
threatcount += 4
//mindshield implants imply trustworthyness
if(isloyal(src))
threatcount -= 1
return threatcount
/mob/living/carbon/monkey/acid_act(acidpwr, toxpwr, acid_volume)
if(wear_mask)
if(!wear_mask.unacidable)
wear_mask.acid_act(acidpwr)
update_inv_wear_mask()
else
src << "<span class='warning'>Your mask protects you from the acid.</span>"
return
take_organ_damage(min(6*toxpwr, acid_volume * acidpwr/10))
/mob/living/carbon/monkey/help_shake_act(mob/living/carbon/M)
if(health < 0 && ishuman(M))
var/mob/living/carbon/human/H = M
H.do_cpr(src)
else
..()
/mob/living/carbon/monkey/get_permeability_protection()
var/protection = 0
if(head)
protection = 1 - head.permeability_coefficient
if(wear_mask)
protection = max(1 - wear_mask.permeability_coefficient, protection)
protection = protection/7 //the rest of the body isn't covered.
return protection
/mob/living/carbon/monkey/check_eye_prot()
var/number = ..()
if(istype(src.wear_mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
return number
/mob/living/carbon/monkey/fully_heal(admin_revive = 0)
if(!getorganslot("lungs"))
var/obj/item/organ/lungs/L = new()
L.Insert(src)
if(!getorganslot("tongue"))
var/obj/item/organ/tongue/T = new()
T.Insert(src)
..()
/mob/living/carbon/monkey/IsVocal()
if(!getorganslot("lungs"))
return 0
return 1
/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/gun/G)
return 1
@@ -0,0 +1,69 @@
/mob/living/carbon/monkey/punpun //except for a few special persistence features, pun pun is just a normal monkey
name = "Pun Pun" //C A N O N
unique_name = 0
var/ancestor_name
var/ancestor_chain = 1
var/relic_hat //Note: these two are paths
var/relic_mask
var/memory_saved = 0
var/list/pet_monkey_names = list("Pun Pun", "Bubbles", "Mojo", "George", "Darwin", "Aldo", "Caeser", "Kanzi", "Kong", "Terk", "Grodd", "Mala", "Bojangles", "Coco", "Able", "Baker", "Scatter", "Norbit", "Travis")
var/list/rare_pet_monkey_names = list("Professor Bobo", "Deempisi's Revenge", "Furious George", "King Louie", "Dr. Zaius", "Jimmy Rustles", "Dinner", "Lanky")
/mob/living/carbon/monkey/punpun/New()
Read_Memory()
if(relic_hat)
equip_to_slot_or_del(new relic_hat, slot_head)
if(relic_mask)
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
if(ancestor_name)
name = ancestor_name
if(ancestor_chain > 1)
name += " [num2roman(ancestor_chain)]"
else
if(prob(5))
name = pick(rare_pet_monkey_names)
else
name = pick(pet_monkey_names)
gender = pick(MALE, FEMALE)
..()
/mob/living/carbon/monkey/punpun/Life()
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
..()
/mob/living/carbon/monkey/punpun/death(gibbed)
if(!memory_saved || gibbed)
Write_Memory(1,gibbed)
..()
/mob/living/carbon/monkey/punpun/proc/Read_Memory()
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
S["ancestor_name"] >> ancestor_name
S["ancestor_chain"] >> ancestor_chain
S["relic_hat"] >> relic_hat
S["relic_mask"] >> relic_mask
/mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed)
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
if(gibbed)
S["ancestor_name"] << null
S["ancestor_chain"] << 1
S["relic_hat"] << null
S["relic_mask"] << null
return
if(dead)
S["ancestor_name"] << ancestor_name
S["ancestor_chain"] << ancestor_chain + 1
if(!ancestor_name) //new monkey name this round
S["ancestor_name"] << name
if(head)
S["relic_hat"] << head.type
else
S["relic_hat"] << null
if(wear_mask)
S["relic_mask"] << wear_mask.type
else
S["relic_mask"] << null
if(!dead)
memory_saved = 1
@@ -0,0 +1,54 @@
/mob/living/carbon/monkey/regenerate_icons()
if(!..())
update_inv_wear_mask()
update_inv_head()
update_inv_back()
update_icons()
update_transform()
/mob/living/carbon/monkey/update_icons()
cut_overlays()
icon_state = "monkey1"
for(var/image/I in overlays_standing)
add_overlay(I)
////////
/mob/living/carbon/monkey/update_fire()
..("Monkey_burning")
/mob/living/carbon/monkey/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
if(handcuffed)
overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
/mob/living/carbon/monkey/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
if(legcuffed)
var/image/standing = image("icon"='icons/mob/mob.dmi', "icon_state"="legcuff1", "layer"=-LEGCUFF_LAYER)
standing.pixel_y = 8
overlays_standing[LEGCUFF_LAYER] = standing
apply_overlay(LEGCUFF_LAYER)
//monkey HUD updates for items in our inventory
//update whether our head item appears on our hud.
/mob/living/carbon/monkey/update_hud_head(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_head
client.screen += I
//update whether our mask item appears on our hud.
/mob/living/carbon/monkey/update_hud_wear_mask(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_mask
client.screen += I
//update whether our back item appears on our hud.
/mob/living/carbon/monkey/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_back
client.screen += I
+26
View File
@@ -0,0 +1,26 @@
/mob/living/carbon/treat_message(message)
message = ..(message)
var/obj/item/organ/tongue/T = getorganslot("tongue")
if(!T) //hoooooouaah!
var/regex/tongueless_lower = new("\[gdntke]+", "g")
var/regex/tongueless_upper = new("\[GDNTKE]+", "g")
if(copytext(message, 1, 2) != "*")
message = tongueless_lower.Replace(message, pick("aa","oo","'"))
message = tongueless_upper.Replace(message, pick("AA","OO","'"))
else
message = T.TongueSpeech(message)
if(wear_mask)
message = wear_mask.speechModification(message)
return message
/mob/living/carbon/can_speak_vocal(message)
if(silent)
return 0
return ..()
/mob/living/carbon/get_spans()
. = ..()
var/obj/item/organ/tongue/T = getorganslot("tongue")
if(T)
. |= T.get_spans()
@@ -0,0 +1,79 @@
//Here are the procs used to modify status effects of a mob.
//The effects include: stunned, weakened, paralysis, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, and NEARSIGHT disability.
/mob/living/carbon/damage_eyes(amount)
if(amount>0)
eye_damage = amount
if(eye_damage > 20)
if(eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
/mob/living/carbon/set_eye_damage(amount)
eye_damage = max(amount,0)
if(eye_damage > 20)
if(eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("eye_damage")
/mob/living/carbon/adjust_eye_damage(amount)
eye_damage = max(eye_damage+amount, 0)
if(eye_damage > 20)
if(eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("eye_damage")
/mob/living/carbon/adjust_drugginess(amount)
var/old_druggy = druggy
if(amount>0)
druggy += amount
if(!old_druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else if(old_druggy)
druggy = max(druggy+amount, 0)
if(!druggy)
clear_fullscreen("high")
clear_alert("high")
/mob/living/carbon/set_drugginess(amount)
var/old_druggy = druggy
druggy = amount
if(amount>0)
if(!old_druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else if(old_druggy)
clear_fullscreen("high")
clear_alert("high")
/mob/living/carbon/cure_blind()
if(disabilities & BLIND)
disabilities &= ~BLIND
adjust_blindness(-1)
return 1
/mob/living/carbon/become_blind()
if(!(disabilities & BLIND))
disabilities |= BLIND
blind_eyes(1)
return 1
/mob/living/carbon/cure_nearsighted()
if(disabilities & NEARSIGHT)
disabilities &= ~NEARSIGHT
clear_fullscreen("nearsighted")
return 1
/mob/living/carbon/become_nearsighted()
if(!(disabilities & NEARSIGHT))
disabilities |= NEARSIGHT
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
return 1
@@ -0,0 +1,163 @@
//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
/mob/living/carbon/update_transform()
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/final_pixel_y = pixel_y
var/final_dir = dir
var/changed = 0
if(lying != lying_prev && rotate_on_lying)
changed++
ntransform.TurnTo(lying_prev,lying)
if(lying == 0) //Lying to standing
final_pixel_y = get_standard_pixel_y_offset()
else //if(lying != 0)
if(lying_prev == 0) //Standing to lying
pixel_y = get_standard_pixel_y_offset()
final_pixel_y = get_standard_pixel_y_offset(lying)
if(dir & (EAST|WEST)) //Facing east or west
final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
lying_prev = lying //so we don't try to animate until there's been another change.
if(resize != RESIZE_DEFAULT_SIZE)
changed++
ntransform.Scale(resize)
resize = RESIZE_DEFAULT_SIZE
if(changed)
animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
/mob/living/carbon/proc/apply_overlay(cache_index)
var/image/I = overlays_standing[cache_index]
if(I)
add_overlay(I)
/mob/living/carbon/proc/remove_overlay(cache_index)
if(overlays_standing[cache_index])
overlays -= overlays_standing[cache_index]
overlays_standing[cache_index] = null
/mob/living/carbon/update_inv_r_hand()
remove_overlay(R_HAND_LAYER)
if (handcuffed)
drop_r_hand()
return
if(r_hand)
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
r_hand.screen_loc = ui_rhand
client.screen += r_hand
var/t_state = r_hand.item_state
if(!t_state)
t_state = r_hand.icon_state
var/image/standing = r_hand.build_worn_icon(state = t_state, default_layer = R_HAND_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
overlays_standing[R_HAND_LAYER] = standing
apply_overlay(R_HAND_LAYER)
/mob/living/carbon/update_inv_l_hand()
remove_overlay(L_HAND_LAYER)
if(handcuffed)
drop_l_hand()
return
if(l_hand)
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
l_hand.screen_loc = ui_lhand
client.screen += l_hand
var/t_state = l_hand.item_state
if(!t_state)
t_state = l_hand.icon_state
var/image/standing = l_hand.build_worn_icon(state = t_state, default_layer = L_HAND_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
overlays_standing[L_HAND_LAYER] = standing
apply_overlay(L_HAND_LAYER)
/mob/living/carbon/update_fire(var/fire_icon = "Generic_mob_burning")
remove_overlay(FIRE_LAYER)
if(on_fire)
overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"= fire_icon, "layer"=-FIRE_LAYER)
apply_overlay(FIRE_LAYER)
/mob/living/carbon/regenerate_icons()
if(notransform)
return 1
update_inv_r_hand()
update_inv_l_hand()
update_inv_handcuffed()
update_inv_legcuffed()
update_fire()
/mob/living/carbon/update_inv_wear_mask()
remove_overlay(FACEMASK_LAYER)
if(istype(wear_mask, /obj/item/clothing/mask))
if(!(head && (head.flags_inv & HIDEMASK)))
var/image/standing = wear_mask.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/mask.dmi')
overlays_standing[FACEMASK_LAYER] = standing
update_hud_wear_mask(wear_mask)
apply_overlay(FACEMASK_LAYER)
/mob/living/carbon/update_inv_back()
remove_overlay(BACK_LAYER)
if(client && hud_used && hud_used.inv_slots[slot_back])
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_back]
inv.update_icon()
if(back)
var/image/standing = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi')
overlays_standing[BACK_LAYER] = standing
update_hud_back(back)
apply_overlay(BACK_LAYER)
/mob/living/carbon/update_inv_head()
remove_overlay(HEAD_LAYER)
if(head)
var/image/standing = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi')
overlays_standing[HEAD_LAYER] = standing
update_hud_head(head)
apply_overlay(HEAD_LAYER)
/mob/living/carbon/update_inv_handcuffed()
return
//mob HUD updates for items in our inventory
//update whether handcuffs appears on our hud.
/mob/living/carbon/proc/update_hud_handcuffed()
if(hud_used)
var/obj/screen/inventory/R = hud_used.inv_slots[slot_r_hand]
var/obj/screen/inventory/L = hud_used.inv_slots[slot_l_hand]
if(R && L)
R.update_icon()
L.update_icon()
//update whether our head item appears on our hud.
/mob/living/carbon/proc/update_hud_head(obj/item/I)
return
//update whether our mask item appears on our hud.
/mob/living/carbon/proc/update_hud_wear_mask(obj/item/I)
return
//update whether our back item appears on our hud.
/mob/living/carbon/proc/update_hud_back(obj/item/I)
return
//Overlays for the worn overlay so you can overlay while you overlay
//eg: ammo counters, primed grenade flashing, etc.
/obj/item/proc/worn_overlays(var/isinhands = FALSE)
. = list()
+102
View File
@@ -0,0 +1,102 @@
/*
apply_damage(a,b,c)
args
a:damage - How much damage to take
b:damage_type - What type of damage to take, brute, burn
c:def_zone - Where to take the damage if its brute or burn
Returns
standard 0 if fail
*/
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
blocked = (100-blocked)/100
if(!damage || (blocked <= 0))
return 0
switch(damagetype)
if(BRUTE)
adjustBruteLoss(damage * blocked)
if(BURN)
adjustFireLoss(damage * blocked)
if(TOX)
adjustToxLoss(damage * blocked)
if(OXY)
adjustOxyLoss(damage * blocked)
if(CLONE)
adjustCloneLoss(damage * blocked)
if(STAMINA)
adjustStaminaLoss(damage * blocked)
updatehealth()
return 1
/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = 0, stamina = 0)
if(blocked >= 100)
return 0
if(brute)
apply_damage(brute, BRUTE, def_zone, blocked)
if(burn)
apply_damage(burn, BURN, def_zone, blocked)
if(tox)
apply_damage(tox, TOX, def_zone, blocked)
if(oxy)
apply_damage(oxy, OXY, def_zone, blocked)
if(clone)
apply_damage(clone, CLONE, def_zone, blocked)
if(stamina)
apply_damage(stamina, STAMINA, def_zone, blocked)
return 1
/mob/living/proc/apply_effect(effect = 0,effecttype = STUN, blocked = 0)
blocked = (100-blocked)/100
if(!effect || (blocked <= 0))
return 0
switch(effecttype)
if(STUN)
Stun(effect * blocked)
if(WEAKEN)
Weaken(effect * blocked)
if(PARALYZE)
Paralyse(effect * blocked)
if(IRRADIATE)
radiation += max(effect * blocked, 0)
if(SLUR)
slurring = max(slurring,(effect * blocked))
if(STUTTER)
if(status_flags & CANSTUN) // stun is usually associated with stutter
stuttering = max(stuttering,(effect * blocked))
if(EYE_BLUR)
blur_eyes(effect * blocked)
if(DROWSY)
drowsyness = max(drowsyness,(effect * blocked))
if(JITTER)
if(status_flags & CANSTUN)
jitteriness = max(jitteriness,(effect * blocked))
return 1
/mob/living/proc/apply_effects(stun = 0, weaken = 0, paralyze = 0, irradiate = 0, slur = 0, stutter = 0, eyeblur = 0, drowsy = 0, blocked = 0, stamina = 0, jitter = 0)
if(blocked >= 100)
return 0
if(stun)
apply_effect(stun, STUN, blocked)
if(weaken)
apply_effect(weaken, WEAKEN, blocked)
if(paralyze)
apply_effect(paralyze, PARALYZE, blocked)
if(irradiate)
apply_effect(irradiate, IRRADIATE, blocked)
if(slur)
apply_effect(slur, SLUR, blocked)
if(stutter)
apply_effect(stutter, STUTTER, blocked)
if(eyeblur)
apply_effect(eyeblur, EYE_BLUR, blocked)
if(drowsy)
apply_effect(drowsy, DROWSY, blocked)
if(stamina)
apply_damage(stamina, STAMINA, null, blocked)
if(jitter)
apply_effect(jitter, JITTER, blocked)
return 1
+75
View File
@@ -0,0 +1,75 @@
/mob/living/gib(no_brain, no_organs)
var/prev_lying = lying
if(stat != DEAD)
death(1)
if(buckled)
buckled.unbuckle_mob(src,force=1) //to update alien nest overlay, forced because we don't exist anymore
if(!prev_lying)
gib_animation()
if(!no_organs)
spill_organs(no_brain)
spawn_gibs()
qdel(src)
/mob/living/proc/gib_animation()
return
/mob/living/proc/spawn_gibs()
gibs(loc, viruses)
/mob/living/proc/spill_organs(no_brain)
return
/mob/living/dust()
death(1)
if(buckled)
buckled.unbuckle_mob(src,force=1)
dust_animation()
spawn_dust()
qdel(src)
/mob/living/proc/dust_animation()
return
/mob/living/proc/spawn_dust()
new /obj/effect/decal/cleanable/ash(loc)
/mob/living/death(gibbed)
unset_machine()
timeofdeath = world.time
tod = worldtime2text()
var/turf/T = get_turf(src)
if(mind && mind.name && mind.active && (T.z != ZLEVEL_CENTCOM))
var/area/A = get_area(T)
var/rendered = "<span class='game deadsay'><span class='name'>\
[mind.name]</span> has died at <span class='name'>[A.name]\
</span>.</span>"
deadchat_broadcast(rendered, follow_target = src,
message_type=DEADCHAT_DEATHRATTLE)
if(mind)
mind.store_memory("Time of death: [tod]", 0)
living_mob_list -= src
if(!gibbed)
dead_mob_list += src
else if(buckled)
buckled.unbuckle_mob(src,force=1)
paralysis = 0
stunned = 0
weakened = 0
set_drugginess(0)
SetSleeping(0, 0)
blind_eyes(1)
reset_perspective(null)
hide_fullscreens()
update_action_buttons_icon()
update_damage_hud()
update_health_hud()
update_canmove()
med_hud_set_health()
med_hud_set_status()
+352
View File
@@ -0,0 +1,352 @@
//This only assumes that the mob has a body and face with at least one mouth.
//Things like airguitar can be done without arms, and the flap thing makes so little sense it's a keeper.
//Intended to be called by a higher up emote proc if the requested emote isn't in the custom emotes.
/mob/living/emote(act, m_type=1, message = null)
if(stat)
return
var/param = null
if (findtext(act, "-", 1, null)) //Removes dashes for npcs "EMOTE-PLAYERNAME" or something like that, I ain't no AI coder. It's not for players. -Sum99
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
act = lowertext(act)
switch(act)//Hello, how would you like to order? Alphabetically!
if ("aflap")
if (!src.restrained())
message = "<B>[src]</B> flaps its wings ANGRILY!"
m_type = 2
if ("blush","blushes")
message = "<B>[src]</B> blushes."
m_type = 1
if ("bow","bows")
if (!src.buckled)
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> bows to [param]."
else
message = "<B>[src]</B> bows."
m_type = 1
if ("burp","burps")
message = "<B>[src]</B> burps."
m_type = 2
if ("choke","chokes")
message = "<B>[src]</B> chokes!"
m_type = 2
if ("cross","crosses")
message = "<B>[src]</B> crosses their arms."
m_type = 2
if ("chuckle","chuckles")
message = "<B>[src]</B> chuckles."
m_type = 2
if ("collapse","collapses")
Paralyse(2)
message = "<B>[src]</B> collapses!"
m_type = 2
if ("cough","coughs")
message = "<B>[src]</B> coughs!"
m_type = 2
if ("dance","dances")
if (!src.restrained())
message = "<B>[src]</B> dances around happily."
m_type = 1
if ("deathgasp","deathgasps")
message = "<B>[src]</B> seizes up and falls limp, its eyes dead and lifeless..."
m_type = 1
if ("drool","drools")
message = "<B>[src]</B> drools."
m_type = 1
if ("faint","faints")
message = "<B>[src]</B> faints."
if(sleeping)
return //Can't faint while asleep
SetSleeping(10) //Short-short nap
m_type = 1
if ("flap","flaps")
if (!src.restrained())
message = "<B>[src]</B> flaps its wings."
m_type = 2
if ("flip","flips")
if (!restrained() || !resting || !sleeping)
src.SpinAnimation(7,1)
m_type = 2
if ("frown","frowns")
message = "<B>[src]</B> frowns."
m_type = 1
if ("gag","gags")
message = "<B>[src]</B> gags!"
m_type = 2
if ("gasp","gasps")
message = "<B>[src]</B> gasps!"
m_type = 2
if ("giggle","giggles")
message = "<B>[src]</B> giggles."
m_type = 2
if ("glare","glares")
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> glares at [param]."
else
message = "<B>[src]</B> glares."
if ("grin","grins")
message = "<B>[src]</B> grins."
m_type = 1
if ("groan","groans")
message = "<B>[src]</B> groans!"
m_type = 1
if ("grimace","grimaces")
message = "<B>[src]</B> grimaces."
m_type = 1
if ("jump","jumps")
message = "<B>[src]</B> jumps!"
m_type = 1
if ("kiss","kisses") //S-so forward uwa~
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> blows a kiss to [param]." //I was gonna make this <B>[src]</B> kisses [param] but then I imagined dealing with an ahelp about someone spamming it and following certain players around and I had a miniature stroke.
else
message = "<B>[src]</B> blows a kiss."
if ("laugh","laughs")
message = "<B>[src]</B> laughs."
m_type = 2
if ("look","looks")
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> looks at [param]."
else
message = "<B>[src]</B> looks."
m_type = 1
if ("me")
if(jobban_isbanned(src, "emote"))
src << "You cannot send custom emotes (banned)"
return
if (src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if(!(message))
return
else
message = "<B>[src]</B> [message]"
if ("nod","nods")
message = "<B>[src]</B> nods."
m_type = 1
if ("point","points")
if (!src.restrained())
var/atom/M = null
if (param)
for (var/atom/A as mob|obj|turf in view())
if (param == A.name)
M = A
break
if (!M)
message = "<B>[src]</B> points."
else
pointed(M)
m_type = 1
if ("pout","pouts")
message = "<B>[src]</B> pouts."
m_type = 2
if ("scream","screams")
message = "<B>[src]</B> screams!"
m_type = 2
if ("scowl","scowls")
message = "<B>[src]</B> scowls."
m_type = 1
if ("shake","shakes")
message = "<B>[src]</B> shakes its head."
m_type = 1
if ("sigh","sighs")
message = "<B>[src]</B> sighs."
m_type = 2
if ("sit","sits")
message = "<B>[src]</B> sits down."
m_type = 1
if ("smile","smiles")
message = "<B>[src]</B> smiles."
m_type = 1
if ("sneeze","sneezes")
message = "<B>[src]</B> sneezes."
m_type = 2
if ("smug","smugs")
message = "<B>[src]</B> grins smugly."
m_type = 2
if ("sniff","sniffs")
message = "<B>[src]</B> sniffs."
m_type = 2
if ("snore","snores")
message = "<B>[src]</B> snores."
m_type = 2
if ("stare","stares")
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> stares at [param]."
else
message = "<B>[src]</B> stares."
if ("stretch","stretches")
message = "<B>[src]</B> stretches their arms."
m_type = 2
if ("sulk","sulks")
message = "<B>[src]</B> sulks down sadly."
m_type = 1
if ("surrender","surrenders")
message = "<B>[src]</B> puts their hands on their head and falls to the ground, they surrender!"
if(sleeping)
return //Can't surrender while asleep.
Weaken(20) //So you can't resist.
m_type = 1
if ("faint","faints")
message = "<B>[src]</B> faints."
if(sleeping)
return //Can't faint while asleep
SetSleeping(10) //Short-short nap
m_type = 1
if ("sway","sways")
message = "<B>[src]</B> sways around dizzily."
m_type = 1
if ("tremble","trembles")
message = "<B>[src]</B> trembles in fear!"
m_type = 1
if ("twitch","twitches")
message = "<B>[src]</B> twitches violently."
m_type = 1
if ("twitch_s")
message = "<B>[src]</B> twitches."
m_type = 1
if ("wave","waves")
message = "<B>[src]</B> waves."
m_type = 1
if ("whimper","whimpers")
message = "<B>[src]</B> whimpers."
m_type = 2
if ("wsmile","wsmiles")
message = "<B>[src]</B> smiles weakly."
m_type = 2
if ("yawn","yawns")
message = "<B>[src]</B> yawns."
m_type = 2
if ("help")
src << "Help for emotes. You can use these emotes with say \"*emote\":\n\naflap, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cross, dance, deathgasp, drool, flap, frown, gasp, giggle, glare-(none)/mob, grin, grimace, groan, jump, kiss, laugh, look, me, nod, point-atom, scream, shake, sigh, sit, smile, sneeze, sniff, snore, stare-(none)/mob, stretch, sulk, surrender, sway, tremble, twitch, twitch_s, wave, whimper, wsmile, yawn"
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
if (message)
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
var/T = get_turf(src)
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(T,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
+115
View File
@@ -0,0 +1,115 @@
/mob/living/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if(digitalinvis)
handle_diginvis() //AI becomes unable to see mob
if (notransform)
return
if(!loc)
return
var/datum/gas_mixture/environment = loc.return_air()
if(stat != DEAD)
//Breathing, if applicable
handle_breathing()
//Mutations and radiation
handle_mutations_and_radiation()
//Chemicals in the body
handle_chemicals_in_body()
//Random events (vomiting etc)
handle_random_events()
. = 1
//Handle temperature/pressure differences between body and environment
if(environment)
handle_environment(environment)
handle_fire()
//stuff in the stomach
handle_stomach()
update_gravity(mob_has_gravity())
if(machine)
machine.check_eye(src)
if(stat != DEAD)
handle_disabilities() // eye, ear, brain damages
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
/mob/living/proc/handle_breathing()
return
/mob/living/proc/handle_mutations_and_radiation()
radiation = 0 //so radiation don't accumulate in simple animals
return
/mob/living/proc/handle_chemicals_in_body()
return
/mob/living/proc/handle_diginvis()
if(!digitaldisguise)
src.digitaldisguise = image(loc = src)
src.digitaldisguise.override = 1
for(var/mob/living/silicon/ai/AI in player_list)
AI.client.images |= src.digitaldisguise
/mob/living/proc/handle_random_events()
return
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
return
/mob/living/proc/handle_stomach()
return
//this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc..
/mob/living/proc/handle_status_effects()
if(paralysis)
AdjustParalysis(-1)
if(stunned)
AdjustStunned(-1, 1, 1)
if(weakened)
AdjustWeakened(-1, 1, 1)
if(confused)
confused = max(0, confused - 1)
/mob/living/proc/handle_disabilities()
//Eyes
if(eye_blind) //blindness, heals slowly over time
if(!stat && !(disabilities & BLIND))
eye_blind = max(eye_blind-1,0)
if(client && !eye_blind)
clear_alert("blind")
clear_fullscreen("blind")
else
eye_blind = max(eye_blind-1,1)
else if(eye_blurry) //blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)
if(client && !eye_blurry)
clear_fullscreen("blurry")
//Ears
if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own
setEarDamage(-1, max(ear_deaf, 1))
else
// deafness heals slowly over time, unless ear_damage is over 100
if(ear_damage < 100)
adjustEarDamage(-0.05,-1)
/mob/living/proc/update_damage_hud()
return
File diff suppressed because it is too large Load Diff
+381
View File
@@ -0,0 +1,381 @@
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text)
var/armor = getarmor(def_zone, attack_flag)
//the if "armor" check is because this is used for everything on /living, including humans
if(armor && armour_penetration)
armor = max(0, armor - armour_penetration)
if(penetrated_text)
src << "<span class='userdanger'>[penetrated_text]</span>"
else
src << "<span class='userdanger'>Your armor was penetrated!</span>"
else if(armor >= 100)
if(absorb_text)
src << "<span class='userdanger'>[absorb_text]</span>"
else
src << "<span class='userdanger'>Your armor absorbs the blow!</span>"
else if(armor > 0)
if(soften_text)
src << "<span class='userdanger'>[soften_text]</span>"
else
src << "<span class='userdanger'>Your armor softens the blow!</span>"
return armor
/mob/living/proc/getarmor(def_zone, type)
return 0
/mob/living/proc/on_hit(obj/item/projectile/proj_type)
return
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
return P.on_hit(src, armor, def_zone)
/proc/vol_by_throwforce_and_or_w_class(obj/item/I)
if(!I)
return 0
if(I.throwforce && I.w_class)
return Clamp((I.throwforce + I.w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(I.w_class)
return Clamp(I.w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = vol_by_throwforce_and_or_w_class(I)
if(istype(I,/obj/item/weapon)) //If the item is a weapon...
var/obj/item/weapon/W = I
dtype = W.damtype
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
if (W.throwhitsound) //...and throwhitsound is defined...
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, I)
if(I.thrownby)
add_logs(I.thrownby, src, "hit", I)
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
..()
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == "harm")
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
switch(M.damtype)
if("brute")
Paralyse(1)
take_overall_damage(rand(M.force/2, M.force))
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
if("tox")
M.mech_toxin_damage(src)
else
return
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>")
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
step_away(src,M)
add_logs(M.occupant, src, "pushed", M)
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>")
//Mobs on Fire
/mob/living/proc/IgniteMob()
if(fire_stacks > 0 && !on_fire)
on_fire = 1
src.visible_message("<span class='warning'>[src] catches fire!</span>", \
"<span class='userdanger'>You're set on fire!</span>")
src.AddLuminosity(3)
throw_alert("fire", /obj/screen/alert/fire)
update_fire()
return TRUE
return FALSE
/mob/living/proc/ExtinguishMob()
if(on_fire)
on_fire = 0
fire_stacks = 0
src.AddLuminosity(-3)
clear_alert("fire")
update_fire()
/mob/living/proc/update_fire()
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
/mob/living/proc/handle_fire()
if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly
fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable.
if(!on_fire)
return 1
if(fire_stacks > 0)
adjust_fire_stacks(-0.1) //the fire is slowly consumed
else
ExtinguishMob()
return
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(!G.gases["o2"] || G.gases["o2"][MOLES] < 1)
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act()
adjust_fire_stacks(3)
IgniteMob()
//Share fire evenly between the two mobs
//Called in MobBump() and Crossed()
/mob/living/proc/spreadFire(mob/living/L)
if(!istype(L))
return
var/L_old_on_fire = L.on_fire
if(on_fire) //Only spread fire stacks if we're on fire
fire_stacks /= 2
L.fire_stacks += fire_stacks
if(L.IgniteMob())
log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire")
if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them
L.fire_stacks /= 2
fire_stacks += L.fire_stacks
IgniteMob()
//Mobs on Fire end
/mob/living/proc/dominate_mind(mob/living/target, duration = 100, silent) //Allows one mob to assume control of another while imprisoning the old consciousness for a time
if(!target)
return 0
if(target.mental_dominator)
src << "<span class='warning'>[target] is already being controlled by someone else!</span>"
return 0
if(!target.mind)
src << "<span class='warning'>[target] is mindless and would make you permanently catatonic!</span>"
return 0
if(!silent)
src << "<span class='userdanger'>You pounce upon [target]'s mind and seize control of their body!</span>"
target << "<span class='userdanger'>Your control over your body is wrenched away from you!</span>"
target.mind_control_holder = new/mob/living/mind_control_holder(target)
target.mind_control_holder.real_name = "imprisoned mind of [target.real_name]"
target.mind.transfer_to(target.mind_control_holder)
mind.transfer_to(target)
target.mental_dominator = src
spawn(duration)
if(!src)
if(!silent)
target << "<span class='userdanger'>You try to return to your own body, but sense nothing! You're being forced out!</span>"
target.ghostize(1)
target.mind_control_holder.mind.transfer_to(target)
if(!silent)
target << "<span class='userdanger'>You take control of your own body again!</span>"
return 0
if(!silent)
target << "<span class='userdanger'>You're forced out! You return to your own body.</span>"
target.mind.transfer_to(src)
target.mind_control_holder.mind.transfer_to(target)
qdel(mind_control_holder)
if(!silent)
target << "<span class='userdanger'>You take control of your own body again!</span>"
return 1
/mob/living/acid_act(acidpwr, toxpwr, acid_volume)
take_organ_damage(min(10*toxpwr, acid_volume * toxpwr))
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src || anchored)
return 0
if(!user.pulling || user.pulling != src)
user.start_pulling(src, supress_message)
return
if(!(status_flags & CANPUSH))
user << "<span class='warning'>[src] can't be grabbed more aggressively!</span>"
return 0
grippedby(user)
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
var/grab_upgrade_time = 30
visible_message("<span class='danger'>[user] starts to tighten \his grip on [src]!</span>", \
"<span class='userdanger'>[user] starts to tighten \his grip on you!</span>")
if(!do_mob(user, src, grab_upgrade_time))
return 0
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != "grab")
return 0
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
add_logs(user, src, "grabbed", addition="aggressively")
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
drop_r_hand()
drop_l_hand()
stop_pulling()
if(GRAB_NECK)
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
if(GRAB_KILL)
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
"<span class='userdanger'>[user] is strangling you!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
return 1
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if (stat != DEAD)
add_logs(M, src, "attacked")
M.do_attack_animation(src)
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
"<span class='userdanger'>The [M.name] glomps [src]!</span>")
return 1
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if(M.melee_damage_upper == 0)
M.visible_message("<span class='notice'>\The [M] [M.friendly] [src]!</span>")
return 0
else
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>")
add_logs(M, src, "attacked")
return 1
/mob/living/attack_paw(mob/living/carbon/monkey/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return 0
if (istype(loc, /turf) && istype(loc.loc, /area/start))
M << "No attacking people at spawn, you jackass."
return 0
if (M.a_intent == "harm")
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
M << "<span class='warning'>You can't bite with your mouth covered!</span>"
return 0
M.do_attack_animation(src)
if (prob(75))
add_logs(M, src, "attacked")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>")
return 1
else
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>")
return 0
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if("help")
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return 0
else
L.do_attack_animation(src)
if(prob(90))
add_logs(L, src, "attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
return 1
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>")
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return 0
if (istype(loc, /turf) && istype(loc.loc, /area/start))
M << "No attacking people at spawn, you jackass."
return 0
switch(M.a_intent)
if ("help")
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return 0
if ("grab")
grabbedby(M)
return 0
else
M.do_attack_animation(src)
return 1
/mob/living/incapacitated(ignore_restraints, ignore_grab)
if(stat || paralysis || stunned || weakened || (!ignore_restraints && restrained(ignore_grab)))
return 1
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
/mob/living/Stun(amount, updating = 1, ignore_canstun = 0)
if(stun_absorption && !stat)
visible_message("<span class='warning'>[src]'s yellow aura momentarily intensifies!</span>", "<span class='userdanger'>Your ward absorbs the stun!</span>")
stun_absorption_count += amount
return 0
..()
/mob/living/Weaken(amount, updating = 1, ignore_canweaken = 0)
if(stun_absorption && !stat)
visible_message("<span class='warning'>[src]'s yellow aura momentarily intensifies!</span>", "<span class='userdanger'>Your ward absorbs the stun!</span>")
stun_absorption_count += amount
return 0
..()
+74
View File
@@ -0,0 +1,74 @@
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
languages_spoken = HUMAN
languages_understood = HUMAN
sight = 0
see_in_dark = 2
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
var/health = 100 //A mob's health
//Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS
var/bruteloss = 0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage)
var/oxyloss = 0 //Oxygen depravation damage (no air in lungs)
var/toxloss = 0 //Toxic damage caused by being poisoned or radiated
var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt.
var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot.
var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are stunned if it gets too high. Holodeck and hallucinations deal this.
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
var/now_pushing = null //used by living/Bump() and living/PushAM() to prevent potential infinite loop.
var/cameraFollow = null
var/tod = null // Time of death
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
var/bloodcrawl = 0 //0 No blood crawling, BLOODCRAWL for bloodcrawling, BLOODCRAWL_EAT for crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/list/image/staticOverlays = list()
var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head)
var/list/pipes_shown = list()
var/last_played_vent
var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob.
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
var/bubble_icon = "default" //what icon the mob uses for speechbubbles
var/last_bumped = 0
var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666)
var/list/butcher_results = null
var/hellbound = 0 //People who've signed infernal contracts are unrevivable.
var/list/weather_immunities = list()
var/stun_absorption = FALSE //If all incoming stuns are being absorbed
var/stun_absorption_count = 0 //How many seconds of stun that have been absorbed
var/mob/living/mental_dominator //The person controlling the mind of this person, if applicable
var/mob/living/mind_control_holder/mind_control_holder //If the mob is being mind controlled, where their old mind is stored (check clock_mobs.dm)
var/blood_volume = 0 //how much blood the mob has
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
+22
View File
@@ -0,0 +1,22 @@
/mob/living/Login()
..()
//Mind updates
sync_mind()
mind.show_memory(src, 0)
//Round specific stuff
if(ticker && ticker.mode)
switch(ticker.mode.name)
if("sandbox")
CanBuild()
update_damage_hud()
update_health_hud()
//Vents
if(ventcrawler)
src << "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>"
if(ranged_ability)
client.click_intercept = ranged_ability
src << "<span class='notice'>You currently have <b>[ranged_ability.name]</b> active!</span>"
+4
View File
@@ -0,0 +1,4 @@
/mob/living/Logout()
..()
if(!key && mind) //key and mind have become seperated.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
+308
View File
@@ -0,0 +1,308 @@
var/list/department_radio_keys = list(
":r" = "right hand", "#r" = "right hand", ".r" = "right hand",
":l" = "left hand", "#l" = "left hand", ".l" = "left hand",
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
":h" = "department", "#h" = "department", ".h" = "department",
":c" = "Command", "#c" = "Command", ".c" = "Command",
":n" = "Science", "#n" = "Science", ".n" = "Science",
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
":s" = "Security", "#s" = "Security", ".s" = "Security",
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
":b" = "binary", "#b" = "binary", ".b" = "binary",
":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk",
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
":v" = "Service", "#v" = "Service", ".v" = "Service",
":o" = "AI Private", "#o" = "AI Private", ".o" = "AI Private",
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
":y" = "Centcom", "#y" = "Centcom", ".y" = "Centcom",
":R" = "right hand", "#R" = "right hand", ".R" = "right hand",
":L" = "left hand", "#L" = "left hand", ".L" = "left hand",
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
":H" = "department", "#H" = "department", ".H" = "department",
":C" = "Command", "#C" = "Command", ".C" = "Command",
":N" = "Science", "#N" = "Science", ".N" = "Science",
":M" = "Medical", "#M" = "Medical", ".M" = "Medical",
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
":S" = "Security", "#S" = "Security", ".S" = "Security",
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
":B" = "binary", "#B" = "binary", ".B" = "binary",
":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk",
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":V" = "Service", "#V" = "Service", ".V" = "Service",
":O" = "AI Private", "#O" = "AI Private", ".O" = "AI Private",
":G" = "changeling", "#G" = "changeling", ".G" = "changeling",
":Y" = "Centcom", "#Y" = "Centcom", ".Y" = "Centcom",
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand",
":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand",
":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom",
":ð" = "department", "#ð" = "department", ".ð" = "department",
":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering",
":û" = "Security", "#û" = "Security", ".û" = "Security",
":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
":è" = "binary", "#è" = "binary", ".è" = "binary",
":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
":é" = "Supply", "#é" = "Supply", ".é" = "Supply",
":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling"
)
var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
/mob/living/say(message, bubble_type,var/list/spans = list())
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if(stat == DEAD)
say_dead(message)
return
if(check_emote(message))
return
if(!can_speak_basic(message)) //Stat is seperate so I can handle whispers properly.
return
var/message_mode = get_message_mode(message)
if(stat && !(message_mode in crit_allowed_modes))
return
if(message_mode == MODE_HEADSET || message_mode == MODE_ROBOT)
message = copytext(message, 2)
else if(message_mode)
message = copytext(message, 3)
if(findtext(message, " ", 1, 2))
message = copytext(message, 2)
if(handle_inherent_channels(message, message_mode)) //Hiveminds, binary chat & holopad.
return
if(!can_speak_vocal(message))
src << "<span class='warning'>You find yourself unable to speak!</span>"
return
if(message_mode != MODE_WHISPER) //whisper() calls treat_message(); double process results in "hisspering"
message = treat_message(message)
spans += get_spans()
if(!message)
return
//Log of what we've said, plain message, no spans or junk
say_log += message
var/message_range = 7
var/radio_return = radio(message, message_mode, spans)
if(radio_return & NOPASS) //There's a whisper() message_mode, no need to continue the proc if that is called
return
if(radio_return & ITALICS)
spans |= SPAN_ITALICS
if(radio_return & REDUCE_RANGE)
message_range = 1
//No screams in space, unless you're next to someone.
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.return_air()
var/pressure = (environment)? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1
if(pressure < ONE_ATMOSPHERE*0.4) //Thin air, let's italicise the message
spans |= SPAN_ITALICS
send_speech(message, message_range, src, bubble_type, spans)
log_say("[name]/[key] : [message]")
return 1
/mob/living/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
if(!client)
return
var/deaf_message
var/deaf_type
if(speaker != src)
if(!radio_freq) //These checks have to be seperate, else people talking on the radio will make "You can't hear yourself!" appear when hearing people over the radio while deaf.
deaf_message = "<span class='name'>[speaker]</span> [speaker.verb_say] something but you cannot hear them."
deaf_type = 1
else
deaf_message = "<span class='notice'>You can't hear yourself!</span>"
deaf_type = 2 // Since you should be able to hear yourself without looking
if(!(message_langs & languages_understood) || force_compose) //force_compose is so AIs don't end up without their hrefs.
message = compose_message(speaker, message_langs, raw_message, radio_freq, spans)
show_message(message, 2, deaf_message, deaf_type)
return message
/mob/living/send_speech(message, message_range = 7, obj/source = src, bubble_type = bubble_icon, list/spans)
var/list/listening = get_hearers_in_view(message_range, source)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7)) && client) // client is so that ghosts don't have to listen to mice
listening |= M
var/rendered = compose_message(src, languages_spoken, message, , spans)
for(var/atom/movable/AM in listening)
AM.Hear(rendered, src, languages_spoken, message, , spans)
//speech bubble
var/list/speech_bubble_recipients = list()
for(var/mob/M in listening)
if(M.client)
speech_bubble_recipients.Add(M.client)
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
spawn(0)
flick_overlay(I, speech_bubble_recipients, 30)
/mob/proc/binarycheck()
return 0
/mob/living/can_speak(message) //For use outside of Say()
if(can_speak_basic(message) && can_speak_vocal(message))
return 1
/mob/living/proc/can_speak_basic(message) //Check BEFORE handling of xeno and ling channels
if(client)
if(client.prefs.muted & MUTE_IC)
src << "<span class='danger'>You cannot speak in IC (muted).</span>"
return 0
if(client.handle_spam_prevention(message,MUTE_IC))
return 0
return 1
/mob/living/proc/can_speak_vocal(message) //Check AFTER handling of xeno and ling channels
if(disabilities & MUTE)
return 0
if(is_muzzled())
return 0
if(!IsVocal())
return 0
return 1
/mob/living/proc/check_emote(message)
if(copytext(message, 1, 2) == "*")
emote(copytext(message, 2))
return 1
/mob/living/proc/get_message_mode(message)
if(copytext(message, 1, 2) == ";")
return MODE_HEADSET
else if(length(message) > 2)
return department_radio_keys[copytext(message, 1, 3)]
/mob/living/proc/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_CHANGELING)
switch(lingcheck())
if(3)
var/msg = "<i><font color=#800040><b>[src.mind]:</b> [message]</font></i>"
for(var/mob/M in mob_list)
if(M in dead_mob_list)
var/link = FOLLOW_LINK(M, src)
M << "[link] [msg]"
else
switch(M.lingcheck())
if(3)
M << msg
if(2)
M << msg
if(1)
if(prob(40))
M << "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>"
return 1
if(2)
var/msg = "<i><font color=#800080><b>[mind.changeling.changelingID]:</b> [message]</font></i>"
log_say("[mind.changeling.changelingID]/[src.key] : [message]")
for(var/mob/M in mob_list)
if(M in dead_mob_list)
var/link = FOLLOW_LINK(M, src)
M << "[link] [msg]"
else
switch(M.lingcheck())
if(3)
M << msg
if(2)
M << msg
if(1)
if(prob(40))
M << "<i><font color=#800080>We can faintly sense another of our kind trying to communicate through the hivemind...</font></i>"
return 1
if(1)
src << "<i><font color=#800080>Our senses have not evolved enough to be able to communicate this way...</font></i>"
return 1
if(message_mode == MODE_ALIEN)
if(hivecheck())
alien_talk(message)
return 1
return 0
/mob/living/proc/treat_message(message)
if(getBrainLoss() >= 60)
message = derpspeech(message, stuttering)
if(stuttering)
message = stutter(message)
if(slurring)
message = slur(message)
if(cultslurring)
message = cultslur(message)
message = capitalize(message)
return message
/mob/living/proc/radio(message, message_mode, list/spans)
switch(message_mode)
if(MODE_R_HAND)
if (r_hand)
r_hand.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
if(MODE_L_HAND)
if (l_hand)
l_hand.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
if(MODE_INTERCOM)
for (var/obj/item/device/radio/intercom/I in view(1, null))
I.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
if(MODE_BINARY)
if(binarycheck())
robot_talk(message)
return ITALICS | REDUCE_RANGE //Does not return 0 since this is only reached by humans, not borgs or AIs.
if(MODE_WHISPER)
whisper(message)
return NOPASS
return 0
/mob/living/lingcheck() //1 is ling w/ no hivemind. 2 is ling w/hivemind. 3 is ling victim being linked into hivemind.
if(mind && mind.changeling)
if(mind.changeling.changeling_speak)
return 2
return 1
if(mind && mind.linglink)
return 3
return 0
/mob/living/say_quote(input, list/spans)
var/tempinput = attach_spans(input, spans)
if (stuttering)
return "stammers, \"[tempinput]\""
if (getBrainLoss() >= 60)
return "gibbers, \"[tempinput]\""
return ..()
+900
View File
@@ -0,0 +1,900 @@
var/list/ai_list = list()
//Not sure why this is necessary...
/proc/AutoUpdateAI(obj/subject)
var/is_in_use = 0
if (subject!=null)
for(var/A in ai_list)
var/mob/living/silicon/ai/M = A
if ((M.client && M.machine == subject))
is_in_use = 1
subject.attack_ai(M)
return is_in_use
/mob/living/silicon/ai
name = "AI"
icon = 'icons/mob/AI.dmi'//
icon_state = "ai"
anchored = 1
density = 1
status_flags = CANSTUN|CANPUSH
force_compose = 1 //This ensures that the AI always composes it's own hear message. Needed for hrefs and job display.
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
see_in_dark = 8
med_hud = DATA_HUD_MEDICAL_BASIC
sec_hud = DATA_HUD_SECURITY_BASIC
mob_size = MOB_SIZE_LARGE
var/list/network = list("SS13")
var/obj/machinery/camera/current = null
var/list/connected_robots = list()
var/aiRestorePowerRoutine = 0
//var/list/laws = list()
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
var/viewalerts = 0
var/icon/holo_icon//Default is assigned when AI is created.
var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye.
var/radio_enabled = 1 //Determins if a carded AI can speak with its built in radio or not.
radiomod = ";" //AIs will, by default, state their laws on the internal radio.
var/obj/item/device/pda/ai/aiPDA = null
var/obj/item/device/multitool/aiMulti = null
var/mob/living/simple_animal/bot/Bot
var/tracking = 0 //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
//MALFUNCTION
var/datum/module_picker/malf_picker
var/list/datum/AI_Module/current_modules = list()
var/fire_res_on_core = 0
var/can_dominate_mechs = 0
var/shunted = 0 //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead
var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click()
var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
var/malf_cooldown = 0 //Cooldown var for malf modules
var/obj/machinery/power/apc/malfhack = null
var/explosive = 0 //does the AI explode when it dies?
var/mob/living/silicon/ai/parent = null
var/camera_light_on = 0
var/list/obj/machinery/camera/lit_cameras = list()
var/datum/trackable/track = new()
var/last_paper_seen = null
var/can_shunt = 1
var/last_announcement = "" // For AI VOX, if enabled
var/turf/waypoint //Holds the turf of the currently selected waypoint.
var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking.
var/apc_override = 0 //hack for letting the AI use its APC even when visionless
var/nuking = FALSE
var/obj/machinery/doomsday_device/doomsday_device
var/mob/camera/aiEye/eyeobj = new()
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
var/obj/machinery/camera/portable/builtInCamera
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
..()
rename_self("ai")
name = real_name
anchored = 1
canmove = 0
density = 1
loc = loc
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
if(L)
if (istype(L, /datum/ai_laws))
laws = L
else
make_laws()
verbs += /mob/living/silicon/ai/proc/show_laws_verb
aiPDA = new/obj/item/device/pda/ai(src)
aiPDA.owner = name
aiPDA.ownjob = "AI"
aiPDA.name = name + " (" + aiPDA.ownjob + ")"
aiMulti = new(src)
radio = new /obj/item/device/radio/headset/ai(src)
aicamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
if (istype(loc, /turf))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall,\
/mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/set_automatic_say_channel)
if(!safety)//Only used by AIize() to successfully spawn an AI.
if (!B)//If there is no player/brain inside.
new/obj/structure/AIcore/deactivated(loc)//New empty terminal.
qdel(src)//Delete AI.
return
else
if (B.brainmob.mind)
B.brainmob.mind.transfer_to(src)
rename_self("ai")
if(mind.special_role)
mind.store_memory("As an AI, you must obey your silicon laws above all else. Your objectives will consider you to be dead.")
src << "<span class='userdanger'>You have been installed as an AI! </span>"
src << "<span class='danger'>You must obey your silicon laws above all else. Your objectives will consider you to be dead.</span>"
src << "<B>You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).</B>"
src << "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>"
src << "<B>While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.</B>"
src << "To use something, simply click on it."
src << "Use say :b to speak to your cyborgs through binary."
src << "For department channels, use the following say commands:"
src << ":o - AI Private, :c - Command, :s - Security, :e - Engineering, :u - Supply, :v - Service, :m - Medical, :n - Science."
show_laws()
src << "<b>These laws may be changed by other players, or by you being the traitor.</b>"
job = "AI"
ai_list += src
shuttle_caller_list += src
eyeobj.ai = src
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
eyeobj.loc = src.loc
builtInCamera = new /obj/machinery/camera/portable(src)
builtInCamera.network = list("SS13")
/mob/living/silicon/ai/Destroy()
ai_list -= src
shuttle_caller_list -= src
SSshuttle.autoEvac()
qdel(eyeobj) // No AI, no Eye
return ..()
/mob/living/silicon/ai/verb/pick_icon()
set category = "AI Commands"
set name = "Set AI Core Display"
if(stat || aiRestorePowerRoutine)
return
//if(icon_state == initial(icon_state))
var/icontype = input("Please, select a display!", "AI", null/*, null*/) in list("Clown", "Monochrome", "Blue", "Inverted", "Firewall", "Green", "Red", "Static", "Red October", "House", "Heartline", "Hades", "Helios", "President", "Syndicat Meow", "Alien", "Too Deep", "Triumvirate", "Triumvirate-M", "Text", "Matrix", "Dorf", "Bliss", "Not Malf", "Fuzzy", "Goon", "Database", "Glitchman", "Murica", "Nanotrasen", "Gentoo", "Angel")
if(icontype == "Clown")
icon_state = "ai-clown2"
else if(icontype == "Monochrome")
icon_state = "ai-mono"
else if(icontype == "Blue")
icon_state = "ai"
else if(icontype == "Inverted")
icon_state = "ai-u"
else if(icontype == "Firewall")
icon_state = "ai-magma"
else if(icontype == "Green")
icon_state = "ai-wierd"
else if(icontype == "Red")
icon_state = "ai-malf"
else if(icontype == "Static")
icon_state = "ai-static"
else if(icontype == "Red October")
icon_state = "ai-redoctober"
else if(icontype == "House")
icon_state = "ai-house"
else if(icontype == "Heartline")
icon_state = "ai-heartline"
else if(icontype == "Hades")
icon_state = "ai-hades"
else if(icontype == "Helios")
icon_state = "ai-helios"
else if(icontype == "President")
icon_state = "ai-pres"
else if(icontype == "Syndicat Meow")
icon_state = "ai-syndicatmeow"
else if(icontype == "Alien")
icon_state = "ai-alien"
else if(icontype == "Too Deep")
icon_state = "ai-toodeep"
else if(icontype == "Triumvirate")
icon_state = "ai-triumvirate"
else if(icontype == "Triumvirate-M")
icon_state = "ai-triumvirate-malf"
else if(icontype == "Text")
icon_state = "ai-text"
else if(icontype == "Matrix")
icon_state = "ai-matrix"
else if(icontype == "Dorf")
icon_state = "ai-dorf"
else if(icontype == "Bliss")
icon_state = "ai-bliss"
else if(icontype == "Not Malf")
icon_state = "ai-notmalf"
else if(icontype == "Fuzzy")
icon_state = "ai-fuzz"
else if(icontype == "Goon")
icon_state = "ai-goon"
else if(icontype == "Database")
icon_state = "ai-database"
else if(icontype == "Glitchman")
icon_state = "ai-glitchman"
else if(icontype == "Murica")
icon_state = "ai-murica"
else if(icontype == "Nanotrasen")
icon_state = "ai-nanotrasen"
else if(icontype == "Gentoo")
icon_state = "ai-gentoo"
else if(icontype == "Angel")
icon_state = "ai-angel"
//else
//usr <<"You can only change your display once!"
//return
/mob/living/silicon/ai/Stat()
..()
if(statpanel("Status"))
if(!stat)
stat(null, text("System integrity: [(health+100)/2]%"))
stat(null, "Station Time: [worldtime2text()]")
stat(null, text("Connected cyborgs: [connected_robots.len]"))
var/area/borg_area
for(var/mob/living/silicon/robot/R in connected_robots)
borg_area = get_area(R)
var/robot_status = "Nominal"
if(R.stat || !R.client)
robot_status = "OFFLINE"
else if(!R.cell || R.cell.charge <= 0)
robot_status = "DEPOWERED"
//Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
else
stat(null, text("Systems nonfunctional"))
/mob/living/silicon/ai/proc/ai_alerts()
var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
dat += "<A HREF='?src=\ref[src];mach_close=aialerts'>Close</A><BR><BR>"
for (var/cat in alarms)
dat += text("<B>[]</B><BR>\n", cat)
var/list/L = alarms[cat]
if (L.len)
for (var/alarm in L)
var/list/alm = L[alarm]
var/area/A = alm[1]
var/C = alm[2]
var/list/sources = alm[3]
dat += "<NOBR>"
if (C && istype(C, /list))
var/dat2 = ""
for (var/obj/machinery/camera/I in C)
dat2 += text("[]<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>", (dat2=="") ? "" : " | ", src, I, I.c_tag)
dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera")
else if (C && istype(C, /obj/machinery/camera))
var/obj/machinery/camera/Ctmp = C
dat += text("-- [] (<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>)", A.name, src, C, Ctmp.c_tag)
else
dat += text("-- [] (No Camera)", A.name)
if (sources.len > 1)
dat += text("- [] sources", sources.len)
dat += "</NOBR><BR>\n"
else
dat += "-- All Systems Nominal<BR>\n"
dat += "<BR>\n"
viewalerts = 1
src << browse(dat, "window=aialerts&can_close=0")
/mob/living/silicon/ai/proc/ai_roster()
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
for(var/datum/data/record/t in sortRecord(data_core.general))
dat += t.fields["name"] + " - " + t.fields["rank"] + "<br>"
dat += "</body></html>"
src << browse(dat, "window=airoster")
onclose(src, "airoster")
/mob/living/silicon/ai/proc/ai_call_shuttle()
if(stat == DEAD)
return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
usr << "Wireless control is disabled!"
return
var/reason = input(src, "What is the nature of your emergency? ([CALL_SHUTTLE_REASON_LENGTH] characters required.)", "Confirm Shuttle Call") as null|text
if(trim(reason))
SSshuttle.requestEvac(src, reason)
// hack to display shuttle timer
if(!EMERGENCY_IDLE_OR_RECALLED)
var/obj/machinery/computer/communications/C = locate() in machines
if(C)
C.post_status("shuttle")
return
/mob/living/silicon/ai/cancel_camera()
src.view_core()
/mob/living/silicon/ai/verb/toggle_anchor()
set category = "AI Commands"
set name = "Toggle Floor Bolts"
if(!isturf(loc)) // if their location isn't a turf
return // stop
if(stat == DEAD)
return //won't work if dead
anchored = !anchored // Toggles the anchor
src << "[anchored ? "<b>You are now anchored.</b>" : "<b>You are now unanchored.</b>"]"
// the message in the [] will change depending whether or not the AI is anchored
/mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore
return 0
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "Malfunction"
if(stat == DEAD)
return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
src << "Wireless control is disabled!"
return
SSshuttle.cancelEvac(src)
return
/mob/living/silicon/ai/blob_act(obj/effect/blob/B)
if (stat != DEAD)
adjustBruteLoss(60)
updatehealth()
return 1
return 0
/mob/living/silicon/ai/restrained(ignore_grab)
. = 0
/mob/living/silicon/ai/emp_act(severity)
if (prob(30))
switch(pick(1,2))
if(1)
view_core()
if(2)
SSshuttle.requestEvac(src,"ALERT: Energy surge detected in AI core! Station integrity may be compromised! Initiati--%m091#ar-BZZT")
..()
/mob/living/silicon/ai/ex_act(severity, target)
..()
switch(severity)
if(1)
gib()
if(2)
if (stat != DEAD)
adjustBruteLoss(60)
adjustFireLoss(60)
if(3)
if (stat != DEAD)
adjustBruteLoss(30)
return
/mob/living/silicon/ai/Topic(href, href_list)
if(usr != src)
return
..()
if (href_list["mach_close"])
if (href_list["mach_close"] == "aialerts")
viewalerts = 0
var/t1 = text("window=[]", href_list["mach_close"])
unset_machine()
src << browse(null, t1)
if (href_list["switchcamera"])
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
if (href_list["showalerts"])
ai_alerts()
#ifdef AI_VOX
if(href_list["say_word"])
play_vox_word(href_list["say_word"], null, src)
return
#endif
if(href_list["show_paper"])
if(last_paper_seen)
src << browse(last_paper_seen, "window=show_paper")
//Carn: holopad requests
if(href_list["jumptoholopad"])
var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"])
if(stat == CONSCIOUS)
if(H)
H.attack_ai(src) //may as well recycle
else
src << "<span class='notice'>Unable to locate the holopad.</span>"
if(href_list["track"])
var/string = href_list["track"]
trackable_mobs()
var/list/trackeable = list()
trackeable += track.humans + track.others
var/list/target = list()
for(var/I in trackeable)
var/mob/M = trackeable[I]
if(M.name == string)
target += M
if(name == string)
target += src
if(target.len)
ai_actual_track(pick(target))
else
src << "Target is not on or near any active cameras on the station."
return
if(href_list["callbot"]) //Command a bot to move to a selected location.
Bot = locate(href_list["callbot"]) in living_mob_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
waypoint_mode = 1
src << "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>"
return
if(href_list["interface"]) //Remotely connect to a bot!
Bot = locate(href_list["interface"]) in living_mob_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return
Bot.attack_ai(src)
if(href_list["botrefresh"]) //Refreshes the bot control panel.
botcall()
return
if (href_list["ai_take_control"]) //Mech domination
var/obj/mecha/M = locate(href_list["ai_take_control"])
if(controlled_mech)
src << "You are already loaded into an onboard computer!"
return
if(M)
M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
/mob/living/silicon/ai/bullet_act(obj/item/projectile/Proj)
..(Proj)
updatehealth()
return 2
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return
..()
return
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
if(!tracking)
cameraFollow = null
if (!C || stat == DEAD) //C.can_use())
return 0
if(!src.eyeobj)
view_core()
return
// ok, we're alive, camera is good and in our network...
eyeobj.setLoc(get_turf(C))
//machine = src
return 1
/mob/living/silicon/ai/proc/botcall()
set category = "AI Commands"
set name = "Access Robot Control"
set desc = "Wirelessly control various automatic robots."
if(stat == 2)
return //won't work if dead
if(control_disabled)
src << "Wireless communication is disabled."
return
var/turf/ai_current_turf = get_turf(src)
var/ai_Zlevel = ai_current_turf.z
var/d
var/area/bot_area
d += "<A HREF=?src=\ref[src];botrefresh=1>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='30%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
for (Bot in living_mob_list)
if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
bot_area = get_area(Bot)
var/bot_mode = Bot.get_mode()
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!)</span>" : ""] [Bot.name]</A> ([Bot.model])</td>"
//If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all.
d += "<td width='30%'>[bot_mode]</td>"
d += "<td width='30%'>[bot_area.name]</td>"
d += "<td width='10%'><A HREF=?src=\ref[src];interface=\ref[Bot]>Interface</A></td>"
d += "<td width='10%'><A HREF=?src=\ref[src];callbot=\ref[Bot]>Call</A></td>"
d += "</tr>"
d = format_text(d)
var/datum/browser/popup = new(src, "botcall", "Remote Robot Control", 700, 400)
popup.set_content(d)
popup.open()
/mob/living/silicon/ai/proc/set_waypoint(atom/A)
var/turf/turf_check = get_turf(A)
//The target must be in view of a camera or near the core.
if(turf_check in range(get_turf(src)))
call_bot(turf_check)
else if(cameranet && cameranet.checkTurfVis(turf_check))
call_bot(turf_check)
else
src << "<span class='danger'>Selected location is not visible.</span>"
/mob/living/silicon/ai/proc/call_bot(turf/waypoint)
if(!Bot)
return
if(Bot.calling_ai && Bot.calling_ai != src) //Prevents an override if another AI is controlling this bot.
src << "<span class='danger'>Interface error. Unit is already in use.</span>"
return
Bot.call_bot(src, waypoint)
/mob/living/silicon/ai/triggerAlarm(class, area/A, O, obj/alarmsource)
if(alarmsource.z != z)
return
if (stat == 2)
return 1
var/list/L = alarms[class]
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[3]
if (!(alarmsource in sources))
sources += alarmsource
return 1
var/obj/machinery/camera/C = null
var/list/CL = null
if (O && istype(O, /list))
CL = O
if (CL.len == 1)
C = CL[1]
else if (O && istype(O, /obj/machinery/camera))
C = O
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
if (O)
if (C && C.can_use())
queueAlarm("--- [class] alarm detected in [A.name]! (<A HREF=?src=\ref[src];switchcamera=\ref[C]>[C.c_tag]</A>)", class)
else if (CL && CL.len)
var/foo = 0
var/dat2 = ""
for (var/obj/machinery/camera/I in CL)
dat2 += text("[]<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit...
foo = 1
queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
else
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
else
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
if (viewalerts) ai_alerts()
return 1
/mob/living/silicon/ai/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = 0
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[3]
if (origin in srcs)
srcs -= origin
if (srcs.len == 0)
cleared = 1
L -= I
if (cleared)
queueAlarm("--- [class] alarm in [A.name] has been cleared.", class, 0)
if (viewalerts) ai_alerts()
return !cleared
//Replaces /mob/living/silicon/ai/verb/change_network() in ai.dm & camera.dm
//Adds in /mob/living/silicon/ai/proc/ai_network_change() instead
//Addition by Mord_Sith to define AI's network change ability
/mob/living/silicon/ai/proc/ai_network_change()
set category = "AI Commands"
set name = "Jump To Network"
unset_machine()
cameraFollow = null
var/cameralist[0]
if(stat == 2)
return //won't work if dead
var/mob/living/silicon/ai/U = usr
for (var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
var/list/tempnetwork = C.network
tempnetwork.Remove("CREED", "thunder", "RD", "toxins", "Prison")
if(tempnetwork.len)
for(var/i in C.network)
cameralist[i] = i
var/old_network = network
network = input(U, "Which network would you like to view?") as null|anything in cameralist
if(!U.eyeobj)
U.view_core()
return
if(isnull(network))
network = old_network // If nothing is selected
else
for(var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
if(network in C.network)
U.eyeobj.setLoc(get_turf(C))
break
src << "<span class='notice'>Switched to [network] camera network.</span>"
//End of code by Mord_Sith
/mob/living/silicon/ai/proc/choose_modules()
set category = "Malfunction"
set name = "Choose Module"
malf_picker.use(src)
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
if(stat == 2)
return //won't work if dead
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/M in machines) //change status
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/AISD = M
AISD.emotion = emote
//if Friend Computer, change ALL displays
else if(istype(M, /obj/machinery/status_display))
var/obj/machinery/status_display/SD = M
if(emote=="Friend Computer")
SD.friendc = 1
else
SD.friendc = 0
return
//I am the icon meister. Bow fefore me. //>fefore
/mob/living/silicon/ai/proc/ai_hologram_change()
set name = "Change Hologram"
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
var/input
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
var/personnel_list[] = list()
for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
if(personnel_list.len)
input = input("Select a crew member:") as null|anything in personnel_list
var/icon/character_icon = personnel_list[input]
if(character_icon)
qdel(holo_icon)//Clear old icon so we're not storing it in memory.
holo_icon = getHologramIcon(icon(character_icon))
else
alert("No suitable records found. Aborting.")
else
var/icon_list[] = list(
"default",
"floating face",
"xeno queen",
"space carp"
)
input = input("Please select a hologram:") as null|anything in icon_list
if(input)
qdel(holo_icon)
switch(input)
if("default")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
if("floating face")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2"))
if("xeno queen")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3"))
if("space carp")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4"))
return
/mob/living/silicon/ai/proc/corereturn()
set category = "Malfunction"
set name = "Return to Main Core"
var/obj/machinery/power/apc/apc = src.loc
if(!istype(apc))
src << "<span class='notice'>You are already in your Main Core.</span>"
return
apc.malfvacate()
/mob/living/silicon/ai/proc/toggle_camera_light()
if(stat != CONSCIOUS)
return
camera_light_on = !camera_light_on
if (!camera_light_on)
src << "Camera lights deactivated."
for (var/obj/machinery/camera/C in lit_cameras)
C.SetLuminosity(0)
lit_cameras = list()
return
light_cameras()
src << "Camera lights activated."
return
//AI_CAMERA_LUMINOSITY
/mob/living/silicon/ai/proc/light_cameras()
var/list/obj/machinery/camera/add = list()
var/list/obj/machinery/camera/remove = list()
var/list/obj/machinery/camera/visible = list()
for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks)
for (var/obj/machinery/camera/C in CC.cameras)
if (!C.can_use() || get_dist(C, eyeobj) > 7)
continue
visible |= C
add = visible - lit_cameras
remove = lit_cameras - visible
for (var/obj/machinery/camera/C in remove)
lit_cameras -= C //Removed from list before turning off the light so that it doesn't check the AI looking away.
C.Togglelight(0)
for (var/obj/machinery/camera/C in add)
C.Togglelight(1)
lit_cameras |= C
/mob/living/silicon/ai/proc/control_integrated_radio()
set name = "Transceiver Settings"
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
src << "Accessing Subspace Transceiver control..."
if (radio)
radio.interact(src)
/mob/living/silicon/ai/proc/set_syndie_radio()
if(radio)
radio.make_syndie()
/mob/living/silicon/ai/proc/set_automatic_say_channel()
set name = "Set Auto Announce Mode"
set desc = "Modify the default radio setting for your automatic announcements."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
set_autosay()
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
return
/mob/living/silicon/ai/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card)
if(!..())
return
if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card.
if(!mind)
user << "<span class='warning'>No intelligence patterns detected.</span>" //No more magical carding of empty cores, AI RETURN TO BODY!!!11
return
new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
ai_restore_power()//So the AI initially has power.
control_disabled = 1//Can't control things remotely if you're stuck in a card!
radio_enabled = 0 //No talking on the built-in radio for you either!
loc = card//Throw AI into the card.
card.AI = src
src << "You have been downloaded to a mobile storage device. Remote device connection severed."
user << "<span class='boldnotice'>Transfer successful</span>: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
/mob/living/silicon/ai/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
return // no eyes, no flashing
/mob/living/silicon/ai/attackby(obj/item/weapon/W, mob/user, params)
if(W.force && W.damtype != STAMINA && src.stat != DEAD) //only sparks if real damage is dealt.
spark_system.start()
return ..()
/mob/living/silicon/ai/can_buckle()
return 0
/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close = 0)
if(stat)
return
if(be_close && !in_range(M, src))
return
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
if(M && cameranet && !cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
return
return 1
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
raw_message = lang_treat(speaker, message_langs, raw_message, spans)
var/name_used = speaker.GetVoice()
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> <span class='message'>[raw_message]</span></span></i>"
show_message(rendered, 2)
/mob/living/silicon/ai/fully_replace_character_name(oldname,newname)
..()
if(oldname != real_name)
if(eyeobj)
eyeobj.name = "[newname] (AI Eye)"
// Notify Cyborgs
for(var/mob/living/silicon/robot/Slave in connected_robots)
Slave.show_laws()
/mob/living/silicon/ai/replace_identification_name(oldname,newname)
if(aiPDA)
aiPDA.owner = newname
aiPDA.name = newname + " (" + aiPDA.ownjob + ")"
/mob/living/silicon/ai/proc/add_malf_picker()
src << "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices."
src << "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds."
view_core() //A BYOND bug requires you to be viewing your core before your verbs update
verbs += /mob/living/silicon/ai/proc/choose_modules
malf_picker = new /datum/module_picker
/mob/living/silicon/ai/reset_perspective(atom/A)
if(camera_light_on)
light_cameras()
if(istype(A,/obj/machinery/camera))
current = A
if(client)
if(istype(A, /atom/movable))
client.perspective = EYE_PERSPECTIVE
client.eye = A
else
if(isturf(loc))
if(eyeobj)
client.eye = eyeobj
client.perspective = MOB_PERSPECTIVE
else
client.eye = client.mob
client.perspective = MOB_PERSPECTIVE
else
client.perspective = EYE_PERSPECTIVE
client.eye = loc
update_sight()
if(client.eye != src)
var/atom/AT = client.eye
AT.get_remote_view_fullscreens(src)
else
clear_fullscreen("remote_view", 0)
/mob/living/silicon/ai/revive(full_heal = 0, admin_revive = 0)
if(..()) //successfully ressuscitated from death
icon_state = "ai"
. = 1

Some files were not shown because too many files have changed in this diff Show More