diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 9ebf60632c..84007beae3 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -34,8 +34,9 @@ #define STANCE_FOLLOW 6 // Following somone #define STANCE_BUSY 7 // Do nothing on life ticks (Other code is running) -#define LEFT 1 -#define RIGHT 2 +#define LEFT 0x1 +#define RIGHT 0x2 +#define UNDER 0x4 // Pulse levels, very simplified. #define PULSE_NONE 0 // So !M.pulse checks would be possible. @@ -124,10 +125,12 @@ #define TINT_HEAVY 2 #define TINT_BLIND 3 +#define FLASH_PROTECTION_VULNERABLE -2 #define FLASH_PROTECTION_REDUCED -1 #define FLASH_PROTECTION_NONE 0 #define FLASH_PROTECTION_MODERATE 1 #define FLASH_PROTECTION_MAJOR 2 + #define ANIMAL_SPAWN_DELAY round(config.respawn_delay / 6) #define DRONE_SPAWN_DELAY round(config.respawn_delay / 3) diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index 9082482ebe..bd0d02ae80 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -56,3 +56,7 @@ #define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message #define NO_STUTTER 256 // No stuttering, slurring, or other speech problems #define ALT_TRANSMIT 512 // Language is not based on vision or sound (Todo: add this into the say code and use it for the rootspeak languages) + +#define SKIN_NORMAL 0 +#define SKIN_THREAT 1 +#define SKIN_CLOAK 2 diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm index f104b77fd7..0ad5ac13f8 100644 --- a/code/game/objects/effects/decals/Cleanable/tracks.dm +++ b/code/game/objects/effects/decals/Cleanable/tracks.dm @@ -154,20 +154,49 @@ var/global/list/image/fluidtrack_cache=list() /obj/effect/decal/cleanable/blood/tracks/footprints name = "wet footprints" dryname = "dried footprints" - desc = "Whoops..." - drydesc = "Whoops..." + desc = "They look like still wet tracks left by footwear." + drydesc = "They look like dried tracks left by footwear." coming_state = "human1" going_state = "human2" amount = 0 +/obj/effect/decal/cleanable/blood/tracks/snake + name = "wet tracks" + dryname = "dried tracks" + desc = "They look like still wet tracks left by a giant snake." + drydesc = "They look like dried tracks left by a giant snake." + coming_state = "snake1" + going_state = "snake2" + random_icon_states = null + amount = 0 + +/obj/effect/decal/cleanable/blood/tracks/paw + name = "wet tracks" + dryname = "dried tracks" + desc = "They look like still wet tracks left by a mammal." + drydesc = "They look like dried tracks left by a mammal." + coming_state = "paw1" + going_state = "paw2" + random_icon_states = null + amount = 0 + +/obj/effect/decal/cleanable/blood/tracks/claw + name = "wet tracks" + dryname = "dried tracks" + desc = "They look like still wet tracks left by a reptile." + drydesc = "They look like dried tracks left by a reptile." + coming_state = "claw1" + going_state = "claw2" + random_icon_states = null + amount = 0 + /obj/effect/decal/cleanable/blood/tracks/wheels name = "wet tracks" dryname = "dried tracks" - desc = "Whoops..." - drydesc = "Whoops..." + desc = "They look like still wet tracks left by wheels." + drydesc = "They look like dried tracks left by wheels." coming_state = "wheels" going_state = "" - desc = "They look like tracks left by wheels." gender = PLURAL random_icon_states = null amount = 0 \ No newline at end of file diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 6a049a4e68..a47590d55d 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -119,10 +119,10 @@ H.track_blood-- if (bloodDNA) - src.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,H.dir,0,bloodcolor) // Coming + src.AddTracks(H.species.get_move_trail(H),bloodDNA,H.dir,0,bloodcolor) // Coming var/turf/simulated/from = get_step(H,reverse_direction(H.dir)) if(istype(from) && from) - from.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,0,H.dir,bloodcolor) // Going + from.AddTracks(H.species.get_move_trail(H),bloodDNA,0,H.dir,bloodcolor) // Going bloodDNA = null diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 6653448b1c..5f2a72aeb8 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -9,6 +9,9 @@ var/list/restricted_accessory_slots var/list/starting_accessories + var/flash_protection = FLASH_PROTECTION_NONE + var/tint = TINT_NONE + /* Sprites used when the clothing item is refit. This is done by setting icon_override. For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary. diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 48ab03ed3f..d0a90a86b5 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -42,12 +42,16 @@ BLIND // can't see anything active = 0 icon_state = off_state user.update_inv_glasses() - usr << "You deactivate the optical matrix on the [src]." + flash_protection = FLASH_PROTECTION_NONE + tint = TINT_NONE + to_chat(usr, "You deactivate the optical matrix on the [src].") else active = 1 icon_state = initial(icon_state) user.update_inv_glasses() - usr << "You activate the optical matrix on the [src]." + flash_protection = initial(flash_protection) + tint = initial(tint) + to_chat(usr, "You activate the optical matrix on the [src].") user.update_action_buttons() /obj/item/clothing/glasses/meson @@ -128,6 +132,7 @@ BLIND // can't see anything action_button_name = "Toggle Goggles" see_invisible = SEE_INVISIBLE_NOLIGHTING off_state = "denight" + flash_protection = FLASH_PROTECTION_REDUCED /obj/item/clothing/glasses/night/vox name = "Alien Optics" @@ -219,6 +224,7 @@ BLIND // can't see anything icon_state = "sun" item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") darkness_view = -1 + flash_protection = FLASH_PROTECTION_MODERATE /obj/item/clothing/glasses/sunglasses/aviator name = "aviators" @@ -234,6 +240,8 @@ BLIND // can't see anything matter = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 1000) item_flags = AIRTIGHT var/up = 0 + flash_protection = FLASH_PROTECTION_MAJOR + tint = TINT_HEAVY /obj/item/clothing/glasses/welding/attack_self() toggle() @@ -249,13 +257,17 @@ BLIND // can't see anything flags_inv |= HIDEEYES body_parts_covered |= EYES icon_state = initial(icon_state) - usr << "You flip \the [src] down to protect your eyes." + flash_protection = initial(flash_protection) + tint = initial(tint) + to_chat(usr, "You flip \the [src] down to protect your eyes.") else src.up = !src.up flags_inv &= ~HIDEEYES body_parts_covered &= ~EYES icon_state = "[initial(icon_state)]up" - usr << "You push \the [src] up out of your face." + flash_protection = FLASH_PROTECTION_NONE + tint = TINT_NONE + to_chat(usr, "You push \the [src] up out of your face.") update_clothing_icon() usr.update_action_buttons() @@ -263,13 +275,15 @@ BLIND // can't see anything name = "superior welding goggles" desc = "Welding goggles made from more expensive materials, strangely smells like potatoes." icon_state = "rwelding-g" + tint = TINT_MODERATE /obj/item/clothing/glasses/sunglasses/blindfold name = "blindfold" desc = "Covers the eyes, preventing sight." icon_state = "blindfold" item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") - //vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses + flash_protection = FLASH_PROTECTION_MAJOR + tint = BLIND /obj/item/clothing/glasses/sunglasses/blindfold/tape name = "length of tape" @@ -340,11 +354,13 @@ BLIND // can't see anything if(toggleable && !user.incapacitated()) on = !on if(on) + flash_protection = FLASH_PROTECTION_NONE src.hud = hud_holder - to_chat(user, "You switch the [src] to HUD mode.") + to_chat(usr, "You switch the [src] to HUD mode.") else + flash_protection = initial(flash_protection) src.hud = null - to_chat(user, "You switch \the [src] to flash protection mode.") + to_chat(usr, "You switch \the [src] to flash protection mode.") update_icon() user << activation_sound user.update_inv_glasses() @@ -382,7 +398,7 @@ BLIND // can't see anything action_button_name = "Toggle Goggles" vision_flags = SEE_MOBS see_invisible = SEE_INVISIBLE_NOLIGHTING - + flash_protection = FLASH_PROTECTION_REDUCED emp_act(severity) if(istype(src.loc, /mob/living/carbon/human)) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 97c5ae4a6d..eea135212d 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -25,6 +25,8 @@ siemens_coefficient = 0.9 w_class = ITEMSIZE_NORMAL var/base_state + flash_protection = FLASH_PROTECTION_MAJOR + tint = TINT_HEAVY /obj/item/clothing/head/welding/attack_self() toggle() @@ -44,13 +46,17 @@ body_parts_covered |= (EYES|FACE) flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) icon_state = base_state - usr << "You flip the [src] down to protect your eyes." + flash_protection = FLASH_PROTECTION_MAJOR + tint = initial(tint) + to_chat(usr, "You flip the [src] down to protect your eyes.") else src.up = !src.up body_parts_covered &= ~(EYES|FACE) flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) icon_state = "[base_state]up" - usr << "You push the [src] up out of your face." + flash_protection = FLASH_PROTECTION_NONE + tint = TINT_NONE + to_chat(usr, "You push the [src] up out of your face.") update_clothing_icon() //so our mob-overlays if (ismob(src.loc)) //should allow masks to update when it is opened/closed var/mob/M = src.loc diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index c66ff3440c..03466eea22 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -93,6 +93,7 @@ name = "Emergency Space Helmet" icon_state = "syndicate-helm-orange" desc = "A simple helmet with a built in light, smells like mothballs." + flash_protection = FLASH_PROTECTION_NONE /obj/item/clothing/suit/space/emergency name = "Emergency Softsuit" diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index ccbbf56ab2..a39b6809c6 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -17,6 +17,7 @@ species_restricted = list("exclude","Diona") preserve_item = 1 phoronproof = 1 + flash_protection = FLASH_PROTECTION_NONE var/obj/machinery/camera/camera var/list/camera_networks diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3788735d76..0b5781b67b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -688,43 +688,40 @@ ///Returns a number between -1 to 2 /mob/living/carbon/human/eyecheck() - var/obj/item/organ/I = internal_organs_by_name[O_EYES] - if(!I || I.status & (ORGAN_CUT_AWAY|ORGAN_DESTROYED)) - return 2 + var/obj/item/organ/internal/eyes/I - var/number = 0 - if(istype(src.head, /obj/item/clothing/head/welding)) - if(!src.head:up) - number += 2 - if(istype(back, /obj/item/weapon/rig)) - var/obj/item/weapon/rig/O = back - if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES)) - number += 2 - if(istype(src.head, /obj/item/clothing/head/helmet/space)) - number += 2 - if(istype(src.head, /obj/item/clothing/head/helmet/space/emergency)) - number -= 2 - if(istype(src.glasses, /obj/item/clothing/glasses/thermal)) - var/obj/item/clothing/glasses/thermal/T = src.glasses - if(T.active) - number -= 1 - if(istype(src.glasses, /obj/item/clothing/glasses/night)) - var/obj/item/clothing/glasses/night/N = src.glasses - if(N.active) - number -= 1 - if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses)) - if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses/sechud/aviator)) - var/obj/item/clothing/glasses/sunglasses/sechud/aviator/S = src.glasses - if(!S.on) - number += 1 - else - number += 1 - if(istype(src.glasses, /obj/item/clothing/glasses/welding)) - var/obj/item/clothing/glasses/welding/W = src.glasses - if(!W.up) - number += 2 + if(internal_organs_by_name[O_EYES]) // Eyes are fucked, not a 'weak point'. + I = internal_organs_by_name[O_EYES] + if(I.is_broken()) + return FLASH_PROTECTION_MAJOR + else // They can't be flashed if they don't have eyes. + return FLASH_PROTECTION_MAJOR + + var/number = get_equipment_flash_protection() + number = I.get_total_protection(number) + I.additional_flash_effects(number) return number +#define add_clothing_protection(A) \ + var/obj/item/clothing/C = A; \ + flash_protection += C.flash_protection; \ + +/mob/living/carbon/human/proc/get_equipment_flash_protection() + var/flash_protection = 0 + + if(istype(src.head, /obj/item/clothing/head)) + add_clothing_protection(head) + if(istype(src.glasses, /obj/item/clothing/glasses)) + add_clothing_protection(glasses) + if(istype(src.wear_mask, /obj/item/clothing/mask)) + add_clothing_protection(wear_mask) + if(istype(back,/obj/item/weapon/rig)) + add_clothing_protection(back) + + return flash_protection + +#undef add_clothing_protection + //Used by various things that knock people out by applying blunt trauma to the head. //Checks that the species has a "head" (brain containing organ) and that hit_zone refers to it. /mob/living/carbon/human/proc/headcheck(var/target_zone, var/brain_tag = "brain") diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index fbb98c3f98..8d81a9ce95 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -23,6 +23,8 @@ var/g_skin = 0 var/b_skin = 0 + var/skin_state = SKIN_NORMAL + //Synth colors var/synth_color = 0 //Lets normally uncolorable synth parts be colorable. var/r_synth //Used with synth_color to color synth parts that normaly can't be colored. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 2855dd5656..0c14d3d384 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -972,7 +972,7 @@ if(paralysis || sleeping) blinded = 1 - stat = UNCONSCIOUS + set_stat(UNCONSCIOUS) animate_tail_reset() adjustHalLoss(-3) @@ -987,7 +987,7 @@ emote("snore") //CONSCIOUS else - stat = CONSCIOUS + set_stat(CONSCIOUS) //Periodically double-check embedded_flag if(embedded_flag && !(life_tick % 10)) @@ -1075,6 +1075,11 @@ return 1 +/mob/living/carbon/human/proc/set_stat(var/new_stat) + stat = new_stat + if(stat) + update_skin(1) + /mob/living/carbon/human/handle_regular_hud_updates() if(hud_updateflag) // update our mob's hud overlays, AKA what others see flaoting above our head handle_hud_list() diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index beb531f901..d38ac45d31 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -158,6 +158,9 @@ var/spawn_flags = 0 // Flags that specify who can spawn as this species var/slowdown = 0 // Passive movement speed malus (or boost, if negative) + var/obj/effect/decal/cleanable/blood/tracks/move_trail = /obj/effect/decal/cleanable/blood/tracks/footprints // What marks are left when walking + var/list/skin_overlays = list() + var/has_floating_eyes = 0 // Whether the eyes can be shown above other icons var/water_movement = 0 // How much faster or slower the species is in water var/snow_movement = 0 // How much faster or slower the species is on snow @@ -358,4 +361,32 @@ // Called when lying down on a water tile. /datum/species/proc/can_breathe_water() - return FALSE \ No newline at end of file + return FALSE + +// Impliments different trails for species depending on if they're wearing shoes. +/datum/species/proc/get_move_trail(var/mob/living/carbon/human/H) + if( H.shoes || ( H.wear_suit && (H.wear_suit.body_parts_covered & FEET) ) ) + return /obj/effect/decal/cleanable/blood/tracks/footprints + else + return move_trail + +/datum/species/proc/update_skin(var/mob/living/carbon/human/H) + return + +/datum/species/proc/get_eyes(var/mob/living/carbon/human/H) + return + +/datum/species/proc/can_overcome_gravity(var/mob/living/carbon/human/H) + return FALSE + +// Used for any extra behaviour when falling and to see if a species will fall at all. +/datum/species/proc/can_fall(var/mob/living/carbon/human/H) + return TRUE + +// Used to find a special target for falling on, such as pouncing on someone from above. +/datum/species/proc/find_fall_target_special(src, landing) + return FALSE + +// Used to override normal fall behaviour. Use only when the species does fall down a level. +/datum/species/proc/fall_impact_special(var/mob/living/carbon/human/H, var/atom/A) + return FALSE diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 0a6e1df9a4..c84b9ad64f 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -26,6 +26,8 @@ tail_hair = "feathers" reagent_tag = IS_TESHARI + move_trail = /obj/effect/decal/cleanable/blood/tracks/paw + icobase = 'icons/mob/human_races/r_seromi.dmi' deform = 'icons/mob/human_races/r_seromi.dmi' damage_overlays = 'icons/mob/human_races/masks/dam_seromi.dmi' diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index e7d1083e86..a133b82495 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -87,6 +87,8 @@ reagent_tag = IS_UNATHI + move_trail = /obj/effect/decal/cleanable/blood/tracks/claw + has_limbs = list( BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi), BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi), @@ -188,6 +190,8 @@ reagent_tag = IS_TAJARA + move_trail = /obj/effect/decal/cleanable/blood/tracks/paw + heat_discomfort_level = 292 heat_discomfort_strings = list( "Your fur prickles in the heat.", diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 3cab75ef2d..8f8974473a 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -107,34 +107,35 @@ Please contact me on #coderbus IRC. ~Carn x //Human Overlays Indexes///////// #define MUTATIONS_LAYER 1 -#define DAMAGE_LAYER 2 -#define SURGERY_LEVEL 3 //bs12 specific. -#define UNDERWEAR_LAYER 4 -#define SHOES_LAYER_ALT 5 -#define UNIFORM_LAYER 6 -#define ID_LAYER 7 -#define SHOES_LAYER 8 -#define GLOVES_LAYER 9 -#define BELT_LAYER 10 -#define SUIT_LAYER 11 -#define TAIL_LAYER 12 //bs12 specific. //In a perfect world the parts of the tail that show between legs would be on a new layer. Until then, sprite's been tweaked -#define GLASSES_LAYER 13 -#define BELT_LAYER_ALT 14 -#define SUIT_STORE_LAYER 15 -#define BACK_LAYER 16 -#define HAIR_LAYER 17 //TODO: make part of head layer? -#define EARS_LAYER 18 -#define FACEMASK_LAYER 19 -#define HEAD_LAYER 20 -#define COLLAR_LAYER 21 -#define HANDCUFF_LAYER 22 -#define LEGCUFF_LAYER 23 -#define L_HAND_LAYER 24 -#define R_HAND_LAYER 25 -#define MODIFIER_EFFECTS_LAYER 26 -#define FIRE_LAYER 27 //If you're on fire -#define WATER_LAYER 28 //If you're submerged in water. -#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system +#define SKIN_LAYER 2 +#define DAMAGE_LAYER 3 +#define SURGERY_LEVEL 4 //bs12 specific. +#define UNDERWEAR_LAYER 5 +#define SHOES_LAYER_ALT 6 +#define UNIFORM_LAYER 7 +#define ID_LAYER 8 +#define SHOES_LAYER 9 +#define GLOVES_LAYER 10 +#define BELT_LAYER 11 +#define SUIT_LAYER 12 +#define TAIL_LAYER 13 //bs12 specific. //In a perfect world the parts of the tail that show between legs would be on a new layer. Until then, sprite's been tweaked +#define GLASSES_LAYER 14 +#define BELT_LAYER_ALT 15 +#define SUIT_STORE_LAYER 16 +#define BACK_LAYER 17 +#define HAIR_LAYER 18 //TODO: make part of head layer? +#define EARS_LAYER 19 +#define FACEMASK_LAYER 20 +#define HEAD_LAYER 21 +#define COLLAR_LAYER 22 +#define HANDCUFF_LAYER 23 +#define LEGCUFF_LAYER 24 +#define L_HAND_LAYER 25 +#define R_HAND_LAYER 26 +#define MODIFIER_EFFECTS_LAYER 27 +#define FIRE_LAYER 28 //If you're on fire +#define WATER_LAYER 29 //If you're submerged in water. +#define TARGETED_LAYER 30 //BS12: Layer for the target overlay from weapon targeting system #define TOTAL_LAYERS 30 ////////////////////////////////// @@ -158,6 +159,8 @@ Please contact me on #coderbus IRC. ~Carn x else if(istype(entry, /list)) for(var/inner_entry in entry) overlays += inner_entry + if(species && species.has_floating_eyes) + overlays |= species.get_eyes(src) update_transform() @@ -280,6 +283,7 @@ var/global/list/damage_icon_parts = list() icon_key += "[rgb(part.s_col[1],part.s_col[2],part.s_col[3])]" if(part.body_hair && part.h_col && part.h_col.len >= 3) icon_key += "[rgb(part.h_col[1],part.h_col[2],part.h_col[3])]" + icon_key += "[part.s_col_blend]" else icon_key += "#000000" for(var/M in part.markings) @@ -311,7 +315,7 @@ var/global/list/damage_icon_parts = list() var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) - if(part.icon_position&(LEFT|RIGHT)) + if(part.icon_position & (LEFT | RIGHT)) var/icon/temp2 = new('icons/mob/human.dmi',"blank") temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) @@ -325,6 +329,8 @@ var/global/list/damage_icon_parts = list() if(part.icon_position & RIGHT) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) base_icon.Blend(temp2, ICON_UNDERLAY) + else if(part.icon_position & UNDER) + base_icon.Blend(temp, ICON_UNDERLAY) else base_icon.Blend(temp, ICON_OVERLAY) @@ -354,6 +360,10 @@ var/global/list/damage_icon_parts = list() //tail update_tail_showing(0) +/mob/living/carbon/human/proc/update_skin(var/update_icons=1) + overlays_standing[SKIN_LAYER] = species.update_skin(src) + if(update_icons) update_icons() + //UNDERWEAR OVERLAY /mob/living/carbon/human/proc/update_underwear(var/update_icons=1) overlays_standing[UNDERWEAR_LAYER] = null @@ -463,6 +473,7 @@ var/global/list/damage_icon_parts = list() if(transforming || QDELETED(src)) return update_mutations(0) + update_skin(0) update_body(0) update_underwear(0) update_hair(0) diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 25d099155d..59b0b2ebe8 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -38,7 +38,7 @@ return 0 var/area/area = get_area(src) - if(direction == UP && area.has_gravity) + if(direction == UP && area.has_gravity() && !can_overcome_gravity()) var/obj/structure/lattice/lattice = locate() in destination.contents if(lattice) var/pull_up_time = max(5 SECONDS + (src.movement_delay() * 10), 1) @@ -61,6 +61,12 @@ return 0 return 1 +/mob/proc/can_overcome_gravity() + return FALSE + +/mob/living/carbon/human/can_overcome_gravity() + return species && species.can_overcome_gravity(src) + /mob/observer/zMove(direction) var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) if(destination) @@ -183,6 +189,10 @@ if((locate(/obj/structure/disposalpipe/up) in below) || locate(/obj/machinery/atmospherics/pipe/zpipe/up in below)) return FALSE +/mob/living/carbon/human/can_fall() + if(..()) + return species.can_fall(src) + /mob/living/simple_animal/parrot/can_fall() // Poly can fly. return FALSE @@ -222,7 +232,6 @@ return FALSE return falling_atom.fall_impact(src) - // Actually process the falling movement and impacts. /atom/movable/proc/handle_fall(var/turf/landing) var/turf/oldloc = loc @@ -244,50 +253,89 @@ // Detect if we made a silent landing. if(locate(/obj/structure/stairs) in landing) return 1 + else + var/atom/A = find_fall_target(oldloc, landing) + if(special_fall_handle(A) || !A || !A.check_impact(src)) + return + fall_impact(A) +/atom/movable/proc/special_fall_handle(var/atom/A) + return FALSE + +/mob/living/carbon/human/special_fall_handle(var/atom/A) + if(species) + return species.fall_impact_special(src, A) + return FALSE + +/atom/movable/proc/find_fall_target(var/turf/oldloc, var/turf/landing) if(isopenspace(oldloc)) oldloc.visible_message("\The [src] falls down through \the [oldloc]!", "You hear something falling through the air.") // If the turf has density, we give it first dibs if (landing.density && landing.CheckFall(src)) - return + return landing // First hit objects in the turf! for(var/atom/movable/A in landing) if(A != src && A.CheckFall(src)) - return + return A // If none of them stopped us, then hit the turf itself - landing.CheckFall(src) + if(landing.CheckFall(src)) + return landing +/mob/living/carbon/human/find_fall_target(var/turf/landing) + if(species) + var/atom/A = species.find_fall_target_special(src, landing) + if(A) + return A + return ..() + +//CheckFall landing.fall_impact(src) // ## THE FALLING PROCS ### -// Called on everything that falling_atom might hit. Return 1 if you're handling it so handle_fall() will stop checking. -// If you're soft and break the fall gently, just return 1 -// If the falling atom will hit you hard, call fall_impact() and return its result. +// Called on everything that falling_atom might hit. Return TRUE if you're handling it so find_fall_target() will stop checking. /atom/proc/CheckFall(var/atom/movable/falling_atom) if(density && !(flags & ON_BORDER)) - return falling_atom.fall_impact(src) + return TRUE + +// If you are hit: how is it handled. +// Return TRUE if the generic fall_impact should be called +// Return FALSE if you handled it yourself or if there's no effect from hitting you +/atom/proc/check_impact(var/atom/movable/falling_atom) + if(density && !(flags & ON_BORDER)) + return TRUE // By default all turfs are gonna let you hit them regardless of density. /turf/CheckFall(var/atom/movable/falling_atom) - return falling_atom.fall_impact(src) + return TRUE + +/turf/check_impact(var/atom/movable/falling_atom) + return TRUE // Obviously you can't really hit open space. /turf/simulated/open/CheckFall(var/atom/movable/falling_atom) - // Don't need to print this, the open space it falls into will print it for us! - // visible_message("\The [falling_atom] falls from above through \the [src]!", "You hear a whoosh of displaced air.") - return 0 + return FALSE + +/turf/simulated/open/check_impact(var/atom/movable/falling_atom) + return FALSE // We return 1 without calling fall_impact in order to provide a soft landing. So nice. // Note this really should never even get this far /obj/structure/stairs/CheckFall(var/atom/movable/falling_atom) - return 1 + return TRUE + +/obj/structure/stairs/check_impact(var/atom/movable/falling_atom) + return FALSE // Can't fall onto ghosts /mob/observer/dead/CheckFall() - return 0 + return FALSE + +/mob/observer/dead/check_impact() + return FALSE + // Called by CheckFall when we actually hit something. Various Vars will be described below // hit_atom is the thing we fall on diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm index 4febf8f479..07d70bc6e2 100644 --- a/code/modules/organs/internal/eyes.dm +++ b/code/modules/organs/internal/eyes.dm @@ -7,6 +7,7 @@ organ_tag = O_EYES parent_organ = BP_HEAD var/list/eye_colour = list(0,0,0) + var/innate_flash_protection = FLASH_PROTECTION_NONE /obj/item/organ/internal/eyes/robotize() ..() @@ -86,3 +87,9 @@ if(prob(1)) owner.custom_pain("Your eyes are watering, making it harder to see clearly for a moment.",1) owner.eye_blurry += 10 + +/obj/item/organ/internal/eyes/proc/get_total_protection(var/flash_protection = FLASH_PROTECTION_NONE) + return (flash_protection + innate_flash_protection) + +/obj/item/organ/internal/eyes/proc/additional_flash_effects(var/intensity) + return -1 diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index b6ad2fff2c..8d084f9e0e 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -36,6 +36,7 @@ var/gendered_icon = 0 // Whether or not the icon state appends a gender. var/s_tone // Skin tone. var/list/s_col // skin colour + var/s_col_blend = ICON_ADD // How the skin colour is applied. var/list/h_col // hair colour var/body_hair // Icon blend for body hair if any. var/mob/living/applied_pressure diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 3c986b16fd..170475a208 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -58,7 +58,7 @@ var/global/list/limb_icon_cache = list() if(owner.should_have_organ(O_EYES)) var/obj/item/organ/internal/eyes/eyes = owner.internal_organs_by_name[O_EYES] if(eye_icon) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', eye_icon) + var/icon/eyes_icon = new/icon(eye_icon_location, eye_icon) if(eyes) eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) else @@ -178,9 +178,10 @@ var/global/list/limb_icon_cache = list() else applying.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) icon_cache_key += "_tone_[s_tone]" - else if(s_col && s_col.len >= 3) - applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD) - icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]" + else + if(s_col && s_col.len >= 3) + applying.Blend(rgb(s_col[1], s_col[2], s_col[3]), s_col_blend) + icon_cache_key += "_color_[s_col[1]]_[s_col[2]]_[s_col[3]]_[s_col_blend]" // Translucency. if(nonsolid) applying += rgb(,,,180) // SO INTUITIVE TY BYOND diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index d1eb81cc7f..10123c9ea4 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -265,6 +265,8 @@ force = 3 throwforce = 7 + var/eye_icon_location = 'icons/mob/human_face.dmi' + /obj/item/organ/external/head/robotize(var/company, var/skip_prosthetics, var/keep_organs) return ..(company, skip_prosthetics, 1) diff --git a/icons/effects/fluidtracks.dmi b/icons/effects/fluidtracks.dmi index 58e8fae934..58865d6234 100644 Binary files a/icons/effects/fluidtracks.dmi and b/icons/effects/fluidtracks.dmi differ