Merge remote-tracking branch 'upstream/master' into ambitioncheck

This commit is contained in:
keronshb
2022-02-22 17:10:25 -05:00
1045 changed files with 68632 additions and 58299 deletions

View File

@@ -126,5 +126,5 @@ INITIALIZE_IMMEDIATE(/mob/dead)
return ..()
/mob/dead/onTransitZ(old_z,new_z)
..()
. = ..()
update_z(new_z)

View File

@@ -578,8 +578,6 @@
Spl.Fade(TRUE)
character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25)
character.update_parallax_teleport()
job.standard_assign_skills(character.mind)
SSticker.minds += character.mind
@@ -762,6 +760,7 @@
client.prefs.scars_list["[cur_scar_index]"] = valid_scars
client.prefs.save_character()
client.prefs.copy_to(H, initial_spawn = TRUE)
H.dna.update_dna_identity()
if(mind)

View File

@@ -1,4 +1,8 @@
//Angel Wings
//Functional Wings
/datum/sprite_accessory/wings
icon = 'icons/mob/wings_functional.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/wings/none
name = "None"
@@ -9,23 +13,12 @@
return (!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception))))
/datum/sprite_accessory/wings_open
icon = 'icons/mob/wings.dmi'
icon = 'icons/mob/wings_functional.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/wings_open/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)) || H.dna.species.mutant_bodyparts["wings"])
/datum/sprite_accessory/wings_open/angel
name = "Angel"
icon_state = "angel"
color_src = 0
dimension_x = 46
center = TRUE
dimension_y = 34
/datum/sprite_accessory/wings
icon = 'icons/mob/wings.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/wings/angel
name = "Angel"
@@ -36,6 +29,114 @@
dimension_y = 34
locked = TRUE
/datum/sprite_accessory/wings_open/angel
name = "Angel"
icon_state = "angel"
color_src = 0
dimension_x = 46
center = TRUE
dimension_y = 34
/datum/sprite_accessory/wings/dragon
name = "Dragon"
icon_state = "dragon"
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/dragon
name = "Dragon"
icon_state = "dragon"
dimension_x = 96
center = TRUE
dimension_y = 32
/datum/sprite_accessory/wings/megamoth
name = "Megamoth"
icon_state = "megamoth"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/megamoth
name = "Megamoth"
icon_state = "megamoth"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
/datum/sprite_accessory/wings/mothra
name = "Mothra"
icon_state = "mothra"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/mothra
name = "Mothra"
icon_state = "mothra"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
/datum/sprite_accessory/wings/skeleton
name = "Skeleton"
icon_state = "skele"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/skeleton
name = "Skeleton"
icon_state = "skele"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
/datum/sprite_accessory/wings/robotic
name = "Robotic"
icon_state = "robotic"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/robotic
name = "Robotic"
icon_state = "robotic"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
/datum/sprite_accessory/wings/fly
name = "Fly"
icon_state = "fly"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
locked = TRUE
/datum/sprite_accessory/wings_open/fly
name = "Fly"
icon_state = "fly"
color_src = FALSE
dimension_x = 96
center = TRUE
dimension_y = 32
// Decorative wings
/datum/sprite_accessory/deco_wings
@@ -43,6 +144,10 @@
color_src = WINGCOLOR
mutant_part_string = "insect_wings"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
var/list/upgrade_to = list() //What the wings change to if the mob consumes a flight potion or gains true wings through other means. If it's an empty list, it will pick the species alternative instead.
/datum/sprite_accessory/deco_wings/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (H.dna.features["wings"] != "None") //true wings will override decorative wings
/datum/sprite_accessory/deco_wings/none
name = "None"
@@ -57,162 +162,201 @@
center = TRUE
dimension_y = 34
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
upgrade_to = SPECIES_WINGS_ANGEL //obviously
//nonmoth wings
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
icon_state = "bat"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/deco_wings/bee
name = "Bee"
icon_state = "bee"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/deco_wings/bee2
name = "Small Bee"
icon_state = "beewings"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/deco_wings/dragon
name = "Dragon"
icon_state = "dragon"
upgrade_to = SPECIES_WINGS_DRAGON //lol
/datum/sprite_accessory/deco_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/deco_wings/fairy
name = "Fairy"
icon_state = "fairy"
upgrade_to = SPECIES_WINGS_INSECT //rip people's sparkly wings until someone sprites in some huge fairy wings or something
/datum/sprite_accessory/deco_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/deco_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/deco_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/deco_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/deco_wings/roboticwing
name = "Robotic"
icon_state = "drago"
upgrade_to = SPECIES_WINGS_ROBOT
/datum/sprite_accessory/deco_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/deco_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/deco_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/deco_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
upgrade_to = list()
//moth wings
/datum/sprite_accessory/deco_wings/atlas
name = "Atlas"
icon_state = "atlas"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/brown
name = "Brown"
icon_state = "brown"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/firewatch
name = "Firewatch"
icon_state = "firewatch"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/gothic
name = "Gothic"
icon_state = "gothic"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/jungle
name = "Jungle"
icon_state = "jungle"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/lovers
name = "Lovers"
icon_state = "lovers"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/luna
name = "Luna"
icon_state = "luna"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/monarch
name = "Monarch"
icon_state = "monarch"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/moonfly
name = "Moon Fly"
icon_state = "moonfly"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/plain
name = "Plain"
icon_state = "plain"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/poison
name = "Poison"
icon_state = "poison"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/punished
name = "Burnt Off"
icon_state = "punished"
upgrade_to = SPECIES_WINGS_MOTH //through TG code moth wings aren't meant to get upgraded if they're burnt off but...
/datum/sprite_accessory/deco_wings/ragged
name = "Ragged"
icon_state = "ragged"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/reddish
name = "Reddish"
icon_state = "redish"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/rosy
name = "Rosy"
icon_state = "rosy"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/royal
name = "Royal"
icon_state = "royal"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/snow
name = "Snow"
icon_state = "snow"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/whitefly
name = "White Fly"
icon_state = "whitefly"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/deco_wings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
upgrade_to = SPECIES_WINGS_MOTH
//INSECT WINGS
@@ -220,67 +364,86 @@
icon = 'icons/mob/wings.dmi'
color_src = WINGCOLOR
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
var/list/upgrade_to = list()
/datum/sprite_accessory/insect_wings/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (H.dna.features["wings"] != "None") //true wings will override decorative wings
//non insect wings
/datum/sprite_accessory/deco_wings/bat
/datum/sprite_accessory/insect_wings/bat
name = "Bat"
icon_state = "bat"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
icon_state = "bee"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/insect_wings/bee2
name = "Small Bee"
icon_state = "beewings"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/insect_wings/dragon
name = "Dragon"
icon_state = "dragon"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/insect_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/insect_wings/fairy
name = "Fairy"
icon_state = "fairy"
upgrade_to = SPECIES_WINGS_INSECT
/datum/sprite_accessory/insect_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/insect_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/insect_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/insect_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
upgrade_to = SPECIES_WINGS_ANGEL
/datum/sprite_accessory/insect_wings/roboticwing
name = "Robotic"
icon_state = "drago"
upgrade_to = SPECIES_WINGS_ROBOT
/datum/sprite_accessory/insect_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/insect_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/insect_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
upgrade_to = SPECIES_WINGS_DRAGON
/datum/sprite_accessory/insect_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
upgrade_to = list()
//moth wings
@@ -288,98 +451,122 @@
name = "None"
icon_state = "none"
relevant_layers = null
upgrade_to = list()
/datum/sprite_accessory/insect_wings/atlas
name = "Atlas"
icon_state = "atlas"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/brown
name = "Brown"
icon_state = "brown"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/firewatch
name = "Firewatch"
icon_state = "firewatch"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/gothic
name = "Gothic"
icon_state = "gothic"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/jungle
name = "Jungle"
icon_state = "jungle"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/lovers
name = "Lovers"
icon_state = "lovers"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/luna
name = "Luna"
icon_state = "luna"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/monarch
name = "Monarch"
icon_state = "monarch"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/moonfly
name = "Moon Fly"
icon_state = "moonfly"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/plain
name = "Plain"
icon_state = "plain"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/poison
name = "Poison"
icon_state = "poison"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/punished
name = "Burnt Off"
icon_state = "punished"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/ragged
name = "Ragged"
icon_state = "ragged"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/reddish
name = "Reddish"
icon_state = "redish"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/rosy
name = "Rosy"
icon_state = "rosy"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/royal
name = "Royal"
icon_state = "royal"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/snow
name = "Snow"
icon_state = "snow"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/whitefly
name = "White Fly"
icon_state = "whitefly"
upgrade_to = SPECIES_WINGS_MOTH
/datum/sprite_accessory/insect_wings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
upgrade_to = SPECIES_WINGS_MOTH
//insect markings
/datum/sprite_accessory/insect_markings // Extra markings for insects ported from tg.
@@ -453,9 +640,11 @@
/datum/sprite_accessory/deco_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
upgrade_to = list() //and suddenly flight potions become a lot more awkward when they gouge your tentacle eyes out.
//ckeys_allowed = list("liquidfirefly","seiga") //At request.
/datum/sprite_accessory/insect_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
upgrade_to = list()
//ckeys_allowed = list("liquidfirefly","seiga") //At request.

View File

@@ -377,8 +377,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
ghostize(0, penalize = TRUE)
/mob/dead/observer/Move(NewLoc, direct)
if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, NewLoc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
return
@@ -388,7 +386,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(NewLoc)
forceMove(NewLoc)
update_parallax_contents()
else
forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
@@ -487,9 +484,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!L || !L.len)
to_chat(usr, "No area available.")
return
usr.forceMove(pick(L))
update_parallax_contents()
/mob/dead/observer/proc/view_gas()
set category = "Ghost"
@@ -568,7 +563,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
A.forceMove(T)
A.update_parallax_contents()
else
to_chat(A, "This mob is not located in the game world.")

View File

@@ -165,7 +165,7 @@
/**
* Actual proc that removes us and puts us back on lobby
*
*
* Returns the new mob.
*/
/mob/dead/observer/proc/transfer_to_lobby()
@@ -174,8 +174,7 @@
return
client.screen.Cut()
client.view_size.resetToDefault()
client.generate_clickcatcher()
client.apply_clickcatcher()
client.update_clickcatcher()
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))
client.view_size.resetToDefault()

View File

@@ -414,10 +414,6 @@
drop_all_held_items()
/obj/item/proc/equip_to_best_slot(mob/M)
if(src != M.get_active_held_item())
to_chat(M, "<span class='warning'>You are not holding anything to equip!</span>")
return FALSE
if(M.equip_to_appropriate_slot(src, TRUE))
M.update_inv_hands()
return TRUE

View File

@@ -65,29 +65,30 @@
blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
//Effects of bloodloss
var/word = pick("dizzy","woozy","faint")
var/blood_effect_volume = blood_volume + integrating_blood
switch(blood_effect_volume)
if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
if(prob(10))
to_chat(src, "<span class='warning'>You feel terribly bloated.</span>")
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))
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
if(prob(5))
blur_eyes(6)
to_chat(src, "<span class='warning'>You feel very [word].</span>")
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
adjustOxyLoss(5)
if(prob(15))
Unconscious(rand(20,60))
to_chat(src, "<span class='warning'>You feel extremely [word].</span>")
if(-INFINITY to BLOOD_VOLUME_SURVIVE)
if(!HAS_TRAIT(src, TRAIT_NODEATH))
death()
if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM)) //Synths are immune to direct consequences of bloodloss, instead suffering penalties to heat exchange.
var/word = pick("dizzy","woozy","faint")
var/blood_effect_volume = blood_volume + integrating_blood
switch(blood_effect_volume)
if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
if(prob(10))
to_chat(src, "<span class='warning'>You feel terribly bloated.</span>")
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))
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
if(prob(5))
blur_eyes(6)
to_chat(src, "<span class='warning'>You feel very [word].</span>")
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
adjustOxyLoss(5)
if(prob(15))
Unconscious(rand(20,60))
to_chat(src, "<span class='warning'>You feel extremely [word].</span>")
if(-INFINITY to BLOOD_VOLUME_SURVIVE)
if(!HAS_TRAIT(src, TRAIT_NODEATH))
death()
var/temp_bleed = 0
//Bleeding out
@@ -156,7 +157,7 @@
blood_volume -= amount
var/list/blood_data = get_blood_data(blood_id)
var/list/blood_data = get_blood_data()
if(iscarbon(AM))
var/mob/living/carbon/C = AM
@@ -177,54 +178,53 @@
return TRUE
/mob/living/proc/get_blood_data(blood_id)
/mob/living/proc/get_blood_data()
return
/mob/living/carbon/get_blood_data(blood_id)
if(blood_id == /datum/reagent/blood || /datum/reagent/blood/jellyblood) //actual blood reagent
var/blood_data = list()
//set the blood data
blood_data["donor"] = src
blood_data["viruses"] = list()
/mob/living/carbon/get_blood_data()
var/blood_data = list()
//set the blood data
blood_data["donor"] = src
blood_data["viruses"] = list()
for(var/thing in diseases)
var/datum/disease/D = thing
blood_data["viruses"] += D.Copy()
for(var/thing in diseases)
var/datum/disease/D = thing
blood_data["viruses"] += D.Copy()
blood_data["blood_DNA"] = dna.unique_enzymes
blood_data["bloodcolor"] = dna.species.exotic_blood_color
if(disease_resistances && disease_resistances.len)
blood_data["resistances"] = disease_resistances.Copy()
var/list/temp_chem = list()
for(var/datum/reagent/R in reagents.reagent_list)
temp_chem[R.type] = R.volume
blood_data["trace_chem"] = list2params(temp_chem)
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["blood_DNA"] = dna.unique_enzymes
blood_data["bloodcolor"] = dna.species.exotic_blood_color
if(disease_resistances && disease_resistances.len)
blood_data["resistances"] = disease_resistances.Copy()
var/list/temp_chem = list()
for(var/datum/reagent/R in reagents.reagent_list)
temp_chem[R.type] = R.volume
blood_data["trace_chem"] = list2params(temp_chem)
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)
if(!suiciding)
blood_data["cloneable"] = 1
blood_data["blood_type"] = dna.blood_type
blood_data["gender"] = gender
blood_data["real_name"] = real_name
blood_data["features"] = dna.features
blood_data["factions"] = faction
blood_data["quirks"] = list()
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
blood_data["quirks"] += T.type
blood_data["changeling_loudness"] = 0
if(mind)
var/datum/antagonist/changeling/ling = mind.has_antag_datum(/datum/antagonist/changeling)
if(istype(ling))
blood_data["changeling_loudness"] = ling.loudfactor
return blood_data
if(!suiciding)
blood_data["cloneable"] = 1
blood_data["blood_type"] = dna.blood_type
blood_data["gender"] = gender
blood_data["real_name"] = real_name
blood_data["features"] = dna.features
blood_data["factions"] = faction
blood_data["quirks"] = list()
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
blood_data["quirks"] += T.type
blood_data["changeling_loudness"] = 0
if(mind)
var/datum/antagonist/changeling/ling = mind.has_antag_datum(/datum/antagonist/changeling)
if(istype(ling))
blood_data["changeling_loudness"] = ling.loudfactor
return blood_data
//get the id of the substance this mob use as blood.
/mob/proc/get_blood_id()

View File

