mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-19 02:56:14 +01:00
Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 12/16/2015_newwizard
This commit is contained in:
@@ -140,11 +140,11 @@ note dizziness decrements automatically in the mob's Life() proc.
|
||||
//reset the pixel offsets to zero
|
||||
is_floating = 0
|
||||
|
||||
/atom/movable/proc/do_attack_animation(atom/A)
|
||||
/mob/proc/do_attack_animation(mob/M)
|
||||
|
||||
var/pixel_x_diff = 0
|
||||
var/pixel_y_diff = 0
|
||||
var/direction = get_dir(src, A)
|
||||
var/direction = get_dir(src, M)
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
pixel_y_diff = 8
|
||||
@@ -167,7 +167,7 @@ note dizziness decrements automatically in the mob's Life() proc.
|
||||
pixel_x_diff = -8
|
||||
pixel_y_diff = -8
|
||||
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2)
|
||||
animate(pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 2)
|
||||
animate(pixel_x = old_x, pixel_y = old_y, time = 2)
|
||||
|
||||
/mob/do_attack_animation(atom/A)
|
||||
..()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/mob/dead/dust() //ghosts can't be vaporised.
|
||||
/mob/observer/dust() //ghosts can't be vaporised.
|
||||
return
|
||||
|
||||
/mob/dead/gib() //ghosts can't be gibbed.
|
||||
/mob/observer/gib() //ghosts can't be gibbed.
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/dead/observer/Login()
|
||||
/mob/observer/dead/Login()
|
||||
..()
|
||||
if (ghostimage)
|
||||
ghostimage.icon_state = src.icon_state
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/dead/observer/Logout()
|
||||
/mob/observer/dead/Logout()
|
||||
..()
|
||||
spawn(0)
|
||||
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
var/global/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
|
||||
var/global/list/image/ghost_sightless_images = list() //this is a list of images for things ghosts should still be able to see even without ghost sight
|
||||
|
||||
/mob/dead/observer
|
||||
/mob/observer
|
||||
name = "observer"
|
||||
desc = "This shouldn't appear"
|
||||
density = 0
|
||||
|
||||
/mob/observer/dead
|
||||
name = "ghost"
|
||||
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon = 'icons/mob/ghost.dmi'
|
||||
icon_state = "ghost"
|
||||
layer = 4
|
||||
stat = DEAD
|
||||
density = 0
|
||||
canmove = 0
|
||||
blinded = 0
|
||||
anchored = 1 // don't get pushed around
|
||||
@@ -31,11 +35,52 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
var/seedarkness = 1
|
||||
incorporeal_move = 1
|
||||
|
||||
/mob/dead/observer/New(mob/body)
|
||||
var/is_manifest = 0 //If set to 1, the ghost is able to whisper. Usually only set if a cultist drags them through the veil.
|
||||
var/ghost_sprite = null
|
||||
var/global/list/possible_ghost_sprites = list(
|
||||
"Clear" = "blank",
|
||||
"Green Blob" = "otherthing",
|
||||
"Bland" = "ghost",
|
||||
"Robed-B" = "ghost1",
|
||||
"Robed-BAlt" = "ghost2",
|
||||
"Corgi" = "corgi",
|
||||
"King" = "ghostking",
|
||||
"Shade" = "shade",
|
||||
"Hecate" = "ghost-narsie",
|
||||
"Glowing Statue" = "armour",
|
||||
"Artificer" = "artificer",
|
||||
"Behemoth" = "behemoth",
|
||||
"Harvester" = "harvester",
|
||||
"Wraith" = "wraith",
|
||||
"Viscerator" = "viscerator",
|
||||
"Bats" = "bat",
|
||||
"Red Robes" = "robe_red",
|
||||
"Faithless" = "faithless",
|
||||
"Shadowform" = "forgotten",
|
||||
"Black Cat" = "blackcat",
|
||||
"Dark Ethereal" = "bloodguardian",
|
||||
"Holy Ethereal" = "lightguardian",
|
||||
"Red Elemental" = "magicRed",
|
||||
"Blue Elemental" = "magicBlue",
|
||||
"Pink Elemental" = "magicPink",
|
||||
"Orange Elemental" = "magicOrange",
|
||||
"Green Elemental" = "magicGreen",
|
||||
"Daemon" = "daemon",
|
||||
"Guard Spider" = "guard",
|
||||
"Hunter Spider" = "hunter",
|
||||
"Nurse Spider" = "nurse",
|
||||
"Carp" = "carp",
|
||||
"Space Bear" = "bear",
|
||||
"Rogue Drone" = "drone",
|
||||
"ED-209" = "ed209",
|
||||
"Beepsky" = "secbot"
|
||||
)
|
||||
|
||||
/mob/observer/dead/New(mob/body)
|
||||
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
|
||||
see_invisible = SEE_INVISIBLE_OBSERVER
|
||||
see_in_dark = 100
|
||||
verbs += /mob/dead/observer/proc/dead_tele
|
||||
verbs += /mob/observer/dead/proc/dead_tele
|
||||
|
||||
stat = DEAD
|
||||
|
||||
@@ -81,7 +126,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
real_name = name
|
||||
..()
|
||||
|
||||
/mob/dead/observer/Destroy()
|
||||
/mob/observer/dead/Destroy()
|
||||
if (ghostimage)
|
||||
ghost_darkness_images -= ghostimage
|
||||
qdel(ghostimage)
|
||||
@@ -89,7 +134,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
updateallghostimages()
|
||||
..()
|
||||
|
||||
/mob/dead/observer/Topic(href, href_list)
|
||||
/mob/observer/dead/Topic(href, href_list)
|
||||
if (href_list["track"])
|
||||
var/mob/target = locate(href_list["track"]) in mob_list
|
||||
if(target)
|
||||
@@ -97,19 +142,19 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
|
||||
|
||||
|
||||
/mob/dead/attackby(obj/item/W, mob/user)
|
||||
/mob/observer/dead/attackby(obj/item/W, mob/user)
|
||||
if(istype(W,/obj/item/weapon/book/tome))
|
||||
var/mob/dead/M = src
|
||||
var/mob/observer/dead/M = src
|
||||
M.manifest(user)
|
||||
|
||||
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
/mob/observer/dead/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
return 1
|
||||
/*
|
||||
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/dead/observer/Life()
|
||||
/mob/observer/dead/Life()
|
||||
..()
|
||||
if(!loc) return
|
||||
if(!client) return 0
|
||||
@@ -131,13 +176,13 @@ Works together with spawning an observer, noted above.
|
||||
process_medHUD(src)
|
||||
|
||||
|
||||
/mob/dead/proc/process_medHUD(var/mob/M)
|
||||
/mob/observer/dead/proc/process_medHUD(var/mob/M)
|
||||
var/client/C = M.client
|
||||
for(var/mob/living/carbon/human/patient in oview(M, 14))
|
||||
C.images += patient.hud_list[HEALTH_HUD]
|
||||
C.images += patient.hud_list[STATUS_HUD_OOC]
|
||||
|
||||
/mob/dead/proc/assess_targets(list/target_list, mob/dead/observer/U)
|
||||
/mob/observer/dead/proc/assess_targets(list/target_list, mob/observer/dead/U)
|
||||
var/client/C = U.client
|
||||
for(var/mob/living/carbon/human/target in target_list)
|
||||
C.images += target.hud_list[SPECIALROLE_HUD]
|
||||
@@ -147,14 +192,20 @@ Works together with spawning an observer, noted above.
|
||||
|
||||
/mob/proc/ghostize(var/can_reenter_corpse = 1)
|
||||
if(key)
|
||||
var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc.
|
||||
var/mob/observer/dead/ghost = new(src) //Transfer safety to observer spawning proc.
|
||||
ghost.can_reenter_corpse = can_reenter_corpse
|
||||
ghost.timeofdeath = src.timeofdeath //BS12 EDIT
|
||||
ghost.key = key
|
||||
if(istype(loc, /obj/structure/morgue))
|
||||
var/obj/structure/morgue/M = loc
|
||||
M.update()
|
||||
else if(istype(loc, /obj/structure/closet/body_bag))
|
||||
var/obj/structure/closet/body_bag/B = loc
|
||||
B.update()
|
||||
if(ghost.client)
|
||||
ghost.client.time_died_as_mouse = ghost.timeofdeath
|
||||
if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
|
||||
ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
|
||||
ghost.verbs -= /mob/observer/dead/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
|
||||
return ghost
|
||||
|
||||
/*
|
||||
@@ -183,14 +234,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/turf/location = get_turf(src)
|
||||
message_admins("[key_name_admin(usr)] has ghosted. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
|
||||
log_game("[key_name_admin(usr)] has ghosted.")
|
||||
var/mob/dead/observer/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
|
||||
var/mob/observer/dead/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
|
||||
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
|
||||
announce_ghost_joinleave(ghost)
|
||||
|
||||
/mob/dead/observer/can_use_hands() return 0
|
||||
/mob/dead/observer/is_active() return 0
|
||||
/mob/observer/dead/can_use_hands() return 0
|
||||
/mob/observer/dead/is_active() return 0
|
||||
|
||||
/mob/dead/observer/Stat()
|
||||
/mob/observer/dead/Stat()
|
||||
..()
|
||||
if(statpanel("Status"))
|
||||
if(emergency_shuttle)
|
||||
@@ -198,7 +249,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(eta_status)
|
||||
stat(null, eta_status)
|
||||
|
||||
/mob/dead/observer/verb/reenter_corpse()
|
||||
/mob/observer/dead/verb/reenter_corpse()
|
||||
set category = "Ghost"
|
||||
set name = "Re-enter Corpse"
|
||||
if(!client) return
|
||||
@@ -220,11 +271,17 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
mind.current.ajourn=0
|
||||
mind.current.key = key
|
||||
mind.current.teleop = null
|
||||
if(istype(mind.current.loc, /obj/structure/morgue))
|
||||
var/obj/structure/morgue/M = mind.current.loc
|
||||
M.update(1)
|
||||
else if(istype(mind.current.loc, /obj/structure/closet/body_bag))
|
||||
var/obj/structure/closet/body_bag/B = mind.current.loc
|
||||
B.update(1)
|
||||
if(!admin_ghosted)
|
||||
announce_ghost_joinleave(mind, 0, "They now occupy their body again.")
|
||||
return 1
|
||||
|
||||
/mob/dead/observer/verb/toggle_medHUD()
|
||||
/mob/observer/dead/verb/toggle_medHUD()
|
||||
set category = "Ghost"
|
||||
set name = "Toggle MedicHUD"
|
||||
set desc = "Toggles Medical HUD allowing you to see how everyone is doing"
|
||||
@@ -237,7 +294,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
medHUD = 1
|
||||
src << "\blue <B>Medical HUD Enabled</B>"
|
||||
|
||||
/mob/dead/observer/verb/toggle_antagHUD()
|
||||
/mob/observer/dead/verb/toggle_antagHUD()
|
||||
set category = "Ghost"
|
||||
set name = "Toggle AntagHUD"
|
||||
set desc = "Toggles AntagHUD allowing you to see who is the antagonist"
|
||||
@@ -248,7 +305,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(!config.antag_hud_allowed && (!client.holder || mentor))
|
||||
src << "\red Admins have disabled this for this round."
|
||||
return
|
||||
var/mob/dead/observer/M = src
|
||||
var/mob/observer/dead/M = src
|
||||
if(jobban_isbanned(M, "AntagHUD"))
|
||||
src << "\red <B>You have been banned from using this feature</B>"
|
||||
return
|
||||
@@ -265,16 +322,16 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
M.antagHUD = 1
|
||||
src << "\blue <B>AntagHUD Enabled</B>"
|
||||
|
||||
/mob/dead/observer/proc/dead_tele(A in ghostteleportlocs)
|
||||
/mob/observer/dead/proc/dead_tele(A in ghostteleportlocs)
|
||||
set category = "Ghost"
|
||||
set name = "Teleport"
|
||||
set desc= "Teleport to a location"
|
||||
if(!istype(usr, /mob/dead/observer))
|
||||
if(!istype(usr, /mob/observer/dead))
|
||||
usr << "Not when you're not dead!"
|
||||
return
|
||||
usr.verbs -= /mob/dead/observer/proc/dead_tele
|
||||
usr.verbs -= /mob/observer/dead/proc/dead_tele
|
||||
spawn(30)
|
||||
usr.verbs += /mob/dead/observer/proc/dead_tele
|
||||
usr.verbs += /mob/observer/dead/proc/dead_tele
|
||||
var/area/thearea = ghostteleportlocs[A]
|
||||
if(!thearea) return
|
||||
|
||||
@@ -300,7 +357,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
usr.forceMove(pick(L))
|
||||
following = null
|
||||
|
||||
/mob/dead/observer/verb/follow(input in getmobs())
|
||||
/mob/observer/dead/verb/follow(input in getmobs())
|
||||
set category = "Ghost"
|
||||
set name = "Follow" // "Haunt"
|
||||
set desc = "Follow and haunt a mob."
|
||||
@@ -310,7 +367,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
ManualFollow(target)
|
||||
|
||||
// This is the ghost's follow verb with an argument
|
||||
/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
|
||||
/mob/observer/dead/proc/ManualFollow(var/atom/movable/target)
|
||||
if(!target)
|
||||
return
|
||||
|
||||
@@ -340,7 +397,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
/mob/proc/update_following()
|
||||
. = get_turf(src)
|
||||
for(var/mob/dead/observer/M in following_mobs)
|
||||
for(var/mob/observer/dead/M in following_mobs)
|
||||
if(M.following != src)
|
||||
following_mobs -= M
|
||||
else
|
||||
@@ -351,12 +408,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/list/following_mobs = list()
|
||||
|
||||
/mob/Destroy()
|
||||
for(var/mob/dead/observer/M in following_mobs)
|
||||
for(var/mob/observer/dead/M in following_mobs)
|
||||
M.following = null
|
||||
following_mobs = null
|
||||
return ..()
|
||||
|
||||
/mob/dead/observer/Destroy()
|
||||
/mob/observer/dead/Destroy()
|
||||
if(ismob(following))
|
||||
var/mob/M = following
|
||||
M.following_mobs -= src
|
||||
@@ -376,18 +433,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
/mob/proc/check_holy(var/turf/T)
|
||||
return 0
|
||||
|
||||
/mob/dead/observer/check_holy(var/turf/T)
|
||||
/mob/observer/dead/check_holy(var/turf/T)
|
||||
if(check_rights(R_ADMIN|R_FUN, 0, src))
|
||||
return 0
|
||||
|
||||
return (T && T.holy) && (invisibility <= SEE_INVISIBLE_LIVING || (mind in cult.current_antagonists))
|
||||
|
||||
/mob/dead/observer/verb/jumptomob(target in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak
|
||||
/mob/observer/dead/verb/jumptomob(target in getmobs()) //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!
|
||||
if(istype(usr, /mob/observer/dead)) //Make sure they're an observer!
|
||||
|
||||
if (!target)//Make sure we actually have a target
|
||||
return
|
||||
@@ -401,7 +458,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
else
|
||||
src << "This mob is not located in the game world."
|
||||
/*
|
||||
/mob/dead/observer/verb/boo()
|
||||
/mob/observer/dead/verb/boo()
|
||||
set category = "Ghost"
|
||||
set name = "Boo!"
|
||||
set desc= "Scare your crew members because of boredom!"
|
||||
@@ -416,22 +473,22 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
return
|
||||
*/
|
||||
|
||||
/mob/dead/observer/memory()
|
||||
/mob/observer/dead/memory()
|
||||
set hidden = 1
|
||||
src << "\red You are dead! You have no mind to store memory!"
|
||||
|
||||
/mob/dead/observer/add_memory()
|
||||
/mob/observer/dead/add_memory()
|
||||
set hidden = 1
|
||||
src << "\red You are dead! You have no mind to store memory!"
|
||||
|
||||
/mob/dead/observer/Post_Incorpmove()
|
||||
/mob/observer/dead/Post_Incorpmove()
|
||||
following = null
|
||||
|
||||
/mob/dead/observer/verb/analyze_air()
|
||||
/mob/observer/dead/verb/analyze_air()
|
||||
set name = "Analyze Air"
|
||||
set category = "Ghost"
|
||||
|
||||
if(!istype(usr, /mob/dead/observer)) return
|
||||
if(!istype(usr, /mob/observer/dead)) return
|
||||
|
||||
// Shamelessly copied from the Gas Analyzers
|
||||
if (!( istype(usr.loc, /turf) ))
|
||||
@@ -453,7 +510,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
src << "\blue Temperature: [round(environment.temperature-T0C,0.1)]°C ([round(environment.temperature,0.1)]K)"
|
||||
src << "\blue Heat Capacity: [round(environment.heat_capacity(),0.1)]"
|
||||
|
||||
/mob/dead/observer/verb/become_mouse()
|
||||
/mob/observer/dead/verb/become_mouse()
|
||||
set name = "Become mouse"
|
||||
set category = "Ghost"
|
||||
|
||||
@@ -500,7 +557,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
host.ckey = src.ckey
|
||||
host << "<span class='info'>You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.</span>"
|
||||
|
||||
/mob/dead/observer/verb/view_manfiest()
|
||||
/mob/observer/dead/verb/view_manfiest()
|
||||
set name = "Show Crew Manifest"
|
||||
set category = "Ghost"
|
||||
|
||||
@@ -511,7 +568,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
src << browse(dat, "window=manifest;size=370x420;can_close=1")
|
||||
|
||||
//This is called when a ghost is drag clicked to something.
|
||||
/mob/dead/observer/MouseDrop(atom/over)
|
||||
/mob/observer/dead/MouseDrop(atom/over)
|
||||
if(!usr || !over) return
|
||||
if (isobserver(usr) && usr.client && usr.client.holder && isliving(over))
|
||||
if (usr.client.holder.cmd_ghost_drag(src,over))
|
||||
@@ -520,7 +577,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
return ..()
|
||||
|
||||
//Used for drawing on walls with blood puddles as a spooky ghost.
|
||||
/mob/dead/verb/bloody_doodle()
|
||||
/mob/observer/dead/verb/bloody_doodle()
|
||||
|
||||
set category = "Ghost"
|
||||
set name = "Write in blood"
|
||||
@@ -594,18 +651,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
W.add_hiddenprint(src)
|
||||
W.visible_message("\red Invisible fingers crudely paint something in blood on [T]...")
|
||||
|
||||
/mob/dead/observer/pointed(atom/A as mob|obj|turf in view())
|
||||
/mob/observer/dead/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/proc/manifest(mob/user)
|
||||
var/is_manifest = 0
|
||||
/mob/observer/dead/proc/manifest(mob/user)
|
||||
is_manifest = 0
|
||||
if(!is_manifest)
|
||||
is_manifest = 1
|
||||
verbs += /mob/dead/proc/toggle_visibility
|
||||
|
||||
verbs += /mob/observer/dead/proc/toggle_visibility
|
||||
verbs += /mob/observer/dead/proc/ghost_whisper
|
||||
src << "<font color='purple'>As you are now in the realm of the living, you can whisper to the living with the <b>Spectral Whisper</b> verb, inside the IC tab.</font>"
|
||||
if(src.invisibility != 0)
|
||||
user.visible_message( \
|
||||
"<span class='warning'>\The [user] drags ghost, [src], to our plane of reality!</span>", \
|
||||
@@ -618,7 +676,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
"<span class='warning'>You get the feeling that the ghost can't become any more visible.</span>" \
|
||||
)
|
||||
|
||||
/mob/dead/proc/toggle_icon(var/icon)
|
||||
/mob/observer/dead/proc/toggle_icon(var/icon)
|
||||
if(!client)
|
||||
return
|
||||
|
||||
@@ -632,7 +690,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/image/J = image('icons/mob/mob.dmi', loc = src, icon_state = icon)
|
||||
client.images += J
|
||||
|
||||
/mob/dead/proc/toggle_visibility(var/forced = 0)
|
||||
/mob/observer/dead/proc/toggle_visibility(var/forced = 0)
|
||||
set category = "Ghost"
|
||||
set name = "Toggle Visibility"
|
||||
set desc = "Allows you to turn (in)visible (almost) at will."
|
||||
@@ -652,7 +710,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
// Give the ghost a cult icon which should be visible only to itself
|
||||
toggle_icon("cult")
|
||||
|
||||
/mob/dead/observer/verb/toggle_anonsay()
|
||||
/mob/observer/dead/verb/toggle_anonsay()
|
||||
set category = "Ghost"
|
||||
set name = "Toggle Anonymous Chat"
|
||||
set desc = "Toggles showing your key in dead chat."
|
||||
@@ -663,13 +721,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
else
|
||||
src << "<span class='info'>Your key will be publicly visible again.</span>"
|
||||
|
||||
/mob/dead/observer/canface()
|
||||
/mob/observer/dead/canface()
|
||||
return 1
|
||||
|
||||
/mob/dead/observer/proc/can_admin_interact()
|
||||
/mob/observer/dead/proc/can_admin_interact()
|
||||
return check_rights(R_ADMIN, 0, src)
|
||||
|
||||
/mob/dead/observer/verb/toggle_ghostsee()
|
||||
/mob/observer/dead/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"
|
||||
@@ -677,13 +735,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
updateghostsight()
|
||||
usr << "You [(ghostvision?"now":"no longer")] have ghost vision."
|
||||
|
||||
/mob/dead/observer/verb/toggle_darkness()
|
||||
/mob/observer/dead/verb/toggle_darkness()
|
||||
set name = "Toggle Darkness"
|
||||
set category = "Ghost"
|
||||
seedarkness = !(seedarkness)
|
||||
updateghostsight()
|
||||
|
||||
/mob/dead/observer/proc/updateghostsight()
|
||||
/mob/observer/dead/proc/updateghostsight()
|
||||
if (!seedarkness)
|
||||
see_invisible = SEE_INVISIBLE_NOLIGHTING
|
||||
else
|
||||
@@ -693,10 +751,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
updateghostimages()
|
||||
|
||||
/proc/updateallghostimages()
|
||||
for (var/mob/dead/observer/O in player_list)
|
||||
for (var/mob/observer/dead/O in player_list)
|
||||
O.updateghostimages()
|
||||
|
||||
/mob/dead/observer/proc/updateghostimages()
|
||||
/mob/observer/dead/proc/updateghostimages()
|
||||
if (!client)
|
||||
return
|
||||
if (seedarkness || !ghostvision)
|
||||
@@ -709,7 +767,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if (ghostimage)
|
||||
client.images -= ghostimage //remove ourself
|
||||
|
||||
mob/dead/observer/MayRespawn(var/feedback = 0)
|
||||
mob/observer/dead/MayRespawn(var/feedback = 0)
|
||||
if(!client)
|
||||
return 0
|
||||
if(mind && mind.current && mind.current.stat != DEAD && can_reenter_corpse)
|
||||
@@ -729,7 +787,7 @@ mob/dead/observer/MayRespawn(var/feedback = 0)
|
||||
if(client && eyeobj)
|
||||
return "|<a href='byond://?src=\ref[ghost];track=\ref[eyeobj]'>eye</a>"
|
||||
|
||||
/mob/dead/observer/extra_ghost_link(var/atom/ghost)
|
||||
/mob/observer/dead/extra_ghost_link(var/atom/ghost)
|
||||
if(mind && mind.current)
|
||||
return "|<a href='byond://?src=\ref[ghost];track=\ref[mind.current]'>body</a>"
|
||||
|
||||
@@ -737,3 +795,45 @@ mob/dead/observer/MayRespawn(var/feedback = 0)
|
||||
if((!target) || (!ghost)) return
|
||||
. = "<a href='byond://?src=\ref[ghost];track=\ref[target]'>follow</a>"
|
||||
. += target.extra_ghost_link(ghost)
|
||||
|
||||
//Culted Ghosts
|
||||
|
||||
/mob/observer/dead/proc/ghost_whisper()
|
||||
set name = "Spectral Whisper"
|
||||
set category = "IC"
|
||||
|
||||
if(is_manifest) //Only able to whisper if it's hit with a tome.
|
||||
var/list/options = list()
|
||||
for(var/mob/living/Ms in view(src))
|
||||
options += Ms
|
||||
var/mob/living/M = input(src, "Select who to whisper to:", "Whisper to?", null) as null|mob in options
|
||||
if(!M)
|
||||
return 0
|
||||
var/msg = sanitize(input(src, "Message:", "Spectral Whisper") as text|null)
|
||||
if(msg)
|
||||
log_say("SpectralWhisper: [key_name(usr)]->[M.key] : [msg]")
|
||||
M << "<span class='warning'> You hear a strange, unidentifiable voice in your head... <font color='purple'>[msg]</font></span>"
|
||||
src << "<span class='warning'> You said: '[msg]' to [M].</span>"
|
||||
else
|
||||
return
|
||||
return 1
|
||||
else
|
||||
src << "<span class='danger'>You have not been pulled past the veil!</span>"
|
||||
|
||||
/mob/observer/dead/verb/choose_ghost_sprite()
|
||||
set category = "Ghost"
|
||||
set name = "Choose Sprite"
|
||||
|
||||
icon = 'icons/mob/ghost.dmi'
|
||||
overlays.Cut()
|
||||
var/choice
|
||||
var/finalized = "No"
|
||||
while(finalized == "No" && src.client)
|
||||
|
||||
choice = input(usr,"What would you like to use for your ghost sprite?") as null|anything in possible_ghost_sprites
|
||||
if(!choice) return
|
||||
|
||||
icon_state = possible_ghost_sprites[choice]
|
||||
finalized = alert("Look at your sprite. Is this what you wish to use?",,"No","Yes")
|
||||
|
||||
ghost_sprite = possible_ghost_sprites[choice]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/dead/observer/say(var/message)
|
||||
/mob/observer/dead/say(var/message)
|
||||
message = sanitize(message)
|
||||
|
||||
if (!message)
|
||||
@@ -11,13 +11,10 @@
|
||||
src << "\red You cannot talk in deadchat (muted)."
|
||||
return
|
||||
|
||||
if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
. = src.say_dead(message)
|
||||
|
||||
|
||||
/mob/dead/observer/emote(var/act, var/type, var/message)
|
||||
/mob/observer/dead/emote(var/act, var/type, var/message)
|
||||
//message = sanitize(message) - already sanitized in verb/me_verb()
|
||||
|
||||
if(!message)
|
||||
@@ -33,9 +30,6 @@
|
||||
src << "\red You cannot emote in deadchat (muted)."
|
||||
return
|
||||
|
||||
if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT))
|
||||
return
|
||||
|
||||
. = src.emote_dead(message)
|
||||
|
||||
/*
|
||||
|
||||
@@ -66,9 +66,6 @@
|
||||
|
||||
layer = MOB_LAYER
|
||||
|
||||
if(blind && client)
|
||||
blind.layer = 0
|
||||
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
see_in_dark = 8
|
||||
see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
@@ -85,6 +82,7 @@
|
||||
dead_mob_list |= src
|
||||
|
||||
updateicon()
|
||||
handle_regular_hud_updates()
|
||||
|
||||
if(ticker && ticker.mode)
|
||||
ticker.mode.check_win()
|
||||
|
||||
+20
-36
@@ -1,7 +1,7 @@
|
||||
// All mobs should have custom emote, really..
|
||||
//m_type == 1 --> visual.
|
||||
//m_type == 2 --> audible
|
||||
/mob/proc/custom_emote(var/m_type=1,var/message = null)
|
||||
/mob/proc/custom_emote(var/m_type=1,var/message = null,var/range=world.view)
|
||||
if(stat || !use_me && usr == src)
|
||||
src << "You are unable to emote."
|
||||
return
|
||||
@@ -23,42 +23,23 @@
|
||||
if (message)
|
||||
log_emote("[name]/[key] : [message]")
|
||||
|
||||
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
|
||||
// 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 player_list)
|
||||
if (!M.client)
|
||||
continue //skip monkeys and leavers
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
if(findtext(message," snores.")) //Because we have so many sleeping people.
|
||||
break
|
||||
if(M.stat == 2 && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
|
||||
M.show_message(message, m_type)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,range,2)
|
||||
var/list/m_viewers = in_range["mobs"]
|
||||
var/list/o_viewers = in_range["objs"]
|
||||
|
||||
if (m_type & 1)
|
||||
var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null)
|
||||
for(var/I in see)
|
||||
if(isobj(I))
|
||||
spawn(0)
|
||||
if(I) //It's possible that it could be deleted in the meantime.
|
||||
var/obj/O = I
|
||||
O.see_emote(src, message, 1)
|
||||
else if(ismob(I))
|
||||
var/mob/M = I
|
||||
M.show_message(message, 1)
|
||||
|
||||
else if (m_type & 2)
|
||||
var/list/hear = get_mobs_or_objects_in_view(world.view,src)
|
||||
for(var/I in hear)
|
||||
if(isobj(I))
|
||||
spawn(0)
|
||||
if(I) //It's possible that it could be deleted in the meantime.
|
||||
var/obj/O = I
|
||||
O.see_emote(src, message, 2)
|
||||
else if(ismob(I))
|
||||
var/mob/M = I
|
||||
M.show_message(message, 2)
|
||||
for(var/mob/M in m_viewers)
|
||||
spawn(0) // It's possible that it could be deleted in the meantime, or that it runtimes.
|
||||
if(M)
|
||||
M.show_message(message, m_type)
|
||||
for(var/obj/O in o_viewers)
|
||||
spawn(0)
|
||||
if(O)
|
||||
O.see_emote(src, message, m_type)
|
||||
|
||||
/mob/proc/emote_dead(var/message)
|
||||
|
||||
@@ -66,7 +47,7 @@
|
||||
src << "<span class='danger'>You cannot send deadchat emotes (muted).</span>"
|
||||
return
|
||||
|
||||
if(!(client.prefs.toggles & CHAT_DEAD))
|
||||
if(!is_preference_enabled(/datum/client_preference/show_dsay))
|
||||
src << "<span class='danger'>You have deadchat muted.</span>"
|
||||
return
|
||||
|
||||
@@ -84,4 +65,7 @@
|
||||
|
||||
if(input)
|
||||
log_emote("Ghost/[src.key] : [input]")
|
||||
say_dead_direct(input, src)
|
||||
if(!invisibility) //If the ghost is made visible by admins or cult. And to see if the ghost has toggled its own visibility, as well. -Mech
|
||||
visible_message("<span class='deadsay'><B>[src]</B> [input]</span>")
|
||||
else
|
||||
say_dead_direct(input, src)
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
// A mob that the AI controls to look around the station with.
|
||||
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
|
||||
|
||||
/mob/eye/aiEye
|
||||
/mob/observer/eye/aiEye
|
||||
name = "Inactive AI Eye"
|
||||
icon_state = "AI-eye"
|
||||
|
||||
/mob/eye/aiEye/New()
|
||||
/mob/observer/eye/aiEye/New()
|
||||
..()
|
||||
visualnet = cameranet
|
||||
|
||||
/mob/eye/aiEye/setLoc(var/T, var/cancel_tracking = 1)
|
||||
/mob/observer/eye/aiEye/setLoc(var/T, var/cancel_tracking = 1)
|
||||
if(..())
|
||||
var/mob/living/silicon/ai/ai = owner
|
||||
if(cancel_tracking)
|
||||
@@ -43,7 +43,7 @@
|
||||
/mob/living/silicon/ai/proc/create_eyeobj(var/newloc)
|
||||
if(eyeobj) destroy_eyeobj()
|
||||
if(!newloc) newloc = src.loc
|
||||
eyeobj = PoolOrNew(/mob/eye/aiEye, newloc)
|
||||
eyeobj = PoolOrNew(/mob/observer/eye/aiEye, newloc)
|
||||
eyeobj.owner = src
|
||||
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
|
||||
if(client) client.eye = eyeobj
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
// Add an eye to the chunk, then update if changed.
|
||||
|
||||
/datum/chunk/proc/add(mob/eye/eye)
|
||||
/datum/chunk/proc/add(mob/observer/eye/eye)
|
||||
if(!eye.owner)
|
||||
return
|
||||
eye.visibleChunks += src
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
// Remove an eye from the chunk, then update if changed.
|
||||
|
||||
/datum/chunk/proc/remove(mob/eye/eye)
|
||||
/datum/chunk/proc/remove(mob/observer/eye/eye)
|
||||
if(!eye.owner)
|
||||
return
|
||||
eye.visibleChunks -= src
|
||||
@@ -91,7 +91,7 @@
|
||||
if(t.obfuscations[obfuscation.type])
|
||||
obscured -= t.obfuscations[obfuscation.type]
|
||||
for(var/eye in seenby)
|
||||
var/mob/eye/m = eye
|
||||
var/mob/observer/eye/m = eye
|
||||
if(!m || !m.owner)
|
||||
continue
|
||||
if(m.owner.client)
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
obscured += t.obfuscations[obfuscation.type]
|
||||
for(var/eye in seenby)
|
||||
var/mob/eye/m = eye
|
||||
var/mob/observer/eye/m = eye
|
||||
if(!m || !m.owner)
|
||||
seenby -= m
|
||||
continue
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
// A mob that another mob controls to look around the station with.
|
||||
// It streams chunks as it moves around, which will show it what the controller can and cannot see.
|
||||
|
||||
/mob/eye
|
||||
/mob/observer/eye
|
||||
name = "Eye"
|
||||
icon = 'icons/mob/eye.dmi'
|
||||
icon_state = "default-eye"
|
||||
alpha = 127
|
||||
density = 0
|
||||
|
||||
var/sprint = 10
|
||||
var/cooldown = 0
|
||||
@@ -25,14 +24,14 @@
|
||||
var/ghostimage = null
|
||||
var/datum/visualnet/visualnet
|
||||
|
||||
/mob/eye/New()
|
||||
/mob/observer/eye/New()
|
||||
ghostimage = image(src.icon,src,src.icon_state)
|
||||
ghost_darkness_images |= ghostimage //so ghosts can see the eye when they disable darkness
|
||||
ghost_sightless_images |= ghostimage //so ghosts can see the eye when they disable ghost sight
|
||||
updateallghostimages()
|
||||
..()
|
||||
|
||||
mob/eye/Destroy()
|
||||
mob/observer/eye/Destroy()
|
||||
if (ghostimage)
|
||||
ghost_darkness_images -= ghostimage
|
||||
ghost_sightless_images -= ghostimage
|
||||
@@ -41,30 +40,30 @@ mob/eye/Destroy()
|
||||
updateallghostimages()
|
||||
..()
|
||||
|
||||
/mob/eye/Move(n, direct)
|
||||
/mob/observer/eye/Move(n, direct)
|
||||
if(owner == src)
|
||||
return EyeMove(n, direct)
|
||||
return 0
|
||||
|
||||
/mob/eye/airflow_hit(atom/A)
|
||||
/mob/observer/eye/airflow_hit(atom/A)
|
||||
airflow_speed = 0
|
||||
airflow_dest = null
|
||||
|
||||
/mob/eye/examinate()
|
||||
/mob/observer/eye/examinate()
|
||||
set popup_menu = 0
|
||||
set src = usr.contents
|
||||
return 0
|
||||
|
||||
/mob/eye/pointed()
|
||||
/mob/observer/eye/pointed()
|
||||
set popup_menu = 0
|
||||
set src = usr.contents
|
||||
return 0
|
||||
|
||||
/mob/eye/examine(mob/user)
|
||||
/mob/observer/eye/examine(mob/user)
|
||||
|
||||
// Use this when setting the eye's location.
|
||||
// It will also stream the chunk that the new loc is in.
|
||||
/mob/eye/proc/setLoc(var/T)
|
||||
/mob/observer/eye/proc/setLoc(var/T)
|
||||
if(owner)
|
||||
T = get_turf(T)
|
||||
if(T != loc)
|
||||
@@ -82,13 +81,13 @@ mob/eye/Destroy()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/eye/proc/getLoc()
|
||||
/mob/observer/eye/proc/getLoc()
|
||||
if(owner)
|
||||
if(!isturf(owner.loc) || !owner.client)
|
||||
return
|
||||
return loc
|
||||
/mob
|
||||
var/mob/eye/eyeobj
|
||||
var/mob/observer/eye/eyeobj
|
||||
|
||||
/mob/proc/EyeMove(n, direct)
|
||||
if(!eyeobj)
|
||||
@@ -96,7 +95,7 @@ mob/eye/Destroy()
|
||||
|
||||
return eyeobj.EyeMove(n, direct)
|
||||
|
||||
/mob/eye/EyeMove(n, direct)
|
||||
/mob/observer/eye/EyeMove(n, direct)
|
||||
var/initial = initial(sprint)
|
||||
var/max_sprint = 50
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/eye/Life()
|
||||
/mob/observer/eye/Life()
|
||||
..()
|
||||
// If we lost our client, reset the list of visible chunks so they update properly on return
|
||||
if(owner == src && !client)
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// A mob that a cultists controls to look around the station with.
|
||||
// It streams chunks as it moves around, which will show it what the cultist can and cannot see.
|
||||
|
||||
/mob/eye/maskEye
|
||||
/mob/observer/eye/maskEye
|
||||
name = "Eye of Nar-Sie"
|
||||
acceleration = 0
|
||||
owner_follows_eye = 1
|
||||
|
||||
/mob/eye/maskEye/New()
|
||||
/mob/observer/eye/maskEye/New()
|
||||
..()
|
||||
visualnet = cultnet
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
|
||||
|
||||
/datum/visualnet/proc/visibility(mob/eye/eye)
|
||||
/datum/visualnet/proc/visibility(mob/observer/eye/eye)
|
||||
// 0xf = 15
|
||||
var/x1 = max(0, eye.x - 16) & ~0xf
|
||||
var/y1 = max(0, eye.y - 16) & ~0xf
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(speaker && !speaker.client && istype(src,/mob/dead/observer) && client.prefs.toggles & CHAT_GHOSTEARS && !speaker in view(src))
|
||||
if(speaker && !speaker.client && istype(src,/mob/observer/dead) && is_preference_enabled(/datum/client_preference/ghost_ears) && !(speaker in view(src)))
|
||||
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
|
||||
//Or someone snoring. So we make it where they won't hear it.
|
||||
return
|
||||
|
||||
//make sure the air can transmit speech - hearer's side
|
||||
var/turf/T = get_turf(src)
|
||||
if ((T) && (!(istype(src, /mob/dead/observer)))) //Ghosts can hear even in vacuum.
|
||||
if ((T) && (!(istype(src, /mob/observer/dead)))) //Ghosts can hear even in vacuum.
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = (environment)? environment.return_pressure() : 0
|
||||
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
|
||||
@@ -50,13 +50,13 @@
|
||||
message = "<i>[message]</i>"
|
||||
|
||||
var/track = null
|
||||
if(istype(src, /mob/dead/observer))
|
||||
if(italics && client.prefs.toggles & CHAT_GHOSTRADIO)
|
||||
if(istype(src, /mob/observer/dead))
|
||||
if(italics && is_preference_enabled(/datum/client_preference/ghost_radio))
|
||||
return
|
||||
if(speaker_name != speaker.real_name && speaker.real_name)
|
||||
speaker_name = "[speaker.real_name] ([speaker_name])"
|
||||
track = "([ghost_follow_link(speaker, src)]) "
|
||||
if(client.prefs.toggles & CHAT_GHOSTEARS && speaker in view(src))
|
||||
if(is_preference_enabled(/datum/client_preference/ghost_ears) && (speaker in view(src)))
|
||||
message = "<b>[message]</b>"
|
||||
|
||||
if((sdisabilities & DEAF) || ear_deaf)
|
||||
@@ -81,7 +81,7 @@
|
||||
var/time = say_timestamp()
|
||||
src << "[time] [message]"
|
||||
|
||||
/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
|
||||
if(!client)
|
||||
return
|
||||
@@ -177,16 +177,16 @@
|
||||
else
|
||||
track = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[speaker]'>[speaker_name] ([jobname])</a>"
|
||||
|
||||
if(istype(src, /mob/dead/observer))
|
||||
if(istype(src, /mob/observer/dead))
|
||||
if(speaker_name != speaker.real_name && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
|
||||
speaker_name = "[speaker.real_name] ([speaker_name])"
|
||||
track = "[speaker_name] ([ghost_follow_link(speaker, src)])"
|
||||
|
||||
var/formatted
|
||||
if(language)
|
||||
formatted = language.format_message_radio(message, verb)
|
||||
formatted = "[language.format_message_radio(message, verb)][part_c]"
|
||||
else
|
||||
formatted = "[verb], <span class=\"body\">\"[message]\"</span>"
|
||||
formatted = "[verb], <span class=\"body\">\"[message]\"</span>[part_c]"
|
||||
if((sdisabilities & DEAF) || ear_deaf)
|
||||
if(prob(20))
|
||||
src << "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>"
|
||||
@@ -199,7 +199,7 @@
|
||||
/mob/proc/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
|
||||
src << "[part_a][speaker_name][part_b][formatted]"
|
||||
|
||||
/mob/dead/observer/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
|
||||
/mob/observer/dead/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
|
||||
src << "[part_a][track][part_b][formatted]"
|
||||
|
||||
/mob/living/silicon/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
|
||||
@@ -230,7 +230,7 @@
|
||||
var/heard = ""
|
||||
if(prob(15))
|
||||
var/list/punctuation = list(",", "!", ".", ";", "?")
|
||||
var/list/messages = text2list(message, " ")
|
||||
var/list/messages = splittext(message, " ")
|
||||
var/R = rand(1, messages.len)
|
||||
var/heardword = messages[R]
|
||||
if(copytext(heardword,1, 1) in punctuation)
|
||||
|
||||
@@ -18,6 +18,7 @@ var/list/holder_mob_icon_cache = list()
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_holder.dmi',
|
||||
)
|
||||
pixel_y = 8
|
||||
var/mob/living/held_mob
|
||||
|
||||
/obj/item/weapon/holder/New()
|
||||
..()
|
||||
@@ -29,21 +30,26 @@ var/list/holder_mob_icon_cache = list()
|
||||
|
||||
/obj/item/weapon/holder/process()
|
||||
update_state()
|
||||
drop_items()
|
||||
|
||||
/obj/item/weapon/holder/dropped()
|
||||
..()
|
||||
spawn(1)
|
||||
update_state()
|
||||
|
||||
/obj/item/weapon/proc/update_state()
|
||||
/obj/item/weapon/holder/proc/update_state()
|
||||
if(istype(loc,/turf) || !(contents.len))
|
||||
for(var/mob/M in contents)
|
||||
var/atom/movable/mob_container
|
||||
mob_container = M
|
||||
mob_container.forceMove(get_turf(src))
|
||||
M.reset_view()
|
||||
if(held_mob)
|
||||
held_mob.forceMove(loc)
|
||||
drop_items()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/holder/proc/drop_items()
|
||||
for(var/atom/movable/M in contents)
|
||||
if(M == held_mob)
|
||||
continue
|
||||
M.forceMove(get_turf(src))
|
||||
|
||||
/obj/item/weapon/holder/GetID()
|
||||
for(var/mob/M in contents)
|
||||
var/obj/item/I = M.GetIdCard()
|
||||
@@ -108,7 +114,13 @@ var/list/holder_mob_icon_cache = list()
|
||||
if(!holder_type || buckled || pinned.len)
|
||||
return
|
||||
|
||||
if(self_grab)
|
||||
if(src.incapacitated()) return
|
||||
else
|
||||
if(grabber.incapacitated()) return
|
||||
|
||||
var/obj/item/weapon/holder/H = new holder_type(get_turf(src))
|
||||
H.held_mob = src
|
||||
src.forceMove(H)
|
||||
grabber.put_in_hands(H)
|
||||
|
||||
@@ -138,7 +150,7 @@ var/list/holder_mob_icon_cache = list()
|
||||
var/skin_colour = rgb(owner.r_skin, owner.g_skin, owner.b_skin)
|
||||
var/hair_colour = rgb(owner.r_hair, owner.g_hair, owner.b_hair)
|
||||
var/eye_colour = rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)
|
||||
var/species_name = lowertext(owner.species.get_bodytype())
|
||||
var/species_name = lowertext(owner.species.get_bodytype(owner))
|
||||
|
||||
for(var/cache_entry in generate_for_slots)
|
||||
var/cache_key = "[owner.species]-[cache_entry]-[skin_colour]-[hair_colour]"
|
||||
|
||||
@@ -1,43 +1,3 @@
|
||||
//This proc is called whenever someone clicks an inventory ui slot.
|
||||
/mob/proc/attack_ui(slot)
|
||||
var/obj/item/W = get_active_hand()
|
||||
if(istype(W))
|
||||
equip_to_slot_if_possible(W, slot)
|
||||
|
||||
/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1)
|
||||
if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob))
|
||||
return 1
|
||||
else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//This is a SAFE proc. Use this instead of equip_to_slot()!
|
||||
//set del_on_fail to have it delete W if it fails to equip
|
||||
//set disable_warning to disable the 'you are unable to equip that' warning.
|
||||
//unset redraw_mob to prevent the mob from being redrawn at the end.
|
||||
/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1)
|
||||
if(!istype(W)) return 0
|
||||
|
||||
if(!W.mob_can_equip(src, slot))
|
||||
if(del_on_fail)
|
||||
qdel(W)
|
||||
else
|
||||
if(!disable_warning)
|
||||
src << "\red You are unable to equip that." //Only print if del_on_fail is false
|
||||
return 0
|
||||
|
||||
equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
|
||||
return 1
|
||||
|
||||
//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task.
|
||||
//In most cases you will want to use equip_to_slot_if_possible()
|
||||
/mob/proc/equip_to_slot(obj/item/W as obj, slot)
|
||||
return
|
||||
|
||||
//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such.
|
||||
/mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot)
|
||||
return equip_to_slot_if_possible(W, slot, 1, 1, 0)
|
||||
|
||||
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
|
||||
var/list/slot_equipment_priority = list( \
|
||||
slot_back,\
|
||||
@@ -58,6 +18,57 @@ var/list/slot_equipment_priority = list( \
|
||||
slot_r_store\
|
||||
)
|
||||
|
||||
/mob
|
||||
var/obj/item/weapon/storage/s_active = null // Even ghosts can/should be able to peek into boxes on the ground
|
||||
|
||||
//This proc is called whenever someone clicks an inventory ui slot.
|
||||
/mob/proc/attack_ui(var/slot)
|
||||
var/obj/item/W = get_active_hand()
|
||||
|
||||
var/obj/item/E = get_equipped_item(slot)
|
||||
if (istype(E))
|
||||
if(istype(W))
|
||||
E.attackby(W,src)
|
||||
else
|
||||
E.attack_hand(src)
|
||||
else
|
||||
equip_to_slot_if_possible(W, slot)
|
||||
|
||||
/* Inventory manipulation */
|
||||
|
||||
/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1)
|
||||
if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob))
|
||||
return 1
|
||||
else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//This is a SAFE proc. Use this instead of equip_to_slot()!
|
||||
//set del_on_fail to have it delete W if it fails to equip
|
||||
//set disable_warning to disable the 'you are unable to equip that' warning.
|
||||
//unset redraw_mob to prevent the mob from being redrawn at the end.
|
||||
/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1)
|
||||
if(!W.mob_can_equip(src, slot))
|
||||
if(del_on_fail)
|
||||
qdel(W)
|
||||
|
||||
else
|
||||
if(!disable_warning)
|
||||
src << "\red You are unable to equip that." //Only print if del_on_fail is false
|
||||
return 0
|
||||
|
||||
equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
|
||||
return 1
|
||||
|
||||
//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task.
|
||||
//In most cases you will want to use equip_to_slot_if_possible()
|
||||
/mob/proc/equip_to_slot(obj/item/W as obj, slot)
|
||||
return
|
||||
|
||||
//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such.
|
||||
/mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot)
|
||||
return equip_to_slot_if_possible(W, slot, 1, 1, 0)
|
||||
|
||||
//Checks if a given slot can be accessed at this time, either to equip or unequip I
|
||||
/mob/proc/slot_is_accessible(var/slot, var/obj/item/I, mob/user=null)
|
||||
return 1
|
||||
@@ -65,8 +76,6 @@ var/list/slot_equipment_priority = list( \
|
||||
//puts the item "W" into an appropriate slot in a human's inventory
|
||||
//returns 0 if it cannot, 1 if successful
|
||||
/mob/proc/equip_to_appropriate_slot(obj/item/W)
|
||||
if(!istype(W)) return 0
|
||||
|
||||
for(var/slot in slot_equipment_priority)
|
||||
if(equip_to_slot_if_possible(W, slot, del_on_fail=0, disable_warning=1, redraw_mob=1))
|
||||
return 1
|
||||
@@ -74,32 +83,15 @@ var/list/slot_equipment_priority = list( \
|
||||
return 0
|
||||
|
||||
/mob/proc/equip_to_storage(obj/item/newitem)
|
||||
// Try put it in their backpack
|
||||
if(istype(src.back,/obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/backpack = src.back
|
||||
if(backpack.contents.len < backpack.storage_slots)
|
||||
newitem.forceMove(src.back)
|
||||
return 1
|
||||
|
||||
// Try to place it in any item that can store stuff, on the mob.
|
||||
for(var/obj/item/weapon/storage/S in src.contents)
|
||||
if (S.contents.len < S.storage_slots)
|
||||
newitem.forceMove(S)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//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.
|
||||
/* Hands */
|
||||
|
||||
//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
|
||||
|
||||
//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(var/obj/item/W)
|
||||
@@ -150,16 +142,15 @@ var/list/slot_equipment_priority = list( \
|
||||
|
||||
//Drops the item in our left hand
|
||||
/mob/proc/drop_l_hand(var/atom/Target)
|
||||
return drop_from_inventory(l_hand, Target)
|
||||
return 0
|
||||
|
||||
//Drops the item in our right hand
|
||||
/mob/proc/drop_r_hand(var/atom/Target)
|
||||
return drop_from_inventory(r_hand, Target)
|
||||
return 0
|
||||
|
||||
//Drops the item in our active hand. TODO: rename this to drop_active_hand or something
|
||||
/mob/proc/drop_item(var/atom/Target)
|
||||
if(hand) return drop_l_hand(Target)
|
||||
else return drop_r_hand(Target)
|
||||
return
|
||||
|
||||
/*
|
||||
Removes the object from any slots the mob might have, calling the appropriate icon update proc.
|
||||
@@ -173,19 +164,6 @@ var/list/slot_equipment_priority = list( \
|
||||
the search through all the slots, without having to duplicate the rest of the item dropping.
|
||||
*/
|
||||
/mob/proc/u_equip(obj/W as obj)
|
||||
if (W == r_hand)
|
||||
r_hand = null
|
||||
update_inv_r_hand(0)
|
||||
else if (W == l_hand)
|
||||
l_hand = null
|
||||
update_inv_l_hand(0)
|
||||
else if (W == back)
|
||||
back = null
|
||||
update_inv_back(0)
|
||||
else if (W == wear_mask)
|
||||
wear_mask = null
|
||||
update_inv_wear_mask(0)
|
||||
return
|
||||
|
||||
/mob/proc/isEquipped(obj/item/I)
|
||||
if(!I)
|
||||
@@ -206,6 +184,7 @@ var/list/slot_equipment_priority = list( \
|
||||
break
|
||||
return slot
|
||||
|
||||
|
||||
//This differs from remove_from_mob() in that it checks if the item can be unequipped first.
|
||||
/mob/proc/unEquip(obj/item/I, force = 0) //Force overrides NODROP for things like wizarditis and admin undress.
|
||||
if(!(force || canUnEquip(I)))
|
||||
@@ -213,6 +192,7 @@ var/list/slot_equipment_priority = list( \
|
||||
drop_from_inventory(I)
|
||||
return 1
|
||||
|
||||
|
||||
//Attemps to remove an object on a mob.
|
||||
/mob/proc/remove_from_mob(var/obj/O)
|
||||
src.u_equip(O)
|
||||
@@ -229,11 +209,6 @@ var/list/slot_equipment_priority = list( \
|
||||
|
||||
//Returns the item equipped to the specified slot, if any.
|
||||
/mob/proc/get_equipped_item(var/slot)
|
||||
switch(slot)
|
||||
if(slot_l_hand) return l_hand
|
||||
if(slot_r_hand) return r_hand
|
||||
if(slot_back) return back
|
||||
if(slot_wear_mask) return wear_mask
|
||||
return null
|
||||
|
||||
//Outdated but still in use apparently. This should at least be a human proc.
|
||||
@@ -258,3 +233,8 @@ var/list/slot_equipment_priority = list( \
|
||||
//if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand
|
||||
|
||||
return items
|
||||
|
||||
/mob/proc/delete_inventory()
|
||||
for(var/entry in get_equipped_items())
|
||||
drop_from_inventory(entry)
|
||||
qdel(entry)
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
var/speech_verb = "says" // 'says', 'hisses', 'farts'.
|
||||
var/ask_verb = "asks" // Used when sentence ends in a ?
|
||||
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
|
||||
var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead.
|
||||
var/signlang_verb = list("signs") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
|
||||
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
|
||||
var/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
|
||||
var/colour = "body" // CSS style to use for strings in this language.
|
||||
var/key = "x" // Character used to speak in language eg. :o for Unathi.
|
||||
var/flags = 0 // Various language flags.
|
||||
@@ -114,7 +114,7 @@
|
||||
/mob/new_player/hear_broadcast(var/datum/language/language, var/mob/speaker, var/speaker_name, var/message)
|
||||
return
|
||||
|
||||
/mob/dead/observer/hear_broadcast(var/datum/language/language, var/mob/speaker, var/speaker_name, var/message)
|
||||
/mob/observer/dead/hear_broadcast(var/datum/language/language, var/mob/speaker, var/speaker_name, var/message)
|
||||
if(speaker.name == speaker_name || antagHUD)
|
||||
src << "<i><span class='game say'>[language.name], <span class='name'>[speaker_name]</span> ([ghost_follow_link(speaker, src)]) [message]</span></i>"
|
||||
else
|
||||
@@ -158,7 +158,12 @@
|
||||
|
||||
// Can we speak this language, as opposed to just understanding it?
|
||||
/mob/proc/can_speak(datum/language/speaking)
|
||||
return (speaking.can_speak_special(src) && (universal_speak || (speaking && speaking.flags & INNATE) || speaking in src.languages))
|
||||
//Prevents someone from speaking a null language.
|
||||
if(speaking)
|
||||
return (speaking.can_speak_special(src) && (universal_speak || (speaking && (speaking.flags & INNATE)) || speaking in src.languages))
|
||||
else
|
||||
log_debug("[src] attempted to speak a null language.")
|
||||
return 0
|
||||
|
||||
/mob/proc/get_language_prefix()
|
||||
if(client && client.prefs.language_prefixes && client.prefs.language_prefixes.len)
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
..(speaker,message,speaker_mask)
|
||||
|
||||
/datum/language/cultcommon
|
||||
name = "Cult"
|
||||
name = LANGUAGE_CULT
|
||||
desc = "The chants of the occult, the incomprehensible."
|
||||
speech_verb = "intones"
|
||||
ask_verb = "intones"
|
||||
@@ -52,8 +52,8 @@
|
||||
"mah'weyh", "pleggh", "at", "e'ntrath", "tok-lyr", "rqa'nap", "g'lt-ulotf", "ta'gh", "fara'qha", "fel", "d'amar det", \
|
||||
"yu'gular", "faras", "desdae", "havas", "mithum", "javara", "umathar", "uf'kal", "thenar", "rash'tla", \
|
||||
"sektath", "mal'zua", "zasan", "therium", "viortia", "kla'atu", "barada", "nikt'o", "fwe'sh", "mah", "erl", "nyag", "r'ya", \
|
||||
"gal'h'rfikk", "harfrandid", "mud'gib", "fuu", "ma'jin", "dedo", "ol'btoh", "n'ath", "reth", "sh'yro", "eth", \
|
||||
"d'rekkathnor", "khari'd", "gual'te", "nikka", "nikt'o", "barada", "kla'atu", "barhah", "hra" ,"zar'garis")
|
||||
"gal'h'rfikk", "harfrandid", "mud'gib", "il", "fuu", "ma'jin", "dedo", "ol'btoh", "n'ath", "reth", "sh'yro", "eth", \
|
||||
"d'rekkathnor", "khari'd", "gual'te", "nikka", "nikt'o", "barada", "kla'atu", "barhah", "hra" ,"zar'garis", "spiri", "malum")
|
||||
|
||||
/datum/language/cult
|
||||
name = "Occult"
|
||||
|
||||
@@ -23,7 +23,16 @@
|
||||
colour = "soghun"
|
||||
key = "o"
|
||||
flags = WHITELISTED
|
||||
syllables = list("ss","ss","ss","ss","skak","seeki","resh","las","esi","kor","sh")
|
||||
space_chance = 40
|
||||
syllables = list(
|
||||
"za", "az", "ze", "ez", "zi", "iz", "zo", "oz", "zu", "uz", "zs", "sz",
|
||||
"ha", "ah", "he", "eh", "hi", "ih", "ho", "oh", "hu", "uh", "hs", "sh",
|
||||
"la", "al", "le", "el", "li", "il", "lo", "ol", "lu", "ul", "ls", "sl",
|
||||
"ka", "ak", "ke", "ek", "ki", "ik", "ko", "ok", "ku", "uk", "ks", "sk",
|
||||
"sa", "as", "se", "es", "si", "is", "so", "os", "su", "us", "ss", "ss",
|
||||
"ra", "ar", "re", "er", "ri", "ir", "ro", "or", "ru", "ur", "rs", "sr",
|
||||
"a", "a", "e", "e", "i", "i", "o", "o", "u", "u", "s", "s"
|
||||
)
|
||||
|
||||
/datum/language/unathi/get_random_name()
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
. += pick(map[min_char])
|
||||
message = copytext(message, min_index + 1)
|
||||
|
||||
return list2text(.)
|
||||
return jointext(., null)
|
||||
|
||||
#undef AUTOHISS_OFF
|
||||
#undef AUTOHISS_BASIC
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
layer = MOB_LAYER
|
||||
universal_speak = 1
|
||||
density = 0
|
||||
|
||||
var/obj/item/weapon/card/id/botcard = null
|
||||
var/list/botcard_access = list()
|
||||
var/on = 1
|
||||
@@ -13,11 +14,30 @@
|
||||
var/locked = 1
|
||||
var/emagged = 0
|
||||
var/light_strength = 3
|
||||
var/busy = 0
|
||||
|
||||
var/obj/access_scanner = null
|
||||
var/list/req_access = list()
|
||||
var/list/req_one_access = list()
|
||||
|
||||
var/atom/target = null
|
||||
var/list/ignore_list = list()
|
||||
var/list/patrol_path = list()
|
||||
var/list/target_path = list()
|
||||
var/turf/obstacle = null
|
||||
|
||||
var/wait_if_pulled = 0 // Only applies to moving to the target
|
||||
var/will_patrol = 0 // Not a setting - whether or no this type of bots patrols at all
|
||||
var/patrol_speed = 1 // How many times per tick we move when patrolling
|
||||
var/target_speed = 2 // Ditto for chasing the target
|
||||
var/min_target_dist = 1 // How close we try to get to the target
|
||||
var/max_target_dist = 50 // How far we are willing to go
|
||||
var/max_patrol_dist = 250
|
||||
|
||||
var/target_patience = 5
|
||||
var/frustration = 0
|
||||
var/max_frustration = 0
|
||||
|
||||
/mob/living/bot/New()
|
||||
..()
|
||||
update_icons()
|
||||
@@ -40,6 +60,9 @@
|
||||
stunned = 0
|
||||
paralysis = 0
|
||||
|
||||
if(on && !client && !busy)
|
||||
handleAI()
|
||||
|
||||
/mob/living/bot/updatehealth()
|
||||
if(status_flags & GODMODE)
|
||||
health = maxHealth
|
||||
@@ -109,6 +132,123 @@
|
||||
/mob/living/bot/emag_act(var/remaining_charges, var/mob/user)
|
||||
return 0
|
||||
|
||||
/mob/living/bot/proc/handleAI()
|
||||
if(ignore_list.len)
|
||||
for(var/atom/A in ignore_list)
|
||||
if(!A || !A.loc || prob(1))
|
||||
ignore_list -= A
|
||||
handleRegular()
|
||||
if(target && confirmTarget(target))
|
||||
if(Adjacent(target))
|
||||
handleAdjacentTarget()
|
||||
else
|
||||
handleRangedTarget()
|
||||
if(!wait_if_pulled || !pulledby)
|
||||
for(var/i = 1 to target_speed)
|
||||
stepToTarget()
|
||||
if(i < target_speed)
|
||||
sleep(20 / target_speed)
|
||||
if(max_frustration && frustration > max_frustration * target_speed)
|
||||
handleFrustrated(1)
|
||||
else
|
||||
resetTarget()
|
||||
lookForTargets()
|
||||
if(will_patrol && !pulledby && !target)
|
||||
if(patrol_path.len)
|
||||
for(var/i = 1 to patrol_speed)
|
||||
handlePatrol()
|
||||
if(i < patrol_speed)
|
||||
sleep(20 / patrol_speed)
|
||||
if(max_frustration && frustration > max_frustration * patrol_speed)
|
||||
handleFrustrated(0)
|
||||
else
|
||||
startPatrol()
|
||||
else
|
||||
handleIdle()
|
||||
|
||||
/mob/living/bot/proc/handleRegular()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/handleAdjacentTarget()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/handleRangedTarget()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/stepToTarget()
|
||||
if(!target || !target.loc)
|
||||
return
|
||||
if(get_dist(src, target) > min_target_dist)
|
||||
if(!target_path.len || get_turf(target) != target_path[target_path.len])
|
||||
calcTargetPath()
|
||||
if(makeStep(target_path))
|
||||
frustration = 0
|
||||
else if(max_frustration)
|
||||
++frustration
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/handleFrustrated(var/targ)
|
||||
obstacle = targ ? target_path[1] : patrol_path[1]
|
||||
target_path = list()
|
||||
patrol_path = list()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/lookForTargets()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/confirmTarget(var/atom/A)
|
||||
if(A.invisibility >= INVISIBILITY_LEVEL_ONE)
|
||||
return 0
|
||||
if(A in ignore_list)
|
||||
return 0
|
||||
if(!A.loc)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/mob/living/bot/proc/handlePatrol()
|
||||
makeStep(patrol_path)
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/startPatrol()
|
||||
var/turf/T = getPatrolTurf()
|
||||
if(T)
|
||||
patrol_path = AStar(get_turf(loc), T, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, max_patrol_dist, id = botcard, exclude = obstacle)
|
||||
if(!patrol_path)
|
||||
patrol_path = list()
|
||||
obstacle = null
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/getPatrolTurf()
|
||||
return null
|
||||
|
||||
/mob/living/bot/proc/handleIdle()
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/calcTargetPath()
|
||||
target_path = AStar(get_turf(loc), get_turf(target), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, max_target_dist, id = botcard, exclude = obstacle)
|
||||
if(!target_path)
|
||||
if(target && target.loc)
|
||||
ignore_list |= target
|
||||
resetTarget()
|
||||
obstacle = null
|
||||
return
|
||||
|
||||
/mob/living/bot/proc/makeStep(var/list/path)
|
||||
if(!path.len)
|
||||
return 0
|
||||
var/turf/T = path[1]
|
||||
if(get_turf(src) == T)
|
||||
path -= T
|
||||
return makeStep(path)
|
||||
|
||||
return step_towards(src, T)
|
||||
|
||||
/mob/living/bot/proc/resetTarget()
|
||||
target = null
|
||||
target_path = list()
|
||||
frustration = 0
|
||||
obstacle = null
|
||||
|
||||
/mob/living/bot/proc/turn_on()
|
||||
if(stat)
|
||||
return 0
|
||||
@@ -121,13 +261,13 @@
|
||||
on = 0
|
||||
set_light(0)
|
||||
update_icons()
|
||||
resetTarget()
|
||||
patrol_path = list()
|
||||
ignore_list = list()
|
||||
|
||||
/mob/living/bot/proc/explode()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/attack_throat()
|
||||
return
|
||||
|
||||
/******************************************************************/
|
||||
// Navigation procs
|
||||
// Used for A-star pathfinding
|
||||
@@ -141,7 +281,7 @@
|
||||
// for(var/turf/simulated/t in oview(src,1))
|
||||
|
||||
for(var/d in cardinal)
|
||||
var/turf/simulated/T = get_step(src, d)
|
||||
var/turf/T = get_step(src, d)
|
||||
if(istype(T) && !T.density)
|
||||
if(!LinkBlockedWithAccess(src, T, ID))
|
||||
L.Add(T)
|
||||
@@ -194,3 +334,4 @@
|
||||
//if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID)
|
||||
else return !D.check_access(ID) // it's a real, air blocking door
|
||||
return 0
|
||||
|
||||
|
||||
@@ -6,18 +6,8 @@
|
||||
botcard_access = list(access_janitor, access_maint_tunnels)
|
||||
|
||||
locked = 0 // Start unlocked so roboticist can set them to patrol.
|
||||
|
||||
var/obj/effect/decal/cleanable/target
|
||||
var/list/path = list()
|
||||
var/list/patrol_path = list()
|
||||
var/list/ignorelist = list()
|
||||
|
||||
var/obj/cleanbot_listener/listener = null
|
||||
var/beacon_freq = 1445 // navigation beacon frequency
|
||||
var/signal_sent = 0
|
||||
var/closest_dist
|
||||
var/next_dest
|
||||
var/next_dest_loc
|
||||
wait_if_pulled = 1
|
||||
min_target_dist = 0
|
||||
|
||||
var/cleaning = 0
|
||||
var/screwloose = 0
|
||||
@@ -26,48 +16,11 @@
|
||||
var/blood = 1
|
||||
var/list/target_types = list()
|
||||
|
||||
var/maximum_search_range = 7
|
||||
|
||||
/mob/living/bot/cleanbot/New()
|
||||
..()
|
||||
get_targets()
|
||||
|
||||
listener = new /obj/cleanbot_listener(src)
|
||||
listener.cleanbot = src
|
||||
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
|
||||
/mob/living/bot/cleanbot/proc/handle_target()
|
||||
if(loc == target.loc)
|
||||
if(!cleaning)
|
||||
UnarmedAttack(target)
|
||||
return 1
|
||||
if(!path.len)
|
||||
// spawn(0)
|
||||
path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
custom_emote(2, "[src] can't reach the target and is giving up.")
|
||||
target = null
|
||||
path = list()
|
||||
return
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
return 1
|
||||
return
|
||||
|
||||
/mob/living/bot/cleanbot/Life()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(client)
|
||||
return
|
||||
if(cleaning)
|
||||
return
|
||||
|
||||
/mob/living/bot/cleanbot/handleIdle()
|
||||
if(!screwloose && !oddbutton && prob(5))
|
||||
custom_emote(2, "makes an excited beeping booping sound!")
|
||||
|
||||
@@ -79,68 +32,27 @@
|
||||
if(oddbutton && prob(5)) // Make a big mess
|
||||
visible_message("Something flies out of [src]. He seems to be acting oddly.")
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc)
|
||||
ignorelist += gib
|
||||
ignore_list += gib
|
||||
spawn(600)
|
||||
ignorelist -= gib
|
||||
ignore_list -= gib
|
||||
|
||||
// Find a target
|
||||
|
||||
if(pulledby) // Don't wiggle if someone pulls you
|
||||
patrol_path = list()
|
||||
return
|
||||
|
||||
var/found_spot
|
||||
search_loop:
|
||||
for(var/i=0, i <= maximum_search_range, i++)
|
||||
for(var/obj/effect/decal/cleanable/D in view(i, src))
|
||||
if(D in ignorelist)
|
||||
continue
|
||||
for(var/T in target_types)
|
||||
if(istype(D, T))
|
||||
patrol_path = list()
|
||||
target = D
|
||||
found_spot = handle_target()
|
||||
if (found_spot)
|
||||
break search_loop
|
||||
else
|
||||
target = null
|
||||
continue // no need to check the other types
|
||||
|
||||
|
||||
if(!found_spot && !target) // No targets in range
|
||||
if(!patrol_path || !patrol_path.len)
|
||||
if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
closest_dist = 9999
|
||||
next_dest = null
|
||||
next_dest_loc = null
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = src
|
||||
signal.transmission_method = 1
|
||||
signal.data = list("findbeakon" = "patrol")
|
||||
frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
|
||||
signal_sent = world.time
|
||||
else
|
||||
if(next_dest)
|
||||
next_dest_loc = listener.memorized[next_dest]
|
||||
if(next_dest_loc)
|
||||
patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null)
|
||||
signal_sent = 0
|
||||
else
|
||||
if(pulledby) // Don't wiggle if someone pulls you
|
||||
patrol_path = list()
|
||||
return
|
||||
if(patrol_path[1] == loc)
|
||||
patrol_path -= patrol_path[1]
|
||||
var/moved = step_towards(src, patrol_path[1])
|
||||
if(moved)
|
||||
patrol_path -= patrol_path[1]
|
||||
/mob/living/bot/cleanbot/lookForTargets()
|
||||
for(var/obj/effect/decal/cleanable/D in view(world.view, src)) // There was some odd code to make it start with nearest decals, it's unnecessary, this works
|
||||
if(confirmTarget(D))
|
||||
target = D
|
||||
return
|
||||
|
||||
/mob/living/bot/cleanbot/confirmTarget(var/obj/effect/decal/cleanable/D)
|
||||
if(!..())
|
||||
return 0
|
||||
for(var/T in target_types)
|
||||
if(istype(D, T))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/bot/cleanbot/handleAdjacentTarget()
|
||||
if(get_turf(target) == src.loc)
|
||||
UnarmedAttack(target)
|
||||
|
||||
/mob/living/bot/cleanbot/UnarmedAttack(var/obj/effect/decal/cleanable/D, var/proximity)
|
||||
if(!..())
|
||||
@@ -152,7 +64,7 @@
|
||||
if(D.loc != loc)
|
||||
return
|
||||
|
||||
cleaning = 1
|
||||
busy = 1
|
||||
custom_emote(2, "begins to clean up \the [D]")
|
||||
update_icons()
|
||||
var/cleantime = istype(D, /obj/effect/decal/cleanable/dirt) ? 10 : 50
|
||||
@@ -165,7 +77,7 @@
|
||||
qdel(D)
|
||||
if(D == target)
|
||||
target = null
|
||||
cleaning = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
|
||||
/mob/living/bot/cleanbot/explode()
|
||||
@@ -185,17 +97,11 @@
|
||||
return
|
||||
|
||||
/mob/living/bot/cleanbot/update_icons()
|
||||
if(cleaning)
|
||||
if(busy)
|
||||
icon_state = "cleanbot-c"
|
||||
else
|
||||
icon_state = "cleanbot[on]"
|
||||
|
||||
/mob/living/bot/cleanbot/turn_off()
|
||||
..()
|
||||
target = null
|
||||
path = list()
|
||||
patrol_path = list()
|
||||
|
||||
/mob/living/bot/cleanbot/attack_hand(var/mob/user)
|
||||
var/dat
|
||||
dat += "<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>"
|
||||
@@ -230,10 +136,6 @@
|
||||
if("patrol")
|
||||
should_patrol = !should_patrol
|
||||
patrol_path = null
|
||||
if("freq")
|
||||
var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10
|
||||
if (freq > 0)
|
||||
beacon_freq = freq
|
||||
if("screw")
|
||||
screwloose = !screwloose
|
||||
usr << "<span class='notice'>You twiddle the screw.</span>"
|
||||
@@ -264,25 +166,6 @@
|
||||
if(blood)
|
||||
target_types += /obj/effect/decal/cleanable/blood
|
||||
|
||||
/* Radio object that listens to signals */
|
||||
|
||||
/obj/cleanbot_listener
|
||||
var/mob/living/bot/cleanbot/cleanbot = null
|
||||
var/list/memorized = list()
|
||||
|
||||
/obj/cleanbot_listener/receive_signal(var/datum/signal/signal)
|
||||
var/recv = signal.data["beacon"]
|
||||
var/valid = signal.data["patrol"]
|
||||
if(!recv || !valid || !cleanbot)
|
||||
return
|
||||
|
||||
var/dist = get_dist(cleanbot, signal.source.loc)
|
||||
memorized[recv] = signal.source.loc
|
||||
|
||||
if(dist < cleanbot.closest_dist) // We check all signals, choosing the closest beakon; then we move to the NEXT one after the closest one
|
||||
cleanbot.closest_dist = dist
|
||||
cleanbot.next_dest = signal.data["next_patrol"]
|
||||
|
||||
/* Assembly */
|
||||
|
||||
/obj/item/weapon/bucket_sensor
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
|
||||
bot_version = "2.5"
|
||||
is_ranged = 1
|
||||
preparing_arrest_sounds = new()
|
||||
|
||||
@@ -20,7 +19,7 @@
|
||||
var/last_shot = 0
|
||||
|
||||
/mob/living/bot/secbot/ed209/update_icons()
|
||||
if(on && is_attacking)
|
||||
if(on && busy)
|
||||
icon_state = "ed209-c"
|
||||
else
|
||||
icon_state = "ed209[on]"
|
||||
@@ -50,6 +49,9 @@
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/secbot/ed209/handleRangedTarget()
|
||||
RangedAttack(target)
|
||||
|
||||
/mob/living/bot/secbot/ed209/RangedAttack(var/atom/A)
|
||||
if(last_shot + shot_delay > world.time)
|
||||
src << "You are not ready to fire yet!"
|
||||
|
||||
@@ -22,17 +22,14 @@
|
||||
|
||||
var/obj/structure/reagent_dispensers/watertank/tank
|
||||
|
||||
var/attacking = 0
|
||||
var/list/path = list()
|
||||
var/atom/target
|
||||
var/frustration = 0
|
||||
|
||||
/mob/living/bot/farmbot/New()
|
||||
..()
|
||||
spawn(5)
|
||||
tank = locate() in contents
|
||||
if(!tank)
|
||||
tank = new /obj/structure/reagent_dispensers/watertank(src)
|
||||
/mob/living/bot/farmbot/New(var/newloc, var/newTank)
|
||||
..(newloc)
|
||||
if(!newTank)
|
||||
newTank = new /obj/structure/reagent_dispensers/watertank(src)
|
||||
tank = newTank
|
||||
tank.forceMove(src)
|
||||
|
||||
|
||||
/mob/living/bot/farmbot/attack_hand(var/mob/user as mob)
|
||||
. = ..()
|
||||
@@ -110,63 +107,60 @@
|
||||
else
|
||||
icon_state = "farmbot[on]"
|
||||
|
||||
/mob/living/bot/farmbot/Life()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
/mob/living/bot/farmbot/handleRegular()
|
||||
if(emagged && prob(1))
|
||||
flick("farmbot_broke", src)
|
||||
if(client)
|
||||
return
|
||||
|
||||
if(target)
|
||||
if(Adjacent(target))
|
||||
UnarmedAttack(target)
|
||||
path = list()
|
||||
target = null
|
||||
else
|
||||
if(path.len && frustration < 5)
|
||||
if(path[1] == loc)
|
||||
path -= path[1]
|
||||
var/t = step_towards(src, path[1])
|
||||
if(t)
|
||||
path -= path[1]
|
||||
else
|
||||
++frustration
|
||||
else
|
||||
path = list()
|
||||
target = null
|
||||
|
||||
|
||||
/mob/living/bot/farmbot/handleAdjacentTarget()
|
||||
UnarmedAttack(target)
|
||||
|
||||
/mob/living/bot/farmbot/lookForTargets()
|
||||
if(emagged)
|
||||
for(var/mob/living/carbon/human/H in view(7, src))
|
||||
target = H
|
||||
return
|
||||
else
|
||||
if(emagged)
|
||||
for(var/mob/living/carbon/human/H in view(7, src))
|
||||
target = H
|
||||
break
|
||||
else
|
||||
for(var/obj/machinery/portable_atmospherics/hydroponics/tray in view(7, src))
|
||||
if(process_tray(tray))
|
||||
target = tray
|
||||
frustration = 0
|
||||
break
|
||||
if(!target && refills_water && tank && tank.reagents.total_volume < tank.reagents.maximum_volume)
|
||||
for(var/obj/structure/sink/source in view(7, src))
|
||||
target = source
|
||||
frustration = 0
|
||||
break
|
||||
if(target)
|
||||
var/t = get_dir(target, src) // Turf with the tray is impassable, so a* can't navigate directly to it
|
||||
path = AStar(loc, get_step(target, t), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
for(var/obj/machinery/portable_atmospherics/hydroponics/tray in view(7, src))
|
||||
if(confirmTarget(tray))
|
||||
target = tray
|
||||
return
|
||||
if(!target && refills_water && tank && tank.reagents.total_volume < tank.reagents.maximum_volume)
|
||||
for(var/obj/structure/sink/source in view(7, src))
|
||||
target = source
|
||||
return
|
||||
|
||||
/mob/living/bot/farmbot/calcTargetPath() // We need to land NEXT to the tray, because the tray itself is impassable
|
||||
for(var/trayDir in list(NORTH, SOUTH, EAST, WEST))
|
||||
target_path = AStar(get_turf(loc), get_step(get_turf(target), trayDir), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, max_target_dist, id = botcard)
|
||||
if(target_path)
|
||||
break
|
||||
if(!target_path)
|
||||
ignore_list |= target
|
||||
target = null
|
||||
target_path = list()
|
||||
return
|
||||
|
||||
/mob/living/bot/farmbot/stepToTarget() // Same reason
|
||||
var/turf/T = get_turf(target)
|
||||
if(!target_path.len || !T.Adjacent(target_path[target_path.len]))
|
||||
calcTargetPath()
|
||||
makeStep(target_path)
|
||||
return
|
||||
|
||||
/mob/living/bot/farmbot/UnarmedAttack(var/atom/A, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
if(attacking)
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(istype(A, /obj/machinery/portable_atmospherics/hydroponics))
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/T = A
|
||||
var/t = process_tray(T)
|
||||
|
||||
var/t = confirmTarget(T)
|
||||
switch(t)
|
||||
if(0)
|
||||
return
|
||||
@@ -174,7 +168,8 @@
|
||||
action = "water" // Needs a better one
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] starts [T.dead? "removing the plant from" : "harvesting"] \the [A].</span>")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
if(do_after(src, 30))
|
||||
visible_message("<span class='notice'>[src] [T.dead? "removes the plant from" : "harvests"] \the [A].</span>")
|
||||
T.attack_hand(src)
|
||||
@@ -182,7 +177,8 @@
|
||||
action = "water"
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] starts watering \the [A].</span>")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
if(do_after(src, 30))
|
||||
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
|
||||
visible_message("<span class='notice'>[src] waters \the [A].</span>")
|
||||
@@ -191,7 +187,8 @@
|
||||
action = "hoe"
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] starts uprooting the weeds in \the [A].</span>")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
if(do_after(src, 30))
|
||||
visible_message("<span class='notice'>[src] uproots the weeds in \the [A].</span>")
|
||||
T.weedlevel = 0
|
||||
@@ -199,11 +196,14 @@
|
||||
action = "fertile"
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] starts fertilizing \the [A].</span>")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
if(do_after(src, 30))
|
||||
visible_message("<span class='notice'>[src] waters \the [A].</span>")
|
||||
|
||||
visible_message("<span class='notice'>[src] fertilizes \the [A].</span>")
|
||||
T.reagents.add_reagent("ammonia", 10)
|
||||
attacking = 0
|
||||
|
||||
busy = 0
|
||||
action = ""
|
||||
update_icons()
|
||||
T.update_icon()
|
||||
@@ -213,20 +213,24 @@
|
||||
action = "water"
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] starts refilling its tank from \the [A].</span>")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
while(do_after(src, 10) && tank.reagents.total_volume < tank.reagents.maximum_volume)
|
||||
tank.reagents.add_reagent("water", 10)
|
||||
if(prob(5))
|
||||
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
|
||||
attacking = 0
|
||||
|
||||
busy = 0
|
||||
action = ""
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] finishes refilling its tank.</span>")
|
||||
else if(emagged && ishuman(A))
|
||||
var/action = pick("weed", "water")
|
||||
attacking = 1
|
||||
|
||||
busy = 1
|
||||
spawn(50) // Some delay
|
||||
attacking = 0
|
||||
|
||||
busy = 0
|
||||
switch(action)
|
||||
if("weed")
|
||||
flick("farmbot_hoe", src)
|
||||
@@ -238,7 +242,9 @@
|
||||
A.attack_generic(src, 5, t)
|
||||
if("water")
|
||||
flick("farmbot_water", src)
|
||||
visible_message("<span class='danger'>[src] splashes [A] with water!</span>") // That's it. RP effect.
|
||||
|
||||
visible_message("<span class='danger'>[src] splashes [A] with water!</span>")
|
||||
tank.reagents.splash(A, 100)
|
||||
|
||||
/mob/living/bot/farmbot/explode()
|
||||
visible_message("<span class='danger'>[src] blows apart!</span>")
|
||||
@@ -261,8 +267,23 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/bot/farmbot/proc/process_tray(var/obj/machinery/portable_atmospherics/hydroponics/tray)
|
||||
if(!tray || !istype(tray))
|
||||
|
||||
/mob/living/bot/farmbot/confirmTarget(var/atom/targ)
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(emagged && ishuman(targ))
|
||||
if(targ in view(world.view, src))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
if(istype(targ, /obj/structure/sink))
|
||||
if(!tank || tank.reagents.total_volume >= tank.reagents.maximum_volume)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/tray = targ
|
||||
if(!istype(tray))
|
||||
return 0
|
||||
|
||||
if(tray.closed_system || !tray.seed)
|
||||
@@ -291,34 +312,38 @@
|
||||
icon_state = "water_arm"
|
||||
var/build_step = 0
|
||||
var/created_name = "Farmbot"
|
||||
var/obj/tank
|
||||
w_class = 3.0
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(4) // If an admin spawned it, it won't have a watertank it, so lets make one for em!
|
||||
var tank = locate(/obj/structure/reagent_dispensers/watertank) in contents
|
||||
if(!tank)
|
||||
new /obj/structure/reagent_dispensers/watertank(src)
|
||||
|
||||
/obj/item/weapon/farmbot_arm_assembly/New(var/newloc, var/theTank)
|
||||
..(newloc)
|
||||
if(!theTank) // If an admin spawned it, it won't have a watertank it, so lets make one for em!
|
||||
tank = new /obj/structure/reagent_dispensers/watertank(src)
|
||||
else
|
||||
tank = theTank
|
||||
tank.forceMove(src)
|
||||
|
||||
/obj/structure/reagent_dispensers/watertank/attackby(var/obj/item/robot_parts/S, mob/user as mob)
|
||||
if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm)))
|
||||
..()
|
||||
return
|
||||
|
||||
var/obj/item/weapon/farmbot_arm_assembly/A = new /obj/item/weapon/farmbot_arm_assembly(loc)
|
||||
|
||||
user << "You add the robot arm to [src]."
|
||||
loc = A //Place the water tank into the assembly, it will be needed for the finished bot
|
||||
|
||||
user.drop_from_inventory(S)
|
||||
qdel(S)
|
||||
|
||||
new /obj/item/weapon/farmbot_arm_assembly(loc, src)
|
||||
|
||||
/obj/item/weapon/farmbot_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if((istype(W, /obj/item/device/analyzer/plant_analyzer)) && (build_step == 0))
|
||||
build_step++
|
||||
user << "You add the plant analyzer to [src]."
|
||||
name = "farmbot assembly"
|
||||
|
||||
user.remove_from_mob(W)
|
||||
qdel(W)
|
||||
|
||||
@@ -326,6 +351,7 @@
|
||||
build_step++
|
||||
user << "You add a bucket to [src]."
|
||||
name = "farmbot assembly with bucket"
|
||||
|
||||
user.remove_from_mob(W)
|
||||
qdel(W)
|
||||
|
||||
@@ -333,17 +359,17 @@
|
||||
build_step++
|
||||
user << "You add a minihoe to [src]."
|
||||
name = "farmbot assembly with bucket and minihoe"
|
||||
|
||||
user.remove_from_mob(W)
|
||||
qdel(W)
|
||||
|
||||
else if((isprox(W)) && (build_step == 3))
|
||||
build_step++
|
||||
user << "You complete the Farmbot! Beep boop."
|
||||
var/mob/living/bot/farmbot/S = new /mob/living/bot/farmbot(get_turf(src))
|
||||
for(var/obj/structure/reagent_dispensers/watertank/wTank in contents)
|
||||
wTank.loc = S
|
||||
S.tank = wTank
|
||||
|
||||
var/mob/living/bot/farmbot/S = new /mob/living/bot/farmbot(get_turf(src), tank)
|
||||
S.name = created_name
|
||||
|
||||
user.remove_from_mob(W)
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
|
||||
@@ -3,22 +3,20 @@
|
||||
desc = "A little floor repairing robot, he looks so excited!"
|
||||
icon_state = "floorbot0"
|
||||
req_access = list(access_construction)
|
||||
wait_if_pulled = 1
|
||||
min_target_dist = 0
|
||||
|
||||
var/amount = 10 // 1 for tile, 2 for lattice
|
||||
var/maxAmount = 60
|
||||
var/tilemake = 0 // When it reaches 100, bot makes a tile
|
||||
var/repairing = 0
|
||||
var/improvefloors = 0
|
||||
var/eattiles = 0
|
||||
var/maketiles = 0
|
||||
var/targetdirection = null
|
||||
var/list/path = list()
|
||||
var/list/ignorelist = list()
|
||||
var/turf/target
|
||||
var/floor_build_type = /decl/flooring/tiling // Basic steel floor.
|
||||
|
||||
/mob/living/bot/floorbot/update_icons()
|
||||
if(repairing)
|
||||
if(busy)
|
||||
icon_state = "floorbot-c"
|
||||
else if(amount > 0)
|
||||
icon_state = "floorbot[on]"
|
||||
@@ -31,7 +29,7 @@
|
||||
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
|
||||
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
|
||||
//dat += "Tiles left: [amount]<BR>"
|
||||
dat += "Tiles left: [amount]<BR>"
|
||||
dat += "Behvaiour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
if(!locked || issilicon(user))
|
||||
dat += "Improves floors: <A href='?src=\ref[src];operation=improve'>[improvefloors ? "Yes" : "No"]</A><BR>"
|
||||
@@ -89,100 +87,90 @@
|
||||
targetdirection = null
|
||||
attack_hand(usr)
|
||||
|
||||
/mob/living/bot/floorbot/turn_off()
|
||||
..()
|
||||
target = null
|
||||
path = list()
|
||||
ignorelist = list()
|
||||
|
||||
/mob/living/bot/floorbot/Life()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
return
|
||||
|
||||
/mob/living/bot/floorbot/handleRegular()
|
||||
++tilemake
|
||||
if(tilemake >= 100)
|
||||
tilemake = 0
|
||||
addTiles(1)
|
||||
|
||||
if(client)
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
if(prob(1))
|
||||
custom_emote(2, "makes an excited booping beeping sound!")
|
||||
|
||||
if(ignorelist.len) // Don't stick forever
|
||||
for(var/T in ignorelist)
|
||||
if(prob(1))
|
||||
ignorelist -= T
|
||||
|
||||
if(amount && !emagged)
|
||||
if(!target && targetdirection) // Building a bridge
|
||||
var/turf/T = get_step(src, targetdirection)
|
||||
while(T in range(src))
|
||||
if(istype(T, /turf/space))
|
||||
target = T
|
||||
break
|
||||
T = get_step(T, targetdirection)
|
||||
|
||||
if(!target) // Fixing floors
|
||||
for(var/turf/T in view(src))
|
||||
if(T.loc.name == "Space")
|
||||
continue
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
if(istype(T, /turf/space))
|
||||
if(get_turf(T) == loc || prob(40)) // So they target the same tile all the time
|
||||
target = T
|
||||
if(improvefloors && istype(T, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = T
|
||||
if(!F.flooring && (get_turf(T) == loc || prob(40)))
|
||||
target = T
|
||||
|
||||
if(emagged) // Time to griff
|
||||
for(var/turf/simulated/floor/D in view(src))
|
||||
if(D.loc.name == "Space")
|
||||
continue
|
||||
if(D in ignorelist)
|
||||
continue
|
||||
target = D
|
||||
break
|
||||
|
||||
if(!target && amount < maxAmount && eattiles || maketiles) // Eat tiles
|
||||
if(eattiles)
|
||||
for(var/obj/item/stack/tile/floor/T in view(src))
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
target = T
|
||||
break
|
||||
if(maketiles && !target)
|
||||
for(var/obj/item/stack/material/steel/T in view(src))
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
target = T
|
||||
break
|
||||
|
||||
if(target && get_turf(target) == loc)
|
||||
/mob/living/bot/floorbot/handleAdjacentTarget()
|
||||
if(get_turf(target) == src.loc)
|
||||
UnarmedAttack(target)
|
||||
|
||||
if(target && get_turf(target) != loc && !path.len)
|
||||
spawn(0)
|
||||
path = AStar(loc, get_turf(target), /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
ignorelist += target
|
||||
target = null
|
||||
/mob/living/bot/floorbot/lookForTargets()
|
||||
if(emagged) // Time to griff
|
||||
for(var/turf/simulated/floor/D in view(src))
|
||||
if(confirmTarget(D))
|
||||
target = D
|
||||
return
|
||||
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
else if(amount)
|
||||
if(targetdirection) // Building a bridge
|
||||
var/turf/T = get_step(src, targetdirection)
|
||||
while(T in range(world.view, src))
|
||||
if(confirmTarget(T))
|
||||
target = T
|
||||
return
|
||||
T = get_step(T, targetdirection)
|
||||
|
||||
else // Fixing floors
|
||||
for(var/turf/space/T in view(src)) // Breaches are of higher priority
|
||||
if(confirmTarget(T))
|
||||
target = T
|
||||
return
|
||||
|
||||
for(var/turf/simulated/mineral/floor/T in view(src)) // Asteroids are of smaller priority
|
||||
if(confirmTarget(T))
|
||||
target = T
|
||||
return
|
||||
|
||||
if(improvefloors)
|
||||
for(var/turf/simulated/floor/T in view(src))
|
||||
if(confirmTarget(T))
|
||||
target = T
|
||||
return
|
||||
|
||||
if(amount < maxAmount && (eattiles || maketiles))
|
||||
for(var/obj/item/stack/S in view(src))
|
||||
if(confirmTarget(S))
|
||||
target = S
|
||||
return
|
||||
|
||||
/mob/living/bot/floorbot/confirmTarget(var/atom/A) // The fact that we do some checks twice may seem confusing but remember that the bot's settings may be toggled while it's moving and we want them to stop in that case
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(istype(A, /obj/item/stack/tile/floor))
|
||||
return (amount < maxAmount && eattiles)
|
||||
if(istype(A, /obj/item/stack/material/steel))
|
||||
return (amount < maxAmount && maketiles)
|
||||
|
||||
if(A.loc.name == "Space")
|
||||
return 0
|
||||
|
||||
if(emagged)
|
||||
return (istype(A, /turf/simulated/floor))
|
||||
|
||||
if(!amount)
|
||||
return 0
|
||||
|
||||
if(istype(A, /turf/space))
|
||||
return 1
|
||||
|
||||
if(istype(A, /turf/simulated/mineral/floor))
|
||||
return 1
|
||||
|
||||
var/turf/simulated/floor/T = A
|
||||
return (istype(T) && improvefloors && !T.flooring && (get_turf(T) == loc || prob(40)))
|
||||
|
||||
/mob/living/bot/floorbot/UnarmedAttack(var/atom/A, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(repairing)
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(get_turf(A) != loc)
|
||||
@@ -190,9 +178,9 @@
|
||||
|
||||
if(emagged && istype(A, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = A
|
||||
repairing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
if(F.is_plating())
|
||||
if(F.flooring)
|
||||
visible_message("<span class='warning'>[src] begins to tear the floor tile from the floor!</span>")
|
||||
if(do_after(src, 50))
|
||||
F.break_tile_to_plating()
|
||||
@@ -203,15 +191,15 @@
|
||||
F.ReplaceWithLattice()
|
||||
addTiles(1)
|
||||
target = null
|
||||
repairing = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
else if(istype(A, /turf/space))
|
||||
else if(istype(A, /turf/space) || istype(A, /turf/simulated/mineral/floor))
|
||||
var/building = 2
|
||||
if(locate(/obj/structure/lattice, A))
|
||||
building = 1
|
||||
if(amount < building)
|
||||
return
|
||||
repairing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] begins to repair the hole.</span>")
|
||||
if(do_after(src, 50))
|
||||
@@ -223,12 +211,12 @@
|
||||
I = PoolOrNew(/obj/item/stack/rods, src)
|
||||
A.attackby(I, src)
|
||||
target = null
|
||||
repairing = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
else if(istype(A, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = A
|
||||
if(!F.flooring && amount)
|
||||
repairing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
visible_message("<span class='notice'>[src] begins to improve the floor.</span>")
|
||||
if(do_after(src, 50))
|
||||
@@ -236,12 +224,12 @@
|
||||
F.set_flooring(get_flooring_data(floor_build_type))
|
||||
addTiles(-1)
|
||||
target = null
|
||||
repairing = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
else if(istype(A, /obj/item/stack/tile/floor) && amount < maxAmount)
|
||||
var/obj/item/stack/tile/floor/T = A
|
||||
visible_message("<span class='notice'>[src] begins to collect tiles.</span>")
|
||||
repairing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
if(do_after(src, 20))
|
||||
if(T)
|
||||
@@ -249,13 +237,13 @@
|
||||
T.use(eaten)
|
||||
addTiles(eaten)
|
||||
target = null
|
||||
repairing = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount)
|
||||
var/obj/item/stack/material/M = A
|
||||
if(M.get_material_name() == DEFAULT_WALL_MATERIAL)
|
||||
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
|
||||
repairing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
if(do_after(50))
|
||||
if(M)
|
||||
@@ -288,7 +276,7 @@
|
||||
|
||||
/* Assembly */
|
||||
|
||||
/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/floor/T, mob/user as mob)
|
||||
/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/floor/T, mob/living/user as mob)
|
||||
if(!istype(T, /obj/item/stack/tile/floor))
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -3,21 +3,16 @@
|
||||
desc = "A little medical robot. He looks somewhat underwhelmed."
|
||||
icon_state = "medibot0"
|
||||
req_access = list(access_medical)
|
||||
|
||||
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
|
||||
botcard_access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics)
|
||||
|
||||
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
|
||||
|
||||
//AI vars
|
||||
var/frustration = 0
|
||||
var/list/path = list()
|
||||
var/mob/living/carbon/human/patient = null
|
||||
var/mob/ignored = list() // Used by emag
|
||||
var/last_newpatient_speak = 0
|
||||
var/vocal = 1
|
||||
|
||||
//Healing vars
|
||||
var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
|
||||
var/currently_healing = 0
|
||||
var/injection_amount = 15 //How much reagent do we inject at a time?
|
||||
var/heal_threshold = 10 //Start healing when they have this much damage in a category
|
||||
var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents.
|
||||
@@ -29,49 +24,26 @@
|
||||
var/treatment_emag = "toxin"
|
||||
var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds?
|
||||
|
||||
/mob/living/bot/medbot/Life()
|
||||
..()
|
||||
/mob/living/bot/medbot/handleIdle()
|
||||
if(vocal && prob(1))
|
||||
var/message = pick("Radar, put a mask on!", "There's always a catch, and it's the best there is.", "I knew it, I should've been a plastic surgeon.", "What kind of medbay is this? Everyone's dropping like dead flies.", "Delicious!")
|
||||
say(message)
|
||||
|
||||
if(!on)
|
||||
return
|
||||
/mob/living/bot/medbot/handleAdjacentTarget()
|
||||
UnarmedAttack(target)
|
||||
|
||||
if(!client)
|
||||
/mob/living/bot/medbot/lookForTargets()
|
||||
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
|
||||
if(confirmTarget(H))
|
||||
target = H
|
||||
if(last_newpatient_speak + 300 < world.time)
|
||||
var/message = pick("Hey, [H.name]! Hold on, I'm coming.", "Wait [H.name]! I want to help!", "[H.name], you appear to be injured!")
|
||||
say(message)
|
||||
custom_emote(1, "points at [H.name].")
|
||||
last_newpatient_speak = world.time
|
||||
break
|
||||
|
||||
if(vocal && prob(1))
|
||||
var/message = pick("Radar, put a mask on!", "There's always a catch, and it's the best there is.", "I knew it, I should've been a plastic surgeon.", "What kind of medbay is this? Everyone's dropping like dead flies.", "Delicious!")
|
||||
say(message)
|
||||
|
||||
if(patient)
|
||||
if(Adjacent(patient))
|
||||
if(!currently_healing)
|
||||
UnarmedAttack(patient)
|
||||
else
|
||||
if(path.len && (get_dist(patient, path[path.len]) > 2)) // We have a path, but it's off
|
||||
path = list()
|
||||
if(!path.len && (get_dist(src, patient) > 1))
|
||||
spawn(0)
|
||||
path = AStar(loc, get_turf(patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
++frustration
|
||||
if(get_dist(src, patient) > 7 || frustration > 8)
|
||||
patient = null
|
||||
else
|
||||
for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient!
|
||||
if(valid_healing_target(H))
|
||||
patient = H
|
||||
frustration = 0
|
||||
if(last_newpatient_speak + 300 < world.time)
|
||||
var/message = pick("Hey, [H.name]! Hold on, I'm coming.", "Wait [H.name]! I want to help!", "[H.name], you appear to be injured!")
|
||||
say(message)
|
||||
custom_emote(1, "points at [H.name].")
|
||||
last_newpatient_speak = world.time
|
||||
break
|
||||
|
||||
/mob/living/bot/medbot/UnarmedAttack(var/mob/living/carbon/human/H, var/proximity)
|
||||
/mob/living/bot/medbot/UnarmedAttack(var/mob/living/carbon/human/H)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
@@ -81,25 +53,27 @@
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(H.stat == DEAD)
|
||||
var/death_message = pick("No! NO!", "Live, damnit! LIVE!", "I... I've never lost a patient before. Not today, I mean.")
|
||||
say(death_message)
|
||||
patient = null
|
||||
target = null
|
||||
return
|
||||
|
||||
var/t = valid_healing_target(H)
|
||||
var/t = confirmTarget(H)
|
||||
if(!t)
|
||||
var/message = pick("All patched up!", "An apple a day keeps me away.", "Feel better soon!")
|
||||
say(message)
|
||||
patient = null
|
||||
target = null
|
||||
return
|
||||
|
||||
icon_state = "medibots"
|
||||
visible_message("<span class='warning'>[src] is trying to inject [H]!</span>")
|
||||
if(declare_treatment)
|
||||
var/area/location = get_area(src)
|
||||
broadcast_medical_hud_message("[src] is treating <b>[H]</b> in <b>[location]</b>", src)
|
||||
currently_healing = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
if(do_mob(src, H, 30))
|
||||
if(t == 1)
|
||||
@@ -107,14 +81,14 @@
|
||||
else
|
||||
H.reagents.add_reagent(t, injection_amount)
|
||||
visible_message("<span class='warning'>[src] injects [H] with the syringe!</span>")
|
||||
currently_healing = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
|
||||
/mob/living/bot/medbot/update_icons()
|
||||
overlays.Cut()
|
||||
if(skin)
|
||||
overlays += image('icons/obj/aibots.dmi', "medskin_[skin]")
|
||||
if(currently_healing)
|
||||
if(busy)
|
||||
icon_state = "medibots"
|
||||
else
|
||||
icon_state = "medibot[on]"
|
||||
@@ -226,13 +200,13 @@
|
||||
user << "<span class='warning'>You short out [src]'s reagent synthesis circuits.</span>"
|
||||
visible_message("<span class='warning'>[src] buzzes oddly!</span>")
|
||||
flick("medibot_spark", src)
|
||||
patient = null
|
||||
currently_healing = 0
|
||||
target = null
|
||||
busy = 0
|
||||
emagged = 1
|
||||
on = 1
|
||||
update_icons()
|
||||
. = 1
|
||||
ignored |= user
|
||||
ignore_list |= user
|
||||
|
||||
/mob/living/bot/medbot/explode()
|
||||
on = 0
|
||||
@@ -255,15 +229,15 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/bot/medbot/proc/valid_healing_target(var/mob/living/carbon/human/H)
|
||||
/mob/living/bot/medbot/confirmTarget(var/mob/living/carbon/human/H)
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(H.stat == DEAD) // He's dead, Jim
|
||||
return null
|
||||
return 0
|
||||
|
||||
if(H.suiciding)
|
||||
return null
|
||||
|
||||
if(H in ignored)
|
||||
return null
|
||||
return 0
|
||||
|
||||
if(emagged)
|
||||
return treatment_emag
|
||||
|
||||
@@ -17,23 +17,22 @@
|
||||
maxHealth = 150
|
||||
mob_bump_flag = HEAVY
|
||||
|
||||
min_target_dist = 0
|
||||
max_target_dist = 250
|
||||
target_speed = 3
|
||||
max_frustration = 5
|
||||
botcard_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
||||
|
||||
var/busy = 0
|
||||
var/mode = MULE_IDLE
|
||||
var/atom/movable/load
|
||||
|
||||
var/paused = 0
|
||||
var/crates_only = 1
|
||||
var/auto_return = 1
|
||||
var/safety = 1
|
||||
|
||||
var/list/path = list()
|
||||
var/frustration = 0
|
||||
var/turf/target
|
||||
var/targetName
|
||||
var/turf/home
|
||||
var/homeName
|
||||
var/turf/obstacle
|
||||
|
||||
var/global/amount = 0
|
||||
|
||||
@@ -71,19 +70,6 @@
|
||||
dat += "Power: [on ? "On" : "Off"]<BR>"
|
||||
|
||||
if(!open)
|
||||
dat += "Status: "
|
||||
switch(mode)
|
||||
if(MULE_IDLE)
|
||||
dat += "Ready"
|
||||
if(MULE_MOVING, MULE_UNLOAD, MULE_PATH_DONE)
|
||||
dat += "Navigating"
|
||||
if(MULE_UNLOAD)
|
||||
dat += "Unloading"
|
||||
if(MULE_LOST)
|
||||
dat += "Processing commands"
|
||||
if(MULE_CALC_MIN to MULE_CALC_MAX)
|
||||
dat += "Calculating navigation path"
|
||||
|
||||
dat += "<BR>Current Load: [load ? load.name : "<i>none</i>"]<BR>"
|
||||
|
||||
if(locked)
|
||||
@@ -177,10 +163,9 @@
|
||||
/mob/living/bot/mulebot/proc/obeyCommand(var/command)
|
||||
switch(command)
|
||||
if("Home")
|
||||
mode = MULE_IDLE
|
||||
resetTarget()
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
if("SetD")
|
||||
var/new_dest
|
||||
var/list/beaconlist = new()
|
||||
@@ -192,13 +177,13 @@
|
||||
else
|
||||
alert("No destination beacons available.")
|
||||
if(new_dest)
|
||||
resetTarget()
|
||||
target = get_turf(beaconlist[new_dest])
|
||||
targetName = new_dest
|
||||
if("GoTD")
|
||||
if(mode == MULE_IDLE)
|
||||
mode = MULE_LOST
|
||||
paused = 0
|
||||
if("Stop")
|
||||
mode = MULE_IDLE
|
||||
paused = 1
|
||||
|
||||
/mob/living/bot/mulebot/emag_act(var/remaining_charges, var/user)
|
||||
locked = !locked
|
||||
@@ -211,89 +196,49 @@
|
||||
if(open)
|
||||
icon_state = "mulebot-hatch"
|
||||
return
|
||||
if(mode == MULE_MOVING || mode == MULE_UNLOAD)
|
||||
if(target_path.len && !paused)
|
||||
icon_state = "mulebot1"
|
||||
return
|
||||
icon_state = "mulebot0"
|
||||
|
||||
/mob/living/bot/mulebot/Life()
|
||||
..()
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
/mob/living/bot/mulebot/handleRegular()
|
||||
if(!safety && prob(1))
|
||||
flick("mulebot-emagged", src)
|
||||
update_icons()
|
||||
|
||||
switch(mode)
|
||||
if(MULE_IDLE) // Idle
|
||||
return
|
||||
if(MULE_MOVING) // Moving to target
|
||||
if(!target) // Return home
|
||||
if(auto_return && home)
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(loc == target) // Unload or stop
|
||||
custom_emote(2, "makes a chiming sound.")
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
|
||||
mode = MULE_UNLOAD
|
||||
update_icons()
|
||||
return
|
||||
if(path.len) // Move
|
||||
makeStep()
|
||||
sleep(10)
|
||||
if(path.len)
|
||||
makeStep()
|
||||
else
|
||||
mode = MULE_LOST
|
||||
/mob/living/bot/mulebot/handleFrustrated()
|
||||
custom_emote(2, "makes a sighing buzz.")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
..()
|
||||
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_UNLOAD)
|
||||
unload(dir)
|
||||
/mob/living/bot/mulebot/handleAdjacentTarget()
|
||||
if(target == src.loc)
|
||||
custom_emote(2, "makes a chiming sound.")
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
|
||||
UnarmedAttack(target)
|
||||
resetTarget()
|
||||
if(auto_return && home && (loc != home))
|
||||
target = home
|
||||
targetName = "Home"
|
||||
|
||||
if(auto_return && home && (loc != home))
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_LOST) // Lost my way
|
||||
if(target)
|
||||
spawn(0)
|
||||
calc_path(obstacle)
|
||||
mode = MULE_CALC_MIN
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_CALC_MIN to MULE_CALC_MAX) // Calcing path
|
||||
if(path.len)
|
||||
mode = MULE_PATH_DONE
|
||||
update_icons()
|
||||
else
|
||||
++mode
|
||||
return
|
||||
if(MULE_PATH_DONE) // Done with path
|
||||
obstacle = null
|
||||
if(path.len)
|
||||
frustration = 0
|
||||
mode = MULE_MOVING
|
||||
else
|
||||
if(home)
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
/mob/living/bot/mulebot/confirmTarget()
|
||||
return 1
|
||||
|
||||
/mob/living/bot/mulebot/calcTargetPath()
|
||||
..()
|
||||
if(!target_path.len && target != home) // I presume that target is not null
|
||||
resetTarget()
|
||||
target = home
|
||||
targetName = "Home"
|
||||
|
||||
/mob/living/bot/mulebot/stepToTarget()
|
||||
if(paused)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/UnarmedAttack(var/turf/T)
|
||||
if(T == src.loc)
|
||||
unload(dir)
|
||||
|
||||
/mob/living/bot/mulebot/Bump(var/mob/living/M)
|
||||
if(!safety && istype(M))
|
||||
@@ -302,28 +247,6 @@
|
||||
M.Weaken(5)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/proc/makeStep()
|
||||
var/turf/next = path[1]
|
||||
if(next == loc)
|
||||
path -= next
|
||||
return
|
||||
|
||||
var/moved = step_towards(src, next)
|
||||
if(moved)
|
||||
frustration = 0
|
||||
path -= next
|
||||
else if(frustration < 6)
|
||||
if(frustration == 3)
|
||||
custom_emote(2, "makes an annoyed buzzing sound")
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
++frustration
|
||||
else
|
||||
custom_emote(2, "makes a sighing buzz.")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
obstacle = next
|
||||
|
||||
mode = MULE_LOST
|
||||
|
||||
/mob/living/bot/mulebot/proc/runOver(var/mob/living/carbon/human/H)
|
||||
if(istype(H)) // No safety checks - WILL run over lying humans. Stop ERPing in the maint!
|
||||
visible_message("<span class='warning'>[src] drives over [H]!</span>")
|
||||
@@ -362,11 +285,6 @@
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/proc/calc_path(var/turf/avoid = null)
|
||||
path = AStar(loc, target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id = botcard, exclude = avoid)
|
||||
if(!path)
|
||||
path = list()
|
||||
|
||||
/mob/living/bot/mulebot/proc/load(var/atom/movable/C)
|
||||
if(busy || load || get_dist(C, src) > 1 || !isturf(C.loc))
|
||||
return
|
||||
@@ -384,10 +302,6 @@
|
||||
if(istype(crate))
|
||||
crate.close()
|
||||
|
||||
//I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool.
|
||||
//So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below.
|
||||
//if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C))
|
||||
// return
|
||||
busy = 1
|
||||
|
||||
C.loc = loc
|
||||
@@ -428,11 +342,3 @@
|
||||
AM.layer = initial(AM.layer)
|
||||
AM.pixel_y = initial(AM.pixel_y)
|
||||
busy = 0
|
||||
|
||||
#undef MULE_IDLE
|
||||
#undef MULE_MOVING
|
||||
#undef MULE_UNLOAD
|
||||
#undef MULE_LOST
|
||||
#undef MULE_CALC_MIN
|
||||
#undef MULE_CALC_MAX
|
||||
#undef MULE_PATH_DONE
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
health = 50
|
||||
req_one_access = list(access_security, access_forensics_lockers)
|
||||
botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels)
|
||||
|
||||
var/mob/target
|
||||
patrol_speed = 2
|
||||
target_speed = 3
|
||||
|
||||
var/idcheck = 0 // If true, arrests for having weapons without authorization.
|
||||
var/check_records = 0 // If true, arrests people without a record.
|
||||
@@ -16,30 +16,9 @@
|
||||
var/declare_arrests = 0 // If true, announces arrests over sechuds.
|
||||
var/auto_patrol = 0 // If true, patrols on its own
|
||||
|
||||
var/mode = 0
|
||||
#define SECBOT_IDLE 0 // idle
|
||||
#define SECBOT_HUNT 1 // found target, hunting
|
||||
#define SECBOT_ARREST 2 // arresting target
|
||||
#define SECBOT_START_PATROL 3 // start patrol
|
||||
#define SECBOT_WAIT_PATROL 4 // waiting for signals
|
||||
#define SECBOT_PATROL 5 // patrolling
|
||||
#define SECBOT_SUMMON 6 // summoned by PDA
|
||||
var/is_attacking = 0
|
||||
var/is_ranged = 0
|
||||
var/awaiting_surrender = 0
|
||||
|
||||
var/obj/secbot_listener/listener = null
|
||||
var/beacon_freq = 1445 // Navigation beacon frequency
|
||||
var/control_freq = BOT_FREQ // Bot control frequency
|
||||
var/list/path = list()
|
||||
var/frustration = 0
|
||||
var/turf/patrol_target = null // This is where we are headed
|
||||
var/closest_dist // Used to find the closest beakon
|
||||
var/destination = "__nearest__" // This is the current beacon's ID
|
||||
var/next_destination = "__nearest__" // This is the next beacon's ID
|
||||
var/nearest_beacon // Tag of the beakon that we assume to be the closest one
|
||||
|
||||
var/bot_version = 1.3
|
||||
var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
|
||||
var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
|
||||
|
||||
@@ -48,24 +27,8 @@
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
auto_patrol = 1
|
||||
|
||||
/mob/living/bot/secbot/New()
|
||||
..()
|
||||
listener = new /obj/secbot_listener(src)
|
||||
listener.secbot = src
|
||||
|
||||
spawn(5) // Since beepsky is made on the start... this delay is necessary
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(listener, control_freq, filter = RADIO_SECBOT)
|
||||
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
|
||||
/mob/living/bot/secbot/turn_off()
|
||||
..()
|
||||
target = null
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
|
||||
/mob/living/bot/secbot/update_icons()
|
||||
if(on && is_attacking)
|
||||
if(on && busy)
|
||||
icon_state = "secbot-c"
|
||||
else
|
||||
icon_state = "secbot[on]"
|
||||
@@ -78,7 +41,7 @@
|
||||
/mob/living/bot/secbot/attack_hand(var/mob/user)
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
dat += "<TT><B>Automatic Security Unit v[bot_version]</B></TT><BR><BR>"
|
||||
dat += "<TT><B>Automatic Security Unit</B></TT><BR><BR>"
|
||||
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
dat += "Maintenance panel is [open ? "opened" : "closed"]"
|
||||
@@ -89,7 +52,7 @@
|
||||
dat += "Operating Mode: <A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A><BR>"
|
||||
dat += "Report Arrests: <A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>"
|
||||
user << browse("<HEAD><TITLE>Securitron v[bot_version] controls</TITLE></HEAD>[dat]", "window=autosec")
|
||||
user << browse("<HEAD><TITLE>Securitron controls</TITLE></HEAD>[dat]", "window=autosec")
|
||||
onclose(user, "autosec")
|
||||
return
|
||||
|
||||
@@ -118,7 +81,6 @@
|
||||
arrest_type = !arrest_type
|
||||
if("patrol")
|
||||
auto_patrol = !auto_patrol
|
||||
mode = SECBOT_IDLE
|
||||
if("declarearrests")
|
||||
declare_arrests = !declare_arrests
|
||||
attack_hand(usr)
|
||||
@@ -129,127 +91,47 @@
|
||||
if(health < curhealth)
|
||||
target = user
|
||||
awaiting_surrender = 5
|
||||
mode = SECBOT_HUNT
|
||||
|
||||
/mob/living/bot/secbot/Life()
|
||||
/mob/living/bot/secbot/startPatrol()
|
||||
if(!locked) // Stop running away when we set you up
|
||||
return
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
if(client)
|
||||
return
|
||||
|
||||
if(!target)
|
||||
scan_view()
|
||||
/mob/living/bot/secbot/confirmTarget(var/atom/A)
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(!locked && (mode == SECBOT_START_PATROL || mode == SECBOT_PATROL)) // Stop running away when we set you up
|
||||
mode = SECBOT_IDLE
|
||||
return (check_threat(A) > 3)
|
||||
|
||||
switch(mode)
|
||||
if(SECBOT_IDLE)
|
||||
if(auto_patrol && locked)
|
||||
mode = SECBOT_START_PATROL
|
||||
/mob/living/bot/secbot/lookForTargets()
|
||||
for(var/mob/living/M in view(src))
|
||||
if(M.stat == DEAD)
|
||||
continue
|
||||
if(confirmTarget(M))
|
||||
var/threat = check_threat(M)
|
||||
target = M
|
||||
awaiting_surrender = -1
|
||||
say("Level [threat] infraction alert!")
|
||||
custom_emote(1, "points at [M.name]!")
|
||||
return
|
||||
|
||||
if(SECBOT_HUNT) // Target is in the view or has been recently - chase it
|
||||
if(frustration > 7)
|
||||
target = null
|
||||
frustration = 0
|
||||
awaiting_surrender = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(target)
|
||||
var/threat = check_threat(target)
|
||||
if(threat < 4) // Re-evaluate in case they dropped the weapon or something
|
||||
target = null
|
||||
frustration = 0
|
||||
awaiting_surrender = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(!(target in view(7, src)))
|
||||
++frustration
|
||||
if(Adjacent(target))
|
||||
mode = SECBOT_ARREST
|
||||
return
|
||||
else
|
||||
if(is_ranged)
|
||||
RangedAttack(target)
|
||||
else
|
||||
step_towards(src, target) // Melee bots chase a bit faster
|
||||
spawn(8)
|
||||
if(!Adjacent(target))
|
||||
step_towards(src, target)
|
||||
spawn(16)
|
||||
if(!Adjacent(target))
|
||||
step_towards(src, target)
|
||||
/mob/living/bot/secbot/calcTargetPath()
|
||||
..()
|
||||
if(awaiting_surrender != -1)
|
||||
awaiting_surrender = 5 // This implies that a) we have already approached the target and b) it has moved after the warning
|
||||
|
||||
if(SECBOT_ARREST) // Target is next to us - attack it
|
||||
if(!target)
|
||||
mode = SECBOT_IDLE
|
||||
if(!Adjacent(target))
|
||||
awaiting_surrender = 5 // I'm done playing nice
|
||||
mode = SECBOT_HUNT
|
||||
return
|
||||
var/threat = check_threat(target)
|
||||
if(threat < 4)
|
||||
target = null
|
||||
awaiting_surrender = 0
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(awaiting_surrender < 5 && ishuman(target) && !target.lying)
|
||||
if(awaiting_surrender == 0)
|
||||
say("Down on the floor, [target]! You have five seconds to comply.")
|
||||
++awaiting_surrender
|
||||
else
|
||||
UnarmedAttack(target)
|
||||
if(ishuman(target) && declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect <b>[target]</b> in <b>[location]</b>.", src)
|
||||
return
|
||||
|
||||
if(SECBOT_START_PATROL)
|
||||
if(path.len && patrol_target)
|
||||
mode = SECBOT_PATROL
|
||||
return
|
||||
else if(patrol_target)
|
||||
spawn(0)
|
||||
calc_path()
|
||||
if(!path.len)
|
||||
patrol_target = null
|
||||
mode = SECBOT_IDLE
|
||||
else
|
||||
mode = SECBOT_PATROL
|
||||
if(!patrol_target)
|
||||
if(next_destination)
|
||||
find_next_target()
|
||||
else
|
||||
find_patrol_target()
|
||||
say("Engaging patrol mode.")
|
||||
mode = SECBOT_WAIT_PATROL
|
||||
return
|
||||
|
||||
if(SECBOT_WAIT_PATROL)
|
||||
if(patrol_target)
|
||||
mode = SECBOT_START_PATROL
|
||||
else
|
||||
++frustration
|
||||
if(frustration > 120)
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
|
||||
if(SECBOT_PATROL)
|
||||
patrol_step()
|
||||
spawn(10)
|
||||
patrol_step()
|
||||
return
|
||||
|
||||
if(SECBOT_SUMMON)
|
||||
patrol_step()
|
||||
spawn(8)
|
||||
patrol_step()
|
||||
spawn(16)
|
||||
patrol_step()
|
||||
return
|
||||
/mob/living/bot/secbot/handleAdjacentTarget()
|
||||
if(awaiting_surrender < 5 && ishuman(target) && !target:lying)
|
||||
if(awaiting_surrender == -1)
|
||||
say("Down on the floor, [target]! You have five seconds to comply.")
|
||||
++awaiting_surrender
|
||||
else
|
||||
UnarmedAttack(target)
|
||||
if(ishuman(target) && declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect <b>[target]</b> in <b>[location]</b>.", src)
|
||||
|
||||
// say("Engaging patrol mode.")
|
||||
|
||||
/mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity)
|
||||
if(!..())
|
||||
@@ -271,31 +153,33 @@
|
||||
C.stun_effect_act(0, 60, null)
|
||||
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
|
||||
do_attack_animation(C)
|
||||
is_attacking = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
spawn(2)
|
||||
is_attacking = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
visible_message("<span class='warning'>[C] was prodded by [src] with a stun baton!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
|
||||
visible_message("<span class='warning'>[src] is trying to put handcuffs on [C]!</span>")
|
||||
busy = 1
|
||||
if(do_mob(src, C, 60))
|
||||
if(!C.handcuffed)
|
||||
C.handcuffed = new /obj/item/weapon/handcuffs(C)
|
||||
C.update_inv_handcuffed()
|
||||
if(preparing_arrest_sounds.len)
|
||||
playsound(loc, pick(preparing_arrest_sounds), 50, 0)
|
||||
busy = 0
|
||||
else if(istype(M, /mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/S = M
|
||||
S.AdjustStunned(10)
|
||||
S.adjustBruteLoss(15)
|
||||
do_attack_animation(M)
|
||||
playsound(loc, "swing_hit", 50, 1, -1)
|
||||
is_attacking = 1
|
||||
busy = 1
|
||||
update_icons()
|
||||
spawn(2)
|
||||
is_attacking = 0
|
||||
busy = 0
|
||||
update_icons()
|
||||
visible_message("<span class='warning'>[M] was beaten by [src] with a stun baton!</span>")
|
||||
|
||||
@@ -319,30 +203,8 @@
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/secbot/proc/scan_view()
|
||||
for(var/mob/living/M in view(7, src))
|
||||
if(M.invisibility >= INVISIBILITY_LEVEL_ONE)
|
||||
continue
|
||||
if(M.stat)
|
||||
continue
|
||||
|
||||
var/threat = check_threat(M)
|
||||
|
||||
if(threat >= 4)
|
||||
target = M
|
||||
say("Level [threat] infraction alert!")
|
||||
custom_emote(1, "points at [M.name]!")
|
||||
mode = SECBOT_HUNT
|
||||
break
|
||||
return
|
||||
|
||||
/mob/living/bot/secbot/proc/calc_path(var/turf/avoid = null)
|
||||
path = AStar(loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
|
||||
if(!path)
|
||||
path = list()
|
||||
|
||||
/mob/living/bot/secbot/proc/check_threat(var/mob/living/M)
|
||||
if(!M || !istype(M) || M.stat || src == M)
|
||||
if(!M || !istype(M) || M.stat == DEAD || src == M)
|
||||
return 0
|
||||
|
||||
if(emagged)
|
||||
@@ -350,131 +212,6 @@
|
||||
|
||||
return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest)
|
||||
|
||||
/mob/living/bot/secbot/proc/patrol_step()
|
||||
if(loc == patrol_target)
|
||||
patrol_target = null
|
||||
path = list()
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
|
||||
if(path.len && patrol_target)
|
||||
var/turf/next = path[1]
|
||||
if(loc == next)
|
||||
path -= next
|
||||
return
|
||||
var/moved = step_towards(src, next)
|
||||
if(moved)
|
||||
path -= next
|
||||
frustration = 0
|
||||
else
|
||||
++frustration
|
||||
if(frustration > 5) // Make a new path
|
||||
mode = SECBOT_START_PATROL
|
||||
return
|
||||
else
|
||||
mode = SECBOT_START_PATROL
|
||||
|
||||
/mob/living/bot/secbot/proc/find_patrol_target()
|
||||
send_status()
|
||||
nearest_beacon = null
|
||||
next_destination = "__nearest__"
|
||||
listener.post_signal(beacon_freq, "findbeacon", "patrol")
|
||||
|
||||
/mob/living/bot/secbot/proc/find_next_target()
|
||||
send_status()
|
||||
nearest_beacon = null
|
||||
listener.post_signal(beacon_freq, "findbeacon", "patrol")
|
||||
|
||||
/mob/living/bot/secbot/proc/send_status()
|
||||
var/list/kv = list(
|
||||
"type" = "secbot",
|
||||
"name" = name,
|
||||
"loca" = get_area(loc),
|
||||
"mode" = mode
|
||||
)
|
||||
listener.post_signal_multiple(control_freq, kv)
|
||||
|
||||
/obj/secbot_listener
|
||||
var/mob/living/bot/secbot/secbot = null
|
||||
|
||||
/obj/secbot_listener/proc/post_signal(var/freq, var/key, var/value) // send a radio signal with a single data key/value pair
|
||||
post_signal_multiple(freq, list("[key]" = value))
|
||||
|
||||
/obj/secbot_listener/proc/post_signal_multiple(var/freq, var/list/keyval) // send a radio signal with multiple data key/values
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = secbot
|
||||
signal.transmission_method = 1
|
||||
signal.data = keyval.Copy()
|
||||
|
||||
if(signal.data["findbeacon"])
|
||||
frequency.post_signal(secbot, signal, filter = RADIO_NAVBEACONS)
|
||||
else if(signal.data["type"] == "secbot")
|
||||
frequency.post_signal(secbot, signal, filter = RADIO_SECBOT)
|
||||
else
|
||||
frequency.post_signal(secbot, signal)
|
||||
|
||||
/obj/secbot_listener/receive_signal(datum/signal/signal)
|
||||
if(!secbot || !secbot.on)
|
||||
return
|
||||
|
||||
var/recv = signal.data["command"]
|
||||
if(recv == "bot_status")
|
||||
secbot.send_status()
|
||||
return
|
||||
|
||||
if(signal.data["active"] == secbot)
|
||||
switch(recv)
|
||||
if("stop")
|
||||
secbot.mode = SECBOT_IDLE
|
||||
secbot.auto_patrol = 0
|
||||
return
|
||||
|
||||
if("go")
|
||||
secbot.mode = SECBOT_IDLE
|
||||
secbot.auto_patrol = 1
|
||||
return
|
||||
|
||||
if("summon")
|
||||
secbot.patrol_target = signal.data["target"]
|
||||
secbot.next_destination = secbot.destination
|
||||
secbot.destination = null
|
||||
//secbot.awaiting_beacon = 0
|
||||
secbot.mode = SECBOT_SUMMON
|
||||
secbot.calc_path()
|
||||
secbot.say("Responding.")
|
||||
return
|
||||
|
||||
recv = signal.data["beacon"]
|
||||
var/valid = signal.data["patrol"]
|
||||
if(!recv || !valid)
|
||||
return
|
||||
|
||||
if(recv == secbot.next_destination) // This beacon is our target
|
||||
secbot.destination = secbot.next_destination
|
||||
secbot.patrol_target = signal.source.loc
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
else if(secbot.next_destination == "__nearest__")
|
||||
var/dist = get_dist(secbot, signal.source.loc)
|
||||
if(dist <= 1)
|
||||
return
|
||||
|
||||
if(secbot.nearest_beacon)
|
||||
if(dist < secbot.closest_dist)
|
||||
secbot.nearest_beacon = recv
|
||||
secbot.patrol_target = secbot.nearest_beacon
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
secbot.closest_dist = dist
|
||||
return
|
||||
else
|
||||
secbot.nearest_beacon = recv
|
||||
secbot.patrol_target = secbot.nearest_beacon
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
secbot.closest_dist = dist
|
||||
|
||||
//Secbot Construction
|
||||
|
||||
/obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/carbon/alien/ex_act(severity)
|
||||
|
||||
if(!blinded)
|
||||
flick("flash", flash)
|
||||
flash_eyes()
|
||||
|
||||
var/b_loss = null
|
||||
var/f_loss = null
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/mob/living/carbon/human/H = over_object
|
||||
if(!istype(H) || !Adjacent(H))
|
||||
return ..()
|
||||
if(H.a_intent == "grab" && hat && !(H.l_hand && H.r_hand))
|
||||
if(H.a_intent == "grab" && hat && !H.hands_are_full())
|
||||
hat.loc = get_turf(src)
|
||||
H.put_in_hands(hat)
|
||||
H.visible_message("<span class='danger'>\The [H] removes \the [src]'s [hat].</span>")
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
if (client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot send IC messages (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
if (stat)
|
||||
return
|
||||
if(!(message))
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
silent = 0
|
||||
else
|
||||
updatehealth()
|
||||
handle_stunned()
|
||||
handle_weakened()
|
||||
if(health <= 0)
|
||||
death()
|
||||
blinded = 1
|
||||
@@ -52,7 +50,6 @@
|
||||
return 1
|
||||
|
||||
if(paralysis && paralysis > 0)
|
||||
handle_paralysed()
|
||||
blinded = 1
|
||||
stat = UNCONSCIOUS
|
||||
if(halloss > 0)
|
||||
@@ -127,21 +124,16 @@
|
||||
if (client)
|
||||
client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired)
|
||||
|
||||
if ((blind && stat != 2))
|
||||
if ( stat != 2)
|
||||
if ((blinded))
|
||||
blind.layer = 18
|
||||
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
||||
else
|
||||
blind.layer = 0
|
||||
if (disabilities & NEARSIGHTED)
|
||||
client.screen += global_hud.vimpaired
|
||||
if (eye_blurry)
|
||||
client.screen += global_hud.blurry
|
||||
if (druggy)
|
||||
client.screen += global_hud.druggy
|
||||
|
||||
if (stat != 2)
|
||||
if (machine)
|
||||
if ( machine.check_eye(src) < 0)
|
||||
clear_fullscreen("blind")
|
||||
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /obj/screen/fullscreen/impaired, 1)
|
||||
set_fullscreen(eye_blurry, "blurry", /obj/screen/fullscreen/blurry)
|
||||
set_fullscreen(druggy, "high", /obj/screen/fullscreen/high)
|
||||
if(machine)
|
||||
if(machine.check_eye(src) < 0)
|
||||
reset_view(null)
|
||||
else
|
||||
if(client && !client.adminobs)
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
if (client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot send IC messages (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
if (stat)
|
||||
return
|
||||
if(!(message))
|
||||
@@ -70,7 +68,7 @@
|
||||
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.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_sight) && !(M in viewers(src,null)))
|
||||
M.show_message(message)
|
||||
|
||||
|
||||
|
||||
@@ -157,8 +157,6 @@
|
||||
src << "\red All systems restored."
|
||||
emp_damage -= 1
|
||||
|
||||
//Other
|
||||
handle_statuses()
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/brain/handle_regular_hud_updates()
|
||||
@@ -210,22 +208,15 @@
|
||||
if (client)
|
||||
client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired)
|
||||
|
||||
if ((blind && stat != 2))
|
||||
if ((blinded))
|
||||
blind.layer = 18
|
||||
else
|
||||
blind.layer = 0
|
||||
|
||||
if (disabilities & NEARSIGHTED)
|
||||
client.screen += global_hud.vimpaired
|
||||
|
||||
if (eye_blurry)
|
||||
client.screen += global_hud.blurry
|
||||
|
||||
if (druggy)
|
||||
client.screen += global_hud.druggy
|
||||
|
||||
if (stat != 2)
|
||||
if ((blinded))
|
||||
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
||||
else
|
||||
clear_fullscreen("blind")
|
||||
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /obj/screen/fullscreen/impaired, 1)
|
||||
set_fullscreen(eye_blurry, "blurry", /obj/screen/fullscreen/blurry)
|
||||
set_fullscreen(druggy, "high", /obj/screen/fullscreen/high)
|
||||
|
||||
if (machine)
|
||||
if (!( machine.check_eye(src) ))
|
||||
reset_view(null)
|
||||
@@ -241,17 +232,4 @@
|
||||
reset_view(null)
|
||||
else
|
||||
if(client && !client.adminobs)
|
||||
reset_view(null)
|
||||
|
||||
/*/mob/living/carbon/brain/emp_act(severity)
|
||||
if(!(container && istype(container, /obj/item/device/mmi)))
|
||||
return
|
||||
else
|
||||
switch(severity)
|
||||
if(1)
|
||||
emp_damage += rand(20,30)
|
||||
if(2)
|
||||
emp_damage += rand(10,20)
|
||||
if(3)
|
||||
emp_damage += rand(0,10)
|
||||
..()*/
|
||||
reset_view(null)
|
||||
@@ -23,7 +23,7 @@
|
||||
spawn(600) reset_search()
|
||||
|
||||
/obj/item/device/mmi/digital/posibrain/proc/request_player()
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(!O.MayRespawn())
|
||||
continue
|
||||
if(jobban_isbanned(O, "AI") && jobban_isbanned(O, "Cyborg"))
|
||||
@@ -74,6 +74,7 @@
|
||||
/obj/item/device/mmi/digital/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
|
||||
|
||||
if(src.brainmob && src.brainmob.key) return
|
||||
world.log << "Resetting Posibrain: [brainmob][brainmob ? ", [brainmob.key]" : ""]"
|
||||
|
||||
src.searching = 0
|
||||
icon_state = "posibrain"
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
status += "hurts when touched"
|
||||
if(org.status & ORGAN_DEAD)
|
||||
status += "is bruised and necrotic"
|
||||
if(!org.is_usable())
|
||||
if(!org.is_usable() || org.is_dislocated())
|
||||
status += "dangling uselessly"
|
||||
if(status.len)
|
||||
src.show_message("My [org.name] is <span class='warning'> [english_list(status)].</span>",1)
|
||||
@@ -309,14 +309,19 @@
|
||||
|
||||
if(!item) return
|
||||
|
||||
var/throw_range = item.throw_range
|
||||
if (istype(item, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = item
|
||||
item = G.throw_held() //throw the person instead of the grab
|
||||
if(ismob(item))
|
||||
var/mob/M = item
|
||||
|
||||
//limit throw range by relative mob size
|
||||
throw_range = round(M.throw_range * min(src.mob_size/M.mob_size, 1))
|
||||
|
||||
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/mob/M = item
|
||||
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>"
|
||||
|
||||
@@ -324,31 +329,28 @@
|
||||
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]</font>")
|
||||
msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
|
||||
if(!item) return //Grab processing has a chance of returning null
|
||||
|
||||
|
||||
src.remove_from_mob(item)
|
||||
item.loc = src.loc
|
||||
src.drop_from_inventory(item)
|
||||
if(!item || !isturf(item.loc))
|
||||
return
|
||||
|
||||
//actually throw it!
|
||||
if (item)
|
||||
src.visible_message("\red [src] has thrown [item].")
|
||||
src.visible_message("<span class='warning'>[src] has thrown [item].</span>")
|
||||
|
||||
if(!src.lastarea)
|
||||
src.lastarea = get_area(src.loc)
|
||||
if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
|
||||
src.inertia_dir = get_dir(target, src)
|
||||
step(src, inertia_dir)
|
||||
if(!src.lastarea)
|
||||
src.lastarea = get_area(src.loc)
|
||||
if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
|
||||
src.inertia_dir = get_dir(target, src)
|
||||
step(src, inertia_dir)
|
||||
|
||||
|
||||
/*
|
||||
if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
|
||||
src.inertia_dir = get_dir(target, src)
|
||||
step(src, inertia_dir)
|
||||
if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
|
||||
src.inertia_dir = get_dir(target, src)
|
||||
step(src, inertia_dir)
|
||||
*/
|
||||
|
||||
|
||||
item.throw_at(target, item.throw_range, item.throw_speed, src)
|
||||
item.throw_at(target, throw_range, item.throw_speed, src)
|
||||
|
||||
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
..()
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
//Called when the mob is hit with an item in combat.
|
||||
/mob/living/carbon/resolve_item_attack(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
if(check_attack_throat(I, user))
|
||||
return null
|
||||
..()
|
||||
|
||||
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
if(!effective_force || blocked >= 100)
|
||||
return 0
|
||||
|
||||
//Hulk modifier
|
||||
if(HULK in user.mutations)
|
||||
effective_force *= 2
|
||||
|
||||
//Apply weapon damage
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if(prob(getarmor(hit_zone, "melee"))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
//Melee weapon embedded object code.
|
||||
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
|
||||
var/damage = effective_force
|
||||
if (blocked)
|
||||
damage *= (100 - blocked)/100
|
||||
|
||||
//blunt objects should really not be embedding in things unless a huge amount of force is involved
|
||||
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
|
||||
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
|
||||
|
||||
//Sharp objects will always embed if they do enough damage.
|
||||
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
|
||||
src.embed(I, hit_zone)
|
||||
|
||||
return 1
|
||||
|
||||
// Attacking someone with a weapon while they are neck-grabbed
|
||||
/mob/living/carbon/proc/check_attack_throat(obj/item/W, mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
for(var/obj/item/weapon/grab/G in src.grabbed_by)
|
||||
if(G.assailant == user && G.state >= GRAB_NECK)
|
||||
if(attack_throat(W, G, user))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Knifing
|
||||
/mob/living/carbon/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
if(!W.edge || !W.force || W.damtype != BRUTE)
|
||||
return 0 //unsuitable weapon
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
|
||||
|
||||
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
|
||||
if(!do_after(user, 20))
|
||||
return 0
|
||||
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
|
||||
return 0
|
||||
|
||||
var/damage_mod = 1
|
||||
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
|
||||
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
|
||||
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.flags & STOPPRESSUREDAMAGE))
|
||||
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
|
||||
damage_mod = 1.0 - (helmet.armor["melee"]/100)
|
||||
|
||||
var/total_damage = 0
|
||||
for(var/i in 1 to 3)
|
||||
var/damage = min(W.force*1.5, 20)*damage_mod
|
||||
apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge)
|
||||
total_damage += damage
|
||||
|
||||
var/oxyloss = total_damage
|
||||
if(total_damage >= 40) //threshold to make someone pass out
|
||||
oxyloss = 60 // Brain lacks oxygen immediately, pass out
|
||||
|
||||
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
|
||||
|
||||
if(total_damage)
|
||||
if(oxyloss >= 40)
|
||||
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
|
||||
|
||||
if(W.hitsound)
|
||||
playsound(loc, W.hitsound, 50, 1, -1)
|
||||
|
||||
G.last_action = world.time
|
||||
flick(G.hud.icon_state, G.hud)
|
||||
|
||||
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
|
||||
return 1
|
||||
@@ -3,40 +3,40 @@
|
||||
set name = "Give"
|
||||
|
||||
// TODO : Change to incapacitated() on merge.
|
||||
if(usr.stat || usr.lying || usr.resting || usr.buckled)
|
||||
if(src.stat || src.lying || src.resting || src.buckled)
|
||||
return
|
||||
if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null)
|
||||
return
|
||||
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
var/obj/item/I = src.get_active_hand()
|
||||
if(!I)
|
||||
I = usr.get_inactive_hand()
|
||||
I = src.get_inactive_hand()
|
||||
if(!I)
|
||||
usr << "<span class='warning'>You don't have anything in your hands to give to \the [target].</span>"
|
||||
src << "<span class='warning'>You don't have anything in your hands to give to \the [target].</span>"
|
||||
return
|
||||
|
||||
if(alert(target,"[usr] wants to give you \a [I]. Will you accept it?",,"No","Yes") == "No")
|
||||
target.visible_message("<span class='notice'>\The [usr] tried to hand \the [I] to \the [target], \
|
||||
if(alert(target,"[src] wants to give you \a [I]. Will you accept it?",,"No","Yes") == "No")
|
||||
target.visible_message("<span class='notice'>\The [src] tried to hand \the [I] to \the [target], \
|
||||
but \the [target] didn't want it.</span>")
|
||||
return
|
||||
|
||||
if(!I) return
|
||||
|
||||
if(!Adjacent(target))
|
||||
usr << "<span class='warning'>You need to stay in reaching distance while giving an object.</span>"
|
||||
target << "<span class='warning'>\The [usr] moved too far away.</span>"
|
||||
src << "<span class='warning'>You need to stay in reaching distance while giving an object.</span>"
|
||||
target << "<span class='warning'>\The [src] moved too far away.</span>"
|
||||
return
|
||||
|
||||
if(I.loc != usr || (usr.l_hand != I && usr.r_hand != I))
|
||||
usr << "<span class='warning'>You need to keep the item in your hands.</span>"
|
||||
target << "<span class='warning'>\The [usr] seems to have given up on passing \the [I] to you.</span>"
|
||||
if(I.loc != src || !src.item_is_in_hands(I))
|
||||
src << "<span class='warning'>You need to keep the item in your hands.</span>"
|
||||
target << "<span class='warning'>\The [src] seems to have given up on passing \the [I] to you.</span>"
|
||||
return
|
||||
|
||||
if(target.r_hand != null && target.l_hand != null)
|
||||
if(target.hands_are_full())
|
||||
target << "<span class='warning'>Your hands are full.</span>"
|
||||
usr << "<span class='warning'>Their hands are full.</span>"
|
||||
src << "<span class='warning'>Their hands are full.</span>"
|
||||
return
|
||||
|
||||
if(usr.unEquip(I))
|
||||
if(src.unEquip(I))
|
||||
target.put_in_hands(I) // If this fails it will just end up on the floor, but that's fitting for things like dionaea.
|
||||
target.visible_message("<span class='notice'>\The [usr] handed \the [I] to \the [target].</span>")
|
||||
target.visible_message("<span class='notice'>\The [src] handed \the [I] to \the [target].</span>")
|
||||
|
||||
@@ -143,13 +143,13 @@
|
||||
var/datum/species/current_species = all_species[current_species_name]
|
||||
|
||||
if(check_whitelist && config.usealienwhitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it!
|
||||
if(!(current_species.spawn_flags & CAN_JOIN))
|
||||
if(!(current_species.spawn_flags & SPECIES_CAN_JOIN))
|
||||
continue
|
||||
if(whitelist.len && !(current_species_name in whitelist))
|
||||
continue
|
||||
if(blacklist.len && (current_species_name in blacklist))
|
||||
continue
|
||||
if((current_species.spawn_flags & IS_WHITELISTED) && !is_alien_whitelisted(src, current_species_name))
|
||||
if((current_species.spawn_flags & SPECIES_IS_WHITELISTED) && !is_alien_whitelisted(src, current_species_name))
|
||||
continue
|
||||
|
||||
valid_species += current_species_name
|
||||
@@ -158,9 +158,9 @@
|
||||
|
||||
/mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1)
|
||||
|
||||
var/use_species = species.get_bodytype()
|
||||
var/use_species = species.get_bodytype(src)
|
||||
var/obj/item/organ/external/head/H = get_organ(BP_HEAD)
|
||||
if(H) use_species = H.species.get_bodytype()
|
||||
if(H) use_species = H.species.get_bodytype(src)
|
||||
|
||||
var/list/valid_hairstyles = new()
|
||||
for(var/hairstyle in hair_styles_list)
|
||||
@@ -180,9 +180,9 @@
|
||||
|
||||
/mob/living/carbon/human/proc/generate_valid_facial_hairstyles()
|
||||
|
||||
var/use_species = species.get_bodytype()
|
||||
var/use_species = species.get_bodytype(src)
|
||||
var/obj/item/organ/external/head/H = get_organ(BP_HEAD)
|
||||
if(H) use_species = H.species.get_bodytype()
|
||||
if(H) use_species = H.species.get_bodytype(src)
|
||||
|
||||
var/list/valid_facial_hairstyles = new()
|
||||
for(var/facialhairstyle in facial_hair_styles_list)
|
||||
|
||||
@@ -31,19 +31,18 @@
|
||||
BITSET(hud_updateflag, STATUS_HUD)
|
||||
BITSET(hud_updateflag, LIFE_HUD)
|
||||
|
||||
handle_hud_list()
|
||||
|
||||
//Handle species-specific deaths.
|
||||
species.handle_death(src)
|
||||
animate_tail_stop()
|
||||
|
||||
//Handle brain slugs.
|
||||
var/obj/item/organ/external/head = get_organ(BP_HEAD)
|
||||
var/obj/item/organ/external/Hd = get_organ(BP_HEAD)
|
||||
var/mob/living/simple_animal/borer/B
|
||||
|
||||
for(var/I in head.implants)
|
||||
if(istype(I,/mob/living/simple_animal/borer))
|
||||
B = I
|
||||
if(Hd)
|
||||
for(var/I in Hd.implants)
|
||||
if(istype(I,/mob/living/simple_animal/borer))
|
||||
B = I
|
||||
if(B)
|
||||
if(!B.ckey && ckey && B.controlling)
|
||||
B.ckey = ckey
|
||||
|
||||
@@ -112,8 +112,6 @@
|
||||
if (client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot send IC messages (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
if (stat)
|
||||
return
|
||||
if(!(message))
|
||||
@@ -538,9 +536,9 @@
|
||||
if ("handshake")
|
||||
m_type = 1
|
||||
if (!src.restrained() && !src.r_hand)
|
||||
var/mob/M = null
|
||||
var/mob/living/M = null
|
||||
if (param)
|
||||
for (var/mob/A in view(1, null))
|
||||
for (var/mob/living/A in view(1, null))
|
||||
if (param == A.name)
|
||||
M = A
|
||||
break
|
||||
|
||||
@@ -4,29 +4,72 @@
|
||||
var/skipjumpsuit = 0
|
||||
var/skipshoes = 0
|
||||
var/skipmask = 0
|
||||
|
||||
var/skipears = 0
|
||||
var/skipeyes = 0
|
||||
var/skipface = 0
|
||||
var/skipchest = 0
|
||||
var/skipgroin = 0
|
||||
var/skiphands = 0
|
||||
var/skiplegs = 0
|
||||
var/skiparms = 0
|
||||
var/skipfeet = 0
|
||||
|
||||
var/looks_synth = looksSynthetic()
|
||||
|
||||
//exosuits and helmets obscure our view and stuff.
|
||||
if(wear_suit)
|
||||
skipgloves = wear_suit.flags_inv & HIDEGLOVES
|
||||
skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE
|
||||
skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT
|
||||
skipshoes = wear_suit.flags_inv & HIDESHOES
|
||||
skipsuitstorage |= wear_suit.flags_inv & HIDESUITSTORAGE
|
||||
if(wear_suit.flags_inv & HIDEJUMPSUIT)
|
||||
skiparms |= 1
|
||||
skiplegs |= 1
|
||||
skipchest |= 1
|
||||
skipgroin |= 1
|
||||
if(wear_suit.flags_inv & HIDESHOES)
|
||||
skipshoes |= 1
|
||||
skipfeet |= 1
|
||||
if(wear_suit.flags_inv & HIDEGLOVES)
|
||||
skipgloves |= 1
|
||||
skiphands |= 1
|
||||
|
||||
if(w_uniform)
|
||||
skiplegs |= w_uniform.body_parts_covered & LEGS
|
||||
skiparms |= w_uniform.body_parts_covered & ARMS
|
||||
skipchest |= w_uniform.body_parts_covered & UPPER_TORSO
|
||||
skipgroin |= w_uniform.body_parts_covered & LOWER_TORSO
|
||||
|
||||
if(gloves)
|
||||
skiphands |= gloves.body_parts_covered & HANDS
|
||||
|
||||
if(shoes)
|
||||
skipfeet |= shoes.body_parts_covered & FEET
|
||||
|
||||
if(head)
|
||||
skipmask = head.flags_inv & HIDEMASK
|
||||
skipeyes = head.flags_inv & HIDEEYES
|
||||
skipears = head.flags_inv & HIDEEARS
|
||||
skipface = head.flags_inv & HIDEFACE
|
||||
skipmask |= head.flags_inv & HIDEMASK
|
||||
skipeyes |= head.flags_inv & HIDEEYES
|
||||
skipears |= head.flags_inv & HIDEEARS
|
||||
skipface |= head.flags_inv & HIDEFACE
|
||||
|
||||
if(wear_mask)
|
||||
skipface |= wear_mask.flags_inv & HIDEFACE
|
||||
|
||||
//This is what hides what
|
||||
var/list/hidden = list(
|
||||
BP_GROIN = skipgroin,
|
||||
BP_TORSO = skipchest,
|
||||
BP_HEAD = skipface,
|
||||
BP_L_ARM = skiparms,
|
||||
BP_R_ARM = skiparms,
|
||||
BP_L_HAND= skiphands,
|
||||
BP_R_HAND= skiphands,
|
||||
BP_L_FOOT= skipfeet,
|
||||
BP_R_FOOT= skipfeet,
|
||||
BP_L_LEG = skiplegs,
|
||||
BP_R_LEG = skiplegs)
|
||||
|
||||
var/msg = "<span class='info'>*---------*\nThis is "
|
||||
|
||||
var/datum/gender/T = gender_datums[gender]
|
||||
var/datum/gender/T = gender_datums[get_gender()]
|
||||
if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender
|
||||
T = gender_datums[PLURAL]
|
||||
else
|
||||
@@ -39,19 +82,23 @@
|
||||
|
||||
msg += "<EM>[src.name]</EM>"
|
||||
|
||||
var/is_synth = isSynthetic()
|
||||
if(!(skipjumpsuit && skipface))
|
||||
if(is_synth)
|
||||
if(looks_synth)
|
||||
var/use_gender = "a synthetic"
|
||||
if(gender == MALE)
|
||||
use_gender = "an android"
|
||||
else if(gender == FEMALE)
|
||||
use_gender = "a gynoid"
|
||||
|
||||
msg += ", <font color='#555555'>[use_gender]!</font></b>"
|
||||
msg += ", <b><font color='#555555'>[use_gender]!</font></b>"
|
||||
|
||||
else if(species.name != "Human")
|
||||
msg += ", <b><font color='[species.get_flesh_colour(src)]'>\a [species.name]!</font></b>"
|
||||
msg += ", <b><font color='[species.get_flesh_colour(src)]'>\a [species.get_examine_name()]!</font></b>"
|
||||
|
||||
var/extra_species_text = species.get_additional_examine_text(src)
|
||||
if(extra_species_text)
|
||||
msg += "[extra_species_text]<br>"
|
||||
|
||||
msg += "<br>"
|
||||
|
||||
//uniform
|
||||
@@ -119,8 +166,6 @@
|
||||
else if(blood_DNA)
|
||||
msg += "<span class='warning'>[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!</span>\n"
|
||||
|
||||
//handcuffed?
|
||||
|
||||
//handcuffed?
|
||||
if(handcuffed)
|
||||
if(istype(handcuffed, /obj/item/weapon/handcuffs/cable))
|
||||
@@ -210,7 +255,7 @@
|
||||
msg += "[T.He] [T.is] small halfling!\n"
|
||||
|
||||
var/distance = get_dist(usr,src)
|
||||
if(istype(usr, /mob/dead/observer) || usr.stat == 2) // ghosts can see anything
|
||||
if(istype(usr, /mob/observer/dead) || usr.stat == 2) // ghosts can see anything
|
||||
distance = 1
|
||||
if (src.stat)
|
||||
msg += "<span class='warning'>[T.He] [T.is]n't responding to anything around [T.him] and seems to be asleep.</span>\n"
|
||||
@@ -268,21 +313,23 @@
|
||||
|
||||
for(var/obj/item/organ/external/temp in organs)
|
||||
if(temp)
|
||||
if((temp.organ_tag in hidden) && hidden[temp.organ_tag])
|
||||
continue //Organ is hidden, don't talk about it
|
||||
if(temp.status & ORGAN_DESTROYED)
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'><b>[T.He] [T.is] missing [T.his] [temp.name].</b></span>\n"
|
||||
continue
|
||||
if(!is_synth && temp.status & ORGAN_ROBOT)
|
||||
if(!looks_synth && temp.robotic == ORGAN_ROBOT)
|
||||
if(!(temp.brute_dam + temp.burn_dam))
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name]!</span>\n"
|
||||
continue
|
||||
wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name].\n"
|
||||
else
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name]. It has[temp.get_wounds_desc()]!</span>\n"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!</span>\n"
|
||||
continue
|
||||
else if(temp.wounds.len > 0 || temp.open)
|
||||
if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ])
|
||||
var/obj/item/organ/external/parent = organs_by_name[temp.parent_organ]
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.His] [parent.name].</span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [parent.name].</span><br>"
|
||||
else
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.His] [temp.name].</span><br>"
|
||||
wound_flavor_text["[temp.name]"] = "<span class='warning'>[T.He] has [temp.get_wounds_desc()] on [T.his] [temp.name].</span><br>"
|
||||
if(temp.status & ORGAN_BLEEDING)
|
||||
is_bleeding["[temp.name]"] = "<span class='danger'>[T.His] [temp.name] is bleeding!</span><br>"
|
||||
else
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
/mob/living/carbon/human/Stat()
|
||||
..()
|
||||
if(statpanel("Status"))
|
||||
stat(null, "Intent: [a_intent]")
|
||||
stat(null, "Move Mode: [m_intent]")
|
||||
stat("Intent:", "[a_intent]")
|
||||
stat("Move Mode:", "[m_intent]")
|
||||
if(emergency_shuttle)
|
||||
var/eta_status = emergency_shuttle.get_status_panel_eta()
|
||||
if(eta_status)
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
/mob/living/carbon/human/ex_act(severity)
|
||||
if(!blinded)
|
||||
flick("flash", flash)
|
||||
flash_eyes()
|
||||
|
||||
var/shielded = 0
|
||||
var/b_loss = null
|
||||
@@ -150,21 +150,21 @@
|
||||
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
|
||||
if(update) UpdateDamageIcon()
|
||||
|
||||
/mob/living/carbon/human/proc/implant_loyalty(mob/living/carbon/human/M, override = FALSE) // Won't override by default.
|
||||
/mob/living/carbon/human/proc/implant_loyalty(override = FALSE) // Won't override by default.
|
||||
if(!config.use_loyalty_implants && !override) return // Nuh-uh.
|
||||
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(M)
|
||||
L.imp_in = M
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)
|
||||
L.imp_in = src
|
||||
L.implanted = 1
|
||||
var/obj/item/organ/external/affected = M.organs_by_name[BP_HEAD]
|
||||
var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD]
|
||||
affected.implants += L
|
||||
L.part = affected
|
||||
L.implanted(src)
|
||||
|
||||
/mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M)
|
||||
for(var/L in M.contents)
|
||||
/mob/living/carbon/human/proc/is_loyalty_implanted()
|
||||
for(var/L in src.contents)
|
||||
if(istype(L, /obj/item/weapon/implant/loyalty))
|
||||
for(var/obj/item/organ/external/O in M.organs)
|
||||
for(var/obj/item/organ/external/O in src.organs)
|
||||
if(L in O.implants)
|
||||
return 1
|
||||
return 0
|
||||
@@ -326,11 +326,19 @@
|
||||
//Removed the horrible safety parameter. It was only being used by ninja code anyways.
|
||||
//Now checks siemens_coefficient of the affected area by default
|
||||
/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null)
|
||||
|
||||
if(status_flags & GODMODE) return 0 //godmode
|
||||
|
||||
if (!def_zone)
|
||||
def_zone = pick("l_hand", "r_hand")
|
||||
|
||||
if(species.siemens_coefficient == -1)
|
||||
if(stored_shock_by_ref["\ref[src]"])
|
||||
stored_shock_by_ref["\ref[src]"] += shock_damage
|
||||
else
|
||||
stored_shock_by_ref["\ref[src]"] = shock_damage
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/affected_organ = get_organ(check_zone(def_zone))
|
||||
var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ)
|
||||
|
||||
@@ -766,13 +774,6 @@
|
||||
b_eyes = hex2num(copytext(new_eyes, 6, 8))
|
||||
update_eyes()
|
||||
|
||||
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-s_tone]") as text
|
||||
|
||||
if (!new_tone)
|
||||
new_tone = 35
|
||||
s_tone = max(min(round(text2num(new_tone)), 220), 1)
|
||||
s_tone = -s_tone + 35
|
||||
|
||||
// hair
|
||||
var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
|
||||
var/list/hairs = list()
|
||||
@@ -842,7 +843,7 @@
|
||||
target.show_message("\blue You hear a voice that seems to echo around the room: [say]")
|
||||
usr.show_message("\blue You project your mind into [target.real_name]: [say]")
|
||||
log_say("[key_name(usr)] sent a telepathic message to [key_name(target)]: [say]")
|
||||
for(var/mob/dead/observer/G in world)
|
||||
for(var/mob/observer/dead/G in world)
|
||||
G.show_message("<i>Telepathic message from <b>[src]</b> to <b>[target]</b>: [say]</i>")
|
||||
|
||||
/mob/living/carbon/human/proc/remoteobserve()
|
||||
@@ -1022,7 +1023,7 @@
|
||||
src << msg
|
||||
|
||||
organ.take_damage(rand(1,3), 0, 0)
|
||||
if(!(organ.status & ORGAN_ROBOT) && !should_have_organ(O_HEART)) //There is no blood in protheses.
|
||||
if(!(organ.robotic >= ORGAN_ROBOT) && !(should_have_organ(O_HEART))) //There is no blood in protheses.
|
||||
organ.status |= ORGAN_BLEEDING
|
||||
src.adjustToxLoss(rand(1,3))
|
||||
|
||||
@@ -1104,6 +1105,9 @@
|
||||
if(species.holder_type)
|
||||
holder_type = species.holder_type
|
||||
|
||||
if(!(gender in species.genders))
|
||||
gender = species.genders[1]
|
||||
|
||||
icon_state = lowertext(species.name)
|
||||
|
||||
species.create_organs(src)
|
||||
@@ -1115,9 +1119,11 @@
|
||||
spawn(0)
|
||||
regenerate_icons()
|
||||
if(vessel.total_volume < species.blood_volume)
|
||||
vessel.maximum_volume = species.blood_volume
|
||||
vessel.add_reagent("blood", species.blood_volume - vessel.total_volume)
|
||||
else if(vessel.total_volume > species.blood_volume)
|
||||
vessel.remove_reagent("blood", vessel.total_volume - species.blood_volume)
|
||||
vessel.maximum_volume = species.blood_volume
|
||||
fixblood()
|
||||
|
||||
// Rebuild the HUD. If they aren't logged in then login() should reinstantiate it for them.
|
||||
@@ -1127,8 +1133,6 @@
|
||||
qdel(hud_used)
|
||||
hud_used = new /datum/hud(src)
|
||||
|
||||
full_prosthetic = null
|
||||
|
||||
if(species)
|
||||
return 1
|
||||
else
|
||||
@@ -1203,7 +1207,7 @@
|
||||
if(!affecting)
|
||||
. = 0
|
||||
fail_msg = "They are missing that limb."
|
||||
else if (affecting.status & ORGAN_ROBOT)
|
||||
else if (affecting.robotic >= ORGAN_ROBOT)
|
||||
. = 0
|
||||
fail_msg = "That limb is robotic."
|
||||
else
|
||||
@@ -1320,8 +1324,8 @@
|
||||
var/list/limbs = list()
|
||||
for(var/limb in organs_by_name)
|
||||
var/obj/item/organ/external/current_limb = organs_by_name[limb]
|
||||
if(current_limb && current_limb.dislocated == 2)
|
||||
limbs |= limb
|
||||
if(current_limb && current_limb.dislocated > 0 && !current_limb.is_parent_dislocated()) //if the parent is also dislocated you will have to relocate that first
|
||||
limbs |= current_limb
|
||||
var/choice = input(usr,"Which joint do you wish to relocate?") as null|anything in limbs
|
||||
|
||||
if(!choice)
|
||||
@@ -1431,7 +1435,7 @@
|
||||
else if(organ_check in list(O_LIVER, O_KIDNEYS))
|
||||
affecting = organs_by_name[BP_GROIN]
|
||||
|
||||
if(affecting && (affecting.status & ORGAN_ROBOT))
|
||||
if(affecting && (affecting.robotic >= ORGAN_ROBOT))
|
||||
return 0
|
||||
return (species && species.has_organ[organ_check])
|
||||
|
||||
|
||||
@@ -310,23 +310,6 @@
|
||||
updatehealth()
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/proc/attack_joint(var/obj/item/W, var/mob/living/user, var/def_zone)
|
||||
if(!def_zone) def_zone = user.zone_sel.selecting
|
||||
var/target_zone = get_zone_with_miss_chance(check_zone(def_zone), src)
|
||||
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
return null
|
||||
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
|
||||
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1))
|
||||
return null
|
||||
var/dislocation_str
|
||||
if(prob(W.force))
|
||||
dislocation_str = "[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!"
|
||||
organ.dislocate(1)
|
||||
return dislocation_str
|
||||
|
||||
//Used to attack a joint through grabbing
|
||||
/mob/living/carbon/human/proc/grab_joint(var/mob/living/user, var/def_zone)
|
||||
var/has_grab = 0
|
||||
@@ -343,7 +326,7 @@
|
||||
if(!target_zone)
|
||||
return 0
|
||||
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
|
||||
if(!organ || organ.is_dislocated() || organ.dislocated == -1)
|
||||
if(!organ || organ.dislocated > 0 || organ.dislocated == -1) //don't use is_dislocated() here, that checks parent
|
||||
return 0
|
||||
|
||||
user.visible_message("<span class='warning'>[user] begins to dislocate [src]'s [organ.joint]!</span>")
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
var/total_burn = 0
|
||||
var/total_brute = 0
|
||||
for(var/obj/item/organ/external/O in organs) //hardcoded to streamline things a bit
|
||||
if((O.status & ORGAN_ROBOT) && !O.vital)
|
||||
continue // Non-vital robot limbs don't count towards shock and crit
|
||||
if((O.robotic >= ORGAN_ROBOT) && !O.vital)
|
||||
continue //*non-vital* robot limbs don't count towards shock and crit
|
||||
total_brute += O.brute_dam
|
||||
total_burn += O.burn_dam
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
/mob/living/carbon/human/getBruteLoss()
|
||||
var/amount = 0
|
||||
for(var/obj/item/organ/external/O in organs)
|
||||
if((O.status & ORGAN_ROBOT) && !O.vital)
|
||||
if(O.robotic >= ORGAN_ROBOT)
|
||||
continue //robot limbs don't count towards shock and crit
|
||||
amount += O.brute_dam
|
||||
return amount
|
||||
@@ -75,7 +75,7 @@
|
||||
/mob/living/carbon/human/getFireLoss()
|
||||
var/amount = 0
|
||||
for(var/obj/item/organ/external/O in organs)
|
||||
if((O.status & ORGAN_ROBOT) && !O.vital)
|
||||
if(O.robotic >= ORGAN_ROBOT)
|
||||
continue //robot limbs don't count towards shock and crit
|
||||
amount += O.burn_dam
|
||||
return amount
|
||||
@@ -106,7 +106,7 @@
|
||||
O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
|
||||
else
|
||||
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
|
||||
O.heal_damage(-amount, 0, internal=0, robo_repair=(O.status & ORGAN_ROBOT))
|
||||
O.heal_damage(-amount, 0, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
|
||||
|
||||
BITSET(hud_updateflag, HEALTH_HUD)
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
|
||||
else
|
||||
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
|
||||
O.heal_damage(0, -amount, internal=0, robo_repair=(O.status & ORGAN_ROBOT))
|
||||
O.heal_damage(0, -amount, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
|
||||
|
||||
BITSET(hud_updateflag, HEALTH_HUD)
|
||||
|
||||
@@ -266,7 +266,6 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t
|
||||
UpdateDamageIcon()
|
||||
BITSET(hud_updateflag, HEALTH_HUD)
|
||||
updatehealth()
|
||||
speech_problem_flag = 1
|
||||
|
||||
|
||||
//Heal MANY external organs, in random order
|
||||
@@ -288,7 +287,6 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t
|
||||
parts -= picked
|
||||
updatehealth()
|
||||
BITSET(hud_updateflag, HEALTH_HUD)
|
||||
speech_problem_flag = 1
|
||||
if(update) UpdateDamageIcon()
|
||||
|
||||
// damage MANY external organs, in random order
|
||||
|
||||
@@ -57,7 +57,7 @@ emp_act
|
||||
msg_admin_attack("[src.name] ([src.ckey]) was disarmed by a stun effect")
|
||||
|
||||
drop_from_inventory(c_hand)
|
||||
if (affected.status & ORGAN_ROBOT)
|
||||
if (affected.robotic >= ORGAN_ROBOT)
|
||||
emote("me", 1, "drops what they were holding, their [affected.name] malfunctioning!")
|
||||
else
|
||||
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
|
||||
@@ -92,7 +92,7 @@ emp_act
|
||||
if (!def_zone)
|
||||
return 1.0
|
||||
|
||||
var/siemens_coefficient = species.siemens_coefficient
|
||||
var/siemens_coefficient = max(species.siemens_coefficient,0)
|
||||
|
||||
var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking?
|
||||
for(var/obj/item/clothing/C in clothing_items)
|
||||
@@ -139,67 +139,75 @@ emp_act
|
||||
if(.) return
|
||||
return 0
|
||||
|
||||
//Returns 1 if the attack hit, 0 if it missed.
|
||||
/mob/living/carbon/human/proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
|
||||
if(!I || !user) return 0
|
||||
/mob/living/carbon/human/emp_act(severity)
|
||||
for(var/obj/O in src)
|
||||
if(!O) continue
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src)
|
||||
/mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
||||
if(check_attack_throat(I, user))
|
||||
return null
|
||||
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
visible_message("<span class='danger'>[user] misses [src] with \the [I]!</span>")
|
||||
return 0
|
||||
return target_zone
|
||||
|
||||
var/obj/item/organ/external/affecting = get_organ(target_zone)
|
||||
var/hit_zone = get_zone_with_miss_chance(target_zone, src)
|
||||
|
||||
if(!hit_zone)
|
||||
visible_message("<span class='danger'>\The [user] misses [src] with \the [I]!</span>")
|
||||
return null
|
||||
|
||||
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if (!affecting || affecting.is_stump())
|
||||
user << "<span class='danger'>They are missing that limb!</span>"
|
||||
return null
|
||||
|
||||
return hit_zone
|
||||
|
||||
/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if(!affecting)
|
||||
return //should be prevented by attacked_with_item() but for sanity.
|
||||
|
||||
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [affecting.name] with [I.name] by [user]!</span>")
|
||||
|
||||
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
|
||||
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
|
||||
|
||||
return blocked
|
||||
|
||||
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if(!affecting)
|
||||
return 0
|
||||
|
||||
var/effective_force = I.force
|
||||
if(user.a_intent == "disarm") effective_force = round(I.force/2)
|
||||
var/hit_area = affecting.name
|
||||
// Handle striking to cripple.
|
||||
if(user.a_intent == I_DISARM)
|
||||
effective_force *= 0.66 //reduced effective force...
|
||||
if(!..(I, user, effective_force, blocked, hit_zone))
|
||||
return 0
|
||||
|
||||
if((user != src) && check_shields(effective_force, I, user, target_zone, "the [I.name]"))
|
||||
//set the dislocate mult less than the effective force mult so that
|
||||
//dislocating limbs on disarm is a bit easier than breaking limbs on harm
|
||||
attack_joint(affecting, I, effective_force, 0.5, blocked) //...but can dislocate joints
|
||||
else if(!..())
|
||||
return 0
|
||||
|
||||
if(istype(I,/obj/item/weapon/card/emag))
|
||||
if(!(affecting.status & ORGAN_ROBOT))
|
||||
user << "\red That limb isn't robotic."
|
||||
if(effective_force > 10 || effective_force >= 5 && prob(33))
|
||||
forcesay(hit_appends) //forcesay checks stat already
|
||||
|
||||
if(prob(25 + (effective_force * 2)))
|
||||
if(!((I.damtype == BRUTE) || (I.damtype == HALLOSS)))
|
||||
return
|
||||
if(affecting.sabotaged)
|
||||
user << "\red [src]'s [affecting.name] is already sabotaged!"
|
||||
else
|
||||
user << "\red You sneakily slide [I] into the dataport on [src]'s [affecting.name] and short out the safeties."
|
||||
var/obj/item/weapon/card/emag/emag = I
|
||||
emag.uses--
|
||||
affecting.sabotaged = 1
|
||||
return 1
|
||||
|
||||
if(I.attack_verb.len)
|
||||
visible_message("\red <B>[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!</B>")
|
||||
else
|
||||
visible_message("\red <B>[src] has been attacked in the [hit_area] with [I.name] by [user]!</B>")
|
||||
if(!(I.flags & NOBLOODY))
|
||||
I.add_blood(src)
|
||||
|
||||
var/armor = run_armor_check(affecting, "melee", I.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].")
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if ((weapon_sharp || weapon_edge) && prob(getarmor(target_zone, "melee")))
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
if(armor >= 100) return 0
|
||||
if(!effective_force) return 0
|
||||
var/Iforce = effective_force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
|
||||
|
||||
apply_damage(effective_force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
var/bloody = 0
|
||||
if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (effective_force * 2)))
|
||||
I.add_blood(src) //Make the weapon bloody, not the person.
|
||||
// if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon
|
||||
// else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays
|
||||
var/bloody = 0
|
||||
if(prob(33))
|
||||
bloody = 1
|
||||
var/turf/location = loc
|
||||
@@ -212,49 +220,55 @@ emp_act
|
||||
H.bloody_hands(src)
|
||||
|
||||
if(!stat)
|
||||
if(headcheck(hit_area))
|
||||
//Harder to score a stun but if you do it lasts a bit longer
|
||||
if(prob(effective_force))
|
||||
apply_effect(20, PARALYZE, armor)
|
||||
visible_message("<span class='danger'>[src] [species.get_knockout_message(src)]</span>")
|
||||
else
|
||||
//Easier to score a stun but lasts less time
|
||||
if(prob(effective_force + 10))
|
||||
apply_effect(6, WEAKEN, armor)
|
||||
visible_message("<span class='danger'>[src] has been knocked down!</span>")
|
||||
switch(hit_zone)
|
||||
if("head")//Harder to score a stun but if you do it lasts a bit longer
|
||||
if(prob(effective_force))
|
||||
apply_effect(20, PARALYZE, blocked)
|
||||
visible_message("<span class='danger'>\The [src] has been knocked unconscious!</span>")
|
||||
if(bloody)//Apply blood
|
||||
if(wear_mask)
|
||||
wear_mask.add_blood(src)
|
||||
update_inv_wear_mask(0)
|
||||
if(head)
|
||||
head.add_blood(src)
|
||||
update_inv_head(0)
|
||||
if(glasses && prob(33))
|
||||
glasses.add_blood(src)
|
||||
update_inv_glasses(0)
|
||||
if("chest")//Easier to score a stun but lasts less time
|
||||
if(prob(effective_force + 10))
|
||||
apply_effect(6, WEAKEN, blocked)
|
||||
visible_message("<span class='danger'>\The [src] has been knocked down!</span>")
|
||||
if(bloody)
|
||||
bloody_body(src)
|
||||
|
||||
//Apply blood
|
||||
if(bloody)
|
||||
switch(hit_area)
|
||||
if(BP_HEAD)
|
||||
if(wear_mask)
|
||||
wear_mask.add_blood(src)
|
||||
update_inv_wear_mask(0)
|
||||
if(head)
|
||||
head.add_blood(src)
|
||||
update_inv_head(0)
|
||||
if(glasses && prob(33))
|
||||
glasses.add_blood(src)
|
||||
update_inv_glasses(0)
|
||||
if(BP_TORSO)
|
||||
bloody_body(src)
|
||||
return 1
|
||||
|
||||
if(Iforce > 10 || Iforce >= 5 && prob(33))
|
||||
forcesay(hit_appends) //forcesay checks stat already
|
||||
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked)
|
||||
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
|
||||
return 0
|
||||
|
||||
//Melee weapon embedded object code.
|
||||
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
|
||||
var/damage = effective_force
|
||||
if (armor)
|
||||
damage /= armor+1
|
||||
if(W.damtype != BRUTE)
|
||||
return 0
|
||||
|
||||
//blunt objects should really not be embedding in things unless a huge amount of force is involved
|
||||
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
|
||||
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
|
||||
//want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb
|
||||
var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100
|
||||
if(prob(dislocate_chance * (100 - blocked)/100))
|
||||
visible_message("<span class='danger'>[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!</span>")
|
||||
organ.dislocate(1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Sharp objects will always embed if they do enough damage.
|
||||
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
|
||||
affecting.embed(I)
|
||||
/mob/living/carbon/human/emag_act(var/remaining_charges, mob/user, var/emag_source)
|
||||
var/obj/item/organ/external/affecting = get_organ(user.zone_sel.selecting)
|
||||
if(!affecting || !(affecting.status & ORGAN_ROBOT))
|
||||
user << "<span class='warning'>That limb isn't robotic.</span>"
|
||||
return -1
|
||||
if(affecting.sabotaged)
|
||||
user << "<span class='warning'>[src]'s [affecting.name] is already sabotaged!</span>"
|
||||
return -1
|
||||
user << "<span class='notice'>You sneakily slide [emag_source] into the dataport on [src]'s [affecting.name] and short out the safeties.</span>"
|
||||
affecting.sabotaged = 1
|
||||
return 1
|
||||
|
||||
//this proc handles being hit by a thrown atom
|
||||
|
||||
@@ -31,11 +31,10 @@
|
||||
|
||||
var/age = 30 //Player's age (pure fluff)
|
||||
var/b_type = "A+" //Player's bloodtype
|
||||
var/synthetic //If they are a synthetic (aka synthetic torso)
|
||||
|
||||
var/underwear_top = 1 //Which underwear the player wants
|
||||
var/underwear_bottom = 1
|
||||
var/undershirt = 0 //Which undershirt the player wants.
|
||||
var/socks = 0 //Which socks the player wants.
|
||||
var/list/all_underwear = list()
|
||||
var/list/all_underwear_metadata = list()
|
||||
var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack.
|
||||
var/pdachoice = 1 //Which PDA type the player has chosen. Default, Slim, or Old.
|
||||
|
||||
@@ -69,8 +68,6 @@
|
||||
|
||||
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
|
||||
|
||||
var/speech_problem_flag = 0
|
||||
|
||||
var/miming = null //Toggle for the mime's abilities.
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
@@ -85,9 +82,10 @@
|
||||
var/list/flavor_texts = list()
|
||||
var/gunshot_residue
|
||||
var/pulling_punches // Are you trying not to hurt your opponent?
|
||||
var/full_prosthetic // We are a robutt.
|
||||
var/robolimb_count = 0 // Number of robot limbs.
|
||||
|
||||
mob_bump_flag = HUMAN
|
||||
mob_push_flags = ~HEAVY
|
||||
mob_swap_flags = ~HEAVY
|
||||
|
||||
var/identifying_gender // In case the human identifies as another gender than it's biological
|
||||
|
||||
@@ -55,6 +55,40 @@
|
||||
sum += H.ear_protection
|
||||
return sum
|
||||
|
||||
/mob/living/carbon/human/get_gender()
|
||||
return identifying_gender ? identifying_gender : gender
|
||||
|
||||
// This is the 'mechanical' check for synthetic-ness, not appearance
|
||||
// Returns the company that made the synthetic
|
||||
/mob/living/carbon/human/isSynthetic()
|
||||
if(synthetic) return synthetic //Your synthetic-ness is not going away
|
||||
var/obj/item/organ/external/T = organs_by_name[BP_TORSO]
|
||||
if(T && T.robotic >= ORGAN_ROBOT)
|
||||
src.verbs += /mob/living/carbon/human/proc/self_diagnostics
|
||||
var/datum/robolimb/R = all_robolimbs[T.model]
|
||||
synthetic = R
|
||||
return synthetic
|
||||
|
||||
return 0
|
||||
|
||||
// Would an onlooker know this person is synthetic?
|
||||
// Based on sort of logical reasoning, 'Look at head, look at torso'
|
||||
/mob/living/carbon/human/proc/looksSynthetic()
|
||||
var/obj/item/organ/external/T = organs_by_name[BP_TORSO]
|
||||
var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
|
||||
|
||||
//Look at their head
|
||||
if(!head || !(head && (head.flags_inv & HIDEFACE)))
|
||||
if(H && H.robotic == ORGAN_ROBOT) //Exactly robotic, not higher as lifelike is higher
|
||||
return 1
|
||||
|
||||
//Look at their torso
|
||||
if(!wear_suit || (wear_suit && !(wear_suit.flags_inv & HIDEJUMPSUIT)))
|
||||
if(!w_uniform || (w_uniform && !(w_uniform.body_parts_covered & UPPER_TORSO)))
|
||||
if(T && T.robotic == ORGAN_ROBOT)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
#undef HUMAN_EATING_NO_ISSUE
|
||||
#undef HUMAN_EATING_NO_MOUTH
|
||||
|
||||
@@ -25,8 +25,15 @@
|
||||
var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80
|
||||
if (hungry >= 70) tally += hungry/50
|
||||
|
||||
if(wear_suit)
|
||||
tally += wear_suit.slowdown
|
||||
// Loop through some slots, and add up their slowdowns. Shoes are handled below, unfortunately.
|
||||
// Includes slots which can provide armor, the back slot, and suit storage.
|
||||
for(var/obj/item/I in list(wear_suit, w_uniform, back, gloves, head, s_store) )
|
||||
tally += I.slowdown
|
||||
|
||||
// Hands are also included, to make the 'take off your armor instantly and carry it with you to go faster' trick no longer viable.
|
||||
// This is done seperately to disallow negative numbers.
|
||||
for(var/obj/item/I in list(r_hand, l_hand) )
|
||||
tally += max(I.slowdown, 0)
|
||||
|
||||
if(istype(buckled, /obj/structure/bed/chair/wheelchair))
|
||||
for(var/organ_name in list(BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM))
|
||||
|
||||
@@ -9,15 +9,24 @@
|
||||
/mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs
|
||||
/mob/living/carbon/human/var/list/internal_organs_by_name = list() // so internal organs have less ickiness too
|
||||
|
||||
/mob/living/carbon/human/proc/get_bodypart_name(var/zone)
|
||||
var/obj/item/organ/external/E = get_organ(zone)
|
||||
if(E) . = E.name
|
||||
|
||||
/mob/living/carbon/human/proc/recheck_bad_external_organs()
|
||||
var/damage_this_tick = getToxLoss()
|
||||
for(var/obj/item/organ/external/O in organs)
|
||||
damage_this_tick += O.burn_dam + O.brute_dam
|
||||
|
||||
if(damage_this_tick > last_dam)
|
||||
. = TRUE
|
||||
last_dam = damage_this_tick
|
||||
|
||||
// Takes care of organ related updates, such as broken and missing limbs
|
||||
/mob/living/carbon/human/proc/handle_organs()
|
||||
|
||||
number_wounds = 0
|
||||
var/force_process = 0
|
||||
var/damage_this_tick = getBruteLoss() + getFireLoss() + getToxLoss()
|
||||
if(damage_this_tick > last_dam)
|
||||
force_process = 1
|
||||
last_dam = damage_this_tick
|
||||
var/force_process = recheck_bad_external_organs()
|
||||
|
||||
if(force_process)
|
||||
bad_external_organs.Cut()
|
||||
for(var/obj/item/organ/external/Ex in organs)
|
||||
@@ -59,7 +68,7 @@
|
||||
/mob/living/carbon/human/proc/handle_stance()
|
||||
// Don't need to process any of this if they aren't standing anyways
|
||||
// unless their stance is damaged, and we want to check if they should stay down
|
||||
if (!stance_damage && (lying || resting) && (life_tick % 4) == 0)
|
||||
if (!stance_damage && (lying || resting) && (life_tick % 4) != 0)
|
||||
return
|
||||
|
||||
stance_damage = 0
|
||||
@@ -71,7 +80,7 @@
|
||||
var/limb_pain
|
||||
for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot"))
|
||||
var/obj/item/organ/external/E = organs_by_name[limb_tag]
|
||||
if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up.
|
||||
if(!E || !E.is_usable())
|
||||
stance_damage += 2 // let it fail even if just foot&leg
|
||||
else if (E.is_malfunctioning())
|
||||
//malfunctioning only happens intermittently so treat it as a missing limb when it procs
|
||||
@@ -84,7 +93,7 @@
|
||||
spark_system.start()
|
||||
spawn(10)
|
||||
qdel(spark_system)
|
||||
else if (E.is_broken() || !E.is_usable())
|
||||
else if (E.is_broken())
|
||||
stance_damage += 1
|
||||
else if (E.is_dislocated())
|
||||
stance_damage += 0.5
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
var/mob/M = targets[target]
|
||||
|
||||
if(istype(M, /mob/dead/observer) || M.stat == DEAD)
|
||||
if(istype(M, /mob/observer/dead) || M.stat == DEAD)
|
||||
src << "Not even a [src.species.name] can speak to the dead."
|
||||
return
|
||||
|
||||
@@ -145,4 +145,27 @@
|
||||
|
||||
qdel(src)
|
||||
|
||||
/mob/living/carbon/human/proc/self_diagnostics()
|
||||
set name = "Self-Diagnostics"
|
||||
set desc = "Run an internal self-diagnostic to check for damage."
|
||||
set category = "IC"
|
||||
|
||||
if(stat == DEAD) return
|
||||
|
||||
src << "<span class='notice'>Performing self-diagnostic, please wait...</span>"
|
||||
sleep(50)
|
||||
var/output = "<span class='notice'>Self-Diagnostic Results:\n</span>"
|
||||
|
||||
for(var/obj/item/organ/external/EO in organs)
|
||||
if(EO.brute_dam || EO.burn_dam)
|
||||
output += "[EO.name] - <span class='warning'>[EO.burn_dam + EO.brute_dam > ROBOLIMB_REPAIR_CAP ? "Heavy Damage" : "Light Damage"]</span>\n"
|
||||
else
|
||||
output += "[EO.name] - <span style='color:green;'>OK</span>\n"
|
||||
|
||||
for(var/obj/item/organ/IO in internal_organs)
|
||||
if(IO.damage)
|
||||
output += "[IO.name] - <span class='warning'>[IO.damage > 10 ? "Heavy Damage" : "Light Damage"]</span>\n"
|
||||
else
|
||||
output += "[IO.name] - <span style='color:green;'>OK</span>\n"
|
||||
|
||||
src << output
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
real_name = "Test Dummy"
|
||||
status_flags = GODMODE|CANPUSH
|
||||
|
||||
/mob/living/carbon/human/dummy/mannequin/New()
|
||||
..()
|
||||
mob_list -= src
|
||||
living_mob_list -= src
|
||||
dead_mob_list -= src
|
||||
delete_inventory()
|
||||
|
||||
/mob/living/carbon/human/skrell/New(var/new_loc)
|
||||
h_style = "Skrell Male Tentacles"
|
||||
..(new_loc, "Skrell")
|
||||
@@ -17,6 +24,10 @@
|
||||
/mob/living/carbon/human/diona/New(var/new_loc)
|
||||
..(new_loc, "Diona")
|
||||
|
||||
/mob/living/carbon/human/teshari/New(var/new_loc)
|
||||
h_style = "Teshari Default"
|
||||
..(new_loc, "Teshari")
|
||||
|
||||
/mob/living/carbon/human/machine/New(var/new_loc)
|
||||
h_style = "blue IPC screen"
|
||||
..(new_loc, "Machine")
|
||||
|
||||
@@ -267,8 +267,6 @@ This saves us from having to call add_fingerprint() any time something is put in
|
||||
update_inv_shoes(redraw_mob)
|
||||
if(slot_wear_suit)
|
||||
src.wear_suit = W
|
||||
if(wear_suit.flags_inv & HIDESHOES)
|
||||
update_inv_shoes(0)
|
||||
W.equipped(src, slot)
|
||||
update_inv_wear_suit(redraw_mob)
|
||||
if(slot_w_uniform)
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
var/temperature_alert = 0
|
||||
var/in_stasis = 0
|
||||
var/heartbeat = 0
|
||||
var/global/list/overlays_cache = null
|
||||
|
||||
/mob/living/carbon/human/Life()
|
||||
set invisibility = 0
|
||||
@@ -149,6 +148,11 @@
|
||||
return ONE_ATMOSPHERE + pressure_difference
|
||||
|
||||
/mob/living/carbon/human/handle_disabilities()
|
||||
..()
|
||||
|
||||
if(stat != CONSCIOUS) //Let's not worry about tourettes if you're not conscious.
|
||||
return
|
||||
|
||||
if (disabilities & EPILEPSY)
|
||||
if ((prob(1) && paralysis < 1))
|
||||
src << "\red You have a seizure!"
|
||||
@@ -165,7 +169,6 @@
|
||||
emote("cough")
|
||||
return
|
||||
if (disabilities & TOURETTES)
|
||||
speech_problem_flag = 1
|
||||
if ((prob(10) && paralysis <= 1))
|
||||
Stun(10)
|
||||
spawn( 0 )
|
||||
@@ -174,40 +177,32 @@
|
||||
emote("twitch")
|
||||
if(2 to 3)
|
||||
say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
|
||||
var/old_x = pixel_x
|
||||
var/old_y = pixel_y
|
||||
pixel_x += rand(-2,2)
|
||||
pixel_y += rand(-1,1)
|
||||
sleep(2)
|
||||
pixel_x = old_x
|
||||
pixel_y = old_y
|
||||
make_jittery(100)
|
||||
return
|
||||
if (disabilities & NERVOUS)
|
||||
speech_problem_flag = 1
|
||||
if (prob(10))
|
||||
stuttering = max(10, stuttering)
|
||||
|
||||
if(stat != 2)
|
||||
var/rn = rand(0, 200)
|
||||
if(getBrainLoss() >= 5)
|
||||
if(0 <= rn && rn <= 3)
|
||||
custom_pain("Your head feels numb and painful.")
|
||||
if(getBrainLoss() >= 15)
|
||||
if(4 <= rn && rn <= 6) if(eye_blurry <= 0)
|
||||
src << "<span class='warning'>It becomes hard to see for some reason.</span>"
|
||||
eye_blurry = 10
|
||||
if(getBrainLoss() >= 35)
|
||||
if(7 <= rn && rn <= 9) if(get_active_hand())
|
||||
src << "<span class='danger'>Your hand won't respond properly, you drop what you're holding!</span>"
|
||||
drop_item()
|
||||
if(getBrainLoss() >= 45)
|
||||
if(10 <= rn && rn <= 12)
|
||||
if(prob(50))
|
||||
src << "<span class='danger'>You suddenly black out!</span>"
|
||||
Paralyse(10)
|
||||
else if(!lying)
|
||||
src << "<span class='danger'>Your legs won't respond properly, you fall down!</span>"
|
||||
Weaken(10)
|
||||
var/rn = rand(0, 200)
|
||||
if(getBrainLoss() >= 5)
|
||||
if(0 <= rn && rn <= 3)
|
||||
custom_pain("Your head feels numb and painful.")
|
||||
if(getBrainLoss() >= 15)
|
||||
if(4 <= rn && rn <= 6) if(eye_blurry <= 0)
|
||||
src << "<span class='warning'>It becomes hard to see for some reason.</span>"
|
||||
eye_blurry = 10
|
||||
if(getBrainLoss() >= 35)
|
||||
if(7 <= rn && rn <= 9) if(get_active_hand())
|
||||
src << "<span class='danger'>Your hand won't respond properly, you drop what you're holding!</span>"
|
||||
drop_item()
|
||||
if(getBrainLoss() >= 45)
|
||||
if(10 <= rn && rn <= 12)
|
||||
if(prob(50))
|
||||
src << "<span class='danger'>You suddenly black out!</span>"
|
||||
Paralyse(10)
|
||||
else if(!lying)
|
||||
src << "<span class='danger'>Your legs won't respond properly, you fall down!</span>"
|
||||
Weaken(10)
|
||||
|
||||
|
||||
|
||||
@@ -225,12 +220,17 @@
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
speech_problem_flag = 1
|
||||
gene.OnMobLife(src)
|
||||
|
||||
radiation = Clamp(radiation,0,100)
|
||||
|
||||
if (radiation)
|
||||
if(!radiation)
|
||||
if(species.appearance_flags & RADIATION_GLOWS)
|
||||
set_light(0)
|
||||
else
|
||||
if(species.appearance_flags & RADIATION_GLOWS)
|
||||
set_light(max(1,min(10,radiation/10)), max(1,min(20,radiation/20)), species.get_flesh_colour(src))
|
||||
// END DOGSHIT SNOWFLAKE
|
||||
|
||||
var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in internal_organs
|
||||
if(rad_organ && !rad_organ.is_broken())
|
||||
@@ -601,31 +601,32 @@
|
||||
//Body temperature is too hot.
|
||||
fire_alert = max(fire_alert, 1)
|
||||
if(status_flags & GODMODE) return 1 //godmode
|
||||
|
||||
if(bodytemperature < species.heat_level_2)
|
||||
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 2)
|
||||
else if(bodytemperature < species.heat_level_3)
|
||||
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 2)
|
||||
else
|
||||
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 2)
|
||||
var/burn_dam = 0
|
||||
switch(bodytemperature)
|
||||
if(species.heat_level_1 to species.heat_level_2)
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_1
|
||||
if(species.heat_level_2 to species.heat_level_3)
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_2
|
||||
if(species.heat_level_3 to INFINITY)
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_3
|
||||
take_overall_damage(burn=burn_dam, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 2)
|
||||
|
||||
else if(bodytemperature <= species.cold_level_1)
|
||||
fire_alert = max(fire_alert, 1)
|
||||
if(status_flags & GODMODE) return 1 //godmode
|
||||
|
||||
if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
|
||||
if(bodytemperature > species.cold_level_2)
|
||||
take_overall_damage(burn=COLD_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 1)
|
||||
else if(bodytemperature > species.cold_level_3)
|
||||
take_overall_damage(burn=COLD_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 1)
|
||||
else
|
||||
take_overall_damage(burn=COLD_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature")
|
||||
fire_alert = max(fire_alert, 1)
|
||||
var/burn_dam = 0
|
||||
switch(bodytemperature)
|
||||
if(species.cold_level_1 to species.cold_level_2)
|
||||
burn_dam = COLD_DAMAGE_LEVEL_1
|
||||
if(species.cold_level_2 to species.cold_level_3)
|
||||
burn_dam = COLD_DAMAGE_LEVEL_2
|
||||
if(species.cold_level_3 to -INFINITY)
|
||||
burn_dam = COLD_DAMAGE_LEVEL_3
|
||||
take_overall_damage(burn=burn_dam, used_weapon = "Low Body Temperature")
|
||||
fire_alert = max(fire_alert, 1)
|
||||
|
||||
// Account for massive pressure differences. Done by Polymorph
|
||||
// Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense!
|
||||
@@ -711,85 +712,25 @@
|
||||
|
||||
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, UPPER_TORSO, LOWER_TORSO, 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
|
||||
. = 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/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.0
|
||||
if(thermal_protection_flags)
|
||||
if(thermal_protection_flags & HEAD)
|
||||
thermal_protection += THERMAL_PROTECTION_HEAD
|
||||
if(thermal_protection_flags & UPPER_TORSO)
|
||||
thermal_protection += THERMAL_PROTECTION_UPPER_TORSO
|
||||
if(thermal_protection_flags & LOWER_TORSO)
|
||||
thermal_protection += THERMAL_PROTECTION_LOWER_TORSO
|
||||
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)
|
||||
for(var/obj/item/clothing/C in list(head,wear_suit,w_uniform,shoes,gloves,wear_mask))
|
||||
if(C)
|
||||
if(C.max_heat_protection_temperature && C.max_heat_protection_temperature >= temperature)
|
||||
. |= C.heat_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
|
||||
. = 0
|
||||
//Handle normal clothing
|
||||
for(var/obj/item/clothing/C in list(head,wear_suit,w_uniform,shoes,gloves,wear_mask))
|
||||
if(C)
|
||||
if(C.min_cold_protection_temperature && C.min_cold_protection_temperature <= temperature)
|
||||
. |= C.cold_protection
|
||||
|
||||
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/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
|
||||
var/thermal_protection_flags = get_heat_protection_flags(temperature)
|
||||
return get_thermal_protection(thermal_protection_flags)
|
||||
|
||||
/mob/living/carbon/human/get_cold_protection(temperature)
|
||||
if(COLD_RESISTANCE in mutations)
|
||||
@@ -797,33 +738,34 @@
|
||||
|
||||
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)
|
||||
return get_thermal_protection(thermal_protection_flags)
|
||||
|
||||
var/thermal_protection = 0.0
|
||||
if(thermal_protection_flags)
|
||||
if(thermal_protection_flags & HEAD)
|
||||
thermal_protection += THERMAL_PROTECTION_HEAD
|
||||
if(thermal_protection_flags & UPPER_TORSO)
|
||||
thermal_protection += THERMAL_PROTECTION_UPPER_TORSO
|
||||
if(thermal_protection_flags & LOWER_TORSO)
|
||||
thermal_protection += THERMAL_PROTECTION_LOWER_TORSO
|
||||
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/proc/get_thermal_protection(var/flags)
|
||||
.=0
|
||||
if(flags)
|
||||
if(flags & HEAD)
|
||||
. += THERMAL_PROTECTION_HEAD
|
||||
if(flags & UPPER_TORSO)
|
||||
. += THERMAL_PROTECTION_UPPER_TORSO
|
||||
if(flags & LOWER_TORSO)
|
||||
. += THERMAL_PROTECTION_LOWER_TORSO
|
||||
if(flags & LEG_LEFT)
|
||||
. += THERMAL_PROTECTION_LEG_LEFT
|
||||
if(flags & LEG_RIGHT)
|
||||
. += THERMAL_PROTECTION_LEG_RIGHT
|
||||
if(flags & FOOT_LEFT)
|
||||
. += THERMAL_PROTECTION_FOOT_LEFT
|
||||
if(flags & FOOT_RIGHT)
|
||||
. += THERMAL_PROTECTION_FOOT_RIGHT
|
||||
if(flags & ARM_LEFT)
|
||||
. += THERMAL_PROTECTION_ARM_LEFT
|
||||
if(flags & ARM_RIGHT)
|
||||
. += THERMAL_PROTECTION_ARM_RIGHT
|
||||
if(flags & HAND_LEFT)
|
||||
. += THERMAL_PROTECTION_HAND_LEFT
|
||||
if(flags & HAND_RIGHT)
|
||||
. += THERMAL_PROTECTION_HAND_RIGHT
|
||||
return min(1,.)
|
||||
|
||||
/mob/living/carbon/human/handle_chemicals_in_body()
|
||||
|
||||
@@ -860,9 +802,9 @@
|
||||
var/turf/T = loc
|
||||
var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T
|
||||
if(L)
|
||||
light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights
|
||||
light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 2 //hardcapped so it's not abused by having a ton of flashlights
|
||||
else
|
||||
light_amount = 5
|
||||
light_amount = 10
|
||||
nutrition += light_amount
|
||||
traumatic_shock -= light_amount
|
||||
|
||||
@@ -905,7 +847,10 @@
|
||||
if(!isSynthetic() && (species.flags & IS_PLANT) && (!light_organ || light_organ.is_broken()))
|
||||
if(nutrition < 200)
|
||||
take_overall_damage(2,0)
|
||||
traumatic_shock++
|
||||
|
||||
//traumatic_shock is updated every tick, incrementing that is pointless - shock_stage is the counter.
|
||||
//Not that it matters much for diona, who have NO_PAIN.
|
||||
shock_stage++
|
||||
|
||||
// TODO: stomach and bloodstream organ.
|
||||
if(!isSynthetic())
|
||||
@@ -915,6 +860,7 @@
|
||||
|
||||
return //TODO: DEFERRED
|
||||
|
||||
//DO NOT CALL handle_statuses() from this proc, it's called from living/Life() as long as this returns a true value.
|
||||
/mob/living/carbon/human/handle_regular_status_updates()
|
||||
if(!handle_some_updates())
|
||||
return 0
|
||||
@@ -968,19 +914,15 @@
|
||||
animate_tail_reset()
|
||||
adjustHalLoss(-3)
|
||||
|
||||
if(paralysis)
|
||||
AdjustParalysis(-1)
|
||||
|
||||
else if(sleeping)
|
||||
speech_problem_flag = 1
|
||||
handle_dreams()
|
||||
if (mind)
|
||||
//Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar.
|
||||
if(client || sleeping > 3)
|
||||
AdjustSleeping(-1)
|
||||
if( prob(2) && health && !hal_crit )
|
||||
spawn(0)
|
||||
emote("snore")
|
||||
if(sleeping)
|
||||
handle_dreams()
|
||||
if (mind)
|
||||
//Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar.
|
||||
if(client || sleeping > 3)
|
||||
AdjustSleeping(-1)
|
||||
if( prob(2) && health && !hal_crit )
|
||||
spawn(0)
|
||||
emote("snore")
|
||||
//CONSCIOUS
|
||||
else
|
||||
stat = CONSCIOUS
|
||||
@@ -1011,19 +953,18 @@
|
||||
if(species.vision_organ)
|
||||
vision = internal_organs_by_name[species.vision_organ]
|
||||
|
||||
if(!vision) // Presumably if a species has no vision organs, they see via some other means.
|
||||
if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
|
||||
eye_blind = 0
|
||||
blinded = 0
|
||||
eye_blurry = 0
|
||||
else if(vision.is_broken()) // Vision organs cut out or broken? Permablind.
|
||||
else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind.
|
||||
eye_blind = 1
|
||||
blinded = 1
|
||||
eye_blurry = 1
|
||||
else
|
||||
//blindness
|
||||
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
|
||||
else //You have the requisite organs
|
||||
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
|
||||
blinded = 1
|
||||
else if(eye_blind) // Blindness, heals slowly over time
|
||||
else if(eye_blind) // Blindness, heals slowly over time
|
||||
eye_blind = max(eye_blind-1,0)
|
||||
blinded = 1
|
||||
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
|
||||
@@ -1057,9 +998,6 @@
|
||||
jitteriness = max(0, jitteriness - 3)
|
||||
adjustHalLoss(-1)
|
||||
|
||||
//Other
|
||||
handle_statuses()
|
||||
|
||||
if (drowsyness)
|
||||
drowsyness--
|
||||
eye_blurry = max(2, eye_blurry)
|
||||
@@ -1076,33 +1014,6 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/handle_regular_hud_updates()
|
||||
if(!overlays_cache)
|
||||
overlays_cache = list()
|
||||
overlays_cache.len = 23
|
||||
overlays_cache[1] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage1")
|
||||
overlays_cache[2] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage2")
|
||||
overlays_cache[3] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage3")
|
||||
overlays_cache[4] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage4")
|
||||
overlays_cache[5] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage5")
|
||||
overlays_cache[6] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage6")
|
||||
overlays_cache[7] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage7")
|
||||
overlays_cache[8] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage8")
|
||||
overlays_cache[9] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage9")
|
||||
overlays_cache[10] = image('icons/mob/screen1_full.dmi', "icon_state" = "passage10")
|
||||
overlays_cache[11] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay1")
|
||||
overlays_cache[12] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay2")
|
||||
overlays_cache[13] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay3")
|
||||
overlays_cache[14] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay4")
|
||||
overlays_cache[15] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay5")
|
||||
overlays_cache[16] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay6")
|
||||
overlays_cache[17] = image('icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay7")
|
||||
overlays_cache[18] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay1")
|
||||
overlays_cache[19] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay2")
|
||||
overlays_cache[20] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay3")
|
||||
overlays_cache[21] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay4")
|
||||
overlays_cache[22] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay5")
|
||||
overlays_cache[23] = image('icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay6")
|
||||
|
||||
if(hud_updateflag) // update our mob's hud overlays, AKA what others see flaoting above our head
|
||||
handle_hud_list()
|
||||
|
||||
@@ -1115,77 +1026,59 @@
|
||||
if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe
|
||||
client.images.Remove(hud)
|
||||
|
||||
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
|
||||
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science, global_hud.whitense)
|
||||
|
||||
if(damageoverlay.overlays)
|
||||
damageoverlay.overlays = list()
|
||||
if(istype(client.eye,/obj/machinery/camera))
|
||||
var/obj/machinery/camera/cam = client.eye
|
||||
client.screen |= cam.client_huds
|
||||
|
||||
if(stat == UNCONSCIOUS)
|
||||
if(stat == UNCONSCIOUS && health <= 0)
|
||||
//Critical damage passage overlay
|
||||
if(health <= 0)
|
||||
var/image/I
|
||||
switch(health)
|
||||
if(-20 to -10)
|
||||
I = overlays_cache[1]
|
||||
if(-30 to -20)
|
||||
I = overlays_cache[2]
|
||||
if(-40 to -30)
|
||||
I = overlays_cache[3]
|
||||
if(-50 to -40)
|
||||
I = overlays_cache[4]
|
||||
if(-60 to -50)
|
||||
I = overlays_cache[5]
|
||||
if(-70 to -60)
|
||||
I = overlays_cache[6]
|
||||
if(-80 to -70)
|
||||
I = overlays_cache[7]
|
||||
if(-90 to -80)
|
||||
I = overlays_cache[8]
|
||||
if(-95 to -90)
|
||||
I = overlays_cache[9]
|
||||
if(-INFINITY to -95)
|
||||
I = overlays_cache[10]
|
||||
damageoverlay.overlays += I
|
||||
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")
|
||||
//Oxygen damage overlay
|
||||
if(oxyloss)
|
||||
var/image/I
|
||||
var/severity = 0
|
||||
switch(oxyloss)
|
||||
if(10 to 20)
|
||||
I = overlays_cache[11]
|
||||
if(20 to 25)
|
||||
I = overlays_cache[12]
|
||||
if(25 to 30)
|
||||
I = overlays_cache[13]
|
||||
if(30 to 35)
|
||||
I = overlays_cache[14]
|
||||
if(35 to 40)
|
||||
I = overlays_cache[15]
|
||||
if(40 to 45)
|
||||
I = overlays_cache[16]
|
||||
if(45 to INFINITY)
|
||||
I = overlays_cache[17]
|
||||
damageoverlay.overlays += I
|
||||
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 = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp
|
||||
damageoverlaytemp = 0 // We do this so we can detect if someone hits us or not.
|
||||
if(hurtdamage)
|
||||
var/image/I
|
||||
var/severity = 0
|
||||
switch(hurtdamage)
|
||||
if(10 to 25)
|
||||
I = overlays_cache[18]
|
||||
if(25 to 40)
|
||||
I = overlays_cache[19]
|
||||
if(40 to 55)
|
||||
I = overlays_cache[20]
|
||||
if(55 to 70)
|
||||
I = overlays_cache[21]
|
||||
if(70 to 85)
|
||||
I = overlays_cache[22]
|
||||
if(85 to INFINITY)
|
||||
I = overlays_cache[23]
|
||||
damageoverlay.overlays += I
|
||||
if(10 to 25) severity = 1
|
||||
if(25 to 40) severity = 2
|
||||
if(40 to 55) severity = 3
|
||||
if(55 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")
|
||||
|
||||
if( stat == DEAD )
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
|
||||
@@ -1329,20 +1222,20 @@
|
||||
bodytemp.icon_state = "temp-1"
|
||||
else
|
||||
bodytemp.icon_state = "temp0"
|
||||
if(blind)
|
||||
if(blinded) blind.layer = 18
|
||||
else blind.layer = 0
|
||||
|
||||
if(blinded) overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
||||
else clear_fullscreens()
|
||||
|
||||
if(disabilities & NEARSIGHTED) //this looks meh but saves a lot of memory by not requiring to add var/prescription
|
||||
if(glasses) //to every /obj/item
|
||||
var/obj/item/clothing/glasses/G = glasses
|
||||
if(!G.prescription)
|
||||
client.screen += global_hud.vimpaired
|
||||
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /obj/screen/fullscreen/impaired, 1)
|
||||
else
|
||||
client.screen += global_hud.vimpaired
|
||||
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /obj/screen/fullscreen/impaired, 1)
|
||||
|
||||
if(eye_blurry) client.screen += global_hud.blurry
|
||||
if(druggy) client.screen += global_hud.druggy
|
||||
set_fullscreen(eye_blurry, "blurry", /obj/screen/fullscreen/blurry)
|
||||
set_fullscreen(druggy, "high", /obj/screen/fullscreen/high)
|
||||
|
||||
if(config.welder_vision)
|
||||
var/found_welder
|
||||
@@ -1576,7 +1469,7 @@
|
||||
|
||||
var/obj/item/organ/internal/heart/H = internal_organs_by_name[O_HEART]
|
||||
|
||||
if(!H || (H.status & ORGAN_ROBOT))
|
||||
if(!H || (H.robotic >= ORGAN_ROBOT))
|
||||
return
|
||||
|
||||
if(pulse >= PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space))
|
||||
@@ -1601,7 +1494,7 @@
|
||||
/mob/living/carbon/human/proc/handle_hud_list()
|
||||
if (BITTEST(hud_updateflag, HEALTH_HUD))
|
||||
var/image/holder = hud_list[HEALTH_HUD]
|
||||
if(stat == 2)
|
||||
if(stat == DEAD)
|
||||
holder.icon_state = "hudhealth-100" // X_X
|
||||
else
|
||||
var/percentage_health = RoundHealth((health-config.health_threshold_crit)/(maxHealth-config.health_threshold_crit)*100)
|
||||
@@ -1625,12 +1518,9 @@
|
||||
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
var/image/holder2 = hud_list[STATUS_HUD_OOC]
|
||||
if(stat == 2)
|
||||
if(stat == DEAD)
|
||||
holder.icon_state = "huddead"
|
||||
holder2.icon_state = "huddead"
|
||||
else if(status_flags & XENO_HOST)
|
||||
holder.icon_state = "hudxeno"
|
||||
holder2.icon_state = "hudxeno"
|
||||
else if(foundVirus)
|
||||
holder.icon_state = "hudill"
|
||||
else if(has_brain_worms())
|
||||
@@ -1726,28 +1616,11 @@
|
||||
hud_list[SPECIALROLE_HUD] = holder
|
||||
hud_updateflag = 0
|
||||
|
||||
/mob/living/carbon/human/handle_silent()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return silent
|
||||
|
||||
/mob/living/carbon/human/handle_slurring()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return slurring
|
||||
|
||||
/mob/living/carbon/human/handle_stunned()
|
||||
if(!can_feel_pain())
|
||||
stunned = 0
|
||||
return 0
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stunned
|
||||
|
||||
/mob/living/carbon/human/handle_stuttering()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stuttering
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/handle_fire()
|
||||
if(..())
|
||||
@@ -1764,4 +1637,4 @@
|
||||
..()
|
||||
|
||||
#undef HUMAN_MAX_OXYLOSS
|
||||
#undef HUMAN_CRIT_MAX_OXYLOSS
|
||||
#undef HUMAN_CRIT_MAX_OXYLOSS
|
||||
@@ -1,10 +1,10 @@
|
||||
/mob/living/carbon/human/say(var/message)
|
||||
/mob/living/carbon/human/say(var/message,var/whispering=0)
|
||||
var/alt_name = ""
|
||||
if(name != GetVoice())
|
||||
alt_name = "(as [get_id_name("Unknown")])"
|
||||
|
||||
message = sanitize(message)
|
||||
..(message, alt_name = alt_name)
|
||||
..(message, alt_name = alt_name, whispering = whispering)
|
||||
|
||||
/mob/living/carbon/human/proc/forcesay(list/append)
|
||||
if(stat == CONSCIOUS)
|
||||
@@ -125,29 +125,20 @@
|
||||
|
||||
return verb
|
||||
|
||||
/mob/living/carbon/human/handle_speech_problems(var/message, var/verb)
|
||||
/mob/living/carbon/human/handle_speech_problems(var/list/message_data)
|
||||
if(silent || (sdisabilities & MUTE))
|
||||
message = ""
|
||||
speech_problem_flag = 1
|
||||
message_data[1] = ""
|
||||
. = 1
|
||||
|
||||
else if(istype(wear_mask, /obj/item/clothing/mask))
|
||||
var/obj/item/clothing/mask/M = wear_mask
|
||||
if(M.voicechange)
|
||||
message = pick(M.say_messages)
|
||||
verb = pick(M.say_verbs)
|
||||
speech_problem_flag = 1
|
||||
message_data[1] = pick(M.say_messages)
|
||||
message_data[2] = pick(M.say_verbs)
|
||||
. = 1
|
||||
|
||||
if(message != "")
|
||||
var/list/parent = ..()
|
||||
message = parent[1]
|
||||
verb = parent[2]
|
||||
if(parent[3])
|
||||
speech_problem_flag = 1
|
||||
|
||||
var/list/returns[3]
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = speech_problem_flag
|
||||
return returns
|
||||
else
|
||||
. = ..(message_data)
|
||||
|
||||
/mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
|
||||
switch(message_mode)
|
||||
@@ -190,9 +181,6 @@
|
||||
if(has_radio)
|
||||
R.talk_into(src,message,null,verb,speaking)
|
||||
used_radios += R
|
||||
if("whisper")
|
||||
whisper_say(message, speaking, alt_name)
|
||||
return 1
|
||||
else
|
||||
if(message_mode)
|
||||
if(l_ear && istype(l_ear,/obj/item/device/radio))
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
death_message = "dissolves into ash..."
|
||||
|
||||
flags = NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT
|
||||
spawn_flags = IS_RESTRICTED
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
|
||||
genders = list(NEUTER)
|
||||
|
||||
/datum/species/shadow/handle_death(var/mob/living/carbon/human/H)
|
||||
spawn(1)
|
||||
|
||||
@@ -21,10 +21,12 @@
|
||||
var/prone_icon // If set, draws this from icobase when mob is prone.
|
||||
var/blood_color = "#A10808" // Red.
|
||||
var/flesh_color = "#FFC896" // Pink.
|
||||
var/base_color // Used by changelings. Should also be used for icon previes..
|
||||
var/base_color // Used by changelings. Should also be used for icon previews.
|
||||
|
||||
var/tail // Name of tail state in species effects icon file.
|
||||
var/tail_animation // If set, the icon to obtain tail animation states from.
|
||||
var/tail_hair
|
||||
|
||||
var/race_key = 0 // Used for mob icon cache string.
|
||||
var/icon/icon_template // Used for mob icon generation for non-32x32 species.
|
||||
var/mob_size = MOB_MEDIUM
|
||||
@@ -48,7 +50,7 @@
|
||||
|
||||
// Combat vars.
|
||||
var/total_health = 100 // Point at which the mob will enter crit.
|
||||
var/list/unarmed_types = list( // Possible unarmed attacks that the mob will use in combat.
|
||||
var/list/unarmed_types = list( // Possible unarmed attacks that the mob will use in combat,
|
||||
/datum/unarmed_attack,
|
||||
/datum/unarmed_attack/bite
|
||||
)
|
||||
@@ -147,6 +149,8 @@
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
var/list/genders = list(MALE, FEMALE)
|
||||
|
||||
// Bump vars
|
||||
var/bump_flag = HUMAN // What are we considered to be when bumped?
|
||||
var/push_flags = ~HEAVY // What can we push?
|
||||
@@ -173,71 +177,9 @@
|
||||
inherent_verbs = list()
|
||||
inherent_verbs |= /mob/living/carbon/human/proc/regurgitate
|
||||
|
||||
/datum/species/proc/get_station_variant()
|
||||
return name
|
||||
|
||||
/datum/species/proc/get_bodytype()
|
||||
return name
|
||||
|
||||
/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message)
|
||||
|
||||
/datum/species/proc/get_death_message(var/mob/living/carbon/human/H)
|
||||
if(config.show_human_death_message)
|
||||
return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message)
|
||||
else
|
||||
return "no message"
|
||||
|
||||
/datum/species/proc/get_ssd(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd)
|
||||
|
||||
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? SYNTH_BLOOD_COLOUR : blood_color)
|
||||
|
||||
/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? 1 : virus_immune)
|
||||
|
||||
/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? SYNTH_FLESH_COLOUR : flesh_color)
|
||||
|
||||
/datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type)
|
||||
|
||||
if(!prob(5))
|
||||
return
|
||||
|
||||
var/covered = 0 // Basic coverage can help.
|
||||
for(var/obj/item/clothing/clothes in H)
|
||||
if(H.l_hand == clothes|| H.r_hand == clothes)
|
||||
continue
|
||||
if((clothes.body_parts_covered & UPPER_TORSO) && (clothes.body_parts_covered & LOWER_TORSO))
|
||||
covered = 1
|
||||
break
|
||||
|
||||
switch(msg_type)
|
||||
if("cold")
|
||||
if(!covered)
|
||||
H << "<span class='danger'>[pick(cold_discomfort_strings)]</span>"
|
||||
if("heat")
|
||||
if(covered)
|
||||
H << "<span class='danger'>[pick(heat_discomfort_strings)]</span>"
|
||||
|
||||
/datum/species/proc/sanitize_name(var/name)
|
||||
return sanitizeName(name)
|
||||
|
||||
/datum/species/proc/get_random_name(var/gender)
|
||||
if(!name_language)
|
||||
if(gender == FEMALE)
|
||||
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
|
||||
var/datum/language/species_language = all_languages[name_language]
|
||||
if(!species_language)
|
||||
species_language = all_languages[default_language]
|
||||
if(!species_language)
|
||||
return "unknown"
|
||||
return species_language.get_random_name(gender)
|
||||
|
||||
/datum/species/proc/equip_survival_gear(var/mob/living/carbon/human/H,var/extendedtank = 1)
|
||||
if(H.backbag == 1)
|
||||
if (extendedtank) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand)
|
||||
@@ -248,6 +190,7 @@
|
||||
|
||||
/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.
|
||||
|
||||
H.mob_size = mob_size
|
||||
for(var/obj/item/organ/organ in H.contents)
|
||||
if((organ in H.organs) || (organ in H.internal_organs))
|
||||
qdel(organ)
|
||||
@@ -307,7 +250,6 @@
|
||||
H.mob_swap_flags = swap_flags
|
||||
H.mob_push_flags = push_flags
|
||||
H.pass_flags = pass_flags
|
||||
H.mob_size = mob_size
|
||||
|
||||
/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
|
||||
return
|
||||
@@ -349,6 +291,3 @@
|
||||
// Called in life() when the mob has no client.
|
||||
/datum/species/proc/handle_npc(var/mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H)
|
||||
return vision_flags
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
attack_noun = list("body")
|
||||
damage = 2
|
||||
|
||||
/datum/unarmed_attack/slime_glomp/apply_effects()
|
||||
//Todo, maybe have a chance of causing an electrical shock?
|
||||
return
|
||||
/datum/unarmed_attack/slime_glomp/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone)
|
||||
..()
|
||||
user.apply_stored_shock_to(target)
|
||||
|
||||
/datum/unarmed_attack/stomp/weak
|
||||
attack_verb = list("jumped on")
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/datum/species/proc/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H)
|
||||
return list()
|
||||
|
||||
/datum/species/proc/get_additional_examine_text(var/mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/get_tail(var/mob/living/carbon/human/H)
|
||||
return tail
|
||||
|
||||
/datum/species/proc/get_tail_animation(var/mob/living/carbon/human/H)
|
||||
return tail_animation
|
||||
|
||||
/datum/species/proc/get_tail_hair(var/mob/living/carbon/human/H)
|
||||
return tail_hair
|
||||
|
||||
/datum/species/proc/get_blood_mask(var/mob/living/carbon/human/H)
|
||||
return blood_mask
|
||||
|
||||
/datum/species/proc/get_damage_overlays(var/mob/living/carbon/human/H)
|
||||
return damage_overlays
|
||||
|
||||
/datum/species/proc/get_damage_mask(var/mob/living/carbon/human/H)
|
||||
return damage_mask
|
||||
|
||||
/datum/species/proc/get_examine_name(var/mob/living/carbon/human/H)
|
||||
return name
|
||||
|
||||
/datum/species/proc/get_icobase(var/mob/living/carbon/human/H, var/get_deform)
|
||||
return (get_deform ? deform : icobase)
|
||||
|
||||
/datum/species/proc/get_station_variant()
|
||||
return name
|
||||
|
||||
/datum/species/proc/get_race_key(var/mob/living/carbon/human/H)
|
||||
return race_key
|
||||
|
||||
/datum/species/proc/get_bodytype(var/mob/living/carbon/human/H)
|
||||
return name
|
||||
|
||||
/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message)
|
||||
|
||||
/datum/species/proc/get_death_message(var/mob/living/carbon/human/H)
|
||||
if(config.show_human_death_message)
|
||||
return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message)
|
||||
else
|
||||
return "no message"
|
||||
|
||||
/datum/species/proc/get_ssd(var/mob/living/carbon/human/H)
|
||||
if(H)
|
||||
if(H.looksSynthetic())
|
||||
return "flashing a 'system offline' light"
|
||||
else
|
||||
return show_ssd
|
||||
|
||||
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
|
||||
if(H)
|
||||
var/datum/robolimb/company = H.isSynthetic()
|
||||
if(company)
|
||||
return company.blood_color
|
||||
else
|
||||
return blood_color
|
||||
|
||||
/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? 1 : virus_immune)
|
||||
|
||||
/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H)
|
||||
return ((H && H.isSynthetic()) ? SYNTH_FLESH_COLOUR : flesh_color)
|
||||
|
||||
/datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type)
|
||||
|
||||
if(!prob(5))
|
||||
return
|
||||
|
||||
var/covered = 0 // Basic coverage can help.
|
||||
for(var/obj/item/clothing/clothes in H)
|
||||
if(H.item_is_in_hands(clothes))
|
||||
continue
|
||||
if((clothes.body_parts_covered & UPPER_TORSO) && (clothes.body_parts_covered & LOWER_TORSO))
|
||||
covered = 1
|
||||
break
|
||||
|
||||
switch(msg_type)
|
||||
if("cold")
|
||||
if(!covered)
|
||||
H << "<span class='danger'>[pick(cold_discomfort_strings)]</span>"
|
||||
if("heat")
|
||||
if(covered)
|
||||
H << "<span class='danger'>[pick(heat_discomfort_strings)]</span>"
|
||||
|
||||
/datum/species/proc/get_random_name(var/gender)
|
||||
if(!name_language)
|
||||
if(gender == FEMALE)
|
||||
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
|
||||
var/datum/language/species_language = all_languages[name_language]
|
||||
if(!species_language)
|
||||
species_language = all_languages[default_language]
|
||||
if(!species_language)
|
||||
return "unknown"
|
||||
return species_language.get_random_name(gender)
|
||||
|
||||
/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H)
|
||||
return vision_flags
|
||||
@@ -0,0 +1,6 @@
|
||||
var/list/stored_shock_by_ref = list()
|
||||
|
||||
/mob/living/proc/apply_stored_shock_to(var/mob/living/target)
|
||||
if(stored_shock_by_ref["\ref[src]"])
|
||||
target.electrocute_act(stored_shock_by_ref["\ref[src]"]*0.9, src)
|
||||
stored_shock_by_ref["\ref[src]"] = 0
|
||||
@@ -0,0 +1,187 @@
|
||||
// This is something of an intermediary species used for species that
|
||||
// need to emulate the appearance of another race. Currently it is only
|
||||
// used for slimes but it may be useful for changelings later.
|
||||
var/list/wrapped_species_by_ref = list()
|
||||
|
||||
/datum/species/shapeshifter
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_shape,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_gender
|
||||
)
|
||||
|
||||
var/list/valid_transform_species = list()
|
||||
var/monochromatic
|
||||
var/default_form = "Human"
|
||||
|
||||
/datum/species/shapeshifter/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H)
|
||||
return valid_transform_species
|
||||
|
||||
/datum/species/shapeshifter/get_icobase(var/mob/living/carbon/human/H, var/get_deform)
|
||||
if(!H) return ..(null, get_deform)
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_icobase(H, get_deform)
|
||||
|
||||
/datum/species/shapeshifter/get_race_key(var/mob/living/carbon/human/H)
|
||||
return "[..()]-[wrapped_species_by_ref["\ref[H]"]]"
|
||||
|
||||
/datum/species/shapeshifter/get_bodytype(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_bodytype(H)
|
||||
|
||||
/datum/species/shapeshifter/get_blood_mask(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_blood_mask(H)
|
||||
|
||||
/datum/species/shapeshifter/get_damage_mask(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_damage_mask(H)
|
||||
|
||||
/datum/species/shapeshifter/get_damage_overlays(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_damage_overlays(H)
|
||||
|
||||
/datum/species/shapeshifter/get_tail(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_tail(H)
|
||||
|
||||
/datum/species/shapeshifter/get_tail_animation(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_tail_animation(H)
|
||||
|
||||
/datum/species/shapeshifter/get_tail_hair(var/mob/living/carbon/human/H)
|
||||
if(!H) return ..()
|
||||
var/datum/species/S = all_species[wrapped_species_by_ref["\ref[H]"]]
|
||||
return S.get_tail_hair(H)
|
||||
|
||||
/datum/species/shapeshifter/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
..()
|
||||
wrapped_species_by_ref["\ref[H]"] = default_form
|
||||
if(monochromatic)
|
||||
H.r_hair = H.r_skin
|
||||
H.g_hair = H.g_skin
|
||||
H.b_hair = H.b_skin
|
||||
H.r_facial = H.r_skin
|
||||
H.g_facial = H.g_skin
|
||||
H.b_facial = H.b_skin
|
||||
|
||||
for(var/obj/item/organ/external/E in H.organs)
|
||||
E.sync_colour_to_human(H)
|
||||
|
||||
// Verbs follow.
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair()
|
||||
|
||||
set name = "Select Hair"
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
|
||||
last_special = world.time + 10
|
||||
|
||||
var/list/valid_hairstyles = list()
|
||||
var/list/valid_facialhairstyles = list()
|
||||
for(var/hairstyle in hair_styles_list)
|
||||
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
|
||||
if(gender == MALE && S.gender == FEMALE)
|
||||
continue
|
||||
if(gender == FEMALE && S.gender == MALE)
|
||||
continue
|
||||
if(!(species.get_bodytype(src) in S.species_allowed))
|
||||
continue
|
||||
valid_hairstyles += hairstyle
|
||||
for(var/facialhairstyle in facial_hair_styles_list)
|
||||
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
|
||||
if(gender == MALE && S.gender == FEMALE)
|
||||
continue
|
||||
if(gender == FEMALE && S.gender == MALE)
|
||||
continue
|
||||
if(!(species.get_bodytype(src) in S.species_allowed))
|
||||
continue
|
||||
valid_facialhairstyles += facialhairstyle
|
||||
|
||||
|
||||
visible_message("<span class='notice'>\The [src]'s form contorts subtly.</span>")
|
||||
if(valid_hairstyles.len)
|
||||
var/new_hair = input("Select a hairstyle.", "Shapeshifter Hair") as null|anything in valid_hairstyles
|
||||
change_hair(new_hair ? new_hair : "Bald")
|
||||
if(valid_facialhairstyles.len)
|
||||
var/new_hair = input("Select a facial hair style.", "Shapeshifter Hair") as null|anything in valid_facialhairstyles
|
||||
change_facial_hair(new_hair ? new_hair : "Shaved")
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_gender()
|
||||
|
||||
set name = "Select Gender"
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
|
||||
last_special = world.time + 50
|
||||
|
||||
var/new_gender = input("Please select a gender.", "Shapeshifter Gender") as null|anything in list(FEMALE, MALE, NEUTER, PLURAL)
|
||||
if(!new_gender)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>\The [src]'s form contorts subtly.</span>")
|
||||
change_gender(new_gender)
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_shape()
|
||||
|
||||
set name = "Select Body Shape"
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
|
||||
last_special = world.time + 50
|
||||
|
||||
var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src)
|
||||
if(!new_species || !all_species[new_species] || wrapped_species_by_ref["\ref[src]"] == new_species)
|
||||
return
|
||||
|
||||
wrapped_species_by_ref["\ref[src]"] = new_species
|
||||
visible_message("<span class='notice'>\The [src] shifts and contorts, taking the form of \a [new_species]!</span>")
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_colour()
|
||||
|
||||
set name = "Select Body Colour"
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
|
||||
last_special = world.time + 50
|
||||
|
||||
var/new_skin = input("Please select a new body color.", "Shapeshifter Colour") as color
|
||||
if(!new_skin)
|
||||
return
|
||||
shapeshifter_set_colour(new_skin)
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_set_colour(var/new_skin)
|
||||
|
||||
r_skin = hex2num(copytext(new_skin, 2, 4))
|
||||
g_skin = hex2num(copytext(new_skin, 4, 6))
|
||||
b_skin = hex2num(copytext(new_skin, 6, 8))
|
||||
|
||||
var/datum/species/shapeshifter/S = species
|
||||
if(S.monochromatic)
|
||||
r_hair = r_skin
|
||||
g_hair = g_skin
|
||||
b_hair = b_skin
|
||||
r_facial = r_skin
|
||||
g_facial = g_skin
|
||||
b_facial = b_skin
|
||||
|
||||
for(var/obj/item/organ/external/E in organs)
|
||||
E.sync_colour_to_human(src)
|
||||
|
||||
regenerate_icons()
|
||||
@@ -8,7 +8,7 @@
|
||||
language = "Sol Common" //todo?
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch)
|
||||
flags = NO_PAIN | NO_SCAN | NO_POISON | NO_MINOR_CUT
|
||||
spawn_flags = IS_RESTRICTED
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
siemens_coefficient = 0
|
||||
|
||||
breath_type = null
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
death_message = "becomes completely motionless..."
|
||||
|
||||
genders = list(NEUTER)
|
||||
|
||||
/datum/species/golem/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
if(H.mind)
|
||||
H.mind.assigned_role = "Golem"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
brute_mod = 1.5
|
||||
burn_mod = 1.5
|
||||
|
||||
spawn_flags = IS_RESTRICTED
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
|
||||
bump_flag = MONKEY
|
||||
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
var/datum/species/shapeshifter/promethean/prometheans
|
||||
|
||||
// Species definition follows.
|
||||
/datum/species/shapeshifter/promethean
|
||||
|
||||
name = "Promethean"
|
||||
name_plural = "Prometheans"
|
||||
blurb = "What has Science done?"
|
||||
show_ssd = "totally quiescent"
|
||||
death_message = "rapidly loses cohesion, splattering across the ground..."
|
||||
knockout_message = "collapses inwards, forming a disordered puddle of goo."
|
||||
remains_type = /obj/effect/decal/cleanable/ash
|
||||
|
||||
blood_color = "#05FF9B"
|
||||
flesh_color = "#05FFFB"
|
||||
|
||||
hunger_factor = DEFAULT_HUNGER_FACTOR //todo
|
||||
reagent_tag = IS_SLIME
|
||||
mob_size = MOB_SMALL
|
||||
bump_flag = SLIME
|
||||
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT
|
||||
appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | RADIATION_GLOWS
|
||||
spawn_flags = SPECIES_IS_RESTRICTED
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
gluttonous = 2
|
||||
virus_immune = 1
|
||||
blood_volume = 600
|
||||
min_age = 1
|
||||
max_age = 5
|
||||
brute_mod = 0.5
|
||||
burn_mod = 2
|
||||
oxy_mod = 0
|
||||
total_health = 120
|
||||
|
||||
cold_level_1 = 260
|
||||
cold_level_2 = 200
|
||||
cold_level_3 = 120
|
||||
|
||||
heat_level_1 = 360
|
||||
heat_level_2 = 400
|
||||
heat_level_3 = 1000
|
||||
|
||||
body_temperature = 310.15
|
||||
|
||||
siemens_coefficient = -1
|
||||
rarity_value = 5
|
||||
|
||||
unarmed_types = list(/datum/unarmed_attack/slime_glomp)
|
||||
has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime) // Slime core.
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/slime),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin/unbreakable/slime),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/unbreakable/slime),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm/unbreakable/slime),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/unbreakable/slime),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg/unbreakable/slime),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/unbreakable/slime),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand/unbreakable/slime),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/unbreakable/slime),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot/unbreakable/slime),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/unbreakable/slime)
|
||||
)
|
||||
heat_discomfort_strings = list("You feel too warm.")
|
||||
cold_discomfort_strings = list("You feel too cool.")
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_shape,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_colour,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_hair,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_gender
|
||||
)
|
||||
|
||||
valid_transform_species = list("Human", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey")
|
||||
monochromatic = 1
|
||||
|
||||
var/heal_rate = 5 // Temp. Regen per tick.
|
||||
|
||||
/datum/species/shapeshifter/promethean/New()
|
||||
..()
|
||||
prometheans = src
|
||||
|
||||
/datum/species/shapeshifter/promethean/equip_survival_gear(var/mob/living/carbon/human/H)
|
||||
var/boxtype = pick(typesof(/obj/item/weapon/storage/toolbox/lunchbox))
|
||||
var/obj/item/weapon/storage/toolbox/lunchbox/L = new boxtype(get_turf(H))
|
||||
var/mob/living/simple_animal/mouse/mouse = new (L)
|
||||
var/obj/item/weapon/holder/holder = new (L)
|
||||
mouse.forceMove(holder)
|
||||
holder.sync(mouse)
|
||||
if(H.backbag == 1)
|
||||
H.equip_to_slot_or_del(L, slot_r_hand)
|
||||
else
|
||||
H.equip_to_slot_or_del(L, slot_in_backpack)
|
||||
|
||||
/datum/species/shapeshifter/promethean/hug(var/mob/living/carbon/human/H,var/mob/living/target)
|
||||
|
||||
var/t_him = "them"
|
||||
switch(target.gender)
|
||||
if(MALE)
|
||||
t_him = "him"
|
||||
if(FEMALE)
|
||||
t_him = "her"
|
||||
|
||||
H.visible_message("<span class='notice'>\The [H] glomps [target] to make [t_him] feel better!</span>", \
|
||||
"<span class='notice'>You glomps [target] to make [t_him] feel better!</span>")
|
||||
H.apply_stored_shock_to(target)
|
||||
|
||||
/datum/species/shapeshifter/promethean/handle_death(var/mob/living/carbon/human/H)
|
||||
spawn(1)
|
||||
if(H)
|
||||
H.gib()
|
||||
|
||||
/datum/species/shapeshifter/promethean/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
|
||||
var/turf/T = H.loc
|
||||
if(istype(T))
|
||||
var/obj/effect/decal/cleanable/C = locate() in T
|
||||
if(C)
|
||||
qdel(C)
|
||||
//TODO: gain nutriment
|
||||
|
||||
// Regenerate limbs and heal damage if we have any. Copied from Bay xenos code.
|
||||
|
||||
// Theoretically the only internal organ a slime will have
|
||||
// is the slime core. but we might as well be thorough.
|
||||
for(var/obj/item/organ/I in H.internal_organs)
|
||||
if(I.damage > 0)
|
||||
I.damage = max(I.damage - heal_rate, 0)
|
||||
if (prob(5))
|
||||
H << "<span class='notice'>You feel a soothing sensation within your [I.name]...</span>"
|
||||
return 1
|
||||
|
||||
// Replace completely missing limbs.
|
||||
for(var/limb_type in has_limbs)
|
||||
var/obj/item/organ/external/E = H.organs_by_name[limb_type]
|
||||
if(E && (E.is_stump() || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED))))
|
||||
E.removed()
|
||||
qdel(E)
|
||||
E = null
|
||||
if(!E)
|
||||
var/list/organ_data = has_limbs[limb_type]
|
||||
var/limb_path = organ_data["path"]
|
||||
var/obj/item/organ/O = new limb_path(H)
|
||||
organ_data["descriptor"] = O.name
|
||||
H << "<span class='notice'>You feel a slithering sensation as your [O.name] reforms.</span>"
|
||||
H.update_body()
|
||||
return 1
|
||||
|
||||
// Heal remaining damage.
|
||||
if (H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss())
|
||||
H.adjustBruteLoss(-heal_rate)
|
||||
H.adjustFireLoss(-heal_rate)
|
||||
H.adjustOxyLoss(-heal_rate)
|
||||
H.adjustToxLoss(-heal_rate)
|
||||
return 1
|
||||
|
||||
/datum/species/shapeshifter/promethean/get_blood_colour(var/mob/living/carbon/human/H)
|
||||
return (H ? rgb(H.r_skin, H.g_skin, H.b_skin) : ..())
|
||||
|
||||
/datum/species/shapeshifter/promethean/get_flesh_colour(var/mob/living/carbon/human/H)
|
||||
return (H ? rgb(H.r_skin, H.g_skin, H.b_skin) : ..())
|
||||
|
||||
/datum/species/shapeshifter/promethean/get_additional_examine_text(var/mob/living/carbon/human/H)
|
||||
|
||||
if(!stored_shock_by_ref["\ref[H]"])
|
||||
return
|
||||
|
||||
var/t_she = "She is"
|
||||
if(H.gender == MALE)
|
||||
t_she = "He is"
|
||||
else if(H.gender == PLURAL)
|
||||
t_she = "They are"
|
||||
else if(H.gender == NEUTER)
|
||||
t_she = "It is"
|
||||
|
||||
switch(stored_shock_by_ref["\ref[H]"])
|
||||
if(1 to 10)
|
||||
return "[t_she] flickering gently with a little electrical activity."
|
||||
if(11 to 20)
|
||||
return "[t_she] glowing gently with moderate levels of electrical activity.\n"
|
||||
if(21 to 35)
|
||||
return "<span class='warning'>[t_she] glowing brightly with high levels of electrical activity.</span>"
|
||||
if(35 to INFINITY)
|
||||
return "<span class='danger'>[t_she] radiating massive levels of electrical activity!</span>"
|
||||
@@ -36,7 +36,7 @@
|
||||
blood_volume = 400
|
||||
hunger_factor = 0.2
|
||||
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
bump_flag = MONKEY
|
||||
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/datum/species/slime
|
||||
name = "Slime"
|
||||
name_plural = "slimes"
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
icobase = 'icons/mob/human_races/r_slime.dmi'
|
||||
deform = 'icons/mob/human_races/r_slime.dmi'
|
||||
|
||||
language = null //todo?
|
||||
unarmed_types = list(/datum/unarmed_attack/slime_glomp)
|
||||
flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT
|
||||
spawn_flags = IS_RESTRICTED
|
||||
siemens_coefficient = 3 //conductive
|
||||
darksight = 3
|
||||
|
||||
blood_color = "#05FF9B"
|
||||
flesh_color = "#05FFFB"
|
||||
|
||||
remains_type = /obj/effect/decal/cleanable/ash
|
||||
death_message = "rapidly loses cohesion, splattering across the ground..."
|
||||
|
||||
has_organ = list(
|
||||
"brain" = /obj/item/organ/internal/brain/slime
|
||||
)
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
bump_flag = SLIME
|
||||
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin/unbreakable),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/unbreakable),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm/unbreakable),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right/unbreakable),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg/unbreakable),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right/unbreakable),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand/unbreakable),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right/unbreakable),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot/unbreakable),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/unbreakable)
|
||||
)
|
||||
|
||||
/datum/species/slime/handle_death(var/mob/living/carbon/human/H)
|
||||
spawn(1)
|
||||
if(H)
|
||||
H.gib()
|
||||
@@ -14,10 +14,10 @@
|
||||
min_age = 17
|
||||
max_age = 110
|
||||
|
||||
spawn_flags = CAN_JOIN
|
||||
spawn_flags = SPECIES_CAN_JOIN
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
|
||||
|
||||
/datum/species/human/get_bodytype()
|
||||
/datum/species/human/get_bodytype(var/mob/living/carbon/human/H)
|
||||
return "Human"
|
||||
|
||||
/datum/species/unathi
|
||||
@@ -54,7 +54,7 @@
|
||||
heat_level_2 = 480 //Default 400
|
||||
heat_level_3 = 1100 //Default 1000
|
||||
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
|
||||
flesh_color = "#34AF10"
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
primitive_form = "Farwa"
|
||||
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
|
||||
flesh_color = "#AFA59E"
|
||||
@@ -149,13 +149,13 @@
|
||||
herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \
|
||||
the secrets of their empire to their allies."
|
||||
num_alternate_languages = 2
|
||||
secondary_langs = list("Skrellian", "Teshari")
|
||||
name_language = null
|
||||
secondary_langs = list("Skrellian", "Schechi")
|
||||
name_language = "Skrellian"
|
||||
|
||||
min_age = 19
|
||||
max_age = 80
|
||||
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR
|
||||
|
||||
flesh_color = "#8CD7A3"
|
||||
@@ -246,13 +246,14 @@
|
||||
body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not
|
||||
|
||||
flags = NO_SCAN | IS_PLANT | NO_PAIN | NO_SLIP | NO_MINOR_CUT
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
|
||||
|
||||
blood_color = "#004400"
|
||||
flesh_color = "#907E4A"
|
||||
|
||||
reagent_tag = IS_DIONA
|
||||
|
||||
genders = list(PLURAL)
|
||||
/datum/species/diona/can_understand(var/mob/other)
|
||||
var/mob/living/carbon/alien/diona/D = other
|
||||
if(istype(D))
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
// Handle things that are part of this interface but not removing/replacing a given item.
|
||||
if("pockets")
|
||||
visible_message("<span class='danger'>\The [user] is trying to empty \the [src]'s pockets!</span>")
|
||||
if(do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
empty_pockets(user)
|
||||
return
|
||||
if("splints")
|
||||
visible_message("<span class='danger'>\The [user] is trying to remove \the [src]'s splints!</span>")
|
||||
if(do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
remove_splints(user)
|
||||
return
|
||||
if("sensors")
|
||||
visible_message("<span class='danger'>\The [user] is trying to set \the [src]'s sensors!</span>")
|
||||
if(do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
toggle_sensors(user)
|
||||
return
|
||||
if("internals")
|
||||
visible_message("<span class='danger'>\The [usr] is trying to set \the [src]'s internals!</span>")
|
||||
if(do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
toggle_internals(user)
|
||||
return
|
||||
if("tie")
|
||||
@@ -40,7 +40,7 @@
|
||||
return
|
||||
visible_message("<span class='danger'>\The [usr] is trying to remove \the [src]'s [A.name]!</span>")
|
||||
|
||||
if(!do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(!do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
return
|
||||
|
||||
if(!A || suit.loc != src || !(A in suit.accessories))
|
||||
@@ -74,7 +74,7 @@
|
||||
else
|
||||
visible_message("<span class='danger'>\The [user] is trying to put \a [held] on \the [src]!</span>")
|
||||
|
||||
if(!do_after(user,HUMAN_STRIP_DELAY))
|
||||
if(!do_after(user,HUMAN_STRIP_DELAY,src))
|
||||
return
|
||||
|
||||
if(!stripping && user.get_active_hand() != held)
|
||||
|
||||
@@ -109,29 +109,30 @@ Please contact me on #coderbus IRC. ~Carn x
|
||||
#define MUTATIONS_LAYER 1
|
||||
#define DAMAGE_LAYER 2
|
||||
#define SURGERY_LEVEL 3 //bs12 specific.
|
||||
#define UNIFORM_LAYER 4
|
||||
#define ID_LAYER 5
|
||||
#define SHOES_LAYER 6
|
||||
#define GLOVES_LAYER 7
|
||||
#define BELT_LAYER 8
|
||||
#define SUIT_LAYER 9
|
||||
#define TAIL_LAYER 10 //bs12 specific. this hack is probably gonna come back to haunt me
|
||||
#define GLASSES_LAYER 11
|
||||
#define BELT_LAYER_ALT 12
|
||||
#define SUIT_STORE_LAYER 13
|
||||
#define BACK_LAYER 14
|
||||
#define HAIR_LAYER 15 //TODO: make part of head layer?
|
||||
#define EARS_LAYER 16
|
||||
#define FACEMASK_LAYER 17
|
||||
#define HEAD_LAYER 18
|
||||
#define COLLAR_LAYER 19
|
||||
#define HANDCUFF_LAYER 20
|
||||
#define LEGCUFF_LAYER 21
|
||||
#define L_HAND_LAYER 22
|
||||
#define R_HAND_LAYER 23
|
||||
#define FIRE_LAYER 24 //If you're on fire
|
||||
#define TARGETED_LAYER 25 //BS12: Layer for the target overlay from weapon targeting system
|
||||
#define TOTAL_LAYERS 25
|
||||
#define UNDERWEAR_LAYER 4
|
||||
#define UNIFORM_LAYER 5
|
||||
#define ID_LAYER 6
|
||||
#define SHOES_LAYER 7
|
||||
#define GLOVES_LAYER 8
|
||||
#define BELT_LAYER 9
|
||||
#define SUIT_LAYER 10
|
||||
#define TAIL_LAYER 11 //bs12 specific. this hack is probably gonna come back to haunt me
|
||||
#define GLASSES_LAYER 12
|
||||
#define BELT_LAYER_ALT 13
|
||||
#define SUIT_STORE_LAYER 14
|
||||
#define BACK_LAYER 15
|
||||
#define HAIR_LAYER 16 //TODO: make part of head layer?
|
||||
#define EARS_LAYER 17
|
||||
#define FACEMASK_LAYER 18
|
||||
#define HEAD_LAYER 19
|
||||
#define COLLAR_LAYER 20
|
||||
#define HANDCUFF_LAYER 21
|
||||
#define LEGCUFF_LAYER 22
|
||||
#define L_HAND_LAYER 23
|
||||
#define R_HAND_LAYER 24
|
||||
#define FIRE_LAYER 25 //If you're on fire
|
||||
#define TARGETED_LAYER 26 //BS12: Layer for the target overlay from weapon targeting system
|
||||
#define TOTAL_LAYERS 26
|
||||
//////////////////////////////////
|
||||
|
||||
/mob/living/carbon/human
|
||||
@@ -148,8 +149,12 @@ Please contact me on #coderbus IRC. ~Carn x
|
||||
|
||||
if (icon_update)
|
||||
icon = stand_icon
|
||||
for(var/image/I in overlays_standing)
|
||||
overlays += I
|
||||
for(var/entry in overlays_standing)
|
||||
if(istype(entry, /image))
|
||||
overlays += entry
|
||||
else if(istype(entry, /list))
|
||||
for(var/inner_entry in entry)
|
||||
overlays += inner_entry
|
||||
|
||||
if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone.
|
||||
var/matrix/M = matrix()
|
||||
@@ -174,9 +179,6 @@ var/global/list/damage_icon_parts = list()
|
||||
for(var/obj/item/organ/external/O in organs)
|
||||
if(O.is_stump())
|
||||
continue
|
||||
//if(O.status & ORGAN_DESTROYED) damage_appearance += "d" //what is this?
|
||||
//else
|
||||
// damage_appearance += O.damage_state
|
||||
damage_appearance += O.damage_state
|
||||
|
||||
if(damage_appearance == previous_damage_appearance)
|
||||
@@ -194,15 +196,14 @@ var/global/list/damage_icon_parts = list()
|
||||
if(O.is_stump())
|
||||
continue
|
||||
|
||||
|
||||
O.update_icon()
|
||||
if(O.damage_state == "00") continue
|
||||
var/icon/DI
|
||||
var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]"
|
||||
var/cache_index = "[O.damage_state]/[O.icon_name]/[species.get_blood_colour(src)]/[species.get_bodytype(src)]"
|
||||
if(damage_icon_parts[cache_index] == null)
|
||||
DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human
|
||||
DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels
|
||||
DI.Blend(species.blood_color, ICON_MULTIPLY)
|
||||
DI = new /icon(species.get_damage_overlays(src), O.damage_state) // the damage icon for whole human
|
||||
DI.Blend(new /icon(species.get_damage_mask(src), O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels
|
||||
DI.Blend(species.get_blood_colour(src), ICON_MULTIPLY)
|
||||
damage_icon_parts[cache_index] = DI
|
||||
else
|
||||
DI = damage_icon_parts[cache_index]
|
||||
@@ -224,6 +225,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/hulk = (HULK in src.mutations)
|
||||
var/skeleton = (SKELETON in src.mutations)
|
||||
|
||||
robolimb_count = 0
|
||||
|
||||
//CACHING: Generate an index key from visible bodyparts.
|
||||
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
|
||||
|
||||
@@ -236,7 +239,7 @@ var/global/list/damage_icon_parts = list()
|
||||
if(gender == FEMALE)
|
||||
g = "female"
|
||||
|
||||
var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]"
|
||||
var/icon_key = "[species.get_race_key(src)][g][s_tone][r_skin][g_skin][b_skin]"
|
||||
if(lip_style)
|
||||
icon_key += "[lip_style]"
|
||||
else
|
||||
@@ -251,14 +254,15 @@ var/global/list/damage_icon_parts = list()
|
||||
var/obj/item/organ/external/part = organs_by_name[organ_tag]
|
||||
if(isnull(part) || part.is_stump())
|
||||
icon_key += "0"
|
||||
else if(part.status & ORGAN_ROBOT)
|
||||
else if(part.robotic >= ORGAN_ROBOT)
|
||||
icon_key += "2[part.model ? "-[part.model]": ""]"
|
||||
robolimb_count++
|
||||
else if(part.status & ORGAN_DEAD)
|
||||
icon_key += "3"
|
||||
else
|
||||
icon_key += "1"
|
||||
if(part)
|
||||
icon_key += "[part.species.race_key]"
|
||||
icon_key += "[part.species.get_race_key(part.owner)]"
|
||||
icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]"
|
||||
icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]"
|
||||
if(part.s_col && part.s_col.len >= 3)
|
||||
@@ -319,24 +323,24 @@ var/global/list/damage_icon_parts = list()
|
||||
//END CACHED ICON GENERATION.
|
||||
stand_icon.Blend(base_icon,ICON_OVERLAY)
|
||||
|
||||
//Underwear
|
||||
if(underwear_top && species.appearance_flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', underwear_top), ICON_OVERLAY)
|
||||
if(underwear_bottom && species.appearance_flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', underwear_bottom), ICON_OVERLAY)
|
||||
|
||||
if(undershirt && species.appearance_flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', undershirt), ICON_OVERLAY)
|
||||
|
||||
if(socks && species.appearance_flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', socks), ICON_OVERLAY)
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
//tail
|
||||
update_tail_showing(0)
|
||||
|
||||
//UNDERWEAR OVERLAY
|
||||
/mob/living/carbon/human/proc/update_underwear(var/update_icons=1)
|
||||
overlays_standing[UNDERWEAR_LAYER] = null
|
||||
|
||||
if(species.appearance_flags & HAS_UNDERWEAR)
|
||||
overlays_standing[UNDERWEAR_LAYER] = list()
|
||||
for(var/category in all_underwear)
|
||||
var/datum/category_item/underwear/UWI = all_underwear[category]
|
||||
overlays_standing[UNDERWEAR_LAYER] += UWI.generate_image(all_underwear_metadata[category])
|
||||
|
||||
if(update_icons) update_icons()
|
||||
|
||||
//HAIR OVERLAY
|
||||
/mob/living/carbon/human/proc/update_hair(var/update_icons=1)
|
||||
//Reset our hair
|
||||
@@ -357,7 +361,7 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
if(f_style)
|
||||
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style]
|
||||
if(facial_hair_style && facial_hair_style.species_allowed && (src.species.get_bodytype() in facial_hair_style.species_allowed))
|
||||
if(facial_hair_style && facial_hair_style.species_allowed && (src.species.get_bodytype(src) in facial_hair_style.species_allowed))
|
||||
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
|
||||
if(facial_hair_style.do_colouration)
|
||||
facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD)
|
||||
@@ -366,13 +370,16 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
if(h_style && !(head && (head.flags_inv & BLOCKHEADHAIR)))
|
||||
var/datum/sprite_accessory/hair_style = hair_styles_list[h_style]
|
||||
if(hair_style && (src.species.get_bodytype() in hair_style.species_allowed))
|
||||
if(hair_style && (src.species.get_bodytype(src) in hair_style.species_allowed))
|
||||
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
|
||||
if(hair_style.do_colouration)
|
||||
hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD)
|
||||
|
||||
face_standing.Blend(hair_s, ICON_OVERLAY)
|
||||
|
||||
if(head_organ.nonsolid)
|
||||
face_standing += rgb(,,,120)
|
||||
|
||||
overlays_standing[HAIR_LAYER] = image(face_standing)
|
||||
|
||||
if(update_icons) update_icons()
|
||||
@@ -428,6 +435,7 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
update_mutations(0)
|
||||
update_body(0)
|
||||
update_underwear(0)
|
||||
update_hair(0)
|
||||
update_inv_w_uniform(0)
|
||||
update_inv_wear_id(0)
|
||||
@@ -464,8 +472,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/icon/under_icon
|
||||
if(w_uniform.icon_override)
|
||||
under_icon = w_uniform.icon_override
|
||||
else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.get_bodytype()])
|
||||
under_icon = w_uniform.sprite_sheets[species.get_bodytype()]
|
||||
else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.get_bodytype(src)])
|
||||
under_icon = w_uniform.sprite_sheets[species.get_bodytype(src)]
|
||||
else if(w_uniform.item_icons && w_uniform.item_icons[slot_w_uniform_str])
|
||||
under_icon = w_uniform.item_icons[slot_w_uniform_str]
|
||||
else
|
||||
@@ -486,7 +494,7 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
//apply blood overlay
|
||||
if(w_uniform.blood_DNA)
|
||||
var/image/bloodsies = image(icon = species.blood_mask, icon_state = "uniformblood")
|
||||
var/image/bloodsies = image(icon = species.get_blood_mask(src), icon_state = "uniformblood")
|
||||
bloodsies.color = w_uniform.blood_color
|
||||
standing.overlays += bloodsies
|
||||
|
||||
@@ -500,6 +508,9 @@ var/global/list/damage_icon_parts = list()
|
||||
else
|
||||
overlays_standing[UNIFORM_LAYER] = null
|
||||
|
||||
//hiding/revealing shoes if necessary
|
||||
update_inv_shoes(0)
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
@@ -510,8 +521,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing
|
||||
if(wear_id.icon_override)
|
||||
standing = image("icon" = wear_id.icon_override, "icon_state" = "[icon_state]")
|
||||
else if(wear_id.sprite_sheets && wear_id.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = wear_id.sprite_sheets[species.get_bodytype()], "icon_state" = "[icon_state]")
|
||||
else if(wear_id.sprite_sheets && wear_id.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = wear_id.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[icon_state]")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id")
|
||||
overlays_standing[ID_LAYER] = standing
|
||||
@@ -533,13 +544,13 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing
|
||||
if(gloves.icon_override)
|
||||
standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]")
|
||||
else if(gloves.sprite_sheets && gloves.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = gloves.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_state]")
|
||||
else if(gloves.sprite_sheets && gloves.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = gloves.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_state]")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]")
|
||||
|
||||
if(gloves.blood_DNA)
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "bloodyhands")
|
||||
bloodsies.color = gloves.blood_color
|
||||
standing.overlays += bloodsies
|
||||
gloves.screen_loc = ui_gloves
|
||||
@@ -547,7 +558,7 @@ var/global/list/damage_icon_parts = list()
|
||||
overlays_standing[GLOVES_LAYER] = standing
|
||||
else
|
||||
if(blood_DNA)
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "bloodyhands")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "bloodyhands")
|
||||
bloodsies.color = hand_blood_color
|
||||
overlays_standing[GLOVES_LAYER] = bloodsies
|
||||
else
|
||||
@@ -557,13 +568,15 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
/mob/living/carbon/human/update_inv_glasses(var/update_icons=1)
|
||||
if(glasses)
|
||||
|
||||
var/image/standing
|
||||
if(glasses.icon_override)
|
||||
overlays_standing[GLASSES_LAYER] = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]")
|
||||
else if(glasses.sprite_sheets && glasses.sprite_sheets[species.get_bodytype()])
|
||||
overlays_standing[GLASSES_LAYER]= image("icon" = glasses.sprite_sheets[species.get_bodytype()], "icon_state" = "[glasses.icon_state]")
|
||||
standing = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]")
|
||||
else if(glasses.sprite_sheets && glasses.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = glasses.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[glasses.icon_state]")
|
||||
else
|
||||
overlays_standing[GLASSES_LAYER]= image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]")
|
||||
standing = image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]")
|
||||
standing.color = glasses.color
|
||||
overlays_standing[GLASSES_LAYER] = standing
|
||||
|
||||
else
|
||||
overlays_standing[GLASSES_LAYER] = null
|
||||
@@ -576,54 +589,63 @@ var/global/list/damage_icon_parts = list()
|
||||
return
|
||||
|
||||
if(l_ear || r_ear)
|
||||
if(l_ear)
|
||||
// Blank image upon which to layer left & right overlays.
|
||||
var/image/both = image("icon" = 'icons/effects/effects.dmi', "icon_state" = "nothing")
|
||||
|
||||
if(l_ear)
|
||||
var/image/standing
|
||||
var/t_type = l_ear.icon_state
|
||||
if(l_ear.icon_override)
|
||||
t_type = "[t_type]_l"
|
||||
overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]")
|
||||
else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]")
|
||||
else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.get_bodytype(src)])
|
||||
t_type = "[t_type]_l"
|
||||
overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_type]")
|
||||
standing = image("icon" = l_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]")
|
||||
else
|
||||
overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
|
||||
standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
|
||||
standing.color = l_ear.color
|
||||
both.overlays += standing
|
||||
|
||||
if(r_ear)
|
||||
|
||||
var/image/standing
|
||||
var/t_type = r_ear.icon_state
|
||||
if(r_ear.icon_override)
|
||||
t_type = "[t_type]_r"
|
||||
overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]")
|
||||
else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]")
|
||||
else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.get_bodytype(src)])
|
||||
t_type = "[t_type]_r"
|
||||
overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.get_bodytype()], "icon_state" = "[t_type]")
|
||||
standing = image("icon" = r_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]")
|
||||
else
|
||||
overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
|
||||
standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
|
||||
standing.color = r_ear.color
|
||||
both.overlays += standing
|
||||
|
||||
overlays_standing[EARS_LAYER] = both
|
||||
|
||||
else
|
||||
overlays_standing[EARS_LAYER] = null
|
||||
if(update_icons) update_icons()
|
||||
|
||||
/mob/living/carbon/human/update_inv_shoes(var/update_icons=1)
|
||||
if(shoes && !(wear_suit && wear_suit.flags_inv & HIDESHOES))
|
||||
if(shoes && !((wear_suit && wear_suit.flags_inv & HIDESHOES) || (w_uniform && w_uniform.flags_inv & HIDESHOES)))
|
||||
|
||||
var/image/standing
|
||||
if(shoes.icon_override)
|
||||
standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]")
|
||||
else if(shoes.sprite_sheets && shoes.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = shoes.sprite_sheets[species.get_bodytype()], "icon_state" = "[shoes.icon_state]")
|
||||
else if(shoes.sprite_sheets && shoes.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = shoes.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[shoes.icon_state]")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]")
|
||||
|
||||
if(shoes.blood_DNA)
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood")
|
||||
bloodsies.color = shoes.blood_color
|
||||
standing.overlays += bloodsies
|
||||
standing.color = shoes.color
|
||||
overlays_standing[SHOES_LAYER] = standing
|
||||
else
|
||||
if(feet_blood_DNA)
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood")
|
||||
bloodsies.color = feet_blood_color
|
||||
overlays_standing[SHOES_LAYER] = bloodsies
|
||||
else
|
||||
@@ -649,8 +671,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/t_icon
|
||||
if(head.icon_override)
|
||||
t_icon = head.icon_override
|
||||
else if(head.sprite_sheets && head.sprite_sheets[species.get_bodytype()])
|
||||
t_icon = head.sprite_sheets[species.get_bodytype()]
|
||||
else if(head.sprite_sheets && head.sprite_sheets[species.get_bodytype(src)])
|
||||
t_icon = head.sprite_sheets[species.get_bodytype(src)]
|
||||
|
||||
else if(head.item_icons && (slot_head_str in head.item_icons))
|
||||
t_icon = head.item_icons[slot_head_str]
|
||||
@@ -675,13 +697,13 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing = image(icon = t_icon, icon_state = t_state)
|
||||
|
||||
if(head.blood_DNA)
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "helmetblood")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "helmetblood")
|
||||
bloodsies.color = head.blood_color
|
||||
standing.overlays += bloodsies
|
||||
|
||||
if(istype(head,/obj/item/clothing/head))
|
||||
var/obj/item/clothing/head/hat = head
|
||||
var/cache_key = "[hat.light_overlay]_[species.get_bodytype()]"
|
||||
var/cache_key = "[hat.light_overlay]_[species.get_bodytype(src)]"
|
||||
if(hat.on && light_overlay_cache[cache_key])
|
||||
standing.overlays |= light_overlay_cache[cache_key]
|
||||
|
||||
@@ -701,8 +723,8 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
if(belt.icon_override)
|
||||
standing.icon = belt.icon_override
|
||||
else if(belt.sprite_sheets && belt.sprite_sheets[species.get_bodytype()])
|
||||
standing.icon = belt.sprite_sheets[species.get_bodytype()]
|
||||
else if(belt.sprite_sheets && belt.sprite_sheets[species.get_bodytype(src)])
|
||||
standing.icon = belt.sprite_sheets[species.get_bodytype(src)]
|
||||
else
|
||||
standing.icon = 'icons/mob/belt.dmi'
|
||||
|
||||
@@ -739,7 +761,7 @@ var/global/list/damage_icon_parts = list()
|
||||
var/t_icon = INV_SUIT_DEF_ICON
|
||||
if(wear_suit.icon_override)
|
||||
t_icon = wear_suit.icon_override
|
||||
else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.get_bodytype()])
|
||||
else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.get_bodytype(src)])
|
||||
t_icon = wear_suit.sprite_sheets[species.name]
|
||||
else if(wear_suit.item_icons && wear_suit.item_icons[slot_wear_suit_str])
|
||||
t_icon = wear_suit.item_icons[slot_wear_suit_str]
|
||||
@@ -755,20 +777,28 @@ var/global/list/damage_icon_parts = list()
|
||||
if(wear_suit.blood_DNA)
|
||||
var/obj/item/clothing/suit/S = wear_suit
|
||||
if(istype(S)) //You can put non-suits in your suit slot (diona nymphs etc).
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "[S.blood_overlay_type]blood")
|
||||
bloodsies.color = wear_suit.blood_color
|
||||
standing.overlays += bloodsies
|
||||
|
||||
// Accessories - copied from uniform, BOILERPLATE because fuck this system.
|
||||
var/obj/item/clothing/suit/suit = wear_suit
|
||||
if(istype(suit) && suit.accessories.len)
|
||||
for(var/obj/item/clothing/accessory/A in suit.accessories)
|
||||
standing.overlays |= A.get_mob_overlay()
|
||||
|
||||
overlays_standing[SUIT_LAYER] = standing
|
||||
update_tail_showing(0)
|
||||
|
||||
else
|
||||
overlays_standing[SUIT_LAYER] = null
|
||||
update_tail_showing(0)
|
||||
update_inv_shoes(0)
|
||||
|
||||
update_collar(0)
|
||||
|
||||
//hide/show shoes if necessary
|
||||
update_inv_shoes(0)
|
||||
|
||||
if(update_icons) update_icons()
|
||||
|
||||
/mob/living/carbon/human/update_inv_pockets(var/update_icons=1)
|
||||
@@ -784,14 +814,14 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing
|
||||
if(wear_mask.icon_override)
|
||||
standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state]")
|
||||
else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype()], "icon_state" = "[wear_mask.icon_state]")
|
||||
else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[wear_mask.icon_state]")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]")
|
||||
standing.color = wear_mask.color
|
||||
|
||||
if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA )
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood")
|
||||
var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "maskblood")
|
||||
bloodsies.color = wear_mask.blood_color
|
||||
standing.overlays += bloodsies
|
||||
overlays_standing[FACEMASK_LAYER] = standing
|
||||
@@ -812,8 +842,8 @@ var/global/list/damage_icon_parts = list()
|
||||
//If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc.
|
||||
var/obj/item/weapon/rig/rig = back
|
||||
overlay_icon = rig.mob_icon
|
||||
else if(back.sprite_sheets && back.sprite_sheets[species.get_bodytype()])
|
||||
overlay_icon = back.sprite_sheets[species.get_bodytype()]
|
||||
else if(back.sprite_sheets && back.sprite_sheets[species.get_bodytype(src)])
|
||||
overlay_icon = back.sprite_sheets[species.get_bodytype(src)]
|
||||
else if(back.item_icons && (slot_back_str in back.item_icons))
|
||||
overlay_icon = back.item_icons[slot_back_str]
|
||||
else
|
||||
@@ -857,8 +887,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing
|
||||
if(handcuffed.icon_override)
|
||||
standing = image("icon" = handcuffed.icon_override, "icon_state" = "handcuff1")
|
||||
else if(handcuffed.sprite_sheets && handcuffed.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = handcuffed.sprite_sheets[species.get_bodytype()], "icon_state" = "handcuff1")
|
||||
else if(handcuffed.sprite_sheets && handcuffed.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = handcuffed.sprite_sheets[species.get_bodytype(src)], "icon_state" = "handcuff1")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1")
|
||||
overlays_standing[HANDCUFF_LAYER] = standing
|
||||
@@ -873,8 +903,8 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/standing
|
||||
if(legcuffed.icon_override)
|
||||
standing = image("icon" = legcuffed.icon_override, "icon_state" = "legcuff1")
|
||||
else if(legcuffed.sprite_sheets && legcuffed.sprite_sheets[species.get_bodytype()])
|
||||
standing = image("icon" = legcuffed.sprite_sheets[species.get_bodytype()], "icon_state" = "legcuff1")
|
||||
else if(legcuffed.sprite_sheets && legcuffed.sprite_sheets[species.get_bodytype(src)])
|
||||
standing = image("icon" = legcuffed.sprite_sheets[species.get_bodytype(src)], "icon_state" = "legcuff1")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1")
|
||||
overlays_standing[LEGCUFF_LAYER] = standing
|
||||
@@ -963,24 +993,29 @@ var/global/list/damage_icon_parts = list()
|
||||
/mob/living/carbon/human/proc/update_tail_showing(var/update_icons=1)
|
||||
overlays_standing[TAIL_LAYER] = null
|
||||
|
||||
if(species.tail && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
|
||||
var/species_tail = species.get_tail(src)
|
||||
|
||||
if(species_tail && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
|
||||
var/icon/tail_s = get_tail_icon()
|
||||
overlays_standing[TAIL_LAYER] = image(tail_s, icon_state = "[species.tail]_s")
|
||||
overlays_standing[TAIL_LAYER] = image(tail_s, icon_state = "[species_tail]_s")
|
||||
animate_tail_reset(0)
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/get_tail_icon()
|
||||
var/icon_key = "[species.race_key][r_skin][g_skin][b_skin][r_hair][g_hair][b_hair]"
|
||||
var/icon_key = "[species.get_race_key(src)][r_skin][g_skin][b_skin][r_hair][g_hair][b_hair]"
|
||||
var/icon/tail_icon = tail_icon_cache[icon_key]
|
||||
if(!tail_icon)
|
||||
//generate a new one
|
||||
tail_icon = new/icon(icon = (species.tail_animation? species.tail_animation : 'icons/effects/species.dmi'))
|
||||
var/species_tail_anim = species.get_tail_animation(src)
|
||||
if(!species_tail_anim) species_tail_anim = 'icons/effects/species.dmi'
|
||||
tail_icon = new/icon(species_tail_anim)
|
||||
tail_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
|
||||
// The following will not work with animated tails.
|
||||
if(species.tail_hair)
|
||||
var/icon/hair_icon = icon('icons/effects/species.dmi', "[species.tail]_[species.tail_hair]")
|
||||
var/use_species_tail = species.get_tail_hair(src)
|
||||
if(use_species_tail)
|
||||
var/icon/hair_icon = icon('icons/effects/species.dmi', "[species.get_tail(src)]_[use_species_tail]")
|
||||
hair_icon.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD)
|
||||
tail_icon.Blend(hair_icon, ICON_OVERLAY)
|
||||
tail_icon_cache[icon_key] = tail_icon
|
||||
@@ -991,7 +1026,7 @@ var/global/list/damage_icon_parts = list()
|
||||
/mob/living/carbon/human/proc/set_tail_state(var/t_state)
|
||||
var/image/tail_overlay = overlays_standing[TAIL_LAYER]
|
||||
|
||||
if(tail_overlay && species.tail_animation)
|
||||
if(tail_overlay && species.get_tail_animation(src))
|
||||
tail_overlay.icon_state = t_state
|
||||
return tail_overlay
|
||||
return null
|
||||
@@ -999,7 +1034,7 @@ var/global/list/damage_icon_parts = list()
|
||||
//Not really once, since BYOND can't do that.
|
||||
//Update this if the ability to flick() images or make looping animation start at the first frame is ever added.
|
||||
/mob/living/carbon/human/proc/animate_tail_once(var/update_icons=1)
|
||||
var/t_state = "[species.tail]_once"
|
||||
var/t_state = "[species.get_tail(src)]_once"
|
||||
|
||||
var/image/tail_overlay = overlays_standing[TAIL_LAYER]
|
||||
if(tail_overlay && tail_overlay.icon_state == t_state)
|
||||
@@ -1016,29 +1051,28 @@ var/global/list/damage_icon_parts = list()
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_start(var/update_icons=1)
|
||||
set_tail_state("[species.tail]_slow[rand(0,9)]")
|
||||
set_tail_state("[species.get_tail(src)]_slow[rand(0,9)]")
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_fast(var/update_icons=1)
|
||||
set_tail_state("[species.tail]_loop[rand(0,9)]")
|
||||
set_tail_state("[species.get_tail(src)]_loop[rand(0,9)]")
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_reset(var/update_icons=1)
|
||||
if(stat != DEAD)
|
||||
set_tail_state("[species.tail]_idle[rand(0,9)]")
|
||||
set_tail_state("[species.get_tail(src)]_idle[rand(0,9)]")
|
||||
else
|
||||
set_tail_state("[species.tail]_static")
|
||||
|
||||
set_tail_state("[species.get_tail(src)]_static")
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1)
|
||||
set_tail_state("[species.tail]_static")
|
||||
set_tail_state("[species.get_tail(src)]_static")
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
//Lallander was here
|
||||
/mob/living/carbon/human/whisper(message as text)
|
||||
var/alt_name = ""
|
||||
|
||||
if(say_disabled) //This is here to try to identify lag problems
|
||||
usr << "\red Speech is currently admin-disabled."
|
||||
return
|
||||
|
||||
message = sanitize(message)
|
||||
log_whisper("[src.name]/[src.key] : [message]")
|
||||
|
||||
if (src.client)
|
||||
if (src.client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot whisper (muted)."
|
||||
return
|
||||
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
if (src.stat == 2)
|
||||
return src.say_dead(message)
|
||||
|
||||
if (src.stat)
|
||||
return
|
||||
|
||||
if(name != GetVoice())
|
||||
alt_name = "(as [get_id_name("Unknown")])"
|
||||
|
||||
//parse the language code and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if (speaking)
|
||||
message = copytext(message,2+length(speaking.key))
|
||||
|
||||
whisper_say(message, speaking, alt_name)
|
||||
|
||||
|
||||
//This is used by both the whisper verb and human/say() to handle whispering
|
||||
/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers")
|
||||
|
||||
if (is_muzzled())
|
||||
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
|
||||
return
|
||||
|
||||
var/message_range = 1
|
||||
var/eavesdropping_range = 2
|
||||
var/watching_range = 5
|
||||
var/italics = 1
|
||||
|
||||
var/not_heard //the message displayed to people who could not hear the whispering
|
||||
if (speaking)
|
||||
if (speaking.whisper_verb)
|
||||
verb = speaking.whisper_verb
|
||||
not_heard = "[verb] something"
|
||||
else
|
||||
var/adverb = pick("quietly", "softly")
|
||||
verb = "[speaking.speech_verb] [adverb]"
|
||||
not_heard = "[speaking.speech_verb] something [adverb]"
|
||||
else
|
||||
not_heard = "[verb] something" //TODO get rid of the null language and just prevent speech if language is null
|
||||
|
||||
message = capitalize(trim(message))
|
||||
|
||||
if(speech_problem_flag)
|
||||
var/list/handle_r = handle_speech_problems(message)
|
||||
message = handle_r[1]
|
||||
verb = handle_r[2]
|
||||
if(verb == "yells loudly")
|
||||
verb = "slurs emphatically"
|
||||
else
|
||||
var/adverb = pick("quietly", "softly")
|
||||
verb = "[verb] [adverb]"
|
||||
|
||||
speech_problem_flag = handle_r[3]
|
||||
|
||||
if(!message || message=="")
|
||||
return
|
||||
|
||||
//looks like this only appears in whisper. Should it be elsewhere as well? Maybe handle_speech_problems?
|
||||
var/voice_sub
|
||||
if(istype(back,/obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/rig = back
|
||||
// todo: fix this shit
|
||||
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
|
||||
voice_sub = rig.speech.voice_holder.voice
|
||||
else
|
||||
for(var/obj/item/gear in list(wear_mask,wear_suit,head))
|
||||
if(!gear)
|
||||
continue
|
||||
var/obj/item/voice_changer/changer = locate() in gear
|
||||
if(changer && changer.active && changer.voice)
|
||||
voice_sub = changer.voice
|
||||
|
||||
if(voice_sub == "Unknown")
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
var/list/temp_message = text2list(message, " ")
|
||||
var/list/pick_list = list()
|
||||
for(var/i = 1, i <= temp_message.len, i++)
|
||||
pick_list += i
|
||||
for(var/i=1, i <= abs(temp_message.len/3), i++)
|
||||
var/H = pick(pick_list)
|
||||
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
|
||||
temp_message[H] = ninjaspeak(temp_message[H])
|
||||
pick_list -= H
|
||||
message = list2text(temp_message, " ")
|
||||
message = replacetext(message, "o", "¤")
|
||||
message = replacetext(message, "p", "þ")
|
||||
message = replacetext(message, "l", "£")
|
||||
message = replacetext(message, "s", "§")
|
||||
message = replacetext(message, "u", "µ")
|
||||
message = replacetext(message, "b", "ß")
|
||||
|
||||
var/list/listening = hearers(message_range, src)
|
||||
listening |= src
|
||||
|
||||
//ghosts
|
||||
for (var/mob/M in dead_mob_list) //does this include players who joined as observers as well?
|
||||
if (!(M.client))
|
||||
continue
|
||||
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
listening |= M
|
||||
|
||||
//Pass whispers on to anything inside the immediate listeners.
|
||||
for(var/mob/L in listening)
|
||||
for(var/mob/C in L.contents)
|
||||
if(istype(C,/mob/living))
|
||||
listening += C
|
||||
|
||||
//pass on the message to objects that can hear us.
|
||||
for (var/obj/O in view(message_range, src))
|
||||
spawn (0)
|
||||
if (O)
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
|
||||
var/list/eavesdropping = hearers(eavesdropping_range, src)
|
||||
eavesdropping -= src
|
||||
eavesdropping -= listening
|
||||
|
||||
var/list/watching = hearers(watching_range, src)
|
||||
watching -= src
|
||||
watching -= listening
|
||||
watching -= eavesdropping
|
||||
|
||||
//now mobs
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
|
||||
spawn(30) qdel(speech_bubble)
|
||||
|
||||
for(var/mob/M in listening)
|
||||
M << speech_bubble
|
||||
M.hear_say(message, verb, speaking, alt_name, italics, src)
|
||||
|
||||
if (eavesdropping.len)
|
||||
var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
|
||||
for(var/mob/M in eavesdropping)
|
||||
M << speech_bubble
|
||||
M.hear_say(new_message, verb, speaking, alt_name, italics, src)
|
||||
|
||||
if (watching.len)
|
||||
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
|
||||
for (var/mob/M in watching)
|
||||
M.show_message(rendered, 2)
|
||||
@@ -18,8 +18,6 @@
|
||||
if (client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot send IC messages (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
if (stat)
|
||||
return
|
||||
if(!(message))
|
||||
|
||||
@@ -244,8 +244,8 @@
|
||||
processing_objects.Add(src)
|
||||
|
||||
process()
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
var/mob/observer/dead/ghost
|
||||
for(var/mob/observer/dead/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
@@ -256,8 +256,8 @@
|
||||
icon_state = "golem"
|
||||
|
||||
attack_hand(mob/living/user as mob)
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
var/mob/observer/dead/ghost
|
||||
for(var/mob/observer/dead/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
@@ -273,7 +273,7 @@
|
||||
|
||||
|
||||
proc/announce_to_ghosts()
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
for(var/mob/observer/dead/G in player_list)
|
||||
if(G.client)
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
|
||||
@@ -106,14 +106,11 @@
|
||||
else
|
||||
if (src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc.
|
||||
if (src.stunned > 0)
|
||||
AdjustStunned(-1)
|
||||
src.stat = 0
|
||||
if (src.weakened > 0)
|
||||
AdjustWeakened(-1)
|
||||
src.lying = 0
|
||||
src.stat = 0
|
||||
if (src.paralysis > 0)
|
||||
AdjustParalysis(-1)
|
||||
src.blinded = 0
|
||||
src.lying = 0
|
||||
src.stat = 0
|
||||
@@ -220,7 +217,7 @@
|
||||
|
||||
if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.species.name == "Slime")
|
||||
if(H.species.name == "Promethean")
|
||||
continue
|
||||
|
||||
if(!L.canmove) // Only one slime can latch on at a time.
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
speech_buffer.Add(lowertext(html_decode(message)))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
if (speaker in Friends)
|
||||
speech_buffer = list()
|
||||
speech_buffer.Add(speaker)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/mob/living/carbon/process_resist()
|
||||
|
||||
//drop && roll
|
||||
@@ -17,14 +16,17 @@
|
||||
"<span class='notice'>You extinguish yourself.</span>"
|
||||
)
|
||||
ExtinguishMob()
|
||||
return
|
||||
return TRUE
|
||||
|
||||
..()
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(handcuffed)
|
||||
spawn() escape_handcuffs()
|
||||
else if(legcuffed)
|
||||
spawn() escape_legcuffs()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/carbon/proc/escape_handcuffs()
|
||||
//if(!(last_special <= world.time)) return
|
||||
@@ -57,8 +59,8 @@
|
||||
"<span class='warning'>You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, breakouttime))
|
||||
if(!handcuffed)
|
||||
if(do_after(src, breakouttime, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
|
||||
if(!handcuffed || buckled)
|
||||
return
|
||||
visible_message(
|
||||
"<span class='danger'>\The [src] manages to remove \the [handcuffed]!</span>",
|
||||
@@ -91,7 +93,7 @@
|
||||
"<span class='warning'>You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, breakouttime))
|
||||
if(do_after(src, breakouttime, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
|
||||
if(!legcuffed || buckled)
|
||||
return
|
||||
visible_message(
|
||||
@@ -113,7 +115,7 @@
|
||||
"<span class='warning'>You attempt to break your [handcuffed.name]. (This will take around 5 seconds and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, 50))
|
||||
if(do_after(src, 5 SECONDS, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
|
||||
if(!handcuffed || buckled)
|
||||
return
|
||||
|
||||
@@ -134,7 +136,7 @@
|
||||
src << "<span class='warning'>You attempt to break your legcuffs. (This will take around 5 seconds and you need to stand still)</span>"
|
||||
visible_message("<span class='danger'>[src] is trying to break the legcuffs!</span>")
|
||||
|
||||
if(do_after(src, 50))
|
||||
if(do_after(src, 5 SECONDS, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED))
|
||||
if(!legcuffed || buckled)
|
||||
return
|
||||
|
||||
@@ -166,7 +168,7 @@
|
||||
"<span class='warning'>You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(usr, 1200))
|
||||
if(do_after(usr, 2 MINUTES, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY)))
|
||||
if(!buckled)
|
||||
return
|
||||
visible_message("<span class='danger'>[usr] manages to unbuckle themself!</span>",
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
if(istype(src,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/M = src
|
||||
for(var/obj/item/organ/external/organ in M.organs)
|
||||
if(organ && (organ.is_broken() || organ.open))
|
||||
if(organ.is_broken() || organ.open)
|
||||
src.traumatic_shock += 30
|
||||
else if(organ.is_dislocated())
|
||||
src.traumatic_shock += 15
|
||||
|
||||
if(src.traumatic_shock < 0)
|
||||
src.traumatic_shock = 0
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/mob/living/death()
|
||||
clear_fullscreens()
|
||||
. = ..()
|
||||
@@ -0,0 +1,172 @@
|
||||
/mob/living
|
||||
var/hand = null
|
||||
var/obj/item/l_hand = null
|
||||
var/obj/item/r_hand = null
|
||||
var/obj/item/weapon/back = null//Human/Monkey
|
||||
var/obj/item/weapon/tank/internal = null//Human/Monkey
|
||||
var/obj/item/clothing/mask/wear_mask = null//Carbon
|
||||
|
||||
/mob/living/equip_to_storage(obj/item/newitem)
|
||||
// Try put it in their backpack
|
||||
if(istype(src.back,/obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/backpack = src.back
|
||||
if(backpack.can_be_inserted(newitem, 1))
|
||||
newitem.forceMove(src.back)
|
||||
return 1
|
||||
|
||||
// Try to place it in any item that can store stuff, on the mob.
|
||||
for(var/obj/item/weapon/storage/S in src.contents)
|
||||
if (S.can_be_inserted(newitem, 1))
|
||||
newitem.forceMove(S)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Returns the thing in our active hand
|
||||
/mob/living/get_active_hand()
|
||||
if(hand) return l_hand
|
||||
else return r_hand
|
||||
|
||||
//Returns the thing in our inactive hand
|
||||
/mob/living/get_inactive_hand()
|
||||
if(hand) return r_hand
|
||||
else return l_hand
|
||||
|
||||
//Drops the item in our active hand. TODO: rename this to drop_active_hand or something
|
||||
/mob/living/drop_item(var/atom/Target)
|
||||
if(hand) return drop_l_hand(Target)
|
||||
else return drop_r_hand(Target)
|
||||
|
||||
//Drops the item in our left hand
|
||||
/mob/living/drop_l_hand(var/atom/Target)
|
||||
return drop_from_inventory(l_hand, Target)
|
||||
|
||||
//Drops the item in our right hand
|
||||
/mob/living/drop_r_hand(var/atom/Target)
|
||||
return drop_from_inventory(r_hand, Target)
|
||||
|
||||
/mob/living/proc/hands_are_full()
|
||||
return (r_hand && l_hand)
|
||||
|
||||
/mob/living/proc/item_is_in_hands(var/obj/item/I)
|
||||
return (I == r_hand || I == l_hand)
|
||||
|
||||
/mob/living/proc/update_held_icons()
|
||||
if(l_hand)
|
||||
l_hand.update_held_icon()
|
||||
if(r_hand)
|
||||
r_hand.update_held_icon()
|
||||
|
||||
/mob/living/proc/get_type_in_hands(var/T)
|
||||
if(istype(l_hand, T))
|
||||
return l_hand
|
||||
if(istype(r_hand, T))
|
||||
return r_hand
|
||||
return null
|
||||
|
||||
/mob/living/proc/get_left_hand()
|
||||
return l_hand
|
||||
|
||||
/mob/living/proc/get_right_hand()
|
||||
return r_hand
|
||||
|
||||
/mob/living/u_equip(obj/W as obj)
|
||||
if (W == r_hand)
|
||||
r_hand = null
|
||||
update_inv_r_hand(0)
|
||||
else if (W == l_hand)
|
||||
l_hand = null
|
||||
update_inv_l_hand(0)
|
||||
else if (W == back)
|
||||
back = null
|
||||
update_inv_back(0)
|
||||
else if (W == wear_mask)
|
||||
wear_mask = null
|
||||
update_inv_wear_mask(0)
|
||||
return
|
||||
|
||||
/mob/living/get_equipped_item(var/slot)
|
||||
switch(slot)
|
||||
if(slot_l_hand) return l_hand
|
||||
if(slot_r_hand) return r_hand
|
||||
if(slot_back) return back
|
||||
if(slot_wear_mask) return wear_mask
|
||||
return null
|
||||
|
||||
/mob/living/show_inv(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/dat = {"
|
||||
<B><HR><FONT size=3>[name]</FONT></B>
|
||||
<BR><HR>
|
||||
<BR><B>Head(Mask):</B> <A href='?src=\ref[src];item=mask'>[(wear_mask ? wear_mask : "Nothing")]</A>
|
||||
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=l_hand'>[(l_hand ? l_hand : "Nothing")]</A>
|
||||
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=r_hand'>[(r_hand ? r_hand : "Nothing")]</A>
|
||||
<BR><B>Back:</B> <A href='?src=\ref[src];item=back'>[(back ? back : "Nothing")]</A> [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" <A href='?src=\ref[];item=internal'>Set Internal</A>", src) : "")]
|
||||
<BR>[(internal ? text("<A href='?src=\ref[src];item=internal'>Remove Internal</A>") : "")]
|
||||
<BR><A href='?src=\ref[src];item=pockets'>Empty Pockets</A>
|
||||
<BR><A href='?src=\ref[user];refresh=1'>Refresh</A>
|
||||
<BR><A href='?src=\ref[user];mach_close=mob[name]'>Close</A>
|
||||
<BR>"}
|
||||
user << browse(dat, text("window=mob[];size=325x500", name))
|
||||
onclose(user, "mob[name]")
|
||||
return
|
||||
|
||||
/mob/living/ret_grab(obj/effect/list_container/mobl/L as obj, flag)
|
||||
if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) )))
|
||||
if (!( L ))
|
||||
return null
|
||||
else
|
||||
return L.container
|
||||
else
|
||||
if (!( L ))
|
||||
L = new /obj/effect/list_container/mobl( null )
|
||||
L.container += src
|
||||
L.master = src
|
||||
if (istype(l_hand, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = l_hand
|
||||
if (!( L.container.Find(G.affecting) ))
|
||||
L.container += G.affecting
|
||||
if (G.affecting)
|
||||
G.affecting.ret_grab(L, 1)
|
||||
if (istype(r_hand, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = r_hand
|
||||
if (!( L.container.Find(G.affecting) ))
|
||||
L.container += G.affecting
|
||||
if (G.affecting)
|
||||
G.affecting.ret_grab(L, 1)
|
||||
if (!( flag ))
|
||||
if (L.master == src)
|
||||
var/list/temp = list( )
|
||||
temp += L.container
|
||||
//L = null
|
||||
qdel(L)
|
||||
return temp
|
||||
else
|
||||
return L.container
|
||||
return
|
||||
|
||||
/mob/living/mode()
|
||||
set name = "Activate Held Object"
|
||||
set category = "Object"
|
||||
set src = usr
|
||||
|
||||
if(istype(loc,/obj/mecha)) return
|
||||
|
||||
if(hand)
|
||||
var/obj/item/W = l_hand
|
||||
if (W)
|
||||
W.attack_self(src)
|
||||
update_inv_l_hand()
|
||||
else
|
||||
var/obj/item/W = r_hand
|
||||
if (W)
|
||||
W.attack_self(src)
|
||||
update_inv_r_hand()
|
||||
return
|
||||
|
||||
/mob/living/abiotic(var/full_body = 0)
|
||||
if(full_body && ((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )) || (src.back || src.wear_mask)))
|
||||
return 1
|
||||
|
||||
if((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )))
|
||||
return 1
|
||||
return 0
|
||||
@@ -47,14 +47,13 @@
|
||||
|
||||
if(handle_regular_status_updates()) // Status & health update, are we dead or alive etc.
|
||||
handle_disabilities() // eye, ear, brain damages
|
||||
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
|
||||
handle_statuses() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
|
||||
|
||||
handle_actions()
|
||||
|
||||
update_canmove()
|
||||
|
||||
if(client)
|
||||
handle_regular_hud_updates()
|
||||
handle_regular_hud_updates()
|
||||
|
||||
/mob/living/proc/handle_breathing()
|
||||
return
|
||||
@@ -94,23 +93,59 @@
|
||||
stat = CONSCIOUS
|
||||
return 1
|
||||
|
||||
//this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc..
|
||||
/mob/living/proc/handle_status_effects()
|
||||
if(paralysis)
|
||||
paralysis = max(paralysis-1,0)
|
||||
/mob/living/proc/handle_statuses()
|
||||
handle_stunned()
|
||||
handle_weakened()
|
||||
handle_paralysed()
|
||||
handle_stuttering()
|
||||
handle_silent()
|
||||
handle_drugged()
|
||||
handle_slurring()
|
||||
|
||||
/mob/living/proc/handle_stunned()
|
||||
if(stunned)
|
||||
stunned = max(stunned-1,0)
|
||||
AdjustStunned(-1)
|
||||
if(!stunned)
|
||||
update_icons()
|
||||
return stunned
|
||||
|
||||
/mob/living/proc/handle_weakened()
|
||||
if(weakened)
|
||||
weakened = max(weakened-1,0)
|
||||
if(!weakened)
|
||||
update_icons()
|
||||
return weakened
|
||||
|
||||
/mob/living/proc/handle_stuttering()
|
||||
if(stuttering)
|
||||
stuttering = max(stuttering-1, 0)
|
||||
return stuttering
|
||||
|
||||
/mob/living/proc/handle_silent()
|
||||
if(silent)
|
||||
silent = max(silent-1, 0)
|
||||
return silent
|
||||
|
||||
/mob/living/proc/handle_drugged()
|
||||
if(druggy)
|
||||
druggy = max(druggy-1, 0)
|
||||
return druggy
|
||||
|
||||
/mob/living/proc/handle_slurring()
|
||||
if(slurring)
|
||||
slurring = max(slurring-1, 0)
|
||||
return slurring
|
||||
|
||||
/mob/living/proc/handle_paralysed()
|
||||
if(paralysis)
|
||||
AdjustParalysis(-1)
|
||||
if(!paralysis)
|
||||
update_icons()
|
||||
return paralysis
|
||||
|
||||
/mob/living/proc/handle_disabilities()
|
||||
//Eyes
|
||||
if(disabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own
|
||||
if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own
|
||||
eye_blind = max(eye_blind, 1)
|
||||
else if(eye_blind) //blindness, heals slowly over time
|
||||
eye_blind = max(eye_blind-1,0)
|
||||
@@ -118,7 +153,7 @@
|
||||
eye_blurry = max(eye_blurry-1, 0)
|
||||
|
||||
//Ears
|
||||
if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own
|
||||
if(sdisabilities & 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
|
||||
|
||||
@@ -125,10 +125,11 @@ default behaviour is:
|
||||
..()
|
||||
if (!istype(AM, /atom/movable) || AM.anchored)
|
||||
if(confused && prob(50) && m_intent=="run")
|
||||
Paralyse(1)
|
||||
Weaken(2)
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='warning'>[src] [pick("ran", "slammed")] into \the [AM]!</span>")
|
||||
src.take_organ_damage(5)
|
||||
src.apply_damage(5, BRUTE)
|
||||
src << ("<span class='warning'>You just [pick("ran", "slammed")] into \the [AM]!</span>")
|
||||
return
|
||||
if (!now_pushing)
|
||||
now_pushing = 1
|
||||
@@ -453,6 +454,7 @@ default behaviour is:
|
||||
BITSET(hud_updateflag, LIFE_HUD)
|
||||
|
||||
failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
|
||||
reload_fullscreen()
|
||||
|
||||
return
|
||||
|
||||
@@ -510,52 +512,38 @@ default behaviour is:
|
||||
if ((get_dist(src, pulling) > 1 || diag))
|
||||
if (isliving(pulling))
|
||||
var/mob/living/M = pulling
|
||||
var/ok = 1
|
||||
if (locate(/obj/item/weapon/grab, M.grabbed_by))
|
||||
if (prob(75))
|
||||
var/obj/item/weapon/grab/G = pick(M.grabbed_by)
|
||||
if (istype(G, /obj/item/weapon/grab))
|
||||
for(var/mob/O in viewers(M, null))
|
||||
O.show_message(text("\red [] has been pulled from []'s grip by []", G.affecting, G.assailant, src), 1)
|
||||
//G = null
|
||||
qdel(G)
|
||||
else
|
||||
ok = 0
|
||||
if (locate(/obj/item/weapon/grab, M.grabbed_by.len))
|
||||
ok = 0
|
||||
if (ok)
|
||||
var/atom/movable/t = M.pulling
|
||||
M.stop_pulling()
|
||||
var/atom/movable/t = M.pulling
|
||||
M.stop_pulling()
|
||||
|
||||
if(!istype(M.loc, /turf/space))
|
||||
var/area/A = get_area(M)
|
||||
if(A.has_gravity)
|
||||
//this is the gay blood on floor shit -- Added back -- Skie
|
||||
if (M.lying && (prob(M.getBruteLoss() / 6)))
|
||||
if(!istype(M.loc, /turf/space))
|
||||
var/area/A = get_area(M)
|
||||
if(A.has_gravity)
|
||||
//this is the gay blood on floor shit -- Added back -- Skie
|
||||
if (M.lying && (prob(M.getBruteLoss() / 6)))
|
||||
var/turf/location = M.loc
|
||||
if (istype(location, /turf/simulated))
|
||||
location.add_blood(M)
|
||||
//pull damage with injured people
|
||||
if(prob(25))
|
||||
M.adjustBruteLoss(1)
|
||||
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state worsens": "wounds open more"] from being dragged!</span>")
|
||||
if(M.pull_damage())
|
||||
if(prob(25))
|
||||
M.adjustBruteLoss(2)
|
||||
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state" : "wounds"] worsen terribly from being dragged!</span>")
|
||||
var/turf/location = M.loc
|
||||
if (istype(location, /turf/simulated))
|
||||
location.add_blood(M)
|
||||
//pull damage with injured people
|
||||
if(prob(25))
|
||||
M.adjustBruteLoss(1)
|
||||
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state worsens": "wounds open more"] from being dragged!</span>")
|
||||
if(M.pull_damage())
|
||||
if(prob(25))
|
||||
M.adjustBruteLoss(2)
|
||||
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state" : "wounds"] worsen terribly from being dragged!</span>")
|
||||
var/turf/location = M.loc
|
||||
if (istype(location, /turf/simulated))
|
||||
location.add_blood(M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
|
||||
if(blood_volume > 0)
|
||||
H.vessel.remove_reagent("blood", 1)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
|
||||
if(blood_volume > 0)
|
||||
H.vessel.remove_reagent("blood", 1)
|
||||
|
||||
|
||||
step(pulling, get_dir(pulling.loc, T))
|
||||
if(t)
|
||||
M.start_pulling(t)
|
||||
step(pulling, get_dir(pulling.loc, T))
|
||||
if(t)
|
||||
M.start_pulling(t)
|
||||
else
|
||||
if (pulling)
|
||||
if (istype(pulling, /obj/structure/window))
|
||||
@@ -580,7 +568,7 @@ default behaviour is:
|
||||
set name = "Resist"
|
||||
set category = "IC"
|
||||
|
||||
if(!stat && canClick())
|
||||
if(!incapacitated(INCAPACITATION_KNOCKOUT) && canClick())
|
||||
setClickCooldown(20)
|
||||
resist_grab()
|
||||
if(!weakened)
|
||||
@@ -595,11 +583,13 @@ default behaviour is:
|
||||
//unbuckling yourself
|
||||
if(buckled)
|
||||
spawn() escape_buckle()
|
||||
return TRUE
|
||||
|
||||
//Breaking out of a locker?
|
||||
if( src.loc && (istype(src.loc, /obj/structure/closet)) )
|
||||
var/obj/structure/closet/C = loc
|
||||
spawn() C.mob_breakout(src)
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/escape_inventory(obj/item/weapon/holder/H)
|
||||
if(H != src.loc) return
|
||||
@@ -633,24 +623,9 @@ default behaviour is:
|
||||
|
||||
/mob/living/proc/resist_grab()
|
||||
var/resisting = 0
|
||||
for(var/obj/O in requests)
|
||||
requests.Remove(O)
|
||||
qdel(O)
|
||||
resisting++
|
||||
for(var/obj/item/weapon/grab/G in grabbed_by)
|
||||
resisting++
|
||||
switch(G.state)
|
||||
if(GRAB_PASSIVE)
|
||||
qdel(G)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
if(prob(60)) //same chance of breaking the grab as disarm
|
||||
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s grip!</span>")
|
||||
qdel(G)
|
||||
if(GRAB_NECK)
|
||||
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
|
||||
if (((world.time - G.assailant.l_move_time < 30 || !stunned) && prob(15)) || prob(3))
|
||||
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s headlock!</span>")
|
||||
qdel(G)
|
||||
G.handle_resist()
|
||||
if(resisting)
|
||||
visible_message("<span class='danger'>[src] resists!</span>")
|
||||
|
||||
@@ -662,13 +637,22 @@ default behaviour is:
|
||||
src << "<span class='notice'>You are now [resting ? "resting" : "getting up"]</span>"
|
||||
|
||||
/mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item)
|
||||
return isnull(get_inventory_slot(carried_item))
|
||||
return (get_inventory_slot(carried_item) == 0)
|
||||
|
||||
/mob/living/simple_animal/spiderbot/is_allowed_vent_crawl_item(var/obj/item/carried_item)
|
||||
if(carried_item == held_item)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
//called when the mob receives a bright flash
|
||||
/mob/living/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
|
||||
if(override_blindness_check || !(disabilities & BLIND))
|
||||
overlay_fullscreen("flash", type)
|
||||
spawn(25)
|
||||
if(src)
|
||||
clear_fullscreen("flash", 25)
|
||||
return 1
|
||||
|
||||
/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null, var/ignore_items = 0) // -- TLE -- Merged by Carn
|
||||
if(stat)
|
||||
src << "You must be conscious to do this!"
|
||||
@@ -676,7 +660,6 @@ default behaviour is:
|
||||
if(lying)
|
||||
src << "You can't vent crawl while you're stunned!"
|
||||
return
|
||||
|
||||
var/special_fail_msg = cannot_use_vents()
|
||||
if(special_fail_msg)
|
||||
src << "<span class='warning'>[special_fail_msg]</span>"
|
||||
@@ -730,10 +713,12 @@ default behaviour is:
|
||||
return
|
||||
|
||||
if(!ignore_items)
|
||||
var/list/badItems = list()
|
||||
for(var/obj/item/carried_item in contents)//If the monkey got on objects.
|
||||
if(is_allowed_vent_crawl_item(carried_item))
|
||||
continue
|
||||
src << "<span class='warning'>You can't be carrying items or have items equipped when vent crawling!</span>"
|
||||
if(!is_allowed_vent_crawl_item(carried_item))
|
||||
badItems += carried_item.name
|
||||
if(badItems.len)
|
||||
src << "<span class='warning'>Your [english_list(badItems)] prevent[badItems.len == 1 ? "s" : ""] you from ventcrawling.</span>"
|
||||
return
|
||||
|
||||
if(isslime(src))
|
||||
@@ -865,3 +850,58 @@ default behaviour is:
|
||||
sleep(350)
|
||||
lastpuke = 0
|
||||
|
||||
/mob/living/update_canmove()
|
||||
if(!resting && cannot_stand() && can_stand_overridden())
|
||||
lying = 0
|
||||
canmove = 1
|
||||
else
|
||||
if(istype(buckled, /obj/vehicle))
|
||||
var/obj/vehicle/V = buckled
|
||||
if(is_physically_disabled())
|
||||
lying = 0
|
||||
canmove = 1
|
||||
pixel_y = V.mob_offset_y - 5
|
||||
else
|
||||
if(buckled.buckle_lying != -1) lying = buckled.buckle_lying
|
||||
canmove = 1
|
||||
pixel_y = V.mob_offset_y
|
||||
else if(buckled)
|
||||
anchored = 1
|
||||
canmove = 0
|
||||
if(istype(buckled))
|
||||
if(buckled.buckle_lying != -1)
|
||||
lying = buckled.buckle_lying
|
||||
if(buckled.buckle_movable)
|
||||
anchored = 0
|
||||
canmove = 1
|
||||
|
||||
else if(captured)
|
||||
anchored = 1
|
||||
canmove = 0
|
||||
lying = 0
|
||||
else
|
||||
lying = incapacitated(INCAPACITATION_KNOCKDOWN)
|
||||
canmove = !incapacitated(INCAPACITATION_DISABLED)
|
||||
|
||||
if(lying)
|
||||
density = 0
|
||||
if(l_hand) unEquip(l_hand)
|
||||
if(r_hand) unEquip(r_hand)
|
||||
else
|
||||
density = initial(density)
|
||||
|
||||
for(var/obj/item/weapon/grab/G in grabbed_by)
|
||||
if(G.state >= GRAB_AGGRESSIVE)
|
||||
canmove = 0
|
||||
break
|
||||
|
||||
//Temporarily moved here from the various life() procs
|
||||
//I'm fixing stuff incrementally so this will likely find a better home.
|
||||
//It just makes sense for now. ~Carn
|
||||
if( update_icon ) //forces a full overlay update
|
||||
update_icon = 0
|
||||
regenerate_icons()
|
||||
else if( lying != lying_prev )
|
||||
update_icons()
|
||||
return canmove
|
||||
|
||||
|
||||
@@ -144,6 +144,42 @@
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
||||
return target_zone
|
||||
|
||||
//Called when the mob is hit with an item in combat. Returns the blocked result
|
||||
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] with [I.name] by [user]!</span>")
|
||||
|
||||
var/blocked = run_armor_check(hit_zone, "melee")
|
||||
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
|
||||
|
||||
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
|
||||
var/turf/simulated/location = get_turf(src)
|
||||
if(istype(location)) location.add_blood_floor(src)
|
||||
|
||||
return blocked
|
||||
|
||||
//returns 0 if the effects failed to apply for some reason, 1 otherwise.
|
||||
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
if(!effective_force || blocked >= 100)
|
||||
return 0
|
||||
|
||||
//Hulk modifier
|
||||
if(HULK in user.mutations)
|
||||
effective_force *= 2
|
||||
|
||||
//Apply weapon damage
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
return 1
|
||||
|
||||
//this proc handles being hit by a thrown atom
|
||||
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
|
||||
if(istype(AM,/obj/))
|
||||
@@ -370,54 +406,3 @@
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
|
||||
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
|
||||
client.screen += hud_used.hide_actions_toggle
|
||||
|
||||
|
||||
//If simple_animals are ever moved under carbon, then this can probably be moved to carbon as well
|
||||
/mob/living/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
// Knifing
|
||||
if(!W.edge || !W.force || W.damtype != BRUTE) return //unsuitable weapon
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
|
||||
|
||||
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
|
||||
if(!do_after(user, 20))
|
||||
return
|
||||
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
|
||||
return
|
||||
|
||||
var/damage_mod = 1
|
||||
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
|
||||
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
|
||||
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.item_flags & STOPPRESSUREDAMAGE))
|
||||
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
|
||||
damage_mod = 1.0 - (helmet.armor["melee"]/100)
|
||||
|
||||
var/total_damage = 0
|
||||
for(var/i in 1 to 3)
|
||||
var/damage = min(W.force*1.5, 20)*damage_mod
|
||||
apply_damage(damage, W.damtype, BP_HEAD, 0, sharp=W.sharp, edge=W.edge)
|
||||
total_damage += damage
|
||||
|
||||
var/oxyloss = total_damage
|
||||
if(total_damage >= 40) //threshold to make someone pass out
|
||||
oxyloss = 60 // Brain lacks oxygen immediately, pass out
|
||||
|
||||
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
|
||||
|
||||
if(total_damage)
|
||||
if(oxyloss >= 40)
|
||||
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
|
||||
|
||||
if(W.hitsound)
|
||||
playsound(loc, W.hitsound, 50, 1, -1)
|
||||
|
||||
G.last_action = world.time
|
||||
flick(G.hud.icon_state, G.hud)
|
||||
|
||||
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
|
||||
return
|
||||
|
||||
+113
-57
@@ -82,27 +82,31 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
/mob/living/proc/get_default_language()
|
||||
return default_language
|
||||
|
||||
/mob/living/proc/handle_speech_problems(var/message, var/verb)
|
||||
var/list/returns[3]
|
||||
var/speech_problem_flag = 0
|
||||
//Takes a list of the form list(message, verb, whispering) and modifies it as needed
|
||||
//Returns 1 if a speech problem was applied, 0 otherwise
|
||||
/mob/living/proc/handle_speech_problems(var/list/message_data)
|
||||
var/message = message_data[1]
|
||||
var/verb = message_data[2]
|
||||
var/whispering = message_data[3]
|
||||
. = 0
|
||||
|
||||
if((HULK in mutations) && health >= 25 && length(message))
|
||||
message = "[uppertext(message)]!!!"
|
||||
verb = pick("yells","roars","hollers")
|
||||
speech_problem_flag = 1
|
||||
whispering = 0
|
||||
. = 1
|
||||
if(slurring)
|
||||
message = slur(message)
|
||||
verb = pick("slobbers","slurs")
|
||||
speech_problem_flag = 1
|
||||
. = 1
|
||||
if(stuttering)
|
||||
message = stutter(message)
|
||||
verb = pick("stammers","stutters")
|
||||
speech_problem_flag = 1
|
||||
. = 1
|
||||
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = speech_problem_flag
|
||||
return returns
|
||||
message_data[1] = message
|
||||
message_data[2] = verb
|
||||
message_data[3] = whispering
|
||||
|
||||
/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
|
||||
if(message_mode == "intercom")
|
||||
@@ -124,33 +128,42 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
return "asks"
|
||||
return verb
|
||||
|
||||
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
|
||||
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering = 0)
|
||||
//If you're muted for IC chat
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot speak in IC (Muted)."
|
||||
if((client.prefs.muted & MUTE_IC) || say_disabled)
|
||||
src << "<span class='warning'>You cannot speak in IC (Muted).</span>"
|
||||
return
|
||||
|
||||
//Redirect to say_dead if talker is dead
|
||||
if(stat)
|
||||
if(stat == 2)
|
||||
if(stat == DEAD)
|
||||
return say_dead(message)
|
||||
return
|
||||
|
||||
//Parse the mode
|
||||
var/message_mode = parse_message_mode(message, "headset")
|
||||
|
||||
//Maybe they are using say/whisper to do a quick emote, so do those
|
||||
switch(copytext(message,1,2))
|
||||
if("*") return emote(copytext(message,2))
|
||||
if("^") return custom_emote(1, copytext(message,2))
|
||||
|
||||
//parse the radio code and consume it
|
||||
//Parse the radio code and consume it
|
||||
if (message_mode)
|
||||
if (message_mode == "headset")
|
||||
message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
|
||||
else if (message_mode == "whisper")
|
||||
whispering = 1
|
||||
message_mode = null
|
||||
message = copytext(message,3)
|
||||
else
|
||||
message = copytext(message,3)
|
||||
|
||||
//Clean up any remaining space on the left
|
||||
message = trim_left(message)
|
||||
|
||||
//parse the language code and consume it
|
||||
//Parse the language code and consume it
|
||||
if(!speaking)
|
||||
speaking = parse_language(message)
|
||||
if(speaking)
|
||||
@@ -158,42 +171,72 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
else
|
||||
speaking = get_default_language()
|
||||
|
||||
// This is broadcast to all mobs with the language,
|
||||
// irrespective of distance or anything else.
|
||||
//HIVEMIND languages always send to all people with that language
|
||||
if(speaking && (speaking.flags & HIVEMIND))
|
||||
speaking.broadcast(src,trim(message))
|
||||
return 1
|
||||
|
||||
verb = say_quote(message, speaking)
|
||||
|
||||
//Self explanatory.
|
||||
if(is_muzzled())
|
||||
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
|
||||
return
|
||||
|
||||
//Clean up any remaining junk on the left like spaces.
|
||||
message = trim_left(message)
|
||||
|
||||
//Autohiss handles auto-rolling tajaran R's and unathi S's/Z's
|
||||
message = handle_autohiss(message, speaking)
|
||||
|
||||
//Whisper vars
|
||||
var/w_scramble_range = 5 //The range at which you get ***as*th**wi****
|
||||
var/w_adverb //An adverb prepended to the verb in whispers
|
||||
var/w_not_heard //The message for people in watching range
|
||||
|
||||
//Handle language-specific verbs and adverb setup if necessary
|
||||
if(!whispering) //Just doing normal 'say' (for now, may change below)
|
||||
verb = say_quote(message, speaking)
|
||||
else if(whispering && speaking.whisper_verb) //Language has defined whisper verb
|
||||
verb = speaking.whisper_verb
|
||||
w_not_heard = "[verb] something"
|
||||
else //Whispering but language has no whisper verb, use say verb
|
||||
w_adverb = pick("quietly", "softly")
|
||||
verb = speaking.speech_verb
|
||||
w_not_heard = "[speaking.speech_verb] something [w_adverb]"
|
||||
|
||||
//For speech disorders (hulk, slurring, stuttering)
|
||||
if(!(speaking && (speaking.flags & NO_STUTTER)))
|
||||
message = handle_autohiss(message, speaking)
|
||||
var/list/message_data = list(message, verb, whispering)
|
||||
if(handle_speech_problems(message_data))
|
||||
message = message_data[1]
|
||||
whispering = message_data[3]
|
||||
|
||||
var/list/handle_s = handle_speech_problems(message, verb)
|
||||
message = handle_s[1]
|
||||
verb = handle_s[2]
|
||||
if(verb != message_data[2]) //They changed our verb
|
||||
if(whispering)
|
||||
w_adverb = pick("quietly", "softly")
|
||||
verb = message_data[2]
|
||||
|
||||
//Whisper may have adverbs, add those if one was set
|
||||
if(w_adverb) verb = "[verb] [w_adverb]"
|
||||
|
||||
//If something nulled or emptied the message, forget it
|
||||
if(!message || message == "")
|
||||
return 0
|
||||
|
||||
//Radio message handling
|
||||
var/list/obj/item/used_radios = new
|
||||
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name))
|
||||
if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, whispering))
|
||||
return 1
|
||||
|
||||
//For languages with actual speech sounds
|
||||
var/list/handle_v = handle_speech_sound()
|
||||
var/sound/speech_sound = handle_v[1]
|
||||
var/sound_vol = handle_v[2]
|
||||
|
||||
var/italics = 0
|
||||
//Default range and italics, may be overridden past here
|
||||
var/message_range = world.view
|
||||
var/italics = 0
|
||||
|
||||
//speaking into radios
|
||||
//Speaking into radios
|
||||
if(used_radios.len)
|
||||
italics = 1
|
||||
message_range = 1
|
||||
@@ -208,9 +251,13 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
if (speech_sound)
|
||||
sound_vol *= 0.5
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
//Set vars if we're still whispering by this point
|
||||
if(whispering)
|
||||
italics = 1
|
||||
message_range = 1
|
||||
sound_vol *= 0.5
|
||||
|
||||
//handle nonverbal and sign languages here
|
||||
//Handle nonverbal and sign languages here
|
||||
if (speaking)
|
||||
if (speaking.flags & NONVERBAL)
|
||||
if (prob(30))
|
||||
@@ -219,55 +266,64 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
if (speaking.flags & SIGNLANG)
|
||||
return say_signlang(message, pick(speaking.signlang_verb), speaking)
|
||||
|
||||
//These will contain the main receivers of the message
|
||||
var/list/listening = list()
|
||||
var/list/listening_obj = list()
|
||||
|
||||
//Atmosphere calculations (speaker's side only, for now)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
//make sure the air can transmit speech - speaker's side
|
||||
//Air is too thin to carry sound at all, contact speech only
|
||||
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) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
|
||||
//Air is nearing minimum levels, make text italics as a hint, and muffle sound
|
||||
if (pressure < ONE_ATMOSPHERE*0.4)
|
||||
italics = 1
|
||||
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
|
||||
sound_vol *= 0.5
|
||||
|
||||
var/list/hear = get_mobs_or_objects_in_view(message_range,src)
|
||||
var/list/hearturfs = list()
|
||||
|
||||
for(var/I in hear)
|
||||
if(ismob(I))
|
||||
var/mob/M = I
|
||||
listening += M
|
||||
hearturfs += M.locs[1]
|
||||
else if(isobj(I))
|
||||
var/obj/O = I
|
||||
hearturfs += O.locs[1]
|
||||
listening_obj |= O
|
||||
|
||||
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
listening |= M
|
||||
continue
|
||||
if(M.loc && M.locs[1] in hearturfs)
|
||||
listening |= M
|
||||
//Obtain the mobs and objects in the message range
|
||||
var/list/results = get_mobs_and_objs_in_view_fast(T, world.view)
|
||||
listening = results["mobs"]
|
||||
listening_obj = results["objs"]
|
||||
else
|
||||
return 1 //If we're in nullspace, then forget it.
|
||||
|
||||
//The 'post-say' static speech bubble
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
|
||||
spawn(30) qdel(speech_bubble)
|
||||
|
||||
//Main 'say' and 'whisper' message delivery
|
||||
for(var/mob/M in listening)
|
||||
M << speech_bubble
|
||||
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
|
||||
spawn(0) //Using spawns to queue all the messages for AFTER this proc is done, and stop runtimes
|
||||
|
||||
if(M && src) //If we still exist, when the spawn processes
|
||||
var/dst = get_dist(get_turf(M),get_turf(src))
|
||||
|
||||
if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc)
|
||||
M << speech_bubble
|
||||
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
|
||||
|
||||
if(whispering) //Don't even bother with these unless whispering
|
||||
if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range
|
||||
M << speech_bubble
|
||||
M.hear_say(stars(message), verb, speaking, alt_name, italics, src, speech_sound, sound_vol*0.2)
|
||||
if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range
|
||||
M.show_message("<span class='game say'><span class='name'>[src.name]</span> [w_not_heard].</span>", 2)
|
||||
|
||||
//Object message delivery
|
||||
for(var/obj/O in listening_obj)
|
||||
spawn(0)
|
||||
if(O) //It's possible that it could be deleted in the meantime.
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
if(O && src) //If we still exist, when the spawn processes
|
||||
var/dst = get_dist(get_turf(O),get_turf(src))
|
||||
if(dst <= message_range)
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
|
||||
log_say("[name]/[key] : [message]")
|
||||
//Log the message to file
|
||||
log_say("[name]/[key][whispering ? " (W)" : ""]: [message]")
|
||||
return 1
|
||||
|
||||
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
|
||||
|
||||
@@ -20,7 +20,7 @@ var/list/ai_verbs_default = list(
|
||||
/mob/living/silicon/ai/proc/toggle_hidden_verbs,
|
||||
)
|
||||
|
||||
var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.com/1172/
|
||||
var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.com/1172/,
|
||||
/mob/living/silicon/ai/proc/ai_announcement,
|
||||
/mob/living/silicon/ai/proc/ai_call_shuttle,
|
||||
/mob/living/silicon/ai/proc/ai_camera_track,
|
||||
@@ -52,7 +52,7 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c
|
||||
density = 1
|
||||
status_flags = CANSTUN|CANPARALYSE|CANPUSH
|
||||
shouldnt_see = list(/obj/effect/rune)
|
||||
var/list/network = list("Northern Star")
|
||||
var/list/network = list(station_short)
|
||||
var/obj/machinery/camera/camera = null
|
||||
var/list/connected_robots = list()
|
||||
var/aiRestorePowerRoutine = 0
|
||||
@@ -151,11 +151,13 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c
|
||||
add_language("Galactic Common", 1)
|
||||
add_language("Sol Common", 0)
|
||||
add_language("Sinta'unathi", 0)
|
||||
add_language("Siik'maas", 0)
|
||||
add_language("Siik'tajr", 0)
|
||||
add_language("Skrellian", 0)
|
||||
add_language("Tradeband", 1)
|
||||
add_language("Gutter", 0)
|
||||
add_language("Encoded Audio Language", 1)
|
||||
add_language("Schechi", 0)
|
||||
|
||||
if(!safety)//Only used by AIize() to successfully spawn an AI.
|
||||
if (!B)//If there is no player/brain inside.
|
||||
@@ -232,11 +234,11 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c
|
||||
|
||||
/mob/living/silicon/ai/proc/setup_icon()
|
||||
var/file = file2text("config/custom_sprites.txt")
|
||||
var/lines = text2list(file, "\n")
|
||||
var/lines = splittext(file, "\n")
|
||||
|
||||
for(var/line in lines)
|
||||
// split & clean up
|
||||
var/list/Entry = text2list(line, ":")
|
||||
var/list/Entry = splittext(line, ":")
|
||||
for(var/i = 1 to Entry.len)
|
||||
Entry[i] = trim(Entry[i])
|
||||
|
||||
|
||||
@@ -39,6 +39,6 @@
|
||||
/mob/proc/showLaws(var/mob/living/silicon/S)
|
||||
return
|
||||
|
||||
/mob/dead/observer/showLaws(var/mob/living/silicon/S)
|
||||
/mob/observer/dead/showLaws(var/mob/living/silicon/S)
|
||||
if(antagHUD || is_admin(src))
|
||||
S.laws.show_laws(src)
|
||||
|
||||
@@ -56,18 +56,18 @@
|
||||
if (aiRestorePowerRoutine==2)
|
||||
src << "Alert cancelled. Power has been restored without our assistance."
|
||||
aiRestorePowerRoutine = 0
|
||||
src.blind.layer = 0
|
||||
clear_fullscreen("blind")
|
||||
updateicon()
|
||||
return
|
||||
else if (aiRestorePowerRoutine==3)
|
||||
src << "Alert cancelled. Power has been restored."
|
||||
aiRestorePowerRoutine = 0
|
||||
src.blind.layer = 0
|
||||
clear_fullscreen("blind")
|
||||
updateicon()
|
||||
return
|
||||
else if (APU_power)
|
||||
aiRestorePowerRoutine = 0
|
||||
src.blind.layer = 0
|
||||
clear_fullscreen("blind")
|
||||
updateicon()
|
||||
return
|
||||
else
|
||||
@@ -79,9 +79,7 @@
|
||||
|
||||
//Blind the AI
|
||||
updateicon()
|
||||
src.blind.screen_loc = ui_entire_screen
|
||||
if (src.blind.layer!=18)
|
||||
src.blind.layer = 18
|
||||
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
||||
src.sight = src.sight&~SEE_TURFS
|
||||
src.sight = src.sight&~SEE_MOBS
|
||||
src.sight = src.sight&~SEE_OBJS
|
||||
@@ -99,7 +97,7 @@
|
||||
if (!istype(T, /turf/space))
|
||||
src << "Alert cancelled. Power has been restored without our assistance."
|
||||
aiRestorePowerRoutine = 0
|
||||
src.blind.layer = 0
|
||||
clear_fullscreen("blind")
|
||||
return
|
||||
src << "Fault confirmed: missing external power. Shutting down main control system to save power."
|
||||
sleep(20)
|
||||
@@ -129,7 +127,7 @@
|
||||
if (!istype(T, /turf/space))
|
||||
src << "Alert cancelled. Power has been restored without our assistance."
|
||||
aiRestorePowerRoutine = 0
|
||||
src.blind.layer = 0 //This, too, is a fix to issue 603
|
||||
clear_fullscreen("blind") //This, too, is a fix to issue 603
|
||||
return
|
||||
switch(PRP)
|
||||
if (1) src << "APC located. Optimizing route to APC to avoid needless power waste."
|
||||
|
||||
@@ -2,19 +2,6 @@
|
||||
..()
|
||||
for(var/obj/effect/rune/rune in rune_list)
|
||||
client.images += rune.blood_image
|
||||
regenerate_icons()
|
||||
flash = new /obj/screen()
|
||||
flash.icon_state = "blank"
|
||||
flash.name = "flash"
|
||||
flash.screen_loc = ui_entire_screen
|
||||
flash.layer = 17
|
||||
blind = new /obj/screen()
|
||||
blind.icon_state = "black"
|
||||
blind.name = " "
|
||||
blind.screen_loc = ui_entire_screen
|
||||
blind.layer = 0
|
||||
client.screen.Add( blind, flash )
|
||||
|
||||
if(stat != DEAD)
|
||||
for(var/obj/machinery/ai_status_display/O in machines) //change status
|
||||
O.mode = 1
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
pass_flags = 1
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
can_pull_size = 2
|
||||
can_pull_mobs = MOB_PULL_SMALLER
|
||||
|
||||
idcard_type = /obj/item/weapon/card/id
|
||||
var/idaccessible = 0
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
|
||||
for(var/datum/paiCandidate/c in paiController.pai_candidates)
|
||||
if(c.ready)
|
||||
var/found = 0
|
||||
for(var/mob/dead/observer/o in player_list)
|
||||
for(var/mob/observer/dead/o in player_list)
|
||||
if(o.key == c.key && o.MayRespawn())
|
||||
found = 1
|
||||
if(found)
|
||||
@@ -346,7 +346,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
|
||||
|
||||
/datum/paiController/proc/requestRecruits(var/mob/user)
|
||||
inquirer = user
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(!O.MayRespawn())
|
||||
continue
|
||||
if(jobban_isbanned(O, "pAI"))
|
||||
|
||||
@@ -121,11 +121,11 @@
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
data_core.get_manifest_json()
|
||||
data_core.get_manifest_list()
|
||||
|
||||
var/data[0]
|
||||
// This is dumb, but NanoUI breaks if it has no data to send
|
||||
data["manifest"] = list("__json_cache" = ManifestJSON)
|
||||
data["manifest"] = PDA_Manifest
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
var/organ_found
|
||||
if(H.internal_organs.len)
|
||||
for(var/obj/item/organ/external/E in H.organs)
|
||||
if(!(E.status & ORGAN_ROBOT))
|
||||
if(!(E.robotic >= ORGAN_ROBOT))
|
||||
continue
|
||||
organ_found = 1
|
||||
user << "[E.name]: <font color='red'>[E.brute_dam]</font> <font color='#FFA500'>[E.burn_dam]</font>"
|
||||
@@ -86,7 +86,7 @@
|
||||
organ_found = null
|
||||
if(H.internal_organs.len)
|
||||
for(var/obj/item/organ/O in H.internal_organs)
|
||||
if(!(O.status & ORGAN_ROBOT))
|
||||
if(!(O.robotic >= ORGAN_ROBOT))
|
||||
continue
|
||||
organ_found = 1
|
||||
user << "[O.name]: <font color='red'>[O.damage]</font>"
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
/datum/robot_component/armour
|
||||
name = "armour plating"
|
||||
external_type = /obj/item/robot_parts/robot_component/armour
|
||||
max_damage = 60
|
||||
max_damage = 90
|
||||
|
||||
|
||||
// ACTUATOR
|
||||
|
||||
@@ -6,7 +6,7 @@ var/list/robot_custom_icons
|
||||
|
||||
/hook/startup/proc/load_robot_custom_sprites()
|
||||
var/config_file = file2text("config/custom_sprites.txt")
|
||||
var/list/lines = text2list(config_file, "\n")
|
||||
var/list/lines = splittext(config_file, "\n")
|
||||
|
||||
robot_custom_icons = list()
|
||||
for(var/line in lines)
|
||||
|
||||
@@ -240,7 +240,7 @@ var/list/mob_hat_cache = list()
|
||||
//Drones killed by damage will gib.
|
||||
/mob/living/silicon/robot/drone/handle_regular_status_updates()
|
||||
var/turf/T = get_turf(src)
|
||||
if((!T || health <= -35 || (master_fabricator && T.z != master_fabricator.z)) && src.stat != DEAD)
|
||||
if(!T || health <= -35 )
|
||||
timeofdeath = world.time
|
||||
death() //Possibly redundant, having trouble making death() cooperate.
|
||||
gib()
|
||||
@@ -278,7 +278,7 @@ var/list/mob_hat_cache = list()
|
||||
//Reboot procs.
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/request_player()
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(jobban_isbanned(O, "Cyborg"))
|
||||
continue
|
||||
if(O.client)
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
//Has a list of items that it can hold.
|
||||
var/list/can_hold = list(
|
||||
/obj/item/weapon/cell,
|
||||
/obj/item/weapon/firealarm_electronics,
|
||||
/obj/item/weapon/airalarm_electronics,
|
||||
/obj/item/weapon/airlock_electronics,
|
||||
/obj/item/weapon/tracker_electronics,
|
||||
/obj/item/weapon/module/power_control,
|
||||
@@ -63,9 +61,9 @@
|
||||
/obj/item/device/mmi,
|
||||
/obj/item/robot_parts,
|
||||
/obj/item/borg/upgrade,
|
||||
/obj/item/device/flash, //to build borgs
|
||||
/obj/item/organ/internal/brain, //to insert into MMIs.
|
||||
/obj/item/stack/cable_coil, //again, for borg building
|
||||
/obj/item/device/flash, //to build borgs,
|
||||
/obj/item/organ/internal/brain, //to insert into MMIs,
|
||||
/obj/item/weapon/disk,
|
||||
/obj/item/weapon/circuitboard,
|
||||
/obj/item/slime_extract,
|
||||
/obj/item/weapon/reagent_containers/glass,
|
||||
@@ -85,6 +83,35 @@
|
||||
/obj/item/weapon/grown
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ
|
||||
name = "organ gripper"
|
||||
icon_state = "gripper-flesh"
|
||||
desc = "A specialized grasping tool used to preserve and manipulate organic material."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/organ
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/organ/robotics
|
||||
name = "external organ gripper"
|
||||
icon_state = "gripper-flesh"
|
||||
desc = "A specialized grasping tool used in robotics work."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/organ/external,
|
||||
/obj/item/organ/internal/cell
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use/mech
|
||||
name = "exosuit gripper"
|
||||
icon_state = "gripper-mech"
|
||||
desc = "A large, heavy-duty grasping tool used in construction of mechs."
|
||||
|
||||
can_hold = list(
|
||||
/obj/item/mecha_parts/part,
|
||||
/obj/item/mecha_parts/mecha_equipment
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/no_use //Used when you want to hold and put items in other things, but not able to 'use' the item
|
||||
|
||||
/obj/item/weapon/gripper/no_use/attack_self(mob/user as mob)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
|
||||
var/fabricator_tag = "Northern Star Upper Level"
|
||||
var/fabricator_tag = station_short+" Upper Level"
|
||||
var/drone_progress = 0
|
||||
var/produce_drones = 1
|
||||
var/time_last_drone = 500
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/obj/machinery/drone_fabricator/derelict
|
||||
name = "construction drone fabricator"
|
||||
fabricator_tag = "Northern Star Depths"
|
||||
fabricator_tag = station_short+" Depths"
|
||||
drone_type = /mob/living/silicon/robot/drone/construction
|
||||
|
||||
/obj/machinery/drone_fabricator/New()
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
..(user)
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/observer/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
user << "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
@@ -70,7 +70,7 @@
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
return
|
||||
|
||||
if(!player || !istype(player.mob,/mob/dead))
|
||||
if(!player || !istype(player.mob,/mob/observer/dead))
|
||||
return
|
||||
|
||||
announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
drone_progress = 0
|
||||
|
||||
/mob/dead/verb/join_as_drone()
|
||||
/mob/observer/dead/verb/join_as_drone()
|
||||
|
||||
set category = "Ghost"
|
||||
set name = "Join As Drone"
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "You cannot send IC messages (muted)."
|
||||
return 0
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return 0
|
||||
|
||||
message = sanitize(message)
|
||||
|
||||
if (stat == 2)
|
||||
if (stat == DEAD)
|
||||
return say_dead(message)
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
@@ -34,7 +32,7 @@
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
|
||||
else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(M.client) M << "<b>[src]</b> transmits, \"[message]\""
|
||||
return 1
|
||||
return ..(message, 0)
|
||||
@@ -14,8 +14,6 @@
|
||||
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 (stat)
|
||||
return
|
||||
if(!(message))
|
||||
|
||||
@@ -275,29 +275,21 @@
|
||||
// if (src.oxygen) src.oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]"
|
||||
// if (src.fire) src.fire.icon_state = "fire[src.fire_alert ? 1 : 0]"
|
||||
|
||||
client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired)
|
||||
|
||||
if ((src.blind && src.stat != 2))
|
||||
if(src.blinded)
|
||||
src.blind.layer = 18
|
||||
if(stat != 2)
|
||||
if(blinded)
|
||||
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
||||
else
|
||||
src.blind.layer = 0
|
||||
if (src.disabilities & NEARSIGHTED)
|
||||
src.client.screen += global_hud.vimpaired
|
||||
clear_fullscreen("blind")
|
||||
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /obj/screen/fullscreen/impaired, 1)
|
||||
set_fullscreen(eye_blurry, "blurry", /obj/screen/fullscreen/blurry)
|
||||
set_fullscreen(druggy, "high", /obj/screen/fullscreen/high)
|
||||
|
||||
if (src.eye_blurry)
|
||||
src.client.screen += global_hud.blurry
|
||||
|
||||
if (src.druggy)
|
||||
src.client.screen += global_hud.druggy
|
||||
|
||||
if (src.stat != 2)
|
||||
if (src.machine)
|
||||
if (src.machine.check_eye(src) < 0)
|
||||
src.reset_view(null)
|
||||
else
|
||||
if(client && !client.adminobs)
|
||||
reset_view(null)
|
||||
if (src.machine)
|
||||
if (src.machine.check_eye(src) < 0)
|
||||
src.reset_view(null)
|
||||
else
|
||||
if(client && !client.adminobs)
|
||||
reset_view(null)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -28,10 +28,9 @@
|
||||
user << "You activate the analyzer's microlaser, analyzing \the [loaded_item] and breaking it down."
|
||||
flick("portable_analyzer_scan", src)
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
|
||||
var/list/temp_tech = ConvertReqString2List(loaded_item.origin_tech)
|
||||
for(var/T in temp_tech)
|
||||
files.UpdateTech(T, temp_tech[T])
|
||||
user << "\The [loaded_item] had level [temp_tech[T]] in [T]."
|
||||
for(var/T in loaded_item.origin_tech)
|
||||
files.UpdateTech(T, loaded_item.origin_tech[T])
|
||||
user << "\The [loaded_item] had level [loaded_item.origin_tech[T]] in [CallTechName(T)]."
|
||||
loaded_item = null
|
||||
for(var/obj/I in contents)
|
||||
for(var/mob/M in I.contents)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user