mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-26 21:48:21 +01:00
Merge remote-tracking branch 'upstream/master' into fix-cqc
# Conflicts: # code/game/objects/items.dm
This commit is contained in:
@@ -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,3 +3,6 @@
|
||||
|
||||
/mob/dead/gib() //ghosts can't be gibbed.
|
||||
return
|
||||
|
||||
/mob/dead
|
||||
move_resist = INFINITY
|
||||
@@ -7,5 +7,3 @@
|
||||
if(GLOB.non_respawnable_keys[ckey])
|
||||
can_reenter_corpse = 0
|
||||
GLOB.respawnable_list -= src
|
||||
|
||||
update_interface()
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 .
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
if(mind.active)
|
||||
Sleeping(2)
|
||||
player_logged = 1
|
||||
last_logout = world.time
|
||||
last_logout = world.time
|
||||
+81
-122
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 += " <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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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] </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] </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] </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] </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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user