@@ -6,8 +6,6 @@
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
hud_type = /datum/hud/alien
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/leap_on_click = 0
@@ -22,41 +20,26 @@
can_ventcrawl = TRUE
GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
. = ..()
/mob/living/carbon/alien/humanoid/ComponentInitialize()
. = ..()
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -3)
AddElement(/datum/element/strippable, GLOB.strippable_alien_humanoid_items)
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
return handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/list/dat = list()
dat += {"
<HR>
<span class='big bold'>[name]</span>
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=[REF(src)];pouches=1'>Empty Pouches</A>"
if(handcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
user << browse(dat.Join(), "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
//strip panel & embeds
@@ -70,12 +53,6 @@
return
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
if(href_list["pouches"])
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
dropItemToGround(r_store)
dropItemToGround(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free

View File

@@ -51,10 +51,6 @@
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
/mob/living/carbon/alien/larva/show_inv(mob/user)
return
/mob/living/carbon/alien/larva/toggle_throw_mode()
return

View File

@@ -229,61 +229,8 @@
/mob/living/carbon/proc/canBeHandcuffed()
return 0
/mob/living/carbon/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Head:</B> <A href='?src=[REF(src)];item=[SLOT_HEAD]'> [(head && !(head.item_flags & ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=[REF(src)];item=[SLOT_WEAR_MASK]'> [(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Neck:</B> <A href='?src=[REF(src)];item=[SLOT_NECK]'> [(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "Nothing"]</A>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "Nothing"]</a>"
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[SLOT_BACK]'>[back ? back : "Nothing"]</A>"
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS) && istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
if(handcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/mob/living/carbon/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE))
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
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 & 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 your [ITEM.name].</span>", \
target = usr, target_message = "<span class='danger'>You try to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY))
if(internal)
internal = null
update_internals_hud_icon(0)
else if(ITEM && istype(ITEM, /obj/item/tank))
if((wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internal = ITEM
update_internals_hud_icon(1)
visible_message("<span class='danger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>", \
"<span class='userdanger'>[usr] [internal ? "opens" : "closes"] the valve on your [ITEM.name].</span>", \
target = usr, target_message = "<span class='danger'>You [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>")
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE))
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
@@ -699,7 +646,7 @@
become_blind(EYES_COVERED)
else if(tinttotal >= TINT_DARKENED)
cure_blind(EYES_COVERED)
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/impaired, 2)
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/scaled/impaired, 2)
else
cure_blind(EYES_COVERED)
clear_fullscreen("tint", 0)
@@ -775,10 +722,10 @@
visionseverity = 9
if(-INFINITY to -24)
visionseverity = 10
overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/crit/vision, visionseverity)
overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/scaled/crit/vision, visionseverity)
else
clear_fullscreen("critvision")
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity)
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/scaled/crit, severity)
else
clear_fullscreen("crit")
clear_fullscreen("critvision")
@@ -802,7 +749,7 @@
severity = 6
if(45 to INFINITY)
severity = 7
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity)
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/scaled/oxy, severity)
else
clear_fullscreen("oxy")
@@ -823,7 +770,7 @@
severity = 5
if(85 to INFINITY)
severity = 6
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
else
clear_fullscreen("brute")

View File

@@ -361,7 +361,7 @@
return embeds
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
. = ..()
var/damage = override_protection ? intensity : intensity - get_eye_protection()

View File

@@ -0,0 +1,145 @@
/datum/strippable_item/mob_item_slot/head
key = STRIPPABLE_ITEM_HEAD
item_slot = SLOT_HEAD
/datum/strippable_item/mob_item_slot/back
key = STRIPPABLE_ITEM_BACK
item_slot = SLOT_BACK
/datum/strippable_item/mob_item_slot/back/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/back/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/mask
key = STRIPPABLE_ITEM_MASK
item_slot = SLOT_WEAR_MASK
/datum/strippable_item/mob_item_slot/neck
key = STRIPPABLE_ITEM_NECK
item_slot = SLOT_NECK
/datum/strippable_item/mob_item_slot/handcuffs
key = STRIPPABLE_ITEM_HANDCUFFS
item_slot = SLOT_HANDCUFFED
/datum/strippable_item/mob_item_slot/handcuffs/should_show(atom/source, mob/user)
if (!iscarbon(source))
return FALSE
var/mob/living/carbon/carbon_source = source
return !isnull(carbon_source.handcuffed)
// You shouldn't be able to equip things to handcuff slots.
/datum/strippable_item/mob_item_slot/handcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
return FALSE
/datum/strippable_item/mob_item_slot/legcuffs
key = STRIPPABLE_ITEM_LEGCUFFS
item_slot = SLOT_LEGCUFFED
/datum/strippable_item/mob_item_slot/legcuffs/should_show(atom/source, mob/user)
if (!iscarbon(source))
return FALSE
var/mob/living/carbon/carbon_source = source
return !isnull(carbon_source.legcuffed)
// You shouldn't be able to equip things to legcuff slots.
/datum/strippable_item/mob_item_slot/legcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
return FALSE
/// A strippable item for a hand
/datum/strippable_item/hand
// Putting dangerous clothing in our hand is fine.
warn_dangerous_clothing = FALSE
/// Which hand?
var/hand_index
/datum/strippable_item/hand/get_item(atom/source)
if (!ismob(source))
return null
var/mob/mob_source = source
return mob_source.get_item_for_held_index(hand_index)
/datum/strippable_item/hand/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!ismob(source))
return FALSE
var/mob/mob_source = source
if (!mob_source.can_put_in_hand(equipping, hand_index))
to_chat(src, "<span class='warning'>\The [equipping] doesn't fit in that place!</span>")
return FALSE
return TRUE
/datum/strippable_item/hand/start_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return
if (!ismob(source))
return FALSE
var/mob/mob_source = source
if (!do_mob(user, source, equipping.equip_delay_other))
return FALSE
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
if (!mob_source.can_put_in_hand(equipping, hand_index))
return FALSE
if (!user.temporarilyRemoveItemFromInventory(equipping))
return FALSE
return TRUE
/datum/strippable_item/hand/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
if (!iscarbon(source))
return FALSE
var/mob/mob_source = source
mob_source.put_in_hand(equipping, hand_index)
/datum/strippable_item/hand/start_unequip(atom/source, mob/user)
. = ..()
if (!.)
return
return start_unequip_mob(get_item(source), source, user)
/datum/strippable_item/hand/finish_unequip(atom/source, mob/user)
..()
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
if (!ismob(source))
return FALSE
return finish_unequip_mob(item, source, user)
/datum/strippable_item/hand/left
key = STRIPPABLE_ITEM_LHAND
hand_index = 1
/datum/strippable_item/hand/right
key = STRIPPABLE_ITEM_RHAND
hand_index = 2

View File

@@ -37,7 +37,7 @@
var/list/whatmighthappen = list()
whatmighthappen += list("avoided" = 3, "dropthing" = 1, "movetile" = 1, "shortdeaf" = 1, "flopover" = 1, "nutriloss" = 1, "selfflash" = 1, "harmies" = 1)
if(corruption >= CORRUPTION_THRESHHOLD_MAJOR)
whatmighthappen += list("longdeaf" = 1, "longknockdown" = 1, "shortlimbdisable" = 1, "shortblind" = 1, "shortstun" = 1, "shortmute" = 1, "vomit" = 1, "halluscinate" = 1)
whatmighthappen += list("longdeaf" = 1, "longknockdown" = 1, "shortlimbdisable" = 1, "shortblind" = 1, "shortstun" = 1, "shortmute" = 1, "vomit" = 1, "hallucinate" = 1, "jamcoolanthud" = 1)
if(corruption >= CORRUPTION_THRESHHOLD_CRITICAL)
whatmighthappen += list("receporgandamage" = 1, "longlimbdisable" = 1, "blindmutedeaf" = 1, "longstun" = 1, "sleep" = 1, "inducetrauma" = 1, "amplifycorrupt" = 1, "changetemp" = 1)
var/event = pickweight(whatmighthappen)
@@ -97,8 +97,10 @@
if("vomit")
to_chat(src, "<span class='notice'>Ejecting contaminant.</span>")
vomit()
if("halluscinate")
if("hallucinate")
hallucination += 20 //Doesn't give a cue
if("jamcoolanthud")
hud_used.coolant_display.jam(10)
if("receporgandamage")
adjustOrganLoss(ORGAN_SLOT_EARS, rand(10, 20))
adjustOrganLoss(ORGAN_SLOT_EYES, rand(10, 20))
@@ -159,7 +161,7 @@
/mob/living/carbon/proc/forcesleep(time = 100)
to_chat(src, "<span class='notice'>Preparations complete, powering down.</span>")
Sleeping(time, 0)
Sleeping(time)
#undef CORRUPTION_CHECK_INTERVAL

View File

@@ -1,3 +1,4 @@
GLOBAL_LIST_EMPTY(dead_players_during_shift)
/mob/living/carbon/human/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-h")
@@ -39,7 +40,9 @@
dizziness = 0
jitteriness = 0
if(client && !suiciding && !(client in GLOB.dead_players_during_shift))
GLOB.dead_players_during_shift += client
GLOB.deaths_during_shift++
if(ismecha(loc))
var/obj/mecha/M = loc
if(M.occupant == src)

View File

@@ -31,6 +31,27 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
randomize_human(src)
dna.initialize_dna(skip_index = TRUE) //Skip stuff that requires full round init.
/// Provides a dummy that is consistently bald, white, naked, etc.
/mob/living/carbon/human/dummy/consistent
/mob/living/carbon/human/dummy/consistent/setup_human_dna()
create_dna(src)
dna.initialize_dna(skip_index = TRUE)
dna.features["body_markings"] = "None"
dna.features["ears"] = "Cat"
dna.features["ethcolor"] = COLOR_WHITE
dna.features["frills"] = "None"
dna.features["horns"] = "None"
dna.features["mcolor"] = COLOR_LIME
dna.features["moth_antennae"] = "Plain"
dna.features["moth_markings"] = "None"
dna.features["moth_wings"] = "Plain"
dna.features["snout"] = "Round"
dna.features["spines"] = "None"
dna.features["tail_human"] = "Cat"
dna.features["tail_lizard"] = "Smooth"
//Inefficient pooling/caching way.
GLOBAL_LIST_EMPTY(human_dummy_list)
GLOBAL_LIST_EMPTY(dummy_mob_list)

View File

@@ -249,16 +249,17 @@
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
msg += "[t_He] look[p_s()] extremely disgusted.\n"
var/apparent_blood_volume = blood_volume
if(dna.species.use_skintones && skin_tone == "albino")
apparent_blood_volume -= 150 // enough to knock you down one tier
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
msg += "<b>[t_He] look[p_s()] like pale death.</b>\n"
if(-INFINITY to BLOOD_VOLUME_BAD)
msg += "<span class='deadsay'><b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b></span>\n"
if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
var/apparent_blood_volume = blood_volume
if(dna.species.use_skintones && skin_tone == "albino")
apparent_blood_volume -= 150 // enough to knock you down one tier
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
msg += "<b>[t_He] look[p_s()] like pale death.</b>\n"
if(-INFINITY to BLOOD_VOLUME_BAD)
msg += "<span class='deadsay'><b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b></span>\n"
if(bleedsuppress)
msg += "[t_He] [t_is] embued with a power that defies bleeding.\n" // only statues and highlander sword can cause this so whatever

View File

@@ -47,6 +47,7 @@
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
AddElement(/datum/element/strippable, GLOB.strippable_human_items, /mob/living/carbon/human/.proc/should_strip)
/mob/living/carbon/human/Destroy()
QDEL_NULL(physiology)
@@ -110,106 +111,6 @@
var/datum/disease/D = thing
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
/mob/living/carbon/human/show_inv(mob/user)
user.set_machine(src)
var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask)
var/list/obscured = check_obscured_slots()
var/list/dat = list()
dat += "<table>"
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Back:</B></td><td><A href='?src=[REF(src)];item=[SLOT_BACK]'>[(back && !(back.item_flags & ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(back, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_BACK]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr><tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Head:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HEAD]'>[(head && !(head.item_flags & ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_WEAR_MASK in obscured)
dat += "<tr><td><font color=grey><B>Mask:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_MASK]'>[(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_NECK in obscured)
dat += "<tr><td><font color=grey><B>Neck:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=[REF(src)];item=[SLOT_NECK]'>[(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_GLASSES in obscured)
dat += "<tr><td><font color=grey><B>Eyes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Eyes:</B></td><td><A href='?src=[REF(src)];item=[SLOT_GLASSES]'>[(glasses && !(glasses.item_flags & ABSTRACT)) ? glasses : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_EARS in obscured)
dat += "<tr><td><font color=grey><B>Ears:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Ears:</B></td><td><A href='?src=[REF(src)];item=[SLOT_EARS]'>[(ears && !(ears.item_flags & ABSTRACT)) ? ears : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_SUIT]'>[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A>"
if(wear_suit)
if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/hardsuit_head = head && istype(head, /obj/item/clothing/head/helmet/space/hardsuit)
dat += "&nbsp;<A href='?src=[REF(src)];toggle_helmet=[SLOT_WEAR_SUIT]'>[hardsuit_head ? "Retract Helmet" : "Extend Helmet"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Suit Storage:</B></td><td><A href='?src=[REF(src)];item=[SLOT_S_STORE]'>[(s_store && !(s_store.item_flags & ABSTRACT)) ? s_store : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(s_store, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_S_STORE]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
else
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Suit Storage:</B></font></td></tr>"
if(SLOT_SHOES in obscured)
dat += "<tr><td><font color=grey><B>Shoes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Shoes:</B></td><td><A href='?src=[REF(src)];item=[SLOT_SHOES]'>[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "<font color=grey>Empty</font>"]</A>"
if(shoes && shoes.can_be_tied && shoes.tied != SHOES_KNOTTED)
dat += "&nbsp;<A href='?src=[REF(src)];shoes=[SLOT_SHOES]'>[shoes.tied ? "Untie shoes" : "Knot shoes"]</A>"
dat += "</td></tr>"
if(SLOT_GLOVES in obscured)
dat += "<tr><td><font color=grey><B>Gloves:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Gloves:</B></td><td><A href='?src=[REF(src)];item=[SLOT_GLOVES]'>[(gloves && !(gloves.item_flags & ABSTRACT)) ? gloves : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_W_UNIFORM in obscured)
dat += "<tr><td><font color=grey><B>Uniform:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Uniform:</B></td><td><A href='?src=[REF(src)];item=[SLOT_W_UNIFORM]'>[(w_uniform && !(w_uniform.item_flags & ABSTRACT)) ? w_uniform : "<font color=grey>Empty</font>"]</A></td></tr>"
if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (SLOT_W_UNIFORM in obscured))
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Pockets:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>ID:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Belt:</B></font></td></tr>"
else
dat += "<tr><td>&nbsp;&#8627;<B>Belt:</B></td><td><A href='?src=[REF(src)];item=[SLOT_BELT]'>[(belt && !(belt.item_flags & ABSTRACT)) ? belt : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(belt, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_BELT]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=[REF(src)];pockets=left'>[(l_store && !(l_store.item_flags & ABSTRACT)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
dat += "&nbsp;<A href='?src=[REF(src)];pockets=right'>[(r_store && !(r_store.item_flags & ABSTRACT)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>ID:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_ID]'>[(wear_id && !(wear_id.item_flags & ABSTRACT)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
if(handcuffed)
dat += "<tr><td><B>Handcuffed:</B> <A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Remove</A></td></tr>"
if(legcuffed)
dat += "<tr><td><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A></td></tr>"
dat += {"</table>
<A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob[REF(src)]", "[src]", 440, 510)
popup.set_content(dat.Join())
popup.open()
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
/mob/living/carbon/human/Crossed(atom/movable/AM)
@@ -231,83 +132,6 @@
return
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
if(href_list["toggle_helmet"])
if(!istype(head, /obj/item/clothing/head/helmet/space/hardsuit))
return
var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = head
visible_message("<span class='danger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
"<span class='userdanger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
target = usr, target_message = "<span class='danger'>You try to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
if(!do_mob(usr, src, hardsuit_head ? head.strip_delay : POCKET_STRIP_DELAY))
return
if(!istype(wear_suit, /obj/item/clothing/suit/space/hardsuit) || (hardsuit_head ? (!head || head != hardsuit_head) : head))
return
var/obj/item/clothing/suit/space/hardsuit/hardsuit = wear_suit //This should be an hardsuit given all our checks
if(hardsuit.ToggleHelmet(FALSE))
visible_message("<span class='danger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
"<span class='userdanger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
target = usr, target_message = "<span class='danger'>You [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
return
if(href_list["item"])
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots())
to_chat(usr, "<span class='warning'>You can't reach that! Something is covering it.</span>")
return
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
strip_mod = G.strip_mod
strip_silence = G.strip_silence
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? SLOT_R_STORE : SLOT_L_STORE)
var/obj/item/pocket_item = (pocket_id == SLOT_R_STORE ? r_store : l_store)
var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty
var/delay_denominator = 1
if(pocket_item && !(pocket_item.item_flags & ABSTRACT))
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))
to_chat(usr, "<span class='notice'>You try to place [place_item] into [src]'s [pocket_side] pocket.</span>")
delay_denominator = 4
else
return
if(do_mob(usr, src, max(round(POCKET_STRIP_DELAY/(delay_denominator*strip_mod)),1), ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster (and the strip_mod too)
if(pocket_item)
if(pocket_item == (pocket_id == SLOT_R_STORE ? r_store : l_store)) //item still in the pocket we search
dropItemToGround(pocket_item)
if(!usr.can_hold_items() || !usr.put_in_hands(pocket_item))
pocket_item.forceMove(drop_location())
log_combat(usr, src, "pickpocketed of item: [pocket_item]")
else
if(place_item)
if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE))
usr.temporarilyRemoveItemFromInventory(place_item, TRUE)
equip_to_slot(place_item, pocket_id, TRUE)
log_combat(usr, src, "placed item [place_item] onto")
//do nothing otherwise
// Update strip window
if(usr.machine == src && in_range(src, usr))
show_inv(usr)
else
// Display a warning if the user mocks up
if(!strip_silence)
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
log_combat(usr, src, "failed to [pocket_item ? "pickpocket item [pocket_item] from" : "place item [place_item] onto "]")
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY, null, FALSE))
// separate from first canusetopic
var/mob/living/user = usr
if(istype(user) && href_list["shoes"] && (user.mobility_flags & MOBILITY_USE)) // we need to be on the ground, so we'll be a bit looser
shoes.handle_tying(usr)
..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined
///////HUDs///////
if(href_list["hud"])
@@ -1124,9 +948,6 @@
/mob/living/carbon/human/species/android
race = /datum/species/android
/mob/living/carbon/human/species/angel
race = /datum/species/angel
/mob/living/carbon/human/species/corporate
race = /datum/species/corporate

