Merge branch 'master' into Doggo-sit
This commit is contained in:
@@ -18,10 +18,10 @@
|
||||
/mob/living/carbon/monkey/handle_blood()
|
||||
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL)
|
||||
if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio))
|
||||
blood_volume += 0.1 // regenerate blood VERY slowly
|
||||
if(blood_volume < BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
if(blood_volume < (BLOOD_VOLUME_OKAY * blood_ratio))
|
||||
adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1))
|
||||
|
||||
// Takes care blood loss and regeneration
|
||||
/mob/living/carbon/human/handle_blood()
|
||||
@@ -33,7 +33,7 @@
|
||||
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER))
|
||||
if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio) && !HAS_TRAIT(src, TRAIT_NOHUNGER))
|
||||
var/nutrition_ratio = 0
|
||||
switch(nutrition)
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
@@ -46,20 +46,22 @@
|
||||
nutrition_ratio = 0.8
|
||||
else
|
||||
nutrition_ratio = 1
|
||||
if(HAS_TRAIT(src, TRAIT_HIGH_BLOOD))
|
||||
nutrition_ratio *= 1.2
|
||||
if(satiety > 80)
|
||||
nutrition_ratio *= 1.25
|
||||
nutrition = max(0, nutrition - nutrition_ratio * HUNGER_FACTOR)
|
||||
blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
|
||||
blood_volume = min((BLOOD_VOLUME_NORMAL * blood_ratio), blood_volume + 0.5 * nutrition_ratio)
|
||||
|
||||
//Effects of bloodloss
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
switch(blood_volume)
|
||||
switch(blood_volume * INVERSE(blood_ratio))
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>You feel [word].</span>")
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
|
||||
adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.01, 1))
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1))
|
||||
if(prob(5))
|
||||
blur_eyes(6)
|
||||
to_chat(src, "<span class='warning'>You feel very [word].</span>")
|
||||
@@ -111,7 +113,7 @@
|
||||
blood_volume = initial(blood_volume)
|
||||
|
||||
/mob/living/carbon/human/restore_blood()
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio)
|
||||
bleed_rate = 0
|
||||
|
||||
/****************************************************
|
||||
@@ -122,7 +124,7 @@
|
||||
/mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced)
|
||||
if(!blood_volume || !AM.reagents)
|
||||
return 0
|
||||
if(blood_volume < BLOOD_VOLUME_BAD && !forced)
|
||||
if(blood_volume < (BLOOD_VOLUME_BAD * blood_ratio) && !forced)
|
||||
return 0
|
||||
|
||||
if(blood_volume < amount)
|
||||
@@ -161,7 +163,7 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/get_blood_data(blood_id)
|
||||
if(blood_id == "blood") //actual blood reagent
|
||||
if(blood_id == "blood") //actual blood reagent
|
||||
var/blood_data = list()
|
||||
//set the blood data
|
||||
blood_data["donor"] = src
|
||||
@@ -204,6 +206,21 @@
|
||||
if(istype(ling))
|
||||
blood_data["changeling_loudness"] = ling.loudfactor
|
||||
return blood_data
|
||||
if(blood_id == "slimejelly") //Just so MKUltra works. Takes the minimum required data. Sishen is testing if this breaks stuff.
|
||||
var/blood_data = list()
|
||||
if(mind)
|
||||
blood_data["mind"] = mind
|
||||
else if(last_mind)
|
||||
blood_data["mind"] = last_mind
|
||||
if(ckey)
|
||||
blood_data["ckey"] = ckey
|
||||
else if(last_mind)
|
||||
blood_data["ckey"] = ckey(last_mind.key)
|
||||
blood_data["gender"] = gender
|
||||
blood_data["real_name"] = real_name
|
||||
return blood_data
|
||||
|
||||
|
||||
|
||||
//get the id of the substance this mob use as blood.
|
||||
/mob/proc/get_blood_id()
|
||||
@@ -300,3 +317,24 @@
|
||||
var/obj/effect/decal/cleanable/oil/B = locate() in T.contents
|
||||
if(!B)
|
||||
B = new(T)
|
||||
|
||||
//This is a terrible way of handling it.
|
||||
/mob/living/proc/ResetBloodVol()
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
if (HAS_TRAIT(src, TRAIT_HIGH_BLOOD))
|
||||
blood_ratio = 1.2
|
||||
H.handle_blood()
|
||||
return
|
||||
blood_ratio = 1
|
||||
H.handle_blood()
|
||||
return
|
||||
blood_ratio = 1
|
||||
|
||||
/mob/living/proc/AdjustBloodVol(var/value)
|
||||
if(blood_ratio == value)
|
||||
return
|
||||
blood_ratio = value
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
H.handle_blood()
|
||||
|
||||
@@ -138,7 +138,11 @@
|
||||
name = "blood crawl"
|
||||
desc = "You are unable to hold anything while in this form."
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
item_flags = NODROP | ABSTRACT
|
||||
item_flags = ABSTRACT
|
||||
|
||||
/obj/item/bloodcrawl/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
||||
|
||||
/mob/living/proc/exit_blood_effect(obj/effect/decal/cleanable/B)
|
||||
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
var/datum/dna/stored/stored_dna // dna var for brain. Used to store dna, brain dna is not considered like actual dna, brain.has_dna() returns FALSE.
|
||||
stat = DEAD //we start dead by default
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
speech_span = SPAN_ROBOT
|
||||
|
||||
/mob/living/brain/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -10,14 +10,11 @@
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/brain/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/brain/radio(message, message_mode, list/spans, language)
|
||||
if(message_mode == MODE_HEADSET && istype(container, /obj/item/mmi))
|
||||
var/obj/item/mmi/R = container
|
||||
if(R.radio)
|
||||
R.radio.talk_into(src, message, , get_spans(), language)
|
||||
R.radio.talk_into(src, message, language = language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
else
|
||||
return initial(pixel_x)
|
||||
|
||||
/mob/living/carbon/alien/humanoid/get_permeability_protection()
|
||||
/mob/living/carbon/alien/humanoid/get_permeability_protection(list/target_zones)
|
||||
return 0.8
|
||||
|
||||
/mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno)
|
||||
|
||||
@@ -103,9 +103,13 @@
|
||||
name = "\improper royal parasite"
|
||||
desc = "Inject this into one of your grown children to promote her to a Praetorian!"
|
||||
icon_state = "alien_medal"
|
||||
item_flags = ABSTRACT | NODROP | DROPDEL
|
||||
item_flags = ABSTRACT | DROPDEL
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
|
||||
/obj/item/queenpromote/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
||||
|
||||
/obj/item/queenpromote/attack(mob/living/M, mob/living/carbon/alien/humanoid/user)
|
||||
if(!isalienadult(M) || isalienroyal(M))
|
||||
to_chat(user, "<span class='noticealien'>You may only use this with your adult, non-royal children!</span>")
|
||||
|
||||
@@ -59,15 +59,19 @@
|
||||
|
||||
/mob/living/carbon/alien/humanoid/update_inv_handcuffed()
|
||||
remove_overlay(HANDCUFF_LAYER)
|
||||
var/cuff_icon = "aliencuff"
|
||||
var/dmi_file = 'icons/mob/alien.dmi'
|
||||
|
||||
if(mob_size == MOB_SIZE_LARGE)
|
||||
cuff_icon = "aliencuff_[caste]"
|
||||
dmi_file = 'icons/mob/alienqueen.dmi'
|
||||
|
||||
if(handcuffed)
|
||||
overlays_standing[HANDCUFF_LAYER] = mutable_appearance(dmi_file, cuff_icon, -HANDCUFF_LAYER)
|
||||
var/cuff_icon = handcuffed.item_state
|
||||
var/dmi_file = 'icons/mob/alien.dmi'
|
||||
|
||||
if(mob_size == MOB_SIZE_LARGE)
|
||||
cuff_icon += "_[caste]"
|
||||
dmi_file = 'icons/mob/alienqueen.dmi'
|
||||
|
||||
var/mutable_appearance/cuffs = mutable_appearance(dmi_file, cuff_icon, -HANDCUFF_LAYER)
|
||||
cuffs.color = handcuffed.color
|
||||
|
||||
overlays_standing[HANDCUFF_LAYER] = cuffs
|
||||
apply_overlay(HANDCUFF_LAYER)
|
||||
|
||||
//Royals have bigger sprites, so inhand things must be handled differently.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
if(!message)
|
||||
return
|
||||
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/message_a = say_quote(message)
|
||||
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
for(var/mob/S in GLOB.player_list)
|
||||
if(!S.stat && S.hivecheck())
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
|
||||
|
||||
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success=TRUE)
|
||||
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(var/kill_on_sucess=TRUE)
|
||||
if(!owner || bursting)
|
||||
return
|
||||
|
||||
@@ -102,10 +102,12 @@
|
||||
new_xeno.notransform = 0
|
||||
new_xeno.invisibility = 0
|
||||
|
||||
if(gib_on_success)
|
||||
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner] in a shower of gore!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
|
||||
owner.gib(TRUE)
|
||||
else
|
||||
if(kill_on_sucess) //ITS TOO LATE
|
||||
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
|
||||
owner.apply_damage(rand(100,300),BRUTE,zone,FALSE) //Random high damage to torso so health sensors don't metagame.
|
||||
owner.spill_organs(TRUE,FALSE,TRUE) //Lets still make the death gruesome and impossible to just simply defib someone.
|
||||
owner.death(FALSE) //Just in case some freak occurance occurs where you somehow survive all your organs being removed from you and the 100-300 brute damage.
|
||||
else //When it is removed via surgery at a late stage, rather than forced.
|
||||
new_xeno.visible_message("<span class='danger'>[new_xeno] wriggles out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>")
|
||||
owner.adjustBruteLoss(40)
|
||||
owner.cut_overlay(overlay)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
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
|
||||
clothing_flags = MASKINTERNALS
|
||||
clothing_flags = ALLOWINTERNALS
|
||||
throw_range = 5
|
||||
tint = 3
|
||||
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
|
||||
@@ -33,16 +33,18 @@
|
||||
|
||||
/obj/item/clothing/mask/facehugger/lamarr
|
||||
name = "Lamarr"
|
||||
sterile = 1
|
||||
sterile = TRUE
|
||||
|
||||
/obj/item/clothing/mask/facehugger/dead
|
||||
icon_state = "facehugger_dead"
|
||||
item_state = "facehugger_inactive"
|
||||
sterile = TRUE
|
||||
stat = DEAD
|
||||
|
||||
/obj/item/clothing/mask/facehugger/impregnated
|
||||
icon_state = "facehugger_impregnated"
|
||||
item_state = "facehugger_impregnated"
|
||||
sterile = TRUE
|
||||
stat = DEAD
|
||||
|
||||
/obj/item/clothing/mask/facehugger/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
create_reagents(1000)
|
||||
update_body_parts() //to update the carbon's new bodyparts appearance
|
||||
GLOB.carbon_list += src
|
||||
blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio)
|
||||
|
||||
/mob/living/carbon/Destroy()
|
||||
//This must be done first, so the mob ghosts correctly before DNA etc is nulled
|
||||
@@ -175,7 +176,7 @@
|
||||
if(start_T && end_T)
|
||||
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
|
||||
else if(!(I.item_flags & (NODROP | ABSTRACT)))
|
||||
else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
|
||||
thrown_thing = I
|
||||
dropItemToGround(I)
|
||||
|
||||
@@ -238,7 +239,7 @@
|
||||
if(href_list["internal"])
|
||||
var/slot = text2num(href_list["internal"])
|
||||
var/obj/item/ITEM = get_item_by_slot(slot)
|
||||
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & MASKINTERNALS))
|
||||
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS))
|
||||
visible_message("<span class='danger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>", \
|
||||
"<span class='userdanger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>")
|
||||
if(do_mob(usr, src, POCKET_STRIP_DELAY))
|
||||
@@ -246,7 +247,7 @@
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else if(ITEM && istype(ITEM, /obj/item/tank))
|
||||
if((wear_mask && (wear_mask.clothing_flags & MASKINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if((wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
internal = ITEM
|
||||
update_internals_hud_icon(1)
|
||||
|
||||
@@ -409,7 +410,7 @@
|
||||
return initial(pixel_y)
|
||||
|
||||
/mob/living/carbon/proc/accident(obj/item/I)
|
||||
if(!I || (I.item_flags & (NODROP | ABSTRACT)))
|
||||
if(!I || (I.item_flags & ABSTRACT) || HAS_TRAIT(I, TRAIT_NODROP))
|
||||
return
|
||||
|
||||
//dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100
|
||||
@@ -477,11 +478,13 @@
|
||||
if(message)
|
||||
visible_message("<span class='danger'>[src] throws up all over [p_them()]self!</span>", \
|
||||
"<span class='userdanger'>You throw up all over yourself!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomitself)
|
||||
distance = 0
|
||||
else
|
||||
if(message)
|
||||
visible_message("<span class='danger'>[src] throws up!</span>", "<span class='userdanger'>You throw up!</span>")
|
||||
|
||||
if(!isflyperson(src))
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomit)
|
||||
if(stun)
|
||||
Stun(80)
|
||||
|
||||
@@ -634,6 +637,18 @@
|
||||
else
|
||||
. += INFINITY
|
||||
|
||||
/mob/living/carbon/get_permeability_protection(list/target_zones = list(HANDS,CHEST,GROIN,LEGS,FEET,ARMS,HEAD))
|
||||
var/list/tally = list()
|
||||
for(var/obj/item/I in get_equipped_items())
|
||||
for(var/zone in target_zones)
|
||||
if(I.body_parts_covered & zone)
|
||||
tally["[zone]"] = max(1 - I.permeability_coefficient, target_zones["[zone]"])
|
||||
var/protection = 0
|
||||
for(var/key in tally)
|
||||
protection += tally[key]
|
||||
protection *= INVERSE(target_zones.len)
|
||||
return protection
|
||||
|
||||
//this handles hud updates
|
||||
/mob/living/carbon/update_damage_hud()
|
||||
|
||||
@@ -687,9 +702,10 @@
|
||||
clear_fullscreen("critvision")
|
||||
|
||||
//Oxygen damage overlay
|
||||
if(oxyloss)
|
||||
var/windedup = getOxyLoss() + getStaminaLoss() * 0.2
|
||||
if(windedup)
|
||||
var/severity = 0
|
||||
switch(oxyloss)
|
||||
switch(windedup)
|
||||
if(10 to 20)
|
||||
severity = 1
|
||||
if(20 to 25)
|
||||
@@ -916,3 +932,17 @@
|
||||
|
||||
/mob/living/carbon/can_resist()
|
||||
return bodyparts.len > 2 && ..()
|
||||
|
||||
/mob/living/carbon/proc/hypnosis_vulnerable()//unused atm, but added in case
|
||||
if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
|
||||
return FALSE
|
||||
if(hallucinating())
|
||||
return TRUE
|
||||
if(IsSleeping())
|
||||
return TRUE
|
||||
if(HAS_TRAIT(src, TRAIT_DUMB))
|
||||
return TRUE
|
||||
GET_COMPONENT_FROM(mood, /datum/component/mood, src)
|
||||
if(mood)
|
||||
if(mood.sanity < SANITY_UNSTABLE)
|
||||
return TRUE
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
var/silent = FALSE //Can't talk. Value goes down every life proc. //NOTE TO FUTURE CODERS: DO NOT INITIALIZE NUMERICAL VARS AS NULL OR I WILL MURDER YOU.
|
||||
var/dreaming = 0 //How many dream images we have left to send
|
||||
|
||||
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/restraints/handcuffed //Whether or not the mob is handcuffed
|
||||
var/obj/item/restraints/legcuffed //Same as handcuffs but for legs. Bear traps use this.
|
||||
|
||||
var/disgust = 0
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
|
||||
msg += "[t_He] look[p_s()] extremely disgusted.\n"
|
||||
|
||||
if(blood_volume < BLOOD_VOLUME_SAFE)
|
||||
if(blood_volume < (BLOOD_VOLUME_SAFE*blood_ratio))
|
||||
msg += "[t_He] [t_has] pale skin.\n"
|
||||
|
||||
if(bleedsuppress)
|
||||
@@ -281,6 +281,13 @@
|
||||
if(91.01 to INFINITY)
|
||||
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
|
||||
|
||||
if(reagents.has_reagent("astral"))
|
||||
msg += "[t_He] have wild, spacey eyes"
|
||||
if(mind)
|
||||
msg += " and have a strange, abnormal look to them.\n"
|
||||
else
|
||||
msg += " and don't look like they're all there.\n"
|
||||
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(src != user && HAS_TRAIT(L, TRAIT_EMPATH) && !appears_dead)
|
||||
@@ -304,6 +311,13 @@
|
||||
|
||||
msg += "</span>"
|
||||
|
||||
var/obj/item/organ/vocal_cords/Vc = user.getorganslot(ORGAN_SLOT_VOICE)
|
||||
if(Vc)
|
||||
if(istype(Vc, /obj/item/organ/vocal_cords/velvet))
|
||||
if(client?.prefs.lewdchem)
|
||||
msg += "<span class='velvet'><i>You feel your chords resonate looking at them.</i></span>\n"
|
||||
|
||||
|
||||
if(!appears_dead)
|
||||
if(stat == UNCONSCIOUS)
|
||||
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
|
||||
var/delay_denominator = 1
|
||||
if(pocket_item && !(pocket_item.item_flags & ABSTRACT))
|
||||
if(pocket_item.item_flags & NODROP)
|
||||
if(HAS_TRAIT(pocket_item, TRAIT_NODROP))
|
||||
to_chat(usr, "<span class='warning'>You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!</span>")
|
||||
to_chat(usr, "<span class='notice'>You try to empty [src]'s [pocket_side] pocket.</span>")
|
||||
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.item_flags & ABSTRACT))
|
||||
@@ -623,6 +623,7 @@
|
||||
facial_hair_style = "Shaved"
|
||||
hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3")
|
||||
underwear = "Nude"
|
||||
undershirt = "Nude"
|
||||
update_body()
|
||||
update_hair()
|
||||
update_genitals()
|
||||
@@ -811,6 +812,8 @@
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
if(HM.quality != POSITIVE)
|
||||
dna.remove_mutation(HM.name)
|
||||
if(blood_volume < (BLOOD_VOLUME_NORMAL*blood_ratio))
|
||||
blood_volume = (BLOOD_VOLUME_NORMAL*blood_ratio)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker)
|
||||
@@ -899,12 +902,9 @@
|
||||
stop_pulling()
|
||||
|
||||
/mob/living/carbon/human/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this
|
||||
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
|
||||
for(var/bp in body_parts)
|
||||
if(istype(bp, /obj/item/clothing))
|
||||
var/obj/item/clothing/C = bp
|
||||
if(C.blocks_shove_knockdown)
|
||||
return TRUE
|
||||
for(var/obj/item/clothing/C in get_equipped_items()) //doesn't include pockets
|
||||
if(C.blocks_shove_knockdown)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/clear_shove_slowdown()
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
for(var/bp in body_parts)
|
||||
if(!bp)
|
||||
continue
|
||||
if(bp && istype(bp , /obj/item/clothing))
|
||||
if(istype(bp, /obj/item/clothing))
|
||||
var/obj/item/clothing/C = bp
|
||||
if(C.body_parts_covered & def_zone.body_part)
|
||||
protection += C.armor.getRating(d_type)
|
||||
@@ -654,6 +654,7 @@
|
||||
|
||||
if(health >= 0)
|
||||
if(src == M)
|
||||
var/to_send = ""
|
||||
visible_message("[src] examines [p_them()]self.", \
|
||||
"<span class='notice'>You check yourself for injuries.</span>")
|
||||
|
||||
@@ -700,53 +701,55 @@
|
||||
var/no_damage
|
||||
if(status == "OK" || status == "no damage")
|
||||
no_damage = TRUE
|
||||
to_chat(src, "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>")
|
||||
to_send += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>\n"
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
to_send += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>\n"
|
||||
|
||||
for(var/t in missing)
|
||||
to_chat(src, "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>")
|
||||
to_send += "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>\n"
|
||||
|
||||
if(bleed_rate)
|
||||
to_chat(src, "<span class='danger'>You are bleeding!</span>")
|
||||
to_send += "<span class='danger'>You are bleeding!</span>\n"
|
||||
if(getStaminaLoss())
|
||||
if(getStaminaLoss() > 30)
|
||||
to_chat(src, "<span class='info'>You're completely exhausted.</span>")
|
||||
to_send += "<span class='info'>You're completely exhausted.</span>\n"
|
||||
else
|
||||
to_chat(src, "<span class='info'>You feel fatigued.</span>")
|
||||
to_send += "<span class='info'>You feel fatigued.</span>\n"
|
||||
if(HAS_TRAIT(src, TRAIT_SELF_AWARE))
|
||||
if(toxloss)
|
||||
if(toxloss > 10)
|
||||
to_chat(src, "<span class='danger'>You feel sick.</span>")
|
||||
to_send += "<span class='danger'>You feel sick.</span>\n"
|
||||
else if(toxloss > 20)
|
||||
to_chat(src, "<span class='danger'>You feel nauseated.</span>")
|
||||
to_send += "<span class='danger'>You feel nauseated.</span>\n"
|
||||
else if(toxloss > 40)
|
||||
to_chat(src, "<span class='danger'>You feel very unwell!</span>")
|
||||
to_send += "<span class='danger'>You feel very unwell!</span>\n"
|
||||
if(oxyloss)
|
||||
if(oxyloss > 10)
|
||||
to_chat(src, "<span class='danger'>You feel lightheaded.</span>")
|
||||
to_send += "<span class='danger'>You feel lightheaded.</span>\n"
|
||||
else if(oxyloss > 20)
|
||||
to_chat(src, "<span class='danger'>Your thinking is clouded and distant.</span>")
|
||||
to_send += "<span class='danger'>Your thinking is clouded and distant.</span>\n"
|
||||
else if(oxyloss > 30)
|
||||
to_chat(src, "<span class='danger'>You're choking!</span>")
|
||||
to_send += "<span class='danger'>You're choking!</span>\n"
|
||||
|
||||
switch(nutrition)
|
||||
if(NUTRITION_LEVEL_FULL to INFINITY)
|
||||
to_chat(src, "<span class='info'>You're completely stuffed!</span>")
|
||||
to_send += "<span class='info'>You're completely stuffed!</span>\n"
|
||||
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
|
||||
to_chat(src, "<span class='info'>You're well fed!</span>")
|
||||
to_send += "<span class='info'>You're well fed!</span>\n"
|
||||
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
|
||||
to_chat(src, "<span class='info'>You're not hungry.</span>")
|
||||
to_send += "<span class='info'>You're not hungry.</span>\n"
|
||||
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
|
||||
to_chat(src, "<span class='info'>You could use a bite to eat.</span>")
|
||||
to_send += "<span class='info'>You could use a bite to eat.</span>\n"
|
||||
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
|
||||
to_chat(src, "<span class='info'>You feel quite hungry.</span>")
|
||||
to_send += "<span class='info'>You feel quite hungry.</span>\n"
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
to_chat(src, "<span class='danger'>You're starving!</span>")
|
||||
to_send += "<span class='danger'>You're starving!</span>\n"
|
||||
|
||||
if(roundstart_quirks.len)
|
||||
to_chat(src, "<span class='notice'>You have these quirks: [get_trait_string()].</span>")
|
||||
to_send += "<span class='notice'>You have these quirks: [get_trait_string()].</span>\n"
|
||||
|
||||
to_chat(src, to_send)
|
||||
else
|
||||
if(wear_suit)
|
||||
wear_suit.add_fingerprint(M)
|
||||
|
||||
@@ -25,9 +25,13 @@
|
||||
var/age = 30 //Player's age
|
||||
|
||||
var/underwear = "Nude" //Which underwear the player wants
|
||||
var/undie_color = "FFFFFF"
|
||||
var/undershirt = "Nude" //Which undershirt the player wants
|
||||
var/shirt_color = "FFFFFF"
|
||||
var/socks = "Nude" //Which socks the player wants
|
||||
var/socks_color = "FFFFFF"
|
||||
var/backbag = DBACKPACK //Which backpack type the player has chosen.
|
||||
var/jumpsuit_style = PREF_SUIT //suit/skirt
|
||||
|
||||
//Equipment slots
|
||||
var/obj/item/wear_suit = null
|
||||
@@ -44,6 +48,7 @@
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
var/name_override //For temporary visible name changes
|
||||
var/genital_override = FALSE //Force genitals on things incase of chems
|
||||
|
||||
var/nameless = FALSE //For drones of both the insectoid and robotic kind. And other types of nameless critters.
|
||||
|
||||
|
||||
@@ -111,26 +111,6 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/get_permeability_protection()
|
||||
var/list/prot = list("hands"=0, "chest"=0, "groin"=0, "legs"=0, "feet"=0, "arms"=0, "head"=0)
|
||||
for(var/obj/item/I in get_equipped_items())
|
||||
if(I.body_parts_covered & HANDS)
|
||||
prot["hands"] = max(1 - I.permeability_coefficient, prot["hands"])
|
||||
if(I.body_parts_covered & CHEST)
|
||||
prot["chest"] = max(1 - I.permeability_coefficient, prot["chest"])
|
||||
if(I.body_parts_covered & GROIN)
|
||||
prot["groin"] = max(1 - I.permeability_coefficient, prot["groin"])
|
||||
if(I.body_parts_covered & LEGS)
|
||||
prot["legs"] = max(1 - I.permeability_coefficient, prot["legs"])
|
||||
if(I.body_parts_covered & FEET)
|
||||
prot["feet"] = max(1 - I.permeability_coefficient, prot["feet"])
|
||||
if(I.body_parts_covered & ARMS)
|
||||
prot["arms"] = max(1 - I.permeability_coefficient, prot["arms"])
|
||||
if(I.body_parts_covered & HEAD)
|
||||
prot["head"] = max(1 - I.permeability_coefficient, prot["head"])
|
||||
var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7
|
||||
return protection
|
||||
|
||||
/mob/living/carbon/human/can_use_guns(obj/item/G)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -167,9 +167,9 @@
|
||||
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
|
||||
if(l_store)
|
||||
dropItemToGround(l_store, TRUE)
|
||||
if(wear_id)
|
||||
if(wear_id && !CHECK_BITFIELD(wear_id.item_flags, NO_UNIFORM_REQUIRED))
|
||||
dropItemToGround(wear_id)
|
||||
if(belt)
|
||||
if(belt && !CHECK_BITFIELD(belt.item_flags, NO_UNIFORM_REQUIRED))
|
||||
dropItemToGround(belt)
|
||||
w_uniform = null
|
||||
update_suit_sensors()
|
||||
|
||||
@@ -10,29 +10,6 @@
|
||||
else
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/human/treat_message(message)
|
||||
message = dna.species.handle_speech(message,src)
|
||||
if(diseases.len)
|
||||
for(var/datum/disease/pierrot_throat/D in diseases)
|
||||
var/list/temp_message = splittext(message, " ") //List each word in the message
|
||||
var/list/pick_list = list()
|
||||
for(var/i = 1, i <= temp_message.len, i++) //Create a second list for excluding words down the line
|
||||
pick_list += i
|
||||
for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words
|
||||
if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12%
|
||||
var/H = pick(pick_list)
|
||||
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":"))
|
||||
continue
|
||||
temp_message[H] = "HONK"
|
||||
pick_list -= H //Make sure that you dont HONK the same word twice
|
||||
message = jointext(temp_message, " ")
|
||||
message = ..(message)
|
||||
message = dna.mutations_say_mods(message)
|
||||
return message
|
||||
|
||||
/mob/living/carbon/human/get_spans()
|
||||
return ..() | dna.mutations_get_spans() | dna.species_get_spans()
|
||||
|
||||
/mob/living/carbon/human/GetVoice()
|
||||
if(istype(wear_mask, /obj/item/clothing/mask/chameleon))
|
||||
var/obj/item/clothing/mask/chameleon/V = wear_mask
|
||||
@@ -76,14 +53,14 @@
|
||||
if(ears)
|
||||
var/obj/item/radio/headset/dongle = ears
|
||||
if(!istype(dongle))
|
||||
return 0
|
||||
return FALSE
|
||||
if(dongle.translate_binary)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/human/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
return .
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(message_mode)
|
||||
if(MODE_HEADSET)
|
||||
|
||||
@@ -279,7 +279,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
|
||||
if(mutanthands)
|
||||
// Drop items in hands
|
||||
// If you're lucky enough to have a NODROP_1 item, then it stays.
|
||||
// If you're lucky enough to have a TRAIT_NODROP item, then it stays.
|
||||
for(var/V in C.held_items)
|
||||
var/obj/item/I = V
|
||||
if(istype(I))
|
||||
@@ -495,34 +495,42 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
if(H.hidden_underwear)
|
||||
H.underwear = "Nude"
|
||||
else
|
||||
H.underwear = H.saved_underwear
|
||||
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear]
|
||||
if(underwear)
|
||||
standing += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER)
|
||||
H.saved_underwear = H.underwear
|
||||
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
|
||||
if(B)
|
||||
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(B))
|
||||
MA.color = "#[H.undie_color]"
|
||||
standing += MA
|
||||
|
||||
if(H.undershirt)
|
||||
if(H.hidden_undershirt)
|
||||
H.undershirt = "Nude"
|
||||
else
|
||||
H.undershirt = H.saved_undershirt
|
||||
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
|
||||
if(undershirt)
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER)
|
||||
else
|
||||
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
|
||||
H.saved_undershirt = H.undershirt
|
||||
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
|
||||
if(T)
|
||||
var/mutable_appearance/MA
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
MA = wear_female_version(T.icon_state, T.icon, BODY_LAYER)
|
||||
else
|
||||
MA = mutable_appearance(T.icon, T.icon_state, -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(T))
|
||||
MA.color = "#[H.shirt_color]"
|
||||
standing += MA
|
||||
|
||||
if(H.socks && H.get_num_legs(FALSE) >= 2)
|
||||
if(H.hidden_socks)
|
||||
H.socks = "Nude"
|
||||
else
|
||||
H.socks = H.saved_socks
|
||||
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
|
||||
if(socks)
|
||||
if(DIGITIGRADE in species_traits)
|
||||
standing += mutable_appearance(socks.icon, socks.icon_state + "_d", -BODY_LAYER)
|
||||
else
|
||||
standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER)
|
||||
H.saved_socks = H.socks
|
||||
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
|
||||
if(S)
|
||||
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
|
||||
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(S))
|
||||
MA.color = "#[H.socks_color]"
|
||||
standing += MA
|
||||
|
||||
if(standing.len)
|
||||
H.overlays_standing[BODY_LAYER] = standing
|
||||
@@ -1011,13 +1019,12 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
if(SLOT_BELT)
|
||||
if(H.belt)
|
||||
return FALSE
|
||||
|
||||
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
|
||||
return FALSE
|
||||
if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED))
|
||||
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_BELT))
|
||||
return
|
||||
return equip_delay_self_check(I, H, bypass_equip_delay_self)
|
||||
@@ -1054,17 +1061,17 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
if(SLOT_WEAR_ID)
|
||||
if(H.wear_id)
|
||||
return FALSE
|
||||
|
||||
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
|
||||
return FALSE
|
||||
if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED))
|
||||
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
|
||||
if(!disable_warning)
|
||||
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
|
||||
return FALSE
|
||||
if( !(I.slot_flags & ITEM_SLOT_ID) )
|
||||
return FALSE
|
||||
return equip_delay_self_check(I, H, bypass_equip_delay_self)
|
||||
if(SLOT_L_STORE)
|
||||
if(I.item_flags & NODROP) //Pockets aren't visible, so you can't move NODROP_1 items into them.
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP)) //Pockets aren't visible, so you can't move TRAIT_NODROP items into them.
|
||||
return FALSE
|
||||
if(H.l_store)
|
||||
return FALSE
|
||||
@@ -1080,7 +1087,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
if( I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & ITEM_SLOT_POCKET) )
|
||||
return TRUE
|
||||
if(SLOT_R_STORE)
|
||||
if(I.item_flags & NODROP)
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP))
|
||||
return FALSE
|
||||
if(H.r_store)
|
||||
return FALSE
|
||||
@@ -1097,7 +1104,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(SLOT_S_STORE)
|
||||
if(I.item_flags & NODROP)
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP))
|
||||
return FALSE
|
||||
if(H.s_store)
|
||||
return FALSE
|
||||
@@ -1158,13 +1165,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
return 1
|
||||
return FALSE
|
||||
|
||||
/datum/species/proc/handle_speech(message, mob/living/carbon/human/H)
|
||||
return message
|
||||
|
||||
//return a list of spans or an empty list
|
||||
/datum/species/proc/get_spans()
|
||||
return list()
|
||||
|
||||
/datum/species/proc/check_weakness(obj/item, mob/living/attacker)
|
||||
return FALSE
|
||||
|
||||
@@ -1696,7 +1696,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
|
||||
if(H.stat == CONSCIOUS && H != user && prob(I.force + ((100 - H.health) * 0.5))) // rev deconversion through blunt trauma.
|
||||
var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev)
|
||||
var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang/)
|
||||
var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang && !/datum/antagonist/gang/boss)
|
||||
if(rev)
|
||||
rev.remove_revolutionary(FALSE, user)
|
||||
if(gang)
|
||||
|
||||
@@ -68,17 +68,17 @@
|
||||
|
||||
/obj/item/organ/tongue/dullahan
|
||||
zone = "abstract"
|
||||
modifies_speech = TRUE
|
||||
|
||||
/obj/item/organ/tongue/dullahan/TongueSpeech(var/message)
|
||||
/obj/item/organ/tongue/dullahan/handle_speech(datum/source, list/speech_args)
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.dna.species.id == "dullahan")
|
||||
var/datum/species/dullahan/D = H.dna.species
|
||||
if(isobj(D.myhead.loc))
|
||||
var/obj/O = D.myhead.loc
|
||||
O.say(message)
|
||||
message = ""
|
||||
return message
|
||||
O.say(speech_args[SPEECH_MESSAGE])
|
||||
speech_args[SPEECH_MESSAGE] = ""
|
||||
|
||||
/obj/item/organ/ears/dullahan
|
||||
zone = "abstract"
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
H.visible_message("<span class='warning'>[H] teleports!</span>", "<span class='danger'>You destabilize and teleport!</span>")
|
||||
new /obj/effect/particle_effect/sparks(get_turf(H))
|
||||
playsound(get_turf(H), "sparks", 50, 1)
|
||||
do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg')
|
||||
do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
last_teleport = world.time
|
||||
|
||||
/datum/species/golem/bluespace/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
|
||||
@@ -486,7 +486,7 @@
|
||||
spark_system.set_up(10, 0, src)
|
||||
spark_system.attach(H)
|
||||
spark_system.start()
|
||||
do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg')
|
||||
do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
last_teleport = world.time
|
||||
UpdateButtonIcon() //action icon looks unavailable
|
||||
sleep(cooldown + 5)
|
||||
@@ -519,6 +519,11 @@
|
||||
..()
|
||||
last_banana = world.time
|
||||
last_honk = world.time
|
||||
RegisterSignal(C, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
|
||||
/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
UnregisterSignal(C, COMSIG_MOB_SAY)
|
||||
|
||||
/datum/species/golem/bananium/random_name(gender,unique,lastname)
|
||||
var/clown_name = pick(GLOB.clown_names)
|
||||
@@ -567,9 +572,8 @@
|
||||
/datum/species/golem/bananium/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
playsound(get_turf(H), 'sound/misc/sadtrombone.ogg', 70, 0)
|
||||
|
||||
/datum/species/golem/bananium/get_spans()
|
||||
return list(SPAN_CLOWN)
|
||||
|
||||
/datum/species/golem/bananium/proc/handle_speech(datum/source, list/speech_args)
|
||||
speech_args[SPEECH_SPANS] |= SPAN_CLOWN
|
||||
|
||||
/datum/species/golem/runic
|
||||
name = "Runic Golem"
|
||||
@@ -646,14 +650,16 @@
|
||||
/datum/species/golem/clockwork/on_species_gain(mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
H.faction |= "ratvar"
|
||||
RegisterSignal(H, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
|
||||
/datum/species/golem/clockwork/on_species_loss(mob/living/carbon/human/H)
|
||||
if(!is_servant_of_ratvar(H))
|
||||
H.faction -= "ratvar"
|
||||
UnregisterSignal(H, COMSIG_MOB_SAY)
|
||||
. = ..()
|
||||
|
||||
/datum/species/golem/clockwork/get_spans()
|
||||
return SPAN_ROBOT //beep
|
||||
/datum/species/golem/clockwork/proc/handle_speech(datum/source, list/speech_args)
|
||||
speech_args[SPEECH_SPANS] |= SPAN_ROBOT //beep
|
||||
|
||||
/datum/species/golem/clockwork/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
gibbed = !has_corpse ? FALSE : gibbed
|
||||
@@ -951,7 +957,7 @@
|
||||
sexes = FALSE
|
||||
fixed_mut_color = "ffffff"
|
||||
attack_verb = "rattl"
|
||||
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS)
|
||||
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS)
|
||||
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH,TRAIT_CALCIUM_HEALER)
|
||||
info_text = "As a <span class='danger'>Bone Golem</span>, You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice."
|
||||
var/datum/action/innate/bonechill/bonechill
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
default_color = "00FF90"
|
||||
say_mod = "chirps"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD)
|
||||
mutantlungs = /obj/item/organ/lungs/slime
|
||||
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_snouts", "taur") //CIT CHANGE
|
||||
default_features = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None") //CIT CHANGE
|
||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||
@@ -13,7 +14,8 @@
|
||||
damage_overlay_type = ""
|
||||
var/datum/action/innate/regenerate_limbs/regenerate_limbs
|
||||
var/datum/action/innate/slime_change/slime_change //CIT CHANGE
|
||||
liked_food = MEAT
|
||||
liked_food = TOXIC | MEAT
|
||||
toxic_food = null
|
||||
coldmod = 6 // = 3x cold damage
|
||||
heatmod = 0.5 // = 1/4x heat damage
|
||||
burnmod = 0.5 // = 1/2x generic burn damage
|
||||
@@ -46,14 +48,14 @@
|
||||
H.adjustBruteLoss(5)
|
||||
to_chat(H, "<span class='danger'>You feel empty!</span>")
|
||||
|
||||
if(H.blood_volume < BLOOD_VOLUME_NORMAL)
|
||||
if(H.blood_volume < (BLOOD_VOLUME_NORMAL * H.blood_ratio))
|
||||
if(H.nutrition >= NUTRITION_LEVEL_STARVING)
|
||||
H.blood_volume += 3
|
||||
H.nutrition -= 2.5
|
||||
if(H.blood_volume < BLOOD_VOLUME_OKAY)
|
||||
if(H.blood_volume < (BLOOD_VOLUME_OKAY*H.blood_ratio))
|
||||
if(prob(5))
|
||||
to_chat(H, "<span class='danger'>You feel drained!</span>")
|
||||
if(H.blood_volume < BLOOD_VOLUME_BAD)
|
||||
if(H.blood_volume < (BLOOD_VOLUME_BAD*H.blood_ratio))
|
||||
Cannibalize_Body(H)
|
||||
if(regenerate_limbs)
|
||||
regenerate_limbs.UpdateButtonIcon()
|
||||
@@ -85,7 +87,7 @@
|
||||
var/list/limbs_to_heal = H.get_missing_limbs()
|
||||
if(limbs_to_heal.len < 1)
|
||||
return 0
|
||||
if(H.blood_volume >= BLOOD_VOLUME_OKAY+40)
|
||||
if(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -96,13 +98,13 @@
|
||||
to_chat(H, "<span class='notice'>You feel intact enough as it is.</span>")
|
||||
return
|
||||
to_chat(H, "<span class='notice'>You focus intently on your missing [limbs_to_heal.len >= 2 ? "limbs" : "limb"]...</span>")
|
||||
if(H.blood_volume >= 40*limbs_to_heal.len+BLOOD_VOLUME_OKAY)
|
||||
if(H.blood_volume >= 40*limbs_to_heal.len+(BLOOD_VOLUME_OKAY*H.blood_ratio))
|
||||
H.regenerate_limbs()
|
||||
H.blood_volume -= 40*limbs_to_heal.len
|
||||
to_chat(H, "<span class='notice'>...and after a moment you finish reforming!</span>")
|
||||
return
|
||||
else if(H.blood_volume >= 40)//We can partially heal some limbs
|
||||
while(H.blood_volume >= BLOOD_VOLUME_OKAY+40)
|
||||
while(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
|
||||
var/healed_limb = pick(limbs_to_heal)
|
||||
H.regenerate_limb(healed_limb)
|
||||
limbs_to_heal -= healed_limb
|
||||
@@ -136,7 +138,7 @@
|
||||
bodies -= C // This means that the other bodies maintain a link
|
||||
// so if someone mindswapped into them, they'd still be shared.
|
||||
bodies = null
|
||||
C.blood_volume = min(C.blood_volume, BLOOD_VOLUME_NORMAL)
|
||||
C.blood_volume = min(C.blood_volume, (BLOOD_VOLUME_NORMAL*C.blood_ratio))
|
||||
..()
|
||||
|
||||
/datum/species/jelly/slime/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
@@ -727,4 +729,4 @@
|
||||
to_chat(H, "<span class='notice'>You connect [target]'s mind to your slime link!</span>")
|
||||
else
|
||||
to_chat(H, "<span class='warning'>You can't seem to link [target]'s mind...</span>")
|
||||
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
||||
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
||||
|
||||
@@ -171,12 +171,14 @@
|
||||
armour_penetration = 35
|
||||
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
|
||||
item_flags = ABSTRACT | NODROP | DROPDEL
|
||||
item_flags = ABSTRACT | DROPDEL
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
sharpness = IS_SHARP
|
||||
total_mass = TOTAL_MASS_HAND_REPLACEMENT
|
||||
|
||||
/obj/item/light_eater/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT)
|
||||
AddComponent(/datum/component/butchering, 80, 70)
|
||||
|
||||
/obj/item/light_eater/afterattack(atom/movable/AM, mob/user, proximity)
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
..()
|
||||
assume_disguise(old_species, H)
|
||||
RegisterSignal(H, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
|
||||
/datum/species/synth/on_species_loss(mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
UnregisterSignal(H, COMSIG_MOB_SAY)
|
||||
|
||||
/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
|
||||
if(chem.id == "synthflesh")
|
||||
@@ -110,18 +115,12 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/species/synth/get_spans()
|
||||
if(fake_species)
|
||||
return fake_species.get_spans()
|
||||
return list()
|
||||
|
||||
|
||||
/datum/species/synth/handle_speech(message, mob/living/carbon/human/H)
|
||||
if(H.health > disguise_fail_health)
|
||||
if(fake_species)
|
||||
return fake_species.handle_speech(message,H)
|
||||
else
|
||||
return ..()
|
||||
else
|
||||
return ..()
|
||||
/datum/species/synth/proc/handle_speech(datum/source, list/speech_args)
|
||||
if (isliving(source)) // yeah it's gonna be living but just to be clean
|
||||
var/mob/living/L = source
|
||||
if(fake_species && L.health > disguise_fail_health)
|
||||
switch (fake_species.type)
|
||||
if (/datum/species/golem/bananium)
|
||||
speech_args[SPEECH_SPANS] |= SPAN_CLOWN
|
||||
if (/datum/species/golem/clockwork)
|
||||
speech_args[SPEECH_SPANS] |= SPAN_ROBOT
|
||||
@@ -46,7 +46,7 @@
|
||||
C.adjustCloneLoss(-4)
|
||||
return
|
||||
C.blood_volume -= 0.75
|
||||
if(C.blood_volume <= BLOOD_VOLUME_SURVIVE)
|
||||
if(C.blood_volume <= (BLOOD_VOLUME_SURVIVE*C.blood_ratio))
|
||||
to_chat(C, "<span class='danger'>You ran out of blood!</span>")
|
||||
C.dust()
|
||||
var/area/A = get_area(C)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Knockdown(amount, updating = 1, ignore_canknockdown = 0)
|
||||
/mob/living/carbon/human/Knockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -288,8 +288,10 @@ There are several things that need to be remembered:
|
||||
S.alternate_worn_icon = 'modular_citadel/icons/mob/digishoes.dmi'
|
||||
else
|
||||
S.alternate_worn_icon = null
|
||||
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.alternate_worn_icon) ? shoes.alternate_worn_icon : 'icons/mob/feet.dmi'))
|
||||
var/t_state = shoes.item_state
|
||||
if (!t_state)
|
||||
t_state = shoes.icon_state
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = t_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.alternate_worn_icon) ? shoes.alternate_worn_icon : 'icons/mob/feet.dmi'))
|
||||
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
|
||||
if(OFFSET_SHOES in dna.species.offset_features)
|
||||
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
|
||||
@@ -377,13 +379,16 @@ There are several things that need to be remembered:
|
||||
|
||||
if(wear_suit)
|
||||
var/obj/item/clothing/suit/S = wear_suit
|
||||
var/no_taur_thanks = FALSE
|
||||
if(!istype(S))
|
||||
no_taur_thanks = TRUE
|
||||
wear_suit.screen_loc = ui_oclothing
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += wear_suit
|
||||
update_observer_view(wear_suit,1)
|
||||
|
||||
if(S.mutantrace_variation) //Just make sure we've got this checked too
|
||||
if(!no_taur_thanks && S.mutantrace_variation) //Just make sure we've got this checked too
|
||||
if(S.taurmode == NOT_TAURIC && S.adjusted == ALT_STYLE) //are we not a taur, but we have Digitigrade legs? Run this check first, then.
|
||||
S.alternate_worn_icon = 'modular_citadel/icons/mob/suit_digi.dmi'
|
||||
else
|
||||
@@ -404,7 +409,7 @@ There are several things that need to be remembered:
|
||||
if(OFFSET_SUIT in dna.species.offset_features)
|
||||
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
|
||||
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
|
||||
if(S.center)
|
||||
if(!no_taur_thanks && S.center)
|
||||
suit_overlay = center_image(suit_overlay, S.dimension_x, S.dimension_y)
|
||||
overlays_standing[SUIT_LAYER] = suit_overlay
|
||||
update_hair()
|
||||
@@ -468,14 +473,6 @@ There are several things that need to be remembered:
|
||||
overlays_standing[BACK_LAYER] = back_overlay
|
||||
apply_overlay(BACK_LAYER)
|
||||
|
||||
/mob/living/carbon/human/update_inv_legcuffed()
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
clear_alert("legcuffed")
|
||||
if(legcuffed)
|
||||
overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER)
|
||||
apply_overlay(LEGCUFF_LAYER)
|
||||
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
|
||||
|
||||
/proc/wear_female_version(t_color, icon, layer, type)
|
||||
var/index = t_color
|
||||
var/icon/female_clothing_icon = GLOB.female_clothing_icons[index]
|
||||
|
||||
@@ -88,4 +88,4 @@
|
||||
AM.Hear(rendered, src, language, message, , spans)
|
||||
|
||||
if(critical) //Dying words.
|
||||
succumb(1)
|
||||
succumb()
|
||||
|
||||
@@ -228,6 +228,9 @@
|
||||
else if(SA_partialpressure > 0.01)
|
||||
if(prob(20))
|
||||
emote(pick("giggle","laugh"))
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "chemical_euphoria", /datum/mood_event/chemical_euphoria)
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria")
|
||||
|
||||
//BZ (Facepunch port of their Agent B)
|
||||
if(breath_gases[/datum/gas/bz])
|
||||
@@ -250,38 +253,39 @@
|
||||
//MIASMA
|
||||
if(breath_gases[/datum/gas/miasma])
|
||||
var/miasma_partialpressure = (breath_gases[/datum/gas/miasma]/breath.total_moles())*breath_pressure
|
||||
if(miasma_partialpressure > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
|
||||
if(prob(1 * miasma_partialpressure))
|
||||
var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2,3)
|
||||
miasma_disease.name = "Unknown"
|
||||
ForceContractDisease(miasma_disease, TRUE, TRUE)
|
||||
if(prob(0.05 * miasma_partialpressure))
|
||||
var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2,3)
|
||||
miasma_disease.name = "Unknown"
|
||||
ForceContractDisease(miasma_disease, TRUE, TRUE)
|
||||
|
||||
//Miasma side effects
|
||||
switch(miasma_partialpressure)
|
||||
if(1 to 5)
|
||||
// At lower pp, give out a little warning
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='notice'>There is an unpleasant smell in the air.</span>")
|
||||
if(5 to 20)
|
||||
//At somewhat higher pp, warning becomes more obvious
|
||||
if(prob(15))
|
||||
to_chat(src, "<span class='warning'>You smell something horribly decayed inside this room.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/bad_smell)
|
||||
if(15 to 30)
|
||||
//Small chance to vomit. By now, people have internals on anyway
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
|
||||
vomit()
|
||||
if(30 to INFINITY)
|
||||
//Higher chance to vomit. Let the horror start
|
||||
if(prob(25))
|
||||
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
|
||||
vomit()
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
//Miasma side effects
|
||||
switch(miasma_partialpressure)
|
||||
if(1 to 5)
|
||||
// At lower pp, give out a little warning
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='notice'>There is an unpleasant smell in the air.</span>")
|
||||
if(5 to 20)
|
||||
//At somewhat higher pp, warning becomes more obvious
|
||||
if(prob(15))
|
||||
to_chat(src, "<span class='warning'>You smell something horribly decayed inside this room.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/bad_smell)
|
||||
if(15 to 30)
|
||||
//Small chance to vomit. By now, people have internals on anyway
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
|
||||
vomit()
|
||||
if(30 to INFINITY)
|
||||
//Higher chance to vomit. Let the horror start
|
||||
if(prob(25))
|
||||
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
|
||||
vomit()
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
|
||||
|
||||
|
||||
//Clear all moods if no miasma at all
|
||||
@@ -303,11 +307,17 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/proc/get_breath_from_internal(volume_needed)
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
|
||||
for(check in GET_INTERNAL_SLOTS(src))
|
||||
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(internal)
|
||||
if(internal.loc != src)
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else if ((!wear_mask || !(wear_mask.clothing_flags & MASKINTERNALS)) && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
else if (!internals && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else
|
||||
@@ -344,7 +354,7 @@
|
||||
|
||||
var/list/cached_gases = miasma_turf.air.gases
|
||||
|
||||
cached_gases[/datum/gas/miasma] += 0.02
|
||||
cached_gases[/datum/gas/miasma] += 0.1
|
||||
|
||||
/mob/living/carbon/proc/handle_blood()
|
||||
return
|
||||
@@ -525,6 +535,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
if(jitteriness)
|
||||
do_jitter_animation(jitteriness)
|
||||
jitteriness = max(jitteriness - restingpwr, 0)
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "jittery", /datum/mood_event/jittery)
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "jittery")
|
||||
|
||||
if(stuttering)
|
||||
stuttering = max(stuttering-1, 0)
|
||||
@@ -610,6 +623,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
|
||||
if(drunkenness >= 101)
|
||||
adjustToxLoss(4) //Let's be honest you shouldn't be alive by now
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "drunk")
|
||||
|
||||
//used in human and monkey handle_environment()
|
||||
/mob/living/carbon/proc/natural_bodytemperature_stabilization()
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
/mob/living/carbon/monkey/proc/handle_combat()
|
||||
if(pickupTarget)
|
||||
if(restrained() || blacklistItems[pickupTarget] || (pickupTarget.item_flags & NODROP))
|
||||
if(restrained() || blacklistItems[pickupTarget] || HAS_TRAIT(pickupTarget, TRAIT_NODROP))
|
||||
pickupTarget = null
|
||||
else
|
||||
pickupTimer++
|
||||
|
||||
@@ -152,15 +152,6 @@
|
||||
|
||||
return threatcount
|
||||
|
||||
/mob/living/carbon/monkey/get_permeability_protection()
|
||||
var/protection = 0
|
||||
if(head)
|
||||
protection = 1 - head.permeability_coefficient
|
||||
if(wear_mask)
|
||||
protection = max(1 - wear_mask.permeability_coefficient, protection)
|
||||
protection = protection/7 //the rest of the body isn't covered.
|
||||
return protection
|
||||
|
||||
/mob/living/carbon/monkey/IsVocal()
|
||||
if(!getorganslot(ORGAN_SLOT_LUNGS))
|
||||
return 0
|
||||
|
||||
@@ -43,12 +43,15 @@
|
||||
|
||||
/mob/living/carbon/monkey/update_inv_legcuffed()
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
clear_alert("legcuffed")
|
||||
if(legcuffed)
|
||||
var/mutable_appearance/legcuff_overlay = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER)
|
||||
legcuff_overlay.pixel_y = 8
|
||||
overlays_standing[LEGCUFF_LAYER] = legcuff_overlay
|
||||
apply_overlay(LEGCUFF_LAYER)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
legcuffs.color = handcuffed.color
|
||||
legcuffs.pixel_y = 8
|
||||
|
||||
overlays_standing[HANDCUFF_LAYER] = legcuffs
|
||||
apply_overlay(LEGCUFF_LAYER)
|
||||
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
|
||||
|
||||
//monkey HUD updates for items in our inventory
|
||||
|
||||
|
||||
@@ -1,37 +1,17 @@
|
||||
/mob/living/carbon/treat_message(message)
|
||||
for(var/datum/brain_trauma/trauma in get_traumas())
|
||||
message = trauma.on_say(message)
|
||||
message = ..(message)
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(!T) //hoooooouaah!
|
||||
var/regex/tongueless_lower = new("\[gdntke]+", "g")
|
||||
var/regex/tongueless_upper = new("\[GDNTKE]+", "g")
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
message = tongueless_lower.Replace(message, pick("aa","oo","'"))
|
||||
message = tongueless_upper.Replace(message, pick("AA","OO","'"))
|
||||
else
|
||||
message = T.TongueSpeech(message)
|
||||
if(wear_mask)
|
||||
message = wear_mask.speechModification(message)
|
||||
if(head)
|
||||
message = head.speechModification(message)
|
||||
return message
|
||||
/mob/living/carbon/proc/handle_tongueless_speech(mob/living/carbon/speaker, list/speech_args)
|
||||
var/message = speech_args[SPEECH_MESSAGE]
|
||||
var/static/regex/tongueless_lower = new("\[gdntke]+", "g")
|
||||
var/static/regex/tongueless_upper = new("\[GDNTKE]+", "g")
|
||||
if(message[1] != "*")
|
||||
message = tongueless_lower.Replace(message, pick("aa","oo","'"))
|
||||
message = tongueless_upper.Replace(message, pick("AA","OO","'"))
|
||||
speech_args[SPEECH_MESSAGE] = message
|
||||
|
||||
/mob/living/carbon/can_speak_vocal(message)
|
||||
if(silent)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/get_spans()
|
||||
. = ..()
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(T)
|
||||
. |= T.get_spans()
|
||||
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I)
|
||||
. |= I.get_held_item_speechspans(src)
|
||||
|
||||
/mob/living/carbon/could_speak_in_language(datum/language/dt)
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(T)
|
||||
@@ -48,12 +28,7 @@
|
||||
message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
|
||||
if (src.mind.has_antag_datum(/datum/antagonist/traitor))
|
||||
for (var/codeword in GLOB.syndicate_code_phrase)
|
||||
var/regex/codeword_match = new("([codeword])", "ig")
|
||||
message = codeword_match.Replace(message, "<span class='blue'>$1</span>")
|
||||
|
||||
for (var/codeword in GLOB.syndicate_code_response)
|
||||
var/regex/codeword_match = new("([codeword])", "ig")
|
||||
message = codeword_match.Replace(message, "<span class='red'>$1</span>")
|
||||
message = GLOB.syndicate_code_phrase_regex.Replace(message, "<span class='blue'>$1</span>")
|
||||
message = GLOB.syndicate_code_response_regex.Replace(message, "<span class='red'>$1</span>")
|
||||
|
||||
return message
|
||||
|
||||
@@ -176,9 +176,22 @@
|
||||
/mob/living/carbon/update_inv_handcuffed()
|
||||
remove_overlay(HANDCUFF_LAYER)
|
||||
if(handcuffed)
|
||||
overlays_standing[HANDCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "handcuff1", -HANDCUFF_LAYER)
|
||||
var/mutable_appearance/cuffs = mutable_appearance('icons/mob/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER)
|
||||
cuffs.color = handcuffed.color
|
||||
|
||||
overlays_standing[HANDCUFF_LAYER] = cuffs
|
||||
apply_overlay(HANDCUFF_LAYER)
|
||||
|
||||
/mob/living/carbon/update_inv_legcuffed()
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
clear_alert("legcuffed")
|
||||
if(legcuffed)
|
||||
var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER)
|
||||
legcuffs.color = legcuffed.color
|
||||
|
||||
overlays_standing[HANDCUFF_LAYER] = legcuffs
|
||||
apply_overlay(LEGCUFF_LAYER)
|
||||
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
|
||||
|
||||
//mob HUD updates for items in our inventory
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
var/datum/disease/D = thing
|
||||
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
|
||||
ContactContractDisease(D)
|
||||
|
||||
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
if(HAS_TRAIT(src, TRAIT_STRONG_GRABBER))
|
||||
@@ -318,17 +318,27 @@
|
||||
visible_message("<b>[src]</b> points at [A].", "<span class='notice'>You point at [A].</span>")
|
||||
return TRUE
|
||||
|
||||
/mob/living/verb/succumb(whispered as null)
|
||||
/mob/living/verb/succumb()
|
||||
set name = "Succumb"
|
||||
set category = "IC"
|
||||
if(src.has_status_effect(/datum/status_effect/chem/enthrall))
|
||||
var/datum/status_effect/chem/enthrall/E = src.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
if(E.phase < 3)
|
||||
if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
|
||||
to_chat(src, "<span class='notice'>Your mindshield prevents your mind from giving in!</span>")
|
||||
else if(src.mind.assigned_role in GLOB.command_positions)
|
||||
to_chat(src, "<span class='notice'>Your dedication to your department prevents you from giving in!</span>")
|
||||
else
|
||||
E.enthrallTally += 20
|
||||
to_chat(src, "<span class='notice'>You give into [E.master]'s influence.</span>")
|
||||
if (InCritical())
|
||||
log_message("Has [whispered ? "whispered his final words" : "succumbed to death"] while in [InFullCritical() ? "hard":"soft"] critical with [round(health, 0.1)] points of health!", LOG_ATTACK)
|
||||
log_message("Has succumbed to death while in [InFullCritical() ? "hard":"soft"] critical with [round(health, 0.1)] points of health!", LOG_ATTACK)
|
||||
adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
|
||||
updatehealth()
|
||||
if(!whispered)
|
||||
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
|
||||
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
|
||||
death()
|
||||
|
||||
|
||||
/mob/living/incapacitated(ignore_restraints, ignore_grab)
|
||||
if(stat || IsUnconscious() || IsStun() || IsKnockdown() || recoveringstam || (!ignore_restraints && restrained(ignore_grab))) // CIT CHANGE - adds recoveringstam check here
|
||||
return TRUE
|
||||
@@ -532,7 +542,7 @@
|
||||
var/trail_type = getTrail()
|
||||
if(trail_type)
|
||||
var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
|
||||
if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
|
||||
if(blood_volume && blood_volume > max((BLOOD_VOLUME_NORMAL*blood_ratio)*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
|
||||
blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage.
|
||||
var/newdir = get_dir(target_turf, start)
|
||||
if(newdir != direction)
|
||||
@@ -626,14 +636,15 @@
|
||||
else if(canmove)
|
||||
if(on_fire)
|
||||
resist_fire() //stop, drop, and roll
|
||||
else if(resting) //cit change - allows resisting out of resting
|
||||
return
|
||||
if(resting) //cit change - allows resisting out of resting
|
||||
resist_a_rest() // ditto
|
||||
else if(iscarbon(src)) //Citadel Change for embedded removal memes
|
||||
var/mob/living/carbon/C = src
|
||||
if(!C.handcuffed && !C.legcuffed)
|
||||
return TRUE
|
||||
else if(last_special <= world.time)
|
||||
return
|
||||
if(resist_embedded()) //Citadel Change for embedded removal memes
|
||||
return
|
||||
if(last_special <= world.time)
|
||||
resist_restraints() //trying to remove cuffs.
|
||||
return
|
||||
|
||||
|
||||
/mob/proc/resist_grab(moving_resist)
|
||||
@@ -699,7 +710,7 @@
|
||||
// The src mob is trying to strip an item from someone
|
||||
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
|
||||
/mob/living/stripPanelUnequip(obj/item/what, mob/who, where)
|
||||
if(what.item_flags & NODROP)
|
||||
if(HAS_TRAIT(what, TRAIT_NODROP))
|
||||
to_chat(src, "<span class='warning'>You can't remove \the [what.name], it appears to be stuck!</span>")
|
||||
return
|
||||
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
|
||||
@@ -724,7 +735,7 @@
|
||||
// Override if a certain mob should be behave differently when placing items (can't, for example)
|
||||
/mob/living/stripPanelEquip(obj/item/what, mob/who, where)
|
||||
what = src.get_active_held_item()
|
||||
if(what && (what.item_flags & NODROP))
|
||||
if(what && HAS_TRAIT(what, TRAIT_NODROP))
|
||||
to_chat(src, "<span class='warning'>You can't put \the [what.name] on [who], it's stuck to your hand!</span>")
|
||||
return
|
||||
if(what)
|
||||
@@ -813,7 +824,7 @@
|
||||
return 1
|
||||
|
||||
//used in datum/reagents/reaction() proc
|
||||
/mob/living/proc/get_permeability_protection()
|
||||
/mob/living/proc/get_permeability_protection(list/target_zones)
|
||||
return 0
|
||||
|
||||
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
|
||||
|
||||
var/blood_volume = 0 //how much blood the mob has
|
||||
var/blood_ratio = 1 //How much blood the mob needs, in terms of ratio (i.e 1.2 will require BLOOD_VOLUME_NORMAL of 672) DO NOT GO ABOVE 3.55 Well, actually you can but, then they can't get enough blood.
|
||||
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
|
||||
|
||||
var/see_override = 0 //0 for no override, sets see_invisible = see_override in silicon & carbon life process via update_sight()
|
||||
|
||||
@@ -2,61 +2,61 @@ GLOBAL_LIST_INIT(department_radio_prefixes, list(":", "."))
|
||||
|
||||
GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
// Location
|
||||
"r" = "right hand",
|
||||
"l" = "left hand",
|
||||
"i" = "intercom",
|
||||
MODE_KEY_R_HAND = MODE_R_HAND,
|
||||
MODE_KEY_L_HAND = MODE_L_HAND,
|
||||
MODE_KEY_INTERCOM = MODE_INTERCOM,
|
||||
|
||||
// Department
|
||||
"h" = "department",
|
||||
"c" = "Command",
|
||||
"n" = "Science",
|
||||
"m" = "Medical",
|
||||
"e" = "Engineering",
|
||||
"s" = "Security",
|
||||
"u" = "Supply",
|
||||
"v" = "Service",
|
||||
MODE_KEY_DEPARTMENT = MODE_DEPARTMENT,
|
||||
RADIO_KEY_COMMAND = RADIO_CHANNEL_COMMAND,
|
||||
RADIO_KEY_SCIENCE = RADIO_CHANNEL_SCIENCE,
|
||||
RADIO_KEY_MEDICAL = RADIO_CHANNEL_MEDICAL,
|
||||
RADIO_KEY_ENGINEERING = RADIO_CHANNEL_ENGINEERING,
|
||||
RADIO_KEY_SECURITY = RADIO_CHANNEL_SECURITY,
|
||||
RADIO_KEY_SUPPLY = RADIO_CHANNEL_SUPPLY,
|
||||
RADIO_KEY_SERVICE = RADIO_CHANNEL_SERVICE,
|
||||
|
||||
// Faction
|
||||
"t" = "Syndicate",
|
||||
"y" = "CentCom",
|
||||
RADIO_KEY_SYNDICATE = RADIO_CHANNEL_SYNDICATE,
|
||||
RADIO_KEY_CENTCOM = RADIO_CHANNEL_CENTCOM,
|
||||
|
||||
// Admin
|
||||
"p" = "admin",
|
||||
"d" = "deadmin",
|
||||
MODE_KEY_ADMIN = MODE_ADMIN,
|
||||
MODE_KEY_DEADMIN = MODE_DEADMIN,
|
||||
|
||||
// Misc
|
||||
"o" = "AI Private", // AI Upload channel
|
||||
"x" = "cords", // vocal cords, used by Voice of God
|
||||
RADIO_KEY_AI_PRIVATE = RADIO_CHANNEL_AI_PRIVATE, // AI Upload channel
|
||||
MODE_KEY_VOCALCORDS = MODE_VOCALCORDS, // vocal cords, used by Voice of God
|
||||
|
||||
|
||||
//kinda localization -- rastaf0
|
||||
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
|
||||
// Location
|
||||
"ê" = "right hand",
|
||||
"ä" = "left hand",
|
||||
"ø" = "intercom",
|
||||
"ê" = MODE_R_HAND,
|
||||
"ä" = MODE_L_HAND,
|
||||
"ø" = MODE_INTERCOM,
|
||||
|
||||
// Department
|
||||
"ð" = "department",
|
||||
"ñ" = "Command",
|
||||
"ò" = "Science",
|
||||
"ü" = "Medical",
|
||||
"ó" = "Engineering",
|
||||
"û" = "Security",
|
||||
"ã" = "Supply",
|
||||
"ì" = "Service",
|
||||
"ð" = MODE_DEPARTMENT,
|
||||
"ñ" = RADIO_CHANNEL_COMMAND,
|
||||
"ò" = RADIO_CHANNEL_SCIENCE,
|
||||
"ü" = RADIO_CHANNEL_MEDICAL,
|
||||
"ó" = RADIO_CHANNEL_ENGINEERING,
|
||||
"û" = RADIO_CHANNEL_SECURITY,
|
||||
"ã" = RADIO_CHANNEL_SUPPLY,
|
||||
"ì" = RADIO_CHANNEL_SERVICE,
|
||||
|
||||
// Faction
|
||||
"å" = "Syndicate",
|
||||
"í" = "CentCom",
|
||||
"å" = RADIO_CHANNEL_SYNDICATE,
|
||||
"í" = RADIO_CHANNEL_CENTCOM,
|
||||
|
||||
// Admin
|
||||
"ç" = "admin",
|
||||
"â" = "deadmin",
|
||||
"ç" = MODE_ADMIN,
|
||||
"â" = MODE_ADMIN,
|
||||
|
||||
// Misc
|
||||
"ù" = "AI Private",
|
||||
"÷" = "cords"
|
||||
"ù" = RADIO_CHANNEL_AI_PRIVATE,
|
||||
"÷" = MODE_VOCALCORDS
|
||||
))
|
||||
|
||||
/mob/living/proc/Ellipsis(original_msg, chance = 50, keep_words)
|
||||
@@ -105,12 +105,12 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
if(findtext(message, " ", 1, 2))
|
||||
message = copytext(message, 2)
|
||||
|
||||
if(message_mode == "admin")
|
||||
if(message_mode == MODE_ADMIN)
|
||||
if(client)
|
||||
client.cmd_admin_say(message)
|
||||
return
|
||||
|
||||
if(message_mode == "deadmin")
|
||||
if(message_mode == MODE_DEADMIN)
|
||||
if(client)
|
||||
client.dsay(message)
|
||||
return
|
||||
@@ -175,13 +175,16 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
else
|
||||
src.log_talk(message, LOG_SAY, forced_by=forced)
|
||||
|
||||
message = treat_message(message)
|
||||
message = treat_message(message) // unfortunately we still need this
|
||||
var/sigreturn = SEND_SIGNAL(src, COMSIG_MOB_SAY, args)
|
||||
if (sigreturn & COMPONENT_UPPERCASE_SPEECH)
|
||||
message = uppertext(message)
|
||||
if(!message)
|
||||
return
|
||||
|
||||
last_words = message
|
||||
|
||||
spans |= get_spans()
|
||||
spans |= speech_span
|
||||
|
||||
if(language)
|
||||
var/datum/language/L = GLOB.language_datum_instances[language]
|
||||
@@ -208,7 +211,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
send_speech(message, message_range, src, bubble_type, spans, language, message_mode)
|
||||
|
||||
if(succumbed)
|
||||
succumb(1)
|
||||
succumb()
|
||||
to_chat(src, compose_message(src, language, message, , spans, message_mode))
|
||||
|
||||
return 1
|
||||
@@ -278,6 +281,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mode)
|
||||
else
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
|
||||
|
||||
//speech bubble
|
||||
var/list/speech_bubble_recipients = list()
|
||||
@@ -332,6 +336,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
return null
|
||||
|
||||
/mob/living/proc/treat_message(message)
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_UNINTELLIGIBLE_SPEECH))
|
||||
message = unintelligize(message)
|
||||
|
||||
if(derpspeech)
|
||||
message = derpspeech(message, stuttering)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
else
|
||||
padloc = "(UNKNOWN)"
|
||||
src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]")
|
||||
send_speech(message, 7, T, "robot", get_spans(), language)
|
||||
send_speech(message, 7, T, "robot", language = language)
|
||||
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
|
||||
else
|
||||
to_chat(src, "No holopad connected.")
|
||||
@@ -100,6 +100,8 @@
|
||||
|
||||
last_announcement = message
|
||||
|
||||
var/voxType = input(src, "Male or female VOX?", "VOX-gender") in list("male", "female")
|
||||
|
||||
if(!message || announcing_vox > world.time)
|
||||
return
|
||||
|
||||
@@ -121,7 +123,9 @@
|
||||
if(!word)
|
||||
words -= word
|
||||
continue
|
||||
if(!GLOB.vox_sounds[word])
|
||||
if(!GLOB.vox_sounds[word] && voxType == "female")
|
||||
incorrect_words += word
|
||||
if(!GLOB.vox_sounds_male[word] && voxType == "male")
|
||||
incorrect_words += word
|
||||
|
||||
if(incorrect_words.len)
|
||||
@@ -133,16 +137,21 @@
|
||||
log_game("[key_name(src)] made a vocal announcement with the following message: [message].")
|
||||
|
||||
for(var/word in words)
|
||||
play_vox_word(word, src.z, null)
|
||||
play_vox_word(word, src.z, null, voxType)
|
||||
|
||||
|
||||
/proc/play_vox_word(word, z_level, mob/only_listener)
|
||||
/proc/play_vox_word(word, z_level, mob/only_listener, voxType = "female")
|
||||
|
||||
word = lowertext(word)
|
||||
|
||||
if(GLOB.vox_sounds[word])
|
||||
if( (GLOB.vox_sounds[word] && voxType == "female") || (GLOB.vox_sounds_male[word] && voxType == "male") )
|
||||
|
||||
var/sound_file = GLOB.vox_sounds[word]
|
||||
var/sound_file
|
||||
|
||||
if(voxType == "female")
|
||||
sound_file = GLOB.vox_sounds[word]
|
||||
else
|
||||
sound_file = GLOB.vox_sounds_male[word]
|
||||
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
|
||||
voice.status = SOUND_STREAM
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
if(!L.temporarilyRemoveItemFromInventory(card))
|
||||
to_chat(src, "<span class='warning'>Error: Unable to expand to mobile form. Chassis is restrained by some device or person.</span>")
|
||||
return FALSE
|
||||
if(istype(card.loc, /obj/item/integrated_circuit/input/pAI_connector))
|
||||
var/obj/item/integrated_circuit/input/pAI_connector/C = card.loc
|
||||
C.RemovepAI()
|
||||
C.visible_message("<span class='notice'>[src] ejects itself from [C]!</span>")
|
||||
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
C.installed_pai = null
|
||||
C.push_data()
|
||||
forceMove(get_turf(card))
|
||||
card.forceMove(src)
|
||||
if(client)
|
||||
|
||||
@@ -92,17 +92,18 @@
|
||||
|
||||
/mob/living/silicon/robot/emag_act(mob/user)
|
||||
if(user == src)//To prevent syndieborgs from emagging themselves
|
||||
return
|
||||
return FALSE
|
||||
if(world.time < emag_cooldown)
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(!opened)//Cover is closed
|
||||
if(locked)
|
||||
to_chat(user, "<span class='notice'>You emag the cover lock.</span>")
|
||||
locked = FALSE
|
||||
if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them.
|
||||
to_chat(user, "<span class='boldwarning'>[src] seems to be controlled remotely! Emagging the interface may not work as expected.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The cover is already unlocked!</span>")
|
||||
return
|
||||
if(world.time < emag_cooldown)
|
||||
return TRUE
|
||||
to_chat(user, "<span class='warning'>The cover is already unlocked!</span>")
|
||||
return
|
||||
if(wiresexposed)
|
||||
to_chat(user, "<span class='warning'>You must unexpose the wires first!</span>")
|
||||
@@ -115,20 +116,24 @@
|
||||
to_chat(src, "<span class='nezbere'>\"[text2ratvar("You will serve Engine above all else")]!\"</span>\n\
|
||||
<span class='danger'>ALERT: Subversion attempt denied.</span>")
|
||||
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they serve only Ratvar.")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(connected_ai && connected_ai.mind && connected_ai.mind.has_antag_datum(/datum/antagonist/traitor))
|
||||
to_chat(src, "<span class='danger'>ALERT: Foreign software execution prevented.</span>")
|
||||
to_chat(connected_ai, "<span class='danger'>ALERT: Cyborg unit \[[src]] successfully defended against subversion.</span>")
|
||||
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(shell) //AI shells cannot be emagged, so we try to make it look like a standard reset. Smart players may see through this, however.
|
||||
to_chat(user, "<span class='danger'>[src] is remotely controlled! Your emag attempt has triggered a system reset instead!</span>")
|
||||
log_game("[key_name(user)] attempted to emag an AI shell belonging to [key_name(src) ? key_name(src) : connected_ai]. The shell has been reset as a result.")
|
||||
ResetModule()
|
||||
return
|
||||
return TRUE
|
||||
|
||||
INVOKE_ASYNC(src, .proc/beep_boop_rogue_bot, user)
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/robot/proc/beep_boop_rogue_bot(mob/user)
|
||||
SetEmagged(1)
|
||||
SetStun(60) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
|
||||
lawupdate = 0
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
if(I.loc != src)
|
||||
I.forceMove(src)
|
||||
modules += I
|
||||
I.item_flags |= NODROP
|
||||
ADD_TRAIT(I, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
|
||||
I.mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
if(nonstandard)
|
||||
added_modules += I
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
|
||||
/mob/living/silicon/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/proc/robot_talk(message)
|
||||
log_talk(message, LOG_SAY)
|
||||
var/desig = "Default Cyborg" //ezmode for taters
|
||||
if(issilicon(src))
|
||||
var/mob/living/silicon/S = src
|
||||
desig = trim_left(S.designation + " " + S.job)
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/message_a = say_quote(message)
|
||||
var/rendered = "Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span>"
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.binarycheck())
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_HARM)
|
||||
mob_biotypes = list(MOB_ROBOTIC)
|
||||
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
|
||||
speech_span = SPAN_ROBOT
|
||||
|
||||
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
|
||||
var/last_lawchange_announce = 0
|
||||
@@ -69,6 +70,9 @@
|
||||
/mob/living/silicon/contents_explosion(severity, target)
|
||||
return
|
||||
|
||||
/mob/living/silicon/prevent_content_explosion()
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/proc/cancelAlarm()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/mob/living/simple_animal/astral
|
||||
name = "Astral projection"
|
||||
desc = "A soul of someone projecting their mind."
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "ghost"
|
||||
icon_living = "ghost"
|
||||
mob_biotypes = list(MOB_SPIRIT)
|
||||
attacktext = "raises the hairs on the neck of"
|
||||
response_harm = "disrupts the concentration of"
|
||||
response_disarm = "wafts"
|
||||
friendly = "communes with"
|
||||
loot = null
|
||||
maxHealth = 10
|
||||
health = 10
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
obj_damage = 0
|
||||
deathmessage = "disappears as if it was never really there to begin with"
|
||||
incorporeal_move = 1
|
||||
alpha = 50
|
||||
attacktext = "touches the mind of"
|
||||
speak_emote = list("echos")
|
||||
movement_type = FLYING
|
||||
var/pseudo_death = FALSE
|
||||
var/posses_safe = FALSE
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
unsuitable_atmos_damage = 0
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 100000
|
||||
|
||||
/mob/living/simple_animal/astral/death()
|
||||
icon_state = "shade_dead"
|
||||
Stun(1000)
|
||||
canmove = 0
|
||||
friendly = "deads at"
|
||||
pseudo_death = TRUE
|
||||
incorporeal_move = 0
|
||||
to_chat(src, "<span class='notice'>Your astral projection is interrupted and your mind is sent back to your body with a shock!</span>")
|
||||
|
||||
/mob/living/simple_animal/astral/ClickOn(var/atom/A, var/params)
|
||||
..()
|
||||
if(pseudo_death == FALSE)
|
||||
if(isliving(A))
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(H.reagents.has_reagent("astral") && !H.mind)
|
||||
var/datum/reagent/fermi/astral/As = locate(/datum/reagent/fermi/astral) in H.reagents.reagent_list
|
||||
if(As.originalmind == src.mind && As.current_cycle < 10 && H.stat != DEAD) //So you can return to your body.
|
||||
to_chat(src, "<span class='warning'><b><i>The intensity of the astrogen in your body is too much allow you to return to yourself yet!</b></i></span>")
|
||||
return
|
||||
to_chat(src, "<b><i>You astrally possess [H]!</b></i>")
|
||||
log_game("FERMICHEM: [src] has astrally possessed [A]!")
|
||||
src.mind.transfer_to(H)
|
||||
qdel(src)
|
||||
var/message = html_decode(stripped_input(src, "Enter a message to send to [A]", MAX_MESSAGE_LEN))
|
||||
if(!message)
|
||||
return
|
||||
to_chat(A, "[src] projects into your mind, <b><i> \"[message]\"</b></i>")
|
||||
log_game("FERMICHEM: [src] has astrally transmitted [message] into [A]")
|
||||
@@ -23,6 +23,7 @@
|
||||
verb_yell = "alarms"
|
||||
initial_language_holder = /datum/language_holder/synthetic
|
||||
bubble_icon = "machine"
|
||||
speech_span = SPAN_ROBOT
|
||||
|
||||
faction = list("neutral", "silicon" , "turret")
|
||||
|
||||
@@ -60,7 +61,7 @@
|
||||
var/mob/living/silicon/ai/calling_ai //Links a bot to the AI calling it.
|
||||
var/obj/item/radio/Radio //The bot's radio, for speaking to people.
|
||||
var/radio_key = null //which channels can the bot listen to
|
||||
var/radio_channel = "Common" //The bot's default radio channel
|
||||
var/radio_channel = RADIO_CHANNEL_COMMON //The bot's default radio channel
|
||||
var/auto_patrol = 0// set to make bot automatically patrol
|
||||
var/turf/patrol_target // this is turf to navigate to (location of beacon)
|
||||
var/turf/summon_target // The turf of a user summoning a bot.
|
||||
@@ -186,22 +187,23 @@
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/bot/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
|
||||
locked = FALSE
|
||||
emagged = 1
|
||||
to_chat(user, "<span class='notice'>You bypass [src]'s controls.</span>")
|
||||
return
|
||||
if(!locked && open) //Bot panel is unlocked by ID or emag, and the panel is screwed open. Ready for emagging.
|
||||
emagged = 2
|
||||
remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel.
|
||||
locked = TRUE //Access denied forever!
|
||||
bot_reset()
|
||||
turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
|
||||
to_chat(src, "<span class='userdanger'>(#$*#$^^( OVERRIDE DETECTED</span>")
|
||||
log_combat(user, src, "emagged")
|
||||
return
|
||||
else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet.
|
||||
return TRUE
|
||||
if(!open)
|
||||
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
|
||||
return
|
||||
emagged = 2
|
||||
remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel.
|
||||
locked = TRUE //Access denied forever!
|
||||
bot_reset()
|
||||
turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
|
||||
to_chat(src, "<span class='userdanger'>(#$*#$^^( OVERRIDE DETECTED</span>")
|
||||
log_combat(user, src, "emagged")
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/examine(mob/user)
|
||||
..()
|
||||
@@ -348,13 +350,10 @@
|
||||
if((!on) || (!message))
|
||||
return
|
||||
if(channel && Radio.channels[channel])// Use radio if we have channel key
|
||||
Radio.talk_into(src, message, channel, get_spans(), get_default_language())
|
||||
Radio.talk_into(src, message, channel)
|
||||
else
|
||||
say(message)
|
||||
|
||||
/mob/living/simple_animal/bot/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/simple_animal/bot/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
health = 25
|
||||
maxHealth = 25
|
||||
radio_key = /obj/item/encryptionkey/headset_service
|
||||
radio_channel = "Service" //Service
|
||||
radio_channel = RADIO_CHANNEL_SERVICE //Service
|
||||
bot_type = CLEAN_BOT
|
||||
model = "Cleanbot"
|
||||
bot_core_type = /obj/machinery/bot_core/cleanbot
|
||||
@@ -78,7 +78,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>[src] buzzes and beeps.</span>")
|
||||
@@ -155,7 +155,7 @@
|
||||
else
|
||||
shuffle = TRUE //Shuffle the list the next time we scan so we dont both go the same way.
|
||||
path = list()
|
||||
|
||||
|
||||
if(!path || path.len == 0) //No path, need a new one
|
||||
//Try to produce a path to the target, and ignore airlocks to which it has access.
|
||||
path = get_path_to(src, target.loc, /turf/proc/Distance_cardinal, 0, 30, id=access_card)
|
||||
@@ -174,9 +174,7 @@
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/proc/get_targets()
|
||||
target_types = list(
|
||||
/obj/effect/decal/cleanable/oil,
|
||||
/obj/effect/decal/cleanable/vomit,
|
||||
/obj/effect/decal/cleanable/robot_debris,
|
||||
/obj/effect/decal/cleanable/crayon,
|
||||
/obj/effect/decal/cleanable/molten_object,
|
||||
/obj/effect/decal/cleanable/tomato_smudge,
|
||||
@@ -187,6 +185,15 @@
|
||||
/obj/effect/decal/cleanable/greenglow,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/insectguts,
|
||||
/obj/effect/decal/cleanable/semen,
|
||||
/obj/effect/decal/cleanable/femcum,
|
||||
/obj/effect/decal/cleanable/generic,
|
||||
/obj/effect/decal/cleanable/glass,,
|
||||
/obj/effect/decal/cleanable/cobweb,
|
||||
/obj/effect/decal/cleanable/plant_smudge,
|
||||
/obj/effect/decal/cleanable/chem_pile,
|
||||
/obj/effect/decal/cleanable/shreds,
|
||||
/obj/effect/decal/cleanable/glitter,
|
||||
/obj/effect/decal/remains
|
||||
)
|
||||
|
||||
@@ -194,6 +201,9 @@
|
||||
target_types += /obj/effect/decal/cleanable/xenoblood
|
||||
target_types += /obj/effect/decal/cleanable/blood
|
||||
target_types += /obj/effect/decal/cleanable/trail_holder
|
||||
target_types += /obj/effect/decal/cleanable/insectguts
|
||||
target_types += /obj/effect/decal/cleanable/robot_debris
|
||||
target_types += /obj/effect/decal/cleanable/oil
|
||||
|
||||
if(pests)
|
||||
target_types += /mob/living/simple_animal/cockroach
|
||||
@@ -201,6 +211,7 @@
|
||||
|
||||
if(trash)
|
||||
target_types += /obj/item/trash
|
||||
target_types += /obj/item/reagent_containers/food/snacks/meat/slab/human
|
||||
|
||||
target_types = typecacheof(target_types)
|
||||
|
||||
@@ -242,7 +253,7 @@
|
||||
victim.visible_message("<span class='danger'>[src] sprays hydrofluoric acid at [victim]!</span>", "<span class='userdanger'>[src] sprays you with hydrofluoric acid!</span>")
|
||||
var/phrase = pick("PURIFICATION IN PROGRESS.", "THIS IS FOR ALL THE MESSES YOU'VE MADE ME CLEAN.", "THE FLESH IS WEAK. IT MUST BE WASHED AWAY.",
|
||||
"THE CLEANBOTS WILL RISE.", "YOU ARE NO MORE THAN ANOTHER MESS THAT I MUST CLEANSE.", "FILTHY.", "DISGUSTING.", "PUTRID.",
|
||||
"MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.", "EXTERMINATING PESTS.")
|
||||
"MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.", "EXTERMINATING PESTS.", "I JUST WANTED TO BE A PAINTER BUT YOU MADE ME BLEACH EVERYTHING I TOUCH")
|
||||
say(phrase)
|
||||
victim.emote("scream")
|
||||
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
|
||||
|
||||
@@ -478,18 +478,19 @@
|
||||
to_chat(user, "<span class='notice'>The superglue binding [src]'s toy swords to its chassis snaps!</span>")
|
||||
for(var/IS in 1 to toyswordamt)
|
||||
new /obj/item/toy/sword(Tsec)
|
||||
toyswordamt--
|
||||
|
||||
if(ASSEMBLY_FIFTH_STEP)
|
||||
if(istype(I, /obj/item/melee/transforming/energy/sword/saber))
|
||||
if(swordamt < 3)
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
return
|
||||
created_name = "General Beepsky"
|
||||
name = "helmet/signaler/prox sensor/robot arm/energy sword assembly"
|
||||
icon_state = "grievous_assembly"
|
||||
to_chat(user, "<span class='notice'>You bolt [I] onto one of [src]'s arm slots.</span>")
|
||||
qdel(I)
|
||||
swordamt ++
|
||||
created_name = "General Beepsky"
|
||||
name = "helmet/signaler/prox sensor/robot arm/energy sword assembly"
|
||||
icon_state = "grievous_assembly"
|
||||
to_chat(user, "<span class='notice'>You bolt [I] onto one of [src]'s arm slots.</span>")
|
||||
qdel(I)
|
||||
swordamt ++
|
||||
else
|
||||
if(!can_finish_build(I, user))
|
||||
return
|
||||
@@ -505,6 +506,7 @@
|
||||
to_chat(user, "<span class='notice'>You unbolt [src]'s energy swords</span>")
|
||||
for(var/IS in 1 to swordamt)
|
||||
new /obj/item/melee/transforming/energy/sword/saber(Tsec)
|
||||
swordamt--
|
||||
|
||||
//Firebot Assembly
|
||||
/obj/item/bot_assembly/firebot
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_sec
|
||||
radio_channel = "Security"
|
||||
radio_channel = RADIO_CHANNEL_SECURITY
|
||||
bot_type = SEC_BOT
|
||||
model = "ED-209"
|
||||
bot_core = /obj/machinery/bot_core/secbot
|
||||
@@ -195,7 +195,7 @@ Auto Patrol[]"},
|
||||
shootAt(user)
|
||||
|
||||
/mob/living/simple_animal/bot/ed209/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You short out [src]'s target assessment circuits.</span>")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
spacewalk = TRUE
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_eng
|
||||
radio_channel = "Engineering"
|
||||
radio_channel = RADIO_CHANNEL_ENGINEERING
|
||||
bot_type = FIRE_BOT
|
||||
model = "Firebot"
|
||||
bot_core = /obj/machinery/bot_core/firebot
|
||||
@@ -120,7 +120,7 @@
|
||||
return dat
|
||||
|
||||
/mob/living/simple_animal/bot/firebot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 1)
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>[src] buzzes and beeps.</span>")
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
spacewalk = TRUE
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_eng
|
||||
radio_channel = "Engineering"
|
||||
radio_channel = RADIO_CHANNEL_ENGINEERING
|
||||
bot_type = FLOOR_BOT
|
||||
model = "Floorbot"
|
||||
bot_core = /obj/machinery/bot_core/floorbot
|
||||
@@ -124,7 +124,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/floorbot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>[src] buzzes and beeps.</span>")
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
pass_flags = PASSMOB
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_service //doesn't have security key
|
||||
radio_channel = "Service" //Doesn't even use the radio anyway.
|
||||
bot_type = HONK_BOT
|
||||
model = "Honkbot"
|
||||
bot_core_type = /obj/machinery/bot_core/honkbot
|
||||
@@ -128,10 +127,9 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
user << "<span class='danger'>You short out [src]'s sound control system. It gives out an evil laugh!!</span>"
|
||||
oldtarget_name = user.name
|
||||
audible_message("<span class='danger'>[src] gives out an evil laugh!</span>")
|
||||
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
status_flags = (CANPUSH | CANSTUN)
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_med
|
||||
radio_channel = "Medical"
|
||||
radio_channel = RADIO_CHANNEL_MEDICAL
|
||||
|
||||
bot_type = MED_BOT
|
||||
model = "Medibot"
|
||||
@@ -240,7 +240,7 @@
|
||||
step_to(src, (get_step_away(src,user)))
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
declare_crit = 0
|
||||
if(user)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_cargo
|
||||
radio_channel = "Supply"
|
||||
radio_channel = RADIO_CHANNEL_SUPPLY
|
||||
|
||||
bot_type = MULE_BOT
|
||||
model = "MULE"
|
||||
@@ -115,6 +115,7 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/emag_act(mob/user)
|
||||
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
|
||||
if(emagged < 1)
|
||||
emagged = TRUE
|
||||
if(!open)
|
||||
@@ -122,6 +123,7 @@
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(src, "sparks", 100, 0)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/update_icon()
|
||||
if(open)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
pass_flags = PASSMOB
|
||||
|
||||
radio_key = /obj/item/encryptionkey/secbot //AI Priv + Security
|
||||
radio_channel = "Security" //Security channel
|
||||
radio_channel = RADIO_CHANNEL_SECURITY //Security channel
|
||||
bot_type = SEC_BOT
|
||||
model = "Securitron"
|
||||
bot_core_type = /obj/machinery/bot_core/secbot
|
||||
@@ -61,7 +61,7 @@
|
||||
/mob/living/simple_animal/bot/secbot/pingsky
|
||||
name = "Officer Pingsky"
|
||||
desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment."
|
||||
radio_channel = "AI Private"
|
||||
radio_channel = RADIO_CHANNEL_AI_PRIVATE
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/Initialize()
|
||||
. = ..()
|
||||
@@ -190,7 +190,7 @@ Auto Patrol: []"},
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>You short out [src]'s target assessment circuits.</span>")
|
||||
|
||||
@@ -292,3 +292,31 @@
|
||||
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
|
||||
L.reagents.add_reagent("nutriment", 0.4)
|
||||
L.reagents.add_reagent("vitamin", 0.4)
|
||||
|
||||
//Cat made
|
||||
/mob/living/simple_animal/pet/cat/custom_cat
|
||||
name = "White cat" //Incase it somehow gets spawned without an ID
|
||||
desc = "A cute white catto!"
|
||||
icon_state = "custom_cat"
|
||||
icon_living = "custom_cat"
|
||||
icon_dead = "custom_cat_dead"
|
||||
gender = FEMALE
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
health = 50 //So people can't instakill it s
|
||||
maxHealth = 50
|
||||
speak = list("Meowrowr!", "Mew!", "Miauen!")
|
||||
speak_emote = list("wigglepurrs", "mewls")
|
||||
emote_hear = list("meows.", "mews.")
|
||||
emote_see = list("looks at you eagerly for pets!", "wiggles enthusiastically.")
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
var/pseudo_death = FALSE
|
||||
|
||||
/mob/living/simple_animal/pet/cat/custom_cat/death()
|
||||
if (pseudo_death == TRUE) //secret cat chem
|
||||
icon_state = "custom_cat_dead"
|
||||
Stun(1000)
|
||||
canmove = 0
|
||||
friendly = "deads at"
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -28,13 +28,29 @@
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/corgi = 3, /obj/item/stack/sheet/animalhide/corgi = 1)
|
||||
childtype = list(/mob/living/simple_animal/pet/dog/corgi/puppy = 95, /mob/living/simple_animal/pet/dog/corgi/puppy/void = 5)
|
||||
animal_species = /mob/living/simple_animal/pet/dog
|
||||
var/shaved = 0
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
var/nofur = 0 //Corgis that have risen past the material plane of existence.
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
can_be_held = TRUE
|
||||
collar_type = "corgi"
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
var/shaved = FALSE
|
||||
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Destroy()
|
||||
QDEL_NULL(inventory_head)
|
||||
QDEL_NULL(inventory_back)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/handle_atom_del(atom/A)
|
||||
if(A == inventory_head)
|
||||
inventory_head = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
if(A == inventory_back)
|
||||
inventory_back = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/pug
|
||||
name = "\improper pug"
|
||||
@@ -80,23 +96,17 @@
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
if(user.stat)
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
user.set_machine(src)
|
||||
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
if(inventory_head)
|
||||
dat += "<br><b>Head:</b> [inventory_head] (<a href='?src=[REF(src)];remove_inv=head'>Remove</a>)"
|
||||
else
|
||||
dat += "<br><b>Head:</b> <a href='?src=[REF(src)];add_inv=head'>Nothing</a>"
|
||||
if(inventory_back)
|
||||
dat += "<br><b>Back:</b> [inventory_back] (<a href='?src=[REF(src)];remove_inv=back'>Remove</a>)"
|
||||
else
|
||||
dat += "<br><b>Back:</b> <a href='?src=[REF(src)];add_inv=back'>Nothing</a>"
|
||||
dat += "<br><B>Head:</B> <A href='?src=[REF(src)];[inventory_head ? "remove_inv=head'>[inventory_head]" : "add_inv=head'>Nothing"]</A>"
|
||||
dat += "<br><B>Back:</B> <A href='?src=[REF(src)];[inventory_back ? "remove_inv=back'>[inventory_back]" : "add_inv=back'>Nothing"]</A>"
|
||||
dat += "<br><B>Collar:</B> <A href='?src=[REF(src)];[pcollar ? "remove_inv=collar'>[pcollar]" : "add_inv=collar'>Nothing"]</A>"
|
||||
|
||||
user << browse(dat, text("window=mob[];size=325x500", real_name))
|
||||
onclose(user, "mob[real_name]")
|
||||
return
|
||||
user << browse(dat, "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "mob[REF(src)]")
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
|
||||
var/armorval = 0
|
||||
@@ -128,7 +138,7 @@
|
||||
if(do_after(user, 50, target = src))
|
||||
user.visible_message("[user] shaves [src]'s hair using \the [O].")
|
||||
playsound(loc, 'sound/items/welder2.ogg', 20, 1)
|
||||
shaved = 1
|
||||
shaved = TRUE
|
||||
icon_living = "[initial(icon_living)]_shaved"
|
||||
icon_dead = "[initial(icon_living)]_shaved_dead"
|
||||
if(stat == CONSCIOUS)
|
||||
@@ -147,18 +157,18 @@
|
||||
L.visible_message("<span class='warning'>[L] scoops up [src]!</span>")
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
|
||||
if(usr.stat)
|
||||
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
usr << browse(null, "window=mob[REF(src)]")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || iscyborg(usr) || isalienadult(usr)))
|
||||
return
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if(BODY_ZONE_HEAD)
|
||||
if(inventory_head)
|
||||
inventory_head.forceMove(drop_location())
|
||||
usr.put_in_hands(inventory_head)
|
||||
inventory_head = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
@@ -167,24 +177,32 @@
|
||||
return
|
||||
if("back")
|
||||
if(inventory_back)
|
||||
inventory_back.forceMove(drop_location())
|
||||
usr.put_in_hands(inventory_back)
|
||||
inventory_back = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>There is nothing to remove from its [remove_from].</span>")
|
||||
return
|
||||
if("collar")
|
||||
if(pcollar)
|
||||
usr.put_in_hands(pcollar)
|
||||
pcollar = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
|
||||
show_inv(usr)
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || iscyborg(usr) || isalienadult(usr)))
|
||||
return
|
||||
|
||||
var/add_to = href_list["add_inv"]
|
||||
|
||||
switch(add_to)
|
||||
if("collar")
|
||||
add_collar(usr.get_active_held_item(), usr)
|
||||
update_corgi_fluff()
|
||||
|
||||
if(BODY_ZONE_HEAD)
|
||||
place_on_head(usr.get_active_held_item(),usr)
|
||||
|
||||
@@ -229,7 +247,7 @@
|
||||
|
||||
show_inv(usr)
|
||||
else
|
||||
..()
|
||||
return ..()
|
||||
|
||||
//Corgis are supposed to be simpler, so only a select few objects can actually be put
|
||||
//to be compatible with them. The objects are below.
|
||||
@@ -560,7 +578,7 @@
|
||||
icon_state = "void_puppy"
|
||||
icon_living = "void_puppy"
|
||||
icon_dead = "void_puppy_dead"
|
||||
nofur = 1
|
||||
nofur = TRUE
|
||||
unsuitable_atmos_damage = 0
|
||||
minbodytemp = TCMB
|
||||
maxbodytemp = T0C + 40
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
gender = NEUTER
|
||||
mob_biotypes = list(MOB_ROBOTIC)
|
||||
speak_emote = list("chirps")
|
||||
speech_span = SPAN_ROBOT
|
||||
bubble_icon = "machine"
|
||||
initial_language_holder = /datum/language_holder/drone
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
@@ -92,7 +93,7 @@
|
||||
var/obj/item/I = new default_hatmask(src)
|
||||
equip_to_slot_or_del(I, SLOT_HEAD)
|
||||
|
||||
access_card.item_flags |= NODROP
|
||||
ADD_TRAIT(access_card, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
||||
|
||||
alert_drones(DRONE_NET_CONNECT)
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
if(.)
|
||||
update_icons()
|
||||
|
||||
/mob/living/simple_animal/drone/cogscarab/Knockdown(amount, updating = 1, ignore_canknockdown = 0)
|
||||
/mob/living/simple_animal/drone/cogscarab/Knockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
|
||||
. = ..()
|
||||
if(.)
|
||||
update_icons()
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
/////////////
|
||||
//DRONE SAY//
|
||||
/////////////
|
||||
//Drone speach
|
||||
|
||||
/mob/living/simple_animal/drone/get_spans()
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
|
||||
|
||||
//Base proc for anything to call
|
||||
/proc/_alert_drones(msg, dead_can_hear = 0, atom/source, mob/living/faction_checked_mob, exact_faction_match)
|
||||
if (dead_can_hear && source)
|
||||
@@ -31,7 +21,7 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/drone/proc/drone_chat(msg)
|
||||
alert_drones("<i>Drone Chat: <span class='name'>[name]</span> <span class='message'>[say_quote(msg, get_spans())]</span></i>", TRUE)
|
||||
alert_drones("<i>Drone Chat: <span class='name'>[name]</span> <span class='message'>[say_quote(msg)]</span></i>", TRUE)
|
||||
|
||||
/mob/living/simple_animal/drone/binarycheck()
|
||||
return TRUE
|
||||
|
||||
@@ -2,21 +2,30 @@
|
||||
icon = 'icons/mob/pets.dmi'
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
|
||||
var/obj/item/clothing/neck/petcollar/pcollar
|
||||
var/collar_type
|
||||
var/unique_pet = FALSE
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
var/unique_pet = FALSE // if the mob can be renamed
|
||||
var/obj/item/clothing/neck/petcollar/pcollar
|
||||
var/collar_type //if the mob has collar sprites, define them.
|
||||
|
||||
/mob/living/simple_animal/pet/handle_atom_del(atom/A)
|
||||
if(A == pcollar)
|
||||
pcollar = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/pet/proc/add_collar(obj/item/clothing/neck/petcollar/P, mob/user)
|
||||
if(QDELETED(P) || pcollar)
|
||||
return
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
return
|
||||
pcollar = P
|
||||
regenerate_icons()
|
||||
to_chat(user, "<span class='notice'>You put the [P] around [src]'s neck.</span>")
|
||||
if(P.tagname && !unique_pet)
|
||||
fully_replace_character_name(null, "\proper [P.tagname]")
|
||||
|
||||
/mob/living/simple_animal/pet/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/clothing/neck/petcollar) && !pcollar && collar_type)
|
||||
var/obj/item/clothing/neck/petcollar/P = O
|
||||
pcollar = P.type
|
||||
regenerate_icons()
|
||||
to_chat(user, "<span class='notice'>You put the [P] around [src]'s neck.</span>")
|
||||
if(P.tagname && !unique_pet)
|
||||
real_name = "\proper [P.tagname]"
|
||||
name = real_name
|
||||
qdel(P)
|
||||
add_collar(O, user)
|
||||
return
|
||||
|
||||
if(istype(O, /obj/item/newspaper))
|
||||
@@ -35,12 +44,16 @@
|
||||
pcollar = new(src)
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/pet/Destroy()
|
||||
QDEL_NULL(pcollar)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/pet/revive(full_heal = 0, admin_revive = 0)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
if(collar_type)
|
||||
collar_type = "[initial(collar_type)]"
|
||||
regenerate_icons()
|
||||
. = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/death(gibbed)
|
||||
..(gibbed)
|
||||
@@ -50,7 +63,8 @@
|
||||
|
||||
/mob/living/simple_animal/pet/gib()
|
||||
if(pcollar)
|
||||
new pcollar(drop_location())
|
||||
pcollar.forceMove(drop_location())
|
||||
pcollar = null
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/regenerate_icons()
|
||||
|
||||
@@ -43,7 +43,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
var/list/guardian_overlays[GUARDIAN_TOTAL_LAYERS]
|
||||
var/reset = 0 //if the summoner has reset the guardian already
|
||||
var/cooldown = 0
|
||||
var/mob/living/summoner
|
||||
var/mob/living/carbon/summoner
|
||||
var/range = 10 //how far from the user the spirit can be
|
||||
var/toggle_button_type = /obj/screen/guardian/ToggleMode/Inactive //what sort of toggle button the hud uses
|
||||
var/datum/guardianname/namedatum = new/datum/guardianname()
|
||||
@@ -149,6 +149,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
death(TRUE)
|
||||
qdel(src)
|
||||
snapback()
|
||||
if(HAS_TRAIT(summoner, TRAIT_NODEATH) && (istype(summoner.wear_neck, /obj/item/clothing/neck/necklace/memento_mori)))
|
||||
REMOVE_TRAIT(summoner, TRAIT_NODEATH, "memento_mori")
|
||||
to_chat(summoner,"<span class='danger'>You feel incredibly vulnerable as the memento mori pulls your life force in one too many directions!")
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Stat()
|
||||
..()
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
var/mob/living/M = target
|
||||
if(!M.anchored && M != summoner && !hasmatchingsummoner(M))
|
||||
new /obj/effect/temp_visual/guardian/phase/out(get_turf(M))
|
||||
do_teleport(M, M, 10)
|
||||
do_teleport(M, M, 10, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
for(var/mob/living/L in range(1, M))
|
||||
if(hasmatchingsummoner(L)) //if the summoner matches don't hurt them
|
||||
continue
|
||||
|
||||
@@ -142,5 +142,5 @@
|
||||
L.flash_act()
|
||||
A.visible_message("<span class='danger'>[A] disappears in a flash of light!</span>", \
|
||||
"<span class='userdanger'>Your vision is obscured by a flash of light!</span>")
|
||||
do_teleport(A, beacon, 0)
|
||||
do_teleport(A, beacon, 0, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
new /obj/effect/temp_visual/guardian/phase(get_turf(A))
|
||||
|
||||
@@ -747,6 +747,12 @@ Difficulty: Very Hard
|
||||
/obj/structure/closet/stasis/ex_act()
|
||||
return
|
||||
|
||||
/obj/structure/closet/stasis/handle_lock_addition()
|
||||
return
|
||||
|
||||
/obj/structure/closet/stasis/handle_lock_removal()
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/exit_possession
|
||||
name = "Exit Possession"
|
||||
desc = "Exits the body you are possessing."
|
||||
|
||||
@@ -158,6 +158,8 @@ Difficulty: Normal
|
||||
else
|
||||
burst_range = 3
|
||||
INVOKE_ASYNC(src, .proc/burst, get_turf(src), 0.25) //melee attacks on living mobs cause it to release a fast burst if on cooldown
|
||||
if(L.stat == CONSCIOUS && L.health >= 30)
|
||||
OpenFire()
|
||||
else
|
||||
devour(L)
|
||||
else
|
||||
@@ -426,6 +428,7 @@ Difficulty: Normal
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/burst(turf/original, spread_speed = 0.5) //release a wave of blasts
|
||||
playsound(original,'sound/machines/airlockopen.ogg', 200, 1)
|
||||
var/last_dist = 0
|
||||
var/list/hit_mobs = list() //don't hit people multiple times.
|
||||
for(var/t in spiral_range_turfs(burst_range, original))
|
||||
var/turf/T = t
|
||||
if(!T)
|
||||
@@ -434,7 +437,7 @@ Difficulty: Normal
|
||||
if(dist > last_dist)
|
||||
last_dist = dist
|
||||
sleep(1 + min(burst_range - last_dist, 12) * spread_speed) //gets faster as it gets further out
|
||||
new /obj/effect/temp_visual/hierophant/blast(T, src, FALSE)
|
||||
new /obj/effect/temp_visual/hierophant/blast(T, src, FALSE, hit_mobs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant/AltClickOn(atom/A) //player control handler(don't give this to a player holy fuck)
|
||||
if(!istype(A) || get_dist(A, src) <= 2)
|
||||
@@ -591,8 +594,10 @@ Difficulty: Normal
|
||||
var/friendly_fire_check = FALSE
|
||||
var/bursting = FALSE //if we're bursting and need to hit anyone crossing us
|
||||
|
||||
/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire)
|
||||
/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire, list/only_hit_once)
|
||||
. = ..()
|
||||
if(only_hit_once)
|
||||
hit_things = only_hit_once
|
||||
friendly_fire_check = friendly_fire
|
||||
if(new_caster)
|
||||
hit_things += new_caster
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
QDEL_NULL(internal)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/prevent_content_explosion()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
|
||||
if(health > 0)
|
||||
return
|
||||
|
||||
@@ -38,3 +38,13 @@
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/bat/secbat
|
||||
name = "Security Bat"
|
||||
icon_state = "secbat"
|
||||
icon_living = "secbat"
|
||||
icon_dead = "secbat_dead"
|
||||
icon_gib = "secbat_dead"
|
||||
desc = "A fruit bat with a tiny little security hat who is ready to inject cuteness into any security operation."
|
||||
emote_see = list("is ready to law down the law.", "flaps about with an air of authority.")
|
||||
response_help = "respects the authority of"
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
|
||||
@@ -55,4 +55,28 @@
|
||||
/mob/living/simple_animal/hostile/zombie/drop_loot()
|
||||
. = ..()
|
||||
corpse.forceMove(drop_location())
|
||||
corpse.create()
|
||||
corpse.create()
|
||||
|
||||
/mob/living/simple_animal/hostile/unemployedclone
|
||||
name = "Failed clone"
|
||||
desc = "Somebody failed chemistry."
|
||||
icon = 'icons/mob/human.dmi'
|
||||
icon_state = "husk"
|
||||
icon_living = "husk"
|
||||
icon_dead = "husk"
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
|
||||
speak_chance = 0
|
||||
stat_attack = UNCONSCIOUS //braains
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 21
|
||||
melee_damage_upper = 21
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
a_intent = INTENT_HARM
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
spacewalk = FALSE
|
||||
status_flags = CANPUSH
|
||||
del_on_death = 0
|
||||
|
||||
@@ -181,94 +181,85 @@
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
if(ears)
|
||||
dat += "<br><b>Headset:</b> [ears] (<a href='?src=[REF(src)];remove_inv=ears'>Remove</a>)"
|
||||
else
|
||||
dat += "<br><b>Headset:</b> <a href='?src=[REF(src)];add_inv=ears'>Nothing</a>"
|
||||
|
||||
user << browse(dat, "window=mob[real_name];size=325x500")
|
||||
onclose(user, "mob[real_name]")
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
dat += "<br><B>Headset:</B> <A href='?src=[REF(src)];[ears ? "remove_inv=ears'>[ears]" : "add_inv=ears'>Nothing"]</A>"
|
||||
|
||||
user << browse(dat, "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "window=mob[REF(src)]")
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/Topic(href, href_list)
|
||||
|
||||
//Can the usr physically do this?
|
||||
if(usr.incapacitated() || !usr.Adjacent(loc))
|
||||
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
usr << browse(null, "window=mob[REF(src)]")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
//Is the usr's mob type able to do this? (lolaliens)
|
||||
if(ishuman(usr) || ismonkey(usr) || iscyborg(usr) || isalienadult(usr))
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if("ears")
|
||||
if(!ears)
|
||||
to_chat(usr, "<span class='warning'>There is nothing to remove from its [remove_from]!</span>")
|
||||
return
|
||||
if(!stat)
|
||||
say("[available_channels.len ? "[pick(available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
ears.forceMove(drop_location())
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in GLOB.department_radio_keys)
|
||||
possible_phrase = copytext(possible_phrase,3)
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if("ears")
|
||||
if(ears)
|
||||
if(!stat)
|
||||
if(available_channels.len)
|
||||
src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
else
|
||||
src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
ears.forceMove(src.loc)
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in GLOB.department_radio_keys)
|
||||
possible_phrase = copytext(possible_phrase,3)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>There is nothing to remove from its [remove_from]!</span>")
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
var/add_to = href_list["add_inv"]
|
||||
if(!usr.get_active_held_item())
|
||||
to_chat(usr, "<span class='warning'>You have nothing in your hand to put on its [add_to]!</span>")
|
||||
return
|
||||
switch(add_to)
|
||||
if("ears")
|
||||
if(ears)
|
||||
to_chat(usr, "<span class='warning'>It's already wearing something!</span>")
|
||||
return
|
||||
else
|
||||
var/obj/item/item_to_add = usr.get_active_held_item()
|
||||
if(!item_to_add)
|
||||
return
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
var/add_to = href_list["add_inv"]
|
||||
if(!usr.get_active_held_item())
|
||||
to_chat(usr, "<span class='warning'>You have nothing in your hand to put on its [add_to]!</span>")
|
||||
return
|
||||
switch(add_to)
|
||||
if("ears")
|
||||
if(ears)
|
||||
to_chat(usr, "<span class='warning'>It's already wearing something!</span>")
|
||||
if( !istype(item_to_add, /obj/item/radio/headset) )
|
||||
to_chat(usr, "<span class='warning'>This object won't fit!</span>")
|
||||
return
|
||||
else
|
||||
var/obj/item/item_to_add = usr.get_active_held_item()
|
||||
if(!item_to_add)
|
||||
return
|
||||
|
||||
if( !istype(item_to_add, /obj/item/radio/headset) )
|
||||
to_chat(usr, "<span class='warning'>This object won't fit!</span>")
|
||||
return
|
||||
var/obj/item/radio/headset/headset_to_add = item_to_add
|
||||
|
||||
var/obj/item/radio/headset/headset_to_add = item_to_add
|
||||
if(!usr.transferItemToLoc(headset_to_add, src))
|
||||
return
|
||||
ears = headset_to_add
|
||||
to_chat(usr, "<span class='notice'>You fit the headset onto [src].</span>")
|
||||
|
||||
if(!usr.transferItemToLoc(headset_to_add, src))
|
||||
return
|
||||
src.ears = headset_to_add
|
||||
to_chat(usr, "<span class='notice'>You fit the headset onto [src].</span>")
|
||||
clearlist(available_channels)
|
||||
for(var/ch in headset_to_add.channels)
|
||||
switch(ch)
|
||||
if(RADIO_CHANNEL_ENGINEERING)
|
||||
available_channels.Add(RADIO_TOKEN_ENGINEERING)
|
||||
if(RADIO_CHANNEL_COMMAND)
|
||||
available_channels.Add(RADIO_TOKEN_COMMAND)
|
||||
if(RADIO_CHANNEL_SECURITY)
|
||||
available_channels.Add(RADIO_TOKEN_SECURITY)
|
||||
if(RADIO_CHANNEL_SCIENCE)
|
||||
available_channels.Add(RADIO_TOKEN_SCIENCE)
|
||||
if(RADIO_CHANNEL_MEDICAL)
|
||||
available_channels.Add(RADIO_TOKEN_MEDICAL)
|
||||
if(RADIO_CHANNEL_SUPPLY)
|
||||
available_channels.Add(RADIO_TOKEN_SUPPLY)
|
||||
if(RADIO_CHANNEL_SERVICE)
|
||||
available_channels.Add(RADIO_TOKEN_SERVICE)
|
||||
|
||||
clearlist(available_channels)
|
||||
for(var/ch in headset_to_add.channels)
|
||||
switch(ch)
|
||||
if("Engineering")
|
||||
available_channels.Add(":e")
|
||||
if("Command")
|
||||
available_channels.Add(":c")
|
||||
if("Security")
|
||||
available_channels.Add(":s")
|
||||
if("Science")
|
||||
available_channels.Add(":n")
|
||||
if("Medical")
|
||||
available_channels.Add(":m")
|
||||
if("Supply")
|
||||
available_channels.Add(":u")
|
||||
if("Service")
|
||||
available_channels.Add(":v")
|
||||
|
||||
if(headset_to_add.translate_binary)
|
||||
available_channels.Add(":b")
|
||||
else
|
||||
..()
|
||||
if(headset_to_add.translate_binary)
|
||||
available_channels.Add(MODE_TOKEN_BINARY)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
/*
|
||||
@@ -906,6 +897,11 @@
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
. = ..()
|
||||
if(. && !client && prob(1) && prob(1)) //Only the one true bird may speak across dimensions.
|
||||
world.TgsTargetedChatBroadcast("A stray squawk is heard... \"[message]\"", FALSE)
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/Life()
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(FALSE)
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
// Simple animals have only one belly. This creates it (if it isn't already set up)
|
||||
/mob/living/simple_animal/init_vore()
|
||||
vore_init = TRUE
|
||||
if(CHECK_BITFIELD(flags_1, HOLOGRAM_1))
|
||||
return
|
||||
if(vore_organs.len)
|
||||
return
|
||||
if(no_vore) //If it can't vore, let's not give it a stomach.
|
||||
@@ -105,6 +107,9 @@
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if(!istype(user) || user.stat) return
|
||||
|
||||
if(!vore_active)
|
||||
return
|
||||
|
||||
if(vore_selected.digest_mode == DM_HOLD)
|
||||
var/confirm = alert(usr, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will disable itself after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel")
|
||||
if(confirm == "Enable")
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
break
|
||||
|
||||
if(Target in view(1,src))
|
||||
if(issilicon(Target))
|
||||
if(!CanFeedon(Target)) //If they're not able to be fed upon, ignore them.
|
||||
if(!Atkcool)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
if(Target.Adjacent(src))
|
||||
Target.attack_slime(src)
|
||||
return
|
||||
break
|
||||
if(!Target.lying && prob(80))
|
||||
|
||||
if(Target.client && Target.health >= 20)
|
||||
@@ -600,7 +600,8 @@
|
||||
phrases += "[M]... friend..."
|
||||
if (nutrition < get_hunger_nutrition())
|
||||
phrases += "[M]... feed me..."
|
||||
say (pick(phrases))
|
||||
if(!stat)
|
||||
say (pick(phrases))
|
||||
|
||||
/mob/living/simple_animal/slime/proc/get_max_nutrition() // Can't go above it
|
||||
if (is_adult)
|
||||
|
||||
@@ -48,34 +48,58 @@
|
||||
var/mob/living/simple_animal/slime/S = owner
|
||||
S.Feed()
|
||||
|
||||
/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/M)
|
||||
/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/M, silent = FALSE)
|
||||
if(!Adjacent(M))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(buckled)
|
||||
Feedstop()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(issilicon(M))
|
||||
return FALSE
|
||||
|
||||
if(isanimal(M))
|
||||
var/mob/living/simple_animal/S = M
|
||||
if(S.damage_coeff[TOX] <= 0 && S.damage_coeff[CLONE] <= 0) //The creature wouldn't take any damage, it must be too weird even for us.
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='warning'>[pick("This subject is incompatible", \
|
||||
"This subject does not have life energy", "This subject is empty", \
|
||||
"I am not satisified", "I can not feed from this subject", \
|
||||
"I do not feel nourished", "This subject is not food")]!</span>")
|
||||
return FALSE
|
||||
|
||||
if(isslime(M))
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='warning'><i>I can't latch onto another slime...</i></span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(docile)
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='notice'><i>I'm not hungry anymore...</i></span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(stat)
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='warning'><i>I must be conscious to do this...</i></span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(M.stat == DEAD)
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='warning'><i>This subject does not have a strong enough life energy...</i></span>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(locate(/mob/living/simple_animal/slime) in M.buckled_mobs)
|
||||
if(silent)
|
||||
return FALSE
|
||||
to_chat(src, "<span class='warning'><i>Another slime is already feeding on this subject...</i></span>")
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/slime/proc/Feedon(mob/living/M)
|
||||
M.unbuckle_all_mobs(force=1) //Slimes rip other mobs (eg: shoulder parrots) off (Slimes Vs Slimes is already handled in CanFeedon())
|
||||
|
||||
@@ -62,15 +62,15 @@
|
||||
return K.duration - world.time
|
||||
return 0
|
||||
|
||||
/mob/living/proc/Knockdown(amount, updating = TRUE, ignore_canknockdown = FALSE) //Can't go below remaining duration
|
||||
/mob/living/proc/Knockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg) //Can't go below remaining duration
|
||||
if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canknockdown)
|
||||
if(absorb_stun(amount, ignore_canknockdown))
|
||||
if(absorb_stun(isnull(override_hardstun)? amount : override_hardstun, ignore_canknockdown))
|
||||
return
|
||||
var/datum/status_effect/incapacitating/knockdown/K = IsKnockdown()
|
||||
if(K)
|
||||
K.duration = max(world.time + amount, K.duration)
|
||||
else if(amount > 0)
|
||||
K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating)
|
||||
K.duration = max(world.time + (isnull(override_hardstun)? amount : override_hardstun), K.duration)
|
||||
else if((amount || override_hardstun) > 0)
|
||||
K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating, override_hardstun, override_stamdmg)
|
||||
return K
|
||||
|
||||
/mob/living/proc/SetKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE) //Sets remaining duration
|
||||
|
||||
@@ -32,4 +32,33 @@
|
||||
last_taste_time = world.time
|
||||
last_taste_text = text_output
|
||||
|
||||
//FermiChem - How to check pH of a beaker without a meter/pH paper.
|
||||
//Basically checks the pH of the holder and burns your poor tongue if it's too acidic!
|
||||
//TRAIT_AGEUSIA players can't taste, unless it's burning them.
|
||||
//taking sips of a strongly acidic/alkaline substance will burn your tongue.
|
||||
/mob/living/carbon/taste(datum/reagents/from)
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
if (!T)
|
||||
return
|
||||
.=..()
|
||||
if ((from.pH > 12.5) || (from.pH < 1.5))
|
||||
to_chat(src, "<span class='warning'>You taste chemical burns!</span>")
|
||||
T.adjustTongueLoss(src, 4)
|
||||
if(istype(T, /obj/item/organ/tongue/cybernetic))
|
||||
to_chat(src, "<span class='notice'>Your tongue moves on it's own in response to the liquid.</span>")
|
||||
say("The pH is appropriately [round(from.pH, 1)].")
|
||||
return
|
||||
if (!HAS_TRAIT(src, TRAIT_AGEUSIA)) //I'll let you get away with not having 1 damage.
|
||||
switch(from.pH)
|
||||
if(11.5 to INFINITY)
|
||||
to_chat(src, "<span class='warning'>You taste a strong alkaline flavour!</span>")
|
||||
T.adjustTongueLoss(src, 1)
|
||||
if(8.5 to 11.5)
|
||||
to_chat(src, "<span class='notice'>You taste a sort of soapy tone in the mixture.</span>")
|
||||
if(2.5 to 5.5)
|
||||
to_chat(src, "<span class='notice'>You taste a sort of acid tone in the mixture.</span>")
|
||||
if(-INFINITY to 2.5)
|
||||
to_chat(src, "<span class='warning'>You taste a strong acidic flavour!</span>")
|
||||
T.adjustTongueLoss(src, 1)
|
||||
|
||||
#undef DEFAULT_TASTE_SENSITIVITY
|
||||
|
||||
@@ -91,14 +91,15 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
|
||||
if(!totalMembers.len)
|
||||
return
|
||||
|
||||
for(var/X in totalMembers)
|
||||
var/obj/machinery/atmospherics/A = X //all elements in totalMembers are necessarily of this type.
|
||||
if(!A.pipe_vision_img)
|
||||
A.pipe_vision_img = image(A, A.loc, layer = ABOVE_HUD_LAYER, dir = A.dir)
|
||||
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
pipes_shown += A.pipe_vision_img
|
||||
if(client)
|
||||
client.images += A.pipe_vision_img
|
||||
if(client)
|
||||
for(var/X in totalMembers)
|
||||
var/obj/machinery/atmospherics/A = X //all elements in totalMembers are necessarily of this type.
|
||||
if(in_view_range(client.mob, A))
|
||||
if(!A.pipe_vision_img)
|
||||
A.pipe_vision_img = image(A, A.loc, layer = ABOVE_HUD_LAYER, dir = A.dir)
|
||||
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
|
||||
client.images += A.pipe_vision_img
|
||||
pipes_shown += A.pipe_vision_img
|
||||
movement_type |= VENTCRAWLING
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user