Merge remote-tracking branch 'upstream/master' into fix-cqc

# Conflicts:
#	code/game/objects/items.dm
This commit is contained in:
Fox McCloud
2019-04-07 19:54:14 -04:00
1409 changed files with 1712308 additions and 63928 deletions
+2 -5
View File
@@ -3,7 +3,8 @@
/mob/camera
name = "camera mob"
density = 0
anchored = 1
move_force = INFINITY
move_resist = INFINITY
status_flags = GODMODE // You can't damage it.
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
see_in_dark = 7
@@ -13,7 +14,3 @@
/mob/camera/experience_pressure_difference()
return
/mob/camera/Login()
..()
update_interface()
+3
View File
@@ -3,3 +3,6 @@
/mob/dead/gib() //ghosts can't be gibbed.
return
/mob/dead
move_resist = INFINITY
-2
View File
@@ -7,5 +7,3 @@
if(GLOB.non_respawnable_keys[ckey])
can_reenter_corpse = 0
GLOB.respawnable_list -= src
update_interface()
+51 -24
View File
@@ -13,7 +13,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
density = 0
canmove = 0
alpha = 127
anchored = 1 // don't get pushed around
move_resist = INFINITY // don't get pushed around
invisibility = INVISIBILITY_OBSERVER
var/can_reenter_corpse
var/bootime = 0
@@ -25,7 +25,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/ghostvision = 1 //is the ghost able to see things humans can't?
var/seedarkness = 1
var/data_hud_seen = 0 //this should one of the defines in __DEFINES/hud.dm
var/data_hud_seen = FALSE //this should one of the defines in __DEFINES/hud.dm
/mob/dead/observer/New(var/mob/body=null, var/flags=1)
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
@@ -49,7 +49,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
T = get_turf(body) //Where is the body located?
attack_log = body.attack_log //preserve our attack logs by copying them to our ghost
var/mutable_appearance/MA = copy_appearance(body)
var/mutable_appearance/MA = copy_appearance(body)
if(body.mind && body.mind.name)
MA.name = body.mind.name
else if(body.real_name)
@@ -148,6 +148,8 @@ Works together with spawning an observer, noted above.
/mob/proc/ghostize(var/flags = GHOST_CAN_REENTER)
if(key)
if(player_logged) //if they have disconnected we want to remove their SSD overlay
overlays -= image('icons/effects/effects.dmi', icon_state = "zzz_glow")
if(GLOB.non_respawnable_keys[ckey])
flags &= ~GHOST_CAN_REENTER
var/mob/dead/observer/ghost = new(src, flags) //Transfer safety to observer spawning proc.
@@ -177,30 +179,44 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(P)
if(TOO_EARLY_TO_GHOST)
warningmsg = "It's too early in the shift to enter cryo"
// If it's not too early, we'll skip straight to ghosting out without penalty
else if(suiciding && TOO_EARLY_TO_GHOST)
warningmsg = "You have committed suicide too early in the round"
else if(stat != DEAD)
warningmsg = "You are alive"
if(isAI(src))
warningmsg = "You are a living AI! You should probably use OOC -> Wipe Core instead."
else if(GLOB.non_respawnable_keys[ckey])
warningmsg = "You have lost your right to respawn"
if(!warningmsg)
ghostize(1)
else
if(warningmsg)
var/response
var/alertmsg = "Are you -sure- you want to ghost?\n([warningmsg]. If you ghost now, you probably won't be able to rejoin the round! You can't change your mind, so choose wisely!)"
response = alert(src, alertmsg,"Are you sure you want to ghost?","Stay in body","Ghost")
if(response != "Ghost")
return //didn't want to ghost after-all
StartResting()
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
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
return
if(stat == CONSCIOUS)
if(!is_admin_level(z))
player_ghosted = 1
if(mind && mind.special_role)
message_admins("[key_name_admin(src)] has ghosted while alive, with special_role: [mind.special_role]")
if(warningmsg)
// Not respawnable
var/mob/dead/observer/ghost = ghostize(0) // 0 parameter stops them re-entering their body
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
else
// Respawnable
ghostize(1)
// If mob in morgue tray, update tray
var/obj/structure/morgue/Morgue = locate() in M.loc
if(istype(M.loc, /obj/structure/morgue))
Morgue = M.loc
if(Morgue)
Morgue.update()
// If mob in cryopod, despawn mob
if(P)
if(!P.control_computer)
P.find_control_computer(urgent=1)
@@ -208,7 +224,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
P.despawn_occupant()
return
/mob/dead/observer/Move(NewLoc, direct)
following = null
dir = direct
@@ -235,9 +250,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
..()
/mob/dead/observer/experience_pressure_difference()
return 0
/mob/dead/observer/can_use_hands() return 0
/mob/dead/observer/Stat()
@@ -297,30 +309,43 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/show_me_the_hud(hud_index)
var/datum/atom_hud/H = huds[hud_index]
H.add_hud_to(src)
data_hud_seen = hud_index
/mob/dead/observer/proc/remove_the_hud(hud_index) //remove old huds
var/datum/atom_hud/H = huds[hud_index]
H.remove_hud_from(src)
/mob/dead/observer/verb/toggle_medHUD()
set category = "Ghost"
set name = "Toggle Medic/Sec/DiagHUD"
set desc = "Toggles the medical HUD."
set name = "Toggle Medic/Sec/Diag/All HUDs"
set desc = "Toggles the HUDs."
if(!client)
return
if(data_hud_seen) //remove old huds
var/datum/atom_hud/H = huds[data_hud_seen]
H.remove_hud_from(src)
switch(data_hud_seen) //give new huds
if(0)
if(FALSE)
data_hud_seen = DATA_HUD_SECURITY_ADVANCED
show_me_the_hud(DATA_HUD_SECURITY_ADVANCED)
to_chat(src, "<span class='notice'>Security HUD set.</span>")
if(DATA_HUD_SECURITY_ADVANCED)
data_hud_seen = DATA_HUD_MEDICAL_ADVANCED
remove_the_hud(DATA_HUD_SECURITY_ADVANCED)
show_me_the_hud(DATA_HUD_MEDICAL_ADVANCED)
to_chat(src, "<span class='notice'>Medical HUD set.</span>")
if(DATA_HUD_MEDICAL_ADVANCED)
data_hud_seen = DATA_HUD_DIAGNOSTIC
remove_the_hud(DATA_HUD_MEDICAL_ADVANCED)
show_me_the_hud(DATA_HUD_DIAGNOSTIC)
to_chat(src, "<span class='notice'>Diagnostic HUD set.</span>")
if(DATA_HUD_DIAGNOSTIC)
data_hud_seen = 0
data_hud_seen = data_hud_seen + DATA_HUD_SECURITY_ADVANCED + DATA_HUD_MEDICAL_ADVANCED
show_me_the_hud(DATA_HUD_SECURITY_ADVANCED)
show_me_the_hud(DATA_HUD_MEDICAL_ADVANCED)
to_chat(src, "<span class='notice'>All HUDs enabled.</span>")
else
data_hud_seen = FALSE
remove_the_hud(DATA_HUD_DIAGNOSTIC)
remove_the_hud(DATA_HUD_SECURITY_ADVANCED)
remove_the_hud(DATA_HUD_MEDICAL_ADVANCED)
to_chat(src, "<span class='notice'>HUDs disabled.</span>")
@@ -702,10 +727,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else
new_char.key = key
/mob/dead/observer/is_literate()
return TRUE
/mob/dead/observer/proc/open_spawners_menu()
set name = "Mob spawners menu"
set desc = "See all currently available ghost spawners"
set category = "Ghost"
var/datum/spawners_menu/menu = new /datum/spawners_menu(src)
menu.ui_interact(src)
+1 -1
View File
@@ -38,7 +38,7 @@
. = src.emote_dead(message)
/mob/dead/observer/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
/mob/dead/observer/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
return "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])"
/mob/dead/observer/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear)
+11
View File
@@ -10,3 +10,14 @@
/mob/proc/death(gibbed)
return FALSE
/mob/proc/dust_animation()
var/atom/movable/overlay/animation = null
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
// flick("dust-m", animation)
new /obj/effect/decal/cleanable/ash(loc)
QDEL_IN(animation, 15)
+93 -94
View File
@@ -1,6 +1,53 @@
// At minimum every mob has a hear_say proc.
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
/mob/proc/combine_message(var/list/message_pieces, var/verb, var/mob/speaker, always_stars = FALSE)
var/iteration_count = 0
var/msg = "" // This is to make sure that the pieces have actually added something
. = "[verb], \""
for(var/datum/multilingual_say_piece/SP in message_pieces)
iteration_count++
var/piece = SP.message
if(piece == "")
continue
if(SP.speaking && SP.speaking.flags & INNATE) // Fucking snowflake noise lang
return SP.speaking.format_message(piece)
if(iteration_count == 1)
piece = capitalize(piece)
if(SP.speaking)
if(!say_understands(speaker, SP.speaking))
if(isanimal(speaker))
var/mob/living/simple_animal/S = speaker
if(LAZYLEN(S.speak))
piece = pick(S.speak)
else
piece = stars(piece)
else
piece = SP.speaking.scramble(piece)
if(always_stars)
piece = stars(piece)
piece = SP.speaking.format_message(piece)
else
if(!say_understands(speaker, null))
piece = stars(piece)
if(isanimal(speaker))
var/mob/living/simple_animal/S = speaker
if(LAZYLEN(S.speak))
piece = pick(S.speak)
if(always_stars)
piece = stars(piece)
piece = "<span class='message'><span class='body'>[piece]</span></span>"
msg += (piece + " ")
if(msg == "")
// There is literally no content left in this message, we need to shut this shit down
. = "" // hear_say will suppress it
else
. = trim(. + trim(msg))
. += "\""
/mob/proc/hear_say(var/list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(!client)
return 0
@@ -23,35 +70,18 @@
sound_vol *= 0.5
if(sleeping || stat == UNCONSCIOUS)
hear_sleep(message)
hear_sleep(multilingual_to_message(message_pieces))
return 0
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
if(language && (language.flags & NONVERBAL))
if(!has_vision(information_only = TRUE)) //blind people can't see dumbass
message = stars(message)
if(!speaker || !(speaker in view(src)))
message = stars(message)
if(!say_understands(speaker, language))
if(isanimal(speaker))
var/mob/living/simple_animal/S = speaker
if(S.speak.len)
message = pick(S.speak)
else
message = stars(message)
else
if(language)
message = language.scramble(message)
else
message = stars(message)
var/speaker_name = speaker.name
if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
var/message = combine_message(message_pieces, verb, speaker)
if(message == "")
return
if(italics)
message = "<i>[message]</i>"
@@ -66,74 +96,47 @@
message = "<b>[message]</b>"
if(!can_hear())
if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set
if(speaker == src)
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
else
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
else
if(language)
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][language.format_message(message, verb)]</span>")
// INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set
// if(!language || !(language.flags & INNATE))
if(speaker == src)
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
else
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
else
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][message]</span>")
if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
src.playsound_local(source, speech_sound, sound_vol, 1)
/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 = "", var/atom/follow_target)
/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
if(!client)
return
if(sleeping || stat == UNCONSCIOUS) //If unconscious or sleeping
hear_sleep(message)
hear_sleep(multilingual_to_message(message_pieces))
return
var/message = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear)
if(message == "")
return
var/track = null
if(!follow_target)
follow_target = speaker
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
if(language && (language.flags & NONVERBAL))
if(!has_vision(information_only=TRUE)) //blind people can't see dumbass
message = stars(message)
if(!speaker || !(speaker in view(src)))
message = stars(message)
if(!say_understands(speaker, language))
if(isanimal(speaker))
var/mob/living/simple_animal/S = speaker
if(S.speak && S.speak.len)
message = pick(S.speak)
else
return
else
if(language)
message = language.scramble(message)
else
message = stars(message)
if(hard_to_hear)
message = stars(message)
var/speaker_name = handle_speaker_name(speaker, vname, hard_to_hear)
track = handle_track(message, verb, language, speaker, speaker_name, follow_target, hard_to_hear)
track = handle_track(message, verb, speaker, speaker_name, follow_target, hard_to_hear)
var/formatted
if(language)
formatted = language.format_message_radio(message, verb)
else
formatted = "[verb], <span class=\"body\">\"[message]\"</span>"
if(!can_hear())
if(prob(20))
to_chat(src, "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>")
else if(track)
to_chat(src, "[part_a][track][part_b][formatted]</span></span>")
to_chat(src, "[part_a][track][part_b][message]</span></span>")
else
to_chat(src, "[part_a][speaker_name][part_b][formatted]</span></span>")
to_chat(src, "[part_a][speaker_name][part_b][message]</span></span>")
/mob/proc/handle_speaker_name(var/mob/speaker = null, var/vname, var/hard_to_hear)
/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
var/speaker_name = "unknown"
if(speaker)
speaker_name = speaker.name
@@ -146,40 +149,36 @@
return speaker_name
/mob/proc/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
return
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
if(!client)
return
if(say_understands(speaker, language))
message = "<B>[src]</B> [verb], \"[message]\""
else
message = "<B>[src]</B> [verb]."
if(src.status_flags & PASSEMOTES)
for(var/obj/item/holder/H in src.contents)
H.show_message(message)
for(var/mob/living/M in src.contents)
M.show_message(message)
src.show_message(message)
/mob/proc/hear_sleep(var/message)
/mob/proc/hear_sleep(message)
var/heard = ""
if(prob(15))
message = strip_html_properly(message)
var/list/punctuation = list(",", "!", ".", ";", "?")
var/list/messages = splittext(message, " ")
var/R = rand(1, messages.len)
var/heardword = messages[R]
if(copytext(heardword,1, 1) in punctuation)
heardword = copytext(heardword,2)
if(copytext(heardword,-1) in punctuation)
heardword = copytext(heardword,1,lentext(heardword))
heard = "<span class = 'game_say'>...You hear something about...[heardword]</span>"
if(messages.len > 0)
var/R = rand(1, messages.len)
var/heardword = messages[R]
if(copytext(heardword,1, 1) in punctuation)
heardword = copytext(heardword,2)
if(copytext(heardword,-1) in punctuation)
heardword = copytext(heardword,1,lentext(heardword))
heard = "<span class='game say'>...<i>You hear something about<i>... '[heardword]'...</span>"
else
heard = "<span class='game say'>...<i>You almost hear something...</i>...</span>"
else
heard = "<span class = 'game_say'>...<i>You almost hear someone talking</i>...</span>"
heard = "<span class='game say'>...<i>You almost hear someone talking</i>...</span>"
to_chat(src, heard)
/mob/proc/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null)
var/message = combine_message(message_pieces, verb, speaker)
var/name = speaker.name
if(!say_understands(speaker))
name = speaker.voice_name
var/rendered = "<span class='game say'><span class='name'>[name]</span> [message]</span>"
to_chat(src, rendered)
+44 -20
View File
@@ -35,7 +35,7 @@
/mob/proc/put_in_l_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!l_hand)
if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = 20 //TODO: move to equipped?
@@ -51,7 +51,7 @@
/mob/proc/put_in_r_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!r_hand)
if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = 20
@@ -153,26 +153,50 @@
//Outdated but still in use apparently. This should at least be a human proc.
/mob/proc/get_equipped_items()
var/list/items = new/list()
//Daily reminder to murder this - Remie.
/mob/proc/get_equipped_items(include_pockets = FALSE)
var/list/items = list()
if(back)
items += back
if(wear_mask)
items += wear_mask
return items
if(hasvar(src,"back")) if(src:back) items += src:back
if(hasvar(src,"belt")) if(src:belt) items += src:belt
if(hasvar(src,"l_ear")) if(src:l_ear) items += src:l_ear
if(hasvar(src,"r_ear")) if(src:r_ear) items += src:r_ear
if(hasvar(src,"glasses")) if(src:glasses) items += src:glasses
if(hasvar(src,"gloves")) if(src:gloves) items += src:gloves
if(hasvar(src,"head")) if(src:head) items += src:head
if(hasvar(src,"shoes")) if(src:shoes) items += src:shoes
if(hasvar(src,"wear_id")) if(src:wear_id) items += src:wear_id
if(hasvar(src,"wear_mask")) if(src:wear_mask) items += src:wear_mask
if(hasvar(src,"wear_suit")) if(src:wear_suit) items += src:wear_suit
// if(hasvar(src,"w_radio")) if(src:w_radio) items += src:w_radio commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN
if(hasvar(src,"w_uniform")) if(src:w_uniform) items += src:w_uniform
//if(hasvar(src,"l_hand")) if(src:l_hand) items += src:l_hand
//if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand
/mob/living/carbon/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
if(wear_suit)
items += wear_suit
if(head)
items += head
return items
/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
if(belt)
items += belt
if(l_ear)
items += l_ear
if(r_ear)
items += r_ear
if(glasses)
items += glasses
if(gloves)
items += gloves
if(shoes)
items += shoes
if(wear_id)
items += wear_id
if(wear_pda)
items += wear_pda
if(w_uniform)
items += w_uniform
if(include_pockets)
if(l_store)
items += l_store
if(r_store)
items += r_store
if(s_store)
items += s_store
return items
/obj/item/proc/equip_to_best_slot(mob/M)
+40 -16
View File
@@ -11,7 +11,6 @@
var/ask_verb = "asks" // Used when sentence ends in a ?
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
var/signlang_verb = list() // 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.
@@ -85,11 +84,11 @@
return scrambled_text
/datum/language/proc/format_message(message, verb)
return "[verb], <span class='message'><span class='[colour]'>\"[capitalize(message)]\"</span></span>"
/datum/language/proc/format_message(message)
return "<span class='message'><span class='[colour]'>[message]</span></span>"
/datum/language/proc/format_message_radio(message, verb)
return "[verb], <span class='[colour]'>\"[capitalize(message)]\"</span>"
/datum/language/proc/format_message_radio(message)
return "<span class='[colour]'>[message]</span>"
/datum/language/proc/get_talkinto_msg_range(message)
// if you yell, you'll be heard from two tiles over instead of one
@@ -103,11 +102,11 @@
if(!speaker_mask)
speaker_mask = speaker.name
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [format_message(message, get_spoken_verb(message))]</span></i>"
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [get_spoken_verb(message)], [format_message(message)]</span></i>"
for(var/mob/player in GLOB.player_list)
if(istype(player,/mob/dead) && follow)
var/msg_dead = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> ([ghost_follow_link(speaker, ghost=player)]) [format_message(message, get_spoken_verb(message))]</span></i>"
var/msg_dead = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> ([ghost_follow_link(speaker, ghost=player)]) [get_spoken_verb(message)], [format_message(message)]</span></i>"
to_chat(player, msg_dead)
continue
@@ -135,10 +134,10 @@
key = ""
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER
/datum/language/noise/format_message(message, verb)
/datum/language/noise/format_message(message)
return "<span class='message'><span class='[colour]'>[message]</span></span>"
/datum/language/noise/format_message_radio(message, verb)
/datum/language/noise/format_message_radio(message)
return "<span class='[colour]'>[message]</span>"
/datum/language/noise/get_talkinto_msg_range(message)
@@ -247,8 +246,8 @@
syllables = list("hs","zt","kr","st","sh")
/datum/language/diona/get_random_name()
var/new_name = "[pick(list("To Sleep Beneath", "Wind Over", "Embrace of", "Dreams of", "Witnessing", "To Walk Beneath", "Approaching the", "Glimmer of", "The Ripple of", "Colors of", "The Still of", "Silence of", "Gentle Breeze of", "Glistening Waters under", "Child of", "Blessed Plant-ling of", "Grass-Walker of", "Element of", "Spawn of"))]"
new_name += " [pick(list("the Void", "the Sky", "Encroaching Night", "Planetsong", "Starsong", "the Wandering Star", "the Empty Day", "Daybreak", "Nightfall", "the Rain", "the Stars", "the Waves", "Dusk", "Night", "the Wind", "the Summer Wind", "the Blazing Sun", "the Scorching Sun", "Eternal Fields", "the Soothing Plains", "the Undying Fiona", "Mother Nature's Bousum"))]"
var/new_name = "[pick(list("To Sleep Beneath", "Wind Over", "Embrace Of", "Dreams Of", "Witnessing", "To Walk Beneath", "Approaching The", "Glimmer Of", "The Ripple Of", "Colors Of", "The Still Of", "Silence Of", "Gentle Breeze Of", "Glistening Waters Under", "Child Of", "Blessed Plant-Ling Of", "Grass-Walker Of", "Element Of", "Spawn Of"))]"
new_name += " [pick(list("The Void", "The Sky", "Encroaching Night", "Planetsong", "Starsong", "The Wandering Star", "The Empty Day", "Daybreak", "Nightfall", "The Rain", "The Stars", "The Waves", "Dusk", "Night", "The Wind", "The Summer Wind", "The Blazing Sun", "The Scorching Sun", "Eternal Fields", "The Soothing Plains", "The Undying Fiona", "Mother Nature's Bousum"))]"
return new_name
/datum/language/trinary
@@ -415,7 +414,7 @@
exclaim_verb = "snarls"
colour = "gutter"
key = "3"
syllables = list ("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh", "gra")
syllables = list ("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh","gra")
/datum/language/clown
name = "Clownish"
@@ -427,6 +426,26 @@
key = "0"
syllables = list ("honk","squeak","bonk","toot","narf","zub","wee","wub","norf")
/datum/language/com_srus
name = "Neo-Russkiya"
desc = "Neo-Russkiya, a bastard mix of Gutter, Sol Common, and old Russian. The official language of the USSP. It has started to see use outside of the fringe in hobby circles and protest groups. The linguistic spirit of Sol-Gov criticisms."
speech_verb = "articulates"
whisper_verb = "mutters"
exclaim_verb = "exaggerates"
colour = "com_srus"
key = "?"
space_chance = 65
english_names = 1
syllables = list("dyen","bar","bota","vyek","tvo","slov","slav","syen","doup","vah","laz","gloz","yet",
"nyet","da","sky","glav","glaz","netz","doomat","zat","moch","boz",
"comy","vrad","vrade","tay","bli","ay","nov","livn","tolv","glaz","gliz",
"ouy","zet","yevt","dat","botat","nev","novy","vzy","nov","sho","obsh","dasky",
"key","skey","ovsky","skaya","bib","kiev","studen","var","bul","vyan",
"tzion","vaya","myak","gino","volo","olam","miti","nino","menov","perov",
"odasky","trov","niki","ivano","dostov","sokol","oupa","pervom","schel",
"tizan","chka","tagan","dobry","okt","boda","veta","idi","cyk","blyt","hui","na",
"udi","litchki","casa","linka","toly","anatov","vich","vech","vuch","toi","ka","vod")
/datum/language/wryn
name = "Wryn Hivemind"
desc = "Wryn have the strange ability to commune over a psychic hivemind."
@@ -530,6 +549,13 @@
return TRUE
return FALSE
/datum/language/abductor/golem
name = "Golem Mindlink"
desc = "Communicate with other alien alloy golems through a psychic link."
/datum/language/abductor/golem/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker)
return TRUE
/datum/language/corticalborer
name = "Cortical Link"
desc = "Cortical borers possess a strange link between their tiny minds."
@@ -635,10 +661,9 @@
// Language handling.
/mob/proc/add_language(language)
var/datum/language/new_language = GLOB.all_languages[language]
if(!istype(new_language) || new_language in languages)
if(!istype(new_language) || (new_language in languages))
return FALSE
languages |= new_language
@@ -657,8 +682,7 @@
// Can we speak this language, as opposed to just understanding it?
/mob/proc/can_speak_language(datum/language/speaking)
return (universal_speak || (speaking && speaking.flags & INNATE) || speaking in languages)
return universal_speak || (speaking && speaking.flags & INNATE) || (speaking in languages)
//TBD
/mob/proc/check_lang_data()
+11 -1
View File
@@ -1,4 +1,4 @@
/mob/living/proc/handle_autohiss(message, datum/language/L)
/mob/proc/handle_autohiss(message, datum/language/L)
return message // no autohiss at this level
/mob/living/carbon/human/handle_autohiss(message, datum/language/L)
@@ -58,6 +58,16 @@
)
autohiss_exempt = list("Chittin")
/datum/species/drask
autohiss_basic_map = list(
"o" = list ("oo", "ooo"),
"u" = list ("uu", "uuu")
)
autohiss_extra_map = list(
"m" = list ("mm", "mmm")
)
autohiss_exempt = list("Orluum")
/datum/species/proc/handle_autohiss(message, datum/language/lang, mode)
if(!autohiss_basic_map)
+3 -4
View File
@@ -1,10 +1,9 @@
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
#define HUMAN_MAX_OXYLOSS 3 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
#define HUMAN_CRIT_MAX_OXYLOSS ( (tickerProcess.getLastTickerTimeDuration()) / 3) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 100HP to get through, so (1/3)*last_tick_duration per second. Breaths however only happen every 4 ticks.
//NOTE: Breathing happens once EVERY OTHER TICK.
#define HUMAN_MAX_OXYLOSS 5 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 10 //Amount of damage applied when your body temperature passes the 1000K point
#define HEAT_DAMAGE_LEVEL_3 5 //Amount of damage applied when your body temperature passes the 1000K point
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
@@ -171,11 +171,11 @@
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if((istype(r_hand,/obj/item/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/gun/energy/laser/redtag)))
if((istype(r_hand,/obj/item/gun/energy/laser/tag/red)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/red)))
threatcount += 4
if(lasercolor == "r")
if((istype(r_hand,/obj/item/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/gun/energy/laser/bluetag)))
if((istype(r_hand,/obj/item/gun/energy/laser/tag/blue)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/blue)))
threatcount += 4
return threatcount
+15 -10
View File
@@ -1,4 +1,6 @@
/mob/living/carbon/alien/gib()
if(!death(TRUE) && stat != DEAD)
return FALSE
death(1)
var/atom/movable/overlay/animation = null
notransform = 1
@@ -17,30 +19,33 @@
xgibs(loc)
GLOB.dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
QDEL_IN(src, 15)
return TRUE
/mob/living/carbon/alien/dust()
death(1)
var/atom/movable/overlay/animation = null
if(!death(TRUE) && stat != DEAD)
return FALSE
notransform = 1
canmove = 0
icon = null
invisibility = 101
dust_animation()
new /obj/effect/decal/remains/xeno(loc)
GLOB.dead_mob_list -= src
QDEL_IN(src, 15)
return TRUE
/mob/living/carbon/alien/dust_animation()
var/atom/movable/overlay/animation = null
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("dust-a", animation)
new /obj/effect/decal/remains/xeno(loc)
GLOB.dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
/mob/living/carbon/alien/death(gibbed)
// Only execute the below if we successfully died
@@ -46,13 +46,13 @@
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
SetSilence(0)
else //ALIVE. LIGHTS ARE ON
if(health < config.health_threshold_dead || !get_int_organ(/obj/item/organ/internal/brain))
if(health < HEALTH_THRESHOLD_DEAD && check_death_method() || !get_int_organ(/obj/item/organ/internal/brain))
death()
SetSilence(0)
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > 50) || (config.health_threshold_crit >= health))
if((getOxyLoss() > 50) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
if(health <= 20 && prob(1))
emote("gasp")
if(!reagents.has_reagent("epinephrine"))
@@ -18,7 +18,7 @@
if(stat == DEAD)
//If we mostly took damage from fire
if(fireloss > 125)
if(getFireLoss() > 125)
icon_state = "alien[caste]_husked"
pixel_y = 0
else
@@ -93,6 +93,9 @@
/mob/living/carbon/alien/larva/show_inv(mob/user as mob)
return
/mob/living/carbon/alien/larva/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
return FALSE
/* Commented out because it's duplicated in life.dm
/mob/living/carbon/alien/larva/proc/grow() // Larvae can grow into full fledged Xenos if they survive long enough -- TLE
if(icon_state == "larva_l" && !canmove) // This is a shit death check. It is made of shit and death. Fix later.
@@ -19,7 +19,7 @@
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if( (getOxyLoss() > 25) || (config.health_threshold_crit >= health) )
if((getOxyLoss() > 25) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
//if( health <= 20 && prob(1) )
// spawn(0)
// emote("gasp")
@@ -65,9 +65,9 @@ var/const/MAX_ACTIVE_TIME = 400
return
/obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > 300)
Die()
return
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
+8 -1
View File
@@ -19,10 +19,17 @@
var/obj/item/radio/radio = null // For use with the radio MMI upgrade
var/datum/action/generic/configure_mmi_radio/radio_action = null
// Used for cases when mmi or one of it's children commits suicide.
// Needed to fix a rather insane bug when a posibrain/robotic brain commits suicide
var/dead_icon = "mmi_dead"
/obj/item/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/organ/internal/brain/crystal ))
if(istype(O, /obj/item/organ/internal/brain/crystal))
to_chat(user, "<span class='warning'> This brain is too malformed to be able to use with the [src].</span>")
return
if(istype(O, /obj/item/organ/internal/brain/golem))
to_chat(user, "<span class='warning'>You can't find a way to plug [O] into [src].</span>")
return
if(istype(O,/obj/item/organ/internal/brain) && !brainmob) //Time to stick a brain in it --NEO
var/obj/item/organ/internal/brain/B = O
if(!B.brainmob)
@@ -4,8 +4,9 @@
if(!.)
return FALSE
if(!gibbed && container && istype(container, /obj/item/mmi))//If not gibbed but in a container.
var/obj/item/mmi/mmi = container
visible_message("<span class='danger'>[src]'s MMI flatlines!</span>", "<span class='warning'>You hear something flatline.</span>")
container.icon_state = "mmi_dead"
mmi.icon_state = mmi.dead_icon
/mob/living/carbon/brain/gib()
// can we muster a parent call here?
+1 -1
View File
@@ -32,7 +32,7 @@
. = ..()
if(.)
if(!container && (health < config.health_threshold_dead || ((world.time - timeofhostdeath) > config.revival_brain_life)))
if(!container && (health < HEALTH_THRESHOLD_DEAD && check_death_method() || ((world.time - timeofhostdeath) > config.revival_brain_life)))
death()
return 0
@@ -21,11 +21,16 @@
var/mob/living/carbon/human/imprinted_master = null
var/ejected_flavor_text = "circuit"
dead_icon = "boris_blank"
/obj/item/mmi/robotic_brain/Destroy()
imprinted_master = null
return ..()
/obj/item/mmi/robotic_brain/attack_self(mob/user)
if(isgolem(user))
to_chat(user, "<span class='warning'>Your golem fingers are too large to press the switch on [src].</span>")
return
if(requires_master && !imprinted_master)
to_chat(user, "<span class='notice'>You press your thumb on [src] and imprint your user information.</span>")
imprinted_master = user
@@ -156,7 +161,7 @@
if(jobban_isbanned(O, "Cyborg") || jobban_isbanned(O,"nonhumandept"))
to_chat(O, "<span class='warning'>You are job banned from this role.</span>")
return
to_chat(O., "<span class='notice'>You've been added to the list of ghosts that may become this [src]. Click again to unvolunteer.</span>")
to_chat(O, "<span class='notice'>You've been added to the list of ghosts that may become this [src]. Click again to unvolunteer.</span>")
ghost_volunteers.Add(O)
@@ -228,4 +233,5 @@
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
silenced = TRUE
requires_master = FALSE
ejected_flavor_text = "metal cube"
ejected_flavor_text = "metal cube"
dead_icon = "posibrain"
+4 -4
View File
@@ -29,7 +29,7 @@
to_chat(usr, "<span class='warning'>You cannot speak, as your internal speaker is turned off.</span>")
. = FALSE
/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
/mob/living/carbon/brain/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios)
switch(message_mode)
if("headset")
var/radio_worked = 0 // If any of the radios our brainmob could use functioned, this is set true so that we don't use any others
@@ -39,12 +39,12 @@
if(!radio_worked && c.mecha)
var/obj/mecha/metalgear = c.mecha
if(metalgear.radio)
radio_worked = metalgear.radio.talk_into(src, message, message_mode, verb, speaking)
radio_worked = metalgear.radio.talk_into(src, message_pieces, message_mode, verb)
else if(!radio_worked && c.radio)
radio_worked = c.radio.talk_into(src, message, message_mode, verb, speaking)
radio_worked = c.radio.talk_into(src, message_pieces, message_mode, verb)
return radio_worked
if("whisper")
whisper_say(message, speaking)
whisper_say(message_pieces)
return 1
else return 0
@@ -3,12 +3,12 @@
return
// if(health <= min_health)
if(stat == DEAD)
if(container && health > config.health_threshold_dead)
if(container && health > HEALTH_THRESHOLD_DEAD)
update_revive()
create_debug_log("revived, trigger reason: [reason]")
return
else
if(!container || health <= config.health_threshold_dead)
if(!container || health <= HEALTH_THRESHOLD_DEAD && check_death_method())
// Considered "dead" without any external apparatus
death()
create_debug_log("died, trigger reason: [reason]")
+20 -3
View File
@@ -119,6 +119,9 @@
return 1
/mob/living/carbon/gib()
. = death(1)
if(!.)
return
for(var/obj/item/organ/internal/I in internal_organs)
if(isturf(loc))
I.remove(src)
@@ -130,7 +133,6 @@
src.stomach_contents.Remove(M)
M.forceMove(get_turf(src))
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
. = ..()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0)
if(status_flags & GODMODE) //godmode
@@ -145,6 +147,7 @@
if(reagents.has_reagent("teslium"))
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
take_overall_damage(0,shock_damage, TRUE, used_weapon = "Electrocution")
shock_internal_organs(shock_damage)
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
@@ -206,7 +209,7 @@
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
add_attack_logs(M, src, "Shaked", ATKLOG_ALL)
if(health >= config.health_threshold_crit)
if(health >= HEALTH_THRESHOLD_CRIT)
if(src == M && ishuman(src))
var/mob/living/carbon/human/H = src
visible_message( \
@@ -356,11 +359,15 @@
else
to_chat(src, "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>")
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return 1
else if(damage == 0) // just enough protection
if(prob(20))
to_chat(src, "<span class='notice'>Something bright flashes in the corner of your vision!</span>")
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(0)
/mob/living/carbon/proc/tintcheck()
@@ -435,6 +442,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(!do_after(src, 45, target = src))
return
if(buckled)
to_chat(src, "<span class='warning'>You cannot crawl into a vent while buckled to something!</span>")
return
if(!client)
return
@@ -445,6 +456,8 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
continue
if(istype(I, /obj/item/organ))
continue
if(I.flags & ABSTRACT)
continue
else
failed++
@@ -574,7 +587,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force)
/mob/living/carbon/can_use_hands()
if(handcuffed)
@@ -1108,3 +1121,7 @@ so that different stomachs can handle things in different ways VB*/
if(I.flags_inv & HIDEMASK || forced)
update_inv_wear_mask()
update_inv_head()
/mob/living/carbon/proc/shock_internal_organs(intensity)
for(var/obj/item/organ/O in internal_organs)
O.shock_organ(intensity)
@@ -22,9 +22,8 @@
var/wetlevel = 0 //how wet the mob is
var/failed_last_breath = FALSE //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks.
var/co2overloadtime = null
var/dreaming = 0 //How many dream images we have left to send
var/nightmare = 0
blood_volume = BLOOD_VOLUME_NORMAL
blood_volume = BLOOD_VOLUME_NORMAL
+18 -30
View File
@@ -4,22 +4,15 @@
if(!iscarbon(target)) //something is bypassing the give arguments, no clue what, adding a sanity check JIC
to_chat(usr, "<span class='danger'>Wait a second... \the [target] HAS NO HANDS! AHH!</span>")//cheesy messages ftw
return
if(target.incapacitated() || usr.incapacitated() || target.client == null)
return
if(target.stat == 2 || usr.stat == 2|| target.client == null)
return
var/obj/item/I
if(!usr.hand && usr.r_hand == null)
to_chat(usr, "<span class='warning'> You don't have anything in your right hand to give to [target.name]</span>")
return
if(usr.hand && usr.l_hand == null)
to_chat(usr, "<span class='warning'> You don't have anything in your left hand to give to [target.name]</span>")
return
if(usr.hand)
I = usr.l_hand
else if(!usr.hand)
I = usr.r_hand
var/obj/item/I = get_active_hand()
if(!I)
to_chat(usr, "<span class='warning'> You don't have anything in your hand to give to [target.name]</span>")
return
if((I.flags & NODROP) || (I.flags & ABSTRACT))
to_chat(usr, "<span class='notice'>That's not exactly something you can give.</span>")
@@ -29,35 +22,30 @@
if("Yes")
if(!I)
return
if(target.incapacitated() || usr.incapacitated())
return
if(!Adjacent(target))
to_chat(usr, "<span class='warning'> You need to stay in reaching distance while giving an object.</span>")
to_chat(target, "<span class='warning'> [usr.name] moved too far away.</span>")
return
if((usr.hand && usr.l_hand != I) || (!usr.hand && usr.r_hand != I))
if((I.flags & NODROP) || (I.flags & ABSTRACT))
to_chat(usr, "<span class='warning'>[I] stays stuck to your hand when you try to give it!</span>")
to_chat(target, "<span class='warning'>[I] stays stuck to [usr.name]'s hand when you try to take it!</span>")
return
if(I != get_active_hand())
to_chat(usr, "<span class='warning'> You need to keep the item in your active hand.</span>")
to_chat(target, "<span class='warning'> [usr.name] seem to have given up on giving \the [I.name] to you.</span>")
to_chat(target, "<span class='warning'> [usr.name] seem to have given up on giving [I] to you.</span>")
return
if(target.r_hand != null && target.l_hand != null)
to_chat(target, "<span class='warning'> Your hands are full.</span>")
to_chat(usr, "<span class='warning'> Their hands are full.</span>")
return
else
usr.drop_item()
if(target.r_hand == null)
target.r_hand = I
else
target.l_hand = I
I.loc = target
I.layer = 20
I.plane = HUD_PLANE
usr.unEquip(I)
target.put_in_hands(I)
I.add_fingerprint(target)
src.update_inv_l_hand()
src.update_inv_r_hand()
target.update_inv_l_hand()
target.update_inv_r_hand()
target.visible_message("<span class='notice'> [usr.name] handed \the [I.name] to [target.name].</span>")
target.visible_message("<span class='notice'> [usr.name] handed [I] to [target.name].</span>")
I.on_give(usr, target)
if("No")
target.visible_message("<span class='warning'> [usr.name] tried to hand [I.name] to [target.name] but [target.name] didn't want it.</span>")
target.visible_message("<span class='warning'> [usr.name] tried to hand [I] to [target.name] but [target.name] didn't want it.</span>")
else
to_chat(usr, "<span class='warning'> [target.name]'s hands are full.</span>")
@@ -464,3 +464,12 @@
valid_alt_heads += alternate_head
return valid_alt_heads
/mob/living/carbon/human/proc/scramble_appearance()
scramble(1, src, 100)
real_name = random_name(gender, dna.species.name) //Give them a name that makes sense for their species.
sync_organ_dna(assimilate = 1)
update_body(0)
reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover.
reset_markings() //...Or markings.
dna.ResetUIFrom(src)
+16 -3
View File
@@ -50,11 +50,16 @@
/mob/living/carbon/human/dust()
if(!death(TRUE) && stat != DEAD)
return FALSE
var/atom/movable/overlay/animation = null
notransform = 1
canmove = 0
icon = null
invisibility = 101
dust_animation()
QDEL_IN(src, 15)
return TRUE
/mob/living/carbon/human/dust_animation()
var/atom/movable/overlay/animation = null
animation = new(loc)
animation.icon_state = "blank"
@@ -63,7 +68,6 @@
flick("dust-h", animation)
new dna.species.remains_type(get_turf(src))
QDEL_IN(src, 0)
QDEL_IN(animation, 15)
return TRUE
@@ -88,7 +92,7 @@
return TRUE
/mob/living/carbon/human/death(gibbed)
if(can_die() && !gibbed)
if(can_die() && !gibbed && deathgasp_on_death)
emote("deathgasp") //let the world KNOW WE ARE DEAD
// Only execute the below if we successfully died
@@ -176,3 +180,12 @@
ChangeToHusk()
mutations |= NOCLONE
return
/mob/living/carbon/human/proc/cure_husk()
mutations.Remove(HUSK)
var/obj/item/organ/external/head/H = bodyparts_by_name["head"]
if(istype(H))
H.disfigured = FALSE
update_body(0)
update_mutantrace(0)
UpdateAppearance() // reset hair from DNA
+9 -24
View File
@@ -172,7 +172,7 @@
var/M = handle_emote_param(param)
message = "<B>[src]</B> [M ? "drones at [M]" : "rumbles"]."
playsound(loc, 'sound/voice/DraskTalk.ogg', 50, 0)
playsound(loc, 'sound/voice/drasktalk.ogg', 50, 0)
m_type = 2
if("squish", "squishes")
@@ -680,6 +680,14 @@
message = "<B>[src]</B> trembles."
m_type = 1
if("shudder", "shudders")
message = "<B>[src]</B> shudders."
m_type = 1
if("bshake", "bshakes")
message = "<B>[src]</B> shakes."
m_type = 1
if("sneeze", "sneezes")
if(miming)
message = "<B>[src]</B> sneezes."
@@ -832,11 +840,7 @@
message = "<span class='danger'><b>[src]</b> snaps [p_their()] fingers right off!</span>"
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
// Needed for M_TOXIC_FART
if("fart", "farts")
if(reagents.has_reagent("simethicone"))
return
// playsound(loc, 'sound/effects/fart.ogg', 50, 1, -3) //Admins still vote no to fun
if(locate(/obj/item/storage/bible) in get_turf(src))
to_chat(viewers(src), "<span class='danger'>[src] farts on the Bible!</span>")
var/image/cross = image('icons/obj/storage.dmi', "bible")
@@ -844,29 +848,10 @@
for(var/client/X in GLOB.admins)
if(check_rights(R_EVENT, 0, X.mob))
to_chat(X, adminbfmessage)
else if(TOXIC_FARTS in mutations)
message = "<b>[src]</b> unleashes a [pick("horrible", "terrible", "foul", "disgusting", "awful")] fart."
else if(SUPER_FART in mutations)
message = "<b>[src]</b> unleashes a [pick("loud", "deafening")] fart."
else
message = "<b>[src]</b> [pick("passes wind", "farts")]."
m_type = 2
var/turf/location = get_turf(src)
// Process toxic farts first.
if(TOXIC_FARTS in mutations)
for(var/mob/living/carbon/C in range(location, 2))
if(C.internal != null && C.wear_mask && (C.wear_mask.flags & AIRTIGHT))
continue
if(C == src)
continue
C.reagents.add_reagent("jenkem", 1)
// Farting as a form of locomotion in space
if(SUPER_FART in mutations)
newtonian_move(dir)
if("hem")
message = "<b>[src]</b> hems."
@@ -363,8 +363,8 @@
for(var/datum/data/record/R in data_core.security)
if(R.fields["id"] == E.fields["id"])
criminal = R.fields["criminal"]
msg += "<span class = 'deptradio'>Criminal status:</span> <a href='?src=[UID()];criminal=1'>\[[criminal]\]</a>\n"
var/criminal_status = hasHUD(user, "read_only_security") ? "\[[criminal]\]" : "<a href='?src=[UID()];criminal=1'>\[[criminal]\]</a>"
msg += "<span class = 'deptradio'>Criminal status:</span> [criminal_status]\n"
msg += "<span class = 'deptradio'>Security records:</span> <a href='?src=[UID()];secrecord=`'>\[View\]</a> <a href='?src=[UID()];secrecordadd=`'>\[Add comment\]</a>\n"
if(hasHUD(user,"medical"))
@@ -408,7 +408,12 @@
var/obj/item/organ/internal/cyberimp/eyes/hud/CIH = H.get_int_organ(/obj/item/organ/internal/cyberimp/eyes/hud)
switch(hudtype)
if("security")
return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.glasses, /obj/item/clothing/glasses/hud/security/sunglasses) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/security)
return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/security)
if("read_only_security")
var/obj/item/clothing/glasses/hud/security/S
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security))
S = H.glasses
return !istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/security) && S && S.read_only
if("medical")
return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.glasses, /obj/item/clothing/glasses/hud/health/health_advanced) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical)
else
+84 -18
View File
@@ -4,6 +4,7 @@
voice_name = "unknown"
icon = 'icons/mob/human.dmi'
icon_state = "body_m_s"
deathgasp_on_death = TRUE
var/obj/item/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(loc)
@@ -733,7 +734,7 @@
found_record = 1
if(R.fields["criminal"] == "*Execute*")
to_chat(usr, "<span class='warning'>Unable to modify the sec status of a person with an active Execution order. Use a security computer instead.</span>")
else
else
var/rank
if(ishuman(usr))
var/mob/living/carbon/human/U = usr
@@ -1179,7 +1180,6 @@
restore_all_organs() //Rejuvenate and reset all existing organs.
check_and_regenerate_organs(src) //Regenerate limbs and organs only if they're really missing.
surgeries.Cut() //End all surgeries.
update_revive()
if(!isskeleton(src) && (SKELETON in mutations))
mutations.Remove(SKELETON)
@@ -1567,17 +1567,17 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if(istype(wear_suit, /obj/item/clothing/suit/redtag))
threatcount += 4
if((istype(r_hand,/obj/item/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/gun/energy/laser/redtag)))
if((istype(r_hand,/obj/item/gun/energy/laser/tag/red)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/red)))
threatcount += 4
if(istype(belt, /obj/item/gun/energy/laser/redtag))
if(istype(belt, /obj/item/gun/energy/laser/tag/red))
threatcount += 2
if(lasercolor == "r")
if(istype(wear_suit, /obj/item/clothing/suit/bluetag))
threatcount += 4
if((istype(r_hand,/obj/item/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/gun/energy/laser/bluetag)))
if((istype(r_hand,/obj/item/gun/energy/laser/tag/blue)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/blue)))
threatcount += 4
if(istype(belt, /obj/item/gun/energy/laser/bluetag))
if(istype(belt, /obj/item/gun/energy/laser/tag/blue))
threatcount += 2
return threatcount
@@ -1651,6 +1651,9 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
..()
/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/human/H)
if(H == src)
to_chat(src, "<span class='warning'>You cannot perform CPR on yourself!</span>")
return
if(H.stat == DEAD || (H.status_flags & FAKEDEATH))
to_chat(src, "<span class='warning'>[H.name] is dead!</span>")
return
@@ -1662,25 +1665,29 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
return
if((head && (head.flags_cover & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && !wear_mask.mask_adjusted))
to_chat(src, "<span class='warning'>Remove your mask first!</span>")
return 0
return
if((H.head && (H.head.flags_cover & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags_cover & MASKCOVERSMOUTH) && !H.wear_mask.mask_adjusted))
to_chat(src, "<span class='warning'>Remove [H.p_their()] mask first!</span>")
return 0
visible_message("<span class='danger'>[src] is trying to perform CPR on [H.name]!</span>", \
"<span class='danger'>You try to perform CPR on [H.name]!</span>")
return
if(H.receiving_cpr) // To prevent spam stacking
to_chat(src, "<span class='warning'>They are already receiving CPR!</span>")
return
visible_message("<span class='danger'>[src] is trying to perform CPR on [H.name]!</span>", "<span class='danger'>You try to perform CPR on [H.name]!</span>")
H.receiving_cpr = TRUE
if(do_mob(src, H, 40))
if(H.health > config.health_threshold_dead && H.health <= config.health_threshold_crit)
var/suff = min(H.getOxyLoss(), 7)
H.adjustOxyLoss(-suff)
if(H.health <= HEALTH_THRESHOLD_CRIT)
H.adjustOxyLoss(-15)
H.SetLoseBreath(0)
H.AdjustParalysis(-1)
H.updatehealth("cpr")
visible_message("<span class='danger'>[src] performs CPR on [H.name]!</span>", \
"<span class='notice'>You perform CPR on [H.name].</span>")
visible_message("<span class='danger'>[src] performs CPR on [H.name]!</span>", "<span class='notice'>You perform CPR on [H.name].</span>")
to_chat(H, "<span class='notice'>You feel a breath of fresh air enter your lungs. It feels good.</span>")
to_chat(src, "<span class='alert'>Repeat at least every 7 seconds.")
H.receiving_cpr = FALSE
add_attack_logs(src, H, "CPRed", ATKLOG_ALL)
return 1
return TRUE
else
H.receiving_cpr = FALSE
to_chat(src, "<span class='danger'>You need to stay still while performing CPR!</span>")
/mob/living/carbon/human/canBeHandcuffed()
@@ -1696,7 +1703,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
return FALSE
/mob/living/carbon/human/InCritical()
return (health <= config.health_threshold_crit && stat == UNCONSCIOUS)
return (health <= HEALTH_THRESHOLD_CRIT && stat == UNCONSCIOUS)
/mob/living/carbon/human/IsAdvancedToolUser()
@@ -1942,3 +1949,62 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
/mob/living/carbon/human/proc/special_post_clone_handling()
if(mind && mind.assigned_role == "Cluwne") //HUNKE your suffering never stops
makeCluwne()
/mob/living/carbon/human/proc/influenceSin()
var/datum/objective/sintouched/O
switch(rand(1,7))//traditional seven deadly sins... except lust.
if(1) // acedia
log_game("[src] was influenced by the sin of Acedia.")
O = new /datum/objective/sintouched/acedia
if(2) // Gluttony
log_game("[src] was influenced by the sin of gluttony.")
O = new /datum/objective/sintouched/gluttony
if(3) // Greed
log_game("[src] was influenced by the sin of greed.")
O = new /datum/objective/sintouched/greed
if(4) // sloth
log_game("[src] was influenced by the sin of sloth.")
O = new /datum/objective/sintouched/sloth
if(5) // Wrath
log_game("[src] was influenced by the sin of wrath.")
O = new /datum/objective/sintouched/wrath
if(6) // Envy
log_game("[src] was influenced by the sin of envy.")
O = new /datum/objective/sintouched/envy
if(7) // Pride
log_game("[src] was influenced by the sin of pride.")
O = new /datum/objective/sintouched/pride
ticker.mode.sintouched += src.mind
src.mind.objectives += O
var/obj_count = 1
to_chat(src, "<span class='notice> Your current objectives:")
for(var/datum/objective/objective in src.mind.objectives)
to_chat(src, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
obj_count++
/mob/living/carbon/human/is_literate()
return getBrainLoss() < 100
/mob/living/carbon/human/fakefire(var/fire_icon = "Generic_mob_burning")
if(!overlays_standing[FIRE_LAYER])
overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_icon)
update_icons()
/mob/living/carbon/human/fakefireextinguish()
overlays_standing[FIRE_LAYER] = null
update_icons()
/mob/living/carbon/human/proc/cleanSE() //remove all disabilities/powers
for(var/block = 1; block <= DNA_SE_LENGTH; block++)
dna.SetSEState(block, FALSE, TRUE)
genemutcheck(src, block, null, MUTCHK_FORCED)
dna.UpdateSE()
/mob/living/carbon/human/extinguish_light()
// Parent function handles stuff the human may be holding
..()
var/obj/item/organ/internal/lantern/O = get_int_organ(/obj/item/organ/internal/lantern)
if(O && O.glowing)
O.toggle_biolum(TRUE)
visible_message("<span class='danger'>[src] is engulfed in shadows and fades into the darkness.</span>", "<span class='danger'>A sense of dread washes over you as you suddenly dim dark.</span>")
@@ -15,7 +15,7 @@
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
if(((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD)
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD)
ChangeToHusk()
update_stat("updatehealth([reason])")
med_hud_set_health()
@@ -171,11 +171,17 @@
// Defined here solely to take species flags into account without having to recast at mob/living level.
/mob/living/carbon/human/adjustOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
. = ..()
/mob/living/carbon/human/setOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
. = ..()
@@ -233,7 +239,6 @@
var/obj/item/organ/external/picked = pick(parts)
if(picked.receive_damage(brute, burn, sharp, updating_health))
UpdateDamageIcon()
speech_problem_flag = 1
//Heal MANY external organs, in random order
@@ -256,7 +261,6 @@
if(updating_health)
updatehealth("heal overall damage")
speech_problem_flag = 1
if(update)
UpdateDamageIcon()
@@ -10,7 +10,8 @@ emp_act
/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
if(!dna.species.bullet_act(P, src))
return FALSE
if(P.is_reflectable)
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
@@ -228,6 +229,8 @@ emp_act
send_item_attack_message(I, user, hit_area)
var/weakness = check_weakness(I,user)
if(!I.force)
return 0 //item force is zero
@@ -235,12 +238,11 @@ emp_act
var/weapon_sharp = is_sharp(I)
if(weapon_sharp && prob(getarmor(user.zone_sel.selecting, "melee")))
weapon_sharp = 0
if(armor >= 100)
return 0
var/Iforce = I.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(I.force, I.damtype, affecting, armor, sharp = weapon_sharp, used_weapon = I)
apply_damage(I.force * weakness, I.damtype, affecting, armor, sharp = weapon_sharp, used_weapon = I)
var/bloody = 0
if(I.damtype == BRUTE && I.force && prob(25 + I.force * 2))
@@ -298,6 +300,8 @@ emp_act
if(Iforce > 10 || Iforce >= 5 && prob(33))
forcesay(GLOB.hit_appends) //forcesay checks stat already
dna.species.spec_attacked_by(I, user, affecting, user.a_intent, src)
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
var/obj/item/I
@@ -324,6 +328,8 @@ emp_act
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
hitpush = 0
skipcatch = 1 //can't catch the now embedded item
if(!blocked)
dna.species.spec_hitby(AM, src)
return ..()
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
@@ -476,7 +482,7 @@ emp_act
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
update |= affecting.receive_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
playsound(src, 'sound/items/welder.ogg', 50, 1)
if("tox")
M.mech_toxin_damage(src)
else
@@ -511,3 +517,12 @@ emp_act
return TRUE
if(check_mask && wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH))
return TRUE
/mob/living/carbon/human/proc/reagent_safety_check(hot = TRUE)
if(wear_mask)
to_chat(src, "<span class='danger'>Your [wear_mask.name] protects you from the [hot ? "hot" : "cold"] liquid!</span>")
return FALSE
if(head)
to_chat(src, "<span class='danger'>Your [head.name] protects you from the [hot ? "hot" : "cold"] liquid!</span>")
return FALSE
return TRUE
@@ -42,8 +42,6 @@ var/global/default_martial_art = new/datum/martial_art
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/datum/personal_crafting/handcrafting
var/datum/martial_art/martial_art = null
@@ -66,6 +64,7 @@ var/global/default_martial_art = new/datum/martial_art
var/check_mutations=0 // Check mutations on next life tick
var/heartbeat = 0
var/receiving_cpr = FALSE
var/fire_dmi = 'icons/mob/OnFire.dmi'
var/fire_sprite = "Standing"
@@ -13,6 +13,8 @@
var/obj/item/tank/jetpack/thrust
if(istype(back,/obj/item/tank/jetpack))
thrust = back
else if(istype(s_store,/obj/item/tank/jetpack))
thrust = s_store
else if(istype(back,/obj/item/rig))
var/obj/item/rig/rig = back
for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules)
@@ -85,6 +87,13 @@
if(!(step_count % 2)) //every other turf makes a sound
return 0
if(istype(shoes, /obj/item/clothing/shoes))
var/obj/item/clothing/shoes/shooess = shoes
if(shooess.silence_steps)
return 0 //silent
if(shooess.shoe_sound)
return //Handle it on the shoe
var/range = -(world.view - 2)
if(m_intent == MOVE_INTENT_WALK)
range -= 0.333
@@ -104,11 +113,6 @@
if(!shoes)
volume -= 4
if(istype(shoes, /obj/item/clothing/shoes))
var/obj/item/clothing/shoes/shooess = shoes
if(shooess.silence_steps)
return 0 //silent
if(!has_organ("l_foot") && !has_organ("r_foot"))
return 0 //no feet no footsteps
@@ -580,14 +580,14 @@
return FALSE
saveVoice()
/mob/living/carbon/human/interactive/hear_say(message, verb = "says", datum/language/language = null, italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
/mob/living/carbon/human/interactive/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
if(!istype(speaker, /mob/living/carbon/human/interactive))
knownStrings |= html_decode(message)
knownStrings |= html_decode(multilingual_to_message(message_pieces))
..()
/mob/living/carbon/human/interactive/hear_radio(message, verb = "says", datum/language/language=null, part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
/mob/living/carbon/human/interactive/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target)
if(!istype(speaker, /mob/living/carbon/human/interactive))
knownStrings |= html_decode(message)
knownStrings |= html_decode(multilingual_to_message(message_pieces))
..()
/mob/living/carbon/human/interactive/proc/doProcess()
@@ -321,7 +321,7 @@
if(put_in_active_hand(W)) return 1
else if(put_in_inactive_hand(W)) return 1
else
..()
. = ..()
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
@@ -434,11 +434,11 @@
if(slot_l_hand)
if(l_hand)
return 0
return 1
return !incapacitated()
if(slot_r_hand)
if(r_hand)
return 0
return 1
return !incapacitated()
if(slot_wear_mask)
if(wear_mask)
return 0
+90 -53
View File
@@ -10,10 +10,8 @@
update_mutations()
check_mutations=0
handle_shock()
handle_pain()
handle_heartbeat()
handle_heartattack()
handle_drunk()
dna.species.handle_life(src)
@@ -39,6 +37,17 @@
if(life_tick == 1)
regenerate_icons() // Make sure the inventory updates
handle_ghosted()
/mob/living/carbon/human/proc/handle_ghosted()
if(player_ghosted > 0 && stat == CONSCIOUS && job && !restrained())
if(key)
player_ghosted = 0
else
player_ghosted++
if(player_ghosted % 150 == 0)
force_cryo_human(src)
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
..()
var/pressure_difference = abs( pressure - ONE_ATMOSPHERE )
@@ -71,7 +80,6 @@
drop_item()
emote("cough")
if(disabilities & TOURETTES)
speech_problem_flag = 1
if((prob(10) && paralysis <= 1))
Stun(10)
switch(rand(1, 3))
@@ -86,12 +94,10 @@
animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y), time = 1)
if(disabilities & NERVOUS)
speech_problem_flag = 1
if(prob(10))
Stuttering(10)
if(getBrainLoss() >= 60 && stat != DEAD)
speech_problem_flag = 1
if(prob(3))
var/list/s1 = list("IM A [pick("PONY","LIZARD","taJaran","kitty","Vulpakin","drASK","BIRDIE","voxxie","race car","combat meCH","SPESSSHIP")] [pick("NEEEEEEIIIIIIIIIGH","sKREEEEEE","MEOW","NYA~","rawr","Barkbark","Hissssss","vROOOOOM","pewpew","choo Choo")]!",
"without oxigen blob don't evoluate?",
@@ -144,21 +150,11 @@
if(3)
emote("drool")
if(getBrainLoss() >= 100 && stat != DEAD) //you lapse into a coma and die without immediate aid; RIP. -Fox
Weaken(20)
AdjustLoseBreath(10)
AdjustSilence(2)
if(getBrainLoss() >= 120 && stat != DEAD) //they died from stupidity--literally. -Fox
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
/mob/living/carbon/human/handle_mutations_and_radiation()
for(var/datum/dna/gene/gene in dna_genes)
if(!gene.block)
continue
if(gene.is_active(src))
speech_problem_flag = 1
gene.OnMobLife(src)
if(!ignore_gene_stability && gene_stability < GENETIC_DAMAGE_STAGE_1)
var/instability = DEFAULT_GENE_STABILITY - gene_stability
@@ -246,12 +242,10 @@
var/obj/item/organ/internal/L = get_organ_slot("lungs")
if(!L || L && (L.status & ORGAN_DEAD))
if(health >= config.health_threshold_crit)
if(health >= HEALTH_THRESHOLD_CRIT)
adjustOxyLoss(HUMAN_MAX_OXYLOSS + 1)
else if(!(NOCRITDAMAGE in dna.species.species_traits))
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
failed_last_breath = TRUE
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
if(dna.species)
var/datum/species/S = dna.species
@@ -274,7 +268,7 @@
// USED IN DEATHWHISPERS
/mob/living/carbon/human/proc/isInCrit()
// Health is in deep shit and we're not already dead
return health <= 0 && stat != 2
return health <= HEALTH_THRESHOLD_CRIT && stat != DEAD
/mob/living/carbon/human/get_breath_from_internal(volume_needed) //making this call the parent would be far too complicated
@@ -741,7 +735,6 @@
stat = UNCONSCIOUS
else if(sleeping)
speech_problem_flag = 1
stat = UNCONSCIOUS
@@ -796,6 +789,70 @@
handle_organs()
if(getBrainLoss() >= 120 || (health + (getOxyLoss() / 2)) <= -500)
visible_message("<span class='alert'><B>[src]</B> goes limp, their facial expression utterly blank.</span>")
death()
return
if(getBrainLoss() >= 100) // braindeath
AdjustLoseBreath(10, bound_lower = 0, bound_upper = 25)
Weaken(30)
if(!check_death_method())
if(health <= HEALTH_THRESHOLD_DEAD)
var/deathchance = min(99, ((getBrainLoss() * -5) + (health + (getOxyLoss() / 2))) * -0.01)
if(prob(deathchance))
death()
return
if(health <= HEALTH_THRESHOLD_CRIT)
if(prob(5))
emote(pick("faint", "collapse", "cry", "moan", "gasp", "shudder", "shiver"))
AdjustStuttering(5, bound_lower = 0, bound_upper = 5)
EyeBlurry(5)
if(prob(7))
AdjustConfused(2)
if(prob(5))
Paralyse(2)
switch(health)
if(-INFINITY to -100)
adjustOxyLoss(1)
if(prob(health * -0.1))
if(ishuman(src))
var/mob/living/carbon/human/H = src
H.set_heartattack(TRUE)
if(prob(health * -0.2))
var/datum/disease/D = new /datum/disease/critical/heart_failure
ForceContractDisease(D)
Paralyse(5)
if(-99 to -80)
adjustOxyLoss(1)
if(prob(4))
to_chat(src, "<span class='userdanger'>Your chest hurts...</span>")
Paralyse(2)
var/datum/disease/D = new /datum/disease/critical/heart_failure
ForceContractDisease(D)
if(-79 to -50)
adjustOxyLoss(1)
if(prob(10))
var/datum/disease/D = new /datum/disease/critical/shock
ForceContractDisease(D)
if(prob(health * -0.08))
var/datum/disease/D = new /datum/disease/critical/heart_failure
ForceContractDisease(D)
if(prob(6))
to_chat(src, "<span class='userdanger'>You feel [pick("horrible pain", "awful", "like shit", "absolutely awful", "like death", "like you are dying", "nothing", "warm", "sweaty", "tingly", "really, really bad", "horrible")]!</span>")
Weaken(3)
if(prob(3))
Paralyse(2)
if(-49 to 0)
adjustOxyLoss(1)
if(prob(3))
var/datum/disease/D = new /datum/disease/critical/shock
ForceContractDisease(D)
if(prob(5))
to_chat(src, "<span class='userdanger'>You feel [pick("terrible", "awful", "like shit", "sick", "numb", "cold", "sweaty", "tingly", "horrible")]!</span>")
Weaken(3)
else //dead
SetSilence(0)
@@ -967,7 +1024,7 @@
return
if(H.is_robotic()) //Handle robotic hearts specially with a wuuuubb. This also applies to machine-people.
if(shock_stage >= 10 || istype(get_turf(src), /turf/space))
if(isinspace())
//PULSE_THREADY - maximum value for pulse, currently it 5.
//High pulse value corresponds to a fast rate of heartbeat.
//Divided by 2, otherwise it is too slow.
@@ -985,7 +1042,7 @@
if(pulse == PULSE_NONE)
return
if(pulse >= PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space))
if(pulse >= PULSE_2FAST || isinspace())
//PULSE_THREADY - maximum value for pulse, currently it 5.
//High pulse value corresponds to a fast rate of heartbeat.
//Divided by 2, otherwise it is too slow.
@@ -1003,31 +1060,8 @@
This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag.
*/
/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(..())
speech_problem_flag = 1
return stunned
/mob/living/carbon/human/handle_stuttering()
if(..())
speech_problem_flag = 1
return stuttering
/mob/living/carbon/human/proc/can_heartattack()
if(NO_BLOOD in dna.species.species_traits)
if((NO_BLOOD in dna.species.species_traits) && !dna.species.forced_heartattack)
return FALSE
if(NO_INTORGANS in dna.species.species_traits)
return FALSE
@@ -1054,16 +1088,19 @@
heart.beating = !status
/mob/living/carbon/human/proc/handle_heartattack()
/mob/living/carbon/human/handle_heartattack()
if(!can_heartattack() || !undergoing_cardiac_arrest() || reagents.has_reagent("corazone"))
return
AdjustLoseBreath(2, bound_lower = 0, bound_upper = 3)
adjustOxyLoss(5)
Paralyse(4)
adjustBruteLoss(2)
if(getOxyLoss())
adjustBrainLoss(3)
else if(prob(10))
adjustBrainLoss(1)
Weaken(5)
AdjustLoseBreath(20, bound_lower = 0, bound_upper = 25)
adjustOxyLoss(20)
// Need this in species.
//#undef HUMAN_MAX_OXYLOSS
//#undef HUMAN_CRIT_MAX_OXYLOSS
//#undef HUMAN_CRIT_MAX_OXYLOSS
@@ -1,4 +1,6 @@
/mob/living/carbon/human/Login()
if(player_logged)
overlays -= image('icons/effects/effects.dmi', icon_state = "zzz_glow")
..()
if(dna.species && dna.species.ventcrawler)
@@ -0,0 +1,4 @@
/mob/living/carbon/human/Logout()
..()
if(mind && mind.active && stat != DEAD)
overlays += image('icons/effects/effects.dmi', icon_state = "zzz_glow")
+54 -47
View File
@@ -91,6 +91,9 @@
var/obj/item/organ/internal/L = get_organ_slot("lungs")
if((breathes && !L) || breathes && L && (L.status & ORGAN_DEAD))
return FALSE
if(getOxyLoss() > 10 || losebreath >= 4)
emote("gasp")
return FALSE
if(mind)
return !mind.miming
return TRUE
@@ -107,65 +110,69 @@
/mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice
/mob/living/carbon/human/handle_speech_problems(var/message, var/verb)
var/list/returns[3]
var/speech_problem_flag = 0
/mob/living/carbon/human/handle_speech_problems(list/message_pieces, var/verb)
var/span = ""
var/obj/item/organ/internal/cyberimp/brain/speech_translator/translator = locate(/obj/item/organ/internal/cyberimp/brain/speech_translator) in internal_organs
if(translator)
if(translator.active)
span = translator.speech_span
for(var/datum/multilingual_say_piece/S in message_pieces)
S.message = "<span class='[span]'>[S.message]</span>"
verb = translator.speech_verb
return list("verb" = verb)
if(mind)
span = mind.speech_span
if((COMIC in mutations) \
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
|| istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown) \
|| GetComponent(/datum/component/jestosterone))
span = "sans"
if(silent || (disabilities & MUTE))
message = ""
speech_problem_flag = 1
if(WINGDINGS in mutations)
span = "wingdings"
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
if(hoers.voicechange)
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
verb = pick("whinnies","neighs", "says")
speech_problem_flag = 1
var/list/parent = ..()
verb = parent["verb"]
if(dna)
for(var/datum/dna/gene/gene in dna_genes)
if(!gene.block)
continue
if(gene.is_active(src))
message = gene.OnSay(src,message)
speech_problem_flag = 1
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
if(message != "")
var/list/parent = ..()
message = parent[1]
verb = parent[2]
if(parent[3])
speech_problem_flag = 1
if(silent || (disabilities & MUTE))
S.message = ""
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
if(hoers.voicechange)
S.message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
verb = pick("whinnies", "neighs", "says")
if(dna)
for(var/datum/dna/gene/gene in dna_genes)
if(!gene.block)
continue
if(gene.is_active(src))
S.message = gene.OnSay(src, S.message)
var/braindam = getBrainLoss()
if(braindam >= 60)
speech_problem_flag = 1
if(prob(braindam/4))
message = stutter(message)
if(prob(braindam / 4))
S.message = stutter(S.message)
verb = "gibbers"
if(prob(braindam))
message = uppertext(message)
S.message = uppertext(S.message)
verb = "yells loudly"
if((COMIC in mutations) || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) || istype(get_item_by_slot(slot_wear_mask), /obj/item/clothing/mask/gas/voice/clown))
span = "sans"
if(span)
S.message = "<span class='[span]'>[S.message]</span>"
return list("verb" = verb)
if(span)
message = "<span class='[span]'>[message]</span>"
returns[1] = message
returns[2] = verb
returns[3] = speech_problem_flag
return returns
/mob/living/carbon/human/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
/mob/living/carbon/human/handle_message_mode(var/message_mode, list/message_pieces, var/verb, var/used_radios)
switch(message_mode)
if("intercom")
for(var/obj/item/radio/intercom/I in view(1, src))
spawn(0)
I.talk_into(src, message, null, verb, speaking)
I.talk_into(src, message_pieces, null, verb)
used_radios += I
if("headset")
@@ -173,13 +180,13 @@
if(isradio(l_ear))
R = l_ear
used_radios += R
if(R.talk_into(src, message, null, verb, speaking))
if(R.talk_into(src, message_pieces, null, verb))
return
if(isradio(r_ear))
R = r_ear
used_radios += R
if(R.talk_into(src, message, null, verb, speaking))
if(R.talk_into(src, message_pieces, null, verb))
return
if("right ear")
@@ -190,7 +197,7 @@
R = r_hand
if(R)
used_radios += R
R.talk_into(src, message, null, verb, speaking)
R.talk_into(src, message_pieces, null, verb)
if("left ear")
var/obj/item/radio/R
@@ -200,21 +207,21 @@
R = l_hand
if(R)
used_radios += R
R.talk_into(src, message, null, verb, speaking)
R.talk_into(src, message_pieces, null, verb)
if("whisper")
whisper_say(message, speaking)
whisper_say(message_pieces)
return 1
else
if(message_mode)
if(isradio(l_ear))
used_radios += l_ear
if(l_ear.talk_into(src, message, message_mode, verb, speaking))
if(l_ear.talk_into(src, message_pieces, message_mode, verb))
return
if(isradio(r_ear))
used_radios += r_ear
if(r_ear.talk_into(src, message, message_mode, verb, speaking))
if(r_ear.talk_into(src, message_pieces, message_mode, verb))
return
/mob/living/carbon/human/handle_speech_sound()
@@ -1,75 +0,0 @@
/mob/living/carbon/human/var/traumatic_shock = 0
/mob/living/carbon/human/var/shock_stage = 0
// proc to find out in how much pain the mob is at the moment
/mob/living/carbon/human/proc/updateshock()
traumatic_shock = getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()
// broken or ripped off organs will add quite a bit of pain
for(var/thing in bodyparts)
var/obj/item/organ/external/BP = thing
if(BP.status & ORGAN_BROKEN && !(BP.status & ORGAN_SPLINTED) || BP.open)
traumatic_shock += 15
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
if(R.shock_reduction)
traumatic_shock = max(0, traumatic_shock - R.shock_reduction) // now you too can varedit cyanide to reduce shock by 1000 - Iamgoofball
if(drunk)
traumatic_shock = max(0, traumatic_shock - 10)
return traumatic_shock
/mob/living/carbon/human/proc/handle_shock()
if(status_flags & GODMODE) //godmode
return
if(NO_PAIN in dna.species.species_traits)
return
updateshock()
if(health <= config.health_threshold_softcrit)// health 0 makes you immediately collapse
shock_stage = max(shock_stage, 61)
if(traumatic_shock >= 100)
shock_stage += 1
else
shock_stage = min(shock_stage, 160)
shock_stage = max(shock_stage-1, 0)
return
if(shock_stage == 10)
to_chat(src, "<font color='red'><b>"+pick("It hurts so much!", "You really need some painkillers..", "Dear god, the pain!"))
if(shock_stage >= 30)
if(shock_stage == 30)
custom_emote(1,"is having trouble keeping [p_their()] eyes open.")
EyeBlurry(2)
Stuttering(5)
if(shock_stage == 40)
to_chat(src, "<font color='red'><b>"+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!"))
if(shock_stage >=60)
if(shock_stage == 60)
custom_emote(1,"falls limp.")
if(prob(2))
to_chat(src, "<font color='red'><b>"+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!"))
Weaken(20)
if(shock_stage >= 80)
if(prob(5))
to_chat(src, "<font color='red'><b>"+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!"))
Weaken(20)
if(shock_stage >= 120)
if(prob(2))
to_chat(src, "<font color='red'><b>"+pick("You black out!", "You feel like you could die any moment now.", "You're about to lose consciousness."))
Paralyse(5)
if(shock_stage == 150)
custom_emote(1,"can no longer stand, collapsing!")
Weaken(20)
if(shock_stage >= 150)
Weaken(20)
@@ -91,6 +91,8 @@
var/is_small
var/show_ssd = 1
var/forced_heartattack = FALSE //Some species have blood, but we still want them to have heart attacks
var/dies_at_threshold = FALSE // Do they die or get knocked out at specific thresholds, or do they go through complex crit?
var/can_revive_by_healing // Determines whether or not this species can be revived by simply healing them
var/has_gender = TRUE
var/blacklisted = FALSE
@@ -156,6 +158,9 @@
// Mutant pieces
var/obj/item/organ/internal/ears/mutantears = /obj/item/organ/internal/ears
// Species specific boxes
var/speciesbox
/datum/species/New()
//If the species has eyes, they are the default vision organ
if(!vision_organ && has_organ["eyes"])
@@ -199,7 +204,8 @@
if(ears)
qdel(ears)
ears = new mutantears(H)
if(mutantears)
ears = new mutantears(H)
/datum/species/proc/breathe(mob/living/carbon/human/H)
if((NO_BREATHE in species_traits) || (BREATHLESS in H.mutations))
@@ -251,8 +257,6 @@
. += (health_deficiency / 75)
else
. += (health_deficiency / 25)
if(H.shock_stage >= 10)
. += 3
. += 2 * H.stance_damage //damaged/missing feet or legs is slow
if((hungry >= 70) && !flight)
@@ -294,11 +298,8 @@
// (Slime People changing color based on the reagents they consume)
/datum/species/proc/handle_life(mob/living/carbon/human/H)
if((NO_BREATHE in species_traits) || (BREATHLESS in H.mutations))
H.setOxyLoss(0)
H.SetLoseBreath(0)
var/takes_crit_damage = (!(NOCRITDAMAGE in species_traits))
if((H.health <= config.health_threshold_crit) && takes_crit_damage)
if((H.health <= HEALTH_THRESHOLD_CRIT) && takes_crit_damage)
H.adjustBruteLoss(1)
return
@@ -311,7 +312,7 @@
/datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(attacker_style && attacker_style.help_act(user, target))//adminfu only...
return TRUE
if(target.health >= config.health_threshold_crit)
if(target.health >= HEALTH_THRESHOLD_CRIT && !(target.status_flags & FAKEDEATH))
target.help_shake_act(user)
return TRUE
else
@@ -356,6 +357,10 @@
var/datum/unarmed_attack/attack = user.dna.species.unarmed
user.do_attack_animation(target, attack.animation_type)
if(attack.harmless)
playsound(target.loc, attack.attack_sound, 25, 1, -1)
target.visible_message("<span class='danger'>[user] [pick(attack.attack_verb)]ed [target]!</span>")
return FALSE
add_attack_logs(user, target, "Melee attacked with fists", target.ckey ? null : ATKLOG_ALL)
if(!iscarbon(user))
@@ -377,7 +382,6 @@
playsound(target.loc, attack.attack_sound, 25, 1, -1)
target.visible_message("<span class='danger'>[user] [pick(attack.attack_verb)]ed [target]!</span>")
target.apply_damage(damage, BRUTE, affecting, armor_block, sharp = attack.sharp) //moving this back here means Armalis are going to knock you down 70% of the time, but they're pure adminbus anyway.
if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold)
target.visible_message("<span class='danger'>[user] has weakened [target]!</span>", \
@@ -386,6 +390,7 @@
target.forcesay(GLOB.hit_appends)
else if(target.lying)
target.forcesay(GLOB.hit_appends)
SEND_SIGNAL(target, COMSIG_PARENT_ATTACKBY)
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(target.check_block())
@@ -505,6 +510,7 @@
var/miss_sound = 'sound/weapons/punchmiss.ogg'
var/sharp = FALSE
var/animation_type = ATTACK_EFFECT_PUNCH
var/harmless = FALSE //if set to true, attacks won't be admin logged and punches will "hit" for no damage
/datum/unarmed_attack/diona
attack_verb = list("lash", "bludgeon")
@@ -530,7 +536,7 @@
return FALSE
/datum/species/proc/get_perceived_trauma(mob/living/carbon/human/H)
return 100 - ((NO_PAIN in species_traits) ? 0 : H.traumatic_shock) - H.getStaminaLoss()
return H.health - H.getStaminaLoss()
/datum/species/proc/handle_hud_icons(mob/living/carbon/human/H)
if(!H.client)
@@ -705,8 +711,6 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(XRAY in H.mutations)
H.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
H.see_in_dark = max(H.see_in_dark, 8)
H.see_invisible = SEE_INVISIBLE_MINIMUM
if(H.see_override) //Override all
H.see_invisible = H.see_override
@@ -715,6 +719,13 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(abs(temperature - M.bodytemperature) > 10) //If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately
M.bodytemperature = (temperature + M.bodytemperature) * 0.5 //Approximation for gradual heating or cooling
/datum/species/proc/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) //return TRUE if hit, FALSE if stopped/reflected/etc
return TRUE
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
/proc/get_random_species(species_name = FALSE) // Returns a random non black-listed or hazardous species, either as a string or datum
var/static/list/random_species = list()
if(!random_species.len)
@@ -725,3 +736,9 @@ It'll return null if the organ doesn't correspond, so include null checks when u
var/picked_species = pick(random_species)
var/datum/species/selected_species = GLOB.all_species[picked_species]
return species_name ? picked_species : selected_species.type
/datum/species/proc/can_hear(mob/living/carbon/human/H)
. = FALSE
var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears)
if(istype(ears) && !ears.deaf)
. = TRUE
@@ -10,14 +10,13 @@
"heart" = /obj/item/organ/internal/heart,
"liver" = /obj/item/organ/internal/liver,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"brain" = /obj/item/organ/internal/brain/abductor,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/abductor //3 darksight.
)
species_traits = list(NO_BLOOD, NO_BREATHE, VIRUSIMMUNE, NOGUNS, NO_EXAMINE)
oxy_mod = 0
dies_at_threshold = TRUE
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
dietflags = DIET_OMNI
@@ -32,14 +32,14 @@
water and other radiation."
species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN)
dies_at_threshold = TRUE
clothing_flags = HAS_SOCKS
default_hair_colour = "#000000"
has_gender = FALSE
dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary
taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE
skinned_type = /obj/item/stack/sheet/wood
oxy_mod = 0
body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not
blood_color = "#004400"
flesh_color = "#907E4A"
@@ -110,4 +110,4 @@
H.adjustFireLoss(-(light_amount/4))
if(H.nutrition < NUTRITION_LEVEL_STARVING+50)
H.take_overall_damage(10,0)
..()
..()
@@ -6,14 +6,14 @@
language = "Orluum"
eyes = "drask_eyes_s"
speech_sounds = list('sound/voice/DraskTalk.ogg')
speech_sounds = list('sound/voice/drasktalk.ogg')
speech_chance = 20
male_scream_sound = 'sound/voice/DraskTalk2.ogg'
female_scream_sound = 'sound/voice/DraskTalk2.ogg'
male_cough_sounds = 'sound/voice/DraskCough.ogg'
female_cough_sounds = 'sound/voice/DraskCough.ogg'
male_sneeze_sound = 'sound/voice/DraskSneeze.ogg'
female_sneeze_sound = 'sound/voice/DraskSneeze.ogg'
male_scream_sound = 'sound/voice/drasktalk2.ogg'
female_scream_sound = 'sound/voice/drasktalk2.ogg'
male_cough_sounds = 'sound/voice/draskcough.ogg'
female_cough_sounds = 'sound/voice/draskcough.ogg'
male_sneeze_sound = 'sound/voice/drasksneeze.ogg'
female_sneeze_sound = 'sound/voice/drasksneeze.ogg'
burn_mod = 2
//exotic_blood = "cryoxadone"
@@ -35,6 +35,7 @@
species_traits = list(LIPS, IS_WHITELISTED)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT
bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS
has_gender = FALSE
dietflags = DIET_OMNI
cold_level_1 = -1 //Default 260 - Lower is better
@@ -59,4 +60,4 @@
"metabolic strainer" = /obj/item/organ/internal/liver/drask,
"eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight.
"brain" = /obj/item/organ/internal/brain/drask
)
)
@@ -5,9 +5,11 @@
icobase = 'icons/mob/human_races/r_golem.dmi'
deform = 'icons/mob/human_races/r_golem.dmi'
species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE, NOGUNS)
oxy_mod = 0
species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, VIRUSIMMUNE, NOGUNS)
dies_at_threshold = TRUE
brute_mod = 0.45 //55% damage reduction
burn_mod = 0.45
tox_mod = 0.45
dietflags = DIET_OMNI //golems can eat anything because they are magic or something
reagent_tag = PROCESS_ORG
@@ -31,35 +33,672 @@
blood_color = "#515573"
flesh_color = "#137E8F"
skinned_type = /obj/item/stack/sheet/metal
slowdown = 3
siemens_coeff = 0
blacklisted = TRUE // To prevent golem subtypes from overwhelming the odds when random species changes, only the Random Golem type can be chosen
dangerous_existence = TRUE
has_organ = list(
"brain" = /obj/item/organ/internal/brain/golem
"brain" = /obj/item/organ/internal/brain/golem,
"adamantine_resonator" = /obj/item/organ/internal/adamantine_resonator
) //Has standard darksight of 2.
suicide_messages = list(
"is crumbling into dust!",
"is smashing their body apart!")
var/golem_colour = rgb(170, 170, 170)
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
var/random_eligible = TRUE
var/prefix = "Iron"
var/list/special_names = list("Tarkus")
var/human_surname_chance = 3
var/special_name_chance = 5
var/owner //dobby is a free golem
/datum/species/golem/get_random_name()
var/golem_surname = pick(GLOB.golem_names)
// 3% chance that our golem has a human surname, because cultural contamination
if(prob(human_surname_chance))
golem_surname = pick(GLOB.last_names)
else if(special_names && special_names.len && prob(special_name_chance))
golem_surname = pick(special_names)
var/golem_name = "[prefix] [golem_surname]"
return golem_name
/datum/species/golem/on_species_gain(mob/living/carbon/human/H)
..()
if(H.mind)
H.mind.assigned_role = "Golem"
H.mind.special_role = SPECIAL_ROLE_GOLEM
H.real_name = "adamantine golem ([rand(1, 1000)])"
if(owner)
H.mind.special_role = SPECIAL_ROLE_GOLEM
else
H.mind.special_role = SPECIAL_ROLE_FREE_GOLEM
H.real_name = get_random_name()
H.name = H.real_name
H.equip_to_slot_or_del(new /obj/item/clothing/under/golem(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/golem(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/golem(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/golem(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/golem(H), slot_gloves)
H.regenerate_icons()
to_chat(H, info_text)
/datum/species/golem/on_species_loss(mob/living/carbon/human/H)
..()
if(istype(H.w_uniform, /obj/item/clothing/under/golem)) // Doing these if checks here just in case the golem is somehow wearing something other than their golem shell, which should be impossible but you never know.
qdel(H.w_uniform)
if(istype(H.wear_suit, /obj/item/clothing/suit/golem))
qdel(H.wear_suit)
if(istype(H.shoes, /obj/item/clothing/shoes/golem))
qdel(H.shoes)
if(istype(H.wear_mask, /obj/item/clothing/mask/gas/golem))
qdel(H.wear_mask)
if(istype(H.gloves, /obj/item/clothing/gloves/golem))
qdel(H.gloves)
////////Adamantine Golem stuff I dunno where else to put it
//Random Golem
/datum/species/golem/random
name = "Random Golem"
blacklisted = FALSE
dangerous_existence = FALSE
var/static/list/random_golem_types
/datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(!random_golem_types)
random_golem_types = subtypesof(/datum/species/golem) - type
for(var/V in random_golem_types)
var/datum/species/golem/G = V
if(!initial(G.random_eligible))
random_golem_types -= G
var/datum/species/golem/golem_type = pick(random_golem_types)
var/mob/living/carbon/human/H = C
H.set_species(golem_type)
//Golem subtypes
//Leader golems, can resonate to communicate with all other golems
/datum/species/golem/adamantine
name = "Adamantine Golem"
skinned_type = /obj/item/stack/sheet/mineral/adamantine
has_organ = list(
"brain" = /obj/item/organ/internal/brain/golem,
"adamantine_resonator" = /obj/item/organ/internal/adamantine_resonator,
"vocal_cords" = /obj/item/organ/internal/vocal_cords/adamantine
)
golem_colour = rgb(68, 238, 221)
info_text = "As an <span class='danger'>Adamantine Golem</span>, you possess special vocal cords allowing you to \"resonate\" messages to all golems."
prefix = "Adamantine"
special_names = null
//The suicide bombers of golemkind
/datum/species/golem/plasma
name = "Plasma Golem"
skinned_type = /obj/item/stack/ore/plasma
golem_colour = rgb(170, 51, 221)
heat_level_1 = 360
heat_level_2 = 400
heat_level_3 = 460
info_text = "As a <span class='danger'>Plasma Golem</span>, you burn easily. Be careful, if you get hot enough while burning, you'll blow up!"
heatmod = 0 //fine until they blow up
prefix = "Plasma"
special_names = list("Flood", "Fire", "Bar", "Man")
var/boom_warning = FALSE
var/datum/action/innate/ignite/ignite
/datum/species/golem/plasma/handle_life(mob/living/carbon/human/H)
if(H.bodytemperature > 750)
if(!boom_warning && H.on_fire)
to_chat(H, "<span class='userdanger'>You feel like you could blow up at any moment!</span>")
boom_warning = TRUE
else
if(boom_warning)
to_chat(H, "<span class='notice'>You feel more stable.</span>")
boom_warning = FALSE
if(H.bodytemperature > 850 && H.on_fire && prob(25))
explosion(get_turf(H), 1, 2, 4, flame_range = 5)
msg_admin_attack("Plasma Golem ([H.name]) exploded with radius 1, 2, 4 (flame_range: 5) at ([H.x],[H.y],[H.z]). User Ckey: [key_name_admin(H)]", ATKLOG_FEW)
log_game("Plasma Golem ([H.name]) exploded with radius 1, 2, 4 (flame_range: 5) at ([H.x],[H.y],[H.z]). User Ckey: [key_name_admin(H)]", ATKLOG_FEW)
if(H)
H.gib()
if(H.fire_stacks < 2) //flammable
H.adjust_fire_stacks(1)
..()
/datum/species/golem/plasma/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
ignite = new
ignite.Grant(C)
/datum/species/golem/plasma/on_species_loss(mob/living/carbon/C)
if(ignite)
ignite.Remove(C)
..()
/datum/action/innate/ignite
name = "Ignite"
desc = "Set yourself aflame, bringing yourself closer to exploding!"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "sacredflame"
/datum/action/innate/ignite/Activate()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.fire_stacks)
to_chat(owner, "<span class='notice'>You ignite yourself!</span>")
else
to_chat(owner, "<span class='warning'>You try to ignite yourself, but fail!</span>")
H.IgniteMob() //firestacks are already there passively
//Harder to hurt
/datum/species/golem/diamond
name = "Diamond Golem"
golem_colour = rgb(0, 255, 255)
brute_mod = 0.3 //70% damage reduction up from 55%
burn_mod = 0.3
tox_mod = 0.3
skinned_type = /obj/item/stack/ore/diamond
info_text = "As a <span class='danger'>Diamond Golem</span>, you are more resistant than the average golem."
prefix = "Diamond"
special_names = list("Back")
//Faster but softer and less armoured
/datum/species/golem/gold
name = "Gold Golem"
golem_colour = rgb(204, 204, 0)
slowdown = 2
brute_mod = 0.75 //25% damage reduction down from 55%
burn_mod = 0.75
tox_mod = 0.75
skinned_type = /obj/item/stack/ore/gold
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
prefix = "Golden"
special_names = list("Boy")
//Heavier, thus higher chance of stunning when punching
/datum/species/golem/silver
name = "Silver Golem"
golem_colour = rgb(221, 221, 221)
punchstunthreshold = 9 //60% chance, from 40%
skinned_type = /obj/item/stack/ore/silver
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks have a higher chance of stunning."
prefix = "Silver"
special_names = list("Surfer", "Chariot", "Lining")
//Harder to stun, deals more damage, but it's even slower
/datum/species/golem/plasteel
name = "Plasteel Golem"
golem_colour = rgb(187, 187, 187)
stun_mod = 0.4
punchdamagelow = 12
punchdamagehigh = 21
punchstunthreshold = 18 //still 40% stun chance
slowdown = 5 //diona speed
skinned_type = /obj/item/stack/ore/iron
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
prefix = "Plasteel"
special_names = null
unarmed_type = /datum/unarmed_attack/golem/plasteel
/datum/unarmed_attack/golem/plasteel
attack_verb = list("smash")
attack_sound = 'sound/effects/meteorimpact.ogg'
//More resistant to burn damage
//Add ashstorm resistance if we ever port lavaland
/datum/species/golem/titanium
name = "Titanium Golem"
golem_colour = rgb(255, 255, 255)
skinned_type = /obj/item/stack/ore/titanium
info_text = "As a <span class='danger'>Titanium Golem</span>, you are resistant to burn damage."
burn_mod = 0.3
prefix = "Titanium"
special_names = list("Dioxide")
//Even more resistant to burn damage
//Add ashstorm and lava resistance if we ever port lavaland
/datum/species/golem/plastitanium
name = "Plastitanium Golem"
golem_colour = rgb(136, 136, 136)
skinned_type = /obj/item/stack/ore/titanium
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are very resistant to burn damage."
burn_mod = 0.15
prefix = "Plastitanium"
special_names = null
//Fast and regenerates... but can only speak like an abductor
/datum/species/golem/alloy
name = "Alien Alloy Golem"
golem_colour = rgb(51, 51, 51)
skinned_type = /obj/item/stack/sheet/mineral/abductor
language = "Golem Mindlink"
default_language = "Golem Mindlink"
slowdown = 2 //faster
info_text = "As an <span class='danger'>Alloy Golem</span>, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to speak telepathically to other alloy golems."
prefix = "Alien"
special_names = list("Outsider", "Technology", "Watcher", "Stranger") //ominous and unknown
//Regenerates because self-repairing super-advanced alien tech
/datum/species/golem/alloy/handle_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
H.adjustBruteLoss(-2)
H.adjustFireLoss(-2)
H.adjustToxLoss(-2)
H.adjustOxyLoss(-2)
/datum/species/golem/alloy/can_understand(mob/other) //Can understand everyone, but they can only speak over their mindlink
return TRUE
/datum/species/golem/alloy/on_species_gain(mob/living/carbon/human/H)
..()
H.languages.Cut()
H.add_language("Golem Mindlink")
//Regenerates like dionas, less resistant
/datum/species/golem/wood
name = "Wood Golem"
golem_colour = rgb(158, 112, 75)
skinned_type = /obj/item/stack/sheet/wood
species_traits = list(NO_BREATHE, NO_BLOOD, NO_PAIN, RADIMMUNE, VIRUSIMMUNE, NOGUNS, IS_PLANT)
//Can burn and take damage from heat
brute_mod = 0.7 //30% damage reduction down from 55%
burn_mod = 1
heatmod = 1.5
heat_level_1 = 300
heat_level_2 = 340
heat_level_3 = 400
dietflags = 0 //Regenerate nutrition in light, no diet necessary
taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE
info_text = "As a <span class='danger'>Wooden Golem</span>, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness."
prefix = "Wooden"
special_names = list("Bark", "Willow", "Catalpa", "Oak", "Sap", "Twig", "Branch", "Maple", "Birch", "Elm", "Basswood", "Cottonwood", "Larch", "Aspen", "Ash", "Beech", "Buckeye", "Cedar", "Chestnut", "Cypress", "Fir", "Hawthorn", "Hazel", "Hickory", "Ironwood", "Juniper", "Leaf", "Mangrove", "Palm", "Pawpaw", "Pine", "Poplar", "Redwood", "Redbud", "Sassafras", "Spruce", "Sumac", "Trunk", "Walnut", "Yew")
human_surname_chance = 0
special_name_chance = 100
/datum/species/golem/wood/handle_life(mob/living/carbon/human/H)
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights
H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10)
if(light_amount > 0)
H.clear_alert("nolight")
else
H.throw_alert("nolight", /obj/screen/alert/nolight)
if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal
H.adjustBruteLoss(-(light_amount/2))
H.adjustFireLoss(-(light_amount/4))
if(H.nutrition < NUTRITION_LEVEL_STARVING+50)
H.take_overall_damage(10,0)
..()
//Radioactive
/datum/species/golem/uranium
name = "Uranium Golem"
golem_colour = rgb(119, 255, 0)
skinned_type = /obj/item/stack/ore/uranium
info_text = "As an <span class='danger'>Uranium Golem</span>, you emit radiation. It won't harm fellow golems, but organic lifeforms will be affected."
prefix = "Uranium"
special_names = list("Oxide", "Rod", "Meltdown")
/datum/species/golem/uranium/handle_life(mob/living/carbon/human/H)
for(var/mob/living/L in range(2, H))
if(isgolem(H))
continue
to_chat(L, "<span class='danger'>You are enveloped by a soft green glow emanating from [H].</span>")
L.apply_effect(10, IRRADIATE)
..()
//Ventcrawler
/datum/species/golem/plastic
name = "Plastic Golem"
prefix = "Plastic"
special_names = null
golem_colour = rgb(255, 255, 255)
skinned_type = /obj/item/stack/sheet/plastic
info_text = "As a <span class='danger'>Plastic Golem</span>, you are capable of ventcrawling if you're naked."
/datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.ventcrawler = 1
/datum/species/golem/plastic/on_species_loss(mob/living/carbon/C)
. = ..()
C.ventcrawler = initial(C.ventcrawler)
//Immune to physical bullets and resistant to brute, but very vulnerable to burn damage. Dusts on death.
/datum/species/golem/sand
name = "Sand Golem"
golem_colour = rgb(255, 220, 143)
skinned_type = /obj/item/stack/ore/glass //this is sand
brute_mod = 0.25
burn_mod = 3
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage and energy weapons. You will also turn to sand when dying, preventing any form of recovery."
unarmed_type = /datum/unarmed_attack/golem/sand
prefix = "Sand"
special_names = list("Castle", "Bag", "Dune", "Worm", "Storm")
/datum/species/golem/sand/handle_death(mob/living/carbon/human/H)
H.visible_message("<span class='danger'>[H] turns into a pile of sand!</span>")
for(var/obj/item/W in H)
H.unEquip(W)
for(var/i=1, i <= rand(3, 5), i++)
new /obj/item/stack/ore/glass(get_turf(H))
qdel(H)
/datum/species/golem/sand/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(!(P.original == H && P.firer == H))
if(P.flag == "bullet" || P.flag == "bomb")
playsound(H, 'sound/effects/shovel_dig.ogg', 70, 1)
H.visible_message("<span class='danger'>The [P.name] sinks harmlessly in [H]'s sandy body!</span>", \
"<span class='userdanger'>The [P.name] sinks harmlessly in [H]'s sandy body!</span>")
return FALSE
return TRUE
/datum/unarmed_attack/golem/sand
attack_sound = 'sound/effects/shovel_dig.ogg'
//Reflects lasers and resistant to burn damage, but very vulnerable to brute damage. Shatters on death.
/datum/species/golem/glass
name = "Glass Golem"
golem_colour = rgb(90, 150, 180)
skinned_type = /obj/item/shard
brute_mod = 3 //very fragile
burn_mod = 0.25
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage. However, you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
unarmed_type = /datum/unarmed_attack/golem/glass
prefix = "Glass"
special_names = list("Lens", "Prism", "Fiber", "Bead")
/datum/species/golem/glass/handle_death(mob/living/carbon/human/H)
playsound(H, "shatter", 70, 1)
H.visible_message("<span class='danger'>[H] shatters!</span>")
for(var/obj/item/W in H)
H.unEquip(W)
for(var/i=1, i <= rand(3, 5), i++)
new /obj/item/shard(get_turf(H))
qdel(H)
/datum/species/golem/glass/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(!(P.original == H && P.firer == H)) //self-shots don't reflect
if(P.is_reflectable)
H.visible_message("<span class='danger'>The [P.name] gets reflected by [H]'s glass skin!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [H]'s glass skin!</span>")
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(H)
// redirect the projectile
P.firer = src
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.Angle = null
return FALSE
return TRUE
/datum/unarmed_attack/golem/glass
attack_sound = 'sound/effects/glassbr2.ogg'
//Teleports when hit or when it wants to
/datum/species/golem/bluespace
name = "Bluespace Golem"
golem_colour = rgb(51, 51, 255)
skinned_type = /obj/item/stack/ore/bluespace_crystal
info_text = "As a <span class='danger'>Bluespace Golem</span>, you are spatially unstable: You will teleport when hit, and you can teleport manually at a long distance."
prefix = "Bluespace"
special_names = list("Crystal", "Polycrystal")
unarmed_type = /datum/unarmed_attack/golem/bluespace
var/datum/action/innate/unstable_teleport/unstable_teleport
var/teleport_cooldown = 100
var/last_teleport = 0
var/tele_range = 6
/datum/species/golem/bluespace/proc/reactive_teleport(mob/living/carbon/human/H)
H.visible_message("<span class='warning'>[H] teleports!</span>", "<span class='danger'>You destabilize and teleport!</span>")
var/list/turfs = new/list()
for(var/turf/T in orange(tele_range, H))
if(T.density)
continue
if(T.x>world.maxx-tele_range || T.x<tele_range)
continue
if(T.y>world.maxy-tele_range || T.y<tele_range)
continue
turfs += T
if(!turfs.len)
turfs += pick(/turf in orange(tele_range, H))
var/turf/picked = pick(turfs)
if(!isturf(picked))
return
if(H.buckled)
H.buckled.unbuckle_mob()
do_teleport(H, picked)
return TRUE
/datum/species/golem/bluespace/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
..()
var/obj/item/I
if(istype(AM, /obj/item))
I = AM
if(I.thrownby == H) //No throwing stuff at yourself to trigger the teleport
return 0
else
reactive_teleport(H)
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
..()
if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP)
reactive_teleport(H)
/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_teleport + teleport_cooldown && user != H)
reactive_teleport(H)
/datum/species/golem/bluespace/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(world.time > last_teleport + teleport_cooldown)
reactive_teleport(H)
return TRUE
/datum/species/golem/bluespace/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
unstable_teleport = new
unstable_teleport.Grant(C)
last_teleport = world.time
/datum/species/golem/bluespace/on_species_loss(mob/living/carbon/C)
if(unstable_teleport)
unstable_teleport.Remove(C)
..()
/datum/action/innate/unstable_teleport
name = "Unstable Teleport"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "blink"
icon_icon = 'icons/mob/actions/actions.dmi'
var/activated = FALSE // To prevent spamming
var/cooldown = 150
var/last_teleport = 0
var/tele_range = 6
/datum/action/innate/unstable_teleport/IsAvailable()
if(..())
if(world.time > last_teleport + cooldown && !activated)
return 1
return 0
/datum/action/innate/unstable_teleport/Activate()
activated = TRUE
var/mob/living/carbon/human/H = owner
H.visible_message("<span class='warning'>[H] starts vibrating!</span>", "<span class='danger'>You start charging your bluespace core...</span>")
playsound(get_turf(H), 'sound/weapons/flash.ogg', 25, 1)
addtimer(CALLBACK(src, .proc/teleport, H), 15)
/datum/action/innate/unstable_teleport/proc/teleport(mob/living/carbon/human/H)
activated = FALSE
H.visible_message("<span class='warning'>[H] teleports!</span>", "<span class='danger'>You teleport!</span>")
var/list/turfs = new/list()
for(var/turf/T in orange(tele_range, H))
if(istype(T, /turf/space))
continue
if(T.density)
continue
if(T.x>world.maxx-tele_range || T.x<tele_range)
continue
if(T.y>world.maxy-tele_range || T.y<tele_range)
continue
turfs += T
if(!turfs.len)
turfs += pick(/turf in orange(tele_range, H))
var/turf/picked = pick(turfs)
if(!isturf(picked))
return
if(H.buckled)
H.buckled.unbuckle_mob()
do_teleport(H, picked)
last_teleport = world.time
UpdateButtonIcon() //action icon looks unavailable
sleep(cooldown + 5)
UpdateButtonIcon() //action icon looks available again
/datum/unarmed_attack/golem/bluespace
attack_verb = "bluespace punch"
attack_sound = 'sound/effects/phasein.ogg'
//honk
/datum/species/golem/bananium
name = "Bananium Golem"
golem_colour = rgb(255, 255, 0)
punchdamagelow = 0
punchdamagehigh = 0
punchstunthreshold = 1 //Harmless and can't stun
skinned_type = /obj/item/stack/ore/bananium
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you can barely even hurt people when punching them. Your skin also bleeds banana peels when damaged."
prefix = "Bananium"
special_names = null
unarmed_type = /datum/unarmed_attack/golem/bananium
var/last_honk = 0
var/honkooldown = 0
var/last_banana = 0
var/banana_cooldown = 100
var/active = null
/datum/species/golem/bananium/on_species_gain(mob/living/carbon/human/H)
..()
last_banana = world.time
last_honk = world.time
H.job = "Clown"
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
/datum/species/golem/bananium/get_random_name()
var/clown_name = pick(GLOB.clown_names)
var/golem_name = "[prefix] [clown_name]"
return golem_name
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
..()
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown && user != H)
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(world.time > last_banana + banana_cooldown)
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
return TRUE
/datum/species/golem/bananium/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
..()
var/obj/item/I
if(istype(AM, /obj/item))
I = AM
if(I.thrownby == H) //No throwing stuff at yourself to make bananas
return 0
else
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/handle_life(mob/living/carbon/human/H)
if(!active)
if(world.time > last_honk + honkooldown)
active = 1
playsound(get_turf(H), 'sound/items/bikehorn.ogg', 50, 1)
last_honk = world.time
honkooldown = rand(20, 80)
active = null
..()
/datum/species/golem/bananium/handle_death(mob/living/carbon/human/H)
playsound(get_turf(H), 'sound/misc/sadtrombone.ogg', 70, 0)
/datum/unarmed_attack/golem/bananium
attack_verb = list("HONK")
attack_sound = 'sound/items/airhorn2.ogg'
animation_type = ATTACK_EFFECT_DISARM
harmless = TRUE
//...
/datum/species/golem/tranquillite
name = "Tranquillite Golem"
prefix = "Tranquillite"
special_names = null
golem_colour = rgb(255, 255, 255)
skinned_type = /obj/item/stack/ore/tranquillite
info_text = "As a <span class='danger'>Tranquillite Golem</span>, you are capable of creating invisible walls, and can regenerate by drinking your bottle of Nothing."
unarmed_type = /datum/unarmed_attack/golem/tranquillite
/datum/species/golem/tranquillite/get_random_name()
var/mime_name = pick(GLOB.mime_names)
var/golem_name = "[prefix] [mime_name]"
return golem_name
/datum/species/golem/tranquillite/on_species_gain(mob/living/carbon/human/H)
..()
H.job = "Mime"
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/cane(H), slot_l_hand)
if(H.mind)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null))
H.mind.miming = TRUE
/datum/unarmed_attack/golem/tranquillite
attack_sound = null
miss_sound = null
//Golem abstract items
/obj/item/clothing/under/golem
name = "adamantine skin"
name = "golem skin"
desc = "a golem's skin"
icon_state = "golem"
item_state = "golem"
@@ -69,34 +708,39 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/golem
name = "adamantine shell"
name = "golem shell"
desc = "a golem's thick outter shell"
icon_state = "golem"
item_state = "golem"
body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
flags_inv = HIDEGLOVES|HIDESHOES
flags = ABSTRACT | NODROP | THICKMATERIAL
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.02
body_parts_covered = HEAD | UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
flags_inv = HIDEGLOVES | HIDESHOES
flags = STOPSPRESSUREDMAGE | ABSTRACT | NODROP | THICKMATERIAL
flags_size = ONESIZEFITSALL
armor = list(melee = 55, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
cold_protection = HEAD | UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 0)
/obj/item/clothing/shoes/golem
name = "golem's feet"
desc = "sturdy adamantine feet"
desc = "sturdy golem feet"
icon_state = "golem"
item_state = "golem"
flags = ABSTRACT | NODROP
/obj/item/clothing/mask/gas/golem
name = "golem's face"
desc = "the imposing face of an adamantine golem"
desc = "the imposing face of a golem"
icon_state = "golem"
item_state = "golem"
unacidable = 1
flags = ABSTRACT | NODROP
flags_inv = HIDEEARS | HIDEEYES
/obj/item/clothing/gloves/golem
name = "golem's hands"
desc = "strong adamantine hands"
desc = "strong golem hands"
icon_state = "golem"
item_state = null
flags = ABSTRACT | NODROP
@@ -8,10 +8,10 @@
butt_sprite = "grey"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/grey,
"lungs" = /obj/item/organ/internal/lungs/grey,
"liver" = /obj/item/organ/internal/liver/grey,
"kidneys" = /obj/item/organ/internal/kidneys,
"kidneys" = /obj/item/organ/internal/kidneys/grey,
"brain" = /obj/item/organ/internal/brain/grey,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/grey //5 darksight.
@@ -21,11 +21,11 @@
default_genes = list(REMOTE_TALK)
species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT)
species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT, CAN_WINGDINGS)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_BODY_MARKINGS
dietflags = DIET_HERB
has_gender = FALSE
reagent_tag = PROCESS_ORG
blood_color = "#A200FF"
@@ -33,6 +33,7 @@
..()
H.dna.SetSEState(REMOTETALKBLOCK, !remove, 1)
genemutcheck(H, REMOTETALKBLOCK, null, MUTCHK_FORCED)
H.dna.default_blocks.Add(REMOTETALKBLOCK)
/datum/species/grey/water_act(mob/living/carbon/human/H, volume, temperature, source)
..()
@@ -40,12 +41,24 @@
H.emote("scream")
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
var/speech_pref = H.client.prefs.speciesprefs
if(speech_pref)
H.mind.speech_span = "wingdings"
var/translator_pref = H.client.prefs.speciesprefs
if(translator_pref || ((ismindshielded(H) || J.is_command || J.supervisors == "the captain") && (WINGDINGS in H.mutations)))
if(J.title == "Mime")
return
if(J.title == "Clown")
var/obj/item/organ/internal/cyberimp/brain/speech_translator/clown/implant = new
implant.insert(H)
else
var/obj/item/organ/internal/cyberimp/brain/speech_translator/implant = new
implant.insert(H)
if(!translator_pref)
to_chat(H, "<span class='notice'>A speech translator implant has been installed due to your role on the station.</span>")
/datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
if(R.id == "sacid")
H.reagents.del_reagent(R.id)
return 0
return ..()
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
return FALSE
if(R.id == "water")
H.adjustFireLoss(1)
return TRUE
return ..()
@@ -17,4 +17,5 @@
worlds tumultous at best."
reagent_tag = PROCESS_ORG
//Has standard darksight of 2.
//Has standard darksight of 2.
@@ -20,13 +20,13 @@
butt_sprite = "kidan"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/kidan,
"lungs" = /obj/item/organ/internal/lungs/kidan,
"liver" = /obj/item/organ/internal/liver/kidan,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/kidan,
"brain" = /obj/item/organ/internal/brain/kidan,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2.
"eyes" = /obj/item/organ/internal/eyes/kidan, //Default darksight of 2.
"lantern" = /obj/item/organ/internal/lantern
)
@@ -19,7 +19,6 @@
burn_mod = 2.28 // So they take 50% extra damage from brute/burn overall
tox_mod = 0
clone_mod = 0
oxy_mod = 0
death_message = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off..."
species_traits = list(IS_WHITELISTED, NO_BREATHE, NO_SCAN, NO_INTORGANS, NO_PAIN, NO_DNA, RADIMMUNE, VIRUSIMMUNE, NOTRANSSTING)
@@ -36,6 +35,7 @@
//Default styles for created mobs.
default_hair = "Blue IPC Screen"
dies_at_threshold = TRUE
can_revive_by_healing = 1
has_gender = FALSE
reagent_tag = PROCESS_SYN
@@ -55,6 +55,7 @@
)
vision_organ = /obj/item/organ/internal/eyes/optical_sensor
mutantears = /obj/item/organ/internal/ears/microphone
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/ipc),
"groin" = list("path" = /obj/item/organ/external/groin/ipc),
@@ -108,11 +108,11 @@
tail = "farwatail"
reagent_tag = PROCESS_ORG
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/tajaran,
"lungs" = /obj/item/organ/internal/lungs/tajaran,
"liver" = /obj/item/organ/internal/liver/tajaran,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/tajaran,
"brain" = /obj/item/organ/internal/brain/tajaran,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/tajaran/farwa //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
@@ -132,11 +132,11 @@
tail = "wolpintail"
reagent_tag = PROCESS_ORG
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/vulpkanin,
"lungs" = /obj/item/organ/internal/lungs/vulpkanin,
"liver" = /obj/item/organ/internal/liver/vulpkanin,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/vulpkanin,
"brain" = /obj/item/organ/internal/brain/vulpkanin,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/vulpkanin/wolpin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
@@ -156,6 +156,16 @@
reagent_tag = PROCESS_ORG
tail = null
has_organ = list(
"heart" = /obj/item/organ/internal/heart/skrell,
"lungs" = /obj/item/organ/internal/lungs/skrell,
"liver" = /obj/item/organ/internal/liver/skrell,
"kidneys" = /obj/item/organ/internal/kidneys/skrell,
"brain" = /obj/item/organ/internal/brain/skrell,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/skrell //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
/datum/species/monkey/unathi
name = "Stok"
name_plural = "Stok"
@@ -171,3 +181,13 @@
reagent_tag = PROCESS_ORG
bodyflags = HAS_TAIL
has_organ = list(
"heart" = /obj/item/organ/internal/heart/unathi,
"lungs" = /obj/item/organ/internal/lungs/unathi,
"liver" = /obj/item/organ/internal/liver/unathi,
"kidneys" = /obj/item/organ/internal/kidneys/unathi,
"brain" = /obj/item/organ/internal/brain/unathi,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/unathi
)
@@ -13,8 +13,8 @@
language = "Sol Common"
burn_mod = 4 // holy shite, poor guys wont survive half a second cooking smores
brute_mod = 2 // damn, double wham, double dam
oxy_mod = 0
species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_BLOOD, NO_PAIN, NO_SCAN, RADIMMUNE)
dies_at_threshold = TRUE
dietflags = DIET_OMNI //still human at their core, so they maintain their eating habits and diet
//Default styles for created mobs.
@@ -7,6 +7,7 @@
//language = "Clatter"
species_traits = list(IS_WHITELISTED, NO_BLOOD, NOTRANSSTING)
forced_heartattack = TRUE // Plasmamen have no blood, but they should still get heart-attacks
skinned_type = /obj/item/stack/sheet/mineral/plasma // We're low on plasma, R&D! *eyes plasmaman co-worker intently*
dietflags = DIET_OMNI
reagent_tag = PROCESS_ORG
@@ -30,15 +31,17 @@
"shows their true colors, which happens to be the color of plasma!")
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"heart" = /obj/item/organ/internal/heart/plasmaman,
"lungs" = /obj/item/organ/internal/lungs/plasmaman,
"liver" = /obj/item/organ/internal/liver,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"liver" = /obj/item/organ/internal/liver/plasmaman,
"kidneys" = /obj/item/organ/internal/kidneys/plasmaman,
"brain" = /obj/item/organ/internal/brain/plasmaman,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes
"eyes" = /obj/item/organ/internal/eyes/plasmaman
)
speciesbox = /obj/item/storage/box/survival_plasmaman
/datum/species/plasmaman/say_filter(mob/M, message, datum/language/speaking)
if(copytext(message, 1, 2) != "*")
message = replacetext(message, "s", stutter("ss"))
@@ -89,7 +92,7 @@
if("Magistrate")
suit=/obj/item/clothing/suit/space/eva/plasmaman/magistrate
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/magistrate
if("Head of Security")
if("Head of Security", "Special Operations Officer")
suit=/obj/item/clothing/suit/space/eva/plasmaman/security/hos
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security/hos
if("Captain", "Blueshield")
@@ -98,7 +101,7 @@
if("Head of Personnel")
suit=/obj/item/clothing/suit/space/eva/plasmaman/security/hop
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/security/hop
if("Nanotrasen Representative")
if("Nanotrasen Representative", "Nanotrasen Navy Officer")
suit = /obj/item/clothing/suit/space/eva/plasmaman/nt_rep
helm = /obj/item/clothing/head/helmet/space/eva/plasmaman/nt_rep
if("Medical Doctor","Brig Physician","Virologist")
@@ -146,6 +149,9 @@
if("Mime")
suit=/obj/item/clothing/suit/space/eva/plasmaman/mime
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/mime
if("Syndicate Officer")
suit=/obj/item/clothing/suit/space/eva/plasmaman/nuclear
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear
if((H.mind.special_role == SPECIAL_ROLE_WIZARD) || (H.mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE))
H.equip_to_slot(new /obj/item/clothing/suit/space/eva/plasmaman/wizard(H), slot_wear_suit)
@@ -182,6 +188,6 @@
H.adjustFireLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER)
H.adjustPlasma(20)
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
return 0 //Handling reagent removal on our own. Prevents plasma from dealing toxin damage to Plasmamen.
return FALSE //Handling reagent removal on our own. Prevents plasma from dealing toxin damage to Plasmamen.
return ..()
@@ -18,8 +18,7 @@
)
species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE)
oxy_mod = 0
dies_at_threshold = TRUE
dietflags = DIET_OMNI //the mutation process allowed you to now digest all foods regardless of initial race
reagent_tag = PROCESS_ORG
@@ -11,7 +11,6 @@
species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NOGUNS, NO_EXAMINE) //Can't use guns due to muzzle flash
burn_mod = 1.5 //1.5x burn damage, 2x is excessive
oxy_mod = 0
heatmod = 1.5
silent_steps = 1
@@ -63,7 +62,6 @@
species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NO_EXAMINE)
burn_mod = 1.1
oxy_mod = 0
heatmod = 1.1
/datum/species/shadow/ling/lesser/handle_life(mob/living/carbon/human/H)
@@ -11,10 +11,9 @@
flesh_color = "#E6E6C6"
species_traits = list(NO_BREATHE, NO_BLOOD, RADIMMUNE, VIRUSIMMUNE)
dies_at_threshold = TRUE
skinned_type = /obj/item/stack/sheet/bone
oxy_mod = 0
dietflags = DIET_OMNI
reagent_tag = PROCESS_ORG
@@ -42,7 +41,7 @@
/datum/species/skeleton/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
// Crazylemon is still silly
if(R.id == "milk")
H.heal_overall_damage(4,4)
H.heal_overall_damage(4, 4)
if(prob(5)) // 5% chance per proc to find a random limb, and mend it
var/list/our_organs = H.bodyparts.Copy()
shuffle(our_organs)
@@ -55,7 +54,7 @@
L.perma_injury = 0
break // We're only checking one limb here, bucko
if(prob(3))
H.say(pick("Thanks Mr Skeltal", "Thank for strong bones", "Doot doot!"))
return 1
H.say(pick("Thanks Mr. Skeltal", "Thank for strong bones", "Doot doot!"))
return TRUE
return ..()
@@ -28,13 +28,13 @@
butt_sprite = "skrell"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/skrell,
"lungs" = /obj/item/organ/internal/lungs/skrell,
"liver" = /obj/item/organ/internal/liver/skrell,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/skrell,
"brain" = /obj/item/organ/internal/brain/skrell,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2.
"eyes" = /obj/item/organ/internal/eyes/skrell, //Default darksight of 2.
"headpocket" = /obj/item/organ/internal/headpocket
)
@@ -20,13 +20,13 @@
cold_level_3 = 200
coldmod = 3
oxy_mod = 0
brain_mod = 2.5
male_cough_sounds = list('sound/effects/slime_squish.ogg')
female_cough_sounds = list('sound/effects/slime_squish.ogg')
species_traits = list(LIPS, IS_WHITELISTED, NO_BREATHE, NO_INTORGANS, NO_SCAN)
dies_at_threshold = TRUE
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_SKIN_COLOR | NO_EYES
dietflags = DIET_CARN
@@ -42,6 +42,7 @@
has_organ = list(
"brain" = /obj/item/organ/internal/brain/slime
)
mutantears = null
suicide_messages = list(
"is melting into a puddle!",
@@ -82,6 +83,9 @@
H.update_body()
..()
/datum/species/slime/can_hear() // fucking snowflakes
. = TRUE
/datum/action/innate/slimecolor
name = "Toggle Recolor"
check_flags = AB_CHECK_CONSCIOUS
File diff suppressed because it is too large Load Diff
@@ -30,16 +30,17 @@
dietflags = DIET_OMNI
taste_sensitivity = TASTE_SENSITIVITY_SHARP
reagent_tag = PROCESS_ORG
flesh_color = "#AFA59E"
base_color = "#424242"
butt_sprite = "tajaran"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/tajaran,
"lungs" = /obj/item/organ/internal/lungs/tajaran,
"liver" = /obj/item/organ/internal/liver/tajaran,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/tajaran,
"brain" = /obj/item/organ/internal/brain/tajaran,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2)
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
@@ -38,11 +38,11 @@
brute_mod = 1.05
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/unathi,
"lungs" = /obj/item/organ/internal/lungs/unathi,
"liver" = /obj/item/organ/internal/liver/unathi,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/unathi,
"brain" = /obj/item/organ/internal/brain/unathi,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight.
)
@@ -39,6 +39,7 @@
flesh_color = "#808D11"
//Default styles for created mobs.
default_hair = "Short Vox Quills"
has_gender = FALSE
default_hair_colour = "#614f19" //R: 97, G: 79, B: 25
butt_sprite = "vox"
@@ -61,13 +62,13 @@
)
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"heart" = /obj/item/organ/internal/heart/vox,
"lungs" = /obj/item/organ/internal/lungs/vox,
"liver" = /obj/item/organ/internal/liver/vox,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/vox,
"brain" = /obj/item/organ/internal/brain/vox,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2.
"eyes" = /obj/item/organ/internal/eyes/vox, //Default darksight of 2.
"stack" = /obj/item/organ/internal/stack //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used
) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ.
@@ -78,6 +79,8 @@
"is holding their breath!",
"is deeply inhaling oxygen!")
speciesbox = /obj/item/storage/box/survival_vox
/datum/species/vox/handle_death(mob/living/carbon/human/H)
H.stop_tail_wagging(1)
@@ -170,6 +173,7 @@
eyes = "blank_eyes"
species_traits = list(NO_SCAN, NO_BLOOD, NO_PAIN, IS_WHITELISTED)
dies_at_threshold = TRUE
bodyflags = HAS_TAIL
dietflags = DIET_OMNI //should inherit this from vox, this is here just in case
@@ -199,4 +203,4 @@
"is huffing oxygen!")
/datum/species/vox/armalis/handle_reagents() //Skip the Vox oxygen reagent toxicity. Armalis are above such things.
return TRUE
return TRUE
@@ -22,6 +22,7 @@
hunger_drain = 0.11
taste_sensitivity = TASTE_SENSITIVITY_SHARP
reagent_tag = PROCESS_ORG
flesh_color = "#966464"
base_color = "#CF4D2F"
butt_sprite = "vulp"
@@ -29,11 +30,11 @@
scream_verb = "yelps"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"heart" = /obj/item/organ/internal/heart/vulpkanin,
"lungs" = /obj/item/organ/internal/lungs/vulpkanin,
"liver" = /obj/item/organ/internal/liver/vulpkanin,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"kidneys" = /obj/item/organ/internal/kidneys/vulpkanin,
"brain" = /obj/item/organ/internal/brain/vulpkanin,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2)
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
@@ -39,7 +39,7 @@
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
dietflags = DIET_HERB //bees feed off nectar, so bee people feed off plants too
oxy_mod = 0
dies_at_threshold = TRUE
reagent_tag = PROCESS_ORG
base_color = "#704300"
@@ -1,3 +1,9 @@
/mob/living/carbon/human/SetLoseBreath(amount)
if(NO_BREATHE in dna.species.species_traits)
losebreath = 0
return FALSE
. = ..()
/mob/living/carbon/human/SetStunned(amount, updating = 1, force = 0)
if(dna.species)
amount = amount * dna.species.stun_mod
@@ -147,7 +147,7 @@ var/global/list/damage_icon_parts = list()
E.update_icon()
if(E.damage_state == "00")
continue
var/icon/DI
var/cache_index = "[E.damage_state]/[E.icon_name]/[dna.species.blood_color]/[dna.species.name]"
@@ -222,6 +222,10 @@ var/global/list/damage_icon_parts = list()
base_icon.Blend(temp, ICON_OVERLAY)
if(!skeleton)
if(isgolem(src))
var/datum/species/golem/G = src.dna.species
if(G.golem_colour)
base_icon.ColorTone(G.golem_colour)
if(husk)
base_icon.ColorTone(husk_color_mod)
else if(hulk)
@@ -239,6 +243,7 @@ var/global/list/damage_icon_parts = list()
var/mutable_appearance/new_base = mutable_appearance(base_icon, layer = -LIMBS_LAYER)
human_icon_cache[icon_key] = new_base
standing += new_base
//END CACHED ICON GENERATION.
overlays_standing[LIMBS_LAYER] = standing
@@ -437,7 +442,7 @@ var/global/list/damage_icon_parts = list()
else
//warning("Invalid f_style for [species.name]: [f_style]")
/mob/living/carbon/human/update_mutations(var/update_icons=1)
remove_overlay(MUTATIONS_LAYER)
@@ -681,6 +686,8 @@ var/global/list/damage_icon_parts = list()
overlays_standing[GLASSES_LAYER] = new_glasses
apply_overlay(GLASSES_LAYER)
update_misc_effects()
/mob/living/carbon/human/update_inv_ears(var/update_icons=1)
remove_overlay(EARS_LAYER)
if(client && hud_used)
@@ -1035,7 +1042,7 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1)
remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER.
remove_overlay(TAIL_LAYER) /* This will be one of two things:
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
can still appear on the outside of uniforms and such.
Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */
@@ -1110,7 +1117,7 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1)
remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER.
remove_overlay(TAIL_LAYER) /* This will be one of two things:
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
If the species' tail is overlapped by limbs, this will be only the N direction icon so tails
can still appear on the outside of uniforms and such.
Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */
@@ -15,7 +15,7 @@
if(dna.species && dna.species.can_revive_by_healing)
var/obj/item/organ/internal/brain/B = get_int_organ(/obj/item/organ/internal/brain)
if(B)
if((health >= (config.health_threshold_dead + config.health_threshold_crit) * 0.5) && getBrainLoss()<120)
if((health >= (HEALTH_THRESHOLD_DEAD + HEALTH_THRESHOLD_CRIT) * 0.5) && getBrainLoss() < 120)
update_revive()
create_debug_log("revived from healing, trigger reason: [reason]")
@@ -24,4 +24,13 @@
if((disabilities & NEARSIGHTED) && (!istype(G) || !G.prescription))
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("nearsighted")
clear_fullscreen("nearsighted")
/mob/living/carbon/human/can_hear()
. = TRUE // Fallback if we don't have a species
if(dna.species)
. = dna.species.can_hear(src)
/mob/living/carbon/human/check_death_method()
return dna.species.dies_at_threshold
@@ -1,21 +0,0 @@
//Lallander was here
/mob/living/carbon/human/whisper(message as text)
message = trim_strip_html_properly(message) //bit of duplicate code, acceptable because the workaround would be annoying
//parse the language code and consume it
var/datum/language/speaking = parse_language(message)
if(speaking)
message = copytext(message, 2 + length(speaking.key))
else
speaking = get_default_language()
// This is broadcast to all mobs with the language,
// irrespective of distance or anything else.
if(speaking && (speaking.flags & HIVEMIND))
speaking.broadcast(src,trim(message))
return 1
message = trim_left(message)
message = handle_autohiss(message, speaking)
whisper_say(message, speaking)
+52 -37
View File
@@ -27,8 +27,8 @@
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing(times_fired)
if(times_fired % 4 == 2 || failed_last_breath)
breathe() //Breathe per 4 ticks, unless suffocating
if(times_fired % 2 == 1)
breathe() //Breathe every other tick, unless suffocating
else
if(istype(loc, /obj/))
var/obj/location_as_object = loc
@@ -47,13 +47,13 @@
var/datum/gas_mixture/breath
if(health <= config.health_threshold_crit)
if(health <= HEALTH_THRESHOLD_CRIT && check_death_method())
AdjustLoseBreath(1)
//Suffocate
if(losebreath > 0)
AdjustLoseBreath(-1)
if(prob(10))
if(prob(75))
emote("gasp")
if(istype(loc, /obj/))
var/obj/loc_as_obj = loc
@@ -97,7 +97,6 @@
//CRIT
if(!breath || (breath.total_moles() == 0) || !lungs)
adjustOxyLoss(1)
failed_last_breath = TRUE
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
return FALSE
@@ -121,15 +120,12 @@
if(O2_partialpressure > 0)
var/ratio = 1 - O2_partialpressure/safe_oxy_min
adjustOxyLoss(min(5*ratio, 3))
failed_last_breath = TRUE
oxygen_used = breath.oxygen*ratio
else
adjustOxyLoss(3)
failed_last_breath = TRUE
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
else //Enough oxygen
failed_last_breath = FALSE
adjustOxyLoss(-5)
oxygen_used = breath.oxygen
clear_alert("not_enough_oxy")
@@ -406,35 +402,54 @@
handle_hud_icons_health_overlay()
/mob/living/carbon/proc/handle_hud_icons_health_overlay()
if(stat == UNCONSCIOUS && health <= config.health_threshold_crit)
var/severity = 0
switch(health)
if(-20 to -10) severity = 1
if(-30 to -20) severity = 2
if(-40 to -30) severity = 3
if(-50 to -40) severity = 4
if(-60 to -50) severity = 5
if(-70 to -60) severity = 6
if(-80 to -70) severity = 7
if(-90 to -80) severity = 8
if(-95 to -90) severity = 9
if(-INFINITY to -95) severity = 10
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
else if(stat == CONSCIOUS)
clear_fullscreen("crit")
if(oxyloss)
if(stat == UNCONSCIOUS && health <= HEALTH_THRESHOLD_CRIT)
if(check_death_method())
var/severity = 0
switch(oxyloss)
if(10 to 20) severity = 1
if(20 to 25) severity = 2
if(25 to 30) severity = 3
if(30 to 35) severity = 4
if(35 to 40) severity = 5
if(40 to 45) severity = 6
if(45 to INFINITY) severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
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 if(stat == CONSCIOUS)
if(check_death_method())
clear_fullscreen("crit")
if(getOxyLoss())
var/severity = 0
switch(getOxyLoss())
if(10 to 20)
severity = 1
if(20 to 25)
severity = 2
if(25 to 30)
severity = 3
if(30 to 35)
severity = 4
if(35 to 40)
severity = 5
if(40 to 45)
severity = 6
if(45 to INFINITY)
severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
//Fire and Brute damage overlay (BSSR)
var/hurtdamage = getBruteLoss() + getFireLoss() + damageoverlaytemp
@@ -450,4 +465,4 @@
if(85 to INFINITY) severity = 6
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
clear_fullscreen("brute")
@@ -92,7 +92,7 @@
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
if((message && stat == CONSCIOUS))
if(client)
log_emote("[name]/[key] : [message]")
log_emote("[name]/[key] : [message]", src)
if(m_type & 1)
visible_message(message)
else
+2 -2
View File
@@ -174,11 +174,11 @@
else
health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
if(health < config.health_threshold_dead && stat != 2)
if(health < HEALTH_THRESHOLD_DEAD && check_death_method() && stat != DEAD)
death()
return
else if(src.health <= config.health_threshold_crit)
else if(src.health <= HEALTH_THRESHOLD_CRIT && check_death_method())
if(!src.reagents.has_reagent("epinephrine"))
src.adjustOxyLoss(10)
+4 -4
View File
@@ -14,16 +14,16 @@
return 1
return ..()
/mob/living/carbon/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
/mob/living/carbon/slime/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(speaker in Friends)
speech_buffer = list()
speech_buffer.Add(speaker)
speech_buffer.Add(lowertext(html_decode(message)))
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
..()
/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 ="", var/atom/follow_target)
/mob/living/carbon/slime/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target)
if(speaker in Friends)
speech_buffer = list()
speech_buffer.Add(speaker)
speech_buffer.Add(lowertext(html_decode(message)))
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
..()
@@ -9,13 +9,15 @@
var/class
var/list/default_genes = list(REGEN, BREATHLESS, COLDRES)
var/list/default_spells = list()
var/activated = FALSE //for wishgranters to not give an option if someone already has it.
/datum/superheroes/proc/create(var/mob/living/carbon/human/H)
assign_genes(H)
assign_spells(H)
equip(H)
fixflags(H)
assign_id(H)
H.mind.special_role = SPECIAL_ROLE_SUPER
/datum/superheroes/proc/equip(var/mob/living/carbon/human/H)
H.rename_character(H.real_name, name)
@@ -3,12 +3,12 @@
return
if(stat != DEAD)
// if(health <= min_health)
if(health <= config.health_threshold_dead)
if(health <= HEALTH_THRESHOLD_DEAD && check_death_method())
death()
create_debug_log("died of damage, trigger reason: [reason]")
return
// if(paralysis || sleeping || getOxyLoss() > low_oxy_ko || (status_flags & FAKEDEATH) || health <= crit_health)
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= config.health_threshold_crit)
if(paralysis || sleeping || (check_death_method() && getOxyLoss() > 50) || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT && check_death_method())
if(stat == CONSCIOUS)
KnockOut()
create_debug_log("fell unconscious, trigger reason: [reason]")
@@ -21,7 +21,7 @@
..()
if(staminaloss)
var/total_health = (health - staminaloss)
if(total_health <= config.health_threshold_softcrit && !stat)
if(total_health <= HEALTH_THRESHOLD_CRIT && !stat)
to_chat(src, "<span class='notice'>You're too exhausted to keep going...</span>")
Weaken(5)
setStaminaLoss(health - 2)
+24 -15
View File
@@ -104,11 +104,11 @@
/mob/living/proc/getBruteLoss()
return bruteloss
/mob/living/proc/adjustBruteLoss(var/amount, updating_health = TRUE)
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_bruteloss = bruteloss
bruteloss = min(max(bruteloss + amount, 0),(maxHealth*2))
bruteloss = max(bruteloss + amount, 0)
if(old_bruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -120,11 +120,15 @@
/mob/living/proc/getOxyLoss()
return oxyloss
/mob/living/proc/adjustOxyLoss(var/amount, updating_health = TRUE)
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = min(max(oxyloss + amount, 0),(maxHealth*2))
oxyloss = max(oxyloss + amount, 0)
if(old_oxyloss == oxyloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -135,7 +139,11 @@
/mob/living/proc/setOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = amount
if(old_oxyloss == oxyloss)
@@ -149,11 +157,11 @@
/mob/living/proc/getToxLoss()
return toxloss
/mob/living/proc/adjustToxLoss(var/amount, updating_health = TRUE)
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
toxloss = min(max(toxloss + amount, 0),(maxHealth*2))
toxloss = max(toxloss + amount, 0)
if(old_toxloss == toxloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -162,7 +170,7 @@
if(updating_health)
updatehealth("adjustToxLoss")
/mob/living/proc/setToxLoss(var/amount, updating_health = TRUE)
/mob/living/proc/setToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
@@ -178,11 +186,11 @@
/mob/living/proc/getFireLoss()
return fireloss
/mob/living/proc/adjustFireLoss(var/amount, updating_health = TRUE)
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_fireloss = fireloss
fireloss = min(max(fireloss + amount, 0),(maxHealth*2))
fireloss = max(fireloss + amount, 0)
if(old_fireloss == fireloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -194,11 +202,11 @@
/mob/living/proc/getCloneLoss()
return cloneloss
/mob/living/proc/adjustCloneLoss(var/amount, updating_health = TRUE)
/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_cloneloss = cloneloss
cloneloss = min(max(cloneloss + amount, 0),(maxHealth*2))
cloneloss = max(cloneloss + amount, 0)
if(old_cloneloss == cloneloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -207,8 +215,9 @@
if(updating_health)
updatehealth("adjustCloneLoss")
/mob/living/proc/setCloneLoss(var/amount, updating_health = TRUE)
if(status_flags & GODMODE) return 0 //godmode
/mob/living/proc/setCloneLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_cloneloss = cloneloss
cloneloss = amount
if(old_cloneloss == cloneloss)
@@ -235,7 +244,7 @@
if(status_flags & GODMODE)
return FALSE
var/old_stamloss = staminaloss
staminaloss = min(max(staminaloss + amount, 0),(maxHealth*2))
staminaloss = max(staminaloss + amount, 0)
if(old_stamloss == staminaloss)
updating = FALSE
. = STATUS_UPDATE_NONE
@@ -300,4 +309,4 @@
updatehealth("take overall damage")
/mob/living/proc/has_organic_damage()
return (maxHealth - health)
return (maxHealth - health)
+14 -1
View File
@@ -56,7 +56,10 @@
SetJitter(0)
SetLoseBreath(0)
if(suiciding)
if(!gibbed && deathgasp_on_death)
emote("deathgasp")
if(mind && suiciding)
mind.suicided = TRUE
clear_fullscreens()
update_sight()
@@ -64,6 +67,8 @@
med_hud_set_health()
med_hud_set_status()
if(!gibbed && !QDELETED(src))
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
callHook("death", list(src, gibbed))
for(var/s in ownedSoullinks)
@@ -86,6 +91,14 @@
if(ticker && ticker.mode)
ticker.mode.check_win()
if(mind && mind.devilinfo) // Expand this into a general-purpose death-response system when appropriate
mind.devilinfo.beginResurrectionCheck(src)
// u no we dead
return TRUE
/mob/living/proc/delayed_gib()
visible_message("<span class='danger'><b>[src]</b> starts convulsing violently!</span>", "You feel as if your body is tearing itself apart!")
Weaken(15)
do_jitter_animation(1000, -1)
addtimer(CALLBACK(src, .proc/gib), rand(20, 100))
+9 -2
View File
@@ -3,9 +3,9 @@
set background = BACKGROUND_ENABLED
if(notransform)
return
return 0
if(!loc)
return
return 0
var/datum/gas_mixture/environment = loc.return_air()
if(stat != DEAD)
@@ -25,6 +25,10 @@
handle_diseases()
//Heart Attack, if applicable
if(stat != DEAD)
handle_heartattack()
//Handle temperature/pressure differences between body and environment
if(environment)
handle_environment(environment)
@@ -56,6 +60,9 @@
/mob/living/proc/handle_breathing(times_fired)
return
/mob/living/proc/handle_heartattack()
return
/mob/living/proc/handle_mutations_and_radiation()
radiation = 0 //so radiation don't accumulate in simple animals
return
+137 -34
View File
@@ -50,7 +50,7 @@
if(ObjBump(A))
return
if(istype(A, /atom/movable))
if(PushAM(A))
if(PushAM(A, move_force))
return
//Called when we bump into a mob
@@ -80,6 +80,10 @@
if(moving_diagonally) //no mob swap during diagonal moves.
return 1
if(a_intent == INTENT_HELP) // Help intent doesn't mob swap a mob pulling a structure
if(isstructure(M.pulling) || isstructure(pulling))
return 1
if(!M.buckled && !M.has_buckled_mobs())
var/mob_swap
//the puller can always swap with it's victim if on grab intent
@@ -127,32 +131,48 @@
return
//Called when we want to push an atom/movable
/mob/living/proc/PushAM(atom/movable/AM)
/mob/living/proc/PushAM(atom/movable/AM, force = move_force)
if(isstructure(AM) && AM.pulledby)
if(a_intent == INTENT_HELP && AM.pulledby != src) // Help intent doesn't push other peoples pulled structures
return FALSE
if(get_dist(get_step(AM, get_dir(src, AM)), AM.pulledby)>1)//Release pulled structures beyond 1 distance
AM.pulledby.stop_pulling()
if(now_pushing)
return 1
return TRUE
if(moving_diagonally) // no pushing during diagonal moves
return 1
return TRUE
if(!client && (mob_size < MOB_SIZE_SMALL))
return
if(!AM.anchored)
now_pushing = 1
var/t = get_dir(src, AM)
if(istype(AM, /obj/structure/window))
var/obj/structure/window/W = AM
if(W.fulltile)
for(var/obj/structure/window/win in get_step(W, t))
now_pushing = 0
return
if(pulling == AM)
stop_pulling()
var/current_dir
if(isliving(AM))
current_dir = AM.dir
step(AM, t)
if(current_dir)
AM.setDir(current_dir)
now_pushing = 0
now_pushing = TRUE
var/t = get_dir(src, AM)
var/push_anchored = FALSE
if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force)
if(move_crush(AM, move_force, t))
push_anchored = TRUE
if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally
if(force_push(AM, move_force, t, push_anchored))
push_anchored = TRUE
if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO)))
now_pushing = FALSE
return
if(istype(AM, /obj/structure/window))
var/obj/structure/window/W = AM
if(W.fulltile)
for(var/obj/structure/window/win in get_step(W,t))
now_pushing = FALSE
return
if(pulling == AM)
stop_pulling()
var/current_dir
if(isliving(AM))
current_dir = AM.dir
if(step(AM, t))
step(src, t)
if(current_dir)
AM.setDir(current_dir)
now_pushing = FALSE
/mob/living/Stat()
. = ..()
@@ -187,9 +207,20 @@
set name = "Pull"
set category = "Object"
if(AM.Adjacent(src))
if(istype(AM) && Adjacent(AM))
start_pulling(AM)
return
else
stop_pulling()
/mob/living/stop_pulling()
..()
if(pullin)
pullin.update_icon(src)
/mob/living/verb/stop_pulling1()
set name = "Stop Pulling"
set category = "IC"
stop_pulling()
//same as above
/mob/living/pointed(atom/A as mob|obj|turf in view())
@@ -206,7 +237,7 @@
return TRUE
A.visible_message("<span class='danger'>[src] points [hand_item] at [A]!</span>",
"<span class='userdanger'>[src] points [hand_item] at you!</span>")
A << 'sound/weapons/TargetOn.ogg'
A << 'sound/weapons/targeton.ogg'
return TRUE
visible_message("<b>[src]</b> points to [A]")
return TRUE
@@ -215,17 +246,18 @@
set hidden = 1
if(InCritical())
create_attack_log("[src] has ["succumbed to death"] with [round(health, 0.1)] points of health!")
adjustOxyLoss(health - config.health_threshold_dead)
adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
// super check for weird mobs, including ones that adjust hp
// we don't want to go overboard and gib them, though
for(var/i = 1 to 5)
if(health < config.health_threshold_dead)
if(health < HEALTH_THRESHOLD_DEAD)
break
take_overall_damage(max(5, health - config.health_threshold_dead), 0)
take_overall_damage(max(5, health - HEALTH_THRESHOLD_DEAD), 0)
death()
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
/mob/living/proc/InCritical()
return (health < 0 && health > -95.0 && stat == UNCONSCIOUS)
return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS)
/mob/living/ex_act(severity)
..()
@@ -431,7 +463,6 @@
human_mob = src
human_mob.set_heartattack(FALSE)
human_mob.restore_blood()
human_mob.shock_stage = 0
human_mob.decaylevel = 0
human_mob.remove_all_embedded_objects()
@@ -488,6 +519,7 @@
var/turf/T = loc
. = ..()
if(.)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED)
handle_footstep(loc)
step_count++
@@ -727,7 +759,7 @@
if(!silent)
visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>")
if(do_mob(src, who, what.put_on_delay))
if(what && Adjacent(who))
if(what && Adjacent(who) && !(what.flags & NODROP))
unEquip(what)
who.equip_to_slot_if_possible(what, where, 0, 1)
add_attack_logs(src, who, "Equipped [what]")
@@ -754,11 +786,11 @@
..()
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
/mob/living/proc/do_jitter_animation(jitteriness)
/mob/living/proc/do_jitter_animation(jitteriness, loop_amount = 6)
var/amplitude = min(4, (jitteriness/100) + 1)
var/pixel_x_diff = rand(-amplitude, amplitude)
var/pixel_y_diff = rand(-amplitude/3, amplitude/3)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = loop_amount)
animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y) , time = 2)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
@@ -852,6 +884,37 @@
return 0
return 1
/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
if(!AM || !src)
return FALSE
if(!(AM.can_be_pulled(src, state, force)))
return FALSE
if(incapacitated())
return
// If we're pulling something then drop what we're currently pulling and pull this instead.
AM.add_fingerprint(src)
if(pulling)
if(AM == pulling)// Are we trying to pull something we are already pulling? Then just stop here, no need to continue.
return
stop_pulling()
if(AM.pulledby)
visible_message("<span class='danger'>[src] has pulled [AM] from [AM.pulledby]'s grip.</span>")
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
AM.pulledby = src
if(pullin)
pullin.update_icon(src)
if(ismob(AM))
var/mob/M = AM
if(!iscarbon(src))
M.LAssailant = null
else
M.LAssailant = usr
/mob/living/proc/check_pull()
if(pulling && !(pulling in orange(1)))
stop_pulling()
/mob/living/proc/get_taste_sensitivity()
return 1
@@ -889,3 +952,43 @@
return
to_chat(src, "<span class='notice'>You can taste [english_list(final_taste_list)].</span>")
/mob/living/proc/owns_soul()
if(mind)
return mind.soulOwner == mind
return 1
/mob/living/proc/return_soul()
if(mind)
if(mind.soulOwner.devilinfo)//Not sure how this could happen, but whatever.
mind.soulOwner.devilinfo.remove_soul(mind)
mind.soulOwner = mind
mind.damnation_type = 0
/mob/living/proc/has_bane(banetype)
if(mind)
if(mind.devilinfo)
return mind.devilinfo.bane == banetype
return 0
/mob/living/proc/check_weakness(obj/item/weapon, mob/living/attacker)
if(mind && mind.devilinfo)
return check_devil_bane_multiplier(weapon, attacker)
return 1
/mob/living/proc/check_acedia()
if(src.mind && src.mind.objectives)
for(var/datum/objective/sintouched/acedia/A in src.mind.objectives)
return 1
return 0
/mob/living/proc/fakefireextinguish()
return
/mob/living/proc/fakefire()
return
/mob/living/extinguish_light()
for(var/atom/A in src)
if(A.light_range > 0)
A.extinguish_light()
+5 -4
View File
@@ -73,7 +73,7 @@
return 0
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)//Standardization and logging -Sieve
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0, datum/thrownthing/throwingdatum)//Standardization and logging -Sieve
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
@@ -117,7 +117,7 @@
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
playsound(src, 'sound/items/welder.ogg', 50, 1)
if("tox")
M.mech_toxin_damage(src)
else
@@ -179,7 +179,8 @@
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act()
/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
adjust_fire_stacks(3)
IgniteMob()
@@ -229,7 +230,7 @@
// End BS12 momentum-transfer code.
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE)
if(user == src || anchored)
return 0
if(!(status_flags & CANPUSH))
@@ -66,3 +66,5 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD)
var/list/status_effects //a list of all status effects the mob has
var/deathgasp_on_death = FALSE
-3
View File
@@ -7,7 +7,6 @@
//If they're SSD, remove it so they can wake back up.
player_logged = 0
//Vents
if(ventcrawler)
to_chat(src, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
@@ -18,6 +17,4 @@
//Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways.
update_pipe_vision()
update_interface()
return .
+1 -1
View File
@@ -9,4 +9,4 @@
if(mind.active)
Sleeping(2)
player_logged = 1
last_logout = world.time
last_logout = world.time
+81 -122
View File
@@ -54,51 +54,48 @@ proc/get_radio_key_from_channel(var/channel)
/mob/living/proc/binarycheck()
return FALSE
/mob/living/proc/get_default_language()
/mob/proc/get_default_language()
return null
/mob/living/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
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
var/robot = isSynthetic()
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
if((HULK in mutations) && health >= 25)
S.message = "[uppertext(S.message)]!!!"
verb = pick("yells", "roars", "hollers")
if((HULK in mutations) && health >= 25 && length(message))
message = "[uppertext(message)]!!!"
verb = pick("yells","roars","hollers")
speech_problem_flag = 1
if(slurring)
if(robot)
S.message = slur(S.message, list("@", "!", "#", "$", "%", "&", "?"))
else
S.message = slur(S.message)
verb = "slurs"
if(slurring)
if(robot)
message = slur(message, list("@", "!", "#", "$", "%", "&", "?"))
else
message = slur(message)
verb = "slurs"
speech_problem_flag = 1
if(stuttering)
if(robot)
message = robostutter(message)
else
message = stutter(message)
verb = "stammers"
speech_problem_flag = 1
if(cultslurring)
message = cultslur(message)
verb = "slurs"
speech_problem_flag = 1
if(!IsVocal())
message = ""
speech_problem_flag = 1
if(stuttering)
if(robot)
S.message = robostutter(S.message)
else
S.message = stutter(S.message)
verb = "stammers"
returns[1] = message
returns[2] = verb
returns[3] = speech_problem_flag
return returns
if(cultslurring)
S.message = cultslur(S.message)
verb = "slurs"
/mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios)
if(!IsVocal())
S.message = ""
return list("verb" = verb)
/mob/living/proc/handle_message_mode(message_mode, list/message_pieces, verb, used_radios)
switch(message_mode)
if("whisper") //all mobs can whisper by default
whisper_say(message, speaking)
whisper_say(message_pieces)
return 1
return 0
@@ -109,7 +106,7 @@ proc/get_radio_key_from_channel(var/channel)
return returns
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
/mob/living/say(var/message, var/verb = "says", var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
@@ -138,19 +135,17 @@ proc/get_radio_key_from_channel(var/channel)
message = trim_left(message)
//parse the language code and consume it
if(!speaking)
speaking = parse_language(message)
if(speaking)
message = copytext(message, 2 + length(speaking.key))
else
speaking = get_default_language()
// This is broadcast to all mobs with the language,
// irrespective of distance or anything else.
if(speaking && (speaking.flags & HIVEMIND))
speaking.broadcast(src,trim(message))
var/list/message_pieces = parse_languages(message)
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
S.speaking.broadcast(src, S.message)
return 1
if(!LAZYLEN(message_pieces))
log_runtime(EXCEPTION("Message failed to generate pieces. [message] - [json_encode(message_pieces)]"))
return 0
if(message_mode == "cords")
if(iscarbon(src))
var/mob/living/carbon/C = src
@@ -160,7 +155,8 @@ proc/get_radio_key_from_channel(var/channel)
V.speak_with(message) //words come before actions
return 1
verb = say_quote(message, speaking)
var/datum/multilingual_say_piece/first_piece = message_pieces[1]
verb = say_quote(message, first_piece.speaking)
if(is_muzzled())
var/obj/item/clothing/mask/muzzle/G = wear_mask
@@ -168,25 +164,19 @@ proc/get_radio_key_from_channel(var/channel)
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
else if(G.mute == MUZZLE_MUTE_MUFFLE)
message = muffledspeech(message)
muffledspeech_all(message_pieces)
verb = "mumbles"
message = trim_left(message)
if(!ignore_speech_problems)
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
message = handle_autohiss(message, speaking)
if(!ignore_speech_problems && (speaking && !(speaking.flags & NO_STUTTER)))
var/list/handle_s = handle_speech_problems(message, verb)
message = handle_s[1]
verb = handle_s[2]
if(!message || message == "")
return 0
var/list/used_radios = list()
if(handle_message_mode(message_mode, message, verb, speaking, used_radios))
if(handle_message_mode(message_mode, message_pieces, verb, used_radios))
return 1
var/list/handle_v = handle_speech_sound()
var/sound/speech_sound = handle_v[1]
var/sound_vol = handle_v[2]
@@ -198,11 +188,12 @@ proc/get_radio_key_from_channel(var/channel)
if(used_radios.len)
italics = 1
message_range = 1
if(speaking)
message_range = speaking.get_talkinto_msg_range(message)
if(first_piece.speaking)
message_range = first_piece.speaking.get_talkinto_msg_range(message)
var/msg
if(!speaking || !(speaking.flags & NO_TALK_MSG))
msg = "<span class='notice'>\The [src] talks into \the [used_radios[1]]</span>"
if(!first_piece.speaking || !(first_piece.speaking.flags & NO_TALK_MSG))
msg = "<span class='notice'>[src] talks into [used_radios[1]]</span>"
if(msg)
for(var/mob/living/M in hearers(5, src) - src)
@@ -213,16 +204,6 @@ proc/get_radio_key_from_channel(var/channel)
var/turf/T = get_turf(src)
//handle nonverbal and sign languages here
if(speaking)
if(speaking.flags & NONVERBAL)
if(prob(30))
custom_emote(1, "[pick(speaking.signlang_verb)].")
if(speaking.flags & SIGNLANG)
return say_signlang(message, pick(speaking.signlang_verb), speaking)
var/list/listening = list()
var/list/listening_obj = list()
@@ -268,7 +249,7 @@ proc/get_radio_key_from_channel(var/channel)
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message, verb, speaking, italics, src, speech_sound, sound_vol)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
@@ -281,19 +262,13 @@ proc/get_radio_key_from_channel(var/channel)
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)
O.hear_talk(src, message_pieces, verb)
//Log of what we've said, plain message, no spans or junk
say_log += message
log_say(message, src)
return 1
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
for(var/mob/O in viewers(src, null))
O.hear_signlang(message, verb, language, src)
return 1
/obj/effect/speech_bubble
var/mob/parent
@@ -338,28 +313,19 @@ proc/get_radio_key_from_channel(var/channel)
message = trim_strip_html_properly(message)
//parse the language code and consume it
var/datum/language/speaking = parse_language(message)
if(speaking)
message = copytext(message, 2 + length(speaking.key))
else
speaking = get_default_language()
// This is broadcast to all mobs with the language,
// irrespective of distance or anything else.
if(speaking && (speaking.flags & HIVEMIND))
speaking.broadcast(src,trim(message))
var/list/message_pieces = parse_languages(message)
if(istype(message_pieces, /datum/multilingual_say_piece)) // Little quirk to just easily deal with HIVEMIND languages
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
S.speaking.broadcast(src, S.message)
return 1
message = trim_left(message)
message = handle_autohiss(message, speaking)
whisper_say(message, speaking)
whisper_say(message_pieces)
// for weird circumstances where you're inside an atom that is also you, like pai's
/mob/living/proc/get_whisper_loc()
return src
/mob/living/proc/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers")
/mob/living/proc/whisper_say(list/message_pieces, verb = "whispers")
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
@@ -367,7 +333,7 @@ proc/get_radio_key_from_channel(var/channel)
if(stat)
if(stat == DEAD)
return say_dead(message)
return say_dead(message_pieces)
return
if(is_muzzled())
@@ -377,42 +343,36 @@ proc/get_radio_key_from_channel(var/channel)
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
log_whisper(multilingual_to_message(message_pieces), src)
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
var/italics = 1
var/adverb_added = FALSE
var/not_heard //the message displayed to people who could not hear the whispering
if(speaking)
if(speaking.whisper_verb)
verb = speaking.whisper_verb
var/datum/multilingual_say_piece/first_piece = message_pieces[1]
if(first_piece.speaking)
if(first_piece.speaking.whisper_verb)
verb = first_piece.speaking.whisper_verb
not_heard = "[verb] something"
else
var/adverb = pick("quietly", "softly")
adverb_added = TRUE
verb = "[speaking.speech_verb] [adverb]"
not_heard = "[speaking.speech_verb] something [adverb]"
verb = "[first_piece.speaking.speech_verb] [adverb]"
not_heard = "[first_piece.speaking.speech_verb] something [adverb]"
else
not_heard = "[verb] something"
message = trim(message)
var/speech_problem_flag = 0
var/list/handle_s = handle_speech_problems(message, verb)
message = handle_s[1]
verb = handle_s[2]
speech_problem_flag = handle_s[3]
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
if(verb == "yells loudly")
verb = "slurs emphatically"
else if(speech_problem_flag && !adverb_added)
else if(!adverb_added)
var/adverb = pick("quietly", "softly")
verb = "[verb] [adverb]"
if(!message)
return
var/atom/whisper_loc = get_whisper_loc()
var/list/listening = hear(message_range, whisper_loc)
listening |= src
@@ -450,7 +410,7 @@ proc/get_radio_key_from_channel(var/channel)
for(var/obj/O in view(message_range, whisper_loc))
spawn(0)
if(O)
O.hear_talk(src, message, verb, speaking)
O.hear_talk(src, message_pieces, verb)
var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc)
eavesdropping -= src
@@ -463,17 +423,17 @@ proc/get_radio_key_from_channel(var/channel)
//now mobs
var/list/speech_bubble_recipients = list()
var/speech_bubble_test = say_test(message)
var/speech_bubble_test = say_test(multilingual_to_message(message_pieces))
for(var/mob/M in listening)
M.hear_say(message, verb, speaking, italics, src)
M.hear_say(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
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.
stars_all(message_pieces) //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.hear_say(new_message, verb, speaking, italics, src)
M.hear_say(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
@@ -487,7 +447,6 @@ proc/get_radio_key_from_channel(var/channel)
for(var/mob/M in watching)
M.show_message(rendered, 2)
log_whisper(message, src)
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
+34 -24
View File
@@ -36,9 +36,9 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai
name = "AI"
icon = 'icons/mob/AI.dmi'//
icon = 'icons/mob/ai.dmi'//
icon_state = "ai"
anchored = 1 // -- TLE
move_resist = MOVE_FORCE_NORMAL
density = 1
status_flags = CANSTUN|CANPARALYSE|CANPUSH
mob_size = MOB_SIZE_LARGE
@@ -143,7 +143,7 @@ var/list/ai_verbs_default = list(
density = 1
loc = loc
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo1"))
proc_holder_list = new()
@@ -172,6 +172,7 @@ var/list/ai_verbs_default = list(
add_language("Galactic Common", 1)
add_language("Sol Common", 1)
add_language("Tradeband", 1)
add_language("Neo-Russkiya", 0)
add_language("Gutter", 0)
add_language("Sinta'unathi", 0)
add_language("Siik'tajr", 0)
@@ -379,7 +380,7 @@ var/list/ai_verbs_default = list(
//if(icon_state == initial(icon_state))
var/icontype = ""
icontype = input("Select an icon!", "AI", null, null) in display_choices
icon = 'icons/mob/AI.dmi' //reset this in case we were on a custom sprite and want to change to a standard one
icon = 'icons/mob/ai.dmi' //reset this in case we were on a custom sprite and want to change to a standard one
switch(icontype)
if("Custom")
icon = 'icons/mob/custom_synthetic/custom-synthetic.dmi' //set this here so we can use the custom_sprite
@@ -533,7 +534,10 @@ var/list/ai_verbs_default = list(
if(!isturf(loc)) // if their location isn't a turf
return // stop
anchored = !anchored // Toggles the anchor
if(anchored)
anchored = FALSE
else
anchored = TRUE
to_chat(src, "[anchored ? "<b>You are now anchored.</b>" : "<b>You are now unanchored.</b>"]")
@@ -656,7 +660,21 @@ var/list/ai_verbs_default = list(
return
if(href_list["ai_take_control"]) //Mech domination
var/obj/mecha/M = locate(href_list["ai_take_control"])
if(!M)
return
var/mech_has_controlbeacon = FALSE
for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in M.trackers)
mech_has_controlbeacon = TRUE
break
if(!can_dominate_mechs && !mech_has_controlbeacon)
message_admins("Warning: possible href exploit by [key_name(usr)] - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.")
log_debug("Warning: possible href exploit by [key_name(usr)] - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.")
return
if(controlled_mech)
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
return
@@ -670,7 +688,7 @@ var/list/ai_verbs_default = list(
to_chat(src, "<span class='warning'>You aren't in your core!</span>")
return
if(M)
M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
M.transfer_ai(AI_MECH_HACK, src, usr) //Called om the mech itself.
else if(href_list["faketrack"])
var/mob/target = locate(href_list["track"]) in GLOB.mob_list
@@ -988,13 +1006,13 @@ var/list/ai_verbs_default = list(
qdel(holo_icon)
switch(input)
if("default")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo1"))
if("floating face")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo2"))
if("xeno queen")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo3"))
if("eldritch")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo4"))
if("ancient machine")
holo_icon = getHologramIcon(icon('icons/mob/ancient_machine.dmi', "ancient_machine"))
if("custom")
@@ -1003,7 +1021,7 @@ var/list/ai_verbs_default = list(
else if("[ckey]-ai-holo" in icon_states('icons/mob/custom_synthetic/custom-synthetic64.dmi'))
holo_icon = getHologramIcon(icon('icons/mob/custom_synthetic/custom-synthetic64.dmi', "[ckey]-ai-holo"))
else
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"holo1"))
return
@@ -1093,7 +1111,7 @@ var/list/ai_verbs_default = list(
user.visible_message("<span class='notice'>\The [user] decides not to unbolt \the [src].</span>")
return
user.visible_message("<span class='notice'>\The [user] finishes unfastening \the [src]!</span>")
anchored = 0
anchored = FALSE
return
else
user.visible_message("<span class='notice'>\The [user] starts to bolt \the [src] to the plating...</span>")
@@ -1101,7 +1119,7 @@ var/list/ai_verbs_default = list(
user.visible_message("<span class='notice'>\The [user] decides not to bolt \the [src].</span>")
return
user.visible_message("<span class='notice'>\The [user] finishes fastening down \the [src]!</span>")
anchored = 1
anchored = TRUE
return
else
return ..()
@@ -1184,19 +1202,11 @@ var/list/ai_verbs_default = list(
var/list/viewscale = getviewsize(client.view)
return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5)
/mob/living/silicon/ai/proc/relay_speech(mob/living/M, text, verb, datum/language/speaking)
if(!say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
if(speaking)
text = speaking.scramble(text)
else
text = stars(text)
/mob/living/silicon/ai/proc/relay_speech(mob/living/M, list/message_pieces, verb)
var/message = combine_message(message_pieces, verb, M)
var/name_used = M.GetVoice()
//This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
var/rendered
if(speaking)
rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
else
rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [message]</span></i>"
show_message(rendered, 2)
/mob/living/silicon/ai/proc/malfhacked(obj/machinery/power/apc/apc)
@@ -6,7 +6,7 @@
/mob/camera/aiEye
name = "Inactive AI Eye"
icon = 'icons/mob/AI.dmi' //Allows ghosts to see what the AI is looking at.
icon = 'icons/mob/ai.dmi' //Allows ghosts to see what the AI is looking at.
icon_state = "eye"
alpha = 127
invisibility = SEE_INVISIBLE_OBSERVER
@@ -141,6 +141,10 @@
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
/mob/camera/aiEye/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(relay_speech)
ai.relay_speech(speaker, message, verb, language)
if(istype(ai))
ai.relay_speech(speaker, message_pieces, verb)
else
var/mob/M = ai
M.hear_say(message_pieces, verb, italics, speaker, speech_sound, sound_vol)
@@ -37,6 +37,9 @@ var/global/list/empty_playable_ai_cores = list()
var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode
current_mode.possible_traitors.Remove(src)
// Ghost the current player and disallow them to return to the body
ghostize(FALSE)
// Delete the old AI shell
qdel(src)
// TODO: Move away from the insane name-based landmark system
+2 -2
View File
@@ -3,7 +3,7 @@
*/
/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/datum/language/language, var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
/mob/living/silicon/ai/handle_track(var/message, var/verb = "says", var/mob/speaker = null, var/speaker_name, var/atom/follow_target, var/hard_to_hear)
if(hard_to_hear)
return
@@ -55,7 +55,7 @@
if(mob_to_track)
track = "<a href='byond://?src=[UID()];track=\ref[mob_to_track]'>[speaker_name] ([jobname])</a>"
track += "<a href='byond://?src=[UID()];open=\ref[mob_to_track]'>\[O\]</a>"
track += "&nbsp;<a href='byond://?src=[UID()];open=\ref[mob_to_track]'>\[Open\]</a>"
return track
@@ -2,7 +2,7 @@
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health <= config.health_threshold_dead)
if(health <= HEALTH_THRESHOLD_DEAD && check_death_method())
death()
create_debug_log("died of damage, trigger reason: [reason]")
return
+11 -10
View File
@@ -22,22 +22,23 @@
if(src) qdel(src)
/mob/living/silicon/dust()
death(1)
var/atom/movable/overlay/animation = null
if(!death(TRUE) && stat != DEAD)
return FALSE
notransform = 1
canmove = 0
icon = null
invisibility = 101
dust_animation()
GLOB.dead_mob_list -= src
QDEL_IN(src, 15)
return TRUE
/mob/living/silicon/dust_animation()
//hmmm
var/atom/movable/overlay/animation = null
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
// flick("dust-r", animation)
new /obj/effect/decal/remains/robot(loc)
GLOB.dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
@@ -1,13 +1,13 @@
/mob/living/silicon/decoy
name = "AI"
icon = 'icons/mob/AI.dmi'//
icon = 'icons/mob/ai.dmi'//
icon_state = "ai"
anchored = 1 // -- TLE
canmove = 0
a_intent = INTENT_HARM // This is apparently the only thing that stops other mobs walking through them as if they were thin air.
/mob/living/silicon/decoy/New()
src.icon = 'icons/mob/AI.dmi'
src.icon = 'icons/mob/ai.dmi'
src.icon_state = "ai"
src.anchored = 1
src.canmove = 0
+8 -6
View File
@@ -79,6 +79,7 @@
var/obj/item/integrated_radio/signal/sradio // AI's signaller
var/translator_on = 0 // keeps track of the translator module
var/flashlight_on = FALSE //keeps track of the flashlight module
var/current_pda_messaging = null
var/custom_sprite = 0
@@ -517,12 +518,8 @@
/mob/living/silicon/pai/Bumped()
return
/mob/living/silicon/pai/start_pulling(var/atom/movable/AM)
if(stat || sleeping || paralysis || weakened)
return
if(istype(AM,/obj/item))
to_chat(src, "<span class='warning'>You are far too small to pull anything!</span>")
return
/mob/living/silicon/pai/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
return FALSE
/mob/living/silicon/pai/update_canmove(delay_action_updates = 0)
. = ..()
@@ -611,3 +608,8 @@
else //something went very wrong.
CRASH("pAI without card")
loc = card
/mob/living/silicon/pai/extinguish_light()
flashlight_on = FALSE
set_light(0)
card.set_light(0)
+36 -19
View File
@@ -23,24 +23,22 @@ var/datum/paiController/paiController // Global handler for pAI candidates
var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min]
/datum/paiController/Topic(href, href_list[])
if("signup" in href_list)
var/mob/dead/observer/O = locate(href_list["signup"])
if(!O) return
if(!(O in GLOB.respawnable_list))
to_chat(O, "You've given up your ability to respawn!")
var/datum/paiCandidate/candidate = locateUID(href_list["candidate"])
if(candidate)
if(!istype(candidate))
message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate is not a pAI)")
log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate is not a pAI)")
return
if(!check_recruit(O)) return
recruitWindow(O)
return
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/paicard/card = locate(href_list["device"])
if(card.pai)
return
if(usr.incapacitated() || isobserver(usr) || !card.Adjacent(usr))
return
if(istype(card,/obj/item/paicard) && istype(candidate,/datum/paiCandidate))
if(istype(card, /obj/item/paicard) && istype(candidate, /datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(GLOB.ninja_names)
@@ -58,8 +56,27 @@ var/datum/paiController/paiController // Global handler for pAI candidates
pai_candidates -= candidate
usr << browse(null, "window=findPai")
if(candidate)
if(candidate.key && usr.key && candidate.key != usr.key)
message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)")
log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)")
return
if("signup" in href_list)
var/mob/dead/observer/O = locate(href_list["signup"])
if(!O)
return
if(!(O in GLOB.respawnable_list))
to_chat(O, "You've given up your ability to respawn!")
return
if(!check_recruit(O))
return
recruitWindow(O)
return
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
@@ -183,28 +200,28 @@ var/datum/paiController/paiController // Global handler for pAI candidates
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=name;new=1;candidate=\ref[candidate]'>Name</a>:</th>
<th rowspan="2"><a href='byond://?src=[UID()];option=name;new=1;candidate=[candidate.UID()]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=desc;new=1;candidate=\ref[candidate]'>Description</a>:</th>
<th rowspan="2"><a href='byond://?src=[UID()];option=desc;new=1;candidate=[candidate.UID()]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=role;new=1;candidate=\ref[candidate]'>Preferred Role</a>:</th>
<th rowspan="2"><a href='byond://?src=[UID()];option=role;new=1;candidate=[candidate.UID()]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=[UID()];option=ooc;new=1;candidate=\ref[candidate]'>OOC Comments</a>:</th>
<th rowspan="2"><a href='byond://?src=[UID()];option=ooc;new=1;candidate=[candidate.UID()]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
@@ -215,17 +232,17 @@ var/datum/paiController/paiController // Global handler for pAI candidates
<table>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=save;new=1;candidate=\ref[candidate]' class="button">Save Personality</a>
<a href='byond://?src=[UID()];option=save;new=1;candidate=[candidate.UID()]' class="button">Save Personality</a>
</td>
</tr>
<tr>
<td class="button">
<a href='byond://?src=[UID()];option=load;new=1;candidate=\ref[candidate]' class="button">Load Personality</a>
<a href='byond://?src=[UID()];option=load;new=1;candidate=[candidate.UID()]' class="button">Load Personality</a>
</td>
</tr>
</table><br>
<table>
<td class="button"><a href='byond://?src=[UID()];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
<td class="button"><a href='byond://?src=[UID()];option=submit;new=1;candidate=[candidate.UID()]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
</body>
@@ -336,7 +353,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=[UID()];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
<td class="download"><a href='byond://?src=[UID()];download=1;candidate=[c.UID()];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</table>
<br>
@@ -515,6 +515,7 @@
user.add_language("Bubblish")
user.add_language("Orluum")
user.add_language("Clownish")
user.add_language("Neo-Russkiya")
else
user.remove_language("Sinta'unathi")
user.remove_language("Siik'tajr")
@@ -526,6 +527,7 @@
user.remove_language("Bubblish")
user.remove_language("Orluum")
user.remove_language("Clownish")
user.remove_language("Neo-Russkiya")
/datum/pai_software/translator/is_active(mob/living/silicon/pai/user)
return user.translator_on
@@ -609,3 +611,20 @@
data["holder"] = 0
return data
/datum/pai_software/flashlight
name = "Flashlight"
ram_cost = 5
id = "flashlight"
/datum/pai_software/flashlight/toggle(mob/living/silicon/pai/user)
var/atom/movable/actual_location = istype(user.loc, /obj/item/paicard) ? user.loc : user
if(user.flashlight_on)
actual_location.set_light(2)
user.card.set_light(2)
return
actual_location.set_light(2)
user.card.set_light(0)
/datum/pai_software/flashlight/is_active(mob/living/silicon/pai/user)
return user.flashlight_on
+16 -14
View File
@@ -1,4 +1,6 @@
/mob/living/silicon/robot/gib()
if(!death(TRUE) && stat != DEAD)
return FALSE
//robots don't die when gibbed. instead they drop their MMI'd brain
var/atom/movable/overlay/animation = null
notransform = 1
@@ -18,36 +20,36 @@
GLOB.living_mob_list -= src
GLOB.dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
QDEL_IN(src, 15)
return TRUE
/mob/living/silicon/robot/dust()
death(1)
var/atom/movable/overlay/animation = null
if(!death(TRUE) && stat != DEAD)
return FALSE
notransform = 1
canmove = 0
icon = null
invisibility = 101
if(mmi)
qdel(mmi) //Delete the MMI first so that it won't go popping out.
GLOB.dead_mob_list -= src
QDEL_IN(src, 15)
return TRUE
/mob/living/silicon/robot/dust_animation()
var/atom/movable/overlay/animation = null
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("dust-r", animation)
new /obj/effect/decal/remains/robot(loc)
if(mmi) qdel(mmi) //Delete the MMI first so that it won't go popping out.
GLOB.dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
/mob/living/silicon/robot/death(gibbed)
if(can_die())
if(!gibbed)
if(!gibbed && deathgasp_on_death)
emote("deathgasp")
if(module)
@@ -17,7 +17,6 @@
ventcrawler = 2
magpulse = 1
mob_size = MOB_SIZE_SMALL
default_language = "Drone"
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
@@ -38,7 +37,6 @@
/mob/living/silicon/robot/drone/New()
..()
remove_language("Robot Talk")
@@ -101,7 +99,7 @@
/mob/living/silicon/robot/drone/update_icons()
overlays.Cut()
if(stat == 0)
if(stat == CONSCIOUS)
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
@@ -126,7 +124,7 @@
else if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda))
if(stat == 2)
if(stat == DEAD)
if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
to_chat(user, "<span class='warning'>The interface is fried, and a distressing burned smell wafts from the robot's interior. You're not rebooting this one.</span>")
@@ -168,7 +166,7 @@
..()
/mob/living/silicon/robot/drone/emag_act(user as mob)
if(!client || stat == 2)
if(!client || stat == DEAD)
to_chat(user, "<span class='warning'>There's not much point subverting this heap of junk.</span>")
return
@@ -225,12 +223,12 @@
/mob/living/silicon/robot/drone/death(gibbed)
. = ..(gibbed)
ghostize(can_reenter_corpse = 0)
adjustBruteLoss(health)
//CONSOLE PROCS
/mob/living/silicon/robot/drone/proc/law_resync()
if(stat != 2)
if(stat != DEAD)
if(emagged)
to_chat(src, "<span class='warning'>You feel something attempting to modify your programming, but your hacked subroutines are unaffected.</span>")
else
@@ -239,7 +237,7 @@
show_laws()
/mob/living/silicon/robot/drone/proc/shut_down(force=FALSE)
if(stat == 2)
if(stat == DEAD)
return
if(emagged && !force)
@@ -38,16 +38,35 @@
/obj/item/gripper/paperwork
name = "paperwork gripper"
desc = "A simple grasping tool for clerical work."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
can_hold = list(
/obj/item/clipboard,
/obj/item/paper,
// /obj/item/paper_bundle,
/obj/item/card/id
)
/obj/item/gripper/medical
name = "medical gripper"
desc = "A grasping tool used to help patients up once surgery is complete."
can_hold = list()
/obj/item/gripper/medical/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
var/mob/living/carbon/human/H
if(!wrapped && proximity && target && ishuman(target))
H = target
if(H.lying)
H.AdjustSleeping(-5)
if(H.sleeping == 0)
H.StopResting()
H.AdjustParalysis(-3)
H.AdjustStunned(-3)
H.AdjustWeakened(-3)
playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
user.visible_message( \
"<span class='notice'>[user] shakes [H] trying to wake [H.p_them()] up!</span>",\
"<span class='notice'>You shake [H] trying to wake [H.p_them()] up!</span>",\
)
/obj/item/gripper/New()
..()
can_hold = typecacheof(can_hold)
@@ -1,15 +1,14 @@
/mob/living/silicon/robot/drone/say(var/message, var/datum/language/speaking = null)
/mob/living/silicon/robot/drone/say(var/message)
if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2))
if(!speaking)
speaking = parse_language(message)
if(!speaking)
speaking = istype(get_default_language(), /datum/language) ? get_default_language() : GLOB.all_languages[get_default_language()]
message = speaking.key + " " + message; // Prepend key to prevent the message from getting trimmed
if(speaking)
return ..()
return ..()
/mob/living/silicon/robot/drone/whisper_say(var/message, var/datum/language/speaking = null, var/verb="whispers")
say(message) //drones do not get to whisper, only speak normally
return 1
/mob/living/silicon/robot/drone/whisper_say(list/message_pieces)
say(multilingual_to_message(message_pieces)) //drones do not get to whisper, only speak normally
return 1
/mob/living/silicon/robot/drone/get_default_language()
if(default_language)
return default_language
return GLOB.all_languages["Drone"]
@@ -230,7 +230,7 @@
if(on_fire)
overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state"="Generic_mob_burning")
/mob/living/silicon/robot/fire_act()
/mob/living/silicon/robot/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()

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