View File

@@ -416,6 +416,7 @@
severity *= 0.5
var/do_not_stun = FALSE
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
hud_used?.coolant_display.jam(round(severity / 10, 1)) //Messes up the cooling system readout.
severity *= 0.5 //Robotpeople take less limb damage, but instead suffer system corruption (see carbon emp_act)
do_not_stun = TRUE
for(var/obj/item/bodypart/L in src.bodyparts)

View File

@@ -115,13 +115,13 @@
. = ..()
if(!.)
return
if(HAS_TRAIT(src, TRAIT_NOGUNS))
to_chat(src, "<span class='warning'>You can't bring yourself to use a ranged weapon!</span>")
return FALSE
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
balloon_alert(src, "fingers are too big!")
return FALSE
if(HAS_TRAIT(src, TRAIT_NOGUNS))
to_chat(src, span_warning("You can't bring yourself to use a ranged weapon!"))
return FALSE
/mob/living/carbon/human/proc/get_bank_account()
RETURN_TYPE(/datum/bank_account)

View File

@@ -0,0 +1,306 @@
#define INTERNALS_TOGGLE_DELAY (4 SECONDS)
#define POCKET_EQUIP_DELAY (1 SECONDS)
GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
/datum/strippable_item/mob_item_slot/head,
/datum/strippable_item/mob_item_slot/back,
/datum/strippable_item/mob_item_slot/mask,
/datum/strippable_item/mob_item_slot/neck,
/datum/strippable_item/mob_item_slot/eyes,
/datum/strippable_item/mob_item_slot/ears,
/datum/strippable_item/mob_item_slot/jumpsuit,
/datum/strippable_item/mob_item_slot/suit,
/datum/strippable_item/mob_item_slot/gloves,
/datum/strippable_item/mob_item_slot/feet,
/datum/strippable_item/mob_item_slot/suit_storage,
/datum/strippable_item/mob_item_slot/id,
/datum/strippable_item/mob_item_slot/belt,
/datum/strippable_item/mob_item_slot/pocket/left,
/datum/strippable_item/mob_item_slot/pocket/right,
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
/mob/living/carbon/human/proc/should_strip(mob/user)
if (user.pulling != src || user.grab_state != GRAB_AGGRESSIVE)
return TRUE
if (ishuman(user))
var/mob/living/carbon/human/human_user = user
return !human_user.can_be_firemanned(src)
return TRUE
/datum/strippable_item/mob_item_slot/eyes
key = STRIPPABLE_ITEM_EYES
item_slot = SLOT_GLASSES
/datum/strippable_item/mob_item_slot/ears
key = STRIPPABLE_ITEM_EARS
item_slot = SLOT_EARS
/datum/strippable_item/mob_item_slot/jumpsuit
key = STRIPPABLE_ITEM_JUMPSUIT
item_slot = SLOT_W_UNIFORM
/datum/strippable_item/mob_item_slot/jumpsuit/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/under/jumpsuit = get_item(source)
if (!istype(jumpsuit))
return null
return jumpsuit?.can_adjust ? "adjust_jumpsuit" : null
/datum/strippable_item/mob_item_slot/jumpsuit/alternate_action(atom/source, mob/user)
if (!..())
return null
var/obj/item/clothing/under/jumpsuit = get_item(source)
if (!istype(jumpsuit))
return null
to_chat(source, "<span class='notice'>[user] is trying to adjust your [jumpsuit.name].")
if (!do_mob(user, source, jumpsuit.strip_delay * 0.5, ignorehelditem = TRUE))
return
to_chat(source, "<span class='notice'>[user] successfully adjusted your [jumpsuit.name].")
jumpsuit.toggle_jumpsuit_adjust()
if (!ismob(source))
return null
var/mob/mob_source = source
mob_source.update_inv_w_uniform()
mob_source.update_body()
return TRUE
/datum/strippable_item/mob_item_slot/suit
key = STRIPPABLE_ITEM_SUIT
item_slot = SLOT_WEAR_SUIT
/datum/strippable_item/mob_item_slot/suit/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/suit/space/hardsuit/suit = get_item(source)
if(istype(suit))
if(!suit.helmettype)
return null
return suit?.suittoggled ? "disable_helmet" : "enable_helmet"
return null
/datum/strippable_item/mob_item_slot/suit/alternate_action(mob/living/carbon/human/source, mob/user)
if(!..())
return null
if(ishuman(source))
var/obj/item/clothing/suit/space/hardsuit/hardsuit = get_item(source)
var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = hardsuit.helmet
source.visible_message("<span class='danger'>[user] tries to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>", \
"<span class='userdanger'>[user] tries to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>", \
target = user, target_message = "<span class='danger'>You try to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>")
if(!do_mob(user, source, hardsuit_head ? hardsuit_head.strip_delay : POCKET_STRIP_DELAY, ignorehelditem = TRUE))
return null
if((source.head != hardsuit_head) && source.head)
return null
if(hardsuit.ToggleHelmet(FALSE))
source.visible_message("<span class='danger'>[user] [hardsuit_head ? "retract" : "extend"] [source]'s helmet</span>", \
"<span class='userdanger'>[user] [hardsuit_head ? "retract" : "extend"] [source]'s helmet</span>", \
target = user, target_message = "<span class='danger'>You [hardsuit_head ? "retract" : "extend"] [source]'s helmet.</span>")
return TRUE
/datum/strippable_item/mob_item_slot/gloves
key = STRIPPABLE_ITEM_GLOVES
item_slot = SLOT_GLOVES
/datum/strippable_item/mob_item_slot/feet
key = STRIPPABLE_ITEM_FEET
item_slot = SLOT_SHOES
/datum/strippable_item/mob_item_slot/feet/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/shoes/shoes = get_item(source)
if (!istype(shoes) || !shoes.can_be_tied)
return null
switch (shoes.tied)
if (SHOES_UNTIED)
return "knot"
if (SHOES_TIED)
return "untie"
if (SHOES_KNOTTED)
return "unknot"
/datum/strippable_item/mob_item_slot/feet/alternate_action(atom/source, mob/user)
if(!..())
return null
var/obj/item/clothing/shoes/shoes = get_item(source)
if (!istype(shoes))
return null
shoes.handle_tying(user)
return TRUE
/datum/strippable_item/mob_item_slot/suit_storage
key = STRIPPABLE_ITEM_SUIT_STORAGE
item_slot = SLOT_S_STORE
/datum/strippable_item/mob_item_slot/suit_storage/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/suit_storage/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/id
key = STRIPPABLE_ITEM_ID
item_slot = SLOT_WEAR_ID
/datum/strippable_item/mob_item_slot/belt
key = STRIPPABLE_ITEM_BELT
item_slot = SLOT_BELT
/datum/strippable_item/mob_item_slot/belt/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/belt/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/pocket
/// Which pocket we're referencing. Used for visible text.
var/pocket_side
/datum/strippable_item/mob_item_slot/pocket/get_obscuring(atom/source)
return isnull(get_item(source)) \
? STRIPPABLE_OBSCURING_NONE \
: STRIPPABLE_OBSCURING_HIDDEN
/datum/strippable_item/mob_item_slot/pocket/get_equip_delay(obj/item/equipping)
return POCKET_EQUIP_DELAY
/datum/strippable_item/mob_item_slot/pocket/start_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
warn_owner(source)
/datum/strippable_item/mob_item_slot/pocket/start_unequip(atom/source, mob/user)
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
to_chat(user, span_notice("You try to empty [source]'s [pocket_side] pocket."))
var/log_message = "[key_name(source)] is being pickpocketed of [item] by [key_name(user)] ([pocket_side])"
user.log_message(log_message, LOG_ATTACK, color="red")
source.log_message(log_message, LOG_VICTIM, color="red", log_globally=FALSE)
item.add_fingerprint(source)
var/result = start_unequip_mob(item, source, user, POCKET_STRIP_DELAY)
if (!result)
warn_owner(source)
return result
/datum/strippable_item/mob_item_slot/pocket/proc/warn_owner(atom/owner)
to_chat(owner, span_warning("You feel your [pocket_side] pocket being fumbled with!"))
/datum/strippable_item/mob_item_slot/pocket/left
key = STRIPPABLE_ITEM_LPOCKET
item_slot = SLOT_L_STORE
pocket_side = "left"
/datum/strippable_item/mob_item_slot/pocket/right
key = STRIPPABLE_ITEM_RPOCKET
item_slot = SLOT_R_STORE
pocket_side = "right"
/proc/get_strippable_alternate_action_internals(obj/item/item, atom/source)
if (!iscarbon(source))
return null
var/mob/living/carbon/carbon_source = source
var/obj/item/clothing/mask
var/internals = FALSE
for(mask in GET_INTERNAL_SLOTS(carbon_source))
if(istype(mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = mask
if(M.mask_adjusted)
if(M.adjustmask(carbon_source))
internals = TRUE
else
internals = TRUE
if((mask.clothing_flags & ALLOWINTERNALS))
internals = TRUE
if(carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internals = TRUE
if (internals && istype(item, /obj/item/tank))
return isnull(carbon_source.internal) ? "enable_internals" : "disable_internals"
/proc/strippable_alternate_action_internals(obj/item/item, atom/source, mob/user)
var/obj/item/tank/tank = item
if (!istype(tank))
return null
var/mob/living/carbon/carbon_source = source
if (!istype(carbon_source))
return null
var/obj/item/clothing/mask
var/internals = FALSE
for(mask in GET_INTERNAL_SLOTS(carbon_source))
if(istype(mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = mask
if(M.mask_adjusted)
if(M.adjustmask(carbon_source))
internals = TRUE
else
internals = TRUE
if((mask.clothing_flags & ALLOWINTERNALS))
internals = TRUE
if(!internals)
return null
carbon_source.visible_message(
span_danger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]."),
span_userdanger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_notice("You try to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]..."))
if(!do_mob(user, carbon_source, INTERNALS_TOGGLE_DELAY, ignorehelditem = TRUE))
return null
if(carbon_source.internal)
carbon_source.internal = null
// This isn't meant to be FALSE, it correlates to the icon's name.
carbon_source.update_internals_hud_icon(0)
else if (!QDELETED(item))
if(internals || carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
carbon_source.internal = item
carbon_source.update_internals_hud_icon(1)
carbon_source.visible_message(
span_danger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on [source]'s [item.name]."),
span_userdanger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_notice("You [isnull(carbon_source.internal) ? "close" : "open"] the valve on [source]'s [item.name]."))
return TRUE
#undef INTERNALS_TOGGLE_DELAY
#undef POCKET_EQUIP_DELAY

View File

@@ -209,7 +209,7 @@
update_tint()
if(G.vision_correction)
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
if(!QDELETED(src))

View File

@@ -30,6 +30,8 @@
/mob/living/carbon/human/PhysicalLife(seconds, times_fired)
if(!(. = ..()))
return
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM) && hud_used)
hud_used.coolant_display.update_counter(src)
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
@@ -76,9 +78,23 @@
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
var/L = getorganslot(ORGAN_SLOT_LUNGS)
if(breath && HAS_TRAIT(src, TRAIT_NOBREATH) && HAS_TRAIT(src, TRAIT_AUXILIARY_LUNGS)) //Something something bz and synth cooling systems interacting (in reality, this only exists to not make robot lings too strong)
var/total_moles = breath.total_moles()
var/pressure = breath.return_pressure()
#define PP_MOLES(X) ((X / total_moles) * pressure)
#define PP(air, gas) PP_MOLES(air.get_moles(gas))
var/bz_pp = PP(breath, GAS_BZ)
if(bz_pp > 1)
reagents.add_reagent(/datum/reagent/bz_metabolites,5)
else if(bz_pp > 0.1)
reagents.add_reagent(/datum/reagent/bz_metabolites,1)
#undef PP_MOLES
#undef PP
var/L = getorganslot(ORGAN_SLOT_LUNGS)
if(!L)
if(HAS_TRAIT(src, TRAIT_NOBREATH))
return
if(health >= crit_threshold)
adjustOxyLoss(HUMAN_MAX_OXYLOSS + 1)
else if(!HAS_TRAIT(src, TRAIT_NOCRITDAMAGE))

View File

@@ -108,6 +108,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/burnmod = 1
///multiplier for damage from cold temperature
var/coldmod = 1
///moves their safe minimum temp by this value.
var/cold_offset = 0
///moves their safe maximum temp by this value.
var/hot_offset = 0
///multiplier for damage from hot temperature
var/heatmod = 1
///multiplier for stun durations
@@ -138,6 +142,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/// A path to an outfit that is important for species life e.g. plasmaman outfit
var/datum/outfit/outfit_important_for_life
///Is this species a flying species? Used as an easy check for some things
var/flying_species = FALSE
///The actual flying ability given to flying species
var/datum/action/innate/flight/fly
///Current wings icon
var/wings_icon = "Angel"
//Dictates which wing icons are allowed for a given species. If count is >1 a radial menu is used to choose between all icons in list
var/list/wings_icons = SPECIES_WINGS_ANGEL
///Species-only traits. Can be found in [code/__DEFINES/DNA.dm]
var/list/species_traits = list(HAS_FLESH,HAS_BONE) //by default they can scar and have bones/flesh unless set to something else
///Generic traits tied to having the species.
@@ -147,6 +160,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/list/blacklisted_quirks = list() // Quirks that will be removed upon gaining this species, to be defined by species
var/list/removed_quirks = list() // Quirks that got removed due to being blacklisted, and will be restored when on_species_loss() is called
var/balance_point_values = FALSE //If true, will balance point values on species gain after removing blacklisted quirks. Use this for roundstart species with blacklisted quirks that people may attempt to use to powergame trait points.
///Punch-specific attack verb.
var/attack_verb = "punch"
@@ -331,7 +345,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/should_have_brain = TRUE
var/should_have_heart = !(NOBLOOD in species_traits)
var/should_have_lungs = !(TRAIT_NOBREATH in inherent_traits)
var/should_have_lungs = ((TRAIT_AUXILIARY_LUNGS in inherent_traits) || !(TRAIT_NOBREATH in inherent_traits))
var/should_have_appendix = !(TRAIT_NOHUNGER in inherent_traits)
var/should_have_eyes = TRUE
var/should_have_ears = TRUE
@@ -490,6 +504,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/datum/disease/A in C.diseases)
A.cure(FALSE)
if(flying_species && isnull(fly))
fly = new
fly.Grant(C)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(NOGENITALS in H.dna.species.species_traits)
@@ -564,22 +582,54 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(F)
qdel(F)
if(flying_species)
if(C.movement_type & FLYING)
ToggleFlight(C)
fly.Remove(C)
QDEL_NULL(fly)
if(C.dna && C.dna.species && (C.dna.features["wings"] == wings_icon))
if("wings" in C.dna.species.mutant_bodyparts)
C.dna.species.mutant_bodyparts -= "wings"
C.dna.features["wings"] = "None"
C.update_body()
if(ROBOTIC_LIMBS in species_traits)
for(var/obj/item/bodypart/B in C.bodyparts)
B.change_bodypart_status(initial(B.status), FALSE, TRUE)
if((TRAIT_ROBOTIC_ORGANISM in inherent_traits) && C.hud_used)
C.hud_used.coolant_display.clear()
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
// shamelessly inspired by antag_datum.remove_blacklisted_quirks()
/datum/species/proc/remove_blacklisted_quirks(mob/living/carbon/C)
var/mob/living/L = C.mind?.current
if(istype(L))
for(var/q in L.roundstart_quirks)
var/datum/quirk/Q = q
if(Q.type in blacklisted_quirks)
qdel(Q)
removed_quirks += Q.type
. = 0
if(istype(C))
if(!balance_point_values)
for(var/q in C.roundstart_quirks)
var/datum/quirk/Q = q
if(Q.type in blacklisted_quirks)
removed_quirks += Q.type
. += 1
qdel(Q)
else
var/point_overhead = 0
for(var/datum/quirk/Q as anything in C.roundstart_quirks)
if(Q.type in blacklisted_quirks)
point_overhead -= Q.value
removed_quirks += Q.type
. += 1
qdel(Q)
if(point_overhead)
for(var/datum/quirk/Q as anything in C.roundstart_quirks)
if(Q.value > 0)
point_overhead -= Q.value
removed_quirks += Q.type
. += 1
qdel(Q)
if(!point_overhead)
break
// restore any quirks that we removed
/datum/species/proc/restore_quirks(mob/living/carbon/C)
@@ -1159,13 +1209,18 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return move_trail */
/datum/species/proc/spec_life(mob/living/carbon/human/H)
if(flying_species) //turns off flight automatically if they can't.
HandleFlight(H)
if(HAS_TRAIT(H, TRAIT_NOBREATH))
H.setOxyLoss(0)
H.losebreath = 0
var/takes_crit_damage = !HAS_TRAIT(H, TRAIT_NOCRITDAMAGE)
if((H.health < H.crit_threshold) && takes_crit_damage)
H.adjustBruteLoss(1)
if(!HAS_TRAIT(H, TRAIT_ROBOTIC_ORGANISM))
H.adjustBruteLoss(1)
else
H.adjustFireLoss(1) //Robots melt instead of taking brute.
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -1874,7 +1929,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(BODY_ZONE_HEAD)
if(!I.get_sharpness() && armor_block < 50)
if(prob(I.force))
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
if(HAS_TRAIT(H, TRAIT_ROBOTIC_ORGANISM))
H.adjustToxLoss(5, toxins_type = TOX_SYSCORRUPT) //Bonk! - Effectively 5 bonus damage
else
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
@@ -1890,11 +1945,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
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 && !/datum/antagonist/gang/boss)
if(rev)
rev.remove_revolutionary(FALSE, user)
if(gang)
H.mind.remove_antag_datum(/datum/antagonist/gang)
if(bloody) //Apply blood
if(H.wear_mask)
@@ -2171,15 +2223,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//Thermal protection (insulation) has mixed benefits in two situations (hot in hot places, cold in hot places)
if(!H.on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
var/natural = 0
var/cooling_efficiency = 1
if(H.stat != DEAD)
natural = H.natural_bodytemperature_stabilization()
cooling_efficiency = H.get_cooling_efficiency()
if(HAS_TRAIT(H, TRAIT_ROBOTIC_ORGANISM)) //Synths by default slowly heat up and need to lose said heat to the environment or active cooling. If you have very high cooling efficiency, you instead passively cool.
H.adjust_bodytemperature(SYNTH_PASSIVE_HEAT_GAIN * (1 - cooling_efficiency), (T0C + SYNTH_MIN_PASSIVE_COOLING_TEMP), (T0C + SYNTH_MAX_PASSIVE_GAIN_TEMP))
var/thermal_protection = 1
if(loc_temp < H.bodytemperature) //Place is colder than we are
thermal_protection -= H.get_thermal_protection(loc_temp, TRUE) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //we're cold, insulation helps us retain body heat and will reduce the heat we lose to the environment
H.adjust_bodytemperature((thermal_protection+1)*natural + max(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_COLD_DIVISOR, BODYTEMP_COOLING_MAX))
H.adjust_bodytemperature((thermal_protection+1)*natural + max((thermal_protection * (loc_temp - H.bodytemperature) * cooling_efficiency) / BODYTEMP_COLD_DIVISOR, BODYTEMP_COOLING_MAX))
else //we're sweating, insulation hinders our ability to reduce heat - and it will reduce the amount of cooling you get from the environment
H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + max((thermal_protection * (loc_temp - H.bodytemperature) + BODYTEMP_NORMAL - H.bodytemperature) / BODYTEMP_COLD_DIVISOR , BODYTEMP_COOLING_MAX)) //Extra calculation for hardsuits to bleed off heat
H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + max(((thermal_protection * (loc_temp - H.bodytemperature) + BODYTEMP_NORMAL - H.bodytemperature) * cooling_efficiency) / BODYTEMP_COLD_DIVISOR , BODYTEMP_COOLING_MAX)) //Extra calculation for hardsuits to bleed off heat
else //Place is hotter than we are
thermal_protection -= H.get_thermal_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //and we're cold, insulation enhances our ability to retain body heat but reduces the heat we get from the environment
@@ -2203,7 +2260,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 3)
// +/- 50 degrees from 310K is the 'safe' zone, where no damage is dealt.
if(H.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTHEAT))
if(H.bodytemperature > (BODYTEMP_HEAT_DAMAGE_LIMIT + hot_offset) && !HAS_TRAIT(H, TRAIT_RESISTHEAT))
//Body temperature is too hot.
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
@@ -2231,11 +2288,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.emote("scream")
H.apply_damage(burn_damage, BURN)
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
else if(H.bodytemperature < (BODYTEMP_COLD_DAMAGE_LIMIT + cold_offset) && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
//Apply cold slowdown
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = (((BODYTEMP_COLD_DAMAGE_LIMIT + cold_offset) - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
switch(H.bodytemperature)
if(200 to BODYTEMP_COLD_DAMAGE_LIMIT)
H.throw_alert("temp", /atom/movable/screen/alert/shiver, 1)
@@ -2356,10 +2413,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return
////////////
//Stun//
// Stun //
////////////
/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
if(flying_species && H.movement_type & FLYING)
ToggleFlight(H,0)
flyslip(H)
if(H)
stop_wagging_tail(H)
. = stunmod * H.physiology.stun_mod * amount
@@ -2369,10 +2429,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//////////////
/datum/species/proc/space_move(mob/living/carbon/human/H)
return 0
if(H.movement_type & FLYING)
return TRUE
return FALSE
/datum/species/proc/negates_gravity(mob/living/carbon/human/H)
return 0
if(H.movement_type & FLYING)
return TRUE
return FALSE
////////////////
//Tail Wagging//
@@ -2406,3 +2470,130 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
mutant_bodyparts["spines"] = mutant_bodyparts["waggingspines"]
mutant_bodyparts -= "waggingspines"
H.update_body()
///////////////
//FLIGHT SHIT//
///////////////
/datum/species/proc/GiveSpeciesFlight(mob/living/carbon/human/H, all_wings = FALSE)
if(flying_species) //grant them the choice of all wings if they don't have them
all_wings = TRUE
flying_species = TRUE
//CITADEL CHANGE: check if they already have wings, and "evolve" them based off of the wings they have. If they have none, use their species wings basis.
var/list/wingslist
if(all_wings) //give them the full list of wing choices to pick from, typically if they drink a second flight potion
wingslist = SPECIES_WINGS_ALL
else
//why the fuck do we have two different wing types anyways? they're literally almost both using the same wing shit too.
var/datum/sprite_accessory/deco_wings/D = GLOB.deco_wings_list[H.dna.features["deco_wings"]]
var/datum/sprite_accessory/insect_wings/I = GLOB.insect_wings_list[H.dna.features["insect_wings"]]
if(mutant_bodyparts["deco_wings"] && D?.upgrade_to.len) //species check to see if they were allowed to have deco wings
wingslist = D.upgrade_to
else if(mutant_bodyparts["insect_wings"] && I?.upgrade_to.len) //species check to see if they were allowed to have insect wings
wingslist = I.upgrade_to
else
wingslist = wings_icons
if(wingslist.len > 1)
if(!H.client)
wings_icon = pick(wingslist)
else
var/list/wings = list()
for(var/W in wingslist)
var/datum/sprite_accessory/S = GLOB.wings_list[W] //Gets the datum for every wing this species has, then prompts user with a radial menu
var/image/img = image(icon = 'icons/mob/wings_functional.dmi', icon_state = "m_wingsopen_[S.icon_state]_BEHIND") //Process the HUD elements
img.transform *= 0.5
img.pixel_x = -32
if(wings[S.name])
stack_trace("Different wing types with repeated names. Please fix as this may cause issues.")
else
wings[S.name] = img
wings_icon = show_radial_menu(H, H, wings, tooltips = TRUE)
if(!wings_icon)
wings_icon = pick(wings_icons)
else
wings_icon = wingslist[1]
if(isnull(fly))
fly = new
fly.Grant(H)
if(H.dna.features["wings"] != wings_icon)
mutant_bodyparts["wings"] = wings_icon
H.dna.features["wings"] = wings_icon
H.update_body()
/datum/species/proc/HandleFlight(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
if(!CanFly(H))
ToggleFlight(H)
return FALSE
return TRUE
else
return FALSE
/datum/species/proc/CanFly(mob/living/carbon/human/H)
if(H.stat || !(H.mobility_flags & MOBILITY_STAND))
return FALSE
if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too
to_chat(H, "<span class='warning'>Your suit blocks your wings from extending!</span>")
return FALSE
var/turf/T = get_turf(H)
if(!T)
return FALSE
var/datum/gas_mixture/environment = T.return_air()
if(environment && !(environment.return_pressure() > 30))
to_chat(H, "<span class='warning'>The atmosphere is too thin for you to fly!</span>")
return FALSE
else
return TRUE
/datum/species/proc/flyslip(mob/living/carbon/human/H)
var/obj/buckled_obj
if(H.buckled)
buckled_obj = H.buckled
to_chat(H, "<span class='notice'>Your wings spazz out and launch you!</span>")
playsound(H.loc, 'sound/misc/slip.ogg', 50, TRUE, -3)
for(var/obj/item/I in H.held_items)
H.accident(I)
var/olddir = H.dir
H.stop_pulling()
if(buckled_obj)
buckled_obj.unbuckle_mob(H)
step(buckled_obj, olddir)
else
new /datum/forced_movement(H, get_ranged_target_turf(H, olddir, 4), 1, FALSE, CALLBACK(H, /mob/living/carbon/.proc/spin, 1, 1))
return TRUE
//UNSAFE PROC, should only be called through the Activate or other sources that check for CanFly
/datum/species/proc/ToggleFlight(mob/living/carbon/human/H)
if(!(H.movement_type & FLYING) && CanFly(H))
stunmod *= 2
speedmod -= 0.35
H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
H.pass_flags |= PASSTABLE
H.OpenWings()
H.update_mobility()
else
stunmod *= 0.5
speedmod += 0.35
H.setMovetype(H.movement_type & ~FLYING)
override_float = FALSE
H.pass_flags &= ~PASSTABLE
H.CloseWings()
/datum/action/innate/flight
name = "Toggle Flight"
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "flight"
/datum/action/innate/flight/Activate()
var/mob/living/carbon/human/H = owner
var/datum/species/S = H.dna.species
if(S.CanFly(H))
S.ToggleFlight(H)
if(!(H.movement_type & FLYING))
to_chat(H, "<span class='notice'>You settle gently back onto the ground...</span>")
else
to_chat(H, "<span class='notice'>You beat your wings and begin to hover gently above the ground...</span>")
H.set_resting(FALSE, TRUE)

View File

@@ -12,3 +12,4 @@
species_language_holder = /datum/language_holder/synthetic
limbs_id = SPECIES_SYNTH
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT

View File

@@ -1,145 +0,0 @@
/datum/species/angel
name = "Angel"
id = SPECIES_ANGEL
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel")
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
no_equip = list(SLOT_BACK)
blacklisted = 1
limbs_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
species_category = SPECIES_CATEGORY_BASIC //they're a kind of human
var/datum/action/innate/flight/fly
/datum/species/angel/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
..()
if(H.dna && H.dna.species && (H.dna.features["wings"] != "Angel"))
if(!H.dna.species.mutant_bodyparts["wings"])
H.dna.species.mutant_bodyparts["wings"] = "Angel"
H.dna.features["wings"] = "Angel"
H.update_body()
if(ishuman(H) && !fly)
fly = new
fly.Grant(H)
ADD_TRAIT(H, TRAIT_HOLY, SPECIES_TRAIT)
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
if(fly)
fly.Remove(H)
if(H.movement_type & FLYING)
H.setMovetype(H.movement_type & ~FLYING)
ToggleFlight(H,0)
if(H.dna && H.dna.species && (H.dna.features["wings"] == "Angel"))
if(H.dna.species.mutant_bodyparts["wings"])
H.dna.species.mutant_bodyparts -= "wings"
H.dna.features["wings"] = "None"
H.update_body()
REMOVE_TRAIT(H, TRAIT_HOLY, SPECIES_TRAIT)
..()
/datum/species/angel/spec_life(mob/living/carbon/human/H)
HandleFlight(H)
/datum/species/angel/proc/HandleFlight(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
if(!CanFly(H))
ToggleFlight(H,0)
return 0
return 1
else
return 0
/datum/species/angel/proc/CanFly(mob/living/carbon/human/H)
if(!CHECK_MOBILITY(H, MOBILITY_MOVE))
return FALSE
if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too
to_chat(H, "Your suit blocks your wings from extending!")
return FALSE
var/turf/T = get_turf(H)
if(!T)
return FALSE
var/datum/gas_mixture/environment = T.return_air()
if(environment && !(environment.return_pressure() > 30))
to_chat(H, "<span class='warning'>The atmosphere is too thin for you to fly!</span>")
return FALSE
return TRUE
/datum/action/innate/flight
name = "Toggle Flight"
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "flight"
/datum/action/innate/flight/Activate()
var/mob/living/carbon/human/H = owner
var/datum/species/angel/A = H.dna.species
if(A.CanFly(H))
if(H.movement_type & FLYING)
to_chat(H, "<span class='notice'>You settle gently back onto the ground...</span>")
A.ToggleFlight(H,0)
H.update_mobility()
else
to_chat(H, "<span class='notice'>You beat your wings and begin to hover gently above the ground...</span>")
H.set_resting(FALSE, TRUE)
A.ToggleFlight(H,1)
H.update_mobility()
/datum/species/angel/proc/flyslip(mob/living/carbon/human/H)
var/obj/buckled_obj
if(H.buckled)
buckled_obj = H.buckled
to_chat(H, "<span class='notice'>Your wings spazz out and launch you!</span>")
playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3)
for(var/obj/item/I in H.held_items)
H.accident(I)
var/olddir = H.dir
H.stop_pulling()
if(buckled_obj)
buckled_obj.unbuckle_mob(H)
step(buckled_obj, olddir)
else
for(var/i=1, i<5, i++)
spawn (i)
step(H, olddir)
H.spin(1,1)
return 1
/datum/species/angel/spec_stun(mob/living/carbon/human/H,amount)
if(H.movement_type & FLYING)
ToggleFlight(H,0)
flyslip(H)
. = ..()
/datum/species/angel/negates_gravity(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
return 1
/datum/species/angel/space_move(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
return 1
/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
if(flight && CanFly(H))
stunmod = 2
speedmod = -0.1
H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
H.pass_flags |= PASSTABLE
H.OpenWings()
else
stunmod = 1
speedmod = 0
H.setMovetype(H.movement_type & ~FLYING)
override_float = FALSE
H.pass_flags &= ~PASSTABLE
H.CloseWings()
update_species_slowdown(H)

View File

@@ -24,11 +24,18 @@
id = SPECIES_MAMMAL_SYNTHETIC
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE,WINGCOLOR,HORNCOLOR)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM, TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_AUXILIARY_LUNGS)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID|MOB_BEAST
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
coldmod = 0.5
heatmod = 1.2
cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas
blacklisted_quirks = list(/datum/quirk/coldblooded)
balance_point_values = TRUE
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
@@ -47,5 +54,8 @@
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
exotic_bloodtype = "S"
exotic_blood_color = BLOOD_COLOR_OIL
allowed_limb_ids = list("mammal","aquatic","avian", "human")
species_category = "robot"
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT

View File

@@ -21,6 +21,7 @@
var/web_cooldown = 200
var/web_ready = TRUE
var/spinner_rate = 25
wings_icons = SPECIES_WINGS_MOTH //Arachnids' phylum is arthropods, which include butterflies. Might as well hit them with moth wings.
/datum/species/arachnid/random_name(gender,unique,lastname)
if(unique)

View File

@@ -19,6 +19,7 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
species_category = SPECIES_CATEGORY_INSECT
wings_icons = SPECIES_WINGS_INSECT
allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale")

View File

@@ -19,3 +19,4 @@
sexes = 0
gib_types = /obj/effect/gibspawner/robot
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT

View File

@@ -16,6 +16,7 @@
has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head.
species_category = SPECIES_CATEGORY_UNDEAD
var/pumpkin = FALSE
wings_icons = SPECIES_WINGS_SKELETAL //seems suitable for an undead.
var/obj/item/dullahan_relay/myhead

View File

@@ -13,6 +13,7 @@
exotic_bloodtype = "BUG"
exotic_blood_color = BLOOD_COLOR_BUG
species_category = SPECIES_CATEGORY_INSECT
wings_icons = SPECIES_WINGS_INSECT
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(istype(chem, /datum/reagent/toxin/pestkiller))

View File

@@ -5,14 +5,20 @@
default_color = "00FF00"
blacklisted = 0
sexes = 0
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM, TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_AUXILIARY_LUNGS)
species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR,ROBOTIC_LIMBS)
hair_alpha = 210
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
mutant_bodyparts = list("ipc_screen" = "Blank", "deco_wings" = "None", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
coldmod = 0.5
heatmod = 1.2
cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas
blacklisted_quirks = list(/datum/quirk/coldblooded)
balance_point_values = TRUE
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
@@ -26,9 +32,10 @@
//special cybernetic organ for getting power from apcs
mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
exotic_bloodtype = "HF"
exotic_bloodtype = "S"
exotic_blood_color = BLOOD_COLOR_OIL
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT
var/datum/action/innate/monitor_change/screen

View File

@@ -29,6 +29,7 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
species_category = SPECIES_CATEGORY_JELLY
wings_icons = SPECIES_WINGS_JELLY
ass_image = 'icons/ass/assslime.png'
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
@@ -69,6 +70,7 @@
to_chat(H, "<span class='danger'>You feel drained!</span>")
if(H.blood_volume < (BLOOD_VOLUME_BAD*H.blood_ratio))
Cannibalize_Body(H)
..()
/datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H)
var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs()
@@ -404,7 +406,7 @@
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "legs" = "Plantigrade")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade")
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 160 //a notch brighter so it blends better.

View File

@@ -29,6 +29,7 @@
tail_type = "tail_lizard"
wagging_type = "waggingtail_lizard"
species_category = SPECIES_CATEGORY_LIZARD
wings_icons = SPECIES_WINGS_DRAGON
ass_image = 'icons/ass/asslizard.png'

View File

@@ -23,6 +23,7 @@
outfit_important_for_life = /datum/outfit/plasmaman
species_category = SPECIES_CATEGORY_SKELETON
wings_icons = SPECIES_WINGS_SKELETAL
ass_image = 'icons/ass/assplasma.png'

View File

@@ -16,6 +16,7 @@
mutanteyes = /obj/item/organ/eyes/night_vision
species_category = SPECIES_CATEGORY_SHADOW
wings_icons = SPECIES_WINGS_SKELETAL //not sure what's more spooky for these guys - skeleton or dragon?
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()

View File

@@ -16,6 +16,7 @@
burnmod = 1.25
species_category = SPECIES_CATEGORY_SKELETON //they have their own category that's disassociated from undead, paired with plasmapeople
wings_icons = SPECIES_WINGS_SKELETAL
/datum/species/skeleton/New()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!

View File

@@ -4,11 +4,18 @@
say_mod = "beeps"
default_color = "00FF00"
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM, TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_AUXILIARY_LUNGS)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
coldmod = 0.5
heatmod = 1.2
cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas
blacklisted_quirks = list(/datum/quirk/coldblooded)
balance_point_values = TRUE
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
@@ -28,3 +35,4 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT

