Merge branch 'master' into robotic-limbs-PT2

This commit is contained in:
DeltaFire
2020-10-11 00:44:28 +02:00
207 changed files with 8589 additions and 3508 deletions
@@ -26,7 +26,8 @@
features = random_features(pref_species?.id, gender)
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(equip_job = TRUE)
/datum/preferences/proc/update_preview_icon(current_tab)
var/equip_job = (current_tab != 2)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob = get_highest_job()
@@ -45,9 +46,13 @@
mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER))
copy_to(mannequin, initial_spawn = TRUE)
if(previewJob && equip_job)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE, preference_source = parent)
if(current_tab == 3)
//give it its loadout if not on the appearance tab
SSjob.equip_loadout(parent.mob, mannequin, FALSE, bypass_prereqs = TRUE, can_drop = FALSE)
else
if(previewJob && equip_job)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE, preference_source = parent)
COMPILE_OVERLAYS(mannequin)
parent.show_character_previews(new /mutable_appearance(mannequin))
@@ -2,7 +2,7 @@
// Facial Hair Definitions //
/////////////////////////////
/datum/sprite_accessory/facial_hair
icon = 'icons/mob/human_face.dmi'
icon = 'icons/mob/hair.dmi'
gender = MALE // barf (unless you're a dorf, dorfs dig chix w/ beards :P)
// please make sure they're sorted alphabetically and categorized
@@ -2,7 +2,7 @@
// Hair Definitions //
//////////////////////
/datum/sprite_accessory/hair
icon = 'icons/mob/human_face.dmi' // default icon for all hairs
icon = 'icons/mob/hair.dmi' // default icon for all hairs
// please make sure they're sorted alphabetically and, where needed, categorized
// try to capitalize the names please~
+5 -5
View File
@@ -408,7 +408,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mind.current.key && mind.current.key[1] != "@") //makes sure we don't accidentally kick any clients
to_chat(usr, "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>")
return
client.change_view(CONFIG_GET(string/default_view))
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))//Let's reset so people can't become allseeing gods
transfer_ckey(mind.current, FALSE)
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.client.init_verbs()
@@ -568,15 +568,15 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc = "Change your view range."
var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
if(client.view == CONFIG_GET(string/default_view))
if(client.view_size.getView() == client.view_size.default)
var/list/views = list()
for(var/i in 7 to max_view)
views |= i
var/new_view = input("Choose your new view", "Modify view range", 7) as null|anything in views
var/new_view = input("Choose your new view", "Modify view range", 0) as null|anything in views
if(new_view)
client.change_view(clamp(new_view, 7, max_view))
client.view_size.setTo(clamp(new_view, 7, max_view) - 7)
else
client.change_view(CONFIG_GET(string/default_view))
client.view_size.resetToDefault()
/mob/dead/observer/verb/add_view_range(input as num)
set name = "Add View Range"
+2 -17
View File
@@ -979,30 +979,15 @@
O.held_index = r_arm_index_next //2, 4, 6, 8...
hand_bodyparts += O
/mob/living/carbon/do_after_coefficent()
. = ..()
var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) //Currently, only carbons or higher use mood, move this once that changes.
if(mood)
switch(mood.sanity) //Alters do_after delay based on how sane you are
if(SANITY_INSANE to SANITY_DISTURBED)
. *= 1.25
if(SANITY_NEUTRAL to SANITY_GREAT)
. *= 0.90
for(var/i in status_effects)
var/datum/status_effect/S = i
. *= S.interact_speed_modifier()
/mob/living/carbon/proc/create_internal_organs()
for(var/X in internal_organs)
var/obj/item/organ/I = X
I.Insert(src)
/mob/living/carbon/proc/update_disabled_bodyparts()
/mob/living/carbon/proc/update_disabled_bodyparts(silent = FALSE)
for(var/B in bodyparts)
var/obj/item/bodypart/BP = B
BP.update_disabled()
BP.update_disabled(silent)
/mob/living/carbon/vv_get_dropdown()
. = ..()
@@ -1046,7 +1046,8 @@
return
var/stambufferinfluence = (bufferedstam*(100/stambuffer))*0.2 //CIT CHANGE - makes stamina buffer influence movedelay
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
var/health_deficiency = ((maxHealth + stambufferinfluence) - health + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
var/scaling = maxHealth / 100
var/health_deficiency = (((maxHealth / scaling) + stambufferinfluence) - (health / scaling) + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
if(health_deficiency >= 40)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
@@ -1057,11 +1058,6 @@
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
/mob/living/carbon/human/do_after_coefficent()
. = ..()
. *= physiology.do_after_speed
/mob/living/carbon/human/is_bleeding()
if(NOBLOOD in dna.species.species_traits || bleedsuppress)
return FALSE
@@ -101,3 +101,8 @@
if(dna.species.space_move(src))
return TRUE
return ..()
/mob/living/carbon/human/CanPass(atom/movable/mover, turf/target)
if(dna.species.species_pass_check())
return TRUE
return ..()
@@ -23,8 +23,6 @@
var/hunger_mod = 1 //% of hunger rate taken per tick.
var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations.
/// footstep type override for both shoeless and not footstep sounds.
var/footstep_type
@@ -117,6 +117,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//the ids you can use for your species, if empty, it means default only and not changeable
var/list/allowed_limb_ids
//the type of eyes this species has
var/eye_type = "normal"
///////////
// PROCS //
///////////
@@ -510,7 +513,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER)
if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
if(!(NOBLOOD in species_traits))
hair_overlay.icon = 'icons/mob/human_face.dmi'
hair_overlay.icon = 'icons/mob/hair.dmi'
hair_overlay.icon_state = "debrained"
else if(H.hair_style && (HAIR in species_traits))
@@ -569,7 +572,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HD && !(HAS_TRAIT(H, TRAIT_HUSK)))
// lipstick
if(H.lip_style && (LIPS in species_traits))
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[H.lip_style]", -BODY_LAYER)
lip_overlay.color = H.lip_color
if(OFFSET_LIPS in H.dna.species.offset_features)
@@ -582,10 +585,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!(NOEYES in species_traits))
var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES)
if(!has_eyes)
standing += mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)
standing += mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER)
else
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER)
var/left_state = DEFAULT_LEFT_EYE_STATE
var/right_state = DEFAULT_RIGHT_EYE_STATE
if(eye_type in GLOB.eye_types)
left_state = eye_type + "_left_eye"
right_state = eye_type + "_right_eye"
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER)
if((EYECOLOR in species_traits) && has_eyes)
left_eye.color = "#" + H.left_eye_color
right_eye.color = "#" + H.right_eye_color
@@ -1937,6 +1945,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HAS_BONE in species_traits)
. |= BIO_JUST_BONE
//a check for if you should render any overlays or not
/datum/species/proc/should_render(mob/living/carbon/human/H)
return TRUE
//a check for if you want to forcibly make CanPass return TRUE for the mob with this species
/datum/species/proc/species_pass_check()
return FALSE
/////////////
//BREATHING//
/////////////
@@ -21,3 +21,5 @@
species_type = "insect"
allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale")
eye_type = "insect"
@@ -16,7 +16,8 @@
exotic_blood_color = "BLOOD_COLOR_SLIME"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
var/datum/action/innate/slime_change/slime_change //CIT CHANGE
var/datum/action/innate/slime_change/slime_change
var/datum/action/innate/slime_puddle/slime_puddle
liked_food = TOXIC | MEAT
disliked_food = null
toxic_food = ANTITOXIC
@@ -35,12 +36,15 @@
desc = "A slimey membranous mass from a slime person"
icon_state = "brain-slime"
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(slime_puddle && slime_puddle.is_puddle)
slime_puddle.Activate()
if(regenerate_limbs)
regenerate_limbs.Remove(C)
if(slime_change) //CIT CHANGE
slime_change.Remove(C) //CIT CHANGE
if(slime_change)
slime_change.Remove(C)
if(slime_puddle)
slime_puddle.Remove(C)
C.faction -= "slime"
..()
C.faction -= "slime"
@@ -50,8 +54,10 @@
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
slime_change = new //CIT CHANGE
slime_change.Grant(C) //CIT CHANGE
slime_change = new
slime_change.Grant(C)
slime_puddle = new
slime_puddle.Grant(C)
C.faction |= "slime"
/datum/species/jelly/handle_body(mob/living/carbon/human/H)
@@ -59,6 +65,18 @@
//update blood color to body color
exotic_blood_color = "#" + H.dna.features["mcolor"]
/datum/species/jelly/should_render()
if(slime_puddle && slime_puddle.is_puddle)
return FALSE
else
return ..()
/datum/species/jelly/species_pass_check()
if(slime_puddle && slime_puddle.is_puddle)
return TRUE
else
return ..()
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers
return
@@ -670,6 +688,88 @@
else
return
/datum/action/innate/slime_puddle
name = "Puddle Transformation"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimepuddle"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
required_mobility_flags = MOBILITY_STAND
var/is_puddle = FALSE
var/in_transformation_duration = 12
var/out_transformation_duration = 7
var/puddle_into_effect = /obj/effect/temp_visual/slime_puddle
var/puddle_from_effect = /obj/effect/temp_visual/slime_puddle/reverse
var/puddle_icon = 'icons/mob/mob.dmi'
var/puddle_state = "puddle"
var/tracked_overlay
var/datum/component/squeak/squeak
var/transforming = FALSE
var/last_use
/datum/action/innate/slime_puddle/IsAvailable()
if(!transforming)
return ..()
else
return FALSE
/datum/action/innate/slime_puddle/Activate()
if(isjellyperson(owner) && IsAvailable())
transforming = TRUE
UpdateButtonIcon()
var/mob/living/carbon/human/H = owner
var/mutcolor = "#" + H.dna.features["mcolor"]
if(!is_puddle)
if(CHECK_MOBILITY(H, MOBILITY_USE))
is_puddle = TRUE
owner.cut_overlays()
var/obj/effect/puddle_effect = new puddle_into_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
H.Stun(in_transformation_duration, ignore_canstun = TRUE)
ADD_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.update_disabled_bodyparts(silent = TRUE)
H.layer -= 1 //go one layer down so people go over you
ENABLE_BITFIELD(H.pass_flags, PASSMOB)
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg'))
sleep(in_transformation_duration)
var/mutable_appearance/puddle_overlay = mutable_appearance(icon = puddle_icon, icon_state = puddle_state)
puddle_overlay.color = mutcolor
tracked_overlay = puddle_overlay
owner.add_overlay(puddle_overlay)
transforming = FALSE
UpdateButtonIcon()
else
owner.cut_overlay(tracked_overlay)
var/obj/effect/puddle_effect = new puddle_from_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
H.Stun(out_transformation_duration, ignore_canstun = TRUE)
sleep(out_transformation_duration)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE)
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer += 1 //go one layer back above!
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
is_puddle = FALSE
if(squeak)
squeak.RemoveComponent()
owner.regenerate_icons()
transforming = FALSE
UpdateButtonIcon()
else
to_chat(owner, "<span class='warning'>You need to be standing up to do this!") //just assume they're a slime because it's such a weird edgecase to have it and not be one (it shouldn't even be possible)
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
@@ -50,19 +50,21 @@ There are several things that need to be remembered:
//HAIR OVERLAY
/mob/living/carbon/human/update_hair()
dna.species.handle_hair(src)
if(dna.species.should_render())
dna.species.handle_hair(src)
//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/proc/update_mutant_bodyparts()
dna.species.handle_mutant_bodyparts(src)
if(dna.species.should_render())
dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/update_body(update_genitals = FALSE)
remove_overlay(BODY_LAYER)
dna.species.handle_body(src)
..()
if(update_genitals)
update_genitals()
if(dna.species.should_render())
remove_overlay(BODY_LAYER)
dna.species.handle_body(src)
..()
if(update_genitals)
update_genitals()
/mob/living/carbon/human/update_fire()
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
@@ -71,381 +73,385 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
if(!..())
icon_render_key = null //invalidate bodyparts cache
update_body(TRUE)
update_hair()
update_inv_w_uniform()
update_inv_wear_id()
update_inv_gloves()
update_inv_glasses()
update_inv_ears()
update_inv_shoes()
update_inv_s_store()
update_inv_wear_mask()
update_inv_head()
update_inv_belt()
update_inv_back()
update_inv_wear_suit()
update_inv_pockets()
update_inv_neck()
update_transform()
//mutations
update_mutations_overlay()
//damage overlays
update_damage_overlays()
if(dna.species.should_render())
if(!..())
icon_render_key = null //invalidate bodyparts cache
update_body(TRUE)
update_hair()
update_inv_w_uniform()
update_inv_wear_id()
update_inv_gloves()
update_inv_glasses()
update_inv_ears()
update_inv_shoes()
update_inv_s_store()
update_inv_wear_mask()
update_inv_head()
update_inv_belt()
update_inv_back()
update_inv_wear_suit()
update_inv_pockets()
update_inv_neck()
update_transform()
//mutations
update_mutations_overlay()
//damage overlays
update_damage_overlays()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform()
remove_overlay(UNIFORM_LAYER)
if(dna.species.should_render())
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
inv.update_icon()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
inv.update_icon()
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
U.screen_loc = ui_iclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += w_uniform
update_observer_view(w_uniform,1)
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
U.screen_loc = ui_iclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += w_uniform
update_observer_view(w_uniform,1)
if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
return
if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
return
var/target_overlay = U.icon_state
if(U.adjusted == ALT_STYLE)
target_overlay = "[target_overlay]_d"
var/target_overlay = U.icon_state
if(U.adjusted == ALT_STYLE)
target_overlay = "[target_overlay]_d"
var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi'
var/variant_flag = NONE
var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi'
var/variant_flag = NONE
if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE && !(U.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_worn = U.anthro_mob_worn_overlay || 'icons/mob/clothing/uniform_digi.dmi'
variant_flag |= STYLE_DIGITIGRADE
if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE && !(U.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_worn = U.anthro_mob_worn_overlay || 'icons/mob/clothing/uniform_digi.dmi'
variant_flag |= STYLE_DIGITIGRADE
var/mask
if(dna.species.mutant_bodyparts["taur"])
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
var/clip_flag = U.mutantrace_variation & T?.hide_legs
if(clip_flag)
variant_flag |= clip_flag
mask = T.alpha_mask_state
var/mask
if(dna.species.mutant_bodyparts["taur"])
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
var/clip_flag = U.mutantrace_variation & T?.hide_legs
if(clip_flag)
variant_flag |= clip_flag
mask = T.alpha_mask_state
var/mutable_appearance/uniform_overlay
var/mutable_appearance/uniform_overlay
var/gendered = (dna?.species.sexes && dna.features["body_model"] == FEMALE) ? U.fitted : NO_FEMALE_UNIFORM
uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, gendered, target_overlay, variant_flag, FALSE, mask)
var/gendered = (dna?.species.sexes && dna.features["body_model"] == FEMALE) ? U.fitted : NO_FEMALE_UNIFORM
uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, gendered, target_overlay, variant_flag, FALSE, mask)
if(OFFSET_UNIFORM in dna.species.offset_features)
uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
overlays_standing[UNIFORM_LAYER] = uniform_overlay
apply_overlay(UNIFORM_LAYER)
update_mutant_bodyparts()
if(OFFSET_UNIFORM in dna.species.offset_features)
uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
overlays_standing[UNIFORM_LAYER] = uniform_overlay
apply_overlay(UNIFORM_LAYER)
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
remove_overlay(ID_LAYER)
if(dna.species.should_render())
remove_overlay(ID_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
inv.update_icon()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
inv.update_icon()
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
if(wear_id)
wear_id.screen_loc = ui_id
if(client && hud_used && hud_used.hud_shown)
client.screen += wear_id
update_observer_view(wear_id)
if(wear_id)
wear_id.screen_loc = ui_id
if(client && hud_used && hud_used.hud_shown)
client.screen += wear_id
update_observer_view(wear_id)
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state)
if(OFFSET_ID in dna.species.offset_features)
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
overlays_standing[ID_LAYER] = id_overlay
apply_overlay(ID_LAYER)
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state)
if(OFFSET_ID in dna.species.offset_features)
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
overlays_standing[ID_LAYER] = id_overlay
apply_overlay(ID_LAYER)
/mob/living/carbon/human/update_inv_gloves()
remove_overlay(GLOVES_LAYER)
if(dna.species.should_render())
remove_overlay(GLOVES_LAYER)
if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
inv.update_icon()
if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
inv.update_icon()
if(!gloves && bloody_hands)
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
if(get_num_arms(FALSE) < 2)
if(has_left_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_left"
else if(has_right_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_right"
if(!gloves && bloody_hands)
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
if(get_num_arms(FALSE) < 2)
if(has_left_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_left"
else if(has_right_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_right"
overlays_standing[GLOVES_LAYER] = bloody_overlay
overlays_standing[GLOVES_LAYER] = bloody_overlay
var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
if(gloves)
gloves.screen_loc = ui_gloves
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += gloves
update_observer_view(gloves,1)
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
gloves_overlay = overlays_standing[GLOVES_LAYER]
if(OFFSET_GLOVES in dna.species.offset_features)
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
overlays_standing[GLOVES_LAYER] = gloves_overlay
apply_overlay(GLOVES_LAYER)
var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
if(gloves)
gloves.screen_loc = ui_gloves
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += gloves
update_observer_view(gloves,1)
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
gloves_overlay = overlays_standing[GLOVES_LAYER]
if(OFFSET_GLOVES in dna.species.offset_features)
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
overlays_standing[GLOVES_LAYER] = gloves_overlay
apply_overlay(GLOVES_LAYER)
/mob/living/carbon/human/update_inv_glasses()
remove_overlay(GLASSES_LAYER)
if(dna.species.should_render())
remove_overlay(GLASSES_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
inv.update_icon()
if(glasses)
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
client.screen += glasses //Either way, add the item to the HUD
update_observer_view(glasses,1)
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state)
var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
if(glasses_overlay)
if(OFFSET_GLASSES in dna.species.offset_features)
glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
overlays_standing[GLASSES_LAYER] = glasses_overlay
apply_overlay(GLASSES_LAYER)
/mob/living/carbon/human/update_inv_ears()
remove_overlay(EARS_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
inv.update_icon()
if(ears)
ears.screen_loc = ui_ears //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open
client.screen += ears //add it to the client's screen
update_observer_view(ears,1)
overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
if(OFFSET_EARS in dna.species.offset_features)
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
overlays_standing[EARS_LAYER] = ears_overlay
apply_overlay(EARS_LAYER)
/mob/living/carbon/human/update_inv_shoes()
remove_overlay(SHOES_LAYER)
if(get_num_legs(FALSE) <2)
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
inv.update_icon()
if(dna.species.mutant_bodyparts["taur"])
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
if(T?.hide_legs) //If only they actually made shoes unwearable. Please don't making cosmetics, guys.
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
return
if(shoes)
var/obj/item/clothing/shoes/S = shoes
shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open
client.screen += shoes //add it to client's screen
update_observer_view(shoes,1)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
inv.update_icon()
var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi'
var/variation_flag = NONE
if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/feet_digi.dmi'
variation_flag |= STYLE_DIGITIGRADE
if(glasses)
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
client.screen += glasses //Either way, add the item to the HUD
update_observer_view(glasses,1)
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state)
var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
if(glasses_overlay)
if(OFFSET_GLASSES in dna.species.offset_features)
glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
overlays_standing[GLASSES_LAYER] = glasses_overlay
apply_overlay(GLASSES_LAYER)
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, S.icon_state, variation_flag, FALSE)
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
if(OFFSET_SHOES in dna.species.offset_features)
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
overlays_standing[SHOES_LAYER] = shoes_overlay
apply_overlay(SHOES_LAYER)
/mob/living/carbon/human/update_inv_ears()
if(dna.species.should_render())
remove_overlay(EARS_LAYER)
/mob/living/carbon/human/update_inv_s_store()
remove_overlay(SUIT_STORE_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
inv.update_icon()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
inv.update_icon()
if(s_store)
s_store.screen_loc = ui_sstore1
if(client && hud_used && hud_used.hud_shown)
client.screen += s_store
update_observer_view(s_store)
var/t_state = s_store.item_state
if(!t_state)
t_state = s_store.icon_state
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
if(OFFSET_S_STORE in dna.species.offset_features)
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
apply_overlay(SUIT_STORE_LAYER)
if(ears)
ears.screen_loc = ui_ears //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open
client.screen += ears //add it to the client's screen
update_observer_view(ears,1)
overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
if(OFFSET_EARS in dna.species.offset_features)
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
overlays_standing[EARS_LAYER] = ears_overlay
apply_overlay(EARS_LAYER)
/mob/living/carbon/human/update_inv_head()
remove_overlay(HEAD_LAYER)
/mob/living/carbon/human/update_inv_shoes()
if(dna.species.should_render())
remove_overlay(SHOES_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(get_num_legs(FALSE) <2)
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv.update_icon()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
inv.update_icon()
if(head)
head.screen_loc = ui_head
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += head
update_observer_view(head,1)
remove_overlay(HEAD_LAYER)
var/obj/item/clothing/head/H = head
var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
var/muzzled = FALSE
var/variation_flag = NONE
if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
muzzled = TRUE
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
muzzled = TRUE
if(muzzled && H.mutantrace_variation & STYLE_MUZZLE && !(H.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = H.anthro_mob_worn_overlay || 'icons/mob/clothing/head_muzzled.dmi'
variation_flag |= STYLE_MUZZLE
overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE)
var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
if(OFFSET_HEAD in dna.species.offset_features)
head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
overlays_standing[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
inv.update_icon()
if(belt)
belt.screen_loc = ui_belt
if(client && hud_used && hud_used.hud_shown)
client.screen += belt
update_observer_view(belt)
overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi')
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
if(OFFSET_BELT in dna.species.offset_features)
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
overlays_standing[BELT_LAYER] = belt_overlay
apply_overlay(BELT_LAYER)
/mob/living/carbon/human/update_inv_wear_suit()
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
inv.update_icon()
if(wear_suit)
var/obj/item/clothing/suit/S = wear_suit
wear_suit.screen_loc = ui_oclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_suit
update_observer_view(wear_suit,1)
var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi'
var/worn_state = wear_suit.icon_state
var/center = FALSE
var/dimension_x = 32
var/dimension_y = 32
var/variation_flag = NONE
var/datum/sprite_accessory/taur/T
if(dna.species.mutant_bodyparts["taur"])
T = GLOB.taur_list[dna.features["taur"]]
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
if(T?.hide_legs) //If only they actually made shoes unwearable. Please don't making cosmetics, guys.
return
if(S.mutantrace_variation)
if(shoes)
var/obj/item/clothing/shoes/S = shoes
shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open
client.screen += shoes //add it to client's screen
update_observer_view(shoes,1)
if(T?.taur_mode)
var/init_worn_icon = worn_icon
variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode
switch(variation_flag)
if(STYLE_HOOF_TAURIC)
worn_icon = 'icons/mob/clothing/taur_hooved.dmi'
if(STYLE_SNEK_TAURIC)
worn_icon = 'icons/mob/clothing/taur_naga.dmi'
if(STYLE_PAW_TAURIC)
worn_icon = 'icons/mob/clothing/taur_canine.dmi'
if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied.
if(S.taur_mob_worn_overlay) //not going to make several new variables for all taur types. Nope.
var/static/list/icon_to_state = list('icons/mob/clothing/taur_hooved.dmi' = "_hooved", 'icons/mob/clothing/taur_naga.dmi' = "_naga", 'icons/mob/clothing/taur_canine.dmi' = "_paws")
worn_state += icon_to_state[worn_icon]
worn_icon = S.taur_mob_worn_overlay
center = T.center
dimension_x = T.dimension_x
dimension_y = T.dimension_y
else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON)) //not a taur, but digitigrade legs.
worn_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/suit_digi.dmi'
var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi'
var/variation_flag = NONE
if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/feet_digi.dmi'
variation_flag |= STYLE_DIGITIGRADE
overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, worn_state, variation_flag, FALSE)
var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
if(OFFSET_SUIT in dna.species.offset_features)
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
if(center)
suit_overlay = center_image(suit_overlay, dimension_x, dimension_y)
overlays_standing[SUIT_LAYER] = suit_overlay
update_hair()
update_mutant_bodyparts()
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, S.icon_state, variation_flag, FALSE)
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
if(OFFSET_SHOES in dna.species.offset_features)
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
overlays_standing[SHOES_LAYER] = shoes_overlay
apply_overlay(SHOES_LAYER)
apply_overlay(SUIT_LAYER)
/mob/living/carbon/human/update_inv_s_store()
if(dna.species.should_render())
remove_overlay(SUIT_STORE_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
inv.update_icon()
if(s_store)
s_store.screen_loc = ui_sstore1
if(client && hud_used && hud_used.hud_shown)
client.screen += s_store
update_observer_view(s_store)
var/t_state = s_store.item_state
if(!t_state)
t_state = s_store.icon_state
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
if(OFFSET_S_STORE in dna.species.offset_features)
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
apply_overlay(SUIT_STORE_LAYER)
/mob/living/carbon/human/update_inv_head()
if(dna.species.should_render())
remove_overlay(HEAD_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv.update_icon()
if(head)
head.screen_loc = ui_head
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += head
update_observer_view(head,1)
remove_overlay(HEAD_LAYER)
var/obj/item/clothing/head/H = head
var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
var/muzzled = FALSE
var/variation_flag = NONE
if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
muzzled = TRUE
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
muzzled = TRUE
if(muzzled && H.mutantrace_variation & STYLE_MUZZLE && !(H.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = H.anthro_mob_worn_overlay || 'icons/mob/clothing/head_muzzled.dmi'
variation_flag |= STYLE_MUZZLE
overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE)
var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
if(OFFSET_HEAD in dna.species.offset_features)
head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
overlays_standing[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
if(dna.species.should_render())
remove_overlay(BELT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
inv.update_icon()
if(belt)
belt.screen_loc = ui_belt
if(client && hud_used && hud_used.hud_shown)
client.screen += belt
update_observer_view(belt)
overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi')
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
if(OFFSET_BELT in dna.species.offset_features)
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
overlays_standing[BELT_LAYER] = belt_overlay
apply_overlay(BELT_LAYER)
/mob/living/carbon/human/update_inv_wear_suit()
if(dna.species.should_render())
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
inv.update_icon()
if(wear_suit)
var/obj/item/clothing/suit/S = wear_suit
wear_suit.screen_loc = ui_oclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_suit
update_observer_view(wear_suit,1)
var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi'
var/worn_state = wear_suit.icon_state
var/center = FALSE
var/dimension_x = 32
var/dimension_y = 32
var/variation_flag = NONE
var/datum/sprite_accessory/taur/T
if(dna.species.mutant_bodyparts["taur"])
T = GLOB.taur_list[dna.features["taur"]]
if(S.mutantrace_variation)
if(T?.taur_mode)
var/init_worn_icon = worn_icon
variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode
switch(variation_flag)
if(STYLE_HOOF_TAURIC)
worn_icon = 'icons/mob/clothing/taur_hooved.dmi'
if(STYLE_SNEK_TAURIC)
worn_icon = 'icons/mob/clothing/taur_naga.dmi'
if(STYLE_PAW_TAURIC)
worn_icon = 'icons/mob/clothing/taur_canine.dmi'
if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied.
if(S.taur_mob_worn_overlay) //not going to make several new variables for all taur types. Nope.
var/static/list/icon_to_state = list('icons/mob/clothing/taur_hooved.dmi' = "_hooved", 'icons/mob/clothing/taur_naga.dmi' = "_naga", 'icons/mob/clothing/taur_canine.dmi' = "_paws")
worn_state += icon_to_state[worn_icon]
worn_icon = S.taur_mob_worn_overlay
center = T.center
dimension_x = T.dimension_x
dimension_y = T.dimension_y
else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON)) //not a taur, but digitigrade legs.
worn_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/suit_digi.dmi'
variation_flag |= STYLE_DIGITIGRADE
overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, worn_state, variation_flag, FALSE)
var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
if(OFFSET_SUIT in dna.species.offset_features)
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
if(center)
suit_overlay = center_image(suit_overlay, dimension_x, dimension_y)
overlays_standing[SUIT_LAYER] = suit_overlay
update_hair()
update_mutant_bodyparts()
apply_overlay(SUIT_LAYER)
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
@@ -471,55 +477,57 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_wear_mask()
remove_overlay(FACEMASK_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv.update_icon()
if(wear_mask)
wear_mask.screen_loc = ui_mask
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_mask
update_observer_view(wear_mask,1)
var/obj/item/clothing/mask/M = wear_mask
if(dna.species.should_render())
remove_overlay(FACEMASK_LAYER)
var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
var/muzzled = FALSE
var/variation_flag = NONE
if(head && (head.flags_inv & HIDEMASK))
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
muzzled = TRUE
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
muzzled = TRUE
if(muzzled && M.mutantrace_variation & STYLE_MUZZLE && !(M.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = M.anthro_mob_worn_overlay || 'icons/mob/clothing/mask_muzzled.dmi'
variation_flag |= STYLE_MUZZLE
var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv.update_icon()
if(OFFSET_FACEMASK in dna.species.offset_features)
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
overlays_standing[FACEMASK_LAYER] = mask_overlay
apply_overlay(FACEMASK_LAYER)
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
if(wear_mask)
wear_mask.screen_loc = ui_mask
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_mask
update_observer_view(wear_mask,1)
var/obj/item/clothing/mask/M = wear_mask
remove_overlay(FACEMASK_LAYER)
var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
var/muzzled = FALSE
var/variation_flag = NONE
if(head && (head.flags_inv & HIDEMASK))
return
if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
muzzled = TRUE
else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
muzzled = TRUE
if(muzzled && M.mutantrace_variation & STYLE_MUZZLE && !(M.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
alt_icon = M.anthro_mob_worn_overlay || 'icons/mob/clothing/mask_muzzled.dmi'
variation_flag |= STYLE_MUZZLE
var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE)
if(OFFSET_FACEMASK in dna.species.offset_features)
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
overlays_standing[FACEMASK_LAYER] = mask_overlay
apply_overlay(FACEMASK_LAYER)
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
..()
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
if(back_overlay)
remove_overlay(BACK_LAYER)
if(OFFSET_BACK in dna.species.offset_features)
back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
overlays_standing[BACK_LAYER] = back_overlay
apply_overlay(BACK_LAYER)
if(dna.species.should_render())
..()
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
if(back_overlay)
remove_overlay(BACK_LAYER)
if(OFFSET_BACK in dna.species.offset_features)
back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
overlays_standing[BACK_LAYER] = back_overlay
apply_overlay(BACK_LAYER)
/proc/wear_alpha_masked_version(state, icon, layer, female, alpha_mask)
var/mask = "-[alpha_mask]"
@@ -710,8 +718,6 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
..()
update_hair()
/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory)
if(observers && observers.len)
for(var/M in observers)
@@ -729,15 +735,17 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
// Only renders the head of the human
/mob/living/carbon/human/proc/update_body_parts_head_only()
if (!dna)
if(!dna)
return
if (!dna.species)
if(!dna.species)
return
if(dna.species.should_render())
return
var/obj/item/bodypart/HD = get_bodypart("head")
if (!istype(HD))
if(!istype(HD))
return
HD.update_limb()
@@ -748,7 +756,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
if(HD && !(HAS_TRAIT(src, TRAIT_HUSK)))
// lipstick
if(lip_style && (LIPS in dna.species.species_traits))
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER)
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[lip_style]", -BODY_LAYER)
lip_overlay.color = lip_color
if(OFFSET_LIPS in dna.species.offset_features)
lip_overlay.pixel_x += dna.species.offset_features[OFFSET_LIPS][1]
@@ -759,10 +767,17 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
if(!(NOEYES in dna.species.species_traits))
var/has_eyes = getorganslot(ORGAN_SLOT_EYES)
if(!has_eyes)
add_overlay(mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER))
add_overlay(mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER))
else
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/human_face.dmi', "left_eye", -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/human_face.dmi', "right_eye", -BODY_LAYER)
var/left_state = DEFAULT_LEFT_EYE_STATE
var/right_state = DEFAULT_RIGHT_EYE_STATE
if(dna.species)
var/eye_type = dna.species.eye_type
if(GLOB.eye_types[eye_type])
left_state = eye_type + "_left_eye"
right_state = eye_type + "_right_eye"
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER)
if((EYECOLOR in dna.species.species_traits) && has_eyes)
left_eye.color = "#" + left_eye_color
right_eye.color = "#" + right_eye_color
@@ -34,7 +34,7 @@
hair_hidden = 1
if(!hair_hidden)
if(!getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
overlays_standing[HAIR_LAYER] = mutable_appearance('icons/mob/human_face.dmi', "debrained", -HAIR_LAYER)
overlays_standing[HAIR_LAYER] = mutable_appearance('icons/mob/human_parts.dmi', "debrained", -HAIR_LAYER)
apply_overlay(HAIR_LAYER)
@@ -231,6 +231,7 @@
active_block_do_stamina_damage(owner, object, stamina_cost, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = damage - final_damage
block_return[BLOCK_RETURN_SET_DAMAGE_TO] = final_damage
block_return[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(1 - (final_damage / damage), 0, 1)
. = BLOCK_SHOULD_CHANGE_DAMAGE
if((final_damage <= 0) || (damage <= 0))
. |= BLOCK_SUCCESS //full block
+4 -1
View File
@@ -5,12 +5,15 @@
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
//Stuff like mobility flag updates, resting updates, etc.
//Force-set resting variable, without needing to resist/etc.
/mob/living/proc/set_resting(new_resting, silent = FALSE, updating = TRUE)
if(new_resting != resting)
if(resting && HAS_TRAIT(src, TRAIT_MOBILITY_NOREST)) //forcibly block resting from all sources - BE CAREFUL WITH THIS TRAIT
return
resting = new_resting
if(!silent)
to_chat(src, "<span class='notice'>You are now [resting? "resting" : "getting up"].</span>")
@@ -87,7 +90,7 @@
var/canstand_involuntary = conscious && !stat_softcrit && !knockdown && !chokehold && !paralyze && (ignore_legs || has_legs) && !(buckled && buckled.buckle_lying) && !(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)
var/canstand = canstand_involuntary && !resting
var/should_be_lying = !canstand
var/should_be_lying = !canstand && !HAS_TRAIT(src, TRAIT_MOBILITY_NOREST)
if(buckled)
if(buckled.buckle_lying != -1)
should_be_lying = buckled.buckle_lying
@@ -22,7 +22,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
icon_state = "magicbase"
icon_living = "magicbase"
icon_dead = "magicbase"
speed = 0
speed = -0.5
blood_volume = 0
a_intent = INTENT_HARM
stop_automated_movement = 1
@@ -511,7 +511,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/used_message = "<span class='holoparasite'>All the cards seem to be blank now.</span>"
var/failure_message = "<span class='holoparasite bold'>..And draw a card! It's...blank? Maybe you should try again later.</span>"
var/ling_failure = "<span class='holoparasite bold'>The deck refuses to respond to a souless creature such as you.</span>"
var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
var/list/possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
var/random = TRUE
var/allowmultiple = FALSE
var/allowling = TRUE
@@ -559,6 +559,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
if("Chaos")
pickedtype = /mob/living/simple_animal/hostile/guardian/fire
if("Gravitokinetic")
pickedtype = /mob/living/simple_animal/hostile/guardian/gravitokinetic
if("Standard")
pickedtype = /mob/living/simple_animal/hostile/guardian/punch
@@ -615,10 +618,10 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
random = FALSE
/obj/item/guardiancreator/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/guardiancreator/choose/wizard
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard")
possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard")
allowmultiple = TRUE
/obj/item/guardiancreator/tech
@@ -634,7 +637,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
ling_failure = "<span class='holoparasite bold'>The holoparasites recoil in horror. They want nothing to do with a creature like you.</span>"
/obj/item/guardiancreator/tech/choose/traitor
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
allowling = FALSE
/obj/item/guardiancreator/tech/choose/traitor/check_uplink_validity()
@@ -644,10 +647,10 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
random = FALSE
/obj/item/guardiancreator/tech/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/guardiancreator/tech/choose/nukie // lacks support and protector as encouraging nukies to play turtle isnt fun and dextrous is epic
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Ranged", "Standard")
possible_guardians = list("Assassin", "Chaos", "Gravitokinetic", "Charger", "Dextrous", "Explosive", "Lightning", "Ranged", "Standard")
/obj/item/guardiancreator/tech/choose/nukie/check_uplink_validity()
return !used
@@ -666,6 +669,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
<br>
<b>Explosive</b>: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.<br>
<br>
<b>Gravitokinetic</b>: Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user.<br>
<br>
<b>Lightning</b>: Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage.<br>
<br>
<b>Protector</b>: Causes you to teleport to it when out of range, unlike other parasites. Has two modes; Combat, where it does and takes medium damage, and Protection, where it does and takes almost no damage but moves slightly slower.<br>
@@ -695,6 +700,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
<br>
<b>Explosive</b>: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.<br>
<br>
<b>Gravitokinetic</b>: Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user.<br>
<br>
<b>Lightning</b>: Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage.<br>
<br>
<b>Protector</b>: Causes you to teleport to it when out of range, unlike other parasites. Has two modes; Combat, where it does and takes medium damage, and Protection, where it does and takes almost no damage but moves slightly slower.<br>
@@ -720,6 +727,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
<br>
<b>Explosive</b>: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.<br>
<br>
<b>Gravitokinetic</b>: Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user.<br>
<br>
<b>Lightning</b>: Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage.<br>
<br>
<b>Ranged</b>: Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; Cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode.<br>
@@ -1,5 +1,7 @@
//Assassin
/mob/living/simple_animal/hostile/guardian/assassin
melee_damage_lower = 15
melee_damage_upper = 15
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
@@ -1,8 +1,11 @@
//Charger
/mob/living/simple_animal/hostile/guardian/charger
melee_damage_lower = 15
melee_damage_upper = 15
ranged = 1 //technically
ranged_message = "charges"
ranged_cooldown_time = 20
speed = -1
damage_coeff = list(BRUTE = 0.2, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5)
playstyle_string = "<span class='holoparasite'>As a <b>charger</b> type you do medium damage, take half damage, have near immunity to brute damage, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Hunter, an alien master of rapid assault.</span>"
@@ -1,5 +1,7 @@
//Bomb
/mob/living/simple_animal/hostile/guardian/bomb
melee_damage_lower = 15
melee_damage_upper = 15
damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6)
playstyle_string = "<span class='holoparasite'>As an <b>explosive</b> type, you have moderate close combat abilities, take half damage, may explosively teleport targets on attack, and are capable of converting nearby items and objects into disguised bombs via alt click.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Scientist, master of explosive death.</span>"
@@ -0,0 +1,73 @@
//gravitokinetic
/mob/living/simple_animal/hostile/guardian/gravitokinetic
melee_damage_lower = 15
melee_damage_upper = 15
damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75)
playstyle_string = "<span class='holoparasite'>As a <b>gravitokinetic</b> type, you can alt click to make the gravity on the ground stronger, and punching applies this effect to a target.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Singularity, an anomalous force of terror.</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Gravitokinetic modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one! It's a gravitokinetic carp! Now do you understand the gravity of the situation?</span>"
var/list/gravito_targets = list()
var/gravity_power_range = 10 //how close the stand must stay to the target to keep the heavy gravity
///Removes gravity from affected mobs upon guardian death to prevent permanent effects
/mob/living/simple_animal/hostile/guardian/gravitokinetic/death()
. = ..()
for(var/i in gravito_targets)
remove_gravity(i)
/mob/living/simple_animal/hostile/guardian/gravitokinetic/AttackingTarget()
. = ..()
if(isliving(target) && target != src && target != summoner)
to_chat(src, "<span class='danger'><B>Your punch has applied heavy gravity to [target]!</span></B>")
add_gravity(target, 5)
to_chat(target, "<span class='userdanger'>Everything feels really heavy!</span>")
/mob/living/simple_animal/hostile/guardian/gravitokinetic/AltClickOn(atom/A)
if(isopenturf(A) && is_deployed() && stat != DEAD && in_range(src, A) && !incapacitated())
var/turf/T = A
if(isspaceturf(T))
to_chat(src, "<span class='warning'>You cannot add gravity to space!</span>")
return
visible_message("<span class='danger'>[src] slams their fist into the [T]!</span>", "<span class='notice'>You modify the gravity of the [T].</span>")
do_attack_animation(T)
add_gravity(T, 3)
return
return ..()
/mob/living/simple_animal/hostile/guardian/gravitokinetic/Recall(forced)
. = ..()
to_chat(src, "<span class='danger'><B>You have released your gravitokinetic powers!</span></B>")
for(var/i in gravito_targets)
remove_gravity(i)
/mob/living/simple_animal/hostile/guardian/gravitokinetic/Manifest(forced)
. = ..()
//just make sure to reapply a gravity immunity wherever you summon. it can be overridden but not by you at least
summoner.AddElement(/datum/element/forced_gravity, 1)
AddElement(/datum/element/forced_gravity, 1)
/mob/living/simple_animal/hostile/guardian/gravitokinetic/Moved(oldLoc, dir)
. = ..()
for(var/i in gravito_targets)
if(get_dist(src, i) > gravity_power_range)
remove_gravity(i)
/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/add_gravity(atom/A, new_gravity = 3)
if(gravito_targets[A])
return
A.AddElement(/datum/element/forced_gravity, new_gravity)
gravito_targets[A] = new_gravity
RegisterSignal(A, COMSIG_MOVABLE_MOVED, .proc/__distance_check)
playsound(src, 'sound/effects/gravhit.ogg', 100, TRUE)
/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/remove_gravity(atom/target)
if(isnull(gravito_targets[target]))
return
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
target.RemoveElement(/datum/element/forced_gravity, gravito_targets[target])
gravito_targets -= target
/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/__distance_check(atom/movable/AM, OldLoc, Dir, Forced)
if(get_dist(src, AM) > gravity_power_range)
remove_gravity(AM)
@@ -1,5 +1,7 @@
//Protector
/mob/living/simple_animal/hostile/guardian/protector
melee_damage_lower = 15
melee_damage_upper = 15
range = 15 //worse for it due to how it leashes
damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4)
playstyle_string = "<span class='holoparasite'>As a <b>protector</b> type you cause your summoner to leash to you instead of you leashing to them and have two modes; Combat Mode, where you do and take medium damage, and Protection Mode, where you do and take almost no damage, but move slightly slower.</span>"
@@ -31,9 +33,10 @@
cooldown = world.time + 10
if(toggle)
cut_overlays()
melee_damage_lower = 15
melee_damage_upper = 15
speed = 0
add_overlay(cooloverlay) //readd the guardian's colors
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
speed = initial(speed)
damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4)
to_chat(src, "<span class='danger'><B>You switch to combat mode.</span></B>")
toggle = FALSE
@@ -4,6 +4,8 @@
friendly_verb_continuous = "heals"
friendly_verb_simple = "heal"
damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
melee_damage_lower = 15
melee_damage_upper = 15
playstyle_string = "<span class='holoparasite'>As a <b>support</b> type, you have 30% damage reduction and may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the CMO, a potent force of life... and death.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! You caught a support carp. It's a kleptocarp!</span>"
@@ -43,15 +45,15 @@
if(src.loc == summoner)
if(toggle)
a_intent = INTENT_HARM
speed = 0
speed = initial(speed)
damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
melee_damage_lower = 15
melee_damage_upper = 15
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
to_chat(src, "<span class='danger'><B>You switch to combat mode.</span></B>")
toggle = FALSE
else
a_intent = INTENT_HELP
speed = 1
speed = initial(speed)
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
melee_damage_lower = 0
melee_damage_upper = 0
@@ -52,6 +52,19 @@
var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach
var/lose_patience_timeout = 300 //30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever
///When a target is found, will the mob attempt to charge at it's target?
var/charger = FALSE
///Tracks if the target is actively charging.
var/charge_state = FALSE
///In a charge, how many tiles will the charger travel?
var/charge_distance = 3
///How often can the charging mob actually charge? Effects the cooldown between charges.
var/charge_frequency = 6 SECONDS
///If the mob is charging, how long will it stun it's target on success, and itself on failure?
var/knockdown_time = 3 SECONDS
///Declares a cooldown for potential charges right off the bat.
COOLDOWN_DECLARE(charge_cooldown)
/mob/living/simple_animal/hostile/Initialize()
. = ..()
@@ -292,6 +305,9 @@
if(ranged) //We ranged? Shoot at em
if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown
OpenFire(target)
if(charger && (target_distance > minimum_distance) && (target_distance <= charge_distance))//Attempt to close the distance with a charge.
enter_charge(target)
return TRUE
if(!Process_Spacemove()) //Drifting
walk(src,0)
return 1
@@ -599,3 +615,64 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
. += M
else if (M.loc.type in hostile_machines)
. += M.loc
/**
* Proc that handles a charge attack windup for a mob.
*/
/mob/living/simple_animal/hostile/proc/enter_charge(var/atom/target)
if((mobility_flags & (MOBILITY_MOVE | MOBILITY_STAND)) != (MOBILITY_MOVE | MOBILITY_STAND) || charge_state)
return FALSE
if(!(COOLDOWN_FINISHED(src, charge_cooldown)) || !has_gravity() || !target.has_gravity())
return FALSE
Shake(15, 15, 1 SECONDS)
addtimer(CALLBACK(src, .proc/handle_charge_target, target), 1.5 SECONDS, TIMER_STOPPABLE)
/**
* Proc that throws the mob at the target after the windup.
*/
/mob/living/simple_animal/hostile/proc/handle_charge_target(var/atom/target)
charge_state = TRUE
throw_at(target, charge_distance, 1, src, FALSE, TRUE, callback = CALLBACK(src, .proc/charge_end))
COOLDOWN_START(src, charge_cooldown, charge_frequency)
return TRUE
/**
* Proc that handles a charge attack after it's concluded.
*/
/mob/living/simple_animal/hostile/proc/charge_end()
charge_state = FALSE
/**
* Proc that handles the charge impact of the charging mob.
*/
/mob/living/simple_animal/hostile/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!charge_state)
return ..()
if(hit_atom)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
var/blocked = FALSE
if(ishuman(hit_atom))
var/mob/living/carbon/human/H = hit_atom
var/list/return_list = list()
if(H.mob_run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src, null, return_list) & BLOCK_SUCCESS)
blocked = TRUE
if(!blocked)
blocked = return_list[BLOCK_RETURN_MITIGATION_PERCENT]
if(!blocked)
L.visible_message("<span class='danger'>[src] charges on [L]!</span>", "<span class='userdanger'>[src] charges into you!</span>")
L.Knockdown(knockdown_time)
else
Stun((knockdown_time * 2), 1, 1)
charge_end()
else if(hit_atom.density && !hit_atom.CanPass(src))
visible_message("<span class='danger'>[src] smashes into [hit_atom]!</span>")
Stun((knockdown_time * 2), 1, 1)
if(charge_state)
charge_state = FALSE
update_icons()
update_mobility()
@@ -0,0 +1,42 @@
/**
* Lobstrosities, the poster boy of charging AI mobs. Drops crab meat and bones.
* Outside of charging, it's intended behavior is that it is generally slow moving, but makes up for that with a knockdown attack to score additional hits.
*/
/mob/living/simple_animal/hostile/asteroid/lobstrosity
name = "arctic lobstrosity"
desc = "A marvel of evolution gone wrong, the frosty ice produces underground lakes where these ill tempered seafood gather. Beware its charge."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "arctic_lobstrosity"
icon_living = "arctic_lobstrosity"
icon_dead = "arctic_lobstrosity_dead"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
friendly_verb_continuous = "chitters at"
friendly_verb_simple = "chits at"
speak_emote = list("chitters")
speed = 3
move_to_delay = 20
maxHealth = 150
health = 150
obj_damage = 15
melee_damage_lower = 15
melee_damage_upper = 19
attack_verb_continuous = "snips"
attack_verb_simple = "snip"
attack_sound = 'sound/weapons/bite.ogg'
weather_immunities = list("snow")
vision_range = 5
aggro_vision_range = 7
charger = TRUE
charge_distance = 4
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/crab = 2, /obj/item/stack/sheet/bone = 2)
robust_searching = TRUE
footstep_type = FOOTSTEP_MOB_CLAW
gold_core_spawnable = HOSTILE_SPAWN
/mob/living/simple_animal/hostile/asteroid/lobstrosity/lava
name = "tropical lobstrosity"
desc = "A marvel of evolution gone wrong, the sulfur lakes of lavaland have given them a vibrant, red hued shell. Beware its charge."
icon_state = "lobstrosity"
icon_living = "lobstrosity"
icon_dead = "lobstrosity_dead"
@@ -59,12 +59,12 @@
/mob/living/simple_animal/hostile/retaliate/ghost/proc/give_hair()
if(ghost_hair_style != null)
ghost_hair = mutable_appearance('icons/mob/human_face.dmi', "hair_[ghost_hair_style]", -HAIR_LAYER)
ghost_hair = mutable_appearance('icons/mob/hair.dmi', "hair_[ghost_hair_style]", -HAIR_LAYER)
ghost_hair.alpha = 200
ghost_hair.color = ghost_hair_color
add_overlay(ghost_hair)
if(ghost_facial_hair_style != null)
ghost_facial_hair = mutable_appearance('icons/mob/human_face.dmi', "facial_[ghost_facial_hair_style]", -HAIR_LAYER)
ghost_facial_hair = mutable_appearance('icons/mob/hair.dmi', "facial_[ghost_facial_hair_style]", -HAIR_LAYER)
ghost_facial_hair.alpha = 200
ghost_facial_hair.color = ghost_facial_hair_color
add_overlay(ghost_facial_hair)
@@ -6,6 +6,7 @@
gender = PLURAL //placeholder
///How much blud it has for bloodsucking
blood_volume = 550
rad_flags = RAD_NO_CONTAMINATE
status_flags = CANPUSH
+1 -2
View File
@@ -39,8 +39,7 @@
update_client_colour()
update_mouse_pointer()
if(client)
client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed.
client.view_size?.resetToDefault()
if(client.player_details && istype(client.player_details))
if(client.player_details.player_actions.len)
for(var/datum/action/A in client.player_details.player_actions)
+1
View File
@@ -39,6 +39,7 @@
. = ..()
update_config_movespeed()
update_movespeed(TRUE)
initialize_actionspeed()
hook_vr("mob_new",list(src))
/mob/GenerateTag()
+7
View File
@@ -58,6 +58,13 @@
var/list/movespeed_mod_immunities //Lazy list, see mob_movespeed.dm
/// The calculated mob speed slowdown based on the modifiers list
var/cached_multiplicative_slowdown
/// List of action speed modifiers applying to this mob
var/list/actionspeed_modification //Lazy list, see mob_movespeed.dm
/// List of action speed modifiers ignored by this mob. List -> List (id) -> List (sources)
var/list/actionspeed_mod_immunities //Lazy list, see mob_movespeed.dm
/// The calculated mob action speed slowdown based on the modifiers list
var/cached_multiplicative_actions_slowdown
/////////////////
var/name_archive //For admin things like possession