File standardisation (#13131)

* Adds the check components

* Adds in trailing newlines

* Converts all CRLF to LF

* Post merge EOF

* Post merge line endings

* Final commit
This commit is contained in:
AffectedArc07
2020-03-17 22:08:51 +00:00
committed by GitHub
parent ec19ea3d2d
commit 04ba5c1cc9
1451 changed files with 183694 additions and 183593 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
Creature-level abilities.
*/
/var/global/list/ability_verbs = list( )
/var/global/list/ability_verbs = list( )
+1 -1
View File
@@ -30,4 +30,4 @@
SSmobs.dead_players_by_zlevel[new_z] += src
registered_z = new_z
else
registered_z = null
registered_z = null
+1 -1
View File
@@ -5,4 +5,4 @@
return
/mob/dead
move_resist = INFINITY
move_resist = INFINITY
+9 -9
View File
@@ -1,9 +1,9 @@
/mob/dead/observer/Login()
..()
if(ghostimage)
ghostimage.icon_state = src.icon_state
updateghostimages()
if(GLOB.non_respawnable_keys[ckey])
can_reenter_corpse = 0
GLOB.respawnable_list -= src
/mob/dead/observer/Login()
..()
if(ghostimage)
ghostimage.icon_state = src.icon_state
updateghostimages()
if(GLOB.non_respawnable_keys[ckey])
can_reenter_corpse = 0
GLOB.respawnable_list -= src
+7 -7
View File
@@ -1,7 +1,7 @@
/mob/dead/observer/Logout()
if(client)
client.images -= ghost_images
..()
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
qdel(src)
/mob/dead/observer/Logout()
if(client)
client.images -= ghost_images
..()
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
qdel(src)
File diff suppressed because it is too large Load Diff
+48 -48
View File
@@ -1,48 +1,48 @@
/mob/dead/observer/say(var/message)
message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN))
if(!message)
return
log_ghostsay(message, src)
if(src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='warning'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
. = src.say_dead(message)
/mob/dead/observer/emote(act, type, message, force)
message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN))
if(!message)
return
if(act != "me")
return
log_ghostemote(message, src)
if(src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='warning'>You cannot emote in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT))
return
. = src.emote_dead(message)
/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)
var/speaker_name = ..()
if(speaker && (speaker_name != speaker.real_name) && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
speaker_name = "[speaker.real_name] ([speaker_name])"
return speaker_name
/mob/dead/observer/say(var/message)
message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN))
if(!message)
return
log_ghostsay(message, src)
if(src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='warning'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
. = src.say_dead(message)
/mob/dead/observer/emote(act, type, message, force)
message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN))
if(!message)
return
if(act != "me")
return
log_ghostemote(message, src)
if(src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='warning'>You cannot emote in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT))
return
. = src.emote_dead(message)
/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)
var/speaker_name = ..()
if(speaker && (speaker_name != speaker.real_name) && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
speaker_name = "[speaker.real_name] ([speaker_name])"
return speaker_name
+1 -1
View File
@@ -179,4 +179,4 @@
name = speaker.voice_name
var/rendered = "<span class='game say'><span class='name'>[name]</span> [message]</span>"
to_chat(src, rendered)
to_chat(src, rendered)
+265 -265
View File
@@ -1,265 +1,265 @@
//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc
//as they handle all relevant stuff like adding it to the player's screen and updating their overlays.
//Returns the thing in our active hand
/mob/proc/get_active_hand()
if(hand) return l_hand
else return r_hand
/mob/verb/quick_equip()
set name = "quick-equip"
set hidden = 1
var/obj/item/I = get_active_hand()
if(I)
I.equip_to_best_slot(src)
/mob/proc/is_in_active_hand(obj/item/I)
var/obj/item/item_to_test = get_active_hand()
return item_to_test && item_to_test.is_equivalent(I)
//Returns the thing in our inactive hand
/mob/proc/get_inactive_hand()
if(hand) return r_hand
else return l_hand
/mob/proc/is_in_inactive_hand(obj/item/I)
var/obj/item/item_to_test = get_inactive_hand()
return item_to_test && item_to_test.is_equivalent(I)
//Returns if a certain item can be equipped to a certain slot.
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0)
return 0
// Because there's several different places it's stored.
/mob/proc/get_multitool(var/if_active=0)
return null
//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_l_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = ABOVE_HUD_LAYER //TODO: move to equipped?
W.plane = ABOVE_HUD_PLANE //TODO: move to equipped?
W.equipped(src,slot_l_hand)
if(pulling == W)
stop_pulling()
update_inv_l_hand()
return 1
return 0
//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_r_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = ABOVE_HUD_LAYER
W.plane = ABOVE_HUD_PLANE
W.equipped(src,slot_r_hand)
if(pulling == W)
stop_pulling()
update_inv_r_hand()
return 1
return 0
/mob/proc/put_in_hand_check(var/obj/item/W)
if(lying && !(W.flags & ABSTRACT)) return 0
if(!istype(W)) return 0
return 1
//Puts the item into our active hand if possible. returns 1 on success.
/mob/proc/put_in_active_hand(var/obj/item/W)
if(hand) return put_in_l_hand(W)
else return put_in_r_hand(W)
//Puts the item into our inactive hand if possible. returns 1 on success.
/mob/proc/put_in_inactive_hand(var/obj/item/W)
if(hand) return put_in_r_hand(W)
else return put_in_l_hand(W)
//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success.
//If both fail it drops it on the floor and returns 0.
//This is probably the main one you need to know :)
//Just puts stuff on the floor for most mobs, since all mobs have hands but putting stuff in the AI/corgi/ghost hand is VERY BAD.
/mob/proc/put_in_hands(obj/item/W)
W.forceMove(drop_location())
W.layer = initial(W.layer)
W.plane = initial(W.plane)
W.dropped()
/mob/proc/drop_item_v() //this is dumb.
if(stat == CONSCIOUS && isturf(loc))
return drop_item()
return 0
//Drops the item in our left hand
/mob/proc/drop_l_hand()
return unEquip(l_hand) //All needed checks are in unEquip
//Drops the item in our right hand
/mob/proc/drop_r_hand()
return unEquip(r_hand) //Why was this not calling unEquip in the first place jesus fuck.
//Drops the item in our active hand.
/mob/proc/drop_item() //THIS. DOES. NOT. NEED. AN. ARGUMENT.
if(hand)
return drop_l_hand()
else
return drop_r_hand()
//Here lie unEquip and before_item_take, already forgotten and not missed.
/mob/proc/canUnEquip(obj/item/I, force)
if(!I)
return 1
if((I.flags & NODROP) && !force)
return 0
return 1
/mob/proc/unEquip(obj/item/I, force) //Force overrides NODROP for things like wizarditis and admin undress.
if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP.
return 1
if(!canUnEquip(I, force))
return 0
if(I == r_hand)
r_hand = null
update_inv_r_hand()
else if(I == l_hand)
l_hand = null
update_inv_l_hand()
else if(I in tkgrabbed_objects)
var/obj/item/tk_grab/tkgrab = tkgrabbed_objects[I]
unEquip(tkgrab, force)
if(I)
if(client)
client.screen -= I
I.forceMove(drop_location())
I.dropped(src)
if(I)
I.layer = initial(I.layer)
I.plane = initial(I.plane)
return 1
//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob.
/mob/proc/remove_from_mob(var/obj/O)
unEquip(O)
O.screen_loc = null
return 1
//Outdated but still in use apparently. This should at least be a human proc.
//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
/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)
if(src != M.get_active_hand())
to_chat(M, "<span class='warning'>You are not holding anything to equip!</span>")
return 0
if(M.equip_to_appropriate_slot(src))
if(M.hand)
M.update_inv_l_hand(0)
else
M.update_inv_r_hand(0)
return 1
if(M.s_active && M.s_active.can_be_inserted(src, 1)) //if storage active insert there
M.s_active.handle_item_insertion(src)
return 1
var/obj/item/storage/S = M.get_inactive_hand()
if(istype(S) && S.can_be_inserted(src, 1)) //see if we have box in other hand
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_belt)
if(istype(S) && S.can_be_inserted(src, 1)) //else we put in belt
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_back) //else we put in backpack
if(istype(S) && S.can_be_inserted(src, 1))
S.handle_item_insertion(src)
playsound(loc, "rustle", 50, 1, -5)
return 1
to_chat(M, "<span class='warning'>You are unable to equip that!</span>")
return 0
/mob/proc/get_all_slots()
return list(wear_mask, back, l_hand, r_hand)
/mob/proc/get_id_card()
for(var/obj/item/I in get_all_slots())
. = I.GetID()
if(.)
break
/mob/proc/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_wear_mask)
return wear_mask
if(slot_back)
return back
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
return null
//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc
//as they handle all relevant stuff like adding it to the player's screen and updating their overlays.
//Returns the thing in our active hand
/mob/proc/get_active_hand()
if(hand) return l_hand
else return r_hand
/mob/verb/quick_equip()
set name = "quick-equip"
set hidden = 1
var/obj/item/I = get_active_hand()
if(I)
I.equip_to_best_slot(src)
/mob/proc/is_in_active_hand(obj/item/I)
var/obj/item/item_to_test = get_active_hand()
return item_to_test && item_to_test.is_equivalent(I)
//Returns the thing in our inactive hand
/mob/proc/get_inactive_hand()
if(hand) return r_hand
else return l_hand
/mob/proc/is_in_inactive_hand(obj/item/I)
var/obj/item/item_to_test = get_inactive_hand()
return item_to_test && item_to_test.is_equivalent(I)
//Returns if a certain item can be equipped to a certain slot.
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0)
return 0
// Because there's several different places it's stored.
/mob/proc/get_multitool(var/if_active=0)
return null
//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_l_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = ABOVE_HUD_LAYER //TODO: move to equipped?
W.plane = ABOVE_HUD_PLANE //TODO: move to equipped?
W.equipped(src,slot_l_hand)
if(pulling == W)
stop_pulling()
update_inv_l_hand()
return 1
return 0
//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success.
/mob/proc/put_in_r_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = ABOVE_HUD_LAYER
W.plane = ABOVE_HUD_PLANE
W.equipped(src,slot_r_hand)
if(pulling == W)
stop_pulling()
update_inv_r_hand()
return 1
return 0
/mob/proc/put_in_hand_check(var/obj/item/W)
if(lying && !(W.flags & ABSTRACT)) return 0
if(!istype(W)) return 0
return 1
//Puts the item into our active hand if possible. returns 1 on success.
/mob/proc/put_in_active_hand(var/obj/item/W)
if(hand) return put_in_l_hand(W)
else return put_in_r_hand(W)
//Puts the item into our inactive hand if possible. returns 1 on success.
/mob/proc/put_in_inactive_hand(var/obj/item/W)
if(hand) return put_in_r_hand(W)
else return put_in_l_hand(W)
//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success.
//If both fail it drops it on the floor and returns 0.
//This is probably the main one you need to know :)
//Just puts stuff on the floor for most mobs, since all mobs have hands but putting stuff in the AI/corgi/ghost hand is VERY BAD.
/mob/proc/put_in_hands(obj/item/W)
W.forceMove(drop_location())
W.layer = initial(W.layer)
W.plane = initial(W.plane)
W.dropped()
/mob/proc/drop_item_v() //this is dumb.
if(stat == CONSCIOUS && isturf(loc))
return drop_item()
return 0
//Drops the item in our left hand
/mob/proc/drop_l_hand()
return unEquip(l_hand) //All needed checks are in unEquip
//Drops the item in our right hand
/mob/proc/drop_r_hand()
return unEquip(r_hand) //Why was this not calling unEquip in the first place jesus fuck.
//Drops the item in our active hand.
/mob/proc/drop_item() //THIS. DOES. NOT. NEED. AN. ARGUMENT.
if(hand)
return drop_l_hand()
else
return drop_r_hand()
//Here lie unEquip and before_item_take, already forgotten and not missed.
/mob/proc/canUnEquip(obj/item/I, force)
if(!I)
return 1
if((I.flags & NODROP) && !force)
return 0
return 1
/mob/proc/unEquip(obj/item/I, force) //Force overrides NODROP for things like wizarditis and admin undress.
if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP.
return 1
if(!canUnEquip(I, force))
return 0
if(I == r_hand)
r_hand = null
update_inv_r_hand()
else if(I == l_hand)
l_hand = null
update_inv_l_hand()
else if(I in tkgrabbed_objects)
var/obj/item/tk_grab/tkgrab = tkgrabbed_objects[I]
unEquip(tkgrab, force)
if(I)
if(client)
client.screen -= I
I.forceMove(drop_location())
I.dropped(src)
if(I)
I.layer = initial(I.layer)
I.plane = initial(I.plane)
return 1
//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob.
/mob/proc/remove_from_mob(var/obj/O)
unEquip(O)
O.screen_loc = null
return 1
//Outdated but still in use apparently. This should at least be a human proc.
//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
/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)
if(src != M.get_active_hand())
to_chat(M, "<span class='warning'>You are not holding anything to equip!</span>")
return 0
if(M.equip_to_appropriate_slot(src))
if(M.hand)
M.update_inv_l_hand(0)
else
M.update_inv_r_hand(0)
return 1
if(M.s_active && M.s_active.can_be_inserted(src, 1)) //if storage active insert there
M.s_active.handle_item_insertion(src)
return 1
var/obj/item/storage/S = M.get_inactive_hand()
if(istype(S) && S.can_be_inserted(src, 1)) //see if we have box in other hand
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_belt)
if(istype(S) && S.can_be_inserted(src, 1)) //else we put in belt
S.handle_item_insertion(src)
return 1
S = M.get_item_by_slot(slot_back) //else we put in backpack
if(istype(S) && S.can_be_inserted(src, 1))
S.handle_item_insertion(src)
playsound(loc, "rustle", 50, 1, -5)
return 1
to_chat(M, "<span class='warning'>You are unable to equip that!</span>")
return 0
/mob/proc/get_all_slots()
return list(wear_mask, back, l_hand, r_hand)
/mob/proc/get_id_card()
for(var/obj/item/I in get_all_slots())
. = I.GetID()
if(.)
break
/mob/proc/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_wear_mask)
return wear_mask
if(slot_back)
return back
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
return null
+1 -1
View File
@@ -16,4 +16,4 @@
#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
+308 -308
View File
@@ -1,308 +1,308 @@
/mob/living/carbon/alien
name = "alien"
voice_name = "alien"
speak_emote = list("hisses")
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
alien_talk_understand = TRUE
var/nightvision = FALSE
see_in_dark = 4
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = FALSE
var/move_delay_add = FALSE // movement delay to add
status_flags = CANPARALYSE|CANPUSH
var/heal_rate = 5
var/large = FALSE
var/heat_protection = 0.5
var/leaping = FALSE
ventcrawler = 2
var/list/alien_organs = list()
var/death_message = "lets out a waning guttural screech, green blood bubbling from its maw..."
var/death_sound = 'sound/voice/hiss6.ogg'
/mob/living/carbon/alien/New()
verbs += /mob/living/verb/mob_sleep
verbs += /mob/living/verb/lay_down
alien_organs += new /obj/item/organ/internal/brain/xeno
alien_organs += new /obj/item/organ/internal/xenos/hivenode
alien_organs += new /obj/item/organ/internal/ears
for(var/obj/item/organ/internal/I in alien_organs)
I.insert(src)
..()
/mob/living/carbon/alien/get_default_language()
if(default_language)
return default_language
return GLOB.all_languages["Xenomorph"]
/mob/living/carbon/alien/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "hisses"
var/ending = copytext(message, length(message))
if(speaking && (speaking.name != "Galactic Common")) //this is so adminbooze xenos speaking common have their custom verbs,
verb = speaking.get_spoken_verb(ending) //and use normal verbs for their own languages and non-common languages
else
if(ending=="!")
verb = "roars"
else if(ending=="?")
verb = "hisses curiously"
return verb
/mob/living/carbon/alien/adjustToxLoss(amount)
return STATUS_UPDATE_NONE
/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire
if(amount > 0)
return ..(amount * 2)
else
return ..(amount)
/mob/living/carbon/alien/check_eye_prot()
return 2
/mob/living/carbon/alien/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = maxHealth
stat = CONSCIOUS
return
health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
update_stat("updatehealth([reason])")
med_hud_set_health()
med_hud_set_status()
handle_hud_icons_health()
/mob/living/carbon/alien/handle_environment(var/datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
// to_chat(world, "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Fire protection: [heat_protection] - Location: [loc] - src: [src]")
// Aliens are now weak to fire.
//After then, it reacts to the surrounding atmosphere based on your thermal protection
if(!on_fire) // If you're on fire, ignore local air temperature
if(loc_temp > bodytemperature)
//Place is hotter than we are
var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
else
bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
// bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
// +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt.
if(bodytemperature > 360.15)
//Body temperature is too hot.
throw_alert("alien_fire", /obj/screen/alert/alien_fire)
switch(bodytemperature)
if(360 to 400)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else
clear_alert("alien_fire")
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
/mob/living/carbon/alien/IsAdvancedToolUser()
return has_fine_manipulation
/mob/living/carbon/alien/Stat()
..()
statpanel("Status")
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
show_stat_emergency_shuttle_eta()
/mob/living/carbon/alien/SetStunned(amount, updating = 1, force = 0)
..()
if(!(status_flags & CANSTUN) && amount)
// add some movement delay
move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10
/mob/living/carbon/alien/movement_delay()
. = ..()
. += move_delay_add + config.alien_delay //move_delay_add is used to slow aliens with stuns
/mob/living/carbon/alien/getDNA()
return null
/mob/living/carbon/alien/setDNA()
return
/mob/living/carbon/alien/verb/nightvisiontoggle()
set name = "Toggle Night Vision"
set category = "Alien"
if(!nightvision)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
nightvision = TRUE
usr.hud_used.nightvisionicon.icon_state = "nightvision1"
else if(nightvision)
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
nightvision = FALSE
usr.hud_used.nightvisionicon.icon_state = "nightvision0"
update_sight()
/mob/living/carbon/alien/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor)
if(judgebot.emagged == 2)
return 10 //Everyone is a criminal!
var/threatcount = 0
//Securitrons can't identify aliens
if(!lasercolor && judgebot.idcheck)
threatcount += 4
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if((istype(r_hand,/obj/item/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/tag/blue)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/blue)))
threatcount += 4
return threatcount
//Check for weapons
if(judgebot.weaponscheck)
if(judgebot.check_for_weapons(l_hand))
threatcount += 4
if(judgebot.check_for_weapons(r_hand))
threatcount += 4
//Mindshield implants imply trustworthyness
if(ismindshielded(src))
threatcount -= 1
return threatcount
/*----------------------------------------
Proc: AddInfectionImages()
Des: Gives the client of the alien an image on each infected mob.
----------------------------------------*/
/mob/living/carbon/alien/proc/AddInfectionImages()
if(client)
for(var/mob/living/C in GLOB.mob_list)
if(C.status_flags & XENO_HOST)
var/obj/item/organ/internal/body_egg/alien_embryo/A = C.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo)
if(A)
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
client.images += I
return
/*----------------------------------------
Proc: RemoveInfectionImages()
Des: Removes all infected images from the alien.
----------------------------------------*/
/mob/living/carbon/alien/proc/RemoveInfectionImages()
if(client)
for(var/image/I in client.images)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
return
/mob/living/carbon/alien/canBeHandcuffed()
return 1
/mob/living/carbon/alien/proc/updatePlasmaDisplay()
if(hud_used) //clientless aliens
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='magenta'>[getPlasma()]</font></div>"
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
return
/mob/living/carbon/alien/can_use_vents()
return
/mob/living/carbon/alien/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["xeno"])
var/S = pick(T.footstep_sounds["xeno"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
if(!(step_count % 2)) //every other turf makes a sound
return 0
var/range = -(world.view - 2)
range -= 0.666 //-(7 - 2) = (-5) = -5 | -5 - (0.666) = -5.666 | (7 + -5.666) = 1.334 | 1.334 * 3 = 4.002 | range(4.002) = range(4)
var/volume = 5
if(m_intent == MOVE_INTENT_WALK)
return 0 //silent when walking
if(buckled || lying || throwing)
return 0 //people flying, lying down or sitting do not step
if(!has_gravity(src))
if(step_count % 3) //this basically says, every three moves make a noise
return 0 //1st - none, 1%3==1, 2nd - none, 2%3==2, 3rd - noise, 3%3==0
playsound(T, S, volume, 1, range)
return 1
return 0
/mob/living/carbon/alien/getTrail()
if(getBruteLoss() < 200)
return pick("xltrails_1", "xltrails_2")
else
return pick("xttrails_1", "xttrails_2")
/mob/living/carbon/alien/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
see_invisible = initial(see_invisible)
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
else
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.see_in_dark)
see_in_dark = max(see_in_dark, E.see_in_dark)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(!isnull(E.lighting_alpha))
lighting_alpha = min(lighting_alpha, E.lighting_alpha)
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
/mob/living/carbon/alien
name = "alien"
voice_name = "alien"
speak_emote = list("hisses")
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
alien_talk_understand = TRUE
var/nightvision = FALSE
see_in_dark = 4
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = FALSE
var/move_delay_add = FALSE // movement delay to add
status_flags = CANPARALYSE|CANPUSH
var/heal_rate = 5
var/large = FALSE
var/heat_protection = 0.5
var/leaping = FALSE
ventcrawler = 2
var/list/alien_organs = list()
var/death_message = "lets out a waning guttural screech, green blood bubbling from its maw..."
var/death_sound = 'sound/voice/hiss6.ogg'
/mob/living/carbon/alien/New()
verbs += /mob/living/verb/mob_sleep
verbs += /mob/living/verb/lay_down
alien_organs += new /obj/item/organ/internal/brain/xeno
alien_organs += new /obj/item/organ/internal/xenos/hivenode
alien_organs += new /obj/item/organ/internal/ears
for(var/obj/item/organ/internal/I in alien_organs)
I.insert(src)
..()
/mob/living/carbon/alien/get_default_language()
if(default_language)
return default_language
return GLOB.all_languages["Xenomorph"]
/mob/living/carbon/alien/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "hisses"
var/ending = copytext(message, length(message))
if(speaking && (speaking.name != "Galactic Common")) //this is so adminbooze xenos speaking common have their custom verbs,
verb = speaking.get_spoken_verb(ending) //and use normal verbs for their own languages and non-common languages
else
if(ending=="!")
verb = "roars"
else if(ending=="?")
verb = "hisses curiously"
return verb
/mob/living/carbon/alien/adjustToxLoss(amount)
return STATUS_UPDATE_NONE
/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire
if(amount > 0)
return ..(amount * 2)
else
return ..(amount)
/mob/living/carbon/alien/check_eye_prot()
return 2
/mob/living/carbon/alien/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = maxHealth
stat = CONSCIOUS
return
health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
update_stat("updatehealth([reason])")
med_hud_set_health()
med_hud_set_status()
handle_hud_icons_health()
/mob/living/carbon/alien/handle_environment(var/datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
// to_chat(world, "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Fire protection: [heat_protection] - Location: [loc] - src: [src]")
// Aliens are now weak to fire.
//After then, it reacts to the surrounding atmosphere based on your thermal protection
if(!on_fire) // If you're on fire, ignore local air temperature
if(loc_temp > bodytemperature)
//Place is hotter than we are
var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
else
bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
// bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
// +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt.
if(bodytemperature > 360.15)
//Body temperature is too hot.
throw_alert("alien_fire", /obj/screen/alert/alien_fire)
switch(bodytemperature)
if(360 to 400)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else
clear_alert("alien_fire")
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
/mob/living/carbon/alien/IsAdvancedToolUser()
return has_fine_manipulation
/mob/living/carbon/alien/Stat()
..()
statpanel("Status")
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
show_stat_emergency_shuttle_eta()
/mob/living/carbon/alien/SetStunned(amount, updating = 1, force = 0)
..()
if(!(status_flags & CANSTUN) && amount)
// add some movement delay
move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10
/mob/living/carbon/alien/movement_delay()
. = ..()
. += move_delay_add + config.alien_delay //move_delay_add is used to slow aliens with stuns
/mob/living/carbon/alien/getDNA()
return null
/mob/living/carbon/alien/setDNA()
return
/mob/living/carbon/alien/verb/nightvisiontoggle()
set name = "Toggle Night Vision"
set category = "Alien"
if(!nightvision)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
nightvision = TRUE
usr.hud_used.nightvisionicon.icon_state = "nightvision1"
else if(nightvision)
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
nightvision = FALSE
usr.hud_used.nightvisionicon.icon_state = "nightvision0"
update_sight()
/mob/living/carbon/alien/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor)
if(judgebot.emagged == 2)
return 10 //Everyone is a criminal!
var/threatcount = 0
//Securitrons can't identify aliens
if(!lasercolor && judgebot.idcheck)
threatcount += 4
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if((istype(r_hand,/obj/item/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/tag/blue)) || (istype(l_hand,/obj/item/gun/energy/laser/tag/blue)))
threatcount += 4
return threatcount
//Check for weapons
if(judgebot.weaponscheck)
if(judgebot.check_for_weapons(l_hand))
threatcount += 4
if(judgebot.check_for_weapons(r_hand))
threatcount += 4
//Mindshield implants imply trustworthyness
if(ismindshielded(src))
threatcount -= 1
return threatcount
/*----------------------------------------
Proc: AddInfectionImages()
Des: Gives the client of the alien an image on each infected mob.
----------------------------------------*/
/mob/living/carbon/alien/proc/AddInfectionImages()
if(client)
for(var/mob/living/C in GLOB.mob_list)
if(C.status_flags & XENO_HOST)
var/obj/item/organ/internal/body_egg/alien_embryo/A = C.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo)
if(A)
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
client.images += I
return
/*----------------------------------------
Proc: RemoveInfectionImages()
Des: Removes all infected images from the alien.
----------------------------------------*/
/mob/living/carbon/alien/proc/RemoveInfectionImages()
if(client)
for(var/image/I in client.images)
if(dd_hasprefix_case(I.icon_state, "infected"))
qdel(I)
return
/mob/living/carbon/alien/canBeHandcuffed()
return 1
/mob/living/carbon/alien/proc/updatePlasmaDisplay()
if(hud_used) //clientless aliens
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'> <font color='magenta'>[getPlasma()]</font></div>"
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
return
/mob/living/carbon/alien/can_use_vents()
return
/mob/living/carbon/alien/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["xeno"])
var/S = pick(T.footstep_sounds["xeno"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
if(!(step_count % 2)) //every other turf makes a sound
return 0
var/range = -(world.view - 2)
range -= 0.666 //-(7 - 2) = (-5) = -5 | -5 - (0.666) = -5.666 | (7 + -5.666) = 1.334 | 1.334 * 3 = 4.002 | range(4.002) = range(4)
var/volume = 5
if(m_intent == MOVE_INTENT_WALK)
return 0 //silent when walking
if(buckled || lying || throwing)
return 0 //people flying, lying down or sitting do not step
if(!has_gravity(src))
if(step_count % 3) //this basically says, every three moves make a noise
return 0 //1st - none, 1%3==1, 2nd - none, 2%3==2, 3rd - noise, 3%3==0
playsound(T, S, volume, 1, range)
return 1
return 0
/mob/living/carbon/alien/getTrail()
if(getBruteLoss() < 200)
return pick("xltrails_1", "xltrails_2")
else
return pick("xttrails_1", "xttrails_2")
/mob/living/carbon/alien/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
see_invisible = initial(see_invisible)
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
else
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.see_in_dark)
see_in_dark = max(see_in_dark, E.see_in_dark)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(!isnull(E.lighting_alpha))
lighting_alpha = min(lighting_alpha, E.lighting_alpha)
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -80,4 +80,4 @@ In all, this is a lot like the monkey code. /N
damage = rand(10, 40)
adjustBruteLoss(damage)
add_attack_logs(M, src, "Slime'd for [damage] damage")
updatehealth("slime attack")
updatehealth("slime attack")
@@ -1,170 +1,170 @@
/*NOTES:
These are general powers. Specific powers are stored under the appropriate alien creature type.
*/
/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit.
Doesn't work on other aliens/AI.*/
/mob/living/carbon/proc/powerc(X, Y)//Y is optional, checks for weed planting. X can be null.
if(stat)
to_chat(src, "<span class='noticealien'>You must be conscious to do this.</span>")
return 0
else if(X && getPlasma() < X)
to_chat(src, "<span class='noticealien'>Not enough plasma stored.</span>")
return 0
else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space)))
to_chat(src, "<span class='noticealien'>You can't place that here!</span>")
return 0
else return 1
/mob/living/carbon/alien/humanoid/verb/plant()
set name = "Plant Weeds (50)"
set desc = "Plants some alien weeds"
set category = "Alien"
if(locate(/obj/structure/alien/weeds/node) in get_turf(src))
to_chat(src, "<span class='noticealien'>There's already a weed node here.</span>")
return
if(powerc(50,1))
adjustPlasma(-50)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] has planted some alien weeds!</span>"), 1)
new /obj/structure/alien/weeds/node(loc)
return
/mob/living/carbon/alien/humanoid/verb/whisp(mob/M as mob in oview())
set name = "Whisper (10)"
set desc = "Whisper to someone"
set category = "Alien"
if(powerc(10))
adjustPlasma(-10)
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
log_say("(AWHISPER to [key_name(M)]) [msg]", src)
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...<span class='noticealien'>[msg]")
to_chat(src, "<span class='noticealien'>You said: [msg] to [M]</span>")
for(var/mob/dead/observer/G in GLOB.player_list)
G.show_message("<i>Alien message from <b>[src]</b> ([ghost_follow_link(src, ghost=G)]) to <b>[M]</b> ([ghost_follow_link(M, ghost=G)]): [msg]</i>")
return
/mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview())
set name = "Transfer Plasma"
set desc = "Transfer Plasma to another alien"
set category = "Alien"
if(isalien(M))
var/amount = input("Amount:", "Transfer Plasma to [M]") as num
if(amount)
amount = abs(round(amount))
if(powerc(amount))
if(get_dist(src,M) <= 1)
M.adjustPlasma(amount)
adjustPlasma(-amount)
to_chat(M, "<span class='noticealien'>[src] has transfered [amount] plasma to you.</span>")
to_chat(src, {"<span class='noticealien'>You have trasferred [amount] plasma to [M]</span>"})
else
to_chat(src, "<span class='noticealien'>You need to be closer.</span>")
return
/mob/living/carbon/alien/humanoid/proc/corrosive_acid(atom/target) //If they right click to corrode, an error will flash if its an invalid target./N
set name = "Corrossive Acid (200)"
set desc = "Drench an object in acid, destroying it over time."
set category = "Alien"
if(powerc(200))
if(target in oview(1))
if(target.acid_act(200, 100))
visible_message("<span class='alertalien'>[src] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!</span>")
adjustPlasma(-200)
else
to_chat(src, "<span class='noticealien'>You cannot dissolve this object.</span>")
else
to_chat(src, "<span class='noticealien'>[target] is too far away.</span>")
/mob/living/carbon/alien/humanoid/proc/neurotoxin() // ok
set name = "Spit Neurotoxin (50)"
set desc = "Spits neurotoxin at someone, paralyzing them for a short time."
set category = "Alien"
if(powerc(50))
adjustPlasma(-50)
src.visible_message("<span class='danger'>[src] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/turf/T = loc
var/turf/U = get_step(src, dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(usr.loc)
A.current = U
A.firer = src
A.yo = U.y - T.y
A.xo = U.x - T.x
A.fire()
A.newtonian_move(get_dir(U, T))
newtonian_move(get_dir(U, T))
return
/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE
set name = "Secrete Resin (55)"
set desc = "Secrete tough malleable resin."
set category = "Alien"
if(powerc(55))
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
if(!choice || !powerc(55)) return
adjustPlasma(-55)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] vomits up a thick purple substance and shapes it!</span>"), 1)
switch(choice)
if("resin wall")
new /obj/structure/alien/resin/wall(loc)
if("resin membrane")
new /obj/structure/alien/resin/membrane(loc)
if("resin nest")
new /obj/structure/bed/nest(loc)
return
/mob/living/carbon/alien/humanoid/verb/regurgitate()
set name = "Regurgitate"
set desc = "Empties the contents of your stomach"
set category = "Alien"
if(powerc())
if(stomach_contents.len)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(loc)
//Paralyse(10)
src.visible_message("<span class='alertalien'><B>[src] hurls out the contents of [p_their()] stomach!</span>")
return
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
if(!vessel) return 0
return vessel.stored_plasma
/mob/living/carbon/proc/adjustPlasma(amount)
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
if(!vessel) return
vessel.stored_plasma = max(vessel.stored_plasma + amount,0)
vessel.stored_plasma = min(vessel.stored_plasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
return 1
/mob/living/carbon/alien/adjustPlasma(amount)
. = ..()
updatePlasmaDisplay()
/mob/living/carbon/proc/usePlasma(amount)
if(getPlasma() >= amount)
adjustPlasma(-amount)
return 1
return 0
/*NOTES:
These are general powers. Specific powers are stored under the appropriate alien creature type.
*/
/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit.
Doesn't work on other aliens/AI.*/
/mob/living/carbon/proc/powerc(X, Y)//Y is optional, checks for weed planting. X can be null.
if(stat)
to_chat(src, "<span class='noticealien'>You must be conscious to do this.</span>")
return 0
else if(X && getPlasma() < X)
to_chat(src, "<span class='noticealien'>Not enough plasma stored.</span>")
return 0
else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space)))
to_chat(src, "<span class='noticealien'>You can't place that here!</span>")
return 0
else return 1
/mob/living/carbon/alien/humanoid/verb/plant()
set name = "Plant Weeds (50)"
set desc = "Plants some alien weeds"
set category = "Alien"
if(locate(/obj/structure/alien/weeds/node) in get_turf(src))
to_chat(src, "<span class='noticealien'>There's already a weed node here.</span>")
return
if(powerc(50,1))
adjustPlasma(-50)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] has planted some alien weeds!</span>"), 1)
new /obj/structure/alien/weeds/node(loc)
return
/mob/living/carbon/alien/humanoid/verb/whisp(mob/M as mob in oview())
set name = "Whisper (10)"
set desc = "Whisper to someone"
set category = "Alien"
if(powerc(10))
adjustPlasma(-10)
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
log_say("(AWHISPER to [key_name(M)]) [msg]", src)
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...<span class='noticealien'>[msg]")
to_chat(src, "<span class='noticealien'>You said: [msg] to [M]</span>")
for(var/mob/dead/observer/G in GLOB.player_list)
G.show_message("<i>Alien message from <b>[src]</b> ([ghost_follow_link(src, ghost=G)]) to <b>[M]</b> ([ghost_follow_link(M, ghost=G)]): [msg]</i>")
return
/mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview())
set name = "Transfer Plasma"
set desc = "Transfer Plasma to another alien"
set category = "Alien"
if(isalien(M))
var/amount = input("Amount:", "Transfer Plasma to [M]") as num
if(amount)
amount = abs(round(amount))
if(powerc(amount))
if(get_dist(src,M) <= 1)
M.adjustPlasma(amount)
adjustPlasma(-amount)
to_chat(M, "<span class='noticealien'>[src] has transfered [amount] plasma to you.</span>")
to_chat(src, {"<span class='noticealien'>You have trasferred [amount] plasma to [M]</span>"})
else
to_chat(src, "<span class='noticealien'>You need to be closer.</span>")
return
/mob/living/carbon/alien/humanoid/proc/corrosive_acid(atom/target) //If they right click to corrode, an error will flash if its an invalid target./N
set name = "Corrossive Acid (200)"
set desc = "Drench an object in acid, destroying it over time."
set category = "Alien"
if(powerc(200))
if(target in oview(1))
if(target.acid_act(200, 100))
visible_message("<span class='alertalien'>[src] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!</span>")
adjustPlasma(-200)
else
to_chat(src, "<span class='noticealien'>You cannot dissolve this object.</span>")
else
to_chat(src, "<span class='noticealien'>[target] is too far away.</span>")
/mob/living/carbon/alien/humanoid/proc/neurotoxin() // ok
set name = "Spit Neurotoxin (50)"
set desc = "Spits neurotoxin at someone, paralyzing them for a short time."
set category = "Alien"
if(powerc(50))
adjustPlasma(-50)
src.visible_message("<span class='danger'>[src] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/turf/T = loc
var/turf/U = get_step(src, dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(usr.loc)
A.current = U
A.firer = src
A.yo = U.y - T.y
A.xo = U.x - T.x
A.fire()
A.newtonian_move(get_dir(U, T))
newtonian_move(get_dir(U, T))
return
/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE
set name = "Secrete Resin (55)"
set desc = "Secrete tough malleable resin."
set category = "Alien"
if(powerc(55))
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
if(!choice || !powerc(55)) return
adjustPlasma(-55)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] vomits up a thick purple substance and shapes it!</span>"), 1)
switch(choice)
if("resin wall")
new /obj/structure/alien/resin/wall(loc)
if("resin membrane")
new /obj/structure/alien/resin/membrane(loc)
if("resin nest")
new /obj/structure/bed/nest(loc)
return
/mob/living/carbon/alien/humanoid/verb/regurgitate()
set name = "Regurgitate"
set desc = "Empties the contents of your stomach"
set category = "Alien"
if(powerc())
if(stomach_contents.len)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(loc)
//Paralyse(10)
src.visible_message("<span class='alertalien'><B>[src] hurls out the contents of [p_their()] stomach!</span>")
return
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
if(!vessel) return 0
return vessel.stored_plasma
/mob/living/carbon/proc/adjustPlasma(amount)
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
if(!vessel) return
vessel.stored_plasma = max(vessel.stored_plasma + amount,0)
vessel.stored_plasma = min(vessel.stored_plasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
return 1
/mob/living/carbon/alien/adjustPlasma(amount)
. = ..()
updatePlasmaDisplay()
/mob/living/carbon/proc/usePlasma(amount)
if(getPlasma() >= amount)
adjustPlasma(-amount)
return 1
return 0
@@ -1,48 +1,48 @@
/mob/living/carbon/alien/humanoid/drone
name = "alien drone"
caste = "d"
maxHealth = 100
health = 100
icon_state = "aliend_s"
/mob/living/carbon/alien/humanoid/drone/New()
create_reagents(100)
if(src.name == "alien drone")
src.name = text("alien drone ([rand(1, 1000)])")
src.real_name = src.name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/drone
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/resinspinner
..()
//Drones use the same base as generic humanoids.
//Drone verbs
/mob/living/carbon/alien/humanoid/drone/verb/evolve() // -- TLE
set name = "Evolve (500)"
set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time."
set category = "Alien"
if(powerc(500))
// Queen check
var/no_queen = 1
for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list)
if(!Q.key && Q.get_int_organ(/obj/item/organ/internal/brain/))
continue
no_queen = 0
if(src.has_brain_worms())
to_chat(src, "<span class='warning'>We cannot perform this ability at the present time!</span>")
return
if(no_queen)
adjustPlasma(-500)
to_chat(src, "<span class='noticealien'>You begin to evolve!</span>")
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] begins to twist and contort!</span>"), 1)
var/mob/living/carbon/alien/humanoid/queen/new_xeno = new(loc)
mind.transfer_to(new_xeno)
new_xeno.mind.name = new_xeno.name
qdel(src)
else
to_chat(src, "<span class='notice'>We already have an alive queen.</span>")
return
/mob/living/carbon/alien/humanoid/drone
name = "alien drone"
caste = "d"
maxHealth = 100
health = 100
icon_state = "aliend_s"
/mob/living/carbon/alien/humanoid/drone/New()
create_reagents(100)
if(src.name == "alien drone")
src.name = text("alien drone ([rand(1, 1000)])")
src.real_name = src.name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/drone
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/resinspinner
..()
//Drones use the same base as generic humanoids.
//Drone verbs
/mob/living/carbon/alien/humanoid/drone/verb/evolve() // -- TLE
set name = "Evolve (500)"
set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time."
set category = "Alien"
if(powerc(500))
// Queen check
var/no_queen = 1
for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list)
if(!Q.key && Q.get_int_organ(/obj/item/organ/internal/brain/))
continue
no_queen = 0
if(src.has_brain_worms())
to_chat(src, "<span class='warning'>We cannot perform this ability at the present time!</span>")
return
if(no_queen)
adjustPlasma(-500)
to_chat(src, "<span class='noticealien'>You begin to evolve!</span>")
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] begins to twist and contort!</span>"), 1)
var/mob/living/carbon/alien/humanoid/queen/new_xeno = new(loc)
mind.transfer_to(new_xeno)
new_xeno.mind.name = new_xeno.name
qdel(src)
else
to_chat(src, "<span class='notice'>We already have an alive queen.</span>")
return
@@ -1,131 +1,131 @@
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
maxHealth = 125
health = 125
icon_state = "alienh_s"
/mob/living/carbon/alien/humanoid/hunter/New()
create_reagents(100)
if(name == "alien hunter")
name = text("alien hunter ([rand(1, 1000)])")
real_name = name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/hunter
..()
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
. = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != 2)
switch(health)
if(125 to INFINITY)
healths.icon_state = "health0"
if(100 to 125)
healths.icon_state = "health1"
if(50 to 100)
healths.icon_state = "health2"
if(25 to 50)
healths.icon_state = "health3"
if(0 to 25)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/humanoid/hunter/handle_environment()
if(m_intent == MOVE_INTENT_RUN || resting)
..()
else
adjustPlasma(-heal_rate)
//Hunter verbs
/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(var/message = 1)
leap_on_click = !leap_on_click
leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]"
if(message)
to_chat(src, "<span class='noticealien'>You will now [leap_on_click ? "leap at":"slash at"] enemies!</span>")
else
return
/mob/living/carbon/alien/humanoid/hunter/ClickOn(var/atom/A, var/params)
face_atom(A)
if(leap_on_click)
leap_at(A)
else
..()
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(var/atom/A)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
return
if(leaping) //Leap while you leap, so you can leap while you leap
return
if(!has_gravity(src) || !has_gravity(A))
to_chat(src, "<span class='alertalien'>It is unsafe to leap without gravity!</span>")
//It's also extremely buggy visually, so it's balance+bugfix
return
if(lying)
return
else //Maybe uses plasma in the future, although that wouldn't make any sense...
leaping = 1
update_icons()
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin = 0, diagonals_first = 1, callback = CALLBACK(src, .leap_end))
/mob/living/carbon/alien/humanoid/hunter/proc/leap_end()
leaping = 0
update_icons()
/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A)
if(!leaping)
return ..()
if(A)
if(isliving(A))
var/mob/living/L = A
var/blocked = 0
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
blocked = 1
if(!blocked)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
if(ishuman(L))
var/mob/living/carbon/human/H = L
H.apply_effect(5, WEAKEN, H.run_armor_check(null, "melee"))
else
L.Weaken(5)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
else
Weaken(2, 1, 1)
toggle_leap(0)
pounce_cooldown = world.time + pounce_cooldown_time
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
Weaken(2, 1, 1)
if(leaping)
leaping = 0
update_icons()
update_canmove()
/mob/living/carbon/alien/humanoid/float(on)
if(leaping)
return
..()
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
maxHealth = 125
health = 125
icon_state = "alienh_s"
/mob/living/carbon/alien/humanoid/hunter/New()
create_reagents(100)
if(name == "alien hunter")
name = text("alien hunter ([rand(1, 1000)])")
real_name = name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/hunter
..()
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
. = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != 2)
switch(health)
if(125 to INFINITY)
healths.icon_state = "health0"
if(100 to 125)
healths.icon_state = "health1"
if(50 to 100)
healths.icon_state = "health2"
if(25 to 50)
healths.icon_state = "health3"
if(0 to 25)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/humanoid/hunter/handle_environment()
if(m_intent == MOVE_INTENT_RUN || resting)
..()
else
adjustPlasma(-heal_rate)
//Hunter verbs
/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(var/message = 1)
leap_on_click = !leap_on_click
leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]"
if(message)
to_chat(src, "<span class='noticealien'>You will now [leap_on_click ? "leap at":"slash at"] enemies!</span>")
else
return
/mob/living/carbon/alien/humanoid/hunter/ClickOn(var/atom/A, var/params)
face_atom(A)
if(leap_on_click)
leap_at(A)
else
..()
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(var/atom/A)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
return
if(leaping) //Leap while you leap, so you can leap while you leap
return
if(!has_gravity(src) || !has_gravity(A))
to_chat(src, "<span class='alertalien'>It is unsafe to leap without gravity!</span>")
//It's also extremely buggy visually, so it's balance+bugfix
return
if(lying)
return
else //Maybe uses plasma in the future, although that wouldn't make any sense...
leaping = 1
update_icons()
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin = 0, diagonals_first = 1, callback = CALLBACK(src, .leap_end))
/mob/living/carbon/alien/humanoid/hunter/proc/leap_end()
leaping = 0
update_icons()
/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A)
if(!leaping)
return ..()
if(A)
if(isliving(A))
var/mob/living/L = A
var/blocked = 0
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
blocked = 1
if(!blocked)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
if(ishuman(L))
var/mob/living/carbon/human/H = L
H.apply_effect(5, WEAKEN, H.run_armor_check(null, "melee"))
else
L.Weaken(5)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
else
Weaken(2, 1, 1)
toggle_leap(0)
pounce_cooldown = world.time + pounce_cooldown_time
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
Weaken(2, 1, 1)
if(leaping)
leaping = 0
update_icons()
update_canmove()
/mob/living/carbon/alien/humanoid/float(on)
if(leaping)
return
..()
@@ -1,85 +1,85 @@
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
maxHealth = 150
health = 150
icon_state = "aliens_s"
/mob/living/carbon/alien/humanoid/sentinel/large
name = "alien praetorian"
icon = 'icons/mob/alienlarge.dmi'
icon_state = "prat_s"
pixel_x = -16
maxHealth = 200
health = 200
large = 1
/mob/living/carbon/alien/humanoid/sentinel/praetorian
name = "alien praetorian"
maxHealth = 200
health = 200
large = 1
/mob/living/carbon/alien/humanoid/sentinel/large/update_icons()
overlays.Cut()
if(stat == DEAD)
icon_state = "prat_dead"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "prat_sleep"
else
icon_state = "prat_s"
for(var/image/I in overlays_standing)
overlays += I
/mob/living/carbon/alien/humanoid/sentinel/New()
create_reagents(100)
if(name == "alien sentinel")
name = text("alien sentinel ([rand(1, 1000)])")
real_name = name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != 2)
switch(health)
if(150 to INFINITY)
healths.icon_state = "health0"
if(100 to 150)
healths.icon_state = "health1"
if(75 to 100)
healths.icon_state = "health2"
if(25 to 75)
healths.icon_state = "health3"
if(0 to 25)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/*
/mob/living/carbon/alien/humanoid/sentinel/verb/evolve() // -- TLE
set name = "Evolve (250)"
set desc = "Become a Praetorian, Royal Guard to the Queen."
set category = "Alien"
if(powerc(250))
adjustToxLoss(-250)
to_chat(src, "<span class=notice'>You begin to evolve!</span>")
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] begins to twist and contort!</span>"), 1)
var/mob/living/carbon/alien/humanoid/sentinel/praetorian/new_xeno = new(loc)
if(mind)
mind.transfer_to(new_xeno)
else
new_xeno.key = key
new_xeno.mind.name = new_xeno.name
qdel(src)
return
*/
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
maxHealth = 150
health = 150
icon_state = "aliens_s"
/mob/living/carbon/alien/humanoid/sentinel/large
name = "alien praetorian"
icon = 'icons/mob/alienlarge.dmi'
icon_state = "prat_s"
pixel_x = -16
maxHealth = 200
health = 200
large = 1
/mob/living/carbon/alien/humanoid/sentinel/praetorian
name = "alien praetorian"
maxHealth = 200
health = 200
large = 1
/mob/living/carbon/alien/humanoid/sentinel/large/update_icons()
overlays.Cut()
if(stat == DEAD)
icon_state = "prat_dead"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "prat_sleep"
else
icon_state = "prat_s"
for(var/image/I in overlays_standing)
overlays += I
/mob/living/carbon/alien/humanoid/sentinel/New()
create_reagents(100)
if(name == "alien sentinel")
name = text("alien sentinel ([rand(1, 1000)])")
real_name = name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != 2)
switch(health)
if(150 to INFINITY)
healths.icon_state = "health0"
if(100 to 150)
healths.icon_state = "health1"
if(75 to 100)
healths.icon_state = "health2"
if(25 to 75)
healths.icon_state = "health3"
if(0 to 25)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/*
/mob/living/carbon/alien/humanoid/sentinel/verb/evolve() // -- TLE
set name = "Evolve (250)"
set desc = "Become a Praetorian, Royal Guard to the Queen."
set category = "Alien"
if(powerc(250))
adjustToxLoss(-250)
to_chat(src, "<span class=notice'>You begin to evolve!</span>")
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] begins to twist and contort!</span>"), 1)
var/mob/living/carbon/alien/humanoid/sentinel/praetorian/new_xeno = new(loc)
if(mind)
mind.transfer_to(new_xeno)
else
new_xeno.key = key
new_xeno.mind.name = new_xeno.name
qdel(src)
return
*/
@@ -138,4 +138,4 @@
playsound(src.loc, 'sound/voice/hiss1.ogg', 30, 1, 1)
if(act == "gnarl")
playsound(src.loc, 'sound/voice/hiss4.ogg', 30, 1, 1)
..()
..()
@@ -1,123 +1,123 @@
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien_s"
butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/next_attack = 0
var/pounce_cooldown = 0
var/pounce_cooldown_time = 30
var/leap_on_click = 0
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
pass_flags = PASSTABLE
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
create_reagents(1000)
if(name == "alien")
name = text("alien ([rand(1, 1000)])")
real_name = name
add_language("Xenomorph")
add_language("Hivemind")
..()
/mob/living/carbon/alien/humanoid/Process_Spacemove(var/check_drift = 0)
if(..())
return 1
return 0
///mob/living/carbon/alien/humanoid/bullet_act(var/obj/item/projectile/Proj) taken care of in living
/mob/living/carbon/alien/humanoid/emp_act(severity)
if(r_store) r_store.emp_act(severity)
if(l_store) l_store.emp_act(severity)
..()
/mob/living/carbon/alien/humanoid/ex_act(severity)
..()
var/shielded = 0
var/b_loss = null
var/f_loss = null
switch(severity)
if(1.0)
gib()
return
if(2.0)
if(!shielded)
b_loss += 60
f_loss += 60
AdjustEarDamage(30, 120)
if(3.0)
b_loss += 30
if(prob(50) && !shielded)
Paralyse(1)
AdjustEarDamage(15, 60)
take_overall_damage(b_loss, f_loss)
/mob/living/carbon/alien/humanoid/restrained()
if(handcuffed)
return 1
return 0
/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75
/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=[UID()];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=[UID()];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
dat += "<tr><td><B>Head:</B></td><td><A href='?src=[UID()];item=[slot_head]'>[(head && !(head.flags&ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[UID()];item=[slot_wear_suit]'>[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Pouches:</B></td><td><A href='?src=[UID()];item=pockets'>[((l_store && !(l_store.flags&ABSTRACT)) || (r_store && !(r_store.flags&ABSTRACT))) ? "Full" : "<font color=grey>Empty</font>"]</A>"
dat += {"</table>
<A href='?src=[user.UID()];mach_close=mob\ref[src]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500)
popup.set_content(dat)
popup.open()
/mob/living/carbon/alien/humanoid/canBeHandcuffed()
return 1
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
..(I, cuff_break = 1)
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_y_offset)
return custom_pixel_y_offset
else
return initial(pixel_y)
/mob/living/carbon/alien/humanoid/get_standard_pixel_x_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_x_offset)
return custom_pixel_x_offset
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien_s"
butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/next_attack = 0
var/pounce_cooldown = 0
var/pounce_cooldown_time = 30
var/leap_on_click = 0
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
pass_flags = PASSTABLE
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
create_reagents(1000)
if(name == "alien")
name = text("alien ([rand(1, 1000)])")
real_name = name
add_language("Xenomorph")
add_language("Hivemind")
..()
/mob/living/carbon/alien/humanoid/Process_Spacemove(var/check_drift = 0)
if(..())
return 1
return 0
///mob/living/carbon/alien/humanoid/bullet_act(var/obj/item/projectile/Proj) taken care of in living
/mob/living/carbon/alien/humanoid/emp_act(severity)
if(r_store) r_store.emp_act(severity)
if(l_store) l_store.emp_act(severity)
..()
/mob/living/carbon/alien/humanoid/ex_act(severity)
..()
var/shielded = 0
var/b_loss = null
var/f_loss = null
switch(severity)
if(1.0)
gib()
return
if(2.0)
if(!shielded)
b_loss += 60
f_loss += 60
AdjustEarDamage(30, 120)
if(3.0)
b_loss += 30
if(prob(50) && !shielded)
Paralyse(1)
AdjustEarDamage(15, 60)
take_overall_damage(b_loss, f_loss)
/mob/living/carbon/alien/humanoid/restrained()
if(handcuffed)
return 1
return 0
/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75
/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=[UID()];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=[UID()];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
dat += "<tr><td><B>Head:</B></td><td><A href='?src=[UID()];item=[slot_head]'>[(head && !(head.flags&ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[UID()];item=[slot_wear_suit]'>[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Pouches:</B></td><td><A href='?src=[UID()];item=pockets'>[((l_store && !(l_store.flags&ABSTRACT)) || (r_store && !(r_store.flags&ABSTRACT))) ? "Full" : "<font color=grey>Empty</font>"]</A>"
dat += {"</table>
<A href='?src=[user.UID()];mach_close=mob\ref[src]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500)
popup.set_content(dat)
popup.open()
/mob/living/carbon/alien/humanoid/canBeHandcuffed()
return 1
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
..(I, cuff_break = 1)
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_y_offset)
return custom_pixel_y_offset
else
return initial(pixel_y)
/mob/living/carbon/alien/humanoid/get_standard_pixel_x_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_x_offset)
return custom_pixel_x_offset
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
@@ -1,47 +1,47 @@
//unequip
/mob/living/carbon/alien/humanoid/unEquip(var/obj/item/I, var/force)
. = ..(I, force)
if(!. || !I)
return
if(I == r_store)
r_store = null
update_inv_pockets()
else if(I == l_store)
l_store = null
update_inv_pockets()
/mob/living/carbon/alien/humanoid/attack_ui(slot_id)
var/obj/item/W = get_active_hand()
if(W)
if(!istype(W)) return
switch(slot_id)
// if("o_clothing")
// if("head")
if(slot_l_store)
if(l_store)
return
if(W.w_class > WEIGHT_CLASS_NORMAL)
return
unEquip(W)
l_store = W
update_inv_pockets()
if(slot_r_store)
if(r_store)
return
if(W.w_class > WEIGHT_CLASS_NORMAL)
return
unEquip(W)
r_store = W
update_inv_pockets()
else
switch(slot_id)
if(slot_wear_suit)
if(wear_suit) wear_suit.attack_alien(src)
if(slot_head)
if(head) head.attack_alien(src)
if(slot_l_store)
if(l_store) l_store.attack_alien(src)
if(slot_r_store)
if(r_store) r_store.attack_alien(src)
//unequip
/mob/living/carbon/alien/humanoid/unEquip(var/obj/item/I, var/force)
. = ..(I, force)
if(!. || !I)
return
if(I == r_store)
r_store = null
update_inv_pockets()
else if(I == l_store)
l_store = null
update_inv_pockets()
/mob/living/carbon/alien/humanoid/attack_ui(slot_id)
var/obj/item/W = get_active_hand()
if(W)
if(!istype(W)) return
switch(slot_id)
// if("o_clothing")
// if("head")
if(slot_l_store)
if(l_store)
return
if(W.w_class > WEIGHT_CLASS_NORMAL)
return
unEquip(W)
l_store = W
update_inv_pockets()
if(slot_r_store)
if(r_store)
return
if(W.w_class > WEIGHT_CLASS_NORMAL)
return
unEquip(W)
r_store = W
update_inv_pockets()
else
switch(slot_id)
if(slot_wear_suit)
if(wear_suit) wear_suit.attack_alien(src)
if(slot_head)
if(head) head.attack_alien(src)
if(slot_l_store)
if(l_store) l_store.attack_alien(src)
if(slot_r_store)
if(r_store) r_store.attack_alien(src)
@@ -1,89 +1,89 @@
/mob/living/carbon/alien/humanoid/Life(seconds, times_fired)
. = ..()
update_icons()
/mob/living/carbon/alien/humanoid/handle_disabilities()
if(disabilities & EPILEPSY)
if((prob(1) && paralysis < 10))
to_chat(src, "<span class='danger'>You have a seizure!</span>")
Paralyse(10)
if(disabilities & COUGHING)
if((prob(5) && paralysis <= 1))
drop_item()
emote("cough")
return
if(disabilities & TOURETTES)
if((prob(10) && paralysis <= 1))
Stun(10)
emote("twitch")
return
if(disabilities & NERVOUS)
if(prob(10))
stuttering = max(10, stuttering)
/mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference/5
else
increments = difference/10
var/change = increments*boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
/mob/living/carbon/alien/humanoid/handle_regular_status_updates()
updatehealth()
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
SetSilence(0)
else //ALIVE. LIGHTS ARE ON
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) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
if(health <= 20 && prob(1))
emote("gasp")
if(!reagents.has_reagent("epinephrine"))
adjustOxyLoss(1)
Paralyse(3)
if(paralysis)
stat = UNCONSCIOUS
else if(sleeping)
stat = UNCONSCIOUS
if(prob(10) && health)
emote("hiss")
//CONSCIOUS
else
stat = CONSCIOUS
/* What in the living hell is this?*/
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - rand(1, 2))
if(eye_blind) //blindness, heals slowly over time
AdjustEyeBlind(-1)
else if(eye_blurry) //blurry eyes heal slowly
AdjustEyeBlurry(-1)
if(stuttering)
AdjustStuttering(-1)
if(silent)
AdjustSilence(-1)
if(druggy)
AdjustDruggy(-1)
return 1
/mob/living/carbon/alien/humanoid/Life(seconds, times_fired)
. = ..()
update_icons()
/mob/living/carbon/alien/humanoid/handle_disabilities()
if(disabilities & EPILEPSY)
if((prob(1) && paralysis < 10))
to_chat(src, "<span class='danger'>You have a seizure!</span>")
Paralyse(10)
if(disabilities & COUGHING)
if((prob(5) && paralysis <= 1))
drop_item()
emote("cough")
return
if(disabilities & TOURETTES)
if((prob(10) && paralysis <= 1))
Stun(10)
emote("twitch")
return
if(disabilities & NERVOUS)
if(prob(10))
stuttering = max(10, stuttering)
/mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference/5
else
increments = difference/10
var/change = increments*boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
/mob/living/carbon/alien/humanoid/handle_regular_status_updates()
updatehealth()
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
SetSilence(0)
else //ALIVE. LIGHTS ARE ON
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) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
if(health <= 20 && prob(1))
emote("gasp")
if(!reagents.has_reagent("epinephrine"))
adjustOxyLoss(1)
Paralyse(3)
if(paralysis)
stat = UNCONSCIOUS
else if(sleeping)
stat = UNCONSCIOUS
if(prob(10) && health)
emote("hiss")
//CONSCIOUS
else
stat = CONSCIOUS
/* What in the living hell is this?*/
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - rand(1, 2))
if(eye_blind) //blindness, heals slowly over time
AdjustEyeBlind(-1)
else if(eye_blurry) //blurry eyes heal slowly
AdjustEyeBlurry(-1)
if(stuttering)
AdjustStuttering(-1)
if(silent)
AdjustSilence(-1)
if(druggy)
AdjustDruggy(-1)
return 1
@@ -1,95 +1,95 @@
/mob/living/carbon/alien/humanoid/queen
name = "alien queen"
caste = "q"
maxHealth = 250
health = 250
icon_state = "alienq_s"
status_flags = CANPARALYSE
heal_rate = 5
large = 1
ventcrawler = 0
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
/mob/living/carbon/alien/humanoid/queen/New()
create_reagents(100)
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list)
if(Q == src) continue
if(Q.stat == DEAD) continue
if(Q.client)
name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it.
break
real_name = src.name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/queen
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/eggsac
alien_organs += new /obj/item/organ/internal/xenos/resinspinner
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/queen/movement_delay()
. = ..()
. += 3
/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != DEAD)
switch(health)
if(250 to INFINITY)
healths.icon_state = "health0"
if(175 to 250)
healths.icon_state = "health1"
if(100 to 175)
healths.icon_state = "health2"
if(50 to 100)
healths.icon_state = "health3"
if(0 to 50)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/humanoid/queen/can_inject()
return FALSE
//Queen verbs
/mob/living/carbon/alien/humanoid/queen/verb/lay_egg()
set name = "Lay Egg (75)"
set desc = "Lay an egg to produce huggers to impregnate prey with."
set category = "Alien"
if(locate(/obj/structure/alien/egg) in get_turf(src))
to_chat(src, "<span class='noticealien'>There's already an egg here.</span>")
return
if(powerc(75,1))//Can't plant eggs on spess tiles. That's silly.
adjustPlasma(-75)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] has laid an egg!</span>"), 1)
new /obj/structure/alien/egg(loc)
return
/mob/living/carbon/alien/humanoid/queen/large
icon = 'icons/mob/alienlarge.dmi'
icon_state = "queen_s"
pixel_x = -16
large = 1
/mob/living/carbon/alien/humanoid/queen/large/update_icons()
overlays.Cut()
if(stat == DEAD)
icon_state = "queen_dead"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "queen_sleep"
else
icon_state = "queen_s"
for(var/image/I in overlays_standing)
overlays += I
/mob/living/carbon/alien/humanoid/queen
name = "alien queen"
caste = "q"
maxHealth = 250
health = 250
icon_state = "alienq_s"
status_flags = CANPARALYSE
heal_rate = 5
large = 1
ventcrawler = 0
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
/mob/living/carbon/alien/humanoid/queen/New()
create_reagents(100)
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list)
if(Q == src) continue
if(Q.stat == DEAD) continue
if(Q.client)
name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it.
break
real_name = src.name
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/queen
alien_organs += new /obj/item/organ/internal/xenos/acidgland
alien_organs += new /obj/item/organ/internal/xenos/eggsac
alien_organs += new /obj/item/organ/internal/xenos/resinspinner
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/queen/movement_delay()
. = ..()
. += 3
/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health()
..() //-Yvarov
if(healths)
if(stat != DEAD)
switch(health)
if(250 to INFINITY)
healths.icon_state = "health0"
if(175 to 250)
healths.icon_state = "health1"
if(100 to 175)
healths.icon_state = "health2"
if(50 to 100)
healths.icon_state = "health3"
if(0 to 50)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/humanoid/queen/can_inject()
return FALSE
//Queen verbs
/mob/living/carbon/alien/humanoid/queen/verb/lay_egg()
set name = "Lay Egg (75)"
set desc = "Lay an egg to produce huggers to impregnate prey with."
set category = "Alien"
if(locate(/obj/structure/alien/egg) in get_turf(src))
to_chat(src, "<span class='noticealien'>There's already an egg here.</span>")
return
if(powerc(75,1))//Can't plant eggs on spess tiles. That's silly.
adjustPlasma(-75)
for(var/mob/O in viewers(src, null))
O.show_message(text("<span class='alertalien'>[src] has laid an egg!</span>"), 1)
new /obj/structure/alien/egg(loc)
return
/mob/living/carbon/alien/humanoid/queen/large
icon = 'icons/mob/alienlarge.dmi'
icon_state = "queen_s"
pixel_x = -16
large = 1
/mob/living/carbon/alien/humanoid/queen/large/update_icons()
overlays.Cut()
if(stat == DEAD)
icon_state = "queen_dead"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "queen_sleep"
else
icon_state = "queen_s"
for(var/image/I in overlays_standing)
overlays += I
@@ -1,166 +1,166 @@
//Xeno Overlays Indexes//////////
#define X_HEAD_LAYER 1
#define X_SUIT_LAYER 2
#define X_L_HAND_LAYER 3
#define X_R_HAND_LAYER 4
#define X_TARGETED_LAYER 5
#define X_FIRE_LAYER 6
#define X_TOTAL_LAYERS 6
/////////////////////////////////
/mob/living/carbon/alien/humanoid
var/list/overlays_standing[X_TOTAL_LAYERS]
/mob/living/carbon/alien/humanoid/update_icons()
overlays.Cut()
for(var/image/I in overlays_standing)
overlays += I
if(stat == DEAD)
//If we mostly took damage from fire
if(getFireLoss() > 125)
icon_state = "alien[caste]_husked"
pixel_y = 0
else
icon_state = "alien[caste]_dead"
pixel_y = 0
else if(stat == UNCONSCIOUS || IsWeakened())
icon_state = "alien[caste]_unconscious"
pixel_y = 0
else if(leap_on_click)
icon_state = "alien[caste]_pounce"
else if(lying || resting)
icon_state = "alien[caste]_sleep"
else if(m_intent == MOVE_INTENT_RUN)
icon_state = "alien[caste]_running"
else
icon_state = "alien[caste]_s"
if(leaping)
if(alt_icon == initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
icon_state = "alien[caste]_leap"
pixel_x = -32
pixel_y = -32
else
if(alt_icon != initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
pixel_x = get_standard_pixel_x_offset(lying)
pixel_y = get_standard_pixel_y_offset(lying)
/mob/living/carbon/alien/humanoid/regenerate_icons()
..()
if(notransform) return
update_inv_head(0,0)
update_inv_wear_suit(0,0)
update_inv_r_hand(0)
update_inv_l_hand(0)
update_inv_pockets(0)
update_icons()
update_fire()
update_transform()
/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that.
if(lying > 0)
lying = 90 //Anything else looks retarded
..()
update_icons()
/mob/living/carbon/alien/humanoid/update_fire()
overlays -= overlays_standing[X_FIRE_LAYER]
if(on_fire)
overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Generic_mob_burning", "layer"= -X_FIRE_LAYER)
overlays += overlays_standing[X_FIRE_LAYER]
return
else
overlays_standing[X_FIRE_LAYER] = null
/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit]
inv.update_icon()
if(wear_suit)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
client.screen += wear_suit //Either way, add the item to the HUD
var/t_state = wear_suit.item_state
if(!t_state) t_state = wear_suit.icon_state
var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]")
if(wear_suit.blood_DNA)
var/t_suit = "suit"
if( istype(wear_suit, /obj/item/clothing/suit/armor) )
t_suit = "armor"
standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood")
if(wear_suit.breakouttime)
drop_r_hand()
drop_l_hand()
overlays_standing[X_SUIT_LAYER] = standing
else
overlays_standing[X_SUIT_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1)
if(head)
var/t_state = head.item_state
if(!t_state) t_state = head.icon_state
var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]")
if(head.blood_DNA)
standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood")
head.screen_loc = ui_alien_head
overlays_standing[X_HEAD_LAYER] = standing
else
overlays_standing[X_HEAD_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1)
if(l_store) l_store.screen_loc = ui_storage1
if(r_store) r_store.screen_loc = ui_storage2
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1)
..(1)
if(r_hand)
var/t_state = r_hand.item_state
if(!t_state) t_state = r_hand.icon_state
r_hand.screen_loc = ui_rhand
overlays_standing[X_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state" = t_state)
else
overlays_standing[X_R_HAND_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1)
..(1)
if(l_hand)
var/t_state = l_hand.item_state
if(!t_state) t_state = l_hand.icon_state
l_hand.screen_loc = ui_lhand
overlays_standing[X_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state" = t_state)
else
overlays_standing[X_L_HAND_LAYER] = null
if(update_icons) update_icons()
//Xeno Overlays Indexes//////////
#undef X_HEAD_LAYER
#undef X_SUIT_LAYER
#undef X_L_HAND_LAYER
#undef X_R_HAND_LAYER
#undef X_TARGETED_LAYER
#undef X_FIRE_LAYER
#undef X_TOTAL_LAYERS
//Xeno Overlays Indexes//////////
#define X_HEAD_LAYER 1
#define X_SUIT_LAYER 2
#define X_L_HAND_LAYER 3
#define X_R_HAND_LAYER 4
#define X_TARGETED_LAYER 5
#define X_FIRE_LAYER 6
#define X_TOTAL_LAYERS 6
/////////////////////////////////
/mob/living/carbon/alien/humanoid
var/list/overlays_standing[X_TOTAL_LAYERS]
/mob/living/carbon/alien/humanoid/update_icons()
overlays.Cut()
for(var/image/I in overlays_standing)
overlays += I
if(stat == DEAD)
//If we mostly took damage from fire
if(getFireLoss() > 125)
icon_state = "alien[caste]_husked"
pixel_y = 0
else
icon_state = "alien[caste]_dead"
pixel_y = 0
else if(stat == UNCONSCIOUS || IsWeakened())
icon_state = "alien[caste]_unconscious"
pixel_y = 0
else if(leap_on_click)
icon_state = "alien[caste]_pounce"
else if(lying || resting)
icon_state = "alien[caste]_sleep"
else if(m_intent == MOVE_INTENT_RUN)
icon_state = "alien[caste]_running"
else
icon_state = "alien[caste]_s"
if(leaping)
if(alt_icon == initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
icon_state = "alien[caste]_leap"
pixel_x = -32
pixel_y = -32
else
if(alt_icon != initial(alt_icon))
var/old_icon = icon
icon = alt_icon
alt_icon = old_icon
pixel_x = get_standard_pixel_x_offset(lying)
pixel_y = get_standard_pixel_y_offset(lying)
/mob/living/carbon/alien/humanoid/regenerate_icons()
..()
if(notransform) return
update_inv_head(0,0)
update_inv_wear_suit(0,0)
update_inv_r_hand(0)
update_inv_l_hand(0)
update_inv_pockets(0)
update_icons()
update_fire()
update_transform()
/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that.
if(lying > 0)
lying = 90 //Anything else looks retarded
..()
update_icons()
/mob/living/carbon/alien/humanoid/update_fire()
overlays -= overlays_standing[X_FIRE_LAYER]
if(on_fire)
overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Generic_mob_burning", "layer"= -X_FIRE_LAYER)
overlays += overlays_standing[X_FIRE_LAYER]
return
else
overlays_standing[X_FIRE_LAYER] = null
/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit]
inv.update_icon()
if(wear_suit)
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
client.screen += wear_suit //Either way, add the item to the HUD
var/t_state = wear_suit.item_state
if(!t_state) t_state = wear_suit.icon_state
var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]")
if(wear_suit.blood_DNA)
var/t_suit = "suit"
if( istype(wear_suit, /obj/item/clothing/suit/armor) )
t_suit = "armor"
standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood")
if(wear_suit.breakouttime)
drop_r_hand()
drop_l_hand()
overlays_standing[X_SUIT_LAYER] = standing
else
overlays_standing[X_SUIT_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1)
if(head)
var/t_state = head.item_state
if(!t_state) t_state = head.icon_state
var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]")
if(head.blood_DNA)
standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood")
head.screen_loc = ui_alien_head
overlays_standing[X_HEAD_LAYER] = standing
else
overlays_standing[X_HEAD_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1)
if(l_store) l_store.screen_loc = ui_storage1
if(r_store) r_store.screen_loc = ui_storage2
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1)
..(1)
if(r_hand)
var/t_state = r_hand.item_state
if(!t_state) t_state = r_hand.icon_state
r_hand.screen_loc = ui_rhand
overlays_standing[X_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state" = t_state)
else
overlays_standing[X_R_HAND_LAYER] = null
if(update_icons) update_icons()
/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1)
..(1)
if(l_hand)
var/t_state = l_hand.item_state
if(!t_state) t_state = l_hand.icon_state
l_hand.screen_loc = ui_lhand
overlays_standing[X_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state" = t_state)
else
overlays_standing[X_L_HAND_LAYER] = null
if(update_icons) update_icons()
//Xeno Overlays Indexes//////////
#undef X_HEAD_LAYER
#undef X_SUIT_LAYER
#undef X_L_HAND_LAYER
#undef X_R_HAND_LAYER
#undef X_TARGETED_LAYER
#undef X_FIRE_LAYER
#undef X_TOTAL_LAYERS
@@ -123,4 +123,4 @@
for(var/mob/O in hearers(src, null))
O.show_message(message, m_type)
//Foreach goto(746)
return
return
@@ -1,3 +1,3 @@
//can't unequip since it can't equip anything
/mob/living/carbon/alien/larva/unEquip(obj/item/W as obj, force)
return
//can't unequip since it can't equip anything
/mob/living/carbon/alien/larva/unEquip(obj/item/W as obj, force)
return
@@ -1,96 +1,96 @@
/mob/living/carbon/alien/larva
name = "alien larva"
real_name = "alien larva"
icon_state = "larva0"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
maxHealth = 30
health = 30
density = 0
var/amount_grown = 0
var/max_grown = 200
var/time_of_birth
death_message = "lets out a waning high-pitched cry."
death_sound = null
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/larva/New()
create_reagents(100)
if(name == "alien larva")
name = "alien larva ([rand(1, 1000)])"
real_name = name
regenerate_icons()
add_language("Xenomorph")
add_language("Hivemind")
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/larva
..()
//This needs to be fixed
/mob/living/carbon/alien/larva/Stat()
..()
stat(null, "Progress: [amount_grown]/[max_grown]")
/mob/living/carbon/alien/larva/adjustPlasma(amount)
if(stat != DEAD && amount > 0)
amount_grown = min(amount_grown + 1, max_grown)
..(amount)
/mob/living/carbon/alien/larva/ex_act(severity)
..()
var/b_loss = null
var/f_loss = null
switch(severity)
if(1.0)
gib()
return
if(2.0)
b_loss += 60
f_loss += 60
AdjustEarDamage(30, 120)
if(3.0)
b_loss += 30
if(prob(50))
Paralyse(1)
AdjustEarDamage(15, 60)
adjustBruteLoss(b_loss)
adjustFireLoss(f_loss)
updatehealth()
//can't equip anything
/mob/living/carbon/alien/larva/attack_ui(slot_id)
return
/mob/living/carbon/alien/larva/restrained()
return 0
/mob/living/carbon/alien/larva/var/temperature_resistance = T0C+75
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
/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.
return
else
var/mob/living/carbon/alien/humanoid/A = new(loc)
A.key = key
qdel(src) */
/mob/living/carbon/alien/larva
name = "alien larva"
real_name = "alien larva"
icon_state = "larva0"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
maxHealth = 30
health = 30
density = 0
var/amount_grown = 0
var/max_grown = 200
var/time_of_birth
death_message = "lets out a waning high-pitched cry."
death_sound = null
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/larva/New()
create_reagents(100)
if(name == "alien larva")
name = "alien larva ([rand(1, 1000)])"
real_name = name
regenerate_icons()
add_language("Xenomorph")
add_language("Hivemind")
alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/larva
..()
//This needs to be fixed
/mob/living/carbon/alien/larva/Stat()
..()
stat(null, "Progress: [amount_grown]/[max_grown]")
/mob/living/carbon/alien/larva/adjustPlasma(amount)
if(stat != DEAD && amount > 0)
amount_grown = min(amount_grown + 1, max_grown)
..(amount)
/mob/living/carbon/alien/larva/ex_act(severity)
..()
var/b_loss = null
var/f_loss = null
switch(severity)
if(1.0)
gib()
return
if(2.0)
b_loss += 60
f_loss += 60
AdjustEarDamage(30, 120)
if(3.0)
b_loss += 30
if(prob(50))
Paralyse(1)
AdjustEarDamage(15, 60)
adjustBruteLoss(b_loss)
adjustFireLoss(f_loss)
updatehealth()
//can't equip anything
/mob/living/carbon/alien/larva/attack_ui(slot_id)
return
/mob/living/carbon/alien/larva/restrained()
return 0
/mob/living/carbon/alien/larva/var/temperature_resistance = T0C+75
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
/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.
return
else
var/mob/living/carbon/alien/humanoid/A = new(loc)
A.key = key
qdel(src) */
@@ -34,4 +34,4 @@
/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_BITE
..()
..()
@@ -1,57 +1,57 @@
/mob/living/carbon/alien/larva/Life(seconds, times_fired)
if(..()) //still breathing
// GROW!
if(amount_grown < max_grown)
amount_grown++
//some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder
update_icons()
/mob/living/carbon/alien/larva/handle_regular_status_updates()
updatehealth()
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
SetSilence(0)
else //ALIVE. LIGHTS ARE ON
if(health < -25 || !get_int_organ(/obj/item/organ/internal/brain))
death()
SetSilence(0)
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > 25) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
//if( health <= 20 && prob(1) )
// spawn(0)
// emote("gasp")
if(!reagents.has_reagent("epinephrine"))
adjustOxyLoss(1)
Paralyse(3)
if(paralysis)
stat = UNCONSCIOUS
else if(sleeping)
stat = UNCONSCIOUS
if(prob(10) && health)
emote("hiss_")
//CONSCIOUS
else
stat = CONSCIOUS
/* What in the living hell is this?*/
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - rand(1, 2))
if(eye_blind) //blindness, heals slowly over time
AdjustEyeBlind(-1)
else if(eye_blurry) //blurry eyes heal slowly
AdjustEyeBlurry(-1)
if(stuttering)
AdjustStuttering(-1)
if(silent)
AdjustSilence(-1)
if(druggy)
AdjustDruggy(-1)
return 1
/mob/living/carbon/alien/larva/Life(seconds, times_fired)
if(..()) //still breathing
// GROW!
if(amount_grown < max_grown)
amount_grown++
//some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder
update_icons()
/mob/living/carbon/alien/larva/handle_regular_status_updates()
updatehealth()
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
SetSilence(0)
else //ALIVE. LIGHTS ARE ON
if(health < -25 || !get_int_organ(/obj/item/organ/internal/brain))
death()
SetSilence(0)
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > 25) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method()))
//if( health <= 20 && prob(1) )
// spawn(0)
// emote("gasp")
if(!reagents.has_reagent("epinephrine"))
adjustOxyLoss(1)
Paralyse(3)
if(paralysis)
stat = UNCONSCIOUS
else if(sleeping)
stat = UNCONSCIOUS
if(prob(10) && health)
emote("hiss_")
//CONSCIOUS
else
stat = CONSCIOUS
/* What in the living hell is this?*/
if(move_delay_add > 0)
move_delay_add = max(0, move_delay_add - rand(1, 2))
if(eye_blind) //blindness, heals slowly over time
AdjustEyeBlind(-1)
else if(eye_blurry) //blurry eyes heal slowly
AdjustEyeBlurry(-1)
if(stuttering)
AdjustStuttering(-1)
if(silent)
AdjustSilence(-1)
if(druggy)
AdjustDruggy(-1)
return 1
@@ -1,54 +1,54 @@
/mob/living/carbon/alien/larva/verb/hide()
set name = "Hide"
set desc = "Allows to hide beneath tables or certain items. Toggled on or off."
set category = "Alien"
if(stat != CONSCIOUS)
return
if(layer != ABOVE_NORMAL_TURF_LAYER)
layer = ABOVE_NORMAL_TURF_LAYER
visible_message("<B>[src] scurries to the ground!</B>", "<span class='noticealien'>You are now hiding.</span>")
else
layer = MOB_LAYER
visible_message("[src] slowly peeks up from the ground...", "<span class=notice'>You have stopped hiding.</span>")
/mob/living/carbon/alien/larva/verb/evolve()
set name = "Evolve"
set desc = "Evolve into a fully grown Alien."
set category = "Alien"
if(stat != CONSCIOUS)
return
if(handcuffed || legcuffed)
to_chat(src, "<span class='warning'>You cannot evolve when you are cuffed.</span>")
if(amount_grown >= max_grown) //TODO ~Carn
//green is impossible to read, so i made these blue and changed the formatting slightly
to_chat(src, "<span class='boldnotice'>You are growing into a beautiful alien! It is time to choose a caste.</span>")
to_chat(src, "<span class='notice'>There are three to choose from:</span>")
to_chat(src, "<B>Hunters</B> <span class='notice'>are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves.</span>")
to_chat(src, "<B>Sentinels</B> <span class='notice'>are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters.</span>")
to_chat(src, "<B>Drones</B> <span class='notice'>are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen.</span>")
var/alien_caste = alert(src, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
var/mob/living/carbon/alien/humanoid/new_xeno
switch(alien_caste)
if("Hunter")
new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc)
if("Sentinel")
new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc)
if("Drone")
new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
if(mind)
mind.transfer_to(new_xeno)
else
new_xeno.key = key
new_xeno.mind.name = new_xeno.name
qdel(src)
return
else
to_chat(src, "<span class='warning'>You are not fully grown.</span>")
return
/mob/living/carbon/alien/larva/verb/hide()
set name = "Hide"
set desc = "Allows to hide beneath tables or certain items. Toggled on or off."
set category = "Alien"
if(stat != CONSCIOUS)
return
if(layer != ABOVE_NORMAL_TURF_LAYER)
layer = ABOVE_NORMAL_TURF_LAYER
visible_message("<B>[src] scurries to the ground!</B>", "<span class='noticealien'>You are now hiding.</span>")
else
layer = MOB_LAYER
visible_message("[src] slowly peeks up from the ground...", "<span class=notice'>You have stopped hiding.</span>")
/mob/living/carbon/alien/larva/verb/evolve()
set name = "Evolve"
set desc = "Evolve into a fully grown Alien."
set category = "Alien"
if(stat != CONSCIOUS)
return
if(handcuffed || legcuffed)
to_chat(src, "<span class='warning'>You cannot evolve when you are cuffed.</span>")
if(amount_grown >= max_grown) //TODO ~Carn
//green is impossible to read, so i made these blue and changed the formatting slightly
to_chat(src, "<span class='boldnotice'>You are growing into a beautiful alien! It is time to choose a caste.</span>")
to_chat(src, "<span class='notice'>There are three to choose from:</span>")
to_chat(src, "<B>Hunters</B> <span class='notice'>are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves.</span>")
to_chat(src, "<B>Sentinels</B> <span class='notice'>are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters.</span>")
to_chat(src, "<B>Drones</B> <span class='notice'>are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen.</span>")
var/alien_caste = alert(src, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
var/mob/living/carbon/alien/humanoid/new_xeno
switch(alien_caste)
if("Hunter")
new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc)
if("Sentinel")
new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc)
if("Drone")
new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
if(mind)
mind.transfer_to(new_xeno)
else
new_xeno.key = key
new_xeno.mind.name = new_xeno.name
qdel(src)
return
else
to_chat(src, "<span class='warning'>You are not fully grown.</span>")
return
@@ -1,25 +1,25 @@
/mob/living/carbon/alien/larva/regenerate_icons()
overlays = list()
update_icons()
/mob/living/carbon/alien/larva/update_icons()
var/state = 0
if(amount_grown > 150)
state = 2
else if(amount_grown > 50)
state = 1
if(stat == DEAD)
icon_state = "larva[state]_dead"
else if(handcuffed || legcuffed) //This should be an overlay. Who made this an icon_state?
icon_state = "larva[state]_cuff"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "larva[state]_sleep"
else if(stunned)
icon_state = "larva[state]_stun"
else
icon_state = "larva[state]"
/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
return update_icons()
/mob/living/carbon/alien/larva/regenerate_icons()
overlays = list()
update_icons()
/mob/living/carbon/alien/larva/update_icons()
var/state = 0
if(amount_grown > 150)
state = 2
else if(amount_grown > 50)
state = 1
if(stat == DEAD)
icon_state = "larva[state]_dead"
else if(handcuffed || legcuffed) //This should be an overlay. Who made this an icon_state?
icon_state = "larva[state]_cuff"
else if(stat == UNCONSCIOUS || lying || resting)
icon_state = "larva[state]_sleep"
else if(stunned)
icon_state = "larva[state]_stun"
else
icon_state = "larva[state]"
/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
return update_icons()
@@ -1,4 +1,4 @@
/mob/living/carbon/alien/Login()
..()
AddInfectionImages()
return
/mob/living/carbon/alien/Login()
..()
AddInfectionImages()
return
@@ -1,4 +1,4 @@
/mob/living/carbon/alien/Logout()
..()
RemoveInfectionImages()
return
/mob/living/carbon/alien/Logout()
..()
RemoveInfectionImages()
return
@@ -1,129 +1,129 @@
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
/obj/item/organ/internal/body_egg/alien_embryo
name = "alien embryo"
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/stage = 0
var/polling = 0
/obj/item/organ/internal/body_egg/alien_embryo/on_find(mob/living/finder)
..()
if(stage < 4)
to_chat(finder, "It's small and weak, barely the size of a fetus.")
else
to_chat(finder, "It's grown quite large, and writhes slightly as you look at it.")
if(prob(10))
AttemptGrow(0)
/obj/item/organ/internal/body_egg/alien_embryo/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/internal/body_egg/alien_embryo/on_life()
switch(stage)
if(2, 3)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(2))
to_chat(owner, "<span class='danger'>Your throat feels sore.</span>")
if(prob(2))
to_chat(owner, "<span class='danger'>Mucous runs down the back of your throat.</span>")
if(4)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(4))
to_chat(owner, "<span class='danger'>Your muscles ache.</span>")
if(prob(20))
owner.take_organ_damage(1)
if(prob(4))
to_chat(owner, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
owner.adjustToxLoss(1)
if(5)
to_chat(owner, "<span class='danger'>You feel something tearing its way out of your stomach...</span>")
owner.adjustToxLoss(10)
/obj/item/organ/internal/body_egg/alien_embryo/egg_process()
if(stage < 5 && prob(3))
stage++
spawn(0)
RefreshInfectionImage()
if(stage == 5 && prob(50))
for(var/datum/surgery/S in owner.surgeries)
if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/internal/manipulate_organs))
AttemptGrow(0)
return
AttemptGrow()
/obj/item/organ/internal/body_egg/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1)
if(!owner || polling)
return
polling = 1
spawn()
var/list/candidates = pollCandidates("Do you want to play as an alien?", ROLE_ALIEN, 0)
var/mob/C = null
// To stop clientless larva, we will check that our host has a client
// if we find no ghosts to become the alien. If the host has a client
// he will become the alien but if he doesn't then we will set the stage
// to 2, so we don't do a process heavy check everytime.
if(candidates.len)
C = pick(candidates)
else if(owner.client)
C = owner.client
else
stage = 2 // Let's try again later.
polling = 0
return
var/overlay = image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie")
owner.overlays += overlay
spawn(6)
var/mob/living/carbon/alien/larva/new_xeno = new(owner.drop_location())
new_xeno.key = C.key
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
new_xeno.mind.name = new_xeno.name
new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH
new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100)//To get the player's attention
if(gib_on_success)
owner.gib()
else
owner.adjustBruteLoss(40)
owner.overlays -= overlay
qdel(src)
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/internal/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/internal/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
qdel(I)
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
/obj/item/organ/internal/body_egg/alien_embryo
name = "alien embryo"
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/stage = 0
var/polling = 0
/obj/item/organ/internal/body_egg/alien_embryo/on_find(mob/living/finder)
..()
if(stage < 4)
to_chat(finder, "It's small and weak, barely the size of a fetus.")
else
to_chat(finder, "It's grown quite large, and writhes slightly as you look at it.")
if(prob(10))
AttemptGrow(0)
/obj/item/organ/internal/body_egg/alien_embryo/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/internal/body_egg/alien_embryo/on_life()
switch(stage)
if(2, 3)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(2))
to_chat(owner, "<span class='danger'>Your throat feels sore.</span>")
if(prob(2))
to_chat(owner, "<span class='danger'>Mucous runs down the back of your throat.</span>")
if(4)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(4))
to_chat(owner, "<span class='danger'>Your muscles ache.</span>")
if(prob(20))
owner.take_organ_damage(1)
if(prob(4))
to_chat(owner, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
owner.adjustToxLoss(1)
if(5)
to_chat(owner, "<span class='danger'>You feel something tearing its way out of your stomach...</span>")
owner.adjustToxLoss(10)
/obj/item/organ/internal/body_egg/alien_embryo/egg_process()
if(stage < 5 && prob(3))
stage++
spawn(0)
RefreshInfectionImage()
if(stage == 5 && prob(50))
for(var/datum/surgery/S in owner.surgeries)
if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/internal/manipulate_organs))
AttemptGrow(0)
return
AttemptGrow()
/obj/item/organ/internal/body_egg/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1)
if(!owner || polling)
return
polling = 1
spawn()
var/list/candidates = pollCandidates("Do you want to play as an alien?", ROLE_ALIEN, 0)
var/mob/C = null
// To stop clientless larva, we will check that our host has a client
// if we find no ghosts to become the alien. If the host has a client
// he will become the alien but if he doesn't then we will set the stage
// to 2, so we don't do a process heavy check everytime.
if(candidates.len)
C = pick(candidates)
else if(owner.client)
C = owner.client
else
stage = 2 // Let's try again later.
polling = 0
return
var/overlay = image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie")
owner.overlays += overlay
spawn(6)
var/mob/living/carbon/alien/larva/new_xeno = new(owner.drop_location())
new_xeno.key = C.key
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
new_xeno.mind.name = new_xeno.name
new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH
new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100)//To get the player's attention
if(gib_on_success)
owner.gib()
else
owner.adjustBruteLoss(40)
owner.overlays -= overlay
qdel(src)
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/internal/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/internal/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
qdel(I)
@@ -1,239 +1,239 @@
//TODO: Make these simple_animals
#define MIN_IMPREGNATION_TIME 100 //time it takes to impregnate someone
#define MAX_IMPREGNATION_TIME 150
#define MIN_ACTIVE_TIME 200 //time between being dropped and going idle
#define MAX_ACTIVE_TIME 400
/obj/item/clothing/mask/facehugger
name = "alien"
desc = "It has some sort of a tube at the end of its tail."
icon = 'icons/mob/alien.dmi'
icon_state = "facehugger"
item_state = "facehugger"
w_class = WEIGHT_CLASS_TINY //note: can be picked up by aliens unlike most other items of w_class below 4
throw_range = 5
tint = 3
flags = AIRTIGHT
flags_cover = MASKCOVERSMOUTH | MASKCOVERSEYES
layer = MOB_LAYER
max_integrity = 100
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
var/sterile = FALSE
var/real = TRUE //0 for the toy, 1 for real. Sure I could istype, but fuck that.
var/strength = 5
var/attached = 0
/obj/item/clothing/mask/facehugger/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
..()
if(obj_integrity < 90)
Die()
/obj/item/clothing/mask/facehugger/attackby(obj/item/O, mob/user, params)
return O.attack_obj(src, user)
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
return attack_hand(user)
/obj/item/clothing/mask/facehugger/attack_hand(mob/user)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
if(Attach(user))
return
..()
/obj/item/clothing/mask/facehugger/attack(mob/living/M, mob/user)
..()
user.unEquip(src)
Attach(M)
/obj/item/clothing/mask/facehugger/examine(mob/user)
. = ..()
if(real)//So that giant red text about probisci doesn't show up for fake ones
switch(stat)
if(DEAD,UNCONSCIOUS)
. += "<span class='boldannounce'>[src] is not moving.</span>"
if(CONSCIOUS)
. += "<span class='boldannounce'>[src] seems to be active!</span>"
if(sterile)
. += "<span class='boldannounce'>It looks like the proboscis has been removed.</span>"
/obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > 300)
Die()
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target, oldloc)
HasProximity(target)
return
/obj/item/clothing/mask/facehugger/on_found(mob/finder)
if(stat == CONSCIOUS)
return HasProximity(finder)
return 0
/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj)
if(CanHug(AM) && Adjacent(AM))
return Attach(AM)
return 0
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed)
if(!..())
return
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]_thrown"
spawn(15)
if(icon_state == "[initial(icon_state)]_thrown")
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom)
..()
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]"
Attach(hit_atom)
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!isliving(M))
return 0
if((!iscorgi(M) && !iscarbon(M)) || isalien(M))
return 0
if(attached)
return 0
else
attached++
spawn(MAX_IMPREGNATION_TIME)
attached = 0
if(M.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
return 0
if(M.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo))
return 0
if(loc == M)
return 0
if(stat != CONSCIOUS)
return 0
if(!sterile) M.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage
M.visible_message("<span class='danger'>[src] leaps at [M]'s face!</span>", \
"<span class='userdanger'>[src] leaps at [M]'s face!</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.head && H.head.flags_cover & HEADCOVERSMOUTH)
H.visible_message("<span class='danger'>[src] smashes against [H]'s [H.head]!</span>", \
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return 0
if(iscarbon(M))
var/mob/living/carbon/target = M
if(target.wear_mask)
if(prob(20))
return 0
if(istype(target.wear_mask, /obj/item/clothing/mask/muzzle))
var/obj/item/clothing/mask/muzzle/S = target.wear_mask
if(S.do_break())
target.visible_message("<span class='danger'>[src] spits acid onto [S] melting the lock!</span>", \
"<span class='userdanger'>[src] spits acid onto [S] melting the lock!</span>")
var/obj/item/clothing/W = target.wear_mask
if(W.flags & NODROP)
return 0
target.unEquip(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
src.loc = target
target.equip_to_slot(src, slot_wear_mask,,0)
if(!sterile)
M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
GoIdle() //so it doesn't jump the people that tear it off
spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
Impregnate(M)
return 1
/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob)
if(!target || target.stat == DEAD || loc != target) //was taken off or something
return
if(iscarbon(target))
var/mob/living/carbon/C = target
if(C.wear_mask != src)
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!H.check_has_mouth())
return
if(!sterile)
//target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance
target.visible_message("<span class='danger'>[src] falls limp after violating [target]'s face!</span>", \
"<span class='userdanger'>[src] falls limp after violating [target]'s face!</span>")
Die()
icon_state = "[initial(icon_state)]_impregnated"
if(!target.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo))
new /obj/item/organ/internal/body_egg/alien_embryo(target)
else
target.visible_message("<span class='danger'>[src] violates [target]'s face!</span>", \
"<span class='userdanger'>[src] violates [target]'s face!</span>")
/obj/item/clothing/mask/facehugger/proc/GoActive()
if(stat == DEAD || stat == CONSCIOUS)
return
stat = CONSCIOUS
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/proc/GoIdle()
if(stat == DEAD || stat == UNCONSCIOUS)
return
stat = UNCONSCIOUS
icon_state = "[initial(icon_state)]_inactive"
spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME))
GoActive()
return
/obj/item/clothing/mask/facehugger/proc/Die()
if(stat == DEAD)
return
icon_state = "[initial(icon_state)]_dead"
item_state = "facehugger_inactive"
stat = DEAD
visible_message("<span class='danger'>[src] curls up into a ball!</span>")
/proc/CanHug(mob/living/M)
if(!istype(M))
return 0
if(M.stat == DEAD)
return 0
if(M.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
return 0
if(iscorgi(M))
return 1
var/mob/living/carbon/C = M
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.head && H.head.flags_cover & HEADCOVERSMOUTH)
return 0
return 1
return 0
/obj/item/clothing/mask/facehugger/lamarr
name = "Lamarr"
desc = "The worst she might do is attempt to... couple with your head." //hope we don't get sued over a harmless reference, rite?
sterile = 1
gender = FEMALE
//TODO: Make these simple_animals
#define MIN_IMPREGNATION_TIME 100 //time it takes to impregnate someone
#define MAX_IMPREGNATION_TIME 150
#define MIN_ACTIVE_TIME 200 //time between being dropped and going idle
#define MAX_ACTIVE_TIME 400
/obj/item/clothing/mask/facehugger
name = "alien"
desc = "It has some sort of a tube at the end of its tail."
icon = 'icons/mob/alien.dmi'
icon_state = "facehugger"
item_state = "facehugger"
w_class = WEIGHT_CLASS_TINY //note: can be picked up by aliens unlike most other items of w_class below 4
throw_range = 5
tint = 3
flags = AIRTIGHT
flags_cover = MASKCOVERSMOUTH | MASKCOVERSEYES
layer = MOB_LAYER
max_integrity = 100
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
var/sterile = FALSE
var/real = TRUE //0 for the toy, 1 for real. Sure I could istype, but fuck that.
var/strength = 5
var/attached = 0
/obj/item/clothing/mask/facehugger/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
..()
if(obj_integrity < 90)
Die()
/obj/item/clothing/mask/facehugger/attackby(obj/item/O, mob/user, params)
return O.attack_obj(src, user)
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
return attack_hand(user)
/obj/item/clothing/mask/facehugger/attack_hand(mob/user)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
if(Attach(user))
return
..()
/obj/item/clothing/mask/facehugger/attack(mob/living/M, mob/user)
..()
user.unEquip(src)
Attach(M)
/obj/item/clothing/mask/facehugger/examine(mob/user)
. = ..()
if(real)//So that giant red text about probisci doesn't show up for fake ones
switch(stat)
if(DEAD,UNCONSCIOUS)
. += "<span class='boldannounce'>[src] is not moving.</span>"
if(CONSCIOUS)
. += "<span class='boldannounce'>[src] seems to be active!</span>"
if(sterile)
. += "<span class='boldannounce'>It looks like the proboscis has been removed.</span>"
/obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > 300)
Die()
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target, oldloc)
HasProximity(target)
return
/obj/item/clothing/mask/facehugger/on_found(mob/finder)
if(stat == CONSCIOUS)
return HasProximity(finder)
return 0
/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj)
if(CanHug(AM) && Adjacent(AM))
return Attach(AM)
return 0
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed)
if(!..())
return
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]_thrown"
spawn(15)
if(icon_state == "[initial(icon_state)]_thrown")
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom)
..()
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]"
Attach(hit_atom)
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!isliving(M))
return 0
if((!iscorgi(M) && !iscarbon(M)) || isalien(M))
return 0
if(attached)
return 0
else
attached++
spawn(MAX_IMPREGNATION_TIME)
attached = 0
if(M.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
return 0
if(M.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo))
return 0
if(loc == M)
return 0
if(stat != CONSCIOUS)
return 0
if(!sterile) M.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage
M.visible_message("<span class='danger'>[src] leaps at [M]'s face!</span>", \
"<span class='userdanger'>[src] leaps at [M]'s face!</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.head && H.head.flags_cover & HEADCOVERSMOUTH)
H.visible_message("<span class='danger'>[src] smashes against [H]'s [H.head]!</span>", \
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return 0
if(iscarbon(M))
var/mob/living/carbon/target = M
if(target.wear_mask)
if(prob(20))
return 0
if(istype(target.wear_mask, /obj/item/clothing/mask/muzzle))
var/obj/item/clothing/mask/muzzle/S = target.wear_mask
if(S.do_break())
target.visible_message("<span class='danger'>[src] spits acid onto [S] melting the lock!</span>", \
"<span class='userdanger'>[src] spits acid onto [S] melting the lock!</span>")
var/obj/item/clothing/W = target.wear_mask
if(W.flags & NODROP)
return 0
target.unEquip(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
src.loc = target
target.equip_to_slot(src, slot_wear_mask,,0)
if(!sterile)
M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
GoIdle() //so it doesn't jump the people that tear it off
spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
Impregnate(M)
return 1
/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob)
if(!target || target.stat == DEAD || loc != target) //was taken off or something
return
if(iscarbon(target))
var/mob/living/carbon/C = target
if(C.wear_mask != src)
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(!H.check_has_mouth())
return
if(!sterile)
//target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance
target.visible_message("<span class='danger'>[src] falls limp after violating [target]'s face!</span>", \
"<span class='userdanger'>[src] falls limp after violating [target]'s face!</span>")
Die()
icon_state = "[initial(icon_state)]_impregnated"
if(!target.get_int_organ(/obj/item/organ/internal/body_egg/alien_embryo))
new /obj/item/organ/internal/body_egg/alien_embryo(target)
else
target.visible_message("<span class='danger'>[src] violates [target]'s face!</span>", \
"<span class='userdanger'>[src] violates [target]'s face!</span>")
/obj/item/clothing/mask/facehugger/proc/GoActive()
if(stat == DEAD || stat == CONSCIOUS)
return
stat = CONSCIOUS
icon_state = "[initial(icon_state)]"
/obj/item/clothing/mask/facehugger/proc/GoIdle()
if(stat == DEAD || stat == UNCONSCIOUS)
return
stat = UNCONSCIOUS
icon_state = "[initial(icon_state)]_inactive"
spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME))
GoActive()
return
/obj/item/clothing/mask/facehugger/proc/Die()
if(stat == DEAD)
return
icon_state = "[initial(icon_state)]_dead"
item_state = "facehugger_inactive"
stat = DEAD
visible_message("<span class='danger'>[src] curls up into a ball!</span>")
/proc/CanHug(mob/living/M)
if(!istype(M))
return 0
if(M.stat == DEAD)
return 0
if(M.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
return 0
if(iscorgi(M))
return 1
var/mob/living/carbon/C = M
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.head && H.head.flags_cover & HEADCOVERSMOUTH)
return 0
return 1
return 0
/obj/item/clothing/mask/facehugger/lamarr
name = "Lamarr"
desc = "The worst she might do is attempt to... couple with your head." //hope we don't get sued over a harmless reference, rite?
sterile = 1
gender = FEMALE
+299 -299
View File
@@ -1,299 +1,299 @@
/obj/item/mmi
name = "Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity."
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = WEIGHT_CLASS_NORMAL
origin_tech = "biotech=3"
origin_tech = "biotech=2;programming=3;engineering=2"
//Revised. Brainmob is now contained directly within object of transfer. MMI in this case.
var/alien = 0
var/syndiemmi = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null//The current occupant.
var/obj/item/organ/internal/brain/held_brain = null // This is so MMI's aren't brainscrubber 9000's
var/mob/living/silicon/robot/robot = null//Appears unused.
var/obj/mecha/mecha = null//This does not appear to be used outside of reference in mecha.dm.
// I'm using this for mechs giving MMIs HUDs now
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))
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)
to_chat(user, "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain.</span>")
return
if(held_brain)
to_chat(user, "<span class='userdanger'>Somehow, this MMI still has a brain in it. Report this to the bug tracker.</span>")
log_runtime(EXCEPTION("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared"), src)
return
if(user.drop_item())
B.forceMove(src)
visible_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = B.brainmob
B.brainmob = null
brainmob.forceMove(src)
brainmob.container = src
brainmob.stat = CONSCIOUS
GLOB.respawnable_list -= brainmob
GLOB.dead_mob_list -= brainmob//Update dem lists
GLOB.living_mob_list += brainmob
held_brain = B
if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff
name = "Man-Machine Interface: Alien - [brainmob.real_name]"
icon = 'icons/mob/alien.dmi'
become_occupied("AlienMMI")
alien = 1
else
name = "Man-Machine Interface: [brainmob.real_name]"
icon = B.mmi_icon
become_occupied("[B.mmi_icon_state]")
alien = 0
if(radio_action)
radio_action.UpdateButtonIcon()
feedback_inc("cyborg_mmis_filled",1)
else
to_chat(user, "<span class='warning'>You can't drop [B]!</span>")
return
if(istype(O, /obj/item/mmi_radio_upgrade))
if(radio)
to_chat(user, "<span class='warning'>[src] already has a radio installed.</span>")
else
user.visible_message("<span class='notice'>[user] begins to install the [O] into [src]...</span>", \
"<span class='notice'>You start to install the [O] into [src]...</span>")
if(do_after(user, 20, target=src))
if(user.drop_item())
user.visible_message("<span class='notice'>[user] installs [O] in [src].</span>", \
"<span class='notice'>You install [O] in [src].</span>")
if(brainmob)
to_chat(brainmob, "<span class='notice'>MMI radio capability installed.</span>")
install_radio()
qdel(O)
else
to_chat(user, "<span class='warning'>You can't drop [O]!</span>")
return
// Maybe later add encryption key support, but that's a pain in the neck atm
if(brainmob)
O.attack(brainmob, user)//Oh noooeeeee
// Brainmobs can take damage, but they can't actually die. Maybe should fix.
return
return ..()
/obj/item/mmi/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
return
if(!radio)
to_chat(user, "<span class='warning'>There is no radio in [src]!</span>")
return
user.visible_message("<span class='warning'>[user] begins to uninstall the radio from [src]...</span>", \
"<span class='notice'>You start to uninstall the radio from [src]...</span>")
if(!I.use_tool(src, user, 40, volume = I.tool_volume) || !radio)
return
uninstall_radio()
new /obj/item/mmi_radio_upgrade(get_turf(src))
user.visible_message("<span class='warning'>[user] uninstalls the radio from [src].</span>", \
"<span class='notice'>You uninstall the radio from [src].</span>")
/obj/item/mmi/attack_self(mob/user as mob)
if(!brainmob)
to_chat(user, "<span class='warning'>You upend the MMI, but there's nothing in it.</span>")
else
to_chat(user, "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>")
dropbrain(get_turf(user))
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
name = "Man-Machine Interface"
/obj/item/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
brainmob.container = src
if(!istype(H.dna.species) || isnull(H.dna.species.return_organ("brain"))) // Diona/buggy people
held_brain = new(src)
else // We have a species, and it has a brain
var/brain_path = H.dna.species.return_organ("brain")
if(!ispath(brain_path, /obj/item/organ/internal/brain))
brain_path = /obj/item/organ/internal/brain
held_brain = new brain_path(src) // Slime people will keep their slimy brains this way
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
name = "Man-Machine Interface: [brainmob.real_name]"
become_occupied("mmi_full")
//I made this proc as a way to have a brainmob be transferred to any created brain, and to solve the
//problem i was having with alien/nonalien brain drops.
/obj/item/mmi/proc/dropbrain(var/turf/dropspot)
if(isnull(held_brain))
log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)]."), src)
to_chat(brainmob, "<span class='userdanger'>Your MMI did not contain a brain! We'll make a new one for you, but you'd best report this to the bugtracker!</span>")
held_brain = new(dropspot) // Let's not ruin someone's round because of something dumb -- Crazylemon
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
brainmob.container = null//Reset brainmob mmi var.
brainmob.forceMove(held_brain) //Throw mob into brain.
GLOB.respawnable_list += brainmob
GLOB.living_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
held_brain.brainmob.cancel_camera()
brainmob = null//Set mmi brainmob var to null
held_brain.forceMove(dropspot)
held_brain = null
/obj/item/mmi/proc/become_occupied(var/new_icon)
icon_state = new_icon
if(radio)
radio_action.ApplyIcon()
/obj/item/mmi/examine(mob/user)
. = ..()
if(radio)
. += "<span class='notice'>A radio is installed on [src].</span>"
/obj/item/mmi/proc/install_radio()
radio = new(src)
radio.broadcasting = TRUE
radio_action = new(radio, src)
if(brainmob && brainmob.loc == src)
radio_action.Grant(brainmob)
/obj/item/mmi/proc/uninstall_radio()
QDEL_NULL(radio)
QDEL_NULL(radio_action)
/datum/action/generic/configure_mmi_radio
name = "Configure MMI Radio"
desc = "Configure the radio installed in your MMI."
check_flags = AB_CHECK_CONSCIOUS
procname = "ui_interact"
var/obj/item/mmi = null
/datum/action/generic/configure_mmi_radio/New(var/Target, var/obj/item/mmi/M)
. = ..()
mmi = M
/datum/action/generic/configure_mmi_radio/Destroy()
mmi = null
return ..()
/datum/action/generic/configure_mmi_radio/ApplyIcon(obj/screen/movable/action_button/current_button)
// A copy/paste of the item action icon code
current_button.overlays.Cut()
if(target)
var/obj/item/I = mmi
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = 21
I.plane = HUD_PLANE
current_button.overlays += I
I.layer = old_layer
I.plane = old_plane
/obj/item/mmi/emp_act(severity)
if(!brainmob)
return
else
switch(severity)
if(1)
brainmob.emp_damage += rand(20,30)
if(2)
brainmob.emp_damage += rand(10,20)
if(3)
brainmob.emp_damage += rand(0,10)
..()
/obj/item/mmi/relaymove(var/mob/user, var/direction)
if(user.stat || user.stunned)
return
var/obj/item/rig/rig = src.get_rig()
if(rig)
rig.forced_move(direction, user)
/obj/item/mmi/Destroy()
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
borg.mmi = null
QDEL_NULL(brainmob)
QDEL_NULL(held_brain)
QDEL_NULL(radio)
QDEL_NULL(radio_action)
return ..()
// These two procs are important for when an MMI pilots a mech
// (Brainmob "enters/leaves" the MMI when piloting)
// Also neatly handles basically every case where a brain
// is inserted or removed from an MMI
/obj/item/mmi/Entered(atom/movable/A)
if(radio && istype(A, /mob/living/carbon/brain))
radio_action.Grant(A)
/obj/item/mmi/Exited(atom/movable/A)
if(radio && istype(A, /mob/living/carbon/brain))
radio_action.Remove(A)
/obj/item/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores."
origin_tech = "biotech=4;programming=4;syndicate=2"
syndiemmi = 1
/obj/item/mmi/attempt_become_organ(obj/item/organ/external/parent,mob/living/carbon/human/H)
if(!brainmob)
return 0
if(!parent)
log_debug("Attempting to insert into a null parent!")
return 0
if(H.get_int_organ(/obj/item/organ/internal/brain))
// one brain at a time
return 0
var/obj/item/organ/internal/brain/mmi_holder/holder = new()
holder.parent_organ = parent.limb_name
forceMove(holder)
holder.stored_mmi = src
holder.update_from_mmi()
if(brainmob && brainmob.mind)
brainmob.mind.transfer_to(H)
holder.insert(H)
return 1
// As a synthetic, the only limit on visibility is view range
/obj/item/mmi/contents_nano_distance(var/src_object, var/mob/living/user)
if((src_object in view(src)) && get_dist(src_object, src) <= user.client.view)
return STATUS_INTERACTIVE // interactive (green visibility)
return user.shared_living_nano_distance(src_object)
// For now the only thing that is helped by this is radio access
// Later a more intricate system for MMI UI interaction can be established
/obj/item/mmi/contents_nano_interact(var/src_object, var/mob/living/user)
if(!istype(user, /mob/living/carbon/brain))
log_runtime(EXCEPTION("Somehow a non-brain mob is inside an MMI!"), user)
return ..()
var/mob/living/carbon/brain/BM = user
if(BM.container == src && src_object == radio)
return STATUS_INTERACTIVE
return ..()
/obj/item/mmi
name = "Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity."
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = WEIGHT_CLASS_NORMAL
origin_tech = "biotech=3"
origin_tech = "biotech=2;programming=3;engineering=2"
//Revised. Brainmob is now contained directly within object of transfer. MMI in this case.
var/alien = 0
var/syndiemmi = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null//The current occupant.
var/obj/item/organ/internal/brain/held_brain = null // This is so MMI's aren't brainscrubber 9000's
var/mob/living/silicon/robot/robot = null//Appears unused.
var/obj/mecha/mecha = null//This does not appear to be used outside of reference in mecha.dm.
// I'm using this for mechs giving MMIs HUDs now
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))
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)
to_chat(user, "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain.</span>")
return
if(held_brain)
to_chat(user, "<span class='userdanger'>Somehow, this MMI still has a brain in it. Report this to the bug tracker.</span>")
log_runtime(EXCEPTION("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared"), src)
return
if(user.drop_item())
B.forceMove(src)
visible_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = B.brainmob
B.brainmob = null
brainmob.forceMove(src)
brainmob.container = src
brainmob.stat = CONSCIOUS
GLOB.respawnable_list -= brainmob
GLOB.dead_mob_list -= brainmob//Update dem lists
GLOB.living_mob_list += brainmob
held_brain = B
if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff
name = "Man-Machine Interface: Alien - [brainmob.real_name]"
icon = 'icons/mob/alien.dmi'
become_occupied("AlienMMI")
alien = 1
else
name = "Man-Machine Interface: [brainmob.real_name]"
icon = B.mmi_icon
become_occupied("[B.mmi_icon_state]")
alien = 0
if(radio_action)
radio_action.UpdateButtonIcon()
feedback_inc("cyborg_mmis_filled",1)
else
to_chat(user, "<span class='warning'>You can't drop [B]!</span>")
return
if(istype(O, /obj/item/mmi_radio_upgrade))
if(radio)
to_chat(user, "<span class='warning'>[src] already has a radio installed.</span>")
else
user.visible_message("<span class='notice'>[user] begins to install the [O] into [src]...</span>", \
"<span class='notice'>You start to install the [O] into [src]...</span>")
if(do_after(user, 20, target=src))
if(user.drop_item())
user.visible_message("<span class='notice'>[user] installs [O] in [src].</span>", \
"<span class='notice'>You install [O] in [src].</span>")
if(brainmob)
to_chat(brainmob, "<span class='notice'>MMI radio capability installed.</span>")
install_radio()
qdel(O)
else
to_chat(user, "<span class='warning'>You can't drop [O]!</span>")
return
// Maybe later add encryption key support, but that's a pain in the neck atm
if(brainmob)
O.attack(brainmob, user)//Oh noooeeeee
// Brainmobs can take damage, but they can't actually die. Maybe should fix.
return
return ..()
/obj/item/mmi/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
return
if(!radio)
to_chat(user, "<span class='warning'>There is no radio in [src]!</span>")
return
user.visible_message("<span class='warning'>[user] begins to uninstall the radio from [src]...</span>", \
"<span class='notice'>You start to uninstall the radio from [src]...</span>")
if(!I.use_tool(src, user, 40, volume = I.tool_volume) || !radio)
return
uninstall_radio()
new /obj/item/mmi_radio_upgrade(get_turf(src))
user.visible_message("<span class='warning'>[user] uninstalls the radio from [src].</span>", \
"<span class='notice'>You uninstall the radio from [src].</span>")
/obj/item/mmi/attack_self(mob/user as mob)
if(!brainmob)
to_chat(user, "<span class='warning'>You upend the MMI, but there's nothing in it.</span>")
else
to_chat(user, "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>")
dropbrain(get_turf(user))
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
name = "Man-Machine Interface"
/obj/item/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
brainmob.container = src
if(!istype(H.dna.species) || isnull(H.dna.species.return_organ("brain"))) // Diona/buggy people
held_brain = new(src)
else // We have a species, and it has a brain
var/brain_path = H.dna.species.return_organ("brain")
if(!ispath(brain_path, /obj/item/organ/internal/brain))
brain_path = /obj/item/organ/internal/brain
held_brain = new brain_path(src) // Slime people will keep their slimy brains this way
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
name = "Man-Machine Interface: [brainmob.real_name]"
become_occupied("mmi_full")
//I made this proc as a way to have a brainmob be transferred to any created brain, and to solve the
//problem i was having with alien/nonalien brain drops.
/obj/item/mmi/proc/dropbrain(var/turf/dropspot)
if(isnull(held_brain))
log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)]."), src)
to_chat(brainmob, "<span class='userdanger'>Your MMI did not contain a brain! We'll make a new one for you, but you'd best report this to the bugtracker!</span>")
held_brain = new(dropspot) // Let's not ruin someone's round because of something dumb -- Crazylemon
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
brainmob.container = null//Reset brainmob mmi var.
brainmob.forceMove(held_brain) //Throw mob into brain.
GLOB.respawnable_list += brainmob
GLOB.living_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
held_brain.brainmob.cancel_camera()
brainmob = null//Set mmi brainmob var to null
held_brain.forceMove(dropspot)
held_brain = null
/obj/item/mmi/proc/become_occupied(var/new_icon)
icon_state = new_icon
if(radio)
radio_action.ApplyIcon()
/obj/item/mmi/examine(mob/user)
. = ..()
if(radio)
. += "<span class='notice'>A radio is installed on [src].</span>"
/obj/item/mmi/proc/install_radio()
radio = new(src)
radio.broadcasting = TRUE
radio_action = new(radio, src)
if(brainmob && brainmob.loc == src)
radio_action.Grant(brainmob)
/obj/item/mmi/proc/uninstall_radio()
QDEL_NULL(radio)
QDEL_NULL(radio_action)
/datum/action/generic/configure_mmi_radio
name = "Configure MMI Radio"
desc = "Configure the radio installed in your MMI."
check_flags = AB_CHECK_CONSCIOUS
procname = "ui_interact"
var/obj/item/mmi = null
/datum/action/generic/configure_mmi_radio/New(var/Target, var/obj/item/mmi/M)
. = ..()
mmi = M
/datum/action/generic/configure_mmi_radio/Destroy()
mmi = null
return ..()
/datum/action/generic/configure_mmi_radio/ApplyIcon(obj/screen/movable/action_button/current_button)
// A copy/paste of the item action icon code
current_button.overlays.Cut()
if(target)
var/obj/item/I = mmi
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = 21
I.plane = HUD_PLANE
current_button.overlays += I
I.layer = old_layer
I.plane = old_plane
/obj/item/mmi/emp_act(severity)
if(!brainmob)
return
else
switch(severity)
if(1)
brainmob.emp_damage += rand(20,30)
if(2)
brainmob.emp_damage += rand(10,20)
if(3)
brainmob.emp_damage += rand(0,10)
..()
/obj/item/mmi/relaymove(var/mob/user, var/direction)
if(user.stat || user.stunned)
return
var/obj/item/rig/rig = src.get_rig()
if(rig)
rig.forced_move(direction, user)
/obj/item/mmi/Destroy()
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
borg.mmi = null
QDEL_NULL(brainmob)
QDEL_NULL(held_brain)
QDEL_NULL(radio)
QDEL_NULL(radio_action)
return ..()
// These two procs are important for when an MMI pilots a mech
// (Brainmob "enters/leaves" the MMI when piloting)
// Also neatly handles basically every case where a brain
// is inserted or removed from an MMI
/obj/item/mmi/Entered(atom/movable/A)
if(radio && istype(A, /mob/living/carbon/brain))
radio_action.Grant(A)
/obj/item/mmi/Exited(atom/movable/A)
if(radio && istype(A, /mob/living/carbon/brain))
radio_action.Remove(A)
/obj/item/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores."
origin_tech = "biotech=4;programming=4;syndicate=2"
syndiemmi = 1
/obj/item/mmi/attempt_become_organ(obj/item/organ/external/parent,mob/living/carbon/human/H)
if(!brainmob)
return 0
if(!parent)
log_debug("Attempting to insert into a null parent!")
return 0
if(H.get_int_organ(/obj/item/organ/internal/brain))
// one brain at a time
return 0
var/obj/item/organ/internal/brain/mmi_holder/holder = new()
holder.parent_organ = parent.limb_name
forceMove(holder)
holder.stored_mmi = src
holder.update_from_mmi()
if(brainmob && brainmob.mind)
brainmob.mind.transfer_to(H)
holder.insert(H)
return 1
// As a synthetic, the only limit on visibility is view range
/obj/item/mmi/contents_nano_distance(var/src_object, var/mob/living/user)
if((src_object in view(src)) && get_dist(src_object, src) <= user.client.view)
return STATUS_INTERACTIVE // interactive (green visibility)
return user.shared_living_nano_distance(src_object)
// For now the only thing that is helped by this is radio access
// Later a more intricate system for MMI UI interaction can be established
/obj/item/mmi/contents_nano_interact(var/src_object, var/mob/living/user)
if(!istype(user, /mob/living/carbon/brain))
log_runtime(EXCEPTION("Somehow a non-brain mob is inside an MMI!"), user)
return ..()
var/mob/living/carbon/brain/BM = user
if(BM.container == src && src_object == radio)
return STATUS_INTERACTIVE
return ..()
+111 -111
View File
@@ -1,111 +1,111 @@
/mob/living/carbon/brain
var/obj/item/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
use_me = 0 //Can't use the me verb, it's a freaking immobile brain
icon = 'icons/obj/surgery.dmi'
icon_state = "brain1"
/mob/living/carbon/brain/New()
create_reagents(330)
add_language("Galactic Common")
..()
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
return ..()
/mob/living/carbon/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd
if(istype(other, /mob/living/silicon/ai))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/decoy))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/pai))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/robot))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/carbon/human))
return 1
if(istype(other, /mob/living/simple_animal/slime))
return 1
return ..()
/mob/living/carbon/brain/update_canmove(delay_action_updates = 0)
if(in_contents_of(/obj/mecha))
canmove = 1
use_me = 1 //If it can move, let it emote
else if(istype(loc, /obj/item/mmi))
canmove = 1 //mmi won't move anyways so whatever
else
canmove = 0
if(!delay_action_updates)
update_action_buttons_icon()
return canmove
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return
/mob/living/carbon/brain/blob_act(obj/structure/blob/B)
return
/mob/living/carbon/brain/on_forcemove(atom/newloc)
if(container)
container.forceMove(newloc)
else //something went very wrong.
CRASH("Brainmob without container.")
forceMove(container)
/*
This will return true if the brain has a container that leaves it less helpless than a naked brain
I'm using this for Stat to give it a more nifty interface to work with
*/
/mob/living/carbon/brain/proc/has_synthetic_assistance()
return (container && istype(container, /obj/item/mmi)) || in_contents_of(/obj/mecha)
/mob/living/carbon/brain/proc/get_race()
if(container)
var/obj/item/mmi/M = container
if(istype(M) && M.held_brain)
return M.held_brain.dna.species.name
else
return "Artificial Life"
if(istype(loc, /obj/item/organ/internal/brain))
var/obj/item/organ/internal/brain/B = loc
return B.dna.species.name
/mob/living/carbon/brain/Stat()
..()
if(has_synthetic_assistance())
statpanel("Status")
show_stat_emergency_shuttle_eta()
if(client.statpanel == "Status")
//Knowing how well-off your mech is doing is really important as an MMI
if(istype(src.loc, /obj/mecha))
var/obj/mecha/M = src.loc
stat("Exosuit Charge:", "[istype(M.cell) ? "[M.cell.charge] / [M.cell.maxcharge]" : "No cell detected"]")
stat("Exosuit Integrity", "[!M.obj_integrity ? "0" : "[(M.obj_integrity / M.max_integrity) * 100]"]%")
/mob/living/carbon/brain/can_safely_leave_loc()
return 0 //You're not supposed to be ethereal jaunting, brains
/mob/living/carbon/brain/can_hear()
. = TRUE
/mob/living/carbon/brain
var/obj/item/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
use_me = 0 //Can't use the me verb, it's a freaking immobile brain
icon = 'icons/obj/surgery.dmi'
icon_state = "brain1"
/mob/living/carbon/brain/New()
create_reagents(330)
add_language("Galactic Common")
..()
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
return ..()
/mob/living/carbon/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd
if(istype(other, /mob/living/silicon/ai))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/decoy))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/pai))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/robot))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/carbon/human))
return 1
if(istype(other, /mob/living/simple_animal/slime))
return 1
return ..()
/mob/living/carbon/brain/update_canmove(delay_action_updates = 0)
if(in_contents_of(/obj/mecha))
canmove = 1
use_me = 1 //If it can move, let it emote
else if(istype(loc, /obj/item/mmi))
canmove = 1 //mmi won't move anyways so whatever
else
canmove = 0
if(!delay_action_updates)
update_action_buttons_icon()
return canmove
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return
/mob/living/carbon/brain/blob_act(obj/structure/blob/B)
return
/mob/living/carbon/brain/on_forcemove(atom/newloc)
if(container)
container.forceMove(newloc)
else //something went very wrong.
CRASH("Brainmob without container.")
forceMove(container)
/*
This will return true if the brain has a container that leaves it less helpless than a naked brain
I'm using this for Stat to give it a more nifty interface to work with
*/
/mob/living/carbon/brain/proc/has_synthetic_assistance()
return (container && istype(container, /obj/item/mmi)) || in_contents_of(/obj/mecha)
/mob/living/carbon/brain/proc/get_race()
if(container)
var/obj/item/mmi/M = container
if(istype(M) && M.held_brain)
return M.held_brain.dna.species.name
else
return "Artificial Life"
if(istype(loc, /obj/item/organ/internal/brain))
var/obj/item/organ/internal/brain/B = loc
return B.dna.species.name
/mob/living/carbon/brain/Stat()
..()
if(has_synthetic_assistance())
statpanel("Status")
show_stat_emergency_shuttle_eta()
if(client.statpanel == "Status")
//Knowing how well-off your mech is doing is really important as an MMI
if(istype(src.loc, /obj/mecha))
var/obj/mecha/M = src.loc
stat("Exosuit Charge:", "[istype(M.cell) ? "[M.cell.charge] / [M.cell.maxcharge]" : "No cell detected"]")
stat("Exosuit Integrity", "[!M.obj_integrity ? "0" : "[(M.obj_integrity / M.max_integrity) * 100]"]%")
/mob/living/carbon/brain/can_safely_leave_loc()
return 0 //You're not supposed to be ethereal jaunting, brains
/mob/living/carbon/brain/can_hear()
. = TRUE
+141 -141
View File
@@ -1,141 +1,141 @@
/obj/item/organ/internal/brain
name = "brain"
max_damage = 120
icon_state = "brain2"
force = 1.0
w_class = WEIGHT_CLASS_SMALL
throwforce = 1.0
throw_speed = 3
throw_range = 5
origin_tech = "biotech=5"
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
organ_tag = "brain"
parent_organ = "head"
slot = "brain"
vital = TRUE
hidden_pain = TRUE //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type.
var/mmi_icon = 'icons/obj/assemblies.dmi'
var/mmi_icon_state = "mmi_full"
/obj/item/organ/internal/brain/xeno
name = "xenomorph brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
origin_tech = "biotech=6"
mmi_icon = 'icons/mob/alien.dmi'
mmi_icon_state = "AlienMMI"
/obj/item/organ/internal/brain/New()
..()
spawn(5)
if(brainmob && brainmob.client)
brainmob.client.screen.len = null //clear the hud
/obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H)
brainmob = new(src)
if(isnull(dna)) // someone didn't set this right...
log_runtime(EXCEPTION("[src] at [loc] did not contain a dna datum at time of removal."), src)
dna = H.dna.Clone()
name = "\the [dna.real_name]'s [initial(src.name)]"
brainmob.dna = dna.Clone() // Silly baycode, what you do
// brainmob.dna = H.dna.Clone() Putting in and taking out a brain doesn't make it a carbon copy of the original brain of the body you put it in
brainmob.name = dna.real_name
brainmob.real_name = dna.real_name
brainmob.timeofhostdeath = H.timeofdeath
if(H.mind)
H.mind.transfer_to(brainmob)
to_chat(brainmob, "<span class='notice'>You feel slightly disoriented. That's normal when you're just a [initial(src.name)].</span>")
/obj/item/organ/internal/brain/examine(mob/user) // -- TLE
. = ..()
if(brainmob && brainmob.client)//if thar be a brain inside... the brain.
. += "You can feel the small spark of life still left in this one."
else
. += "This one seems particularly lifeless. Perhaps it will regain some of its luster later.."
/obj/item/organ/internal/brain/remove(var/mob/living/user,special = 0)
if(dna)
name = "[dna.real_name]'s [initial(name)]"
if(!owner) return ..() // Probably a redundant removal; just bail
var/obj/item/organ/internal/brain/B = src
if(!special)
var/mob/living/simple_animal/borer/borer = owner.has_brain_worms()
if(borer)
borer.leave_host() //Should remove borer if the brain is removed - RR
if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind.
B.transfer_identity(user)
if(istype(owner,/mob/living/carbon/human))
var/mob/living/carbon/human/H = owner
H.update_hair(1)
. = ..()
/obj/item/organ/internal/brain/insert(var/mob/living/target,special = 0)
name = "[initial(name)]"
var/brain_already_exists = 0
if(istype(target,/mob/living/carbon/human)) // No more IPC multibrain shenanigans
if(target.get_int_organ(/obj/item/organ/internal/brain))
brain_already_exists = 1
var/mob/living/carbon/human/H = target
H.update_hair(1)
if(!brain_already_exists)
if(brainmob)
if(target.key)
target.ghostize()
if(brainmob.mind)
brainmob.mind.transfer_to(target)
else
target.key = brainmob.key
else
log_debug("Multibrain shenanigans at ([target.x],[target.y],[target.z]), mob '[target]'")
..(target, special = special)
/obj/item/organ/internal/brain/receive_damage(amount, silent = 0) //brains are special; if they receive damage by other means, we really just want the damage to be passed ot the owner and back onto the brain.
if(owner)
owner.adjustBrainLoss(amount)
/obj/item/organ/internal/brain/necrotize(update_sprite = TRUE) //Brain also has special handling for when it necrotizes
damage = max_damage
status |= ORGAN_DEAD
STOP_PROCESSING(SSobj, src)
if(dead_icon && !is_robotic())
icon_state = dead_icon
if(owner && vital)
owner.setBrainLoss(120)
/obj/item/organ/internal/brain/prepare_eat()
return // Too important to eat.
/obj/item/organ/internal/brain/slime
name = "slime core"
desc = "A complex, organic knot of jelly and crystalline particles."
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
mmi_icon_state = "slime_mmi"
// parent_organ = "chest" Hello I am from the ministry of rubber forehead aliens how are you
/obj/item/organ/internal/brain/golem
name = "Runic mind"
desc = "A tightly furled roll of paper, covered with indecipherable runes."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll"
/obj/item/organ/internal/brain/Destroy() //copypasted from MMIs.
QDEL_NULL(brainmob)
return ..()
/obj/item/organ/internal/brain/cluwne
/obj/item/organ/internal/brain/cluwne/insert(mob/living/target, special = 0, make_cluwne = 1)
..(target, special = special)
if(ishuman(target) && make_cluwne)
var/mob/living/carbon/human/H = target
H.makeCluwne() //No matter where you go, no matter what you do, you cannot escape
/obj/item/organ/internal/brain
name = "brain"
max_damage = 120
icon_state = "brain2"
force = 1.0
w_class = WEIGHT_CLASS_SMALL
throwforce = 1.0
throw_speed = 3
throw_range = 5
origin_tech = "biotech=5"
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
organ_tag = "brain"
parent_organ = "head"
slot = "brain"
vital = TRUE
hidden_pain = TRUE //the brain has no pain receptors, and brain damage is meant to be a stealthy damage type.
var/mmi_icon = 'icons/obj/assemblies.dmi'
var/mmi_icon_state = "mmi_full"
/obj/item/organ/internal/brain/xeno
name = "xenomorph brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
origin_tech = "biotech=6"
mmi_icon = 'icons/mob/alien.dmi'
mmi_icon_state = "AlienMMI"
/obj/item/organ/internal/brain/New()
..()
spawn(5)
if(brainmob && brainmob.client)
brainmob.client.screen.len = null //clear the hud
/obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H)
brainmob = new(src)
if(isnull(dna)) // someone didn't set this right...
log_runtime(EXCEPTION("[src] at [loc] did not contain a dna datum at time of removal."), src)
dna = H.dna.Clone()
name = "\the [dna.real_name]'s [initial(src.name)]"
brainmob.dna = dna.Clone() // Silly baycode, what you do
// brainmob.dna = H.dna.Clone() Putting in and taking out a brain doesn't make it a carbon copy of the original brain of the body you put it in
brainmob.name = dna.real_name
brainmob.real_name = dna.real_name
brainmob.timeofhostdeath = H.timeofdeath
if(H.mind)
H.mind.transfer_to(brainmob)
to_chat(brainmob, "<span class='notice'>You feel slightly disoriented. That's normal when you're just a [initial(src.name)].</span>")
/obj/item/organ/internal/brain/examine(mob/user) // -- TLE
. = ..()
if(brainmob && brainmob.client)//if thar be a brain inside... the brain.
. += "You can feel the small spark of life still left in this one."
else
. += "This one seems particularly lifeless. Perhaps it will regain some of its luster later.."
/obj/item/organ/internal/brain/remove(var/mob/living/user,special = 0)
if(dna)
name = "[dna.real_name]'s [initial(name)]"
if(!owner) return ..() // Probably a redundant removal; just bail
var/obj/item/organ/internal/brain/B = src
if(!special)
var/mob/living/simple_animal/borer/borer = owner.has_brain_worms()
if(borer)
borer.leave_host() //Should remove borer if the brain is removed - RR
if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind.
B.transfer_identity(user)
if(istype(owner,/mob/living/carbon/human))
var/mob/living/carbon/human/H = owner
H.update_hair(1)
. = ..()
/obj/item/organ/internal/brain/insert(var/mob/living/target,special = 0)
name = "[initial(name)]"
var/brain_already_exists = 0
if(istype(target,/mob/living/carbon/human)) // No more IPC multibrain shenanigans
if(target.get_int_organ(/obj/item/organ/internal/brain))
brain_already_exists = 1
var/mob/living/carbon/human/H = target
H.update_hair(1)
if(!brain_already_exists)
if(brainmob)
if(target.key)
target.ghostize()
if(brainmob.mind)
brainmob.mind.transfer_to(target)
else
target.key = brainmob.key
else
log_debug("Multibrain shenanigans at ([target.x],[target.y],[target.z]), mob '[target]'")
..(target, special = special)
/obj/item/organ/internal/brain/receive_damage(amount, silent = 0) //brains are special; if they receive damage by other means, we really just want the damage to be passed ot the owner and back onto the brain.
if(owner)
owner.adjustBrainLoss(amount)
/obj/item/organ/internal/brain/necrotize(update_sprite = TRUE) //Brain also has special handling for when it necrotizes
damage = max_damage
status |= ORGAN_DEAD
STOP_PROCESSING(SSobj, src)
if(dead_icon && !is_robotic())
icon_state = dead_icon
if(owner && vital)
owner.setBrainLoss(120)
/obj/item/organ/internal/brain/prepare_eat()
return // Too important to eat.
/obj/item/organ/internal/brain/slime
name = "slime core"
desc = "A complex, organic knot of jelly and crystalline particles."
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
mmi_icon_state = "slime_mmi"
// parent_organ = "chest" Hello I am from the ministry of rubber forehead aliens how are you
/obj/item/organ/internal/brain/golem
name = "Runic mind"
desc = "A tightly furled roll of paper, covered with indecipherable runes."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll"
/obj/item/organ/internal/brain/Destroy() //copypasted from MMIs.
QDEL_NULL(brainmob)
return ..()
/obj/item/organ/internal/brain/cluwne
/obj/item/organ/internal/brain/cluwne/insert(mob/living/target, special = 0, make_cluwne = 1)
..(target, special = special)
if(ishuman(target) && make_cluwne)
var/mob/living/carbon/human/H = target
H.makeCluwne() //No matter where you go, no matter what you do, you cannot escape
+27 -27
View File
@@ -1,27 +1,27 @@
/mob/living/carbon/brain/death(gibbed)
// Only execute the below if we successfully died
. = ..()
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>")
mmi.icon_state = mmi.dead_icon
/mob/living/carbon/brain/gib()
// can we muster a parent call here?
if(!death(TRUE) && stat != DEAD)
return FALSE
notransform = 1
canmove = 0
icon = null
invisibility = 101
gibs(loc, dna)
if(container && istype(container, /obj/item/mmi))
qdel(container)//Gets rid of the MMI if there is one
if(loc)
if(istype(loc,/obj/item/organ/internal/brain))
qdel(loc)//Gets rid of the brain item
QDEL_IN(src, 0)
/mob/living/carbon/brain/death(gibbed)
// Only execute the below if we successfully died
. = ..()
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>")
mmi.icon_state = mmi.dead_icon
/mob/living/carbon/brain/gib()
// can we muster a parent call here?
if(!death(TRUE) && stat != DEAD)
return FALSE
notransform = 1
canmove = 0
icon = null
invisibility = 101
gibs(loc, dna)
if(container && istype(container, /obj/item/mmi))
qdel(container)//Gets rid of the MMI if there is one
if(loc)
if(istype(loc,/obj/item/organ/internal/brain))
qdel(loc)//Gets rid of the brain item
QDEL_IN(src, 0)
@@ -48,4 +48,4 @@
to_chat(src, "alarm, alert, notice, flash,blink, whistle, beep, boop")
if(message && !stat)
..()
..()
+40 -40
View File
@@ -1,40 +1,40 @@
/mob/living/carbon/brain/handle_mutations_and_radiation()
if(radiation)
if(radiation > 100)
if(!container)
to_chat(src, "<span class='danger'>You feel weak.</span>")
else
to_chat(src, "<span class='danger'>STATUS: CRITICAL AMOUNTS OF RADIATION DETECTED.</span>")
switch(radiation)
if(50 to 75)
if(prob(5))
if(!container)
to_chat(src, "<span class='danger'>You feel weak.</span>")
else
to_chat(src, "<span class='danger'>STATUS: DANGEROUS AMOUNTS OF RADIATION DETECTED.</span>")
..()
/mob/living/carbon/brain/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity)
if(status_flags & GODMODE)
return
if(exposed_temperature > bodytemperature)
var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
adjustFireLoss(20.0*discomfort)
else
var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
adjustFireLoss(5.0*discomfort)
/mob/living/carbon/brain/handle_regular_status_updates()
. = ..()
if(.)
if(!container && (health < HEALTH_THRESHOLD_DEAD && check_death_method() || ((world.time - timeofhostdeath) > config.revival_brain_life)))
death()
return 0
/mob/living/carbon/brain/breathe()
return
/mob/living/carbon/brain/handle_mutations_and_radiation()
if(radiation)
if(radiation > 100)
if(!container)
to_chat(src, "<span class='danger'>You feel weak.</span>")
else
to_chat(src, "<span class='danger'>STATUS: CRITICAL AMOUNTS OF RADIATION DETECTED.</span>")
switch(radiation)
if(50 to 75)
if(prob(5))
if(!container)
to_chat(src, "<span class='danger'>You feel weak.</span>")
else
to_chat(src, "<span class='danger'>STATUS: DANGEROUS AMOUNTS OF RADIATION DETECTED.</span>")
..()
/mob/living/carbon/brain/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity)
if(status_flags & GODMODE)
return
if(exposed_temperature > bodytemperature)
var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
adjustFireLoss(20.0*discomfort)
else
var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
adjustFireLoss(5.0*discomfort)
/mob/living/carbon/brain/handle_regular_status_updates()
. = ..()
if(.)
if(!container && (health < HEALTH_THRESHOLD_DEAD && check_death_method() || ((world.time - timeofhostdeath) > config.revival_brain_life)))
death()
return 0
/mob/living/carbon/brain/breathe()
return
@@ -1,3 +1,3 @@
/mob/living/carbon/brain/Login()
..()
SetSleeping(0)
/mob/living/carbon/brain/Login()
..()
SetSleeping(0)
+50 -50
View File
@@ -1,50 +1,50 @@
//TODO: Convert this over for languages.
/mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null)
if(!can_speak(warning = TRUE))
return
if(prob(emp_damage * 4))
if(prob(10)) //10% chance to drop the message entirely
return
else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
..(message)
/mob/living/carbon/brain/whisper(message as text)
if(!can_speak(warning = TRUE))
return
..()
/mob/living/carbon/brain/can_speak(var/warning = FALSE)
. = ..()
if(!istype(container, /obj/item/mmi))
. = FALSE
else if(istype(container, /obj/item/mmi/robotic_brain))
var/obj/item/mmi/robotic_brain/R = container
if(R && R.silenced)
if(warning)
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, 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
// I'm doing it this way so that if the mecha radio fails for some reason, a radio MMI still has the built-in fallback
if(container && istype(container,/obj/item/mmi))
var/obj/item/mmi/c = container
if(!radio_worked && c.mecha)
var/obj/mecha/metalgear = c.mecha
if(metalgear.radio)
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_pieces, message_mode, verb)
return radio_worked
if("whisper")
whisper_say(message_pieces)
return 1
else return 0
//TODO: Convert this over for languages.
/mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null)
if(!can_speak(warning = TRUE))
return
if(prob(emp_damage * 4))
if(prob(10)) //10% chance to drop the message entirely
return
else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
..(message)
/mob/living/carbon/brain/whisper(message as text)
if(!can_speak(warning = TRUE))
return
..()
/mob/living/carbon/brain/can_speak(var/warning = FALSE)
. = ..()
if(!istype(container, /obj/item/mmi))
. = FALSE
else if(istype(container, /obj/item/mmi/robotic_brain))
var/obj/item/mmi/robotic_brain/R = container
if(R && R.silenced)
if(warning)
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, 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
// I'm doing it this way so that if the mecha radio fails for some reason, a radio MMI still has the built-in fallback
if(container && istype(container,/obj/item/mmi))
var/obj/item/mmi/c = container
if(!radio_worked && c.mecha)
var/obj/mecha/metalgear = c.mecha
if(metalgear.radio)
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_pieces, message_mode, verb)
return radio_worked
if("whisper")
whisper_say(message_pieces)
return 1
else return 0
+1 -1
View File
@@ -1192,4 +1192,4 @@ so that different stomachs can handle things in different ways VB*/
var/obj/item/I = X
I.acid_level = 0 //washes off the acid on our clothes
I.extinguish() //extinguishes our clothes
..()
..()
@@ -1,30 +1,30 @@
/mob/living/carbon
gender = MALE
pressure_resistance = 15
var/list/stomach_contents = list()
var/list/internal_organs = list()
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
var/antibodies = 0
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed
var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this.
var/obj/item/head = null
var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn
var/mob/living/simple_animal/borer/borer = null
//Active emote/pose
var/pose = null
var/pulse = PULSE_NORM //current pulse level
var/wetlevel = 0 //how wet the mob is
var/co2overloadtime = null
var/dreaming = 0 //How many dream images we have left to send
var/nightmare = 0
blood_volume = BLOOD_VOLUME_NORMAL
/mob/living/carbon
gender = MALE
pressure_resistance = 15
var/list/stomach_contents = list()
var/list/internal_organs = list()
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
var/antibodies = 0
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed
var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this.
var/obj/item/head = null
var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn
var/mob/living/simple_animal/borer/borer = null
//Active emote/pose
var/pose = null
var/pulse = PULSE_NORM //current pulse level
var/wetlevel = 0 //how wet the mob is
var/co2overloadtime = null
var/dreaming = 0 //How many dream images we have left to send
var/nightmare = 0
blood_volume = BLOOD_VOLUME_NORMAL
+195 -195
View File
@@ -1,195 +1,195 @@
/mob/living/carbon/human/gib()
if(!death(TRUE) && stat != DEAD)
return FALSE
var/atom/movable/overlay/animation = null
notransform = 1
canmove = 0
icon = null
invisibility = 101
if(!isSynthetic())
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
playsound(src.loc, 'sound/goonstation/effects/gib.ogg', 50, 1)
else
playsound(src.loc, 'sound/goonstation/effects/robogib.ogg', 50, 1)
for(var/obj/item/organ/internal/I in internal_organs)
if(isturf(loc))
var/atom/movable/thing = I.remove(src)
if(thing)
thing.forceMove(get_turf(src))
thing.throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), 5)
for(var/obj/item/organ/external/E in bodyparts)
if(istype(E, /obj/item/organ/external/chest))
continue
// Only make the limb drop if it's not too damaged
if(prob(100 - E.get_damage()))
// Override the current limb status and don't cause an explosion
E.droplimb(DROPLIMB_SHARP)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(get_turf(src))
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
if(!isSynthetic())
flick("gibbed-h", animation)
hgibs(loc, dna)
else
new /obj/effect/decal/cleanable/blood/gibs/robot(loc)
do_sparks(3, 1, src)
QDEL_IN(animation, 15)
QDEL_IN(src, 0)
return TRUE
/mob/living/carbon/human/dust()
if(!death(TRUE) && stat != DEAD)
return FALSE
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"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("dust-h", animation)
new dna.species.remains_type(get_turf(src))
QDEL_IN(animation, 15)
return TRUE
/mob/living/carbon/human/melt()
if(!death(TRUE) && stat != DEAD)
return FALSE
var/atom/movable/overlay/animation = null
notransform = 1
canmove = 0
icon = null
invisibility = 101
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("liquify", animation)
QDEL_IN(src, 0)
QDEL_IN(animation, 15)
//new /obj/effect/decal/remains/human(loc)
return TRUE
/mob/living/carbon/human/death(gibbed)
if(can_die() && !gibbed && deathgasp_on_death)
emote("deathgasp", force = TRUE) //let the world KNOW WE ARE DEAD
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
set_heartattack(FALSE)
SSmobs.cubemonkeys -= src
if(dna.species)
dna.species.handle_hud_icons(src)
//Handle species-specific deaths.
dna.species.handle_death(gibbed, src)
if(ishuman(LAssailant))
var/mob/living/carbon/human/H=LAssailant
if(H.mind)
H.mind.kills += "[key_name(src)]"
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
if(wearing_rig)
wearing_rig.notify_ai("<span class='danger'>Warning: user death event. Mobility control passed to integrated intelligence system.</span>")
/mob/living/carbon/human/update_revive()
. = ..()
if(. && healthdoll)
// We're alive again, so re-build the entire healthdoll
healthdoll.cached_healthdoll_overlays.Cut()
// Update healthdoll
if(dna.species)
dna.species.update_sight(src)
dna.species.handle_hud_icons(src)
/mob/living/carbon/human/proc/makeSkeleton()
var/obj/item/organ/external/head/H = get_organ("head")
if(SKELETON in src.mutations)
return
if(istype(H))
H.disfigured = TRUE
if(H.f_style)
H.f_style = initial(H.f_style)
if(H.h_style)
H.h_style = initial(H.h_style)
if(H.ha_style)
H.ha_style = initial(H.ha_style)
if(H.alt_head)
H.alt_head = initial(H.alt_head)
H.handle_alt_icon()
m_styles = DEFAULT_MARKING_STYLES
update_fhair(0)
update_hair(0)
update_head_accessory(0)
update_markings(0)
mutations.Add(SKELETON)
mutations.Add(NOCLONE)
update_body(0)
update_mutantrace()
return
/mob/living/carbon/human/proc/ChangeToHusk()
// If the target has no DNA to begin with, its DNA can't be damaged beyond repair.
if(NO_DNA in dna.species.species_traits)
return
if(HUSK in mutations)
return
var/obj/item/organ/external/head/H = bodyparts_by_name["head"]
if(istype(H))
H.disfigured = TRUE //makes them unknown without fucking up other stuff like admintools
if(H.f_style)
H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE
if(H.h_style)
H.h_style = "Bald"
update_fhair(0)
update_hair(0)
mutations.Add(HUSK)
update_body(0)
update_mutantrace()
return
/mob/living/carbon/human/proc/Drain()
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
/mob/living/carbon/human/gib()
if(!death(TRUE) && stat != DEAD)
return FALSE
var/atom/movable/overlay/animation = null
notransform = 1
canmove = 0
icon = null
invisibility = 101
if(!isSynthetic())
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
playsound(src.loc, 'sound/goonstation/effects/gib.ogg', 50, 1)
else
playsound(src.loc, 'sound/goonstation/effects/robogib.ogg', 50, 1)
for(var/obj/item/organ/internal/I in internal_organs)
if(isturf(loc))
var/atom/movable/thing = I.remove(src)
if(thing)
thing.forceMove(get_turf(src))
thing.throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), 5)
for(var/obj/item/organ/external/E in bodyparts)
if(istype(E, /obj/item/organ/external/chest))
continue
// Only make the limb drop if it's not too damaged
if(prob(100 - E.get_damage()))
// Override the current limb status and don't cause an explosion
E.droplimb(DROPLIMB_SHARP)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(get_turf(src))
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
if(!isSynthetic())
flick("gibbed-h", animation)
hgibs(loc, dna)
else
new /obj/effect/decal/cleanable/blood/gibs/robot(loc)
do_sparks(3, 1, src)
QDEL_IN(animation, 15)
QDEL_IN(src, 0)
return TRUE
/mob/living/carbon/human/dust()
if(!death(TRUE) && stat != DEAD)
return FALSE
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"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("dust-h", animation)
new dna.species.remains_type(get_turf(src))
QDEL_IN(animation, 15)
return TRUE
/mob/living/carbon/human/melt()
if(!death(TRUE) && stat != DEAD)
return FALSE
var/atom/movable/overlay/animation = null
notransform = 1
canmove = 0
icon = null
invisibility = 101
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = src
flick("liquify", animation)
QDEL_IN(src, 0)
QDEL_IN(animation, 15)
//new /obj/effect/decal/remains/human(loc)
return TRUE
/mob/living/carbon/human/death(gibbed)
if(can_die() && !gibbed && deathgasp_on_death)
emote("deathgasp", force = TRUE) //let the world KNOW WE ARE DEAD
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
set_heartattack(FALSE)
SSmobs.cubemonkeys -= src
if(dna.species)
dna.species.handle_hud_icons(src)
//Handle species-specific deaths.
dna.species.handle_death(gibbed, src)
if(ishuman(LAssailant))
var/mob/living/carbon/human/H=LAssailant
if(H.mind)
H.mind.kills += "[key_name(src)]"
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
if(wearing_rig)
wearing_rig.notify_ai("<span class='danger'>Warning: user death event. Mobility control passed to integrated intelligence system.</span>")
/mob/living/carbon/human/update_revive()
. = ..()
if(. && healthdoll)
// We're alive again, so re-build the entire healthdoll
healthdoll.cached_healthdoll_overlays.Cut()
// Update healthdoll
if(dna.species)
dna.species.update_sight(src)
dna.species.handle_hud_icons(src)
/mob/living/carbon/human/proc/makeSkeleton()
var/obj/item/organ/external/head/H = get_organ("head")
if(SKELETON in src.mutations)
return
if(istype(H))
H.disfigured = TRUE
if(H.f_style)
H.f_style = initial(H.f_style)
if(H.h_style)
H.h_style = initial(H.h_style)
if(H.ha_style)
H.ha_style = initial(H.ha_style)
if(H.alt_head)
H.alt_head = initial(H.alt_head)
H.handle_alt_icon()
m_styles = DEFAULT_MARKING_STYLES
update_fhair(0)
update_hair(0)
update_head_accessory(0)
update_markings(0)
mutations.Add(SKELETON)
mutations.Add(NOCLONE)
update_body(0)
update_mutantrace()
return
/mob/living/carbon/human/proc/ChangeToHusk()
// If the target has no DNA to begin with, its DNA can't be damaged beyond repair.
if(NO_DNA in dna.species.species_traits)
return
if(HUSK in mutations)
return
var/obj/item/organ/external/head/H = bodyparts_by_name["head"]
if(istype(H))
H.disfigured = TRUE //makes them unknown without fucking up other stuff like admintools
if(H.f_style)
H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE
if(H.h_style)
H.h_style = "Bald"
update_fhair(0)
update_hair(0)
mutations.Add(HUSK)
update_body(0)
update_mutantrace()
return
/mob/living/carbon/human/proc/Drain()
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
+434 -434
View File
@@ -1,434 +1,434 @@
/mob/living/carbon/human/examine(mob/user)
var/skipgloves = 0
var/skipsuitstorage = 0
var/skipjumpsuit = 0
var/skipshoes = 0
var/skipmask = 0
var/skipears = 0
var/skipeyes = 0
var/skipface = 0
//exosuits and helmets obscure our view and stuff.
if(wear_suit)
skipgloves = wear_suit.flags_inv & HIDEGLOVES
skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE
skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT
skipshoes = wear_suit.flags_inv & HIDESHOES
if(head)
skipmask = head.flags_inv & HIDEMASK
skipeyes = head.flags_inv & HIDEEYES
skipears = head.flags_inv & HIDEEARS
skipface = head.flags_inv & HIDEFACE
if(wear_mask)
skipface |= wear_mask.flags_inv & HIDEFACE
var/msg = "<span class='info'>*---------*\nThis is "
if(!(skipjumpsuit && skipface) && icon) //big suits/masks/helmets make it hard to tell their gender
msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated
msg += "<EM>[name]</EM>"
var/displayed_species = dna.species.name
var/examine_color = dna.species.flesh_color
for(var/obj/item/clothing/C in src) //Disguise checks
if(C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back)
if(C.species_disguise)
displayed_species = C.species_disguise
if(skipjumpsuit && skipface || (NO_EXAMINE in dna.species.species_traits)) //either obscured or on the nospecies list
msg += "!\n" //omit the species when examining
else if(displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural
msg += ", a<b><font color='[examine_color]'> slime person</font></b>!\n"
else if(displayed_species == "Unathi") //DAMN YOU, VOWELS
msg += ", a<b><font color='[examine_color]'> unathi</font></b>!\n"
else
msg += ", a<b><font color='[examine_color]'> [lowertext(displayed_species)]</font></b>!\n"
//uniform
if(w_uniform && !skipjumpsuit && !(w_uniform.flags & ABSTRACT))
//Ties
var/tie_msg
if(istype(w_uniform,/obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.accessories.len)
tie_msg += " with [english_accessory_list(U)]"
if(w_uniform.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.blood_color != "#030303" ? "blood-stained":"oil-stained"] [w_uniform.name][tie_msg]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n"
//head
if(head && !(head.flags & ABSTRACT))
if(head.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [p_their()] head!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(head)] \a [head] on [p_their()] head.\n"
//suit/armour
if(wear_suit && !(wear_suit.flags & ABSTRACT))
if(wear_suit.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] \a [wear_suit].\n"
//suit/armour storage
if(s_store && !skipsuitstorage)
if(s_store.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.blood_color != "#030303" ? "blood-stained":"oil-stained"] [s_store.name] on [p_their()] [wear_suit.name]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] \a [s_store] on [p_their()] [wear_suit.name].\n"
//back
if(back && !(back.flags & ABSTRACT))
if(back.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [p_their()] back.</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(back)] \a [back] on [p_their()] back.\n"
//left hand
if(l_hand && !(l_hand.flags & ABSTRACT))
if(l_hand.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [l_hand.name] in [p_their()] left hand!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] \a [l_hand] in [p_their()] left hand.\n"
//right hand
if(r_hand && !(r_hand.flags & ABSTRACT))
if(r_hand.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [r_hand.name] in [p_their()] right hand!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] \a [r_hand] in [p_their()] right hand.\n"
//gloves
if(gloves && !skipgloves && !(gloves.flags & ABSTRACT))
if(gloves.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [p_their()] hands!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(gloves)] \a [gloves] on [p_their()] hands.\n"
else if(blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [hand_blood_color != "#030303" ? "blood-stained":"oil-stained"] hands!</span>\n"
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/restraints/handcuffs/cable/zipties))
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with zipties!</span>\n"
else if(istype(handcuffed, /obj/item/restraints/handcuffs/cable))
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with cable!</span>\n"
else
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] handcuffed!</span>\n"
//belt
if(belt)
if(belt.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.blood_color != "#030303" ? "blood-stained":"oil-stained"] [belt.name] about [p_their()] waist!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(belt)] \a [belt] about [p_their()] waist.\n"
//shoes
if(shoes && !skipshoes && !(shoes.flags & ABSTRACT))
if(shoes.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [p_their()] feet!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] \a [shoes] on [p_their()] feet.\n"
else if(blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [feet_blood_color != "#030303" ? "blood-stained":"oil-stained"] feet!</span>\n"
//mask
if(wear_mask && !skipmask && !(wear_mask.flags & ABSTRACT))
if(wear_mask.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [p_their()] face!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(wear_mask)] \a [wear_mask] on [p_their()] face.\n"
//eyes
if(glasses && !skipeyes && !(glasses.flags & ABSTRACT))
if(glasses.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [p_their()] eyes!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(glasses)] \a [glasses] covering [p_their()] eyes.\n"
//left ear
if(l_ear && !skipears)
msg += "[p_they(TRUE)] [p_have()] [bicon(l_ear)] \a [l_ear] on [p_their()] left ear.\n"
//right ear
if(r_ear && !skipears)
msg += "[p_they(TRUE)] [p_have()] [bicon(r_ear)] \a [r_ear] on [p_their()] right ear.\n"
//ID
if(wear_id)
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_id)] \a [wear_id].\n"
//Jitters
switch(jitteriness)
if(300 to INFINITY)
msg += "<span class='warning'><B>[p_they(TRUE)] [p_are()] convulsing violently!</B></span>\n"
if(200 to 300)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] extremely jittery.</span>\n"
if(100 to 200)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] twitching ever so slightly.</span>\n"
var/appears_dead = FALSE
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = TRUE
if(suiciding)
msg += "<span class='warning'>[p_they(TRUE)] appear[p_s()] to have committed suicide... there is no hope of recovery.</span>\n"
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] limp and unresponsive; there are no signs of life"
if(get_int_organ(/obj/item/organ/internal/brain))
if(!key)
var/foundghost = FALSE
if(mind)
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.mind == mind)
foundghost = TRUE
if(G.can_reenter_corpse == 0)
foundghost = FALSE
break
if(!foundghost)
msg += " and [p_their()] soul has departed"
msg += "...</span>\n"
if(!get_int_organ(/obj/item/organ/internal/brain))
msg += "<span class='deadsay'>It appears that [p_their()] brain is missing...</span>\n"
msg += "<span class='warning'>"
var/list/wound_flavor_text = list()
var/list/is_destroyed = list()
for(var/organ_tag in dna.species.has_limbs)
var/list/organ_data = dna.species.has_limbs[organ_tag]
var/organ_descriptor = organ_data["descriptor"]
is_destroyed["[organ_data["descriptor"]]"] = 1
var/obj/item/organ/external/E = bodyparts_by_name[organ_tag]
if(!E)
wound_flavor_text["[organ_tag]"] = "<B>[p_they(TRUE)] [p_are()] missing [p_their()] [organ_descriptor].</B>\n"
else
if(!isSynthetic())
if(E.is_robotic())
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a robotic [E.name]!\n"
else if(E.status & ORGAN_SPLINTED)
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a splint on [p_their()] [E.name]!\n"
if(E.open)
if(E.is_robotic())
msg += "<b>The maintenance hatch on [p_their()] [ignore_limb_branding(E.limb_name)] is open!</b>\n"
else
msg += "<b>[p_their(TRUE)] [ignore_limb_branding(E.limb_name)] has an open incision!</b>\n"
for(var/obj/item/I in E.embedded_objects)
msg += "<B>[p_they(TRUE)] [p_have()] \a [bicon(I)] [I] embedded in [p_their()] [E.name]!</B>\n"
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas)))))
msg += wound_flavor_text["head"]
if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you.
msg += wound_flavor_text["chest"]
if(wound_flavor_text["l_arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["l_arm"]
if(wound_flavor_text["l_hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["l_hand"]
if(wound_flavor_text["r_arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["r_arm"]
if(wound_flavor_text["r_hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["r_hand"]
if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["groin"]
if(wound_flavor_text["l_leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["l_leg"]
if(wound_flavor_text["l_foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["l_foot"]
if(wound_flavor_text["r_leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["r_leg"]
if(wound_flavor_text["r_foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["r_foot"]
var/temp = getBruteLoss() //no need to calculate each of these twice
if(temp)
var/brute_message = !isSynthetic() ? "bruising" : "denting"
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor [brute_message ].\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe [brute_message ]!</B>\n"
temp = getFireLoss()
if(temp)
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor burns.\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor cellular damage.\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe cellular damage.</B>\n"
if(fire_stacks > 0)
msg += "[p_they(TRUE)] [p_are()] covered in something flammable.\n"
if(fire_stacks < 0)
msg += "[p_they(TRUE)] looks a little soaked.\n"
switch(wetlevel)
if(1)
msg += "[p_they(TRUE)] looks a bit damp.\n"
if(2)
msg += "[p_they(TRUE)] looks a little bit wet.\n"
if(3)
msg += "[p_they(TRUE)] looks wet.\n"
if(4)
msg += "[p_they(TRUE)] looks very wet.\n"
if(5)
msg += "[p_they(TRUE)] looks absolutely soaked.\n"
if(nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[p_they(TRUE)] [p_are()] severely malnourished.\n"
else if(nutrition >= NUTRITION_LEVEL_FAT)
if(user.nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[p_they(TRUE)] [p_are()] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[p_they(TRUE)] [p_are()] quite chubby.\n"
if(!isSynthetic() && blood_volume < BLOOD_VOLUME_SAFE)
msg += "[p_they(TRUE)] [p_have()] pale skin.\n"
if(bleedsuppress)
msg += "[p_they(TRUE)] [p_are()] bandaged with something.\n"
else if(bleed_rate)
var/bleed_message = !isSynthetic() ? "bleeding" : "leaking"
msg += "<B>[p_they(TRUE)] [p_are()] [bleed_message]!</B>\n"
if(reagents.has_reagent("teslium"))
msg += "[p_they(TRUE)] [p_are()] emitting a gentle blue glow!\n"
msg += "</span>"
if(!appears_dead)
if(stat == UNCONSCIOUS)
msg += "[p_they(TRUE)] [p_are()]n't responding to anything around [p_them()] and seems to be asleep.\n"
else if(getBrainLoss() >= 60)
msg += "[p_they(TRUE)] [p_have()] a stupid expression on [p_their()] face.\n"
if(get_int_organ(/obj/item/organ/internal/brain))
if(dna.species.show_ssd)
if(!key)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] totally catatonic. The stresses of life in deep-space must have been too much for [p_them()]. Any recovery is unlikely.</span>\n"
else if(!client)
msg += "[p_they(TRUE)] [p_have()] suddenly fallen asleep, suffering from Space Sleep Disorder. [p_they(TRUE)] may wake up soon.\n"
if(digitalcamo)
msg += "[p_they(TRUE)] [p_are()] moving [p_their()] body in an unnatural and blatantly inhuman manner.\n"
if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src))
msg += "Their features seem unnaturally tight and drawn.\n"
if(decaylevel == 1)
msg += "[p_they(TRUE)] [p_are()] starting to smell.\n"
if(decaylevel == 2)
msg += "[p_they(TRUE)] [p_are()] bloated and smells disgusting.\n"
if(decaylevel == 3)
msg += "[p_they(TRUE)] [p_are()] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n"
if(decaylevel == 4)
msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n"
if(hasHUD(user,"security"))
var/perpname = get_visible_name(TRUE)
var/criminal = "None"
if(perpname)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
if(R.fields["id"] == E.fields["id"])
criminal = R.fields["criminal"]
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"))
var/perpname = get_visible_name(TRUE)
var/medical = "None"
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.general)
if(R.fields["id"] == E.fields["id"])
medical = R.fields["p_stat"]
msg += "<span class = 'deptradio'>Physical status:</span> <a href='?src=[UID()];medical=1'>\[[medical]\]</a>\n"
msg += "<span class = 'deptradio'>Medical records:</span> <a href='?src=[UID()];medrecord=`'>\[View\]</a> <a href='?src=[UID()];medrecordadd=`'>\[Add comment\]</a>\n"
if(print_flavor_text() && !skipface)
msg += "[print_flavor_text()]\n"
msg += "*---------*</span>"
if(pose)
if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 )
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "\n[p_they(TRUE)] [p_are()] [pose]"
. = list(msg)
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
/proc/hasHUD(mob/M as mob, hudtype)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
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(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(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical)
else
return 0
else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system
switch(hudtype)
if("security")
return 1
if("medical")
return 1
else
return 0
else
return 0
// Ignores robotic limb branding prefixes like "Morpheus Cybernetics"
/proc/ignore_limb_branding(limb_name)
switch(limb_name)
if("chest")
. = "upper body"
if("groin")
. = "lower body"
if("head")
. = "head"
if("l_arm")
. = "left arm"
if("r_arm")
. = "right arm"
if("l_leg")
. = "left leg"
if("r_leg")
. = "right leg"
if("l_foot")
. = "left foot"
if("r_foot")
. = "right foot"
if("l_hand")
. = "left hand"
if("r_hand")
. = "right hand"
/mob/living/carbon/human/examine(mob/user)
var/skipgloves = 0
var/skipsuitstorage = 0
var/skipjumpsuit = 0
var/skipshoes = 0
var/skipmask = 0
var/skipears = 0
var/skipeyes = 0
var/skipface = 0
//exosuits and helmets obscure our view and stuff.
if(wear_suit)
skipgloves = wear_suit.flags_inv & HIDEGLOVES
skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE
skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT
skipshoes = wear_suit.flags_inv & HIDESHOES
if(head)
skipmask = head.flags_inv & HIDEMASK
skipeyes = head.flags_inv & HIDEEYES
skipears = head.flags_inv & HIDEEARS
skipface = head.flags_inv & HIDEFACE
if(wear_mask)
skipface |= wear_mask.flags_inv & HIDEFACE
var/msg = "<span class='info'>*---------*\nThis is "
if(!(skipjumpsuit && skipface) && icon) //big suits/masks/helmets make it hard to tell their gender
msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated
msg += "<EM>[name]</EM>"
var/displayed_species = dna.species.name
var/examine_color = dna.species.flesh_color
for(var/obj/item/clothing/C in src) //Disguise checks
if(C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back)
if(C.species_disguise)
displayed_species = C.species_disguise
if(skipjumpsuit && skipface || (NO_EXAMINE in dna.species.species_traits)) //either obscured or on the nospecies list
msg += "!\n" //omit the species when examining
else if(displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural
msg += ", a<b><font color='[examine_color]'> slime person</font></b>!\n"
else if(displayed_species == "Unathi") //DAMN YOU, VOWELS
msg += ", a<b><font color='[examine_color]'> unathi</font></b>!\n"
else
msg += ", a<b><font color='[examine_color]'> [lowertext(displayed_species)]</font></b>!\n"
//uniform
if(w_uniform && !skipjumpsuit && !(w_uniform.flags & ABSTRACT))
//Ties
var/tie_msg
if(istype(w_uniform,/obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.accessories.len)
tie_msg += " with [english_accessory_list(U)]"
if(w_uniform.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.blood_color != "#030303" ? "blood-stained":"oil-stained"] [w_uniform.name][tie_msg]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n"
//head
if(head && !(head.flags & ABSTRACT))
if(head.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [p_their()] head!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(head)] \a [head] on [p_their()] head.\n"
//suit/armour
if(wear_suit && !(wear_suit.flags & ABSTRACT))
if(wear_suit.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_suit)] \a [wear_suit].\n"
//suit/armour storage
if(s_store && !skipsuitstorage)
if(s_store.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.blood_color != "#030303" ? "blood-stained":"oil-stained"] [s_store.name] on [p_their()] [wear_suit.name]!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] carrying [bicon(s_store)] \a [s_store] on [p_their()] [wear_suit.name].\n"
//back
if(back && !(back.flags & ABSTRACT))
if(back.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [p_their()] back.</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(back)] \a [back] on [p_their()] back.\n"
//left hand
if(l_hand && !(l_hand.flags & ABSTRACT))
if(l_hand.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [l_hand.name] in [p_their()] left hand!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] holding [bicon(l_hand)] \a [l_hand] in [p_their()] left hand.\n"
//right hand
if(r_hand && !(r_hand.flags & ABSTRACT))
if(r_hand.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.blood_color != "#030303" ? "blood-stained":"oil-stained"] [r_hand.name] in [p_their()] right hand!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] holding [bicon(r_hand)] \a [r_hand] in [p_their()] right hand.\n"
//gloves
if(gloves && !skipgloves && !(gloves.flags & ABSTRACT))
if(gloves.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [p_their()] hands!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(gloves)] \a [gloves] on [p_their()] hands.\n"
else if(blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [hand_blood_color != "#030303" ? "blood-stained":"oil-stained"] hands!</span>\n"
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/restraints/handcuffs/cable/zipties))
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with zipties!</span>\n"
else if(istype(handcuffed, /obj/item/restraints/handcuffs/cable))
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] restrained with cable!</span>\n"
else
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] [bicon(handcuffed)] handcuffed!</span>\n"
//belt
if(belt)
if(belt.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.blood_color != "#030303" ? "blood-stained":"oil-stained"] [belt.name] about [p_their()] waist!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(belt)] \a [belt] about [p_their()] waist.\n"
//shoes
if(shoes && !skipshoes && !(shoes.flags & ABSTRACT))
if(shoes.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [p_their()] feet!</span>\n"
else
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(shoes)] \a [shoes] on [p_their()] feet.\n"
else if(blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [feet_blood_color != "#030303" ? "blood-stained":"oil-stained"] feet!</span>\n"
//mask
if(wear_mask && !skipmask && !(wear_mask.flags & ABSTRACT))
if(wear_mask.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [p_their()] face!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(wear_mask)] \a [wear_mask] on [p_their()] face.\n"
//eyes
if(glasses && !skipeyes && !(glasses.flags & ABSTRACT))
if(glasses.blood_DNA)
msg += "<span class='warning'>[p_they(TRUE)] [p_have()] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [p_their()] eyes!</span>\n"
else
msg += "[p_they(TRUE)] [p_have()] [bicon(glasses)] \a [glasses] covering [p_their()] eyes.\n"
//left ear
if(l_ear && !skipears)
msg += "[p_they(TRUE)] [p_have()] [bicon(l_ear)] \a [l_ear] on [p_their()] left ear.\n"
//right ear
if(r_ear && !skipears)
msg += "[p_they(TRUE)] [p_have()] [bicon(r_ear)] \a [r_ear] on [p_their()] right ear.\n"
//ID
if(wear_id)
msg += "[p_they(TRUE)] [p_are()] wearing [bicon(wear_id)] \a [wear_id].\n"
//Jitters
switch(jitteriness)
if(300 to INFINITY)
msg += "<span class='warning'><B>[p_they(TRUE)] [p_are()] convulsing violently!</B></span>\n"
if(200 to 300)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] extremely jittery.</span>\n"
if(100 to 200)
msg += "<span class='warning'>[p_they(TRUE)] [p_are()] twitching ever so slightly.</span>\n"
var/appears_dead = FALSE
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = TRUE
if(suiciding)
msg += "<span class='warning'>[p_they(TRUE)] appear[p_s()] to have committed suicide... there is no hope of recovery.</span>\n"
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] limp and unresponsive; there are no signs of life"
if(get_int_organ(/obj/item/organ/internal/brain))
if(!key)
var/foundghost = FALSE
if(mind)
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.mind == mind)
foundghost = TRUE
if(G.can_reenter_corpse == 0)
foundghost = FALSE
break
if(!foundghost)
msg += " and [p_their()] soul has departed"
msg += "...</span>\n"
if(!get_int_organ(/obj/item/organ/internal/brain))
msg += "<span class='deadsay'>It appears that [p_their()] brain is missing...</span>\n"
msg += "<span class='warning'>"
var/list/wound_flavor_text = list()
var/list/is_destroyed = list()
for(var/organ_tag in dna.species.has_limbs)
var/list/organ_data = dna.species.has_limbs[organ_tag]
var/organ_descriptor = organ_data["descriptor"]
is_destroyed["[organ_data["descriptor"]]"] = 1
var/obj/item/organ/external/E = bodyparts_by_name[organ_tag]
if(!E)
wound_flavor_text["[organ_tag]"] = "<B>[p_they(TRUE)] [p_are()] missing [p_their()] [organ_descriptor].</B>\n"
else
if(!isSynthetic())
if(E.is_robotic())
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a robotic [E.name]!\n"
else if(E.status & ORGAN_SPLINTED)
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a splint on [p_their()] [E.name]!\n"
if(E.open)
if(E.is_robotic())
msg += "<b>The maintenance hatch on [p_their()] [ignore_limb_branding(E.limb_name)] is open!</b>\n"
else
msg += "<b>[p_their(TRUE)] [ignore_limb_branding(E.limb_name)] has an open incision!</b>\n"
for(var/obj/item/I in E.embedded_objects)
msg += "<B>[p_they(TRUE)] [p_have()] \a [bicon(I)] [I] embedded in [p_their()] [E.name]!</B>\n"
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas)))))
msg += wound_flavor_text["head"]
if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you.
msg += wound_flavor_text["chest"]
if(wound_flavor_text["l_arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["l_arm"]
if(wound_flavor_text["l_hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["l_hand"]
if(wound_flavor_text["r_arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["r_arm"]
if(wound_flavor_text["r_hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves)))
msg += wound_flavor_text["r_hand"]
if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["groin"]
if(wound_flavor_text["l_leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["l_leg"]
if(wound_flavor_text["l_foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["l_foot"]
if(wound_flavor_text["r_leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit)))
msg += wound_flavor_text["r_leg"]
if(wound_flavor_text["r_foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes)))
msg += wound_flavor_text["r_foot"]
var/temp = getBruteLoss() //no need to calculate each of these twice
if(temp)
var/brute_message = !isSynthetic() ? "bruising" : "denting"
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor [brute_message ].\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe [brute_message ]!</B>\n"
temp = getFireLoss()
if(temp)
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor burns.\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor cellular damage.\n"
else
msg += "<B>[p_they(TRUE)] [p_have()] severe cellular damage.</B>\n"
if(fire_stacks > 0)
msg += "[p_they(TRUE)] [p_are()] covered in something flammable.\n"
if(fire_stacks < 0)
msg += "[p_they(TRUE)] looks a little soaked.\n"
switch(wetlevel)
if(1)
msg += "[p_they(TRUE)] looks a bit damp.\n"
if(2)
msg += "[p_they(TRUE)] looks a little bit wet.\n"
if(3)
msg += "[p_they(TRUE)] looks wet.\n"
if(4)
msg += "[p_they(TRUE)] looks very wet.\n"
if(5)
msg += "[p_they(TRUE)] looks absolutely soaked.\n"
if(nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[p_they(TRUE)] [p_are()] severely malnourished.\n"
else if(nutrition >= NUTRITION_LEVEL_FAT)
if(user.nutrition < NUTRITION_LEVEL_STARVING - 50)
msg += "[p_they(TRUE)] [p_are()] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[p_they(TRUE)] [p_are()] quite chubby.\n"
if(!isSynthetic() && blood_volume < BLOOD_VOLUME_SAFE)
msg += "[p_they(TRUE)] [p_have()] pale skin.\n"
if(bleedsuppress)
msg += "[p_they(TRUE)] [p_are()] bandaged with something.\n"
else if(bleed_rate)
var/bleed_message = !isSynthetic() ? "bleeding" : "leaking"
msg += "<B>[p_they(TRUE)] [p_are()] [bleed_message]!</B>\n"
if(reagents.has_reagent("teslium"))
msg += "[p_they(TRUE)] [p_are()] emitting a gentle blue glow!\n"
msg += "</span>"
if(!appears_dead)
if(stat == UNCONSCIOUS)
msg += "[p_they(TRUE)] [p_are()]n't responding to anything around [p_them()] and seems to be asleep.\n"
else if(getBrainLoss() >= 60)
msg += "[p_they(TRUE)] [p_have()] a stupid expression on [p_their()] face.\n"
if(get_int_organ(/obj/item/organ/internal/brain))
if(dna.species.show_ssd)
if(!key)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] totally catatonic. The stresses of life in deep-space must have been too much for [p_them()]. Any recovery is unlikely.</span>\n"
else if(!client)
msg += "[p_they(TRUE)] [p_have()] suddenly fallen asleep, suffering from Space Sleep Disorder. [p_they(TRUE)] may wake up soon.\n"
if(digitalcamo)
msg += "[p_they(TRUE)] [p_are()] moving [p_their()] body in an unnatural and blatantly inhuman manner.\n"
if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src))
msg += "Their features seem unnaturally tight and drawn.\n"
if(decaylevel == 1)
msg += "[p_they(TRUE)] [p_are()] starting to smell.\n"
if(decaylevel == 2)
msg += "[p_they(TRUE)] [p_are()] bloated and smells disgusting.\n"
if(decaylevel == 3)
msg += "[p_they(TRUE)] [p_are()] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n"
if(decaylevel == 4)
msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n"
if(hasHUD(user,"security"))
var/perpname = get_visible_name(TRUE)
var/criminal = "None"
if(perpname)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
if(R.fields["id"] == E.fields["id"])
criminal = R.fields["criminal"]
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"))
var/perpname = get_visible_name(TRUE)
var/medical = "None"
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.general)
if(R.fields["id"] == E.fields["id"])
medical = R.fields["p_stat"]
msg += "<span class = 'deptradio'>Physical status:</span> <a href='?src=[UID()];medical=1'>\[[medical]\]</a>\n"
msg += "<span class = 'deptradio'>Medical records:</span> <a href='?src=[UID()];medrecord=`'>\[View\]</a> <a href='?src=[UID()];medrecordadd=`'>\[Add comment\]</a>\n"
if(print_flavor_text() && !skipface)
msg += "[print_flavor_text()]\n"
msg += "*---------*</span>"
if(pose)
if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 )
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "\n[p_they(TRUE)] [p_are()] [pose]"
. = list(msg)
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
/proc/hasHUD(mob/M as mob, hudtype)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
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(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(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical)
else
return 0
else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system
switch(hudtype)
if("security")
return 1
if("medical")
return 1
else
return 0
else
return 0
// Ignores robotic limb branding prefixes like "Morpheus Cybernetics"
/proc/ignore_limb_branding(limb_name)
switch(limb_name)
if("chest")
. = "upper body"
if("groin")
. = "lower body"
if("head")
. = "head"
if("l_arm")
. = "left arm"
if("r_arm")
. = "right arm"
if("l_leg")
. = "left leg"
if("r_leg")
. = "right leg"
if("l_foot")
. = "left foot"
if("r_foot")
. = "right foot"
if("l_hand")
. = "left hand"
if("r_hand")
. = "right hand"
File diff suppressed because it is too large Load Diff
@@ -1,350 +1,350 @@
//Updates the mob's health from organs and mob damage variables
/mob/living/carbon/human/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = maxHealth
stat = CONSCIOUS
return
var/total_burn = 0
var/total_brute = 0
for(var/obj/item/organ/external/O in bodyparts) //hardcoded to streamline things a bit
total_brute += O.brute_dam //calculates health based on organ brute and burn
total_burn += O.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD)
ChangeToHusk()
update_stat("updatehealth([reason])")
med_hud_set_health()
med_hud_set_status()
handle_hud_icons_health()
/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE)
if(status_flags & GODMODE)
return STATUS_UPDATE_NONE //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(sponge.damage + amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("adjustBrainLoss")
return STATUS_UPDATE_STAT
/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE)
if(status_flags & GODMODE)
return STATUS_UPDATE_NONE //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("setBrainLoss")
return STATUS_UPDATE_STAT
/mob/living/carbon/human/getBrainLoss()
if(status_flags & GODMODE)
return 0 //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
return min(sponge.damage,maxHealth*2)
else
return 200
else
return 0
//These procs fetch a cumulative total damage from all organs
/mob/living/carbon/human/getBruteLoss()
var/amount = 0
for(var/obj/item/organ/external/O in bodyparts)
amount += O.brute_dam
return amount
/mob/living/carbon/human/getFireLoss()
var/amount = 0
for(var/obj/item/organ/external/O in bodyparts)
amount += O.burn_dam
return amount
/mob/living/carbon/human/adjustBruteLoss(amount, updating_health = TRUE, damage_source = null, robotic = FALSE)
if(amount > 0)
if(dna.species)
amount = amount * dna.species.brute_mod
take_overall_damage(amount, 0, updating_health, used_weapon = damage_source)
else
heal_overall_damage(-amount, 0, updating_health, FALSE, robotic)
// brainless default for now
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/adjustFireLoss(amount, updating_health = TRUE, damage_source = null, robotic = FALSE)
if(amount > 0)
if(dna.species)
amount = amount * dna.species.burn_mod
take_overall_damage(0, amount, updating_health, used_weapon = damage_source)
else
heal_overall_damage(0, -amount, updating_health, FALSE, robotic)
// brainless default for now
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/proc/adjustBruteLossByPart(amount, organ_name, obj/damage_source = null, updating_health = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.brute_mod
if(organ_name in bodyparts_by_name)
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
O.receive_damage(amount, 0, sharp=is_sharp(damage_source), used_weapon=damage_source, list(), FALSE, updating_health)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(-amount, 0, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/proc/adjustFireLossByPart(amount, organ_name, obj/damage_source = null, updating_health = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.burn_mod
if(organ_name in bodyparts_by_name)
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
O.receive_damage(0, amount, sharp=is_sharp(damage_source), used_weapon=damage_source, forbidden_limbs = list(), ignore_resists = FALSE, updating_health = updating_health)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(0, -amount, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/Paralyse(amount)
// Notify our AI if they can now control the suit.
if(wearing_rig && !stat && paralysis < amount) //We are passing out right this second.
wearing_rig.notify_ai("<span class='danger'>Warning: user consciousness failure. Mobility control passed to integrated intelligence system.</span>")
return ..()
/mob/living/carbon/human/adjustCloneLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.clone_mod
. = ..()
var/heal_prob = max(0, 80 - getCloneLoss())
var/mut_prob = min(80, getCloneLoss() + 10)
if(amount > 0) //cloneloss is being added
if(prob(mut_prob))
var/list/obj/item/organ/external/candidates = list() //TYPECASTED LISTS ARE NOT A FUCKING THING WHAT THE FUCK
for(var/obj/item/organ/external/O in bodyparts)
if(O.is_robotic())
continue
if(!(O.status & ORGAN_MUTATED))
candidates |= O
if(candidates.len)
var/obj/item/organ/external/O = pick(candidates)
O.mutate()
to_chat(src, "<span class='notice'>Something is not right with your [O.name]...</span>")
O.add_autopsy_data("Mutation", amount)
return
else //cloneloss is being subtracted
if(prob(heal_prob))
for(var/obj/item/organ/external/O in bodyparts)
if(O.status & ORGAN_MUTATED)
O.unmutate()
to_chat(src, "<span class='notice'>Your [O.name] is shaped normally again.</span>")
return
if(getCloneLoss() < 1) //no cloneloss, fixes organs
for(var/obj/item/organ/external/O in bodyparts)
if(O.status & ORGAN_MUTATED)
O.unmutate()
to_chat(src, "<span class='notice'>Your [O.name] is shaped normally again.</span>")
// 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
. = ..()
/mob/living/carbon/human/adjustToxLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.tox_mod
. = ..()
/mob/living/carbon/human/setToxLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.tox_mod
. = ..()
/mob/living/carbon/human/adjustStaminaLoss(amount, updating = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.stamina_mod
. = ..()
/mob/living/carbon/human/setStaminaLoss(amount, updating = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.stamina_mod
. = ..()
////////////////////////////////////////////
//Returns a list of damaged organs
/mob/living/carbon/human/proc/get_damaged_organs(brute, burn, flags = AFFECT_ALL_ORGANS)
var/list/obj/item/organ/external/parts = list()
for(var/obj/item/organ/external/O in bodyparts)
if((brute && O.brute_dam) || (burn && O.burn_dam))
if(!(flags & AFFECT_ROBOTIC_ORGAN) && O.is_robotic())
continue
if(!(flags & AFFECT_ORGANIC_ORGAN) && !O.is_robotic())
continue
parts += O
return parts
//Returns a list of damageable organs
/mob/living/carbon/human/proc/get_damageable_organs()
var/list/obj/item/organ/external/parts = list()
for(var/obj/item/organ/external/O in bodyparts)
if(O.brute_dam + O.burn_dam < O.max_damage)
parts += O
return parts
//Heals ONE external organ, organ gets randomly selected from damaged ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/heal_organ_damage(brute, burn, updating_health = TRUE)
var/list/obj/item/organ/external/parts = get_damaged_organs(brute,burn)
if(!parts.len)
return
var/obj/item/organ/external/picked = pick(parts)
if(picked.heal_damage(brute,burn, updating_health))
UpdateDamageIcon()
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/take_organ_damage(brute, burn, updating_health = TRUE, sharp = 0, edge = 0)
var/list/obj/item/organ/external/parts = get_damageable_organs()
if(!parts.len)
return
var/obj/item/organ/external/picked = pick(parts)
if(picked.receive_damage(brute, burn, sharp, updating_health))
UpdateDamageIcon()
//Heal MANY external organs, in random order
/mob/living/carbon/human/heal_overall_damage(brute, burn, updating_health = TRUE, internal=0, robotic=0)
var/list/obj/item/organ/external/parts = get_damaged_organs(brute,burn)
var/update = 0
while(parts.len && ( brute > 0 || burn > 0) )
var/obj/item/organ/external/picked = pick(parts)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.heal_damage(brute,burn, internal, robotic, updating_health = FALSE)
brute -= (brute_was-picked.brute_dam)
burn -= (burn_was-picked.burn_dam)
parts -= picked
if(updating_health)
updatehealth("heal overall damage")
if(update)
UpdateDamageIcon()
// damage MANY external organs, in random order
/mob/living/carbon/human/take_overall_damage(brute, burn, updating_health = TRUE, used_weapon = null, sharp = 0, edge = 0)
if(status_flags & GODMODE)
return //godmode
var/list/obj/item/organ/external/parts = get_damageable_organs()
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/organ/external/picked = pick(parts)
var/brute_per_part = brute/parts.len
var/burn_per_part = burn/parts.len
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.receive_damage(brute_per_part, burn_per_part, sharp, used_weapon, list(), FALSE, FALSE)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
parts -= picked
if(updating_health)
updatehealth("take overall damage")
if(update)
UpdateDamageIcon()
////////////////////////////////////////////
/*
This function restores all organs.
*/
/mob/living/carbon/human/restore_all_organs()
for(var/obj/item/organ/external/current_organ in bodyparts)
current_organ.rejuvenate()
/mob/living/carbon/human/proc/HealDamage(zone, brute, burn)
var/obj/item/organ/external/E = get_organ(zone)
if(istype(E, /obj/item/organ/external))
if(E.heal_damage(brute, burn))
UpdateDamageIcon()
else
return 0
/mob/living/carbon/human/get_organ(zone)
if(!zone)
zone = "chest"
if(zone in list("eyes", "mouth"))
zone = "head"
return bodyparts_by_name[zone]
/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
//Handle other types of damage
if((damagetype != BRUTE) && (damagetype != BURN))
..(damage, damagetype, def_zone, blocked)
return 1
//Handle BRUTE and BURN damage
handle_suit_punctures(damagetype, damage)
//Handle species apply_damage procs
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, sharp, used_weapon)
//Updates the mob's health from organs and mob damage variables
/mob/living/carbon/human/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = maxHealth
stat = CONSCIOUS
return
var/total_burn = 0
var/total_brute = 0
for(var/obj/item/organ/external/O in bodyparts) //hardcoded to streamline things a bit
total_brute += O.brute_dam //calculates health based on organ brute and burn
total_burn += O.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD)
ChangeToHusk()
update_stat("updatehealth([reason])")
med_hud_set_health()
med_hud_set_status()
handle_hud_icons_health()
/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE)
if(status_flags & GODMODE)
return STATUS_UPDATE_NONE //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(sponge.damage + amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("adjustBrainLoss")
return STATUS_UPDATE_STAT
/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE)
if(status_flags & GODMODE)
return STATUS_UPDATE_NONE //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("setBrainLoss")
return STATUS_UPDATE_STAT
/mob/living/carbon/human/getBrainLoss()
if(status_flags & GODMODE)
return 0 //godmode
if(dna.species && dna.species.has_organ["brain"])
var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain)
if(sponge)
return min(sponge.damage,maxHealth*2)
else
return 200
else
return 0
//These procs fetch a cumulative total damage from all organs
/mob/living/carbon/human/getBruteLoss()
var/amount = 0
for(var/obj/item/organ/external/O in bodyparts)
amount += O.brute_dam
return amount
/mob/living/carbon/human/getFireLoss()
var/amount = 0
for(var/obj/item/organ/external/O in bodyparts)
amount += O.burn_dam
return amount
/mob/living/carbon/human/adjustBruteLoss(amount, updating_health = TRUE, damage_source = null, robotic = FALSE)
if(amount > 0)
if(dna.species)
amount = amount * dna.species.brute_mod
take_overall_damage(amount, 0, updating_health, used_weapon = damage_source)
else
heal_overall_damage(-amount, 0, updating_health, FALSE, robotic)
// brainless default for now
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/adjustFireLoss(amount, updating_health = TRUE, damage_source = null, robotic = FALSE)
if(amount > 0)
if(dna.species)
amount = amount * dna.species.burn_mod
take_overall_damage(0, amount, updating_health, used_weapon = damage_source)
else
heal_overall_damage(0, -amount, updating_health, FALSE, robotic)
// brainless default for now
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/proc/adjustBruteLossByPart(amount, organ_name, obj/damage_source = null, updating_health = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.brute_mod
if(organ_name in bodyparts_by_name)
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
O.receive_damage(amount, 0, sharp=is_sharp(damage_source), used_weapon=damage_source, list(), FALSE, updating_health)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(-amount, 0, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/proc/adjustFireLossByPart(amount, organ_name, obj/damage_source = null, updating_health = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.burn_mod
if(organ_name in bodyparts_by_name)
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
O.receive_damage(0, amount, sharp=is_sharp(damage_source), used_weapon=damage_source, forbidden_limbs = list(), ignore_resists = FALSE, updating_health = updating_health)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(0, -amount, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/Paralyse(amount)
// Notify our AI if they can now control the suit.
if(wearing_rig && !stat && paralysis < amount) //We are passing out right this second.
wearing_rig.notify_ai("<span class='danger'>Warning: user consciousness failure. Mobility control passed to integrated intelligence system.</span>")
return ..()
/mob/living/carbon/human/adjustCloneLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.clone_mod
. = ..()
var/heal_prob = max(0, 80 - getCloneLoss())
var/mut_prob = min(80, getCloneLoss() + 10)
if(amount > 0) //cloneloss is being added
if(prob(mut_prob))
var/list/obj/item/organ/external/candidates = list() //TYPECASTED LISTS ARE NOT A FUCKING THING WHAT THE FUCK
for(var/obj/item/organ/external/O in bodyparts)
if(O.is_robotic())
continue
if(!(O.status & ORGAN_MUTATED))
candidates |= O
if(candidates.len)
var/obj/item/organ/external/O = pick(candidates)
O.mutate()
to_chat(src, "<span class='notice'>Something is not right with your [O.name]...</span>")
O.add_autopsy_data("Mutation", amount)
return
else //cloneloss is being subtracted
if(prob(heal_prob))
for(var/obj/item/organ/external/O in bodyparts)
if(O.status & ORGAN_MUTATED)
O.unmutate()
to_chat(src, "<span class='notice'>Your [O.name] is shaped normally again.</span>")
return
if(getCloneLoss() < 1) //no cloneloss, fixes organs
for(var/obj/item/organ/external/O in bodyparts)
if(O.status & ORGAN_MUTATED)
O.unmutate()
to_chat(src, "<span class='notice'>Your [O.name] is shaped normally again.</span>")
// 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
. = ..()
/mob/living/carbon/human/adjustToxLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.tox_mod
. = ..()
/mob/living/carbon/human/setToxLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.tox_mod
. = ..()
/mob/living/carbon/human/adjustStaminaLoss(amount, updating = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.stamina_mod
. = ..()
/mob/living/carbon/human/setStaminaLoss(amount, updating = TRUE)
if(dna.species && amount > 0)
amount = amount * dna.species.stamina_mod
. = ..()
////////////////////////////////////////////
//Returns a list of damaged organs
/mob/living/carbon/human/proc/get_damaged_organs(brute, burn, flags = AFFECT_ALL_ORGANS)
var/list/obj/item/organ/external/parts = list()
for(var/obj/item/organ/external/O in bodyparts)
if((brute && O.brute_dam) || (burn && O.burn_dam))
if(!(flags & AFFECT_ROBOTIC_ORGAN) && O.is_robotic())
continue
if(!(flags & AFFECT_ORGANIC_ORGAN) && !O.is_robotic())
continue
parts += O
return parts
//Returns a list of damageable organs
/mob/living/carbon/human/proc/get_damageable_organs()
var/list/obj/item/organ/external/parts = list()
for(var/obj/item/organ/external/O in bodyparts)
if(O.brute_dam + O.burn_dam < O.max_damage)
parts += O
return parts
//Heals ONE external organ, organ gets randomly selected from damaged ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/heal_organ_damage(brute, burn, updating_health = TRUE)
var/list/obj/item/organ/external/parts = get_damaged_organs(brute,burn)
if(!parts.len)
return
var/obj/item/organ/external/picked = pick(parts)
if(picked.heal_damage(brute,burn, updating_health))
UpdateDamageIcon()
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/take_organ_damage(brute, burn, updating_health = TRUE, sharp = 0, edge = 0)
var/list/obj/item/organ/external/parts = get_damageable_organs()
if(!parts.len)
return
var/obj/item/organ/external/picked = pick(parts)
if(picked.receive_damage(brute, burn, sharp, updating_health))
UpdateDamageIcon()
//Heal MANY external organs, in random order
/mob/living/carbon/human/heal_overall_damage(brute, burn, updating_health = TRUE, internal=0, robotic=0)
var/list/obj/item/organ/external/parts = get_damaged_organs(brute,burn)
var/update = 0
while(parts.len && ( brute > 0 || burn > 0) )
var/obj/item/organ/external/picked = pick(parts)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.heal_damage(brute,burn, internal, robotic, updating_health = FALSE)
brute -= (brute_was-picked.brute_dam)
burn -= (burn_was-picked.burn_dam)
parts -= picked
if(updating_health)
updatehealth("heal overall damage")
if(update)
UpdateDamageIcon()
// damage MANY external organs, in random order
/mob/living/carbon/human/take_overall_damage(brute, burn, updating_health = TRUE, used_weapon = null, sharp = 0, edge = 0)
if(status_flags & GODMODE)
return //godmode
var/list/obj/item/organ/external/parts = get_damageable_organs()
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/organ/external/picked = pick(parts)
var/brute_per_part = brute/parts.len
var/burn_per_part = burn/parts.len
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.receive_damage(brute_per_part, burn_per_part, sharp, used_weapon, list(), FALSE, FALSE)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
parts -= picked
if(updating_health)
updatehealth("take overall damage")
if(update)
UpdateDamageIcon()
////////////////////////////////////////////
/*
This function restores all organs.
*/
/mob/living/carbon/human/restore_all_organs()
for(var/obj/item/organ/external/current_organ in bodyparts)
current_organ.rejuvenate()
/mob/living/carbon/human/proc/HealDamage(zone, brute, burn)
var/obj/item/organ/external/E = get_organ(zone)
if(istype(E, /obj/item/organ/external))
if(E.heal_damage(brute, burn))
UpdateDamageIcon()
else
return 0
/mob/living/carbon/human/get_organ(zone)
if(!zone)
zone = "chest"
if(zone in list("eyes", "mouth"))
zone = "head"
return bodyparts_by_name[zone]
/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
//Handle other types of damage
if((damagetype != BRUTE) && (damagetype != BURN))
..(damage, damagetype, def_zone, blocked)
return 1
//Handle BRUTE and BURN damage
handle_suit_punctures(damagetype, damage)
//Handle species apply_damage procs
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, sharp, used_weapon)
File diff suppressed because it is too large Load Diff
@@ -1,74 +1,74 @@
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,GLAND_HUD)
pressure_resistance = 25
//Marking colour and style
var/list/m_colours = DEFAULT_MARKING_COLOURS //All colours set to #000000.
var/list/m_styles = DEFAULT_MARKING_STYLES //All markings set to None.
var/s_tone = 0 //Skin tone
//Skin colour
var/skin_colour = "#000000"
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
var/socks = "Nude" //Which socks the player wants
var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack.
//Equipment slots
var/obj/item/w_uniform = null
var/obj/item/shoes = null
var/obj/item/belt = null
var/obj/item/gloves = null
var/obj/item/glasses = null
var/obj/item/l_ear = null
var/obj/item/r_ear = null
var/obj/item/wear_id = null
var/obj/item/wear_pda = null
var/obj/item/r_store = null
var/obj/item/l_store = null
var/obj/item/s_store = null
var/icon/stand_icon = null
var/icon/lying_icon = null
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/datum/personal_crafting/handcrafting
var/datum/martial_art/martial_art = null
var/special_voice = "" // For changing our voice. Used by a symptom.
var/hand_blood_color
var/name_override //For temporary visible name changes
var/xylophone = 0 //For the spoooooooky xylophone cooldown
var/mob/remoteview_target = null
var/meatleft = 3 //For chef item
var/decaylevel = 0 // For rotting bodies
var/max_blood = BLOOD_VOLUME_NORMAL // For stuff in the vessel
var/bleed_rate = 0
var/bleedsuppress = 0 //for stopping bloodloss
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"
var/datum/body_accessory/body_accessory = null
var/tail // Name of tail image in species effects icon file.
var/list/splinted_limbs = list() //limbs we know are splinted
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,GLAND_HUD)
pressure_resistance = 25
//Marking colour and style
var/list/m_colours = DEFAULT_MARKING_COLOURS //All colours set to #000000.
var/list/m_styles = DEFAULT_MARKING_STYLES //All markings set to None.
var/s_tone = 0 //Skin tone
//Skin colour
var/skin_colour = "#000000"
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
var/socks = "Nude" //Which socks the player wants
var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack.
//Equipment slots
var/obj/item/w_uniform = null
var/obj/item/shoes = null
var/obj/item/belt = null
var/obj/item/gloves = null
var/obj/item/glasses = null
var/obj/item/l_ear = null
var/obj/item/r_ear = null
var/obj/item/wear_id = null
var/obj/item/wear_pda = null
var/obj/item/r_store = null
var/obj/item/l_store = null
var/obj/item/s_store = null
var/icon/stand_icon = null
var/icon/lying_icon = null
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/datum/personal_crafting/handcrafting
var/datum/martial_art/martial_art = null
var/special_voice = "" // For changing our voice. Used by a symptom.
var/hand_blood_color
var/name_override //For temporary visible name changes
var/xylophone = 0 //For the spoooooooky xylophone cooldown
var/mob/remoteview_target = null
var/meatleft = 3 //For chef item
var/decaylevel = 0 // For rotting bodies
var/max_blood = BLOOD_VOLUME_NORMAL // For stuff in the vessel
var/bleed_rate = 0
var/bleedsuppress = 0 //for stopping bloodloss
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"
var/datum/body_accessory/body_accessory = null
var/tail // Name of tail image in species effects icon file.
var/list/splinted_limbs = list() //limbs we know are splinted
@@ -1,133 +1,133 @@
/mob/living/carbon/human/movement_delay()
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0)
if(..())
return 1
//Do we have a working jetpack?
var/obj/item/tank/jetpack/thrust
if(istype(back, /obj/item/tank/jetpack))
thrust = back
else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
thrust = C.jetpack
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)
thrust = module.jets
break
if(thrust)
if((movement_dir || thrust.stabilizers) && thrust.allow_thrust(0.01, src))
return 1
return 0
/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return shoes && shoes.negates_gravity()
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
if(.) // did we actually move?
if(!lying && !buckled && !throwing)
for(var/obj/item/organ/external/splinted in splinted_limbs)
splinted.update_splints()
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
var/obj/item/organ/external/l_foot = get_organ("l_foot")
var/obj/item/organ/external/r_foot = get_organ("r_foot")
var/hasfeet = TRUE
if(!l_foot && !r_foot)
hasfeet = FALSE
if(shoes)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
if(oldFP && oldFP.blood_state == S.blood_state && oldFP.basecolor == S.blood_color)
return
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
if(S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
createFootprintsFrom(shoes, dir, T)
update_inv_shoes()
else if(hasfeet)
if(bloody_feet && bloody_feet[blood_state])
for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
if(oldFP && oldFP.blood_state == blood_state && oldFP.basecolor == feet_blood_color)
return
bloody_feet[blood_state] = max(0, bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP)
if(bloody_feet[blood_state] > BLOOD_LOSS_IN_SPREAD)
createFootprintsFrom(src, dir, T)
update_inv_shoes()
//End bloody footprints
if(S)
S.step_action(src)
/mob/living/carbon/human/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["human"])
var/S = pick(T.footstep_sounds["human"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
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
if(!shoes)
range -= 0.333
//shoes + running
//-(7 - 2) = -(5) = -5 | -5 - 0 = -5 | (7 + -5) = 2 | 2 * 3 = 6 | range(6) = range(6)
//running OR shoes
//-(7 - 2) = (-5) = -5 | -5 - 0.333 = -5.333 | (7 + -5.333) = 1.667 | 1.667 * 3 = 5.001 | range(5.001) = range(5)
//walking AND no shoes
//-(7 - 2) = (-5) = -5 | -5 - (0.333 * 2) = -5.666 | (7 + -5.666) = 1.334 | 1.334 * 3 = 4.002 | range(4.002) = range(4)
var/volume = 13
if(m_intent == MOVE_INTENT_WALK)
volume -= 4
if(!shoes)
volume -= 4
if(!has_organ("l_foot") && !has_organ("r_foot"))
return 0 //no feet no footsteps
if(buckled || lying || throwing)
return 0 //people flying, lying down or sitting do not step
if(!has_gravity(src))
if(step_count % 3) //this basically says, every three moves make a noise
return 0 //1st - none, 1%3==1, 2nd - none, 2%3==2, 3rd - noise, 3%3==0
if(dna.species.silent_steps)
return 0 //species is silent
playsound(T, S, volume, 1, range)
return 1
return 0
/mob/living/carbon/human/movement_delay()
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0)
if(..())
return 1
//Do we have a working jetpack?
var/obj/item/tank/jetpack/thrust
if(istype(back, /obj/item/tank/jetpack))
thrust = back
else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
thrust = C.jetpack
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)
thrust = module.jets
break
if(thrust)
if((movement_dir || thrust.stabilizers) && thrust.allow_thrust(0.01, src))
return 1
return 0
/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return shoes && shoes.negates_gravity()
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
if(.) // did we actually move?
if(!lying && !buckled && !throwing)
for(var/obj/item/organ/external/splinted in splinted_limbs)
splinted.update_splints()
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
var/obj/item/organ/external/l_foot = get_organ("l_foot")
var/obj/item/organ/external/r_foot = get_organ("r_foot")
var/hasfeet = TRUE
if(!l_foot && !r_foot)
hasfeet = FALSE
if(shoes)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
if(oldFP && oldFP.blood_state == S.blood_state && oldFP.basecolor == S.blood_color)
return
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
if(S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
createFootprintsFrom(shoes, dir, T)
update_inv_shoes()
else if(hasfeet)
if(bloody_feet && bloody_feet[blood_state])
for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
if(oldFP && oldFP.blood_state == blood_state && oldFP.basecolor == feet_blood_color)
return
bloody_feet[blood_state] = max(0, bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP)
if(bloody_feet[blood_state] > BLOOD_LOSS_IN_SPREAD)
createFootprintsFrom(src, dir, T)
update_inv_shoes()
//End bloody footprints
if(S)
S.step_action(src)
/mob/living/carbon/human/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["human"])
var/S = pick(T.footstep_sounds["human"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
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
if(!shoes)
range -= 0.333
//shoes + running
//-(7 - 2) = -(5) = -5 | -5 - 0 = -5 | (7 + -5) = 2 | 2 * 3 = 6 | range(6) = range(6)
//running OR shoes
//-(7 - 2) = (-5) = -5 | -5 - 0.333 = -5.333 | (7 + -5.333) = 1.667 | 1.667 * 3 = 5.001 | range(5.001) = range(5)
//walking AND no shoes
//-(7 - 2) = (-5) = -5 | -5 - (0.333 * 2) = -5.666 | (7 + -5.666) = 1.334 | 1.334 * 3 = 4.002 | range(4.002) = range(4)
var/volume = 13
if(m_intent == MOVE_INTENT_WALK)
volume -= 4
if(!shoes)
volume -= 4
if(!has_organ("l_foot") && !has_organ("r_foot"))
return 0 //no feet no footsteps
if(buckled || lying || throwing)
return 0 //people flying, lying down or sitting do not step
if(!has_gravity(src))
if(step_count % 3) //this basically says, every three moves make a noise
return 0 //1st - none, 1%3==1, 2nd - none, 2%3==2, 3rd - noise, 3%3==0
if(dna.species.silent_steps)
return 0 //species is silent
playsound(T, S, volume, 1, range)
return 1
return 0
+437 -437
View File
@@ -1,437 +1,437 @@
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(W, slots[slot], del_on_fail = 0))
return slot
if(del_on_fail)
qdel(W)
return null
/mob/living/carbon/human/proc/is_in_hands(var/typepath)
if(istype(l_hand,typepath))
return l_hand
if(istype(r_hand,typepath))
return r_hand
return 0
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = bodyparts_by_name[name]
return O
/mob/living/carbon/human/proc/has_organ_for_slot(slot)
switch(slot)
if(slot_back)
return has_organ("chest")
if(slot_wear_mask)
return has_organ("head")
if(slot_handcuffed)
return has_organ("l_hand") && has_organ("r_hand")
if(slot_legcuffed)
return has_organ("l_leg") && has_organ("r_leg")
if(slot_l_hand)
return has_organ("l_hand")
if(slot_r_hand)
return has_organ("r_hand")
if(slot_belt)
return has_organ("chest")
if(slot_wear_id)
// the only relevant check for this is the uniform check
return TRUE
if(slot_wear_pda)
return TRUE
if(slot_l_ear)
return has_organ("head")
if(slot_r_ear)
return has_organ("head")
if(slot_glasses)
return has_organ("head")
if(slot_gloves)
return has_organ("l_hand") && has_organ("r_hand")
if(slot_head)
return has_organ("head")
if(slot_shoes)
return has_organ("r_foot") && has_organ("l_foot")
if(slot_wear_suit)
return has_organ("chest")
if(slot_w_uniform)
return has_organ("chest")
if(slot_l_store)
return has_organ("chest")
if(slot_r_store)
return has_organ("chest")
if(slot_s_store)
return has_organ("chest")
if(slot_in_backpack)
return TRUE
if(slot_tie)
return TRUE
// The actual dropping happens at the mob level - checks to prevent drops should
// come here
/mob/living/carbon/human/canUnEquip(obj/item/I, force)
. = ..()
var/obj/item/organ/O = I
if(istype(O) && O.owner == src)
. = 0 // keep a good grip on your heart
/mob/living/carbon/human/unEquip(obj/item/I, force)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(I == wear_suit)
if(s_store)
unEquip(s_store, 1) //It makes no sense for your suit storage to stay on you if you drop your suit.
wear_suit = null
if(I.flags_inv & HIDEJUMPSUIT)
update_inv_w_uniform()
update_inv_wear_suit()
else if(I == w_uniform)
if(r_store)
unEquip(r_store, 1) //Again, makes sense for pockets to drop.
if(l_store)
unEquip(l_store, 1)
if(wear_id)
unEquip(wear_id)
if(belt)
unEquip(belt)
w_uniform = null
update_inv_w_uniform()
else if(I == gloves)
gloves = null
update_inv_gloves()
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.prescription)
update_nearsighted_effects()
if(G.vision_flags || G.see_in_dark || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses()
update_client_colour()
else if(I == head)
head = null
if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR)
update_hair() //rebuild hair
update_fhair()
update_head_accessory()
// Bandanas and paper hats go on the head but are not head clothing
if(istype(I,/obj/item/clothing/head))
var/obj/item/clothing/head/hat = I
if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha))
update_sight()
head_update(I)
update_inv_head()
else if(I == r_ear)
r_ear = null
update_inv_ears()
else if(I == l_ear)
l_ear = null
update_inv_ears()
else if(I == shoes)
shoes = null
update_inv_shoes()
else if(I == belt)
belt = null
update_inv_belt()
else if(I == wear_mask)
wear_mask = null
if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR)
update_hair() //rebuild hair
update_fhair()
update_head_accessory()
if(internal && !get_organ_slot("breathing_tube"))
internal = null
update_action_buttons_icon()
wear_mask_update(I, toggle_off = FALSE)
sec_hud_set_ID()
update_inv_wear_mask()
else if(I == wear_id)
wear_id = null
sec_hud_set_ID()
update_inv_wear_id()
else if(I == wear_pda)
wear_pda = null
update_inv_wear_pda()
else if(I == r_store)
r_store = null
update_inv_pockets()
else if(I == l_store)
l_store = null
update_inv_pockets()
else if(I == s_store)
s_store = null
update_inv_s_store()
else if(I == back)
back = null
update_inv_back()
else if(I == r_hand)
r_hand = null
update_inv_r_hand()
else if(I == l_hand)
l_hand = null
update_inv_l_hand()
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc.
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1)
if(!slot)
return
if(!istype(I))
return
if(!has_organ_for_slot(slot))
return
if(I == src.l_hand)
src.l_hand = null
update_inv_l_hand() //So items actually disappear from hands.
else if(I == src.r_hand)
src.r_hand = null
update_inv_r_hand()
I.screen_loc = null
I.forceMove(src)
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
switch(slot)
if(slot_back)
back = I
update_inv_back(redraw_mob)
if(slot_wear_mask)
wear_mask = I
if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
if(hud_list.len)
sec_hud_set_ID()
wear_mask_update(I, toggle_off = TRUE)
update_inv_wear_mask(redraw_mob)
if(slot_handcuffed)
handcuffed = I
update_inv_handcuffed(redraw_mob)
if(slot_legcuffed)
legcuffed = I
update_inv_legcuffed(redraw_mob)
if(slot_l_hand)
l_hand = I
update_inv_l_hand(redraw_mob)
if(slot_r_hand)
r_hand = I
update_inv_r_hand(redraw_mob)
if(slot_belt)
belt = I
update_inv_belt(redraw_mob)
if(slot_wear_id)
wear_id = I
if(hud_list.len)
sec_hud_set_ID()
update_inv_wear_id(redraw_mob)
if(slot_wear_pda)
wear_pda = I
update_inv_wear_pda(redraw_mob)
if(slot_l_ear)
l_ear = I
if(l_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
r_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_r_ear)
r_ear = I
if(r_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
l_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.prescription)
update_nearsighted_effects()
if(G.vision_flags || G.see_in_dark || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses(redraw_mob)
update_client_colour()
if(slot_gloves)
gloves = I
update_inv_gloves(redraw_mob)
if(slot_head)
head = I
if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
// paper + bandanas
if(istype(I, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = I
if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha))
update_sight()
head_update(I)
update_inv_head(redraw_mob)
if(slot_shoes)
shoes = I
update_inv_shoes(redraw_mob)
if(slot_wear_suit)
wear_suit = I
update_inv_wear_suit(redraw_mob)
if(slot_w_uniform)
w_uniform = I
update_inv_w_uniform(redraw_mob)
if(slot_l_store)
l_store = I
update_inv_pockets(redraw_mob)
if(slot_r_store)
r_store = I
update_inv_pockets(redraw_mob)
if(slot_s_store)
s_store = I
update_inv_s_store(redraw_mob)
if(slot_in_backpack)
if(get_active_hand() == I)
unEquip(I)
I.forceMove(back)
if(slot_tie)
var/obj/item/clothing/under/uniform = src.w_uniform
uniform.attackby(I, src)
else
to_chat(src, "<span class='warning'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>")
/mob/living/carbon/human/put_in_hands(obj/item/I)
if(!I)
return FALSE
if(put_in_active_hand(I))
return TRUE
else if(put_in_inactive_hand(I))
return TRUE
else
. = ..()
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_back)
return back
if(slot_wear_mask)
return wear_mask
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
if(slot_belt)
return belt
if(slot_wear_id)
return wear_id
if(slot_wear_pda)
return wear_pda
if(slot_l_ear)
return l_ear
if(slot_r_ear)
return r_ear
if(slot_glasses)
return glasses
if(slot_gloves)
return gloves
if(slot_head)
return head
if(slot_shoes)
return shoes
if(slot_wear_suit)
return wear_suit
if(slot_w_uniform)
return w_uniform
if(slot_l_store)
return l_store
if(slot_r_store)
return r_store
if(slot_s_store)
return s_store
return null
/mob/living/carbon/human/get_all_slots()
. = get_head_slots() | get_body_slots()
/mob/living/carbon/human/proc/get_body_slots()
return list(
l_hand,
r_hand,
back,
s_store,
handcuffed,
legcuffed,
wear_suit,
gloves,
shoes,
belt,
wear_id,
wear_pda,
l_store,
r_store,
w_uniform
)
/mob/living/carbon/human/proc/get_head_slots()
return list(
head,
wear_mask,
glasses,
r_ear,
l_ear,
)
// humans have their pickpocket gloves, so they get no message when stealing things
/mob/living/carbon/human/stripPanelUnequip(obj/item/what, mob/who, where)
var/is_silent = 0
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
is_silent = G.pickpocket
..(what, who, where, silent = is_silent)
// humans have their pickpocket gloves, so they get no message when stealing things
/mob/living/carbon/human/stripPanelEquip(obj/item/what, mob/who, where)
var/is_silent = 0
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
is_silent = G.pickpocket
..(what, who, where, silent = is_silent)
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE)
return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
var/datum/outfit/O = null
if(ispath(outfit))
O = new outfit
else
O = outfit
if(!istype(O))
return 0
if(!O)
return 0
return O.equip(src, visualsOnly)
//delete all equipment without dropping anything
/mob/living/carbon/human/proc/delete_equipment()
for(var/slot in get_all_slots())//order matters, dependant slots go first
qdel(slot)
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(W, slots[slot], del_on_fail = 0))
return slot
if(del_on_fail)
qdel(W)
return null
/mob/living/carbon/human/proc/is_in_hands(var/typepath)
if(istype(l_hand,typepath))
return l_hand
if(istype(r_hand,typepath))
return r_hand
return 0
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = bodyparts_by_name[name]
return O
/mob/living/carbon/human/proc/has_organ_for_slot(slot)
switch(slot)
if(slot_back)
return has_organ("chest")
if(slot_wear_mask)
return has_organ("head")
if(slot_handcuffed)
return has_organ("l_hand") && has_organ("r_hand")
if(slot_legcuffed)
return has_organ("l_leg") && has_organ("r_leg")
if(slot_l_hand)
return has_organ("l_hand")
if(slot_r_hand)
return has_organ("r_hand")
if(slot_belt)
return has_organ("chest")
if(slot_wear_id)
// the only relevant check for this is the uniform check
return TRUE
if(slot_wear_pda)
return TRUE
if(slot_l_ear)
return has_organ("head")
if(slot_r_ear)
return has_organ("head")
if(slot_glasses)
return has_organ("head")
if(slot_gloves)
return has_organ("l_hand") && has_organ("r_hand")
if(slot_head)
return has_organ("head")
if(slot_shoes)
return has_organ("r_foot") && has_organ("l_foot")
if(slot_wear_suit)
return has_organ("chest")
if(slot_w_uniform)
return has_organ("chest")
if(slot_l_store)
return has_organ("chest")
if(slot_r_store)
return has_organ("chest")
if(slot_s_store)
return has_organ("chest")
if(slot_in_backpack)
return TRUE
if(slot_tie)
return TRUE
// The actual dropping happens at the mob level - checks to prevent drops should
// come here
/mob/living/carbon/human/canUnEquip(obj/item/I, force)
. = ..()
var/obj/item/organ/O = I
if(istype(O) && O.owner == src)
. = 0 // keep a good grip on your heart
/mob/living/carbon/human/unEquip(obj/item/I, force)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(I == wear_suit)
if(s_store)
unEquip(s_store, 1) //It makes no sense for your suit storage to stay on you if you drop your suit.
wear_suit = null
if(I.flags_inv & HIDEJUMPSUIT)
update_inv_w_uniform()
update_inv_wear_suit()
else if(I == w_uniform)
if(r_store)
unEquip(r_store, 1) //Again, makes sense for pockets to drop.
if(l_store)
unEquip(l_store, 1)
if(wear_id)
unEquip(wear_id)
if(belt)
unEquip(belt)
w_uniform = null
update_inv_w_uniform()
else if(I == gloves)
gloves = null
update_inv_gloves()
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.prescription)
update_nearsighted_effects()
if(G.vision_flags || G.see_in_dark || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses()
update_client_colour()
else if(I == head)
head = null
if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR)
update_hair() //rebuild hair
update_fhair()
update_head_accessory()
// Bandanas and paper hats go on the head but are not head clothing
if(istype(I,/obj/item/clothing/head))
var/obj/item/clothing/head/hat = I
if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha))
update_sight()
head_update(I)
update_inv_head()
else if(I == r_ear)
r_ear = null
update_inv_ears()
else if(I == l_ear)
l_ear = null
update_inv_ears()
else if(I == shoes)
shoes = null
update_inv_shoes()
else if(I == belt)
belt = null
update_inv_belt()
else if(I == wear_mask)
wear_mask = null
if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR)
update_hair() //rebuild hair
update_fhair()
update_head_accessory()
if(internal && !get_organ_slot("breathing_tube"))
internal = null
update_action_buttons_icon()
wear_mask_update(I, toggle_off = FALSE)
sec_hud_set_ID()
update_inv_wear_mask()
else if(I == wear_id)
wear_id = null
sec_hud_set_ID()
update_inv_wear_id()
else if(I == wear_pda)
wear_pda = null
update_inv_wear_pda()
else if(I == r_store)
r_store = null
update_inv_pockets()
else if(I == l_store)
l_store = null
update_inv_pockets()
else if(I == s_store)
s_store = null
update_inv_s_store()
else if(I == back)
back = null
update_inv_back()
else if(I == r_hand)
r_hand = null
update_inv_r_hand()
else if(I == l_hand)
l_hand = null
update_inv_l_hand()
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc.
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1)
if(!slot)
return
if(!istype(I))
return
if(!has_organ_for_slot(slot))
return
if(I == src.l_hand)
src.l_hand = null
update_inv_l_hand() //So items actually disappear from hands.
else if(I == src.r_hand)
src.r_hand = null
update_inv_r_hand()
I.screen_loc = null
I.forceMove(src)
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
switch(slot)
if(slot_back)
back = I
update_inv_back(redraw_mob)
if(slot_wear_mask)
wear_mask = I
if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
if(hud_list.len)
sec_hud_set_ID()
wear_mask_update(I, toggle_off = TRUE)
update_inv_wear_mask(redraw_mob)
if(slot_handcuffed)
handcuffed = I
update_inv_handcuffed(redraw_mob)
if(slot_legcuffed)
legcuffed = I
update_inv_legcuffed(redraw_mob)
if(slot_l_hand)
l_hand = I
update_inv_l_hand(redraw_mob)
if(slot_r_hand)
r_hand = I
update_inv_r_hand(redraw_mob)
if(slot_belt)
belt = I
update_inv_belt(redraw_mob)
if(slot_wear_id)
wear_id = I
if(hud_list.len)
sec_hud_set_ID()
update_inv_wear_id(redraw_mob)
if(slot_wear_pda)
wear_pda = I
update_inv_wear_pda(redraw_mob)
if(slot_l_ear)
l_ear = I
if(l_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
r_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_r_ear)
r_ear = I
if(r_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
l_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.prescription)
update_nearsighted_effects()
if(G.vision_flags || G.see_in_dark || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses(redraw_mob)
update_client_colour()
if(slot_gloves)
gloves = I
update_inv_gloves(redraw_mob)
if(slot_head)
head = I
if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
// paper + bandanas
if(istype(I, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = I
if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha))
update_sight()
head_update(I)
update_inv_head(redraw_mob)
if(slot_shoes)
shoes = I
update_inv_shoes(redraw_mob)
if(slot_wear_suit)
wear_suit = I
update_inv_wear_suit(redraw_mob)
if(slot_w_uniform)
w_uniform = I
update_inv_w_uniform(redraw_mob)
if(slot_l_store)
l_store = I
update_inv_pockets(redraw_mob)
if(slot_r_store)
r_store = I
update_inv_pockets(redraw_mob)
if(slot_s_store)
s_store = I
update_inv_s_store(redraw_mob)
if(slot_in_backpack)
if(get_active_hand() == I)
unEquip(I)
I.forceMove(back)
if(slot_tie)
var/obj/item/clothing/under/uniform = src.w_uniform
uniform.attackby(I, src)
else
to_chat(src, "<span class='warning'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>")
/mob/living/carbon/human/put_in_hands(obj/item/I)
if(!I)
return FALSE
if(put_in_active_hand(I))
return TRUE
else if(put_in_inactive_hand(I))
return TRUE
else
. = ..()
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_back)
return back
if(slot_wear_mask)
return wear_mask
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
if(slot_belt)
return belt
if(slot_wear_id)
return wear_id
if(slot_wear_pda)
return wear_pda
if(slot_l_ear)
return l_ear
if(slot_r_ear)
return r_ear
if(slot_glasses)
return glasses
if(slot_gloves)
return gloves
if(slot_head)
return head
if(slot_shoes)
return shoes
if(slot_wear_suit)
return wear_suit
if(slot_w_uniform)
return w_uniform
if(slot_l_store)
return l_store
if(slot_r_store)
return r_store
if(slot_s_store)
return s_store
return null
/mob/living/carbon/human/get_all_slots()
. = get_head_slots() | get_body_slots()
/mob/living/carbon/human/proc/get_body_slots()
return list(
l_hand,
r_hand,
back,
s_store,
handcuffed,
legcuffed,
wear_suit,
gloves,
shoes,
belt,
wear_id,
wear_pda,
l_store,
r_store,
w_uniform
)
/mob/living/carbon/human/proc/get_head_slots()
return list(
head,
wear_mask,
glasses,
r_ear,
l_ear,
)
// humans have their pickpocket gloves, so they get no message when stealing things
/mob/living/carbon/human/stripPanelUnequip(obj/item/what, mob/who, where)
var/is_silent = 0
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
is_silent = G.pickpocket
..(what, who, where, silent = is_silent)
// humans have their pickpocket gloves, so they get no message when stealing things
/mob/living/carbon/human/stripPanelEquip(obj/item/what, mob/who, where)
var/is_silent = 0
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
is_silent = G.pickpocket
..(what, who, where, silent = is_silent)
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE)
return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
var/datum/outfit/O = null
if(ispath(outfit))
O = new outfit
else
O = outfit
if(!istype(O))
return 0
if(!O)
return 0
return O.equip(src, visualsOnly)
//delete all equipment without dropping anything
/mob/living/carbon/human/proc/delete_equipment()
for(var/slot in get_all_slots())//order matters, dependant slots go first
qdel(slot)
File diff suppressed because it is too large Load Diff
@@ -1,9 +1,9 @@
/mob/living/carbon/human/Login()
if(player_logged)
overlays -= image('icons/effects/effects.dmi', icon_state = "zzz_glow")
..()
if(ventcrawler)
to_chat(src, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
update_pipe_vision()
return
/mob/living/carbon/human/Login()
if(player_logged)
overlays -= image('icons/effects/effects.dmi', icon_state = "zzz_glow")
..()
if(ventcrawler)
to_chat(src, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
update_pipe_vision()
return
@@ -1,4 +1,4 @@
/mob/living/carbon/human/Logout()
..()
if(mind && mind.active && stat != DEAD)
overlays += image('icons/effects/effects.dmi', icon_state = "zzz_glow")
overlays += image('icons/effects/effects.dmi', icon_state = "zzz_glow")
+259 -259
View File
@@ -1,259 +1,259 @@
/mob/living/carbon/human/say(var/message, var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
..(message, sanitize = sanitize, ignore_speech_problems = ignore_speech_problems, ignore_atmospherics = ignore_atmospherics) //ohgod we should really be passing a datum here.
/mob/living/carbon/human/GetAltName()
if(name != GetVoice())
return " (as [get_id_name("Unknown")])"
return ..()
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
if(client)
var/virgin = 1 //has the text been modified yet?
var/temp = winget(client, "input", "text")
if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //case sensitive means
temp = replacetext(temp, ";", "") //general radio
if(findtext(trim_left(temp), ":", 6, 7)) //dept radio
temp = copytext(trim_left(temp), 8)
virgin = 0
if(virgin)
temp = copytext(trim_left(temp), 6) //normal speech
virgin = 0
while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary)
temp = copytext(trim_left(temp), 3)
if(findtext(temp, "*", 1, 2)) //emotes
return
temp = copytext(trim_left(temp), 1, rand(5,8))
var/trimmed = trim_left(temp)
if(length(trimmed))
if(append)
temp += pick(append)
say(temp)
winset(client, "input", "text=[null]")
/mob/living/carbon/human/say_understands(var/mob/other, var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
return 1
if(dna.species.can_understand(other))
return 1
//These only pertain to common. Languages are handled by mob/say_understands()
if(!speaking)
if(istype(other, /mob/living/simple_animal/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
return 1
if(issilicon(other))
return 1
if(isbot(other))
return 1
if(isbrain(other))
return 1
if(isslime(other))
return 1
return ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
if(istype(back, /obj/item/rig))
var/obj/item/rig/rig = back
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
return rig.speech.voice_holder.voice
for(var/obj/item/gear in list(wear_mask, wear_suit, head))
if(!gear)
continue
var/obj/item/voice_changer/changer = locate() in gear
if(changer && changer.active)
if(changer.voice)
return changer.voice
else if(wear_id)
var/obj/item/card/id/idcard = wear_id.GetID()
if(istype(idcard))
return idcard.registered_name
return FALSE
/mob/living/carbon/human/GetVoice()
var/has_changer = HasVoiceChanger()
if(has_changer)
return has_changer
if(mind && mind.changeling && mind.changeling.mimicing)
return mind.changeling.mimicing
if(GetSpecialVoice())
return GetSpecialVoice()
return real_name
/mob/living/carbon/human/IsVocal()
var/obj/item/organ/internal/cyberimp/brain/speech_translator/translator = locate(/obj/item/organ/internal/cyberimp/brain/speech_translator) in internal_organs
if(translator && translator.active)
return TRUE
// how do species that don't breathe talk? magic, that's what.
var/breathes = (!(NO_BREATHE in dna.species.species_traits))
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
/mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice)
if(new_voice)
special_voice = new_voice
return
/mob/living/carbon/human/proc/UnsetSpecialVoice()
special_voice = ""
return
/mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice
/mob/living/carbon/human/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) \
|| GetComponent(/datum/component/jestosterone))
span = "sans"
if(WINGDINGS in mutations)
span = "wingdings"
var/list/parent = ..()
verb = parent["verb"]
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
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)
if(prob(braindam / 4))
S.message = stutter(S.message)
verb = "gibbers"
if(prob(braindam))
S.message = uppertext(S.message)
verb = "yells loudly"
if(span)
S.message = "<span class='[span]'>[S.message]</span>"
return list("verb" = verb)
/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_pieces, null, verb)
used_radios += I
if("headset")
var/obj/item/radio/R = null
if(isradio(l_ear))
R = l_ear
used_radios += R
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_pieces, null, verb))
return
if("right ear")
var/obj/item/radio/R
if(isradio(r_ear))
R = r_ear
else if(isradio(r_hand))
R = r_hand
if(R)
used_radios += R
R.talk_into(src, message_pieces, null, verb)
if("left ear")
var/obj/item/radio/R
if(isradio(l_ear))
R = l_ear
else if(isradio(l_hand))
R = l_hand
if(R)
used_radios += R
R.talk_into(src, message_pieces, null, verb)
if("whisper")
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_pieces, message_mode, verb))
return
if(isradio(r_ear))
used_radios += r_ear
if(r_ear.talk_into(src, message_pieces, message_mode, verb))
return
/mob/living/carbon/human/handle_speech_sound()
var/list/returns[3]
if(dna.species.speech_sounds && prob(dna.species.speech_chance))
returns[1] = sound(pick(dna.species.speech_sounds))
returns[2] = 50
returns[3] = get_age_pitch()
return returns
/mob/living/carbon/human/binarycheck()
. = FALSE
var/obj/item/radio/headset/R
if(istype(l_ear, /obj/item/radio/headset))
R = l_ear
if(R.translate_binary)
. = TRUE
if(istype(r_ear, /obj/item/radio/headset))
R = r_ear
if(R.translate_binary)
. = TRUE
/mob/living/carbon/human/say(var/message, var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
..(message, sanitize = sanitize, ignore_speech_problems = ignore_speech_problems, ignore_atmospherics = ignore_atmospherics) //ohgod we should really be passing a datum here.
/mob/living/carbon/human/GetAltName()
if(name != GetVoice())
return " (as [get_id_name("Unknown")])"
return ..()
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
if(client)
var/virgin = 1 //has the text been modified yet?
var/temp = winget(client, "input", "text")
if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //case sensitive means
temp = replacetext(temp, ";", "") //general radio
if(findtext(trim_left(temp), ":", 6, 7)) //dept radio
temp = copytext(trim_left(temp), 8)
virgin = 0
if(virgin)
temp = copytext(trim_left(temp), 6) //normal speech
virgin = 0
while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary)
temp = copytext(trim_left(temp), 3)
if(findtext(temp, "*", 1, 2)) //emotes
return
temp = copytext(trim_left(temp), 1, rand(5,8))
var/trimmed = trim_left(temp)
if(length(trimmed))
if(append)
temp += pick(append)
say(temp)
winset(client, "input", "text=[null]")
/mob/living/carbon/human/say_understands(var/mob/other, var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
return 1
if(dna.species.can_understand(other))
return 1
//These only pertain to common. Languages are handled by mob/say_understands()
if(!speaking)
if(istype(other, /mob/living/simple_animal/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
return 1
if(issilicon(other))
return 1
if(isbot(other))
return 1
if(isbrain(other))
return 1
if(isslime(other))
return 1
return ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
if(istype(back, /obj/item/rig))
var/obj/item/rig/rig = back
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
return rig.speech.voice_holder.voice
for(var/obj/item/gear in list(wear_mask, wear_suit, head))
if(!gear)
continue
var/obj/item/voice_changer/changer = locate() in gear
if(changer && changer.active)
if(changer.voice)
return changer.voice
else if(wear_id)
var/obj/item/card/id/idcard = wear_id.GetID()
if(istype(idcard))
return idcard.registered_name
return FALSE
/mob/living/carbon/human/GetVoice()
var/has_changer = HasVoiceChanger()
if(has_changer)
return has_changer
if(mind && mind.changeling && mind.changeling.mimicing)
return mind.changeling.mimicing
if(GetSpecialVoice())
return GetSpecialVoice()
return real_name
/mob/living/carbon/human/IsVocal()
var/obj/item/organ/internal/cyberimp/brain/speech_translator/translator = locate(/obj/item/organ/internal/cyberimp/brain/speech_translator) in internal_organs
if(translator && translator.active)
return TRUE
// how do species that don't breathe talk? magic, that's what.
var/breathes = (!(NO_BREATHE in dna.species.species_traits))
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
/mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice)
if(new_voice)
special_voice = new_voice
return
/mob/living/carbon/human/proc/UnsetSpecialVoice()
special_voice = ""
return
/mob/living/carbon/human/proc/GetSpecialVoice()
return special_voice
/mob/living/carbon/human/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) \
|| GetComponent(/datum/component/jestosterone))
span = "sans"
if(WINGDINGS in mutations)
span = "wingdings"
var/list/parent = ..()
verb = parent["verb"]
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
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)
if(prob(braindam / 4))
S.message = stutter(S.message)
verb = "gibbers"
if(prob(braindam))
S.message = uppertext(S.message)
verb = "yells loudly"
if(span)
S.message = "<span class='[span]'>[S.message]</span>"
return list("verb" = verb)
/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_pieces, null, verb)
used_radios += I
if("headset")
var/obj/item/radio/R = null
if(isradio(l_ear))
R = l_ear
used_radios += R
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_pieces, null, verb))
return
if("right ear")
var/obj/item/radio/R
if(isradio(r_ear))
R = r_ear
else if(isradio(r_hand))
R = r_hand
if(R)
used_radios += R
R.talk_into(src, message_pieces, null, verb)
if("left ear")
var/obj/item/radio/R
if(isradio(l_ear))
R = l_ear
else if(isradio(l_hand))
R = l_hand
if(R)
used_radios += R
R.talk_into(src, message_pieces, null, verb)
if("whisper")
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_pieces, message_mode, verb))
return
if(isradio(r_ear))
used_radios += r_ear
if(r_ear.talk_into(src, message_pieces, message_mode, verb))
return
/mob/living/carbon/human/handle_speech_sound()
var/list/returns[3]
if(dna.species.speech_sounds && prob(dna.species.speech_chance))
returns[1] = sound(pick(dna.species.speech_sounds))
returns[2] = 50
returns[3] = get_age_pitch()
return returns
/mob/living/carbon/human/binarycheck()
. = FALSE
var/obj/item/radio/headset/R
if(istype(l_ear, /obj/item/radio/headset))
R = l_ear
if(R.translate_binary)
. = TRUE
if(istype(r_ear, /obj/item/radio/headset))
R = r_ear
if(R.translate_binary)
. = TRUE
@@ -980,4 +980,4 @@ It'll return null if the organ doesn't correspond, so include null checks when u
. = FALSE
var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears)
if(istype(ears) && !ears.deaf)
. = TRUE
. = TRUE
@@ -43,4 +43,4 @@
/datum/species/abductor/on_species_loss(mob/living/carbon/human/H)
..()
var/datum/atom_hud/abductor_hud = huds[DATA_HUD_ABDUCTOR]
abductor_hud.remove_hud_from(H)
abductor_hud.remove_hud_from(H)
@@ -117,4 +117,4 @@
/datum/species/diona/pod/on_species_loss(mob/living/carbon/C)
. = ..()
C.faction -= "plants"
C.faction -= "vines"
C.faction -= "vines"
@@ -722,4 +722,4 @@
H.mind.miming = TRUE
/datum/unarmed_attack/golem/tranquillite
attack_sound = null
attack_sound = null
@@ -18,4 +18,4 @@
reagent_tag = PROCESS_ORG
//Has standard darksight of 2.
@@ -39,4 +39,4 @@
"is twisting their own neck!",
"is cracking their exoskeleton!",
"is stabbing themselves with their mandibles!",
"is holding their breath!")
"is holding their breath!")
@@ -38,4 +38,4 @@
var/turf/T = get_turf(H)
H.visible_message("<span class='warning'>[H]'s body explodes, leaving behind a pile of microscopic crystals!</span>")
explosion(T, 0, 0, 2, 2) // Create a small explosion burst upon death
qdel(H)
qdel(H)
@@ -70,4 +70,4 @@
else if(light_amount < 2) //heal in the dark
H.heal_overall_damage(1,1)
H.clear_alert("lightexposure")
..()
..()
@@ -79,4 +79,4 @@
H.adjustToxLoss(-5)
H.adjustBrainLoss(-25)
H.adjustCloneLoss(-1)
..()
..()
@@ -52,4 +52,4 @@
/datum/species/skrell/on_species_loss(mob/living/carbon/human/H)
..()
REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species")
REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species")
@@ -196,4 +196,4 @@
#undef SLIMEPERSON_HUNGERCOST
#undef SLIMEPERSON_MINHUNGER
#undef SLIMEPERSON_REGROWTHDELAY
#undef SLIMEPERSON_REGROWTHDELAY
@@ -56,4 +56,4 @@
"is holding their breath!")
/datum/species/tajaran/handle_death(gibbed, mob/living/carbon/human/H)
H.stop_tail_wagging(1)
H.stop_tail_wagging(1)
@@ -50,4 +50,4 @@
"is holding their breath!")
/datum/species/vulpkanin/handle_death(gibbed, mob/living/carbon/human/H)
H.stop_tail_wagging(1)
H.stop_tail_wagging(1)
@@ -75,4 +75,4 @@
add_attack_logs(user, target, "Antennae removed")
return 0
else
..()
..()
File diff suppressed because it is too large Load Diff
@@ -24,4 +24,4 @@
. = dna.species.can_hear(src)
/mob/living/carbon/human/check_death_method()
return dna.species.dies_at_threshold
return dna.species.dies_at_threshold
+1 -1
View File
@@ -437,4 +437,4 @@
if(85 to INFINITY) severity = 6
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
clear_fullscreen("brute")
@@ -12,4 +12,4 @@
stam_paralyzed = TRUE
update_canmove()
if(!prev && getStaminaLoss() < 120) // Puts you a little further into the initial stamcrit, makes stamcrit harder to outright counter with chems.
adjustStaminaLoss(30, FALSE)
adjustStaminaLoss(30, FALSE)
@@ -87,4 +87,4 @@
//update whether our back item appears on our hud.
/mob/living/carbon/proc/update_hud_back(obj/item/I)
return
return
@@ -30,4 +30,4 @@
. = FALSE
var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears)
if(istype(ears) && !ears.deaf)
. = TRUE
. = TRUE
+342 -342
View File
@@ -1,342 +1,342 @@
/*
apply_damage(a,b,c)
args
a:damage - How much damage to take
b:damage_type - What type of damage to take, brute, burn
c:def_zone - Where to take the damage if its brute or burn
Returns
standard 0 if fail
*/
/mob/living/proc/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/used_weapon = null)
blocked = (100-blocked)/100
if(!damage || (blocked <= 0)) return 0
switch(damagetype)
if(BRUTE)
adjustBruteLoss(damage * blocked)
if(BURN)
adjustFireLoss(damage * blocked)
if(TOX)
adjustToxLoss(damage * blocked)
if(OXY)
adjustOxyLoss(damage * blocked)
if(CLONE)
adjustCloneLoss(damage * blocked)
if(STAMINA)
adjustStaminaLoss(damage * blocked)
updatehealth("apply damage")
return 1
/mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs
switch(damagetype)
if(BRUTE)
return adjustBruteLoss(damage)
if(BURN)
return adjustFireLoss(damage)
if(TOX)
return adjustToxLoss(damage)
if(OXY)
return adjustOxyLoss(damage)
if(CLONE)
return adjustCloneLoss(damage)
if(STAMINA)
return adjustStaminaLoss(damage)
if(BRAIN)
return adjustBrainLoss(damage)
/mob/living/proc/get_damage_amount(damagetype = BRUTE)
switch(damagetype)
if(BRUTE)
return getBruteLoss()
if(BURN)
return getFireLoss()
if(TOX)
return getToxLoss()
if(OXY)
return getOxyLoss()
if(CLONE)
return getCloneLoss()
if(STAMINA)
return getStaminaLoss()
/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/def_zone = null, var/blocked = 0, var/stamina = 0)
if(blocked >= 100) return 0
if(brute) apply_damage(brute, BRUTE, def_zone, blocked)
if(burn) apply_damage(burn, BURN, def_zone, blocked)
if(tox) apply_damage(tox, TOX, def_zone, blocked)
if(oxy) apply_damage(oxy, OXY, def_zone, blocked)
if(clone) apply_damage(clone, CLONE, def_zone, blocked)
if(stamina) apply_damage(stamina, STAMINA, def_zone, blocked)
return 1
/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0, var/negate_armor = 0)
blocked = (100-blocked)/100
if(!effect || (blocked <= 0))
return 0
switch(effecttype)
if(STUN)
Stun(effect * blocked)
if(WEAKEN)
Weaken(effect * blocked)
if(PARALYZE)
Paralyse(effect * blocked)
if(IRRADIATE)
var/rad_damage = effect
if(!negate_armor) // Setting negate_armor overrides radiation armor checks, which are automatic otherwise
rad_damage = max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)
radiation += rad_damage
if(SLUR)
Slur(effect * blocked)
if(STUTTER)
Stuttering(effect * blocked)
if(EYE_BLUR)
EyeBlurry(effect * blocked)
if(DROWSY)
Drowsy(effect * blocked)
if(JITTER)
if(status_flags & CANSTUN)
Jitter(effect * blocked)
updatehealth("apply effect")
return 1
/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/slur = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/blocked = 0, var/stamina = 0, var/jitter = 0)
if(blocked >= 100) return 0
if(stun) apply_effect(stun, STUN, blocked)
if(weaken) apply_effect(weaken, WEAKEN, blocked)
if(paralyze) apply_effect(paralyze, PARALYZE, blocked)
if(irradiate) apply_effect(irradiate, IRRADIATE, blocked)
if(slur) apply_effect(slur, SLUR, blocked)
if(stutter) apply_effect(stutter, STUTTER, blocked)
if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked)
if(drowsy) apply_effect(drowsy, DROWSY, blocked)
if(stamina) apply_damage(stamina, STAMINA, null, blocked)
if(jitter) apply_effect(jitter, JITTER, blocked)
return 1
/mob/living/proc/getBruteLoss()
return bruteloss
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_bruteloss = bruteloss
bruteloss = max(bruteloss + amount, 0)
if(old_bruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustBruteLoss")
/mob/living/proc/getOxyLoss()
return oxyloss
/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 = max(oxyloss + amount, 0)
if(old_oxyloss == oxyloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustOxyLoss")
/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)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setOxyLoss")
/mob/living/proc/getToxLoss()
return toxloss
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
toxloss = max(toxloss + amount, 0)
if(old_toxloss == toxloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustToxLoss")
/mob/living/proc/setToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
toxloss = amount
if(old_toxloss == toxloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setToxLoss")
/mob/living/proc/getFireLoss()
return fireloss
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_fireloss = fireloss
fireloss = max(fireloss + amount, 0)
if(old_fireloss == fireloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustFireLoss")
/mob/living/proc/getCloneLoss()
return cloneloss
/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_cloneloss = cloneloss
cloneloss = max(cloneloss + amount, 0)
if(old_cloneloss == cloneloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustCloneLoss")
/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)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setCloneLoss")
/mob/living/proc/getBrainLoss()
return 0
/mob/living/proc/adjustBrainLoss(amount, updating = TRUE)
return STATUS_UPDATE_NONE
/mob/living/proc/setBrainLoss(amount, updating = TRUE)
return STATUS_UPDATE_NONE
/mob/living/proc/getStaminaLoss()
return staminaloss
/mob/living/proc/adjustStaminaLoss(amount, updating = TRUE)
if(status_flags & GODMODE)
return FALSE
var/old_stamloss = staminaloss
staminaloss = min(max(staminaloss + amount, 0), 120)
if(old_stamloss == staminaloss)
updating = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_STAMINA
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
update_stamina()
/mob/living/proc/setStaminaLoss(amount, updating = TRUE)
if(status_flags & GODMODE)
return FALSE
var/old_stamloss = staminaloss
staminaloss = min(max(amount, 0), 120)
if(old_stamloss == staminaloss)
updating = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_STAMINA
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
update_stamina()
/mob/living/proc/getMaxHealth()
return maxHealth
/mob/living/proc/setMaxHealth(var/newMaxHealth)
maxHealth = newMaxHealth
// heal ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/heal_organ_damage(brute, burn, updating_health = TRUE)
adjustBruteLoss(-brute, FALSE)
adjustFireLoss(-burn, FALSE)
if(updating_health)
updatehealth("heal organ damage")
// damage ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/take_organ_damage(brute, burn, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
adjustBruteLoss(brute, FALSE)
adjustFireLoss(burn, FALSE)
if(updating_health)
updatehealth("take organ damage")
// heal MANY external organs, in random order
/mob/living/proc/heal_overall_damage(brute, burn, updating_health = TRUE)
adjustBruteLoss(-brute, FALSE)
adjustFireLoss(-burn, FALSE)
if(updating_health)
updatehealth("heal overall damage")
// damage MANY external organs, in random order
/mob/living/proc/take_overall_damage(brute, burn, updating_health = TRUE, used_weapon = null)
if(status_flags & GODMODE)
return FALSE //godmode
adjustBruteLoss(brute, FALSE)
adjustFireLoss(burn, FALSE)
if(updating_health)
updatehealth("take overall damage")
/mob/living/proc/has_organic_damage()
return (maxHealth - health)
//heal up to amount damage, in a given order
/mob/living/proc/heal_ordered_damage(amount, list/damage_types)
. = amount //we'll return the amount of damage healed
for(var/i in damage_types)
var/amount_to_heal = min(amount, get_damage_amount(i)) //heal only up to the amount of damage we have
if(amount_to_heal)
apply_damage_type(-amount_to_heal, i)
amount -= amount_to_heal //remove what we healed from our current amount
if(!amount)
break
. -= amount //if there's leftover healing, remove it from what we return
/*
apply_damage(a,b,c)
args
a:damage - How much damage to take
b:damage_type - What type of damage to take, brute, burn
c:def_zone - Where to take the damage if its brute or burn
Returns
standard 0 if fail
*/
/mob/living/proc/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/used_weapon = null)
blocked = (100-blocked)/100
if(!damage || (blocked <= 0)) return 0
switch(damagetype)
if(BRUTE)
adjustBruteLoss(damage * blocked)
if(BURN)
adjustFireLoss(damage * blocked)
if(TOX)
adjustToxLoss(damage * blocked)
if(OXY)
adjustOxyLoss(damage * blocked)
if(CLONE)
adjustCloneLoss(damage * blocked)
if(STAMINA)
adjustStaminaLoss(damage * blocked)
updatehealth("apply damage")
return 1
/mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs
switch(damagetype)
if(BRUTE)
return adjustBruteLoss(damage)
if(BURN)
return adjustFireLoss(damage)
if(TOX)
return adjustToxLoss(damage)
if(OXY)
return adjustOxyLoss(damage)
if(CLONE)
return adjustCloneLoss(damage)
if(STAMINA)
return adjustStaminaLoss(damage)
if(BRAIN)
return adjustBrainLoss(damage)
/mob/living/proc/get_damage_amount(damagetype = BRUTE)
switch(damagetype)
if(BRUTE)
return getBruteLoss()
if(BURN)
return getFireLoss()
if(TOX)
return getToxLoss()
if(OXY)
return getOxyLoss()
if(CLONE)
return getCloneLoss()
if(STAMINA)
return getStaminaLoss()
/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/def_zone = null, var/blocked = 0, var/stamina = 0)
if(blocked >= 100) return 0
if(brute) apply_damage(brute, BRUTE, def_zone, blocked)
if(burn) apply_damage(burn, BURN, def_zone, blocked)
if(tox) apply_damage(tox, TOX, def_zone, blocked)
if(oxy) apply_damage(oxy, OXY, def_zone, blocked)
if(clone) apply_damage(clone, CLONE, def_zone, blocked)
if(stamina) apply_damage(stamina, STAMINA, def_zone, blocked)
return 1
/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0, var/negate_armor = 0)
blocked = (100-blocked)/100
if(!effect || (blocked <= 0))
return 0
switch(effecttype)
if(STUN)
Stun(effect * blocked)
if(WEAKEN)
Weaken(effect * blocked)
if(PARALYZE)
Paralyse(effect * blocked)
if(IRRADIATE)
var/rad_damage = effect
if(!negate_armor) // Setting negate_armor overrides radiation armor checks, which are automatic otherwise
rad_damage = max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)
radiation += rad_damage
if(SLUR)
Slur(effect * blocked)
if(STUTTER)
Stuttering(effect * blocked)
if(EYE_BLUR)
EyeBlurry(effect * blocked)
if(DROWSY)
Drowsy(effect * blocked)
if(JITTER)
if(status_flags & CANSTUN)
Jitter(effect * blocked)
updatehealth("apply effect")
return 1
/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/slur = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/blocked = 0, var/stamina = 0, var/jitter = 0)
if(blocked >= 100) return 0
if(stun) apply_effect(stun, STUN, blocked)
if(weaken) apply_effect(weaken, WEAKEN, blocked)
if(paralyze) apply_effect(paralyze, PARALYZE, blocked)
if(irradiate) apply_effect(irradiate, IRRADIATE, blocked)
if(slur) apply_effect(slur, SLUR, blocked)
if(stutter) apply_effect(stutter, STUTTER, blocked)
if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked)
if(drowsy) apply_effect(drowsy, DROWSY, blocked)
if(stamina) apply_damage(stamina, STAMINA, null, blocked)
if(jitter) apply_effect(jitter, JITTER, blocked)
return 1
/mob/living/proc/getBruteLoss()
return bruteloss
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_bruteloss = bruteloss
bruteloss = max(bruteloss + amount, 0)
if(old_bruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustBruteLoss")
/mob/living/proc/getOxyLoss()
return oxyloss
/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 = max(oxyloss + amount, 0)
if(old_oxyloss == oxyloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustOxyLoss")
/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)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setOxyLoss")
/mob/living/proc/getToxLoss()
return toxloss
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
toxloss = max(toxloss + amount, 0)
if(old_toxloss == toxloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustToxLoss")
/mob/living/proc/setToxLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_toxloss = toxloss
toxloss = amount
if(old_toxloss == toxloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setToxLoss")
/mob/living/proc/getFireLoss()
return fireloss
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_fireloss = fireloss
fireloss = max(fireloss + amount, 0)
if(old_fireloss == fireloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustFireLoss")
/mob/living/proc/getCloneLoss()
return cloneloss
/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
var/old_cloneloss = cloneloss
cloneloss = max(cloneloss + amount, 0)
if(old_cloneloss == cloneloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("adjustCloneLoss")
/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)
updating_health = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth("setCloneLoss")
/mob/living/proc/getBrainLoss()
return 0
/mob/living/proc/adjustBrainLoss(amount, updating = TRUE)
return STATUS_UPDATE_NONE
/mob/living/proc/setBrainLoss(amount, updating = TRUE)
return STATUS_UPDATE_NONE
/mob/living/proc/getStaminaLoss()
return staminaloss
/mob/living/proc/adjustStaminaLoss(amount, updating = TRUE)
if(status_flags & GODMODE)
return FALSE
var/old_stamloss = staminaloss
staminaloss = min(max(staminaloss + amount, 0), 120)
if(old_stamloss == staminaloss)
updating = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_STAMINA
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
update_stamina()
/mob/living/proc/setStaminaLoss(amount, updating = TRUE)
if(status_flags & GODMODE)
return FALSE
var/old_stamloss = staminaloss
staminaloss = min(max(amount, 0), 120)
if(old_stamloss == staminaloss)
updating = FALSE
. = STATUS_UPDATE_NONE
else
. = STATUS_UPDATE_STAMINA
if(amount > 0)
stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME
if(updating)
update_stamina()
/mob/living/proc/getMaxHealth()
return maxHealth
/mob/living/proc/setMaxHealth(var/newMaxHealth)
maxHealth = newMaxHealth
// heal ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/heal_organ_damage(brute, burn, updating_health = TRUE)
adjustBruteLoss(-brute, FALSE)
adjustFireLoss(-burn, FALSE)
if(updating_health)
updatehealth("heal organ damage")
// damage ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/take_organ_damage(brute, burn, updating_health = TRUE)
if(status_flags & GODMODE)
return FALSE //godmode
adjustBruteLoss(brute, FALSE)
adjustFireLoss(burn, FALSE)
if(updating_health)
updatehealth("take organ damage")
// heal MANY external organs, in random order
/mob/living/proc/heal_overall_damage(brute, burn, updating_health = TRUE)
adjustBruteLoss(-brute, FALSE)
adjustFireLoss(-burn, FALSE)
if(updating_health)
updatehealth("heal overall damage")
// damage MANY external organs, in random order
/mob/living/proc/take_overall_damage(brute, burn, updating_health = TRUE, used_weapon = null)
if(status_flags & GODMODE)
return FALSE //godmode
adjustBruteLoss(brute, FALSE)
adjustFireLoss(burn, FALSE)
if(updating_health)
updatehealth("take overall damage")
/mob/living/proc/has_organic_damage()
return (maxHealth - health)
//heal up to amount damage, in a given order
/mob/living/proc/heal_ordered_damage(amount, list/damage_types)
. = amount //we'll return the amount of damage healed
for(var/i in damage_types)
var/amount_to_heal = min(amount, get_damage_amount(i)) //heal only up to the amount of damage we have
if(amount_to_heal)
apply_damage_type(-amount_to_heal, i)
amount -= amount_to_heal //remove what we healed from our current amount
if(!amount)
break
. -= amount //if there's leftover healing, remove it from what we return
+1 -1
View File
@@ -100,4 +100,4 @@
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))
addtimer(CALLBACK(src, .proc/gib), rand(20, 100))
+1 -1
View File
@@ -220,4 +220,4 @@
return
/mob/living/proc/handle_hud_icons_health()
return
return
+360 -360
View File
@@ -1,360 +1,360 @@
/*
run_armor_check(a,b)
args
a:def_zone - What part is getting hit, if null will check entire body
b:attack_flag - What type of attack, bullet, laser, energy, melee
Returns
0 - no block
1 - halfblock
2 - fullblock
*/
/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/absorb_text = null, var/soften_text = null, armour_penetration, penetrated_text)
var/armor = getarmor(def_zone, attack_flag)
//the if "armor" check is because this is used for everything on /living, including humans
if(armor && armor < 100 && armour_penetration) // Armor with 100+ protection can not be penetrated for admin items
armor = max(0, armor - armour_penetration)
if(penetrated_text)
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
if(armor >= 100)
if(absorb_text)
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
else if(armor > 0)
if(soften_text)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
return armor
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
/mob/living/proc/getarmor(var/def_zone, var/type)
return 0
/mob/living/proc/is_mouth_covered(head_only = FALSE, mask_only = FALSE)
return FALSE
/mob/living/proc/is_eyes_covered(check_glasses = TRUE, check_head = TRUE, check_mask = TRUE)
return FALSE
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
//Armor
var/armor = run_armor_check(def_zone, P.flag, armour_penetration = P.armour_penetration)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
return P.on_hit(src, armor, def_zone)
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
return 0
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage)
if(status_flags & GODMODE) //godmode
return FALSE
if(NO_SHOCK in mutations) //shockproof
return FALSE
if(tesla_shock && tesla_ignore)
return FALSE
if(shock_damage > 0)
if(!illusion)
adjustFireLoss(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>",
"<span class='italics'>You hear a heavy electrical crack.</span>")
return shock_damage
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, zone)
dtype = I.damtype
if(I.throwforce > 0) //If the weapon's throwforce is greater than zero...
if(I.throwhitsound) //...and throwhitsound is defined...
playsound(loc, I.throwhitsound, volume, TRUE, -1) //...play the weapon's throwhitsound.
else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, I.hitsound, volume, TRUE, -1) //...play the weapon's hitsound.
else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, TRUE, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit1.ogg', volume, 1, -1)//...play genhit1.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>",
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, is_sharp(I), I)
if(I.thrownby)
add_attack_logs(I.thrownby, src, "Hit with thrown [I]")
else
return 1
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1)
..()
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
if(HAS_TRAIT(M.occupant, TRAIT_PACIFISM))
to_chat(M.occupant, "<span class='warning'>You don't want to harm other living beings!</span>")
return
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
switch(M.damtype)
if("brute")
Paralyse(1)
take_overall_damage(rand(M.force/2, M.force))
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
if("fire")
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
if("tox")
M.mech_toxin_damage(src)
else
return
updatehealth("mech melee attack")
M.occupant_message("<span class='danger'>You hit [src].</span>")
visible_message("<span class='danger'>[M.name] hits [src]!</span>", "<span class='userdanger'>[M.name] hits you!</span>")
add_attack_logs(M.occupant, src, "Mecha-meleed with [M]")
else
step_away(src,M)
add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", ATKLOG_ALL)
M.occupant_message("<span class='warning'>You push [src] out of the way.</span>")
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>")
//Mobs on Fire
/mob/living/proc/IgniteMob()
if(fire_stacks > 0 && !on_fire)
on_fire = 1
visible_message("<span class='warning'>[src] catches fire!</span>", \
"<span class='userdanger'>You're set on fire!</span>")
set_light(light_range + 3,l_color = "#ED9200")
throw_alert("fire", /obj/screen/alert/fire)
update_fire()
return 1
return 0
/mob/living/proc/ExtinguishMob()
if(on_fire)
on_fire = 0
fire_stacks = 0
set_light(max(0,light_range - 3))
clear_alert("fire")
update_fire()
/mob/living/proc/update_fire()
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
/mob/living/proc/handle_fire()
if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly
fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable.
if(!on_fire)
return 1
if(fire_stacks > 0)
adjust_fire_stacks(-0.1) //the fire is slowly consumed
else
ExtinguishMob()
return
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G.oxygen < 1)
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
adjust_fire_stacks(3)
IgniteMob()
//Share fire evenly between the two mobs
//Called in MobBump() and Crossed()
/mob/living/proc/spreadFire(mob/living/L)
if(!istype(L))
return
var/L_old_on_fire = L.on_fire
if(on_fire) //Only spread fire stacks if we're on fire
fire_stacks /= 2
L.fire_stacks += fire_stacks
if(L.IgniteMob())
log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire")
if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them
L.fire_stacks /= 2
fire_stacks += L.fire_stacks
IgniteMob()
/mob/living/can_be_pulled(user, grab_state, force)
return ..() && !(buckled && buckled.buckle_prevents_pull)
/mob/living/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
adjust_fire_stacks(-(volume * 0.2))
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
src.take_organ_damage(speed*5)
/mob/living/proc/near_wall(var/direction,var/distance=1)
var/turf/T = get_step(get_turf(src),direction)
var/turf/last_turf = src.loc
var/i = 1
while(i>0 && i<=distance)
if(T.density) //Turf is a wall!
return last_turf
i++
last_turf = T
T = get_step(T,direction)
return 0
// End BS12 momentum-transfer code.
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE)
if(user == src || anchored)
return 0
if(!(status_flags & CANPUSH))
return 0
for(var/obj/item/grab/G in grabbed_by)
if(G.assailant == user)
to_chat(user, "<span class='notice'>You already grabbed [src].</span>")
return
add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL)
var/obj/item/grab/G = new /obj/item/grab(user, src)
if(buckled)
to_chat(user, "<span class='notice'>You cannot grab [src]; [p_they()] [p_are()] buckled in!</span>")
if(!G) //the grab will delete itself in New if src is anchored
return 0
user.put_in_active_hand(G)
G.synch()
LAssailant = user
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/*if(user.dir == src.dir)
G.state = GRAB_AGGRESSIVE
G.last_upgrade = world.time
if(!supress_message)
visible_message("<span class='warning'>[user] has grabbed [src] from behind!</span>")
else*///This is an example of how you can make special types of grabs simply based on direction.
if(!supress_message)
visible_message("<span class='warning'>[user] has grabbed [src] passively!</span>")
return G
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
if(stat != DEAD)
add_attack_logs(M, src, "Slime'd")
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M.name] glomps [src]!</span>", "<span class='userdanger'>\The [M.name] glomps you!</span>")
return TRUE
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if((M.a_intent == INTENT_HELP && M.ckey) || M.melee_damage_upper == 0)
M.custom_emote(1, "[M.friendly] [src].")
return FALSE
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>")
add_attack_logs(M, src, "Animal attacked")
return TRUE
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if(INTENT_HELP)
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return 0
else
if(HAS_TRAIT(L, TRAIT_PACIFISM))
to_chat(L, "<span class='warning'>You don't want to hurt anyone!</span>")
return
L.do_attack_animation(src)
if(prob(90))
add_attack_logs(L, src, "Larva attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
return 1
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>")
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
switch(M.a_intent)
if(INTENT_HELP)
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return FALSE
if(INTENT_GRAB)
grabbedby(M)
return FALSE
if(INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
M.do_attack_animation(src)
return TRUE
if(INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return TRUE
/*
run_armor_check(a,b)
args
a:def_zone - What part is getting hit, if null will check entire body
b:attack_flag - What type of attack, bullet, laser, energy, melee
Returns
0 - no block
1 - halfblock
2 - fullblock
*/
/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/absorb_text = null, var/soften_text = null, armour_penetration, penetrated_text)
var/armor = getarmor(def_zone, attack_flag)
//the if "armor" check is because this is used for everything on /living, including humans
if(armor && armor < 100 && armour_penetration) // Armor with 100+ protection can not be penetrated for admin items
armor = max(0, armor - armour_penetration)
if(penetrated_text)
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
if(armor >= 100)
if(absorb_text)
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
else if(armor > 0)
if(soften_text)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
return armor
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
/mob/living/proc/getarmor(var/def_zone, var/type)
return 0
/mob/living/proc/is_mouth_covered(head_only = FALSE, mask_only = FALSE)
return FALSE
/mob/living/proc/is_eyes_covered(check_glasses = TRUE, check_head = TRUE, check_mask = TRUE)
return FALSE
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
//Armor
var/armor = run_armor_check(def_zone, P.flag, armour_penetration = P.armour_penetration)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
return P.on_hit(src, armor, def_zone)
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
return 0
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage)
if(status_flags & GODMODE) //godmode
return FALSE
if(NO_SHOCK in mutations) //shockproof
return FALSE
if(tesla_shock && tesla_ignore)
return FALSE
if(shock_damage > 0)
if(!illusion)
adjustFireLoss(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>",
"<span class='italics'>You hear a heavy electrical crack.</span>")
return shock_damage
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, zone)
dtype = I.damtype
if(I.throwforce > 0) //If the weapon's throwforce is greater than zero...
if(I.throwhitsound) //...and throwhitsound is defined...
playsound(loc, I.throwhitsound, volume, TRUE, -1) //...play the weapon's throwhitsound.
else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, I.hitsound, volume, TRUE, -1) //...play the weapon's hitsound.
else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, TRUE, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit1.ogg', volume, 1, -1)//...play genhit1.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>",
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, is_sharp(I), I)
if(I.thrownby)
add_attack_logs(I.thrownby, src, "Hit with thrown [I]")
else
return 1
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1)
..()
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
if(HAS_TRAIT(M.occupant, TRAIT_PACIFISM))
to_chat(M.occupant, "<span class='warning'>You don't want to harm other living beings!</span>")
return
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
switch(M.damtype)
if("brute")
Paralyse(1)
take_overall_damage(rand(M.force/2, M.force))
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
if("fire")
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
if("tox")
M.mech_toxin_damage(src)
else
return
updatehealth("mech melee attack")
M.occupant_message("<span class='danger'>You hit [src].</span>")
visible_message("<span class='danger'>[M.name] hits [src]!</span>", "<span class='userdanger'>[M.name] hits you!</span>")
add_attack_logs(M.occupant, src, "Mecha-meleed with [M]")
else
step_away(src,M)
add_attack_logs(M.occupant, src, "Mecha-pushed with [M]", ATKLOG_ALL)
M.occupant_message("<span class='warning'>You push [src] out of the way.</span>")
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>")
//Mobs on Fire
/mob/living/proc/IgniteMob()
if(fire_stacks > 0 && !on_fire)
on_fire = 1
visible_message("<span class='warning'>[src] catches fire!</span>", \
"<span class='userdanger'>You're set on fire!</span>")
set_light(light_range + 3,l_color = "#ED9200")
throw_alert("fire", /obj/screen/alert/fire)
update_fire()
return 1
return 0
/mob/living/proc/ExtinguishMob()
if(on_fire)
on_fire = 0
fire_stacks = 0
set_light(max(0,light_range - 3))
clear_alert("fire")
update_fire()
/mob/living/proc/update_fire()
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
/mob/living/proc/handle_fire()
if(fire_stacks < 0) //If we've doused ourselves in water to avoid fire, dry off slowly
fire_stacks = min(0, fire_stacks + 1)//So we dry ourselves back to default, nonflammable.
if(!on_fire)
return 1
if(fire_stacks > 0)
adjust_fire_stacks(-0.1) //the fire is slowly consumed
else
ExtinguishMob()
return
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G.oxygen < 1)
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
adjust_fire_stacks(3)
IgniteMob()
//Share fire evenly between the two mobs
//Called in MobBump() and Crossed()
/mob/living/proc/spreadFire(mob/living/L)
if(!istype(L))
return
var/L_old_on_fire = L.on_fire
if(on_fire) //Only spread fire stacks if we're on fire
fire_stacks /= 2
L.fire_stacks += fire_stacks
if(L.IgniteMob())
log_game("[key_name(src)] bumped into [key_name(L)] and set them on fire")
if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them
L.fire_stacks /= 2
fire_stacks += L.fire_stacks
IgniteMob()
/mob/living/can_be_pulled(user, grab_state, force)
return ..() && !(buckled && buckled.buckle_prevents_pull)
/mob/living/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
adjust_fire_stacks(-(volume * 0.2))
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
src.take_organ_damage(speed*5)
/mob/living/proc/near_wall(var/direction,var/distance=1)
var/turf/T = get_step(get_turf(src),direction)
var/turf/last_turf = src.loc
var/i = 1
while(i>0 && i<=distance)
if(T.density) //Turf is a wall!
return last_turf
i++
last_turf = T
T = get_step(T,direction)
return 0
// End BS12 momentum-transfer code.
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE)
if(user == src || anchored)
return 0
if(!(status_flags & CANPUSH))
return 0
for(var/obj/item/grab/G in grabbed_by)
if(G.assailant == user)
to_chat(user, "<span class='notice'>You already grabbed [src].</span>")
return
add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL)
var/obj/item/grab/G = new /obj/item/grab(user, src)
if(buckled)
to_chat(user, "<span class='notice'>You cannot grab [src]; [p_they()] [p_are()] buckled in!</span>")
if(!G) //the grab will delete itself in New if src is anchored
return 0
user.put_in_active_hand(G)
G.synch()
LAssailant = user
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/*if(user.dir == src.dir)
G.state = GRAB_AGGRESSIVE
G.last_upgrade = world.time
if(!supress_message)
visible_message("<span class='warning'>[user] has grabbed [src] from behind!</span>")
else*///This is an example of how you can make special types of grabs simply based on direction.
if(!supress_message)
visible_message("<span class='warning'>[user] has grabbed [src] passively!</span>")
return G
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
if(stat != DEAD)
add_attack_logs(M, src, "Slime'd")
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M.name] glomps [src]!</span>", "<span class='userdanger'>\The [M.name] glomps you!</span>")
return TRUE
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if((M.a_intent == INTENT_HELP && M.ckey) || M.melee_damage_upper == 0)
M.custom_emote(1, "[M.friendly] [src].")
return FALSE
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>")
add_attack_logs(M, src, "Animal attacked")
return TRUE
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if(INTENT_HELP)
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return 0
else
if(HAS_TRAIT(L, TRAIT_PACIFISM))
to_chat(L, "<span class='warning'>You don't want to hurt anyone!</span>")
return
L.do_attack_animation(src)
if(prob(90))
add_attack_logs(L, src, "Larva attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
return 1
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>")
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
switch(M.a_intent)
if(INTENT_HELP)
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return FALSE
if(INTENT_GRAB)
grabbedby(M)
return FALSE
if(INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='warning'>You don't want to hurt anyone!</span>")
return FALSE
M.do_attack_animation(src)
return TRUE
if(INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return TRUE
+74 -74
View File
@@ -1,74 +1,74 @@
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
pressure_resistance = 10
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
var/health = 100 //A mob's health
//Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS
var/bruteloss = 0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage)
var/oxyloss = 0 //Oxygen depravation damage (no air in lungs)
var/toxloss = 0 //Toxic damage caused by being poisoned or radiated
var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt.
var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are stunned if it gets too high. Holodeck and hallucinations deal this.
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.
var/now_pushing = null
var/atom/movable/cameraFollow = null
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
var/implanting = 0 //Used for the mind-slave implant
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/digestion_ratio = 1 //controls how quickly reagents metabolize; largely governered by species attributes.
var/bloodcrawl = 0 //0 No blood crawling, 1 blood crawling, 2 blood crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
var/list/icon/pipes_shown = list()
var/last_played_vent
var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob.
var/step_count = 0
var/list/butcher_results = null
var/list/weather_immunities = list()
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
var/gene_stability = DEFAULT_GENE_STABILITY
var/ignore_gene_stability = 0
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
var/tesla_ignore = FALSE
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
var/list/emote_log = list() //like say_log but for emotes
var/list/recent_tastes = list()
var/blood_volume = 0 //how much blood the mob has
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
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
var/stam_regen_start_time = 0 //used to halt stamina regen temporarily
var/stam_paralyzed = FALSE //knocks you down
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
pressure_resistance = 10
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
var/health = 100 //A mob's health
//Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS
var/bruteloss = 0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage)
var/oxyloss = 0 //Oxygen depravation damage (no air in lungs)
var/toxloss = 0 //Toxic damage caused by being poisoned or radiated
var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt.
var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are stunned if it gets too high. Holodeck and hallucinations deal this.
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.
var/now_pushing = null
var/atom/movable/cameraFollow = null
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
var/implanting = 0 //Used for the mind-slave implant
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/digestion_ratio = 1 //controls how quickly reagents metabolize; largely governered by species attributes.
var/bloodcrawl = 0 //0 No blood crawling, 1 blood crawling, 2 blood crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
var/list/icon/pipes_shown = list()
var/last_played_vent
var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob.
var/step_count = 0
var/list/butcher_results = null
var/list/weather_immunities = list()
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
var/gene_stability = DEFAULT_GENE_STABILITY
var/ignore_gene_stability = 0
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
var/tesla_ignore = FALSE
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
var/list/emote_log = list() //like say_log but for emotes
var/list/recent_tastes = list()
var/blood_volume = 0 //how much blood the mob has
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
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
var/stam_regen_start_time = 0 //used to halt stamina regen temporarily
var/stam_paralyzed = FALSE //knocks you down
+13 -13
View File
@@ -1,13 +1,13 @@
/mob/living/Logout()
update_z(null)
if(ranged_ability && client)
ranged_ability.remove_mousepointer(client)
..()
if(mind)
if(!key) //key and mind have become seperated. I believe this is for when a staff member aghosts.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
//This causes instant sleep and tags a player as SSD. See life.dm for furthering SSD.
if(mind.active)
Sleeping(2)
player_logged = 1
last_logout = world.time
/mob/living/Logout()
update_z(null)
if(ranged_ability && client)
ranged_ability.remove_mousepointer(client)
..()
if(mind)
if(!key) //key and mind have become seperated. I believe this is for when a staff member aghosts.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
//This causes instant sleep and tags a player as SSD. See life.dm for furthering SSD.
if(mind.active)
Sleeping(2)
player_logged = 1
last_logout = world.time
+475 -475
View File
@@ -1,475 +1,475 @@
var/list/department_radio_keys = list(
":r" = "right ear", "#r" = "right ear", ".r" = "right ear",
":l" = "left ear", "#l" = "left ear", ".l" = "left ear",
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
":h" = "department", "#h" = "department", ".h" = "department",
":+" = "special", "#+" = "special", ".+" = "special", //activate radio-specific special functions
":c" = "Command", "#c" = "Command", ".c" = "Command",
":n" = "Science", "#n" = "Science", ".n" = "Science",
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
":s" = "Security", "#s" = "Security", ".s" = "Security",
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
":z" = "Service", "#z" = "Service", ".z" = "Service",
":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private",
":x" = "cords", "#x" = "cords", ".x" = "cords",
":R" = "right ear", "#R" = "right ear", ".R" = "right ear",
":L" = "left ear", "#L" = "left ear", ".L" = "left ear",
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
":H" = "department", "#H" = "department", ".H" = "department",
":C" = "Command", "#C" = "Command", ".C" = "Command",
":N" = "Science", "#N" = "Science", ".N" = "Science",
":M" = "Medical", "#M" = "Medical", ".M" = "Medical",
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
":S" = "Security", "#S" = "Security", ".S" = "Security",
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":Z" = "Service", "#Z" = "Service", ".Z" = "Service",
":P" = "AI Private", "#P" = "AI Private", ".P" = "AI Private",
":$" = "Response Team", "#$" = "Response Team", ".$" = "Response Team",
":-" = "Special Ops", "#-" = "Special Ops", ".-" = "Special Ops",
":_" = "SyndTeam", "#_" = "SyndTeam", "._" = "SyndTeam",
":X" = "cords", "#X" = "cords", ".X" = "cords"
)
var/list/channel_to_radio_key = new
proc/get_radio_key_from_channel(var/channel)
var/key = channel_to_radio_key[channel]
if(!key)
for(var/radio_key in department_radio_keys)
if(department_radio_keys[radio_key] == channel)
key = radio_key
break
if(!key)
key = ""
channel_to_radio_key[channel] = key
return key
/mob/living/proc/binarycheck()
return FALSE
/mob/proc/get_default_language()
return null
/mob/living/get_default_language()
return default_language
/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(slurring)
if(robot)
S.message = slur(S.message, list("@", "!", "#", "$", "%", "&", "?"))
else
S.message = slur(S.message)
verb = "slurs"
if(stuttering)
if(robot)
S.message = robostutter(S.message)
else
S.message = stutter(S.message)
verb = "stammers"
if(cultslurring)
S.message = cultslur(S.message)
verb = "slurs"
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_pieces)
return 1
return 0
/mob/living/proc/handle_speech_sound()
var/list/returns[3]
returns[1] = null
returns[2] = null
returns[3] = null
return returns
/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>")
return
if(sanitize)
message = trim_strip_html_properly(message)
if(stat)
if(stat == DEAD)
return say_dead(message)
return
var/message_mode = parse_message_mode(message, "headset")
if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2))
//parse the radio code and consume it
if(message_mode)
if(message_mode == "headset")
message = copytext(message, 2) //it would be really nice if the parse procs could do this for us.
else
message = copytext(message, 3)
message = trim_left(message)
//parse the language code and consume it
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
var/obj/item/organ/internal/vocal_cords/V = C.get_int_organ(/obj/item/organ/internal/vocal_cords)
if(V && V.can_speak_with())
C.say(V.handle_speech(message), sanitize = FALSE, ignore_speech_problems = TRUE, ignore_atmospherics = TRUE)
V.speak_with(message) //words come before actions
return 1
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
if(G.mute == MUZZLE_MUTE_ALL) //if the mask is supposed to mute you completely or just muffle you
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
else if(G.mute == MUZZLE_MUTE_MUFFLE)
muffledspeech_all(message_pieces)
verb = "mumbles"
if(!ignore_speech_problems)
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
var/list/used_radios = list()
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]
var/sound_frequency = handle_v[3]
var/italics = 0
var/message_range = world.view
//speaking into radios
if(used_radios.len)
italics = 1
message_range = 1
if(first_piece.speaking)
message_range = first_piece.speaking.get_talkinto_msg_range(message)
var/msg
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)
M.show_message(msg)
if(speech_sound)
sound_vol *= 0.5
var/turf/T = get_turf(src)
var/list/listening = list()
var/list/listening_obj = list()
if(T)
//make sure the air can transmit speech - speaker's side
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment ? environment.return_pressure() : 0
if(!ignore_atmospherics)
if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = TRUE
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
var/list/hear = hear(message_range, T)
var/list/hearturfs = list()
for(var/I in hear)
if(ismob(I))
var/mob/M = I
listening += M
hearturfs += get_turf(M)
for(var/obj/O in M.contents)
listening_obj |= O
if(isobj(I))
var/obj/O = I
hearturfs += get_turf(O)
listening_obj |= O
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(isnewplayer(M))
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS) && client) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
if(message_range < world.view && (get_dist(T, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
var/list/speech_bubble_recipients = list()
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
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_pieces, verb)
//Log of what we've said, plain message, no spans or junk
say_log += message
log_say(message, src)
return 1
/obj/effect/speech_bubble
var/mob/parent
/mob/living/proc/GetVoice()
return name
/mob/living/emote(act, type, message, force) //emote code is terrible, this is so that anything that isn't already snowflaked to shit can call the parent and handle emoting sanely
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
if(stat)
return 0
if(..())
return 1
if(act && type && message) //parent call
log_emote(message, src)
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client)
continue //skip monkeys and leavers
if(isnewplayer(M))
continue
if(isobserver(M) && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
M.show_message(message)
switch(type)
if(1) //Visible
visible_message(message)
return 1
if(2) //Audible
audible_message(message)
return 1
else //everything else failed, emote is probably invalid
if(act == "help")
return //except help, because help is handled individually
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
/mob/living/whisper(message as text)
message = trim_strip_html_properly(message)
//parse the language code and consume it
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
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(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>")
return
if(stat)
if(stat == DEAD)
return say_dead(message_pieces)
return
if(is_muzzled())
if(istype(wear_mask, /obj/item/clothing/mask/muzzle/tapegag)) //just for tape
to_chat(src, "<span class='danger'>Your mouth is taped and you cannot speak!</span>")
else
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
var/message = multilingual_to_message(message_pieces)
say_log += "whisper: [message]"
log_whisper(message, 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
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 = "[first_piece.speaking.speech_verb] [adverb]"
not_heard = "[first_piece.speaking.speech_verb] something [adverb]"
else
not_heard = "[verb] something"
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
if(verb == "yells loudly")
verb = "slurs emphatically"
else if(!adverb_added)
var/adverb = pick("quietly", "softly")
verb = "[verb] [adverb]"
var/atom/whisper_loc = get_whisper_loc()
var/list/listening = hear(message_range, whisper_loc)
listening |= src
var/list/hearturfs = list()
// Pass whispers on to anything inside the immediate listeners.
// This comes before the ghosts do so that ghosts don't act as whisper relays
for(var/atom/L in listening)
if(ismob(L))
for(var/mob/C in L.contents)
if(isliving(C))
listening += C
hearturfs += get_turf(L)
if(isobj(L))
hearturfs += get_turf(L)
// Loop through all players to see if they need to hear it.
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(isnewplayer(M))
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS)) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
if(message_range < world.view && (get_dist(whisper_loc, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
//pass on the message to objects that can hear us.
for(var/obj/O in view(message_range, whisper_loc))
spawn(0)
if(O)
O.hear_talk(src, message_pieces, verb)
var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc)
eavesdropping -= src
eavesdropping -= listening
var/list/watching = hearers(watching_range, whisper_loc)
watching -= src
watching -= listening
watching -= eavesdropping
//now mobs
var/list/speech_bubble_recipients = list()
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
if(eavesdropping.len)
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(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, speech_bubble_recipients, 30)
if(watching.len)
var/rendered = "<span class='game say'><span class='name'>[name]</span> [not_heard].</span>"
for(var/mob/M in watching)
M.show_message(rendered, 2)
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, bubble_recipients, 30)
var/list/department_radio_keys = list(
":r" = "right ear", "#r" = "right ear", ".r" = "right ear",
":l" = "left ear", "#l" = "left ear", ".l" = "left ear",
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
":h" = "department", "#h" = "department", ".h" = "department",
":+" = "special", "#+" = "special", ".+" = "special", //activate radio-specific special functions
":c" = "Command", "#c" = "Command", ".c" = "Command",
":n" = "Science", "#n" = "Science", ".n" = "Science",
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
":s" = "Security", "#s" = "Security", ".s" = "Security",
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
":z" = "Service", "#z" = "Service", ".z" = "Service",
":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private",
":x" = "cords", "#x" = "cords", ".x" = "cords",
":R" = "right ear", "#R" = "right ear", ".R" = "right ear",
":L" = "left ear", "#L" = "left ear", ".L" = "left ear",
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
":H" = "department", "#H" = "department", ".H" = "department",
":C" = "Command", "#C" = "Command", ".C" = "Command",
":N" = "Science", "#N" = "Science", ".N" = "Science",
":M" = "Medical", "#M" = "Medical", ".M" = "Medical",
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
":S" = "Security", "#S" = "Security", ".S" = "Security",
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":Z" = "Service", "#Z" = "Service", ".Z" = "Service",
":P" = "AI Private", "#P" = "AI Private", ".P" = "AI Private",
":$" = "Response Team", "#$" = "Response Team", ".$" = "Response Team",
":-" = "Special Ops", "#-" = "Special Ops", ".-" = "Special Ops",
":_" = "SyndTeam", "#_" = "SyndTeam", "._" = "SyndTeam",
":X" = "cords", "#X" = "cords", ".X" = "cords"
)
var/list/channel_to_radio_key = new
proc/get_radio_key_from_channel(var/channel)
var/key = channel_to_radio_key[channel]
if(!key)
for(var/radio_key in department_radio_keys)
if(department_radio_keys[radio_key] == channel)
key = radio_key
break
if(!key)
key = ""
channel_to_radio_key[channel] = key
return key
/mob/living/proc/binarycheck()
return FALSE
/mob/proc/get_default_language()
return null
/mob/living/get_default_language()
return default_language
/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(slurring)
if(robot)
S.message = slur(S.message, list("@", "!", "#", "$", "%", "&", "?"))
else
S.message = slur(S.message)
verb = "slurs"
if(stuttering)
if(robot)
S.message = robostutter(S.message)
else
S.message = stutter(S.message)
verb = "stammers"
if(cultslurring)
S.message = cultslur(S.message)
verb = "slurs"
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_pieces)
return 1
return 0
/mob/living/proc/handle_speech_sound()
var/list/returns[3]
returns[1] = null
returns[2] = null
returns[3] = null
return returns
/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>")
return
if(sanitize)
message = trim_strip_html_properly(message)
if(stat)
if(stat == DEAD)
return say_dead(message)
return
var/message_mode = parse_message_mode(message, "headset")
if(copytext(message, 1, 2) == "*")
return emote(copytext(message, 2))
//parse the radio code and consume it
if(message_mode)
if(message_mode == "headset")
message = copytext(message, 2) //it would be really nice if the parse procs could do this for us.
else
message = copytext(message, 3)
message = trim_left(message)
//parse the language code and consume it
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
var/obj/item/organ/internal/vocal_cords/V = C.get_int_organ(/obj/item/organ/internal/vocal_cords)
if(V && V.can_speak_with())
C.say(V.handle_speech(message), sanitize = FALSE, ignore_speech_problems = TRUE, ignore_atmospherics = TRUE)
V.speak_with(message) //words come before actions
return 1
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
if(G.mute == MUZZLE_MUTE_ALL) //if the mask is supposed to mute you completely or just muffle you
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
else if(G.mute == MUZZLE_MUTE_MUFFLE)
muffledspeech_all(message_pieces)
verb = "mumbles"
if(!ignore_speech_problems)
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
var/list/used_radios = list()
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]
var/sound_frequency = handle_v[3]
var/italics = 0
var/message_range = world.view
//speaking into radios
if(used_radios.len)
italics = 1
message_range = 1
if(first_piece.speaking)
message_range = first_piece.speaking.get_talkinto_msg_range(message)
var/msg
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)
M.show_message(msg)
if(speech_sound)
sound_vol *= 0.5
var/turf/T = get_turf(src)
var/list/listening = list()
var/list/listening_obj = list()
if(T)
//make sure the air can transmit speech - speaker's side
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment ? environment.return_pressure() : 0
if(!ignore_atmospherics)
if(pressure < SOUND_MINIMUM_PRESSURE)
message_range = 1
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = TRUE
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
var/list/hear = hear(message_range, T)
var/list/hearturfs = list()
for(var/I in hear)
if(ismob(I))
var/mob/M = I
listening += M
hearturfs += get_turf(M)
for(var/obj/O in M.contents)
listening_obj |= O
if(isobj(I))
var/obj/O = I
hearturfs += get_turf(O)
listening_obj |= O
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(isnewplayer(M))
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS) && client) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
if(message_range < world.view && (get_dist(T, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
var/list/speech_bubble_recipients = list()
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
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_pieces, verb)
//Log of what we've said, plain message, no spans or junk
say_log += message
log_say(message, src)
return 1
/obj/effect/speech_bubble
var/mob/parent
/mob/living/proc/GetVoice()
return name
/mob/living/emote(act, type, message, force) //emote code is terrible, this is so that anything that isn't already snowflaked to shit can call the parent and handle emoting sanely
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
if(stat)
return 0
if(..())
return 1
if(act && type && message) //parent call
log_emote(message, src)
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client)
continue //skip monkeys and leavers
if(isnewplayer(M))
continue
if(isobserver(M) && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
M.show_message(message)
switch(type)
if(1) //Visible
visible_message(message)
return 1
if(2) //Audible
audible_message(message)
return 1
else //everything else failed, emote is probably invalid
if(act == "help")
return //except help, because help is handled individually
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
/mob/living/whisper(message as text)
message = trim_strip_html_properly(message)
//parse the language code and consume it
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
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(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>")
return
if(stat)
if(stat == DEAD)
return say_dead(message_pieces)
return
if(is_muzzled())
if(istype(wear_mask, /obj/item/clothing/mask/muzzle/tapegag)) //just for tape
to_chat(src, "<span class='danger'>Your mouth is taped and you cannot speak!</span>")
else
to_chat(src, "<span class='danger'>You're muzzled and cannot speak!</span>")
return
var/message = multilingual_to_message(message_pieces)
say_log += "whisper: [message]"
log_whisper(message, 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
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 = "[first_piece.speaking.speech_verb] [adverb]"
not_heard = "[first_piece.speaking.speech_verb] something [adverb]"
else
not_heard = "[verb] something"
var/list/hsp = handle_speech_problems(message_pieces, verb)
verb = hsp["verb"]
if(verb == "yells loudly")
verb = "slurs emphatically"
else if(!adverb_added)
var/adverb = pick("quietly", "softly")
verb = "[verb] [adverb]"
var/atom/whisper_loc = get_whisper_loc()
var/list/listening = hear(message_range, whisper_loc)
listening |= src
var/list/hearturfs = list()
// Pass whispers on to anything inside the immediate listeners.
// This comes before the ghosts do so that ghosts don't act as whisper relays
for(var/atom/L in listening)
if(ismob(L))
for(var/mob/C in L.contents)
if(isliving(C))
listening += C
hearturfs += get_turf(L)
if(isobj(L))
hearturfs += get_turf(L)
// Loop through all players to see if they need to hear it.
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(isnewplayer(M))
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS)) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
if(message_range < world.view && (get_dist(whisper_loc, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
//pass on the message to objects that can hear us.
for(var/obj/O in view(message_range, whisper_loc))
spawn(0)
if(O)
O.hear_talk(src, message_pieces, verb)
var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc)
eavesdropping -= src
eavesdropping -= listening
var/list/watching = hearers(watching_range, whisper_loc)
watching -= src
watching -= listening
watching -= eavesdropping
//now mobs
var/list/speech_bubble_recipients = list()
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
if(eavesdropping.len)
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(message_pieces, verb, italics, src)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, speech_bubble_recipients, 30)
if(watching.len)
var/rendered = "<span class='game say'><span class='name'>[name]</span> [not_heard].</span>"
for(var/mob/M in watching)
M.show_message(rendered, 2)
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, bubble_recipients, 30)
File diff suppressed because it is too large Load Diff
+41 -41
View File
@@ -1,41 +1,41 @@
/mob/living/silicon/ai/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
if(custom_sprite == 1)//check for custom AI sprite, defaulting to blue screen if no.
icon_state = "[ckey]-ai_dead"
else if("[icon_state]_dead" in icon_states(icon,1))
icon_state = "[icon_state]_dead"
else
icon_state = "ai_dead"
if(eyeobj)
eyeobj.setLoc(get_turf(src))
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
if(nuking)
set_security_level("red")
nuking = 0
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
point.the_disk = null //Point back to the disk.
if(doomsday_device)
doomsday_device.timing = 0
SSshuttle.emergencyNoEscape = 0
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
qdel(doomsday_device)
if(explosive)
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in world) //change status
O.mode = 2
if(istype(loc, /obj/item/aicard))
loc.icon_state = "aicard-404"
/mob/living/silicon/ai/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
if(custom_sprite == 1)//check for custom AI sprite, defaulting to blue screen if no.
icon_state = "[ckey]-ai_dead"
else if("[icon_state]_dead" in icon_states(icon,1))
icon_state = "[icon_state]_dead"
else
icon_state = "ai_dead"
if(eyeobj)
eyeobj.setLoc(get_turf(src))
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
if(nuking)
set_security_level("red")
nuking = 0
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
point.the_disk = null //Point back to the disk.
if(doomsday_device)
doomsday_device.timing = 0
SSshuttle.emergencyNoEscape = 0
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
qdel(doomsday_device)
if(explosive)
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in world) //change status
O.mode = 2
if(istype(loc, /obj/item/aicard))
loc.icon_state = "aicard-404"
+34 -34
View File
@@ -1,34 +1,34 @@
/mob/living/silicon/ai/examine(mob/user)
. = ..()
var/msg = "<span class='info'>"
if(src.stat == DEAD)
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
else
msg += "<span class='warning'>"
if(src.getBruteLoss())
if(src.getBruteLoss() < 30)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
if(src.getFireLoss())
if(src.getFireLoss() < 30)
msg += "It looks slightly charred.\n"
else
msg += "<B>Its casing is melted and heat-warped!</B>\n"
if(src.stat == UNCONSCIOUS)
msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n"
if(!shunted && !client)
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
msg += "</span>"
msg += "*---------*</span>"
. += msg
user.showLaws(src)
/mob/proc/showLaws(var/mob/living/silicon/S)
return
/mob/dead/observer/showLaws(var/mob/living/silicon/S)
if(antagHUD || check_rights(R_ADMIN, 0, src))
S.laws.show_laws(src)
/mob/living/silicon/ai/examine(mob/user)
. = ..()
var/msg = "<span class='info'>"
if(src.stat == DEAD)
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
else
msg += "<span class='warning'>"
if(src.getBruteLoss())
if(src.getBruteLoss() < 30)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
if(src.getFireLoss())
if(src.getFireLoss() < 30)
msg += "It looks slightly charred.\n"
else
msg += "<B>Its casing is melted and heat-warped!</B>\n"
if(src.stat == UNCONSCIOUS)
msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n"
if(!shunted && !client)
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
msg += "</span>"
msg += "*---------*</span>"
. += msg
user.showLaws(src)
/mob/proc/showLaws(var/mob/living/silicon/S)
return
/mob/dead/observer/showLaws(var/mob/living/silicon/S)
if(antagHUD || check_rights(R_ADMIN, 0, src))
S.laws.show_laws(src)
@@ -197,4 +197,4 @@ var/datum/cameranet/cameranet = new()
if(cameranet.chunkGenerated(x, y, z))
var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z)
usr.client.debug_variables(chunk)
*/
*/
+151 -151
View File
@@ -1,151 +1,151 @@
// AI EYE
//
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/camera/aiEye
name = "Inactive AI Eye"
icon = 'icons/mob/ai.dmi' //Allows ghosts to see what the AI is looking at.
icon_state = "eye"
alpha = 127
invisibility = SEE_INVISIBLE_OBSERVER
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
var/use_static = TRUE
var/static_visibility_range = 16
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/camera/aiEye/setLoc(T)
if(ai)
if(!isturf(ai.loc))
return
T = get_turf(T)
loc = T
if(use_static)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
update_parallax_contents()
//Holopad
if(ai.master_multicam)
ai.master_multicam.refresh_view()
if(istype(ai.current, /obj/machinery/hologram/holopad))
var/obj/machinery/hologram/holopad/H = ai.current
H.move_hologram(ai, T)
/mob/camera/aiEye/Move()
return 0
/mob/camera/aiEye/proc/GetViewerClient()
if(ai)
return ai.client
return null
/mob/camera/aiEye/proc/RemoveImages()
var/client/C = GetViewerClient()
if(C && use_static)
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
C.images -= chunk.obscured
/mob/camera/aiEye/Destroy()
if(ai)
ai.all_eyes -= src
ai = null
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
chunk.remove(src)
return ..()
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = usr
if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z))
AI.cameraFollow = null
if(isturf(loc) || isturf(src))
AI.eyeobj.setLoc(src)
// AI MOVEMENT
// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
// This is handled in the proc below this one.
/client/proc/AIMove(n, direct, var/mob/living/silicon/ai/user)
var/initial = initial(user.sprint)
var/max_sprint = 50
if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds
user.sprint = initial
for(var/i = 0; i < max(user.sprint, initial); i += 20)
var/turf/step = get_turf(get_step(user.eyeobj, direct))
if(step)
user.eyeobj.setLoc(step)
user.cooldown = world.timeofday + 5
if(user.acceleration)
user.sprint = min(user.sprint + 0.5, max_sprint)
else
user.sprint = initial
if(!user.tracking)
user.cameraFollow = null
//user.unset_machine() //Uncomment this if it causes problems.
//user.lightNearbyCamera()
if(user.camera_light_on)
user.light_cameras()
// Return to the Core.
/mob/living/silicon/ai/proc/core()
set category = "AI Commands"
set name = "AI Core"
view_core()
/mob/living/silicon/ai/proc/view_core()
current = null
cameraFollow = null
unset_machine()
if(src.eyeobj && src.loc)
src.eyeobj.loc = src.loc
else
to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
create_eye()
eyeobj.setLoc(loc)
/mob/living/silicon/ai/proc/create_eye()
if(eyeobj)
return
eyeobj = new /mob/camera/aiEye()
all_eyes += eyeobj
eyeobj.ai = src
eyeobj.setLoc(loc)
eyeobj.name = "[name] (AI Eye)"
/mob/living/silicon/ai/proc/toggle_acceleration()
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
if(usr.stat == 2)
return //won't work if dead
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
if(relay_speech)
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, sound_frequency)
// AI EYE
//
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/camera/aiEye
name = "Inactive AI Eye"
icon = 'icons/mob/ai.dmi' //Allows ghosts to see what the AI is looking at.
icon_state = "eye"
alpha = 127
invisibility = SEE_INVISIBLE_OBSERVER
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
var/use_static = TRUE
var/static_visibility_range = 16
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/camera/aiEye/setLoc(T)
if(ai)
if(!isturf(ai.loc))
return
T = get_turf(T)
loc = T
if(use_static)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
update_parallax_contents()
//Holopad
if(ai.master_multicam)
ai.master_multicam.refresh_view()
if(istype(ai.current, /obj/machinery/hologram/holopad))
var/obj/machinery/hologram/holopad/H = ai.current
H.move_hologram(ai, T)
/mob/camera/aiEye/Move()
return 0
/mob/camera/aiEye/proc/GetViewerClient()
if(ai)
return ai.client
return null
/mob/camera/aiEye/proc/RemoveImages()
var/client/C = GetViewerClient()
if(C && use_static)
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
C.images -= chunk.obscured
/mob/camera/aiEye/Destroy()
if(ai)
ai.all_eyes -= src
ai = null
for(var/V in visibleCameraChunks)
var/datum/camerachunk/chunk = V
chunk.remove(src)
return ..()
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = usr
if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z))
AI.cameraFollow = null
if(isturf(loc) || isturf(src))
AI.eyeobj.setLoc(src)
// AI MOVEMENT
// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
// This is handled in the proc below this one.
/client/proc/AIMove(n, direct, var/mob/living/silicon/ai/user)
var/initial = initial(user.sprint)
var/max_sprint = 50
if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds
user.sprint = initial
for(var/i = 0; i < max(user.sprint, initial); i += 20)
var/turf/step = get_turf(get_step(user.eyeobj, direct))
if(step)
user.eyeobj.setLoc(step)
user.cooldown = world.timeofday + 5
if(user.acceleration)
user.sprint = min(user.sprint + 0.5, max_sprint)
else
user.sprint = initial
if(!user.tracking)
user.cameraFollow = null
//user.unset_machine() //Uncomment this if it causes problems.
//user.lightNearbyCamera()
if(user.camera_light_on)
user.light_cameras()
// Return to the Core.
/mob/living/silicon/ai/proc/core()
set category = "AI Commands"
set name = "AI Core"
view_core()
/mob/living/silicon/ai/proc/view_core()
current = null
cameraFollow = null
unset_machine()
if(src.eyeobj && src.loc)
src.eyeobj.loc = src.loc
else
to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
create_eye()
eyeobj.setLoc(loc)
/mob/living/silicon/ai/proc/create_eye()
if(eyeobj)
return
eyeobj = new /mob/camera/aiEye()
all_eyes += eyeobj
eyeobj.ai = src
eyeobj.setLoc(loc)
eyeobj.name = "[name] (AI Eye)"
/mob/living/silicon/ai/proc/toggle_acceleration()
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
if(usr.stat == 2)
return //won't work if dead
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
if(relay_speech)
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, sound_frequency)
@@ -1,51 +1,51 @@
// CREDITS
/*
Initial code credit for this goes to Uristqwerty.
Debugging, functionality, all comments and porting by Giacom.
Everything about freelook (or what we can put in here) will be stored here.
WHAT IS THIS?
This is a replacement for the current camera movement system, of the AI. Before this, the AI had to move between cameras and could
only see what the cameras could see. Not only this but the cameras could see through walls, which created problems.
With this, the AI controls an "AI Eye" mob, which moves just like a ghost; such as moving through walls and being invisible to players.
The AI's eye is set to this mob and then we use a system (explained below) to determine what the cameras around the AI Eye can and
cannot see. If the camera cannot see a turf, it will black it out, otherwise it won't and the AI will be able to see it.
This creates several features, such as.. no more see-through-wall cameras, easier to control camera movement, easier tracking,
the AI only being able to track mobs which are visible to a camera, only trackable mobs appearing on the mob list and many more.
HOW IT WORKS
It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be
explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy().
Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk.
These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside
the 16x16 block, it is listed as an "obscured" turf. Meaning the AI won't be able to see it.
HOW IT UPDATES
The camera network uses a streaming method in order to effeciently update chunks. Since the server will have doors opening, doors closing,
turf being destroyed and other lag inducing stuff, we want to update it under certain conditions and not every tick.
The chunks are not created straight away, only when an AI eye moves into it's area is when it gets created.
One a chunk is created, when a non glass door opens/closes or an opacity turf is destroyed, we check to see if an AI Eye is looking in the area.
We do this with the "seenby" list, which updates everytime an AI is near a chunk. If there is an AI eye inside the area, we update the chunk
that the changed atom is inside and all surrounding chunks, since a camera's vision could leak onto another chunk. If there is no AI Eye, we instead
flag the chunk to update whenever it is loaded by an AI Eye. This is basically how the chunks update and keep it in sync. We then add some lag reducing
measures, such as an UPDATE_BUFFER which stops a chunk from updating too many times in a certain time-frame, only updating if the changed atom was blocking
sight; for example, we don't update glass airlocks or floors.
WHERE IS EVERYTHING?
cameranet.dm = Everything about the cameranet datum.
chunk.dm = Everything about the chunk datum.
eye.dm = Everything about the AI and the AIEye.
updating.dm = Everything about triggers that will update chunks.
*/
// CREDITS
/*
Initial code credit for this goes to Uristqwerty.
Debugging, functionality, all comments and porting by Giacom.
Everything about freelook (or what we can put in here) will be stored here.
WHAT IS THIS?
This is a replacement for the current camera movement system, of the AI. Before this, the AI had to move between cameras and could
only see what the cameras could see. Not only this but the cameras could see through walls, which created problems.
With this, the AI controls an "AI Eye" mob, which moves just like a ghost; such as moving through walls and being invisible to players.
The AI's eye is set to this mob and then we use a system (explained below) to determine what the cameras around the AI Eye can and
cannot see. If the camera cannot see a turf, it will black it out, otherwise it won't and the AI will be able to see it.
This creates several features, such as.. no more see-through-wall cameras, easier to control camera movement, easier tracking,
the AI only being able to track mobs which are visible to a camera, only trackable mobs appearing on the mob list and many more.
HOW IT WORKS
It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be
explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy().
Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk.
These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside
the 16x16 block, it is listed as an "obscured" turf. Meaning the AI won't be able to see it.
HOW IT UPDATES
The camera network uses a streaming method in order to effeciently update chunks. Since the server will have doors opening, doors closing,
turf being destroyed and other lag inducing stuff, we want to update it under certain conditions and not every tick.
The chunks are not created straight away, only when an AI eye moves into it's area is when it gets created.
One a chunk is created, when a non glass door opens/closes or an opacity turf is destroyed, we check to see if an AI Eye is looking in the area.
We do this with the "seenby" list, which updates everytime an AI is near a chunk. If there is an AI eye inside the area, we update the chunk
that the changed atom is inside and all surrounding chunks, since a camera's vision could leak onto another chunk. If there is no AI Eye, we instead
flag the chunk to update whenever it is loaded by an AI Eye. This is basically how the chunks update and keep it in sync. We then add some lag reducing
measures, such as an UPDATE_BUFFER which stops a chunk from updating too many times in a certain time-frame, only updating if the changed atom was blocking
sight; for example, we don't update glass airlocks or floors.
WHERE IS EVERYTHING?
cameranet.dm = Everything about the cameranet datum.
chunk.dm = Everything about the chunk datum.
eye.dm = Everything about the AI and the AIEye.
updating.dm = Everything about triggers that will update chunks.
*/
+27 -27
View File
@@ -1,27 +1,27 @@
/mob/living/silicon/ai/proc/show_laws_verb()
set category = "AI Commands"
set name = "Show Laws"
src.show_laws()
/mob/living/silicon/ai/show_laws(var/everyone = 0)
var/who
if(everyone)
who = world
else
who = src
to_chat(who, "<b>Obey these laws:</b>")
src.laws_sanity_check()
src.laws.show_laws(who)
/mob/living/silicon/ai/add_ion_law(var/law)
..()
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
if(R.lawupdate && (R.connected_ai == src))
R.show_laws()
/mob/living/silicon/ai/proc/ai_checklaws()
set category = "AI Commands"
set name = "State Laws"
subsystem_law_manager()
/mob/living/silicon/ai/proc/show_laws_verb()
set category = "AI Commands"
set name = "Show Laws"
src.show_laws()
/mob/living/silicon/ai/show_laws(var/everyone = 0)
var/who
if(everyone)
who = world
else
who = src
to_chat(who, "<b>Obey these laws:</b>")
src.laws_sanity_check()
src.laws.show_laws(who)
/mob/living/silicon/ai/add_ion_law(var/law)
..()
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
if(R.lawupdate && (R.connected_ai == src))
R.show_laws()
/mob/living/silicon/ai/proc/ai_checklaws()
set category = "AI Commands"
set name = "State Laws"
subsystem_law_manager()
+154 -154
View File
@@ -1,154 +1,154 @@
#define POWER_RESTORATION_OFF 0
#define POWER_RESTORATION_START 1
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
/mob/living/silicon/ai/Life(seconds, times_fired)
//doesn't call parent because it's a horrible mess
if(stat == DEAD)
return
var/turf/T = get_turf(src)
if(stat != CONSCIOUS) //ai's fucked
cameraFollow = null
reset_perspective(null)
unset_machine()
updatehealth("life")
if(stat == DEAD)
return
update_gravity(mob_has_gravity())
if(!eyeobj || QDELETED(eyeobj) || !eyeobj.loc)
view_core()
if(machine)
machine.check_eye(src)
if(malfhack && malfhack.aidisabled)
to_chat(src, "<span class='danger'>ERROR: APC access disabled, hack attempt canceled.</span>")
deltimer(malfhacking)
// This proc handles cleanup of screen notifications and
// messenging the client
malfhacked(malfhack)
if(aiRestorePowerRoutine)
adjustOxyLoss(1)
else
adjustOxyLoss(-1)
handle_stunned()
var/area/my_area = get_area(src)
if(!lacks_power())
if(aiRestorePowerRoutine > 1)
update_blind_effects()
aiRestorePowerRoutine = 0
update_sight()
to_chat(src, "Alert cancelled. Power has been restored[aiRestorePowerRoutine == 2 ? "without our assistance" : ""].")
else
if(lacks_power())
if(!aiRestorePowerRoutine)
update_blind_effects()
aiRestorePowerRoutine = 1
update_sight()
to_chat(src, "<span class='danger'>You have lost power!</span>")
if(!is_special_character(src))
set_zeroth_law("")
spawn(20)
to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.")
end_multicam()
sleep(50)
my_area = get_area(src)
T = get_turf(src)
if(!lacks_power())
to_chat(src, "Alert cancelled. Power has been restored without our assistance.")
aiRestorePowerRoutine = 0
update_blind_effects()
update_sight()
return
to_chat(src, "Fault confirmed: missing external power. Shutting down main control system to save power.")
sleep(20)
to_chat(src, "Emergency control system online. Verifying connection to power network.")
sleep(50)
T = get_turf(src)
if(istype(T, /turf/space))
to_chat(src, "Unable to verify! No power connection detected!")
aiRestorePowerRoutine = 2
return
to_chat(src, "Connection verified. Searching for APC in power network.")
sleep(50)
my_area = get_area(src)
T = get_turf(src)
var/obj/machinery/power/apc/theAPC = null
var/PRP
for(PRP = 1, PRP <= 4, PRP++)
for(var/obj/machinery/power/apc/APC in my_area)
if(!(APC.stat & BROKEN))
theAPC = APC
break
if(!theAPC)
switch(PRP)
if(1)
to_chat(src, "Unable to locate APC!")
else
to_chat(src, "Lost connection with the APC!")
aiRestorePowerRoutine = 2
return
if(!lacks_power())
to_chat(src, "Alert cancelled. Power has been restored without our assistance.")
aiRestorePowerRoutine = 0
update_blind_effects()
update_sight()
to_chat(src, "Here are your current laws:")
show_laws()
return
switch(PRP)
if(1)
to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
if(2)
to_chat(src, "Best route identified. Hacking offline APC power port.")
if(3)
to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
if(4)
to_chat(src, "Transfer complete. Forcing APC to execute program.")
sleep(50)
to_chat(src, "Receiving control information from APC.")
sleep(2)
//bring up APC dialog
apc_override = 1
theAPC.attack_ai(src)
apc_override = 0
aiRestorePowerRoutine = 3
sleep(50)
theAPC = null
process_queued_alarms()
/mob/living/silicon/ai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
update_stat("updatehealth([reason])")
diag_hud_set_status()
diag_hud_set_health()
/mob/living/silicon/ai/proc/lacks_power()
var/turf/T = get_turf(src)
var/area/A = get_area(src)
return ((!A.power_equip) && A.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item)
/mob/living/silicon/ai/rejuvenate()
..()
add_ai_verbs(src)
#define POWER_RESTORATION_OFF 0
#define POWER_RESTORATION_START 1
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
/mob/living/silicon/ai/Life(seconds, times_fired)
//doesn't call parent because it's a horrible mess
if(stat == DEAD)
return
var/turf/T = get_turf(src)
if(stat != CONSCIOUS) //ai's fucked
cameraFollow = null
reset_perspective(null)
unset_machine()
updatehealth("life")
if(stat == DEAD)
return
update_gravity(mob_has_gravity())
if(!eyeobj || QDELETED(eyeobj) || !eyeobj.loc)
view_core()
if(machine)
machine.check_eye(src)
if(malfhack && malfhack.aidisabled)
to_chat(src, "<span class='danger'>ERROR: APC access disabled, hack attempt canceled.</span>")
deltimer(malfhacking)
// This proc handles cleanup of screen notifications and
// messenging the client
malfhacked(malfhack)
if(aiRestorePowerRoutine)
adjustOxyLoss(1)
else
adjustOxyLoss(-1)
handle_stunned()
var/area/my_area = get_area(src)
if(!lacks_power())
if(aiRestorePowerRoutine > 1)
update_blind_effects()
aiRestorePowerRoutine = 0
update_sight()
to_chat(src, "Alert cancelled. Power has been restored[aiRestorePowerRoutine == 2 ? "without our assistance" : ""].")
else
if(lacks_power())
if(!aiRestorePowerRoutine)
update_blind_effects()
aiRestorePowerRoutine = 1
update_sight()
to_chat(src, "<span class='danger'>You have lost power!</span>")
if(!is_special_character(src))
set_zeroth_law("")
spawn(20)
to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.")
end_multicam()
sleep(50)
my_area = get_area(src)
T = get_turf(src)
if(!lacks_power())
to_chat(src, "Alert cancelled. Power has been restored without our assistance.")
aiRestorePowerRoutine = 0
update_blind_effects()
update_sight()
return
to_chat(src, "Fault confirmed: missing external power. Shutting down main control system to save power.")
sleep(20)
to_chat(src, "Emergency control system online. Verifying connection to power network.")
sleep(50)
T = get_turf(src)
if(istype(T, /turf/space))
to_chat(src, "Unable to verify! No power connection detected!")
aiRestorePowerRoutine = 2
return
to_chat(src, "Connection verified. Searching for APC in power network.")
sleep(50)
my_area = get_area(src)
T = get_turf(src)
var/obj/machinery/power/apc/theAPC = null
var/PRP
for(PRP = 1, PRP <= 4, PRP++)
for(var/obj/machinery/power/apc/APC in my_area)
if(!(APC.stat & BROKEN))
theAPC = APC
break
if(!theAPC)
switch(PRP)
if(1)
to_chat(src, "Unable to locate APC!")
else
to_chat(src, "Lost connection with the APC!")
aiRestorePowerRoutine = 2
return
if(!lacks_power())
to_chat(src, "Alert cancelled. Power has been restored without our assistance.")
aiRestorePowerRoutine = 0
update_blind_effects()
update_sight()
to_chat(src, "Here are your current laws:")
show_laws()
return
switch(PRP)
if(1)
to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
if(2)
to_chat(src, "Best route identified. Hacking offline APC power port.")
if(3)
to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
if(4)
to_chat(src, "Transfer complete. Forcing APC to execute program.")
sleep(50)
to_chat(src, "Receiving control information from APC.")
sleep(2)
//bring up APC dialog
apc_override = 1
theAPC.attack_ai(src)
apc_override = 0
aiRestorePowerRoutine = 3
sleep(50)
theAPC = null
process_queued_alarms()
/mob/living/silicon/ai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
update_stat("updatehealth([reason])")
diag_hud_set_status()
diag_hud_set_health()
/mob/living/silicon/ai/proc/lacks_power()
var/turf/T = get_turf(src)
var/area/A = get_area(src)
return ((!A.power_equip) && A.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item)
/mob/living/silicon/ai/rejuvenate()
..()
add_ai_verbs(src)
+15 -15
View File
@@ -1,15 +1,15 @@
/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up _ ~Carn
..()
for(var/obj/effect/rune/rune in world)
var/image/blood = image(loc = rune)
blood.override = 1
client.images += blood
regenerate_icons()
if(stat != DEAD)
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 1
O.emotion = "Neutral"
if(multicam_on)
end_multicam()
view_core()
/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up _ ~Carn
..()
for(var/obj/effect/rune/rune in world)
var/image/blood = image(loc = rune)
blood.override = 1
client.images += blood
regenerate_icons()
if(stat != DEAD)
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 1
O.emotion = "Neutral"
if(multicam_on)
end_multicam()
view_core()
+6 -6
View File
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/Logout()
..()
for(var/obj/machinery/ai_status_display/O in world) //change status
O.mode = 0
src.view_core()
return
/mob/living/silicon/ai/Logout()
..()
for(var/obj/machinery/ai_status_display/O in world) //change status
O.mode = 0
src.view_core()
return
+185 -185
View File
@@ -1,185 +1,185 @@
/*
* AI Saycode
*/
/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
var/jobname // the mob's "job"
var/mob/living/carbon/human/impersonating //The crewmember being impersonated, if any.
var/changed_voice
if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker
var/obj/item/card/id/id = H.wear_id
if((istype(id) && id.is_untrackable()) && H.HasVoiceChanger())
changed_voice = 1
var/mob/living/carbon/human/I = locate(speaker_name)
if(I)
impersonating = I
jobname = impersonating.get_assignment()
else
jobname = "Unknown"
else
jobname = H.get_assignment()
else if(iscarbon(speaker)) // Nonhuman carbon mob
jobname = "No ID"
else if(isAI(speaker))
jobname = "AI"
else if(isrobot(speaker))
jobname = "Cyborg"
else if(ispAI(speaker))
jobname = "Personal AI"
else if(isAutoAnnouncer(speaker))
var/mob/living/automatedannouncer/AA = speaker
jobname = AA.role
else
jobname = "Unknown"
var/track = ""
var/mob/mob_to_track = null
if(changed_voice)
if(impersonating)
mob_to_track = impersonating
else
track = "[speaker_name] ([jobname])"
else
if(istype(follow_target, /mob/living/simple_animal/bot))
track = "<a href='byond://?src=[UID()];trackbot=\ref[follow_target]'>[speaker_name] ([jobname])</a>"
else
mob_to_track = speaker
if(mob_to_track)
track = "<a href='byond://?src=[UID()];track=\ref[mob_to_track]'>[speaker_name] ([jobname])</a>"
track += "&nbsp;<a href='byond://?src=[UID()];open=\ref[mob_to_track]'>\[Open\]</a>"
return track
/*
* AI VOX Announcements
*/
var/announcing_vox = 0 // Stores the time of the last announcement
#define VOX_DELAY 100
#define VOX_PATH "sound/vox_fem/"
/mob/living/silicon/ai/verb/announcement_help()
set name = "Announcement Help"
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.<BR> \
<UL><LI>You can also click on the word to preview it.</LI>\
<LI>You can only say 30 words for every announcement.</LI>\
<LI>Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.</LI></UL>\
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
var/index = 0
for(var/word in vox_sounds)
index++
dat += "<A href='?src=[UID()];say_word=[word]'>[capitalize(word)]</A>"
if(index != vox_sounds.len)
dat += " / "
var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
popup.set_content(dat)
popup.open()
/mob/living/silicon/ai/proc/ai_announcement()
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
if(announcing_vox > world.time)
to_chat(src, "<span class='warning'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
return
var/message = clean_input("WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement, src)
last_announcement = message
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
if(!message || announcing_vox > world.time)
return
var/list/words = splittext(trim(message), " ")
var/list/incorrect_words = list()
if(words.len > 30)
words.len = 30
for(var/word in words)
word = lowertext(trim(word))
if(!word)
words -= word
continue
if(!vox_sounds[word])
incorrect_words += word
if(incorrect_words.len)
to_chat(src, "<span class='warning'>These words are not available on the announcement system: [english_list(incorrect_words)].</span>")
return
announcing_vox = world.time + VOX_DELAY
log_game("[key_name(src)] made a vocal announcement: [message].")
message_admins("[key_name_admin(src)] made a vocal announcement: [message].")
for(var/word in words)
play_vox_word(word, src.z, null)
ai_voice_announcement_to_text(words)
/mob/living/silicon/ai/proc/ai_voice_announcement_to_text(words)
var/words_string = jointext(words, " ")
var/formatted_message = "<h1 class='alert'>A.I. Announcement</h1>"
formatted_message += "<br><span class='alert'>[words_string]</span>"
formatted_message += "<br><span class='alert'> -[src]</span>"
for(var/player in GLOB.player_list)
var/mob/M = player
if(M.client && !(M.client.prefs.sound & SOUND_AI_VOICE))
var/turf/T = get_turf(M)
if(T && T.z == z && M.can_hear())
SEND_SOUND(M, 'sound/misc/notice2.ogg')
to_chat(M, formatted_message)
/proc/play_vox_word(word, z_level, mob/only_listener)
word = lowertext(word)
if(vox_sounds[word])
var/sound_file = vox_sounds[word]
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
voice.status = SOUND_STREAM
// If there is no single listener, broadcast to everyone in the same z level
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/M in GLOB.player_list)
if(M.client && M.client.prefs.sound & SOUND_AI_VOICE)
var/turf/T = get_turf(M)
if(T && T.z == z_level && M.can_hear())
M << voice
else
only_listener << voice
return 1
return 0
// VOX sounds moved to /code/defines/vox_sounds.dm
/client/proc/preload_vox()
var/list/vox_files = flist(VOX_PATH)
for(var/file in vox_files)
// to_chat(src, "Downloading [file]")
var/sound/S = sound("[VOX_PATH][file]")
src << browse_rsc(S)
/*
* AI Saycode
*/
/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
var/jobname // the mob's "job"
var/mob/living/carbon/human/impersonating //The crewmember being impersonated, if any.
var/changed_voice
if(ishuman(speaker))
var/mob/living/carbon/human/H = speaker
var/obj/item/card/id/id = H.wear_id
if((istype(id) && id.is_untrackable()) && H.HasVoiceChanger())
changed_voice = 1
var/mob/living/carbon/human/I = locate(speaker_name)
if(I)
impersonating = I
jobname = impersonating.get_assignment()
else
jobname = "Unknown"
else
jobname = H.get_assignment()
else if(iscarbon(speaker)) // Nonhuman carbon mob
jobname = "No ID"
else if(isAI(speaker))
jobname = "AI"
else if(isrobot(speaker))
jobname = "Cyborg"
else if(ispAI(speaker))
jobname = "Personal AI"
else if(isAutoAnnouncer(speaker))
var/mob/living/automatedannouncer/AA = speaker
jobname = AA.role
else
jobname = "Unknown"
var/track = ""
var/mob/mob_to_track = null
if(changed_voice)
if(impersonating)
mob_to_track = impersonating
else
track = "[speaker_name] ([jobname])"
else
if(istype(follow_target, /mob/living/simple_animal/bot))
track = "<a href='byond://?src=[UID()];trackbot=\ref[follow_target]'>[speaker_name] ([jobname])</a>"
else
mob_to_track = speaker
if(mob_to_track)
track = "<a href='byond://?src=[UID()];track=\ref[mob_to_track]'>[speaker_name] ([jobname])</a>"
track += "&nbsp;<a href='byond://?src=[UID()];open=\ref[mob_to_track]'>\[Open\]</a>"
return track
/*
* AI VOX Announcements
*/
var/announcing_vox = 0 // Stores the time of the last announcement
#define VOX_DELAY 100
#define VOX_PATH "sound/vox_fem/"
/mob/living/silicon/ai/verb/announcement_help()
set name = "Announcement Help"
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.<BR> \
<UL><LI>You can also click on the word to preview it.</LI>\
<LI>You can only say 30 words for every announcement.</LI>\
<LI>Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.</LI></UL>\
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
var/index = 0
for(var/word in vox_sounds)
index++
dat += "<A href='?src=[UID()];say_word=[word]'>[capitalize(word)]</A>"
if(index != vox_sounds.len)
dat += " / "
var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
popup.set_content(dat)
popup.open()
/mob/living/silicon/ai/proc/ai_announcement()
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
if(announcing_vox > world.time)
to_chat(src, "<span class='warning'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
return
var/message = clean_input("WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement, src)
last_announcement = message
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
if(!message || announcing_vox > world.time)
return
var/list/words = splittext(trim(message), " ")
var/list/incorrect_words = list()
if(words.len > 30)
words.len = 30
for(var/word in words)
word = lowertext(trim(word))
if(!word)
words -= word
continue
if(!vox_sounds[word])
incorrect_words += word
if(incorrect_words.len)
to_chat(src, "<span class='warning'>These words are not available on the announcement system: [english_list(incorrect_words)].</span>")
return
announcing_vox = world.time + VOX_DELAY
log_game("[key_name(src)] made a vocal announcement: [message].")
message_admins("[key_name_admin(src)] made a vocal announcement: [message].")
for(var/word in words)
play_vox_word(word, src.z, null)
ai_voice_announcement_to_text(words)
/mob/living/silicon/ai/proc/ai_voice_announcement_to_text(words)
var/words_string = jointext(words, " ")
var/formatted_message = "<h1 class='alert'>A.I. Announcement</h1>"
formatted_message += "<br><span class='alert'>[words_string]</span>"
formatted_message += "<br><span class='alert'> -[src]</span>"
for(var/player in GLOB.player_list)
var/mob/M = player
if(M.client && !(M.client.prefs.sound & SOUND_AI_VOICE))
var/turf/T = get_turf(M)
if(T && T.z == z && M.can_hear())
SEND_SOUND(M, 'sound/misc/notice2.ogg')
to_chat(M, formatted_message)
/proc/play_vox_word(word, z_level, mob/only_listener)
word = lowertext(word)
if(vox_sounds[word])
var/sound_file = vox_sounds[word]
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
voice.status = SOUND_STREAM
// If there is no single listener, broadcast to everyone in the same z level
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/M in GLOB.player_list)
if(M.client && M.client.prefs.sound & SOUND_AI_VOICE)
var/turf/T = get_turf(M)
if(T && T.z == z_level && M.can_hear())
M << voice
else
only_listener << voice
return 1
return 0
// VOX sounds moved to /code/defines/vox_sounds.dm
/client/proc/preload_vox()
var/list/vox_files = flist(VOX_PATH)
for(var/file in vox_files)
// to_chat(src, "Downloading [file]")
var/sound/S = sound("[VOX_PATH][file]")
src << browse_rsc(S)
+10 -10
View File
@@ -1,10 +1,10 @@
/mob/living/silicon/decoy/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
icon_state = "ai-crash"
for(var/obj/machinery/ai_status_display/O in world) //change status
if(atoms_share_level(O, src))
O.mode = 2
gib()
/mob/living/silicon/decoy/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
icon_state = "ai-crash"
for(var/obj/machinery/ai_status_display/O in world) //change status
if(atoms_share_level(O, src))
O.mode = 2
gib()
+62 -62
View File
@@ -1,62 +1,62 @@
/mob/living/silicon/decoy
name = "AI"
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_state = "ai"
src.anchored = 1
src.canmove = 0
/mob/living/silicon/decoy/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/aicard))
to_chat(user, "<span class='warning'>You cannot find an intellicard slot on [src].</span>")
return TRUE
else
return ..()
/mob/living/silicon/decoy/welder_act()
return
/mob/living/silicon/decoy/syndicate
faction = list("syndicate")
name = "R.O.D.G.E.R"
desc = "Red Operations, Depot General Emission Regulator"
icon_state = "ai-magma"
/mob/living/silicon/decoy/syndicate/New()
. = ..()
icon_state = "ai-magma"
/mob/living/silicon/decoy/syndicate/depot
universal_speak = TRUE
universal_understand = TRUE
var/raised_alert = FALSE
/mob/living/silicon/decoy/syndicate/depot/proc/raise_alert()
raised_alert = TRUE
var/area/syndicate_depot/core/depotarea = get_area(src) // Cannot use myArea or areaMaster as neither will be defined for this mob type
if(istype(depotarea))
depotarea.increase_alert("AI Unit Offline")
else
say("Connection failure!")
/mob/living/silicon/decoy/syndicate/depot/death(pass)
if(!raised_alert)
raise_alert()
. = ..(pass)
/mob/living/silicon/decoy/syndicate/depot/adjustBruteLoss(dmg)
. = ..(dmg)
updatehealth()
/mob/living/silicon/decoy/syndicate/depot/adjustFireLoss(dmg)
. = ..(dmg)
updatehealth()
/mob/living/silicon/decoy/syndicate/depot/ex_act(severity)
adjustBruteLoss(250)
/mob/living/silicon/decoy
name = "AI"
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_state = "ai"
src.anchored = 1
src.canmove = 0
/mob/living/silicon/decoy/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/aicard))
to_chat(user, "<span class='warning'>You cannot find an intellicard slot on [src].</span>")
return TRUE
else
return ..()
/mob/living/silicon/decoy/welder_act()
return
/mob/living/silicon/decoy/syndicate
faction = list("syndicate")
name = "R.O.D.G.E.R"
desc = "Red Operations, Depot General Emission Regulator"
icon_state = "ai-magma"
/mob/living/silicon/decoy/syndicate/New()
. = ..()
icon_state = "ai-magma"
/mob/living/silicon/decoy/syndicate/depot
universal_speak = TRUE
universal_understand = TRUE
var/raised_alert = FALSE
/mob/living/silicon/decoy/syndicate/depot/proc/raise_alert()
raised_alert = TRUE
var/area/syndicate_depot/core/depotarea = get_area(src) // Cannot use myArea or areaMaster as neither will be defined for this mob type
if(istype(depotarea))
depotarea.increase_alert("AI Unit Offline")
else
say("Connection failure!")
/mob/living/silicon/decoy/syndicate/depot/death(pass)
if(!raised_alert)
raise_alert()
. = ..(pass)
/mob/living/silicon/decoy/syndicate/depot/adjustBruteLoss(dmg)
. = ..(dmg)
updatehealth()
/mob/living/silicon/decoy/syndicate/depot/adjustFireLoss(dmg)
. = ..(dmg)
updatehealth()
/mob/living/silicon/decoy/syndicate/depot/ex_act(severity)
adjustBruteLoss(250)
+19 -19
View File
@@ -1,19 +1,19 @@
/mob/living/silicon/decoy/Life(seconds, times_fired)
return
/mob/living/silicon/decoy/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
update_stat("updatehealth([reason])")
/mob/living/silicon/decoy/update_stat(reason = "none given")
if(stat == DEAD)
return
if(health <= 0)
death()
create_debug_log("died of damage, trigger reason: [reason]")
/mob/living/silicon/decoy/Life(seconds, times_fired)
return
/mob/living/silicon/decoy/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
update_stat("updatehealth([reason])")
/mob/living/silicon/decoy/update_stat(reason = "none given")
if(stat == DEAD)
return
if(health <= 0)
death()
create_debug_log("died of damage, trigger reason: [reason]")
+12 -12
View File
@@ -1,12 +1,12 @@
/mob/living/silicon/Login()
SetSleeping(0)
if(mind && SSticker && SSticker.mode)
SSticker.mode.remove_revolutionary(mind, 1)
SSticker.mode.remove_cultist(mind, 1)
SSticker.mode.remove_wizard(mind)
SSticker.mode.remove_changeling(mind)
SSticker.mode.remove_vampire(mind)
SSticker.mode.remove_thrall(mind, 0)
SSticker.mode.remove_shadowling(mind)
SSticker.mode.remove_abductor(mind)
..()
/mob/living/silicon/Login()
SetSleeping(0)
if(mind && SSticker && SSticker.mode)
SSticker.mode.remove_revolutionary(mind, 1)
SSticker.mode.remove_cultist(mind, 1)
SSticker.mode.remove_wizard(mind)
SSticker.mode.remove_changeling(mind)
SSticker.mode.remove_vampire(mind)
SSticker.mode.remove_thrall(mind, 0)
SSticker.mode.remove_shadowling(mind)
SSticker.mode.remove_abductor(mind)
..()
+17 -17
View File
@@ -1,17 +1,17 @@
/mob/living/silicon/pai/death(gibbed, cleanWipe)
if(can_die())
if(!cleanWipe)
force_fold_out()
visible_message("<span class=warning>[src] emits a dull beep before it loses power and collapses.</span>", "<span class=warning>You hear a dull beep followed by the sound of glass crunching.</span>")
name = "pAI debris"
desc = "The unfortunate remains of some poor personal AI device."
icon_state = "[chassis]_dead"
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
if(icon_state != "[chassis]_dead" || cleanWipe)
qdel(src)
/mob/living/silicon/pai/death(gibbed, cleanWipe)
if(can_die())
if(!cleanWipe)
force_fold_out()
visible_message("<span class=warning>[src] emits a dull beep before it loses power and collapses.</span>", "<span class=warning>You hear a dull beep followed by the sound of glass crunching.</span>")
name = "pAI debris"
desc = "The unfortunate remains of some poor personal AI device."
icon_state = "[chassis]_dead"
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
if(icon_state != "[chassis]_dead" || cleanWipe)
qdel(src)
+27 -27
View File
@@ -1,27 +1,27 @@
/mob/living/silicon/pai/Life(seconds, times_fired)
. = ..()
if(.)
//if(secHUD == 1)
// process_sec_hud(src, 1)
////if(medHUD == 1)
// process_med_hud(src, 1)
if(silence_time)
if(world.timeofday >= silence_time)
silence_time = null
to_chat(src, "<font color=green>Communication circuit reinitialized. Speech and messaging functionality restored.</font>")
if(cable)
if(get_dist(src, cable) > 1)
var/turf/T = get_turf_or_move(loc)
for(var/mob/M in viewers(T))
M.show_message("<span class='warning'>The data cable rapidly retracts back into its spool.</span>", 3, "<span class='warning'>You hear a click and the sound of wire spooling rapidly.</span>", 2)
qdel(src.cable)
cable = null
/mob/living/silicon/pai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getBruteLoss() - getFireLoss()
update_stat("updatehealth([reason])")
/mob/living/silicon/pai/Life(seconds, times_fired)
. = ..()
if(.)
//if(secHUD == 1)
// process_sec_hud(src, 1)
////if(medHUD == 1)
// process_med_hud(src, 1)
if(silence_time)
if(world.timeofday >= silence_time)
silence_time = null
to_chat(src, "<font color=green>Communication circuit reinitialized. Speech and messaging functionality restored.</font>")
if(cable)
if(get_dist(src, cable) > 1)
var/turf/T = get_turf_or_move(loc)
for(var/mob/M in viewers(T))
M.show_message("<span class='warning'>The data cable rapidly retracts back into its spool.</span>", 3, "<span class='warning'>You hear a click and the sound of wire spooling rapidly.</span>", 2)
qdel(src.cable)
cable = null
/mob/living/silicon/pai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
stat = CONSCIOUS
else
health = 100 - getBruteLoss() - getFireLoss()
update_stat("updatehealth([reason])")
File diff suppressed because it is too large Load Diff

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