View File

@@ -18,6 +18,7 @@
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
species_language_holder = /datum/language_holder/synthetic
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT
/datum/species/synth/military
name = "Military Synth"

View File

@@ -15,8 +15,10 @@
skinned_type = /obj/item/stack/sheet/animalhide/human
var/info_text = "You are a <span class='danger'>Vampire</span>. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
species_category = SPECIES_CATEGORY_UNDEAD
wings_icons = SPECIES_WINGS_DRAGON //closest to "bat" wings.
var/batform_enabled = TRUE
/datum/species/vampire/roundstart
id = SPECIES_VAMPIRE_WEAK
batform_enabled = FALSE

View File

@@ -17,3 +17,4 @@
disliked_food = JUNKFOOD
liked_food = GROSS | MEAT
species_category = SPECIES_CATEGORY_ALIEN
wings_icons = SPECIES_WINGS_DRAGON //most depictions of xenomorphs with wings are closest to this.

View File

@@ -16,6 +16,7 @@
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
species_category = SPECIES_CATEGORY_UNDEAD
wings_icons = SPECIES_WINGS_SKELETAL //eh.
/datum/species/zombie/notspaceproof
id = "notspaceproofzombie"

View File

@@ -161,55 +161,58 @@
return index && hand_bodyparts[index]
/**
* Proc called when giving an item to another player
* Proc called when offering an item to another player
*
* This handles creating an alert and adding an overlay to it
*/
/mob/living/carbon/proc/give(target)
var/obj/item/receiving = get_active_held_item()
if(!receiving)
var/obj/item/offered_item = get_active_held_item()
if(!offered_item)
to_chat(src, "<span class='warning'>You're not holding anything to give!</span>")
return
visible_message("<span class='notice'>[src] is offering [receiving]</span>", \
"<span class='notice'>You offer [receiving]</span>", null, 2)
var/mob/living/carbon/targets = list()
if(!target)
for(var/mob/living/carbon/C in orange(1, src))
if(!CanReach(C))
return
targets += C
else
targets += target
if(!targets)
if(IS_DEAD_OR_INCAP(src))
to_chat(src, span_warning("You're unable to offer anything in your current state!"))
return
for(var/mob/living/carbon/C in targets)
var/atom/movable/screen/alert/give/G = C.throw_alert("[src]", /atom/movable/screen/alert/give)
if(!G)
return
G.setup(C, src, receiving)
if(has_status_effect(STATUS_EFFECT_OFFERING))
to_chat(src, span_warning("You're already offering up something!"))
return
if(offered_item.on_offered(src)) // see if the item interrupts with its own behavior
return
visible_message(span_notice("[src] is offering [offered_item]."), \
span_notice("You offer [offered_item]."), null, 2)
apply_status_effect(STATUS_EFFECT_OFFERING, offered_item)
/**
* Proc called when the player clicks the give alert
*
* Handles checking if the player taking the item has open slots and is in range of the giver
* Handles checking if the player taking the item has open slots and is in range of the offerer
* Also deals with the actual transferring of the item to the players hands
* Arguments:
* * giver - The person giving the original item
* * I - The item being given by the giver
* * offerer - The person giving the original item
* * I - The item being given by the offerer
*/
/mob/living/carbon/proc/take(mob/living/carbon/giver, obj/item/I)
clear_alert("[giver]")
if(get_dist(src, giver) > 1)
to_chat(src, "<span class='warning'>[giver] is out of range! </span>")
/mob/living/carbon/proc/take(mob/living/carbon/offerer, obj/item/I)
clear_alert("[offerer]")
if(get_dist(src, offerer) > 1)
to_chat(src, span_warning("[offerer] is out of range!"))
return
if(!I || giver.get_active_held_item() != I)
to_chat(src, "<span class='warning'>[giver] is no longer holding the item they were offering! </span>")
if(!I || offerer.get_active_held_item() != I)
to_chat(src, span_warning("[offerer] is no longer holding the item they were offering!"))
return
if(!get_empty_held_indexes())
to_chat(src, "<span class='warning'>You have no empty hands!</span>")
return
if(!giver.temporarilyRemoveItemFromInventory(I))
visible_message("<span class='notice'>[src] tries to hand over [I] but it's stuck to them....", \
if(I.on_offer_taken(offerer, src)) // see if the item has special behavior for being accepted
return
if(!offerer.temporarilyRemoveItemFromInventory(I))
visible_message("<span class='notice'>[offerer] tries to hand over [I] but it's stuck to them....", \
"<span class'notice'> You make a fool of yourself trying to give away an item stuck to your hands")
return
visible_message(span_notice("[src] takes [I] from [offerer]"), \
span_notice("You take [I] from [offerer]"))
put_in_hands(I)

View File

@@ -573,9 +573,6 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
if(druggy)
adjust_drugginess(-1)
if(drunkenness)
drunkenness = max(drunkenness-1,0)
if(silent)
silent = max(silent-1, 0)
@@ -583,7 +580,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
handle_hallucinations()
if(drunkenness)
drunkenness = max(drunkenness - (drunkenness * 0.04), 0)
drunkenness *= 0.96
if(drunkenness >= 6)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk)
if(prob(25))
@@ -598,6 +595,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "drunk")
clear_alert("drunk")
sound_environment_override = SOUND_ENVIRONMENT_NONE
drunkenness = max(drunkenness - 0.2, 0)
if(mind && (mind.assigned_role == "Scientist" || mind.assigned_role == "Research Director"))
if(SSresearch.science_tech)
@@ -661,7 +659,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//used in human and monkey handle_environment()
/mob/living/carbon/proc/natural_bodytemperature_stabilization()
if (HAS_TRAIT(src, TRAIT_COLDBLOODED))
if(HAS_TRAIT(src, TRAIT_COLDBLOODED) || HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
return 0 //Return 0 as your natural temperature. Species proc handle_environment() will adjust your temperature based on this.
var/body_temperature_difference = BODYTEMP_NORMAL - bodytemperature
@@ -674,6 +672,52 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
return min(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, max(body_temperature_difference, -BODYTEMP_AUTORECOVERY_MINIMUM/4))
if(BODYTEMP_HEAT_DAMAGE_LIMIT to INFINITY)
return min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers
/mob/living/carbon/proc/get_cooling_efficiency()
if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
return 1
var/integration_bonus = min(blood_volume * SYNTH_INTEGRATION_COOLANT_CAP, integrating_blood * SYNTH_INTEGRATION_COOLANT_PENALTY) //Integration blood somewhat helps, though only at 40% impact and to a cap of 25% of current blood level.
var/blood_effective_volume = blood_volume + integration_bonus
var/coolant_efficiency = min(blood_effective_volume / BLOOD_VOLUME_SAFE, 1) //Low coolant is only a negative, adding more than needed will not help you.
var/environment_efficiency = get_environment_cooling_efficiency()
return min(coolant_efficiency * environment_efficiency, SYNTH_MAX_COOLING_EFFICIENCY)
/mob/living/carbon/proc/get_environment_cooling_efficiency()
var/suitlink = check_suitlinking()
if(suitlink)
return suitlink //If you are wearing full EVA or lavaland hazard gear (on lavaland), assume it has been made to accomodate your cooling needs.
var/datum/gas_mixture/environment = loc.return_air()
if(!environment)
return 0
var/pressure = environment.return_pressure()
var/heat = environment.return_temperature()
var/heat_efficiency = clamp(1 + ((bodytemperature - heat) * SYNTH_HEAT_EFFICIENCY_COEFF), 0, SYNTH_SINGLE_INFLUENCE_COOLING_EFFECT_CAP)
var/pressure_efficiency = clamp(pressure / ONE_ATMOSPHERE, 0, SYNTH_SINGLE_INFLUENCE_COOLING_EFFECT_CAP)
if(HAS_TRAIT(src, TRAIT_LOWPRESSURECOOLING))
pressure_efficiency = max(pressure_efficiency, 1) //Space adaptation nulls drawbacks of low-pressure cooling.
var/total_environment_efficiency = min(heat_efficiency * pressure_efficiency, SYNTH_TOTAL_ENVIRONMENT_EFFECT_CAP) //At best, you can get 200% total
return total_environment_efficiency
/mob/living/carbon/proc/check_suitlinking()
var/suit_item = get_item_by_slot(SLOT_WEAR_SUIT)
var/head_item = get_item_by_slot(SLOT_HEAD)
var/turf/T = get_turf(src)
if(istype(head_item, /obj/item/clothing/head/helmet/space) && istype(suit_item, /obj/item/clothing/suit/space))
return 1
if(T && is_mining_level(T.z) && istype(head_item, /obj/item/clothing/head/hooded/explorer) && istype(suit_item, /obj/item/clothing/suit/hooded/explorer))
return 1
return 0
/////////
//LIVER//
/////////

View File

@@ -16,6 +16,17 @@
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
GLOBAL_LIST_INIT(strippable_monkey_items, create_strippable_list(list(
/datum/strippable_item/mob_item_slot/head,
/datum/strippable_item/mob_item_slot/back,
/datum/strippable_item/mob_item_slot/mask,
/datum/strippable_item/mob_item_slot/neck,
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/lay_down)
@@ -47,6 +58,7 @@
. = ..()
AddElement(/datum/element/mob_holder, worn_state = "monkey", inv_slots = ITEM_SLOT_HEAD)
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_BAREFOOT, 1, 2)
AddElement(/datum/element/strippable, GLOB.strippable_monkey_items)
/mob/living/carbon/monkey/Destroy()

View File

@@ -5,7 +5,7 @@
/mob/living/carbon/adjust_drugginess(amount)
druggy = max(druggy+amount, 0)
if(druggy)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high)
throw_alert("high", /atom/movable/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
@@ -18,7 +18,7 @@
/mob/living/carbon/set_drugginess(amount)
druggy = max(amount, 0)
if(druggy)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high)
throw_alert("high", /atom/movable/screen/alert/high)
else
clear_fullscreen("high")

View File

@@ -579,7 +579,7 @@
UNLINT(livingdoll.filters += filter(type="alpha", icon = mob_mask))
livingdoll.filters += filter(type="drop_shadow", size = -1)
if(severity > 0)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
else
clear_fullscreen("brute")
@@ -935,13 +935,6 @@
what.forceMove(drop_location())
log_combat(src, who, "stripped [what] off")
if(Adjacent(who)) //update inventory window
who.show_inv(src)
else
src << browse(null,"window=mob[REF(who)]")
who.update_equipment_speed_mods() // Updates speed in case stripped speed affecting item
// The src mob is trying to place an item on someone
// 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)

View File

@@ -539,7 +539,7 @@
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
if((override_protection || get_eye_protection() < intensity) && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND))))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)

View File

@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
if(!eavesdrop_range && say_test(message) == "2") // Yell hook
if(client && !eavesdrop_range && say_test(message) == "2") // Yell hook
process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
//speech bubble

View File

@@ -84,7 +84,6 @@
if(ai.client && !ai.multicam_on)
ai.client.eye = src
update_ai_detect_hud()
update_parallax_contents()
//Holopad
if(istype(ai.current, /obj/machinery/holopad))
var/obj/machinery/holopad/H = ai.current

View File

@@ -4,7 +4,7 @@
stat = DEAD
update_mobility()
update_sight()
clear_fullscreens()
wipe_fullscreens()
//New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here.
remove_from_alive_mob_list()

View File

@@ -144,6 +144,6 @@
P.on_hit(src, 0, def_zone)
return BULLET_ACT_HIT
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static)
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash/static)
if(affect_silicon)
return ..()

View File

@@ -292,18 +292,21 @@
/mob/living/simple_animal/bot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HELP)
interact(H)
ui_interact(H)
else
return ..()
/mob/living/simple_animal/bot/attack_ai(mob/user)
if(!topic_denied(user))
interact(user)
ui_interact(user)
else
to_chat(user, "<span class='warning'>[src]'s interface is not responding!</span>")
/mob/living/simple_animal/bot/interact(mob/user)
show_controls(user)
/mob/living/simple_animal/bot/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SimpleBot", name)
ui.open()
/mob/living/simple_animal/bot/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_SCREWDRIVER)
@@ -795,56 +798,48 @@ Pass a positive integer as an argument to override a bot's default speed.
else // no path, so calculate new one
calc_summon_path()
/mob/living/simple_animal/bot/Bump(M as mob|obj) //Leave no door unopened!
// Variables sent to TGUI
/mob/living/simple_animal/bot/ui_data(mob/user)
var/list/data = list()
data["can_hack"] = (issilicon(user) || IsAdminGhost(user))
data["custom_controls"] = list()
data["emagged"] = emagged
data["locked"] = locked
data["pai"] = list()
data["settings"] = list()
if(!locked || issilicon(user) || IsAdminGhost(user))
data["pai"]["allow_pai"] = allow_pai
data["pai"]["card_inserted"] = paicard
data["settings"]["airplane_mode"] = remote_disabled
data["settings"]["maintenance_lock"] = !open
data["settings"]["power"] = on
data["settings"]["patrol_station"] = auto_patrol
return data
// Actions received from TGUI
/mob/living/simple_animal/bot/ui_act(action, params)
. = ..()
if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(access_card)))
var/obj/machinery/door/D = M
if(D.check_access(access_card))
D.open()
frustration = 0
/mob/living/simple_animal/bot/proc/show_controls(mob/M)
users |= M
var/dat = ""
dat = get_controls(M)
var/datum/browser/popup = new(M,window_id,window_name,350,600)
popup.set_content(dat)
popup.open(use_onclose = 0)
onclose(M,window_id,ref=src)
return
/mob/living/simple_animal/bot/proc/update_controls()
for(var/mob/M in users)
show_controls(M)
/mob/living/simple_animal/bot/proc/get_controls(mob/M)
return "PROTOBOT - NOT FOR USE"
/mob/living/simple_animal/bot/Topic(href, href_list)
//No ..() to prevent strip panel showing up - Todo: make that saner
if(href_list["close"])// HUE HUE
if(usr in users)
users.Remove(usr)
return TRUE
if(topic_denied(usr))
to_chat(usr, "<span class='warning'>[src]'s interface is not responding!</span>")
return TRUE
add_fingerprint(usr)
if((href_list["power"]) && (bot_core.allowed(usr) || !locked))
if(on)
turn_off()
else
turn_on()
switch(href_list["operation"])
if(.)
return
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
to_chat(usr, span_warning("Access denied."))
return
if(action == "lock")
locked = !locked
if(locked && !(issilicon(usr) || IsAdminGhost(usr)))
return
switch(action)
if("power")
on = !on
update_appearance()
if("maintenance")
open = !open
if("patrol")
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
auto_patrol = !auto_patrol
bot_reset()
if("remote")
if("airplane")
remote_disabled = !remote_disabled
if("hack")
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr))
@@ -865,11 +860,11 @@ Pass a positive integer as an argument to override a bot's default speed.
hacked = FALSE
to_chat(usr, "<span class='notice'>[text_dehack]</span>")
bot_reset()
if("ejectpai")
if("eject_pai")
if(paicard && (!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
to_chat(usr, "<span class='notice'>You eject [paicard] from [bot_name]</span>")
ejectpai(usr)
update_controls()
return
/mob/living/simple_animal/bot/update_icon_state()
icon_state = "[initial(icon_state)][on]"
@@ -897,33 +892,6 @@ Pass a positive integer as an argument to override a bot's default speed.
return TRUE
return FALSE
/mob/living/simple_animal/bot/proc/hack(mob/user)
var/hack
if(hasSiliconAccessInArea(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot.
hack += "[emagged == 2 ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]<BR>"
hack += "Harm Prevention Safety System: <A href='?src=[REF(src)];operation=hack'>[emagged ? "<span class='bad'>DANGER</span>" : "Engaged"]</A><BR>"
else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control.
hack += "Remote network control radio: <A href='?src=[REF(src)];operation=remote'>[remote_disabled ? "Disconnected" : "Connected"]</A><BR>"
return hack
/mob/living/simple_animal/bot/proc/showpai(mob/user)
var/eject = ""
if((!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
if(paicard || allow_pai)
eject += "Personality card status: "
if(paicard)
if(client)
eject += "<A href='?src=[REF(src)];operation=ejectpai'>Active</A>"
else
eject += "<A href='?src=[REF(src)];operation=ejectpai'>Inactive</A>"
else if(!allow_pai || key)
eject += "Unavailable"
else
eject += "Not inserted"
eject += "<BR>"
eject += "<BR>"
return eject
/mob/living/simple_animal/bot/proc/insertpai(mob/user, obj/item/paicard/card)
if(paicard)
to_chat(user, "<span class='warning'>A [paicard] is already inserted!</span>")

View File

@@ -443,37 +443,33 @@
/obj/machinery/bot_core/cleanbot
req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS)
/mob/living/simple_animal/bot/cleanbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"})
if(!locked || issilicon(user)|| IsAdminGhost(user))
dat += "<BR>Clean Blood: <A href='?src=[REF(src)];operation=blood'>[blood ? "Yes" : "No"]</A>"
dat += "<BR>Clean Trash: <A href='?src=[REF(src)];operation=trash'>[trash ? "Yes" : "No"]</A>"
dat += "<BR>Clean Graffiti: <A href='?src=[REF(src)];operation=drawn'>[drawn ? "Yes" : "No"]</A>"
dat += "<BR>Exterminate Pests: <A href='?src=[REF(src)];operation=pests'>[pests ? "Yes" : "No"]</A>"
dat += "<BR><BR>Patrol Station: <A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A>"
return dat
// Variables sent to TGUI
/mob/living/simple_animal/bot/cleanbot/ui_data(mob/user)
var/list/data = ..()
/mob/living/simple_animal/bot/cleanbot/Topic(href, href_list)
if(..())
return 1
if(href_list["operation"])
switch(href_list["operation"])
if("blood")
blood = !blood
if("pests")
pests = !pests
if("trash")
trash = !trash
if("drawn")
drawn = !drawn
get_targets()
update_controls()
if(!locked || issilicon(user)|| IsAdminGhost(user))
data["custom_controls"]["clean_blood"] = blood
data["custom_controls"]["clean_trash"] = trash
data["custom_controls"]["clean_graffiti"] = drawn
data["custom_controls"]["pest_control"] = pests
return data
// Actions received from TGUI
/mob/living/simple_animal/bot/cleanbot/ui_act(action, params)
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(action)
if("clean_blood")
blood = !blood
if("pest_control")
pests = !pests
if("clean_trash")
trash = !trash
if("clean_graffiti")
drawn = !drawn
get_targets()
return
/obj/machinery/bot_core/cleanbot/medbay
req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS, ACCESS_MEDICAL)

View File

@@ -96,64 +96,45 @@
text_dehack = "You restore [name]'s combat inhibitor."
text_dehack_fail = "[name] ignores your attempts to restrict him!"
/mob/living/simple_animal/bot/ed209/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Security Unit v2.6 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]<BR>"},
"<A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A>" )
// Variables sent to TGUI
/mob/living/simple_animal/bot/ed209/ui_data(mob/user)
var/list/data = ..()
if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user))
if(!lasercolor)
dat += text({"<BR>
Arrest Unidentifiable Persons: []<BR>
Arrest for Unauthorized Weapons: []<BR>
Arrest for Warrant: []<BR>
<BR>
Operating Mode: []<BR>
Report Arrests[]<BR>
Auto Patrol[]"},
data["custom_controls"]["check_id"] = idcheck
data["custom_controls"]["check_weapons"] = weaponscheck
data["custom_controls"]["check_warrants"] = check_records
data["custom_controls"]["handcuff_targets"] = !arrest_type
data["custom_controls"]["arrest_alert"] = declare_arrests
return data
"<A href='?src=[REF(src)];operation=idcheck'>[idcheck ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=weaponscheck'>[weaponscheck ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=ignorerec'>[check_records ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=[REF(src)];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/ed209/Topic(href, href_list)
// Actions received from TGUI
/mob/living/simple_animal/bot/ed209/ui_act(action, params)
if(lasercolor && ishuman(usr))
var/mob/living/carbon/human/H = usr
if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it
return
else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag)))
return
if(..())
return 1
switch(lasercolor) //Opposing team cannot operate it
if("b")
if(istype(H.wear_suit, /obj/item/clothing/suit/redtag))
return TRUE
if("r")
if(istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
return TRUE
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(href_list["operation"])
if("idcheck")
switch(action)
if("check_id")
idcheck = !idcheck
update_controls()
if("weaponscheck")
if("check_weapons")
weaponscheck = !weaponscheck
update_controls()
if("ignorerec")
if("check_warrants")
check_records = !check_records
update_controls()
if("switchmode")
if("handcuff_targets")
arrest_type = !arrest_type
update_controls()
if("declarearrests")
if("arrest_alert")
declare_arrests = !declare_arrests
update_controls()
return
/mob/living/simple_animal/bot/ed209/proc/judgement_criteria()
var/final = FALSE

View File

@@ -102,23 +102,6 @@
text_dehack = "You detect errors in [name] and reset his programming."
text_dehack_fail = "[name] is not responding to reset commands!"
/mob/living/simple_animal/bot/firebot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<TT><B>Mobile Fire Extinguisher v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
dat += "Extinguish Fires: <A href='?src=[REF(src)];operation=extinguish_fires'>[extinguish_fires ? "Yes" : "No"]</A><BR>"
dat += "Extinguish People: <A href='?src=[REF(src)];operation=extinguish_people'>[extinguish_people ? "Yes" : "No"]</A><BR>"
dat += "Patrol Station: <A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A><BR>"
dat += "Stationary Mode: <a href='?src=[REF(src)];operation=stationary_mode'>[stationary_mode ? "Yes" : "No"]</a><br>"
return dat
/mob/living/simple_animal/bot/firebot/emag_act(mob/user)
. = ..()
if(emagged == 1)
@@ -138,20 +121,29 @@
internal_ext.max_water = INFINITY
internal_ext.refill()
/mob/living/simple_animal/bot/firebot/Topic(href, href_list)
if(..())
return TRUE
// Variables sent to TGUI
/mob/living/simple_animal/bot/firebot/ui_data(mob/user)
var/list/data = ..()
if(!locked || issilicon(user) || IsAdminGhost(user))
data["custom_controls"]["extinguish_fires"] = extinguish_fires
data["custom_controls"]["extinguish_people"] = extinguish_people
data["custom_controls"]["stationary_mode"] = stationary_mode
return data
switch(href_list["operation"])
// Actions received from TGUI
/mob/living/simple_animal/bot/firebot/ui_act(action, params)
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(action)
if("extinguish_fires")
extinguish_fires = !extinguish_fires
if("extinguish_people")
extinguish_people = !extinguish_people
if("stationary_mode")
stationary_mode = !stationary_mode
update_controls()
update_icon()
update_appearance()
return
/mob/living/simple_animal/bot/firebot/proc/is_burning(atom/target)
if(ismob(target))

View File

@@ -71,36 +71,6 @@
text_dehack = "You detect errors in [name] and reset his programming."
text_dehack_fail = "[name] is not responding to reset commands!"
/mob/living/simple_animal/bot/floorbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<TT><B>Floor Repairer Controls v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
dat += "Special tiles: "
if(specialtiles)
dat += "<A href='?src=[REF(src)];operation=eject'>Loaded \[[specialtiles]/[maxtiles]\]</a><BR>"
else
dat += "None Loaded<BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
dat += "Add tiles to new hull plating: <A href='?src=[REF(src)];operation=autotile'>[autotile ? "Yes" : "No"]</A><BR>"
dat += "Place floor tiles: <A href='?src=[REF(src)];operation=place'>[placetiles ? "Yes" : "No"]</A><BR>"
dat += "Replace existing floor tiles with custom tiles: <A href='?src=[REF(src)];operation=replace'>[replacetiles ? "Yes" : "No"]</A><BR>"
dat += "Repair damaged tiles and platings: <A href='?src=[REF(src)];operation=fix'>[fixfloors ? "Yes" : "No"]</A><BR>"
dat += "Traction Magnets: <A href='?src=[REF(src)];operation=anchor'>[anchored ? "Engaged" : "Disengaged"]</A><BR>"
dat += "Patrol Station: <A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A><BR>"
var/bmode
if(targetdirection)
bmode = dir2text(targetdirection)
else
bmode = "disabled"
dat += "Line Mode : <A href='?src=[REF(src)];operation=linemode'>[bmode]</A><BR>"
return dat
/mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params)
if(istype(W, /obj/item/stack/tile/plasteel))
to_chat(user, "<span class='notice'>The floorbot can produce normal tiles itself.</span>")
@@ -161,26 +131,44 @@
if(user)
to_chat(user, "<span class='danger'>[src] buzzes and beeps.</span>")
/mob/living/simple_animal/bot/floorbot/Topic(href, href_list)
if(..())
return 1
// Variables sent to TGUI
/mob/living/simple_animal/bot/floorbot/ui_data(mob/user)
var/list/data = ..()
if(!locked || issilicon(user) || IsAdminGhost(user))
data["custom_controls"]["tile_hull"] = autotile
data["custom_controls"]["place_tiles"] = placetiles
data["custom_controls"]["place_custom"] = replacetiles
data["custom_controls"]["repair_damage"] = fixfloors
data["custom_controls"]["traction_magnets"] = anchored
data["custom_controls"]["tile_stack"] = 0
data["custom_controls"]["line_mode"] = FALSE
if(specialtiles)
data["custom_controls"]["tile_stack"] = specialtiles
if(targetdirection)
data["custom_controls"]["line_mode"] = dir2text(targetdirection)
return data
switch(href_list["operation"])
if("replace")
// Actions received from TGUI
/mob/living/simple_animal/bot/floorbot/ui_act(action, params)
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(action)
if("place_custom")
replacetiles = !replacetiles
if("place")
if("place_tiles")
placetiles = !placetiles
if("fix")
if("repair_damage")
fixfloors = !fixfloors
if("autotile")
if("tile_hull")
autotile = !autotile
if("anchor")
if("traction_magnets")
anchored = !anchored
if("eject")
if("eject_tiles")
if(specialtiles && tiletype != null)
empty_tiles()
if("linemode")
if("line_mode")
var/setdir = input("Select construction direction:") as null|anything in list("north","east","south","west","disable")
switch(setdir)
if("north")
@@ -193,7 +181,7 @@
targetdirection = 8
if("disable")
targetdirection = null
update_controls()
return
/mob/living/simple_animal/bot/floorbot/proc/empty_tiles()
new tiletype(drop_location(), specialtiles)

View File

@@ -78,24 +78,6 @@
text_dehack = "You reboot [name] and restore the sound control system."
text_dehack_fail = "[name] refuses to accept your authority!"
/mob/living/simple_animal/bot/honkbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Honkomatic Bike Horn Unit v1.0.7 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
"<A href='?src=[REF(src)];power=[TRUE]'>[on ? "On" : "Off"]</A>" )
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
dat += text({"<BR> Auto Patrol: []"},
"<A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/honkbot/proc/judgement_criteria()
var/final = NONE
if(check_records)

View File

@@ -155,87 +155,63 @@
/mob/living/simple_animal/bot/medbot/attack_paw(mob/user)
return attack_hand(user)
/mob/living/simple_animal/bot/medbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<TT><B>Medical Unit Controls v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
// Variables sent to TGUI
/mob/living/simple_animal/bot/medbot/ui_data(mob/user)
var/list/data = ..()
if(reagent_glass)
dat += "<A href='?src=[REF(src)];eject=1'>Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]</a>"
else
dat += "None Loaded"
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
data["custom_controls"]["beaker"] = reagent_glass
data["custom_contrlos"]["reagents"] = "[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]"
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
dat += "<TT>Healing Threshold: "
dat += "<a href='?src=[REF(src)];adj_threshold=-10'>--</a> "
dat += "<a href='?src=[REF(src)];adj_threshold=-5'>-</a> "
dat += "[heal_threshold] "
dat += "<a href='?src=[REF(src)];adj_threshold=5'>+</a> "
dat += "<a href='?src=[REF(src)];adj_threshold=10'>++</a>"
dat += "</TT><br>"
data["custom_controls"]["injection_amount"] = injection_amount
data["custom_controls"]["use_beaker"] = use_beaker
data["custom_controls"]["treat_virus"] = treat_virus
data["custom_controls"]["heal_threshold"] = heal_threshold
data["custom_controls"]["speaker"] = !shut_up
data["custom_controls"]["crit_alerts"] = declare_crit
data["custom_controls"]["stationary_mode"] = stationary_mode
return data
dat += "<TT>Injection Level: "
dat += "<a href='?src=[REF(src)];adj_inject=-5'>-</a> "
dat += "[injection_amount] "
dat += "<a href='?src=[REF(src)];adj_inject=5'>+</a> "
dat += "</TT><br>"
// Actions received from TGUI
/mob/living/simple_animal/bot/medbot/ui_act(action, params)
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(action)
if("heal_threshold")
var/adjust_num = round(text2num(params["threshold"]))
heal_threshold = adjust_num
if(heal_threshold < 5)
heal_threshold = 5
if(heal_threshold > 75)
heal_threshold = 75
dat += "Reagent Source: "
dat += "<a href='?src=[REF(src)];use_beaker=1'>[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]</a><br>"
if("injection_amount")
var/adjust_num = round(text2num(params["amount"]))
injection_amount = adjust_num
if(injection_amount < 1)
injection_amount = 1
if(injection_amount > 15)
injection_amount = 15
dat += "Treat Viral Infections: <a href='?src=[REF(src)];virus=1'>[treat_virus ? "Yes" : "No"]</a><br>"
dat += "The speaker switch is [shut_up ? "off" : "on"]. <a href='?src=[REF(src)];togglevoice=[1]'>Toggle</a><br>"
dat += "Critical Patient Alerts: <a href='?src=[REF(src)];critalerts=1'>[declare_crit ? "Yes" : "No"]</a><br>"
dat += "Patrol Station: <a href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</a><br>"
dat += "Stationary Mode: <a href='?src=[REF(src)];stationary=1'>[stationary_mode ? "Yes" : "No"]</a><br>"
if("use_beaker")
use_beaker = !use_beaker
return dat
if("eject")
if(!isnull(reagent_glass))
reagent_glass.forceMove(drop_location())
reagent_glass = null
/mob/living/simple_animal/bot/medbot/Topic(href, href_list)
if(..())
return 1
if("speaker")
shut_up = !shut_up
if("crit_alerts")
declare_crit = !declare_crit
if("stationary_mode")
stationary_mode = !stationary_mode
path = list()
update_appearance()
if(href_list["adj_threshold"])
var/adjust_num = text2num(href_list["adj_threshold"])
heal_threshold += adjust_num
if(heal_threshold < 5)
heal_threshold = 5
if(heal_threshold > 75)
heal_threshold = 75
else if(href_list["adj_inject"])
var/adjust_num = text2num(href_list["adj_inject"])
injection_amount += adjust_num
if(injection_amount < 5)
injection_amount = 5
if(injection_amount > 15)
injection_amount = 15
else if(href_list["use_beaker"])
use_beaker = !use_beaker
else if(href_list["eject"] && (!isnull(reagent_glass)))
reagent_glass.forceMove(drop_location())
reagent_glass = null
else if(href_list["togglevoice"])
shut_up = !shut_up
else if(href_list["critalerts"])
declare_crit = !declare_crit
else if(href_list["stationary"])
stationary_mode = !stationary_mode
path = list()
update_icon()
else if(href_list["virus"])
treat_virus = !treat_virus
update_controls()
if("virus")
treat_virus = !treat_virus
return
/mob/living/simple_animal/bot/medbot/attackby(obj/item/W as obj, mob/user as mob, params)
@@ -251,7 +227,6 @@
reagent_glass = W
to_chat(user, "<span class='notice'>You insert [W].</span>")
show_controls(user)
else if(istype(W, /obj/item/reagent_containers/syringe/piercing))
if(bot_core.allowed(user) && open && !(upgrades & UPGRADE_MEDICAL_PIERERCING))

View File

@@ -276,56 +276,6 @@
if("ejectpai")
ejectpairemote(user)
// TODO: remove this; PDAs currently depend on it
/mob/living/simple_animal/bot/mulebot/get_controls(mob/user)
var/ai = hasSiliconAccessInArea(user)
var/dat
dat += "<h3>Multiple Utility Load Effector Mk. V</h3>"
dat += "<b>ID:</b> [id]<BR>"
dat += "<b>Power:</b> [on ? "On" : "Off"]<BR>"
dat += "<h3>Status</h3>"
dat += "<div class='statusDisplay'>"
switch(mode)
if(BOT_IDLE)
dat += "<span class='good'>Ready</span>"
if(BOT_DELIVER)
dat += "<span class='good'>[mode_name[BOT_DELIVER]]</span>"
if(BOT_GO_HOME)
dat += "<span class='good'>[mode_name[BOT_GO_HOME]]</span>"
if(BOT_BLOCKED)
dat += "<span class='average'>[mode_name[BOT_BLOCKED]]</span>"
if(BOT_NAV,BOT_WAIT_FOR_NAV)
dat += "<span class='average'>[mode_name[BOT_NAV]]</span>"
if(BOT_NO_ROUTE)
dat += "<span class='bad'>[mode_name[BOT_NO_ROUTE]]</span>"
dat += "</div>"
dat += "<b>Current Load:</b> [load ? load.name : "<i>none</i>"]<BR>"
dat += "<b>Destination:</b> [!destination ? "<i>none</i>" : destination]<BR>"
dat += "<b>Power level:</b> [cell ? cell.percent() : 0]%"
if(locked && !ai && !IsAdminGhost(user))
dat += "&nbsp;<br /><div class='notice'>Controls are locked</div><A href='byond://?src=[REF(src)];op=unlock'>Unlock Controls</A>"
else
dat += "&nbsp;<br /><div class='notice'>Controls are unlocked</div><A href='byond://?src=[REF(src)];op=lock'>Lock Controls</A><BR><BR>"
dat += "<A href='byond://?src=[REF(src)];op=power'>Toggle Power</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=stop'>Stop</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=go'>Proceed</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=home'>Return to Home</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=destination'>Set Destination</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=setid'>Set Bot ID</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=sethome'>Set Home</A><BR>"
dat += "<A href='byond://?src=[REF(src)];op=autoret'>Toggle Auto Return Home</A> ([auto_return ? "On":"Off"])<BR>"
dat += "<A href='byond://?src=[REF(src)];op=autopick'>Toggle Auto Pickup Crate</A> ([auto_pickup ? "On":"Off"])<BR>"
dat += "<A href='byond://?src=[REF(src)];op=report'>Toggle Delivery Reporting</A> ([report_delivery ? "On" : "Off"])<BR>"
if(load)
dat += "<A href='byond://?src=[REF(src)];op=unload'>Unload Now</A><BR>"
dat += "<div class='notice'>The maintenance hatch is closed.</div>"
return dat
// returns true if the bot has power
/mob/living/simple_animal/bot/mulebot/proc/has_power()
return !open && cell && cell.charge > 0 && (!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2))

View File

@@ -209,57 +209,34 @@
text_dehack = "You reboot [name] and restore the target identification."
text_dehack_fail = "[name] refuses to accept your authority!"
/mob/living/simple_animal/bot/secbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Securitron v1.6 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
"<A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A>" )
// Variables sent to TGUI
/mob/living/simple_animal/bot/secbot/ui_data(mob/user)
var/list/data = ..()
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
dat += text({"<BR>
Arrest Unidentifiable Persons: []<BR>
Arrest for Unauthorized Weapons: []<BR>
Arrest for Warrant: []<BR>
Operating Mode: []<BR>
Report Arrests[]<BR>
Auto Patrol: []"},
data["custom_controls"]["check_id"] = idcheck
data["custom_controls"]["check_weapons"] = weaponscheck
data["custom_controls"]["check_warrants"] = check_records
data["custom_controls"]["handcuff_targets"] = !arrest_type
data["custom_controls"]["arrest_alert"] = declare_arrests
return data
"<A href='?src=[REF(src)];operation=idcheck'>[idcheck ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=weaponscheck'>[weaponscheck ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=ignorerec'>[check_records ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=[REF(src)];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/secbot/Topic(href, href_list)
if(..())
return 1
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
// Actions received from TGUI
/mob/living/simple_animal/bot/secbot/ui_act(action, params)
. = ..()
if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
return TRUE
switch(href_list["operation"])
if("idcheck")
switch(action)
if("check_id")
idcheck = !idcheck
update_controls()
if("weaponscheck")
if("check_weapons")
weaponscheck = !weaponscheck
update_controls()
if("ignorerec")
if("check_warrants")
check_records = !check_records
update_controls()
if("switchmode")
if("handcuff_targets")
arrest_type = !arrest_type
update_controls()
if("declarearrests")
if("arrest_alert")
declare_arrests = !declare_arrests
update_controls()
return
/mob/living/simple_animal/bot/secbot/proc/retaliate(mob/living/carbon/human/H)
var/judgement_criteria = judgement_criteria()

View File

@@ -24,6 +24,7 @@
. = ..()
AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
AddElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/strippable, GLOB.strippable_corgi_items)
//Corgis and pugs are now under one dog subtype
@@ -104,18 +105,175 @@
..(gibbed)
regenerate_icons()
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
/datum/strippable_item/corgi_head,
/datum/strippable_item/corgi_back,
/datum/strippable_item/corgi_collar,
/datum/strippable_item/corgi_id,
)))
/datum/strippable_item/corgi_head
key = STRIPPABLE_ITEM_HEAD
/datum/strippable_item/corgi_head/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
user.set_machine(src)
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
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>"
return corgi_source.inventory_head
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/datum/strippable_item/corgi_head/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
corgi_source.place_on_head(equipping, user)
/datum/strippable_item/corgi_head/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.inventory_head, corgi_source, user)
corgi_source.inventory_head = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_back
key = STRIPPABLE_ITEM_BACK
/datum/strippable_item/corgi_back/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.inventory_back
/datum/strippable_item/corgi_back/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!ispath(equipping.dog_fashion, /datum/dog_fashion/back))
to_chat(user, "<span class='warning'>You set [equipping] on [source]'s back, but it falls off!</span>")
equipping.forceMove(source.drop_location())
if (prob(25))
step_rand(equipping)
dance_rotate(source, set_original_dir = TRUE)
return FALSE
return TRUE
/datum/strippable_item/corgi_back/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
equipping.forceMove(corgi_source)
corgi_source.inventory_back = equipping
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_back/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.inventory_back, corgi_source, user)
corgi_source.inventory_back = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_collar
key = STRIPPABLE_ITEM_CORGI_COLLAR
/datum/strippable_item/corgi_collar/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.pcollar
/datum/strippable_item/corgi_collar/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!istype(equipping, /obj/item/clothing/neck/petcollar))
to_chat(user, "<span class='warning'>That's not a collar.</span>")
return FALSE
return TRUE
/datum/strippable_item/corgi_collar/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
corgi_source.add_collar(equipping, user)
corgi_source.update_corgi_fluff()
/datum/strippable_item/corgi_collar/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.pcollar, corgi_source, user)
corgi_source.pcollar = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_id
key = STRIPPABLE_ITEM_ID
/datum/strippable_item/corgi_id/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.access_card
/datum/strippable_item/corgi_id/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!istype(equipping, /obj/item/card/id))
to_chat(user, "<span class='warning'>You can't pin [equipping] to [source]!</span>")
return FALSE
return TRUE
/datum/strippable_item/corgi_id/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
equipping.forceMove(source)
corgi_source.access_card = equipping
/datum/strippable_item/corgi_id/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.access_card, corgi_source, user)
corgi_source.access_card = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
var/armorval = 0
@@ -158,114 +316,12 @@
..()
update_corgi_fluff()
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
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"])
var/remove_from = href_list["remove_inv"]
switch(remove_from)
if(BODY_ZONE_HEAD)
if(inventory_head)
usr.put_in_hands(inventory_head)
inventory_head = 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("back")
if(inventory_back)
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"])
var/add_to = href_list["add_inv"]
switch(add_to)
if("collar")
var/obj/item/clothing/neck/petcollar/P = usr.get_active_held_item()
if(!istype(P))
to_chat(usr,"<span class='warning'>That's not a collar.</span>")
return
add_collar(P, usr)
update_corgi_fluff()
if(BODY_ZONE_HEAD)
place_on_head(usr.get_active_held_item(),usr)
if("back")
if(inventory_back)
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)
usr.visible_message("[usr] pets [src].","<span class='notice'>You rest your hand on [src]'s back for a moment.</span>")
return
if(!usr.temporarilyRemoveItemFromInventory(item_to_add))
to_chat(usr, "<span class='warning'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s back!</span>")
return
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,usr,1)
return
//The objects that corgis can wear on their backs.
var/allowed = FALSE
if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/back))
allowed = TRUE
if(!allowed)
to_chat(usr, "<span class='warning'>You set [item_to_add] on [src]'s back, but it falls off!</span>")
item_to_add.forceMove(drop_location())
if(prob(25))
step_rand(item_to_add)
for(var/i in list(1,2,4,8,4,8,4,dir))
setDir(i)
sleep(1)
return
item_to_add.forceMove(src)
src.inventory_back = item_to_add
update_corgi_fluff()
regenerate_icons()
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.
//Many hats added, Some will probably be removed, just want to see which ones are popular.
// > some will probably be removed
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
INVOKE_ASYNC(item_to_add, /obj/item.proc/afterattack, src, user, 1)
return
if(inventory_head)
if(user)
to_chat(user, "<span class='warning'>You can't put more than one hat on [src]!</span>")
@@ -303,9 +359,7 @@
item_to_add.forceMove(drop_location())
if(prob(25))
step_rand(item_to_add)
for(var/i in list(1,2,4,8,4,8,4,dir))
setDir(i)
sleep(1)
dance_rotate(src, set_original_dir = TRUE)
return valid

View File

@@ -113,7 +113,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
severity = 7
hud_used.healths.icon_state = "elite_health[severity]"
if(severity > 0)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
else
clear_fullscreen("brute")

View File

@@ -124,6 +124,9 @@
/mob/living/simple_animal/parrot/proc/toggle_mode,
/mob/living/simple_animal/parrot/proc/perch_mob_player))
/mob/living/simple_animal/parrot/ComponentInitialize()
. = ..()
AddElement(/datum/element/strippable, GLOB.strippable_parrot_items)
/mob/living/simple_animal/parrot/examine(mob/user)
. = ..()
@@ -183,91 +186,101 @@
return 0
/*
* Inventory
*/
/mob/living/simple_animal/parrot/show_inv(mob/user)
user.set_machine(src)
GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
/datum/strippable_item/parrot_headset,
)))
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>"
/datum/strippable_item/parrot_headset
key = STRIPPABLE_ITEM_PARROT_HEADSET
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "window=mob[REF(src)]")
/datum/strippable_item/parrot_headset/get_item(atom/source)
var/mob/living/simple_animal/parrot/parrot_source = source
return istype(parrot_source) ? parrot_source.ears : null
/datum/strippable_item/parrot_headset/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
/mob/living/simple_animal/parrot/Topic(href, href_list)
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
usr << browse(null, "window=mob[REF(src)]")
usr.unset_machine()
if (!istype(equipping, /obj/item/radio/headset))
to_chat(user, "<span class='warning'>[equipping] won't fit!</span>")
return FALSE
return TRUE
// There is no delay for putting a headset on a parrot.
/datum/strippable_item/parrot_headset/start_equip(atom/source, obj/item/equipping, mob/user)
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
return TRUE
/datum/strippable_item/parrot_headset/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/obj/item/radio/headset/radio = equipping
if (!istype(radio))
return FALSE
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return FALSE
if (!user.transferItemToLoc(radio, source))
return FALSE
parrot_source.ears = radio
to_chat(user, "<span class='notice'>You fit [radio] onto [source].</span>")
parrot_source.available_channels.Cut()
for (var/channel in radio.channels)
var/channel_to_add
switch (channel)
if (RADIO_CHANNEL_ENGINEERING)
channel_to_add = RADIO_TOKEN_ENGINEERING
if (RADIO_CHANNEL_COMMAND)
channel_to_add = RADIO_TOKEN_COMMAND
if (RADIO_CHANNEL_SECURITY)
channel_to_add = RADIO_TOKEN_SECURITY
if (RADIO_CHANNEL_SCIENCE)
channel_to_add = RADIO_TOKEN_SCIENCE
if (RADIO_CHANNEL_MEDICAL)
channel_to_add = RADIO_TOKEN_MEDICAL
if (RADIO_CHANNEL_SUPPLY)
channel_to_add = RADIO_TOKEN_SUPPLY
if (RADIO_CHANNEL_SERVICE)
channel_to_add = RADIO_TOKEN_SERVICE
if (channel_to_add)
parrot_source.available_channels += channel_to_add
if (radio.translate_binary)
parrot_source.available_channels.Add(MODE_TOKEN_BINARY)
/datum/strippable_item/parrot_headset/start_unequip(atom/source, mob/user)
. = ..()
if (!.)
return FALSE
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return
//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_char(possible_phrase, 2, 3) in GLOB.department_radio_keys)
possible_phrase = copytext_char(possible_phrase, 3)
if (!parrot_source.stat)
parrot_source.say("[parrot_source.available_channels.len ? "[pick(parrot_source.available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
//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
return TRUE
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
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>")
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)
if(headset_to_add.translate_binary)
available_channels.Add(MODE_TOKEN_BINARY)
else
return ..()
/datum/strippable_item/parrot_headset/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return
finish_unequip_mob(parrot_source.ears, parrot_source, user)
parrot_source.ears = null
/*
* Attack responces

View File

@@ -308,10 +308,15 @@
adjustHealth(unsuitable_atmos_damage)
/mob/living/simple_animal/gib(no_brain, no_organs, no_bodyparts, datum/explosion/was_explosion)
if(butcher_results)
if(butcher_results || guaranteed_butcher_results)
var/list/butcher = list()
if(butcher_results)
butcher += butcher_results
if(guaranteed_butcher_results)
butcher += guaranteed_butcher_results
var/atom/Tsec = drop_location()
for(var/path in butcher_results)
for(var/i in 1 to butcher_results[path])
for(var/path in butcher)
for(var/i in 1 to butcher[path])
new path(Tsec)
..()

View File

@@ -599,7 +599,7 @@
/mob/living/proc/become_nearsighted(source)
if(!HAS_TRAIT(src, TRAIT_NEARSIGHT))
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1)
ADD_TRAIT(src, TRAIT_NEARSIGHT, source)
/mob/living/proc/cure_husk(source)

View File

@@ -1,4 +1,31 @@
/**
* Run when a client is put in this mob or reconnets to byond and their client was on this mob
*
* Things it does:
* * Adds player to player_list
* * sets lastKnownIP
* * sets computer_id
* * logs the login
* * tells the world to update it's status (for player count)
* * create mob huds for the mob if needed
* * reset next_move to 1
* * parent call
* * if the client exists set the perspective to the mob loc
* * call on_log on the loc (sigh)
* * reload the huds for the mob
* * reload all full screen huds attached to this mob
* * load any global alternate apperances
* * sync the mind datum via sync_mind()
* * call any client login callbacks that exist
* * grant any actions the mob has to the client
* * calls [auto_deadmin_on_login](mob.html#proc/auto_deadmin_on_login)
* * send signal COMSIG_MOB_CLIENT_LOGIN
* * attaches the ash listener element so clients can hear weather
* client can be deleted mid-execution of this proc, chiefly on parent calls, with lag
*/
/mob/Login()
if(!client)
return FALSE
add_to_player_list()
lastKnownIP = client.address
computer_id = client.computer_id
@@ -15,6 +42,14 @@
. = ..()
if(!client)
return FALSE
// SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
if (key != client.key)
key = client.key
reset_perspective(loc)
if(loc)
@@ -23,10 +58,6 @@
//readd this mob's HUDs (antag, med, etc)
reload_huds()
reload_fullscreen() // Reload any fullscreen overlays this mob has.
add_click_catcher()
sync_mind()
//Reload alternate appearances
@@ -53,6 +84,15 @@
log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP)
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
client.init_verbs()
if(has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
// load rendering
reload_rendering()
AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds)
// optimized area sound effects. Enable during events (compile flag when 😳)
// AddElement(/datum/element/weather_listener, /datum/weather/long_rain, ZTRAIT_STATION, GLOB.rain_sounds)

View File

@@ -4,7 +4,6 @@
SStgui.on_logout(src)
unset_machine()
remove_from_player_list()
..()
if(loc)

View File

@@ -1,25 +1,3 @@
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
remove_from_mob_list()
remove_from_dead_mob_list()
remove_from_alive_mob_list()
GLOB.all_clockwork_mobs -= src
focus = null
LAssailant = null
movespeed_modification = null
for (var/alert in alerts)
clear_alert(alert, TRUE)
if(observers && observers.len)
for(var/M in observers)
var/mob/dead/observe = M
observe.reset_perspective(null)
qdel(hud_used)
for(var/cc in client_colours)
qdel(cc)
client_colours = null
ghostize()
..()
return QDEL_HINT_HARDDEL
/mob/Initialize()
add_to_mob_list()
if(stat == DEAD)
@@ -38,8 +16,32 @@
update_config_movespeed()
update_movespeed(TRUE)
initialize_actionspeed()
init_rendering()
hook_vr("mob_new",list(src))
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
remove_from_mob_list()
remove_from_dead_mob_list()
remove_from_alive_mob_list()
GLOB.all_clockwork_mobs -= src
focus = null
LAssailant = null
movespeed_modification = null
for (var/alert in alerts)
clear_alert(alert, TRUE)
if(observers && observers.len)
for(var/M in observers)
var/mob/dead/observe = M
observe.reset_perspective(null)
dispose_rendering()
qdel(hud_used)
for(var/cc in client_colours)
qdel(cc)
client_colours = null
ghostize()
..()
return QDEL_HINT_HARDDEL
/mob/GenerateTag()
tag = "mob_[next_mob_id++]"
@@ -289,9 +291,6 @@
SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE, A)
return TRUE
/mob/proc/show_inv(mob/user)
return
//view() but with a signal, to allow blacklisting some of the otherwise visible atoms.
/mob/proc/fov_view(dist = world.view)
. = view(dist, src)
@@ -512,10 +511,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
unset_machine()
src << browse(null, t1)
if(href_list["refresh"])
if(machine && in_range(src, usr))
show_inv(machine)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["item"])
var/slot = text2num(href_list["item"])
@@ -532,12 +527,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
else
usr.stripPanelEquip(what,src,slot)
if(usr.machine == src)
if(Adjacent(usr))
show_inv(usr)
else
usr << browse(null,"window=mob[REF(src)]")
// The src mob is trying to strip an item from someone
// Defined in living.dm
/mob/proc/stripPanelUnequip(obj/item/what, mob/who)
@@ -559,12 +548,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
if(isAI(M))
return
/mob/MouseDrop_T(atom/dropping, atom/user)
. = ..()
if(ismob(dropping) && dropping != user)
var/mob/M = dropping
M.show_inv(user)
/mob/proc/is_muzzled()
return FALSE

View File

@@ -16,6 +16,10 @@
attack_hand_unwieldlyness = CLICK_CD_MELEE
attack_hand_speed = 0
// Rendering
/// Fullscreen objects
var/list/fullscreens = list()
/// What receives our keyboard input. src by default.
var/datum/focus
@@ -143,7 +147,6 @@
var/registered_z
var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly
var/list/screens = list()
var/list/client_colours = list()
var/hud_type = /datum/hud

View File

@@ -144,6 +144,7 @@
newletter = "nglu"
if(5)
newletter = "glor"
else
. += newletter
return sanitize(.)

View File

@@ -110,6 +110,11 @@
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay)
/mob/Moved(atom/OldLoc, Dir)
. = ..()
if(client)
client.parallax_holder.Update()
/// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement.
/client/proc/Process_Grab()
if(mob.pulledby)
@@ -398,3 +403,8 @@
/mob/proc/canZMove(direction, turf/target)
return FALSE
/mob/onTransitZ(old_z, new_z)
. = ..()
if(old_z != new_z)
client?.parallax_holder?.Reset()

View File

@@ -53,7 +53,7 @@
if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(stat == CONSCIOUS || stat == SOFT_CRIT)
throw_alert("blind", /atom/movable/screen/alert/blind)
overlay_fullscreen("blind", /atom/movable/screen/fullscreen/blind)
overlay_fullscreen("blind", /atom/movable/screen/fullscreen/scaled/blind)
// You are blind why should you be able to make out details like color, only shapes near you
// add_client_colour(/datum/client_colour/monochrome/blind)
else // CONSCIOUS no blind trait, no blindness