Merge conflict fix

This commit is contained in:
Artur
2020-05-13 12:37:18 +03:00
985 changed files with 295527 additions and 16121 deletions
@@ -392,6 +392,8 @@
character.update_parallax_teleport()
job.standard_assign_skills(character.mind)
SSticker.minds += character.mind
var/mob/living/carbon/human/humanc
@@ -18,16 +18,10 @@
hair_color = random_short_color()
facial_hair_color = hair_color
eye_color = random_eye_color()
horn_color = "85615a"
wing_color = "fff"
if(!pref_species)
var/rando_race = pick(GLOB.roundstart_races)
pref_species = new rando_race()
features = random_features(pref_species?.id)
if(gender == MALE || gender != FEMALE)
features["body_model"] = gender
else if(gender == PLURAL)
features["body_model"] = pick(MALE,FEMALE)
features = random_features(pref_species?.id, gender)
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(equip_job = TRUE)
@@ -16,6 +16,7 @@
from doing this unless you absolutely know what you are doing, and have defined a
conversion in savefile.dm
*/
/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female, roundstart = FALSE, skip_prototype = TRUE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked
if(!istype(L))
L = list()
@@ -55,19 +56,19 @@
var/gender = NEUTER //Determines if the accessory will be skipped or included in random hair generations
var/gender_specific //Something that can be worn by either gender, but looks different on each
var/color_src = MUTCOLORS //Currently only used by mutantparts so don't worry about hair and stuff. This is the source that this accessory will get its color from. Default is MUTCOLOR, but can also be HAIR, FACEHAIR, EYECOLOR and 0 if none.
var/hasinner //Decides if this sprite has an "inner" part, such as the fleshy parts on ears.
var/locked = FALSE //Is this part locked from roundstart selection? Used for parts that apply effects
var/dimension_x = 32
var/dimension_y = 32
var/center = FALSE //Should we center the sprite?
var/list/relevant_layers //list of layers that this accessory uses. As of now only used in species.handle_mutant_bodyparts(), but that's where most sprite accessories are anyway.
var/mutant_part_string //Also used in species.handle_mutant_bodyparts() to generate the overlay icon state.
var/alpha_mask_state
//Special / holdover traits for Citadel specific sprites.
var/extra = FALSE
var/extra_color_src = MUTCOLORS2 //The color source for the extra overlay.
var/extra_icon = 'modular_citadel/icons/mob/mam_tails.dmi'
var/extra2 = FALSE
var/extra2_color_src = MUTCOLORS3
var/extra2_icon = 'modular_citadel/icons/mob/mam_tails.dmi'
//for snowflake/donor specific sprites
var/list/ckeys_allowed
@@ -4,6 +4,8 @@
*******************************************/
/datum/sprite_accessory/xeno_dorsal
icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi'
mutant_part_string = "xenodorsal"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/xeno_dorsal/standard
name = "Standard"
@@ -22,9 +24,12 @@
*******************************************/
/datum/sprite_accessory/xeno_tail
icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi'
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/xeno_tail/none
name = "None"
relevant_layers = null
/datum/sprite_accessory/xeno_tail/standard
name = "Xenomorph Tail"
@@ -35,6 +40,8 @@
*******************************************/
/datum/sprite_accessory/xeno_head
icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi'
mutant_part_string = "xhead"
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/xeno_head/standard
name = "Standard"
@@ -4,10 +4,12 @@
/datum/sprite_accessory/body_markings
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/body_markings/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/body_markings/dtiger
name = "Dark Tiger Body"
@@ -45,6 +47,7 @@
icon_state = "none"
ckeys_allowed = list("yousshouldnteverbeseeingthisyoumeme")
icon = 'modular_citadel/icons/mob/markings_notmammals.dmi'
relevant_layers = null
/datum/sprite_accessory/mam_body_markings/plain
name = "Plain"
@@ -219,10 +222,12 @@
/datum/sprite_accessory/insect_fluff
icon = 'icons/mob/wings.dmi'
color_src = 0
relevant_layers = list(BODY_FRONT_LAYER)
/datum/sprite_accessory/insect_fluff/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_fluff/plain
name = "Plain"
@@ -1,7 +1,8 @@
datum/sprite_accessory/caps
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HAIR
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/caps/round
name = "Round"
icon_state = "round"
icon_state = "round"
@@ -1,9 +1,12 @@
/datum/sprite_accessory/ears
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "ears"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/ears/none
name = "None"
icon_state = "none"
relevant_layers = null
/******************************************
*************** Human Ears ****************
@@ -29,9 +32,10 @@
/datum/sprite_accessory/ears/human/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
hasinner = 1
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/ears/human/bigwolfdark
name = "Dark Big Wolf"
@@ -42,15 +46,17 @@
/datum/sprite_accessory/ears/human/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
hasinner = 1
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/ears/cat
name = "Cat"
icon_state = "cat"
hasinner = 1
color_src = HAIR
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/ears/human/cow
name = "Cow"
@@ -172,10 +178,13 @@
/datum/sprite_accessory/mam_ears
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
mutant_part_string = "ears"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/mam_ears/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/mam_ears/axolotl
name = "Axolotl"
@@ -196,7 +205,8 @@
/datum/sprite_accessory/mam_ears/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
hasinner = 1
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/mam_ears/bigwolfdark
name = "Dark Big Wolf"
@@ -205,13 +215,16 @@
/datum/sprite_accessory/mam_ears/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
hasinner = 1
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/mam_ears/cat
name = "Cat"
icon_state = "cat"
hasinner = 1
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HAIR
extra = TRUE
extra_color_src = NONE
/datum/sprite_accessory/mam_ears/catbig
name = "Cat, Big"
@@ -309,4 +322,4 @@
/datum/sprite_accessory/mam_ears/bunny
name = "Bunny"
icon_state = "bunny"
icon_state = "bunny"
@@ -1,9 +1,11 @@
/datum/sprite_accessory/frills
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/frills/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/frills/simple
name = "Simple"
@@ -15,4 +17,4 @@
/datum/sprite_accessory/frills/aquatic
name = "Aquatic"
icon_state = "aqua"
icon_state = "aqua"
@@ -1,10 +1,12 @@
/datum/sprite_accessory/horns
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HORNCOLOR
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/horns/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/horns/simple
name = "Simple"
@@ -33,4 +35,4 @@
/datum/sprite_accessory/horns/guilmon
name = "Guilmon"
icon_state = "guilmon"
icon_state = "guilmon"
@@ -5,6 +5,7 @@
/datum/sprite_accessory/screen
icon = 'modular_citadel/icons/mob/ipc_screens.dmi'
color_src = null
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/screen/blank
name = "Blank"
@@ -132,6 +133,7 @@
/datum/sprite_accessory/antenna
icon = 'modular_citadel/icons/mob/ipc_antennas.dmi'
color_src = MUTCOLORS2
relevant_layers = list(BODY_ADJ_LAYER)
recommended_species = list("ipc")
/datum/sprite_accessory/antenna/none
@@ -21,29 +21,42 @@
/datum/sprite_accessory/taur
icon = 'modular_citadel/icons/mob/mam_taur.dmi'
extra_icon = 'modular_citadel/icons/mob/mam_taur.dmi'
extra = TRUE
extra2_icon = 'modular_citadel/icons/mob/mam_taur.dmi'
extra2 = TRUE
center = TRUE
dimension_x = 64
var/taur_mode = NONE //Must be a single specific tauric suit variation bitflag. Don't do FLAG_1|FLAG_2
var/alt_taur_mode = NONE //Same as above.
color_src = MATRIXED
recommended_species = list("human", "lizard", "insect", "mammal", "xeno", "jelly", "slimeperson", "podweak")
relevant_layers = list(BODY_ADJ_UPPER_LAYER, BODY_FRONT_LAYER)
var/taur_mode = NONE //Must be a single specific tauric suit variation bitflag. Don't do FLAG_1|FLAG_2
var/alt_taur_mode = NONE //Same as above.
var/hide_legs = USE_QUADRUPED_CLIP_MASK
/datum/sprite_accessory/taur/New()
switch(hide_legs)
if(USE_QUADRUPED_CLIP_MASK)
alpha_mask_state = "taur_mask_def"
if(USE_SNEK_CLIP_MASK)
alpha_mask_state = "taur_mask_naga"
/datum/sprite_accessory/taur/none
dimension_x = 32
center = FALSE
name = "None"
icon_state = "None"
dimension_x = 32
center = FALSE
recommended_species = null
relevant_layers = null
hide_legs = FALSE
/datum/sprite_accessory/taur/cow
name = "Cow"
icon_state = "cow"
taur_mode = STYLE_HOOF_TAURIC
alt_taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
/datum/sprite_accessory/taur/cow/spotted
name = "Cow (Spotted)"
icon_state = "cow_spotted"
color_src = MATRIXED
/datum/sprite_accessory/taur/deer
name = "Deer"
@@ -56,27 +69,21 @@
name = "Drake"
icon_state = "drake"
taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
extra = TRUE
/datum/sprite_accessory/taur/drider
name = "Drider"
icon_state = "drider"
color_src = MUTCOLORS
extra = TRUE
/datum/sprite_accessory/taur/eevee
name = "Eevee"
icon_state = "eevee"
taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
/datum/sprite_accessory/taur/fox
name = "Fox"
icon_state = "fox"
taur_mode = STYLE_PAW_TAURIC
/datum/sprite_accessory/taur/husky
name = "Husky"
icon_state = "husky"
taur_mode = STYLE_PAW_TAURIC
extra = TRUE
/datum/sprite_accessory/taur/horse
name = "Horse"
@@ -84,15 +91,11 @@
taur_mode = STYLE_HOOF_TAURIC
alt_taur_mode = STYLE_PAW_TAURIC
/datum/sprite_accessory/taur/lab
name = "Lab"
icon_state = "lab"
taur_mode = STYLE_PAW_TAURIC
/datum/sprite_accessory/taur/naga
name = "Naga"
icon_state = "naga"
taur_mode = STYLE_SNEK_TAURIC
hide_legs = USE_SNEK_CLIP_MASK
/datum/sprite_accessory/taur/otie
name = "Otie"
@@ -104,29 +107,26 @@
icon_state = "pede"
taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
/datum/sprite_accessory/taur/panther
name = "Panther"
icon_state = "panther"
taur_mode = STYLE_PAW_TAURIC
/datum/sprite_accessory/taur/shepherd
name = "Shepherd"
icon_state = "shepherd"
taur_mode = STYLE_PAW_TAURIC
extra = TRUE
extra2 = TRUE
/datum/sprite_accessory/taur/tentacle
name = "Tentacle"
icon_state = "tentacle"
taur_mode = STYLE_SNEK_TAURIC
color_src = MUTCOLORS
hide_legs = USE_SNEK_CLIP_MASK
/datum/sprite_accessory/taur/tiger
name = "Tiger"
icon_state = "tiger"
/datum/sprite_accessory/taur/canine
name = "Canine"
icon_state = "canine"
taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
extra = TRUE
/datum/sprite_accessory/taur/wolf
name = "Wolf"
icon_state = "wolf"
/datum/sprite_accessory/taur/feline
name = "Feline"
icon_state = "feline"
taur_mode = STYLE_PAW_TAURIC
color_src = MUTCOLORS
extra = TRUE
@@ -1,5 +1,7 @@
/datum/sprite_accessory/snouts
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/snouts/sharp
name = "Sharp"
@@ -152,11 +154,14 @@
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_snouts.dmi'
recommended_species = list("mammal", "slimeperson", "insect", "podweak")
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/mam_snouts/none
name = "None"
icon_state = "none"
recommended_species = null
relevant_layers = null
/datum/sprite_accessory/mam_snouts/bird
name = "Beak"
@@ -383,4 +388,4 @@
/datum/sprite_accessory/mam_snouts/froundlight
name = "Round + Light (Top)"
icon_state = "froundlight"
color_src = MUTCOLORS
color_src = MUTCOLORS
@@ -1,12 +1,15 @@
/datum/sprite_accessory/spines
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER)
/datum/sprite_accessory/spines_animated
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER)
/datum/sprite_accessory/spines/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/spines_animated/none
name = "None"
@@ -50,4 +53,4 @@
/datum/sprite_accessory/spines_animated/aqautic
name = "Aquatic"
icon_state = "aqua"
icon_state = "aqua"
@@ -1,8 +1,12 @@
/datum/sprite_accessory/tails
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/tails_animated
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "tailwag"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/******************************************
************* Lizard Tails ****************
@@ -43,10 +47,12 @@
/datum/sprite_accessory/tails/lizard/none
name = "None"
icon_state = "None"
relevant_layers = null
/datum/sprite_accessory/tails_animated/lizard/none
name = "None"
icon_state = "None"
relevant_layers = null
/datum/sprite_accessory/tails/lizard/axolotl
name = "Axolotl"
@@ -85,10 +91,12 @@
/datum/sprite_accessory/tails/human/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/tails_animated/human/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/tails/human/ailurus
name = "Red Panda"
@@ -502,20 +510,25 @@
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
recommended_species = list("mammal", "slimeperson", "podweak", "felinid", "insect")
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/mam_tails/none
name = "None"
icon_state = "none"
recommended_species = null
relevant_layers = null
/datum/sprite_accessory/mam_tails_animated
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
mutant_part_string = "tailwag"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/mam_tails_animated/none
name = "None"
icon_state = "none"
color_src = MATRIXED
relevant_layers = null
/datum/sprite_accessory/mam_tails/ailurus
name = "Red Panda"
@@ -576,7 +589,7 @@
/datum/sprite_accessory/mam_tails_animated/catbig
name = "Cat, Big"
icon_state = "catbig"
/datum/sprite_accessory/mam_tails/twocat
name = "Cat, Double"
icon_state = "twocat"
@@ -3,9 +3,11 @@
/datum/sprite_accessory/wings/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/wings_open
icon = 'icons/mob/wings.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/wings_open/angel
name = "Angel"
@@ -17,6 +19,7 @@
/datum/sprite_accessory/wings
icon = 'icons/mob/wings.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/wings/angel
name = "Angel"
@@ -32,10 +35,13 @@
/datum/sprite_accessory/deco_wings
icon = 'icons/mob/wings.dmi'
color_src = WINGCOLOR
mutant_part_string = "insect_wings"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/deco_wings/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/deco_wings/angel
name = "Angel"
@@ -44,6 +50,7 @@
dimension_x = 46
center = TRUE
dimension_y = 34
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
@@ -130,10 +137,12 @@
/datum/sprite_accessory/insect_wings
icon = 'icons/mob/wings.dmi'
color_src = WINGCOLOR
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/insect_wings/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_wings/bat
name = "Bat"
@@ -231,10 +240,12 @@
/datum/sprite_accessory/insect_markings // Extra markings for insects ported from tg.
icon = 'icons/mob/insect_markings.dmi'
color_src = null
relevant_layers = list(BODY_ADJ_LAYER)
/datum/sprite_accessory/insect_markings/none
name = "None"
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_markings/reddish
name = "Reddish"
@@ -290,4 +301,4 @@
/datum/sprite_accessory/insect_markings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
icon_state = "witchwing"
+18 -1
View File
@@ -570,7 +570,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
views |= i
var/new_view = input("Choose your new view", "Modify view range", 7) as null|anything in views
if(new_view)
client.change_view(CLAMP(new_view, 7, max_view))
client.change_view(clamp(new_view, 7, max_view))
else
client.change_view(CONFIG_GET(string/default_view))
@@ -937,3 +937,20 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
spawners_menu = new(src)
spawners_menu.ui_interact(src)
/mob/dead/observer/verb/game_info()
set name = "Game info"
set desc = "Shows various info relating to the game mode, antagonists etc."
set category = "Ghost"
if(!started_as_observer && can_reenter_corpse)
to_chat(src, "You cannot see this info unless you are an observer or you've chosen Do Not Resuscitate!")
return
var/list/stuff = list("[SSticker.mode.name]")
stuff += "Antagonists:\n"
for(var/datum/antagonist/A in GLOB.antagonists)
if(A.owner)
stuff += "[A.owner] the [A.name]"
var/ghost_info = SSticker.mode.ghost_info()
if(ghost_info)
stuff += ghost_info
to_chat(src,stuff.Join("\n"))
+3
View File
@@ -33,6 +33,9 @@
else
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Create map text prior to modifying message for goonchat
if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker)))
create_chat_message(speaker, message_language, raw_message, spans, message_mode)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)
to_chat(src, "[link] [message]")
+2 -1
View File
@@ -333,7 +333,8 @@
I.moveToNullspace()
else
I.forceMove(newloc)
I.dropped(src)
if(I.dropped(src) == ITEM_RELOCATED_BY_DROPPED)
return FALSE
return TRUE
//Outdated but still in use apparently. This should at least be a human proc.
+11 -17
View File
@@ -229,7 +229,7 @@
var/adjusted_amount
if(amount >= 0 && maximum)
var/brainloss = get_brain_damage()
var/new_brainloss = CLAMP(brainloss + amount, 0, maximum)
var/new_brainloss = clamp(brainloss + amount, 0, maximum)
if(brainloss > new_brainloss) //brainloss is over the cap already
return 0
adjusted_amount = new_brainloss - brainloss
@@ -245,23 +245,17 @@
. = adjusted_amount
*/
/obj/item/organ/brain/on_life()
if(damage >= BRAIN_DAMAGE_DEATH) //rip
to_chat(owner, "<span class='userdanger'>The last spark of life in your brain fizzles out...</span>")
owner.death()
brain_death = TRUE
return
..()
/obj/item/organ/brain/on_death()
if(damage <= BRAIN_DAMAGE_DEATH) //rip
brain_death = FALSE
..()
/obj/item/organ/brain/applyOrganDamage(var/d, var/maximum = maxHealth)
..()
. = ..()
if(!. || !owner)
return
if(damage >= BRAIN_DAMAGE_DEATH) //rip
if(owner.stat != DEAD)
to_chat(owner, "<span class='userdanger'>The last spark of life in your brain fizzles out...</span>")
owner.death()
brain_death = TRUE
else
brain_death = FALSE
/obj/item/organ/brain/check_damage_thresholds(mob/M)
. = ..()
-7
View File
@@ -25,10 +25,3 @@
/mob/living/brain/treat_message(message)
message = capitalize(message)
return message
/mob/living/brain/could_speak_in_language(datum/language/dt)
if(istype(container, /obj/item/mmi/posibrain/soul_vessel))
// soul vessels can only speak ratvarian.
. = ispath(dt, /datum/language/ratvar)
else
. = ..()
@@ -12,6 +12,13 @@
bubble_icon = "alien"
type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
/// How much brute damage without armor piercing they do against mobs in melee
var/meleeSlashHumanPower = 20
/// How much power they have for DefaultCombatKnockdown when attacking humans
var/meleeKnockdownPower = 100
/// How much brute damage they do to simple animals
var/meleeSlashSAPower = 35
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
@@ -4,6 +4,7 @@
maxHealth = 125
health = 125
icon_state = "aliend"
meleeKnockdownPower = 80
/mob/living/carbon/alien/humanoid/drone/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
@@ -1,9 +1,12 @@
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
maxHealth = 125
health = 125
maxHealth = 170
health = 170
icon_state = "alienh"
meleeKnockdownPower = 75
meleeSlashHumanPower = 20
meleeSlashSAPower = 45
var/obj/screen/leap_icon = null
/mob/living/carbon/alien/humanoid/hunter/create_internal_organs()
@@ -63,11 +66,12 @@
if(hit_atom)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
if(L.run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
if(L.mob_run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src, null, null) & BLOCK_SUCCESS)
DefaultCombatKnockdown(40, 1, 1)
else
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.DefaultCombatKnockdown(100)
L.Stagger(4 SECONDS)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
@@ -1,9 +1,10 @@
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
maxHealth = 150
health = 150
maxHealth = 140
health = 140
icon_state = "aliens"
meleeSlashHumanPower = 15
/mob/living/carbon/alien/humanoid/sentinel/Initialize()
AddAbility(new /obj/effect/proc_holder/alien/sneak)
@@ -112,7 +112,6 @@
return A
return FALSE
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
@@ -1,4 +1,3 @@
/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling))
devour_mob(pulling, devour_time = 60)
@@ -1,5 +1,3 @@
/mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
@@ -11,6 +11,10 @@
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 20, /obj/item/stack/sheet/animalhide/xeno = 3)
meleeKnockdownPower = 125
meleeSlashHumanPower = 30
meleeSlashSAPower = 60
var/alt_inhands_file = 'icons/mob/alienqueen.dmi'
/mob/living/carbon/alien/humanoid/royal/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE)
@@ -6,6 +6,7 @@
mob_size = MOB_SIZE_SMALL
density = FALSE
hud_type = /datum/hud/larva
mouse_opacity = MOUSE_OPACITY_OPAQUE
maxHealth = 25
health = 25
@@ -77,6 +77,9 @@
alien_powers = list(/obj/effect/proc_holder/alien/transfer)
/obj/item/organ/alien/plasmavessel/on_life()
. = ..()
if(!.)
return
//If there are alien weeds on the ground then heal if needed or give some plasma
if(locate(/obj/structure/alien/weeds) in owner.loc)
if(owner.health >= owner.maxHealth)
@@ -23,6 +23,8 @@
/obj/item/organ/body_egg/alien_embryo/on_life()
. = ..()
if(!owner)
return
switch(stage)
if(2, 3)
if(prob(2))
@@ -20,5 +20,5 @@
/mob/living/carbon/alien/AdjustStun(amount, updating = 1, ignore_canstun = 0)
. = ..()
if(!.)
move_delay_add = CLAMP(move_delay_add + round(amount/2), 0, 10)
move_delay_add = clamp(move_delay_add + round(amount/2), 0, 10)
*/
+15 -5
View File
@@ -7,6 +7,7 @@
update_body_parts() //to update the carbon's new bodyparts appearance
GLOB.carbon_list += src
blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio)
add_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling)
/mob/living/carbon/Destroy()
//This must be done first, so the mob ghosts correctly before DNA etc is nulled
@@ -98,6 +99,8 @@
/mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
var/hurt = TRUE
if(GetComponent(/datum/component/tackler))
return
if(throwingdatum?.thrower && iscyborg(throwingdatum.thrower))
var/mob/living/silicon/robot/R = throwingdatum.thrower
if(!R.emagged)
@@ -196,7 +199,7 @@
to_chat(src, "<span class='notice'>You set [I] down gently on the ground.</span>")
return
adjustStaminaLossBuffered(I.getweight()*2)//CIT CHANGE - throwing items shall be more tiring than swinging em. Doubly so.
adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST))
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
@@ -537,10 +540,16 @@
return 1
/mob/living/carbon/proc/spew_organ(power = 5, amt = 1)
var/list/spillable_organs = list()
for(var/A in internal_organs)
var/obj/item/organ/O = A
if(!(O.organ_flags & ORGAN_NO_DISMEMBERMENT))
spillable_organs += O
for(var/i in 1 to amt)
if(!internal_organs.len)
if(!spillable_organs.len)
break //Guess we're out of organs!
var/obj/item/organ/guts = pick(internal_organs)
var/obj/item/organ/guts = pick(spillable_organs)
spillable_organs -= guts
var/turf/T = get_turf(src)
guts.Remove()
guts.forceMove(T)
@@ -548,6 +557,7 @@
guts.throw_at(throw_target, power, 4, src)
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
if(dna)
@@ -572,9 +582,9 @@
become_husk("burn")
med_hud_set_health()
if(stat == SOFT_CRIT)
add_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE, multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN)
add_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit)
else
remove_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE)
remove_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit)
/mob/living/carbon/update_stamina()
var/stam = getStaminaLoss()
@@ -9,7 +9,7 @@
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
var/obj/item/clothing/glasses/GFP = src.glasses
number += GFP.flash_protect
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
@@ -77,24 +77,22 @@
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
var/totitemdamage = pre_attacked_by(I, user)
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 0.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
totitemdamage *= 0.5
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 1.5
//CIT CHANGES END HERE
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, null) & BLOCK_SUCCESS))
return FALSE
var/obj/item/bodypart/affecting = get_bodypart(impacting_zone)
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
send_item_attack_message(I, user, affecting.name)
I.do_stagger_action(src, user)
I.do_stagger_action(src, user, totitemdamage)
if(I.force)
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
@@ -275,7 +273,7 @@
if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
var/friendly_check = FALSE
if(run_block(M, 0, M.name, ATTACK_TYPE_UNARMED))
if(mob_run_block(M, 0, M.name, ATTACK_TYPE_UNARMED, 0, null, null, null))
return
if(lying)
if(buckled)
@@ -63,6 +63,7 @@
var/damageoverlaytemp = 0
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/tackling = FALSE //Whether or not we are tackling, this will prevent the knock into effects for carbons
/// Protection (insulation) from the heat, Value 0-1 corresponding to the percentage of protection
var/heat_protection = 0 // No heat protection
@@ -38,7 +38,7 @@
adjustCloneLoss(damage_amount, forced = forced)
if(STAMINA)
if(BP)
if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage_amount)))
if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage_amount), FALSE, FALSE))
update_damage_overlays()
else
adjustStaminaLoss(damage_amount, forced = forced)
+2 -6
View File
@@ -41,18 +41,14 @@
if(no_brain && istype(O, /obj/item/organ/brain))
qdel(O) //so the brain isn't transfered to the head when the head drops.
continue
var/org_zone = check_zone(O.zone) //both groin and chest organs.
if(org_zone == BODY_ZONE_CHEST)
if(!(O.organ_flags & ORGAN_NO_DISMEMBERMENT) && check_zone(O.zone) == BODY_ZONE_CHEST)
O.Remove()
O.forceMove(Tsec)
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
else
for(var/X in internal_organs)
var/obj/item/organ/I = X
if(no_brain && istype(I, /obj/item/organ/brain))
qdel(I)
continue
if(no_organs && !istype(I, /obj/item/organ/brain))
if(I.organ_flags & ORGAN_NO_DISMEMBERMENT || (no_brain && istype(I, /obj/item/organ/brain)) || (no_organs && !istype(I, /obj/item/organ/brain)))
qdel(I)
continue
I.Remove()
@@ -43,5 +43,6 @@ GLOBAL_LIST_EMPTY(dummy_mob_list)
return
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
if(istype(D))
D.set_species(/datum/species/human,icon_update = TRUE, pref_load = TRUE) //for some fucking reason, if you don't change the species every time, some species will dafault certain things when it's their own species on the mannequin two times in a row, like lizards losing spines and tails setting to smooth. If you can find a fix for this that isn't this, good on you
D.wipe_state()
D.in_use = FALSE
+17 -12
View File
@@ -38,8 +38,9 @@
. = ..()
if(!CONFIG_GET(flag/disable_human_mood))
AddComponent(/datum/component/mood)
AddElement(/datum/element/flavor_text/carbon)
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
/mob/living/carbon/human/Destroy()
QDEL_NULL(physiology)
@@ -768,7 +769,7 @@
return
else
if(hud_used.healths)
var/health_amount = min(health, maxHealth - CLAMP(getStaminaLoss()-50, 0, 80))//CIT CHANGE - makes staminaloss have less of an impact on the health hud
var/health_amount = min(health, maxHealth - clamp(getStaminaLoss()-50, 0, 80))//CIT CHANGE - makes staminaloss have less of an impact on the health hud
if(..(health_amount)) //not dead
switch(hal_screwyhud)
if(SCREWYHUD_CRIT)
@@ -1041,7 +1042,7 @@
return FALSE
/mob/living/carbon/human/proc/clear_shove_slowdown()
remove_movespeed_modifier(MOVESPEED_ID_SHOVE)
remove_movespeed_modifier(/datum/movespeed_modifier/shove)
var/active_item = get_active_held_item()
if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
visible_message("<span class='warning'>[src.name] regains their grip on \the [active_item]!</span>", "<span class='warning'>You regain your grip on \the [active_item]</span>", null, COMBAT_MESSAGE_RANGE)
@@ -1049,18 +1050,22 @@
/mob/living/carbon/human/updatehealth()
. = ..()
if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN))
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN)
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING)
if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN)) //if we want to ignore slowdown from damage and equipment
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
return
var/stambufferinfluence = (bufferedstam*(100/stambuffer))*0.2 //CIT CHANGE - makes stamina buffer influence movedelay
var/health_deficiency = ((100 + stambufferinfluence) - health + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
if(health_deficiency >= 40)
add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN, override = TRUE, multiplicative_slowdown = ((health_deficiency-39) / 75), blacklisted_movetypes = FLOATING|FLYING)
add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING, override = TRUE, multiplicative_slowdown = ((health_deficiency-39) / 25), movetypes = FLYING, blacklisted_movetypes = FLOATING)
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
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)
else
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
else
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN)
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
/mob/living/carbon/human/do_after_coefficent()
. = ..()
@@ -1,8 +1,8 @@
/mob/living/carbon/human/get_blocking_items()
. = ..()
if(wear_suit)
. += wear_suit
. |= wear_suit
if(w_uniform)
. += w_uniform
. |= w_uniform
if(wear_neck)
. += wear_neck
. |= wear_neck
@@ -155,7 +155,7 @@
if(M.a_intent == INTENT_HARM)
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
var/damage = prob(90) ? M.meleeSlashHumanPower : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
@@ -182,10 +182,7 @@
"<span class='userdanger'>[M] disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(!lying) //CITADEL EDIT
DefaultCombatKnockdown(100, TRUE, FALSE, 30, 25)
else
DefaultCombatKnockdown(100)
DefaultCombatKnockdown(M.meleeKnockdownPower)
log_combat(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
@@ -11,7 +11,7 @@
status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH|CANSTAGGER
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
@@ -23,10 +23,6 @@
//Eye colour
var/eye_color = "000"
var/horn_color = "85615a" //specific horn colors, because why not?
var/wing_color = "fff" //wings too
var/skin_tone = "caucasian1" //Skin tone
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
@@ -1,11 +1,13 @@
/mob/living/carbon/human/get_movespeed_modifiers()
var/list/considering = ..()
. = considering
if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN))
for(var/id in .)
var/list/data = .[id]
if(data[MOVESPEED_DATA_INDEX_FLAGS] & IGNORE_NOSLOW)
.[id] = data
. = list()
for(var/id in considering)
var/datum/movespeed_modifier/M = considering[id]
if(M.flags & IGNORE_NOSLOW || M.multiplicative_slowdown < 0)
.[id] = M
return
return considering
/mob/living/carbon/human/movement_delay()
. = ..()
@@ -22,13 +24,18 @@
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
return 0
if (!(lube&GALOSHES_DONT_HELP))
if (!(lube & GALOSHES_DONT_HELP))
if(HAS_TRAIT(src, TRAIT_NOSLIPWATER))
return 0
if(shoes && istype(shoes, /obj/item/clothing))
var/obj/item/clothing/CS = shoes
if (CS.clothing_flags & NOSLIP)
return 0
if (lube & SLIDE_ICE)
if(shoes && istype(shoes, /obj/item/clothing))
var/obj/item/clothing/CS = shoes
if (CS.clothing_flags & NOSLIP_ICE)
return FALSE
return ..()
/mob/living/carbon/human/experience_pressure_difference()
+138 -193
View File
@@ -35,10 +35,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
var/horn_color //specific horn colors, because why not?
var/wing_color
var/use_skintones = NO_SKINTONES // does it use skintones or not? (spoiler alert this is only used by humans)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
@@ -53,6 +49,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/blacklisted = 0 //Flag to exclude from green slime core species.
var/dangerous_existence //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!"
var/say_mod = "says" // affects the speech message
var/species_language_holder = /datum/language_holder
var/list/mutant_bodyparts = list() // Visible CURRENT bodyparts that are unique to a species. Changes to this list for non-species specific bodyparts (ie cat ears and tails) should be assigned at organ level if possible. Layer hiding is handled by handle_mutant_bodyparts() below.
var/list/mutant_organs = list() //Internal organs that are unique to this race.
var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
@@ -331,7 +328,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(mutant_bodyparts["meat_type"]) //I can't believe it's come to the meat
H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]]
C.add_movespeed_modifier(MOVESPEED_ID_SPECIES, TRUE, 100, override=TRUE, multiplicative_slowdown=speedmod, movetypes=(~FLYING))
C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod)
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
@@ -349,7 +346,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/X in inherent_traits)
REMOVE_TRAIT(C, X, SPECIES_TRAIT)
C.remove_movespeed_modifier(MOVESPEED_ID_SPECIES)
C.remove_movespeed_modifier(/datum/movespeed_modifier/species)
if(mutant_bodyparts["meat_type"])
C.type_of_meat = GLOB.meat_types[C.dna.features["meat_type"]]
@@ -550,8 +547,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits))
if(H.socks && !H.hidden_socks && H.get_num_legs(FALSE) >= 2)
var/datum/sprite_accessory/taur/TA
if(mutant_bodyparts["taur"] && H.dna.features["taur"])
TA = GLOB.taur_list[H.dna.features["taur"]]
if(!(TA?.hide_legs) && H.socks && !H.hidden_socks && H.get_num_legs(FALSE) >= 2)
if(H.saved_socks)
H.socks = H.saved_socks
H.saved_socks = ""
@@ -584,7 +583,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/state = "[T.icon_state][((DIGITIGRADE in species_traits) && T.has_digitigrade) ? "_d" : ""]"
var/mutable_appearance/MA
if(H.dna.species.sexes && H.dna.features["body_model"] == FEMALE)
MA = wear_female_version(state, T.icon, BODY_LAYER)
MA = wear_alpha_masked_version(state, T.icon, BODY_LAYER, FEMALE_UNIFORM_TOP)
else
MA = mutable_appearance(T.icon, state, -BODY_LAYER)
if(T.has_color)
@@ -599,21 +598,17 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER, BODY_TAUR_LAYER)
var/list/standing = list()
H.remove_overlay(BODY_BEHIND_LAYER)
H.remove_overlay(BODY_ADJ_LAYER)
H.remove_overlay(BODY_ADJ_UPPER_LAYER)
H.remove_overlay(BODY_FRONT_LAYER)
//CITADEL EDIT - Do not forget to add this to relevent_layers list just above too!
H.remove_overlay(BODY_TAUR_LAYER)
//END EDIT
if(!mutant_bodyparts)
return
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
var/tauric = H.dna.features["taur"] && H.dna.features["taur"] != "None"
var/tauric = mutant_bodyparts["taur"] && H.dna.features["taur"] && H.dna.features["taur"] != "None"
if(mutant_bodyparts["tail_lizard"])
if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
@@ -744,95 +739,105 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!bodyparts_to_add)
return
var/list/relevant_layers = list()
var/list/dna_feature_as_text_string = list()
for(var/bodypart in bodyparts_to_add)
var/datum/sprite_accessory/S
switch(bodypart)
if("tail_lizard")
S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
if("waggingtail_lizard")
S = GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
if("tail_human")
S = GLOB.tails_list_human[H.dna.features["tail_human"]]
if("waggingtail_human")
S = GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
if("spines")
S = GLOB.spines_list[H.dna.features["spines"]]
if("waggingspines")
S = GLOB.animated_spines_list[H.dna.features["spines"]]
if("snout")
S = GLOB.snouts_list[H.dna.features["snout"]]
if("frills")
S = GLOB.frills_list[H.dna.features["frills"]]
if("horns")
S = GLOB.horns_list[H.dna.features["horns"]]
if("ears")
S = GLOB.ears_list[H.dna.features["ears"]]
if("body_markings")
S = GLOB.body_markings_list[H.dna.features["body_markings"]]
if("wings")
S = GLOB.wings_list[H.dna.features["wings"]]
if("wingsopen")
S = GLOB.wings_open_list[H.dna.features["wings"]]
if("deco_wings")
S = GLOB.deco_wings_list[H.dna.features["deco_wings"]]
if("legs")
S = GLOB.legs_list[H.dna.features["legs"]]
if("insect_wings")
S = GLOB.insect_wings_list[H.dna.features["insect_wings"]]
if("insect_fluff")
S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]]
if("insect_markings")
S = GLOB.insect_markings_list[H.dna.features["insect_markings"]]
if("caps")
S = GLOB.caps_list[H.dna.features["caps"]]
if("ipc_screen")
S = GLOB.ipc_screens_list[H.dna.features["ipc_screen"]]
if("ipc_antenna")
S = GLOB.ipc_antennas_list[H.dna.features["ipc_antenna"]]
if("mam_tail")
S = GLOB.mam_tails_list[H.dna.features["mam_tail"]]
if("mam_waggingtail")
S = GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]]
if("mam_body_markings")
S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
if("mam_ears")
S = GLOB.mam_ears_list[H.dna.features["mam_ears"]]
if("mam_snouts")
S = GLOB.mam_snouts_list[H.dna.features["mam_snouts"]]
if("taur")
S = GLOB.taur_list[H.dna.features["taur"]]
if("xenodorsal")
S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]]
if("xenohead")
S = GLOB.xeno_head_list[H.dna.features["xenohead"]]
if("xenotail")
S = GLOB.xeno_tail_list[H.dna.features["xenotail"]]
if(!S || S.icon_state == "none")
continue
for(var/L in S.relevant_layers)
LAZYADD(relevant_layers["[L]"], S)
if(!S.mutant_part_string)
dna_feature_as_text_string[S] = bodypart
var/static/list/layer_text = list("[BODY_BEHIND_LAYER]" = "BEHIND", "[BODY_ADJ_LAYER]" = "ADJ", \
"[BODY_ADJ_UPPER_LAYER]" = "ADJUP", "[BODY_FRONT_LAYER]" = "FRONT")
var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m"
var/list/colorlist = list()
var/husk = HAS_TRAIT(H, TRAIT_HUSK)
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor"]]0")
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor2"]]0")
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]0")
colorlist += list(0,0,0, hair_alpha)
for(var/index in 1 to colorlist.len)
colorlist[index] /= 255
for(var/layer in relevent_layers)
var/layertext = mutant_bodyparts_layertext(layer)
for(var/bodypart in bodyparts_to_add)
var/datum/sprite_accessory/S
switch(bodypart)
if("tail_lizard")
S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
if("waggingtail_lizard")
S = GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
if("tail_human")
S = GLOB.tails_list_human[H.dna.features["tail_human"]]
if("waggingtail_human")
S = GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
if("spines")
S = GLOB.spines_list[H.dna.features["spines"]]
if("waggingspines")
S = GLOB.animated_spines_list[H.dna.features["spines"]]
if("snout")
S = GLOB.snouts_list[H.dna.features["snout"]]
if("frills")
S = GLOB.frills_list[H.dna.features["frills"]]
if("horns")
S = GLOB.horns_list[H.dna.features["horns"]]
if("ears")
S = GLOB.ears_list[H.dna.features["ears"]]
if("body_markings")
S = GLOB.body_markings_list[H.dna.features["body_markings"]]
if("wings")
S = GLOB.wings_list[H.dna.features["wings"]]
if("wingsopen")
S = GLOB.wings_open_list[H.dna.features["wings"]]
if("deco_wings")
S = GLOB.deco_wings_list[H.dna.features["deco_wings"]]
if("legs")
S = GLOB.legs_list[H.dna.features["legs"]]
if("insect_wings")
S = GLOB.insect_wings_list[H.dna.features["insect_wings"]]
if("insect_fluff")
S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]]
if("insect_markings")
S = GLOB.insect_markings_list[H.dna.features["insect_markings"]]
if("caps")
S = GLOB.caps_list[H.dna.features["caps"]]
if("ipc_screen")
S = GLOB.ipc_screens_list[H.dna.features["ipc_screen"]]
if("ipc_antenna")
S = GLOB.ipc_antennas_list[H.dna.features["ipc_antenna"]]
if("mam_tail")
S = GLOB.mam_tails_list[H.dna.features["mam_tail"]]
if("mam_waggingtail")
S = GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]]
if("mam_body_markings")
S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
if("mam_ears")
S = GLOB.mam_ears_list[H.dna.features["mam_ears"]]
if("mam_snouts")
S = GLOB.mam_snouts_list[H.dna.features["mam_snouts"]]
if("taur")
S = GLOB.taur_list[H.dna.features["taur"]]
if("xenodorsal")
S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]]
if("xenohead")
S = GLOB.xeno_head_list[H.dna.features["xenohead"]]
if("xenotail")
S = GLOB.xeno_tail_list[H.dna.features["xenotail"]]
if(!S || S.icon_state == "none")
continue
var/mutable_appearance/accessory_overlay = mutable_appearance(S.icon, layer = -layer)
accessory_overlay.color = null //just because. reee.
//A little rename so we don't have to use tail_lizard or tail_human when naming the sprites.
if(bodypart == "tail_lizard" || bodypart == "tail_human" || bodypart == "mam_tail" || bodypart == "xenotail")
bodypart = "tail"
if(bodypart == "mam_waggingtail" || bodypart == "waggingtail_human" || bodypart == "waggingtail_lizard")
bodypart = "tailwag"
if(bodypart == "mam_ears" || bodypart == "ears")
bodypart = "ears"
if(bodypart == "mam_snouts" || bodypart == "snout")
bodypart = "snout"
if(bodypart == "xenohead")
bodypart = "xhead"
if(bodypart == "insect_wings" || bodypart == "deco_wings")
bodypart = "insect_wings"
for(var/layer in relevant_layers)
var/list/standing = list()
var/layertext = layer_text[layer]
if(!layertext) //shouldn't happen
stack_trace("invalid layer '[layer]' found in the list of relevant layers on species.handle_mutant_bodyparts().")
continue
var/layernum = text2num(layer)
for(var/bodypart in relevant_layers[layer])
var/datum/sprite_accessory/S = bodypart
var/mutable_appearance/accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
bodypart = S.mutant_part_string || dna_feature_as_text_string[S]
if(S.gender_specific)
accessory_overlay.icon_state = "[g]_[bodypart]_[S.icon_state]_[layertext]"
@@ -842,16 +847,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(S.center)
accessory_overlay = center_image(accessory_overlay, S.dimension_x, S.dimension_y)
var/list/colorlist = list()
colorlist.Cut()
colorlist += ReadRGB("[H.dna.features["mcolor"]]0")
colorlist += ReadRGB("[H.dna.features["mcolor2"]]0")
colorlist += ReadRGB("[H.dna.features["mcolor3"]]0")
colorlist += list(0,0,0, hair_alpha)
for(var/index=1, index<=colorlist.len, index++)
colorlist[index] = colorlist[index]/255
if(!HAS_TRAIT(H, TRAIT_HUSK))
if(!husk)
if(!forced_colour)
switch(S.color_src)
if(SKINTONE)
@@ -885,9 +881,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(EYECOLOR)
accessory_overlay.color = "#[H.eye_color]"
if(HORNCOLOR)
accessory_overlay.color = "#[H.horn_color]"
accessory_overlay.color = "#[H.dna.features["horns_color"]]"
if(WINGCOLOR)
accessory_overlay.color = "#[H.wing_color]"
accessory_overlay.color = "#[H.dna.features["wings_color"]]"
else
accessory_overlay.color = forced_colour
else
@@ -896,14 +892,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(bodypart == "tail")
accessory_overlay.icon_state = "m_tail_husk_[layertext]"
if(S.color_src == MATRIXED)
var/list/husklist = list()
husklist += ReadRGB("#a3a3a3")
husklist += ReadRGB("#a3a3a3")
husklist += ReadRGB("#a3a3a3")
husklist += list(0,0,0, hair_alpha)
for(var/index=1, index<=husklist.len, index++)
husklist[index] = husklist[index]/255
accessory_overlay.color = husklist
accessory_overlay.color = colorlist
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
@@ -911,24 +900,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
standing += accessory_overlay
if(S.hasinner)
var/mutable_appearance/inner_accessory_overlay = mutable_appearance(S.icon, layer = -layer)
if(S.gender_specific)
inner_accessory_overlay.icon_state = "[g]_[bodypart]inner_[S.icon_state]_[layertext]"
else
inner_accessory_overlay.icon_state = "m_[bodypart]inner_[S.icon_state]_[layertext]"
if(S.center)
inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y)
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
standing += inner_accessory_overlay
if(S.extra) //apply the extra overlay, if there is one
var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layer)
var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
if(S.gender_specific)
extra_accessory_overlay.icon_state = "[g]_[bodypart]_extra_[S.icon_state]_[layertext]"
else
@@ -964,9 +937,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
extra_accessory_overlay.color = "#[H.eye_color]"
if(HORNCOLOR)
extra_accessory_overlay.color = "#[H.horn_color]"
extra_accessory_overlay.color = "#[H.dna.features["horns_color"]]"
if(WINGCOLOR)
extra_accessory_overlay.color = "#[H.wing_color]"
extra_accessory_overlay.color = "#[H.dna.features["wings_color"]]"
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
extra_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
@@ -975,7 +948,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
standing += extra_accessory_overlay
if(S.extra2) //apply the extra overlay, if there is one
var/mutable_appearance/extra2_accessory_overlay = mutable_appearance(S.icon, layer = -layer)
var/mutable_appearance/extra2_accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
if(S.gender_specific)
extra2_accessory_overlay.icon_state = "[g]_[bodypart]_extra2_[S.icon_state]_[layertext]"
else
@@ -1005,9 +978,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else
extra2_accessory_overlay.color = "#[H.hair_color]"
if(HORNCOLOR)
extra2_accessory_overlay.color = "#[H.horn_color]"
extra2_accessory_overlay.color = "#[H.dna.features["horns_color"]]"
if(WINGCOLOR)
extra2_accessory_overlay.color = "#[H.wing_color]"
extra2_accessory_overlay.color = "#[H.dna.features["wings_color"]]"
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
extra2_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
@@ -1016,13 +989,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
standing += extra2_accessory_overlay
H.overlays_standing[layer] = standing.Copy()
standing = list()
H.overlays_standing[layernum] = standing
H.apply_overlay(BODY_BEHIND_LAYER)
H.apply_overlay(BODY_ADJ_LAYER)
H.apply_overlay(BODY_ADJ_UPPER_LAYER)
H.apply_overlay(BODY_FRONT_LAYER)
H.apply_overlay(BODY_TAUR_LAYER) // CITADEL EDIT
/*
@@ -1034,21 +1006,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
outfit_important_for_life= new()
outfit_important_for_life.equip(human_to_equip)
//This exists so sprite accessories can still be per-layer without having to include that layer's
//number in their sprite name, which causes issues when those numbers change.
/datum/species/proc/mutant_bodyparts_layertext(layer)
switch(layer)
if(BODY_BEHIND_LAYER)
return "BEHIND"
if(BODY_ADJ_LAYER)
return "ADJ"
if(BODY_FRONT_LAYER)
return "FRONT"
//CITADEL EDIT
if(BODY_TAUR_LAYER)
return "TAUR"
//END EDIT
/* TODO: Snowflake trail marks
// Impliments different trails for species depending on if they're wearing shoes.
/datum/species/proc/get_move_trail(var/mob/living/carbon/human/H)
@@ -1301,14 +1258,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.overeatduration < 100)
to_chat(H, "<span class='notice'>You feel fit again!</span>")
REMOVE_TRAIT(H, TRAIT_FAT, OBESITY)
H.remove_movespeed_modifier(MOVESPEED_ID_FAT)
H.remove_movespeed_modifier(/datum/movespeed_modifier/obesity)
H.update_inv_w_uniform()
H.update_inv_wear_suit()
else
if(H.overeatduration >= 100)
to_chat(H, "<span class='danger'>You suddenly feel blubbery!</span>")
ADD_TRAIT(H, TRAIT_FAT, OBESITY)
H.add_movespeed_modifier(MOVESPEED_ID_FAT, multiplicative_slowdown = 1.5)
H.add_movespeed_modifier(/datum/movespeed_modifier/obesity)
H.update_inv_w_uniform()
H.update_inv_wear_suit()
@@ -1364,9 +1321,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!HAS_TRAIT(H, TRAIT_NOHUNGER))
var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80
if(hungry >= 70)
H.add_movespeed_modifier(MOVESPEED_ID_HUNGRY, override = TRUE, multiplicative_slowdown = (hungry / 50))
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (hungry / 50))
else
H.remove_movespeed_modifier(MOVESPEED_ID_HUNGRY)
H.remove_movespeed_modifier(/datum/movespeed_modifier/hunger)
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
@@ -1582,9 +1539,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(IS_STAMCRIT(user))
to_chat(user, "<span class='warning'>You're too exhausted!</span>")
return FALSE
else if(target.check_block())
target.visible_message("<span class='warning'>[target] blocks [user]'s disarm attempt!</span>")
return FALSE
else if(aim_for_mouth && ( target_on_help || target_restrained || target_aiming_for_mouth))
playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1)
@@ -1617,7 +1571,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
"You hear a slap."
)
return FALSE
else
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
@@ -1625,10 +1579,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
user.adjustStaminaLossBuffered(1)
else
user.adjustStaminaLossBuffered(3)
if(attacker_style && attacker_style.disarm_act(user,target))
return TRUE
if(target.w_uniform)
target.w_uniform.add_fingerprint(user)
//var/randomized_zone = ran_zone(user.zone_selected) CIT CHANGE - comments out to prevent compiling errors
@@ -1661,7 +1615,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
randn -= 25 //if you are a pugilist, you're slapping that item from them pretty reliably
if(HAS_TRAIT(target, TRAIT_PUGILIST))
randn += 25 //meanwhile, pugilists are less likely to get disarmed
if(randn <= 35)//CIT CHANGE - changes this back to a 35% chance to accomodate for the above being commented out in favor of right-click pushing
var/obj/item/I = null
if(target.pulling)
@@ -1714,9 +1668,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
disarm(M, H, attacker_style)
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
var/totitemdamage = H.pre_attacked_by(I, user)
// Allows you to put in item-specific reactions based on species
if(user != H)
if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
if(H.mob_run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, null) & BLOCK_SUCCESS)
return 0
if(H.check_martial_melee_block())
H.visible_message("<span class='warning'>[H] blocks [I]!</span>")
@@ -1732,24 +1687,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 0.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
totitemdamage *= 0.5
if(istype(H))
if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 1.5
//CIT CHANGES END HERE
var/weakness = H.check_weakness(I, user)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
H.send_item_attack_message(I, user, hit_area)
I.do_stagger_action(H, user)
I.do_stagger_action(H, user, totitemdamage)
if(!I.force)
if(!totitemdamage)
return 0 //item force is zero
//dismemberment
@@ -1834,7 +1779,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return TRUE
if(M.mind)
attacker_style = M.mind.martial_art
if((M != H) && M.a_intent != INTENT_HELP && (H.run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected) & BLOCK_SUCCESS))
if((M != H) && M.a_intent != INTENT_HELP && (H.mob_run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected, null) & BLOCK_SUCCESS))
log_combat(M, H, "attempted to touch")
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
return TRUE
@@ -1934,8 +1879,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/obj/item/target_held_item = target.get_active_held_item()
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove))
target.add_movespeed_modifier(/datum/movespeed_modifier/shove)
if(target_held_item)
if(!HAS_TRAIT(target_held_item, TRAIT_NODROP))
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
@@ -2086,7 +2031,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
H.remove_movespeed_modifier(MOVESPEED_ID_COLD)
H.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
var/burn_damage
var/firemodifier = H.fire_stacks / 50
@@ -2103,8 +2048,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
//Sorry for the nasty oneline but I don't want to assign a variable on something run pretty frequently
H.add_movespeed_modifier(MOVESPEED_ID_COLD, override = TRUE, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR), blacklisted_movetypes = FLOATING)
//Apply cold slowdown
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
switch(H.bodytemperature)
if(200 to BODYTEMP_COLD_DAMAGE_LIMIT)
H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod*H.physiology.cold_mod, BURN)
@@ -2114,7 +2059,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod*H.physiology.cold_mod, BURN)
else
H.remove_movespeed_modifier(MOVESPEED_ID_COLD)
H.remove_movespeed_modifier(/datum/movespeed_modifier/cold)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
@@ -9,6 +9,7 @@
gib_types = /obj/effect/gibspawner/robot
damage_overlay_type = "synth"
mutanttongue = /obj/item/organ/tongue/robot
species_language_holder = /datum/language_holder/synthetic
limbs_id = "synth"
/datum/species/android/on_species_gain(mob/living/carbon/C)
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
name = "Dwarf"
id = "dwarf" //Also called Homo sapiens pumilionis
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR)
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR,TRAIT_DWARF)
inherent_traits = list()
limbs_id = "human"
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
@@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
disliked_food = JUNKFOOD | FRIED //Dwarves hate foods that have no nutrition other than alcohol.
mutant_organs = list(/obj/item/organ/dwarfgland) //Dwarven alcohol gland, literal gland warrior
mutantliver = /obj/item/organ/liver/dwarf //Dwarven super liver (Otherwise they r doomed)
species_language_holder = /datum/language_holder/dwarf
/mob/living/carbon/human/species/dwarf //species admin spawn path
race = /datum/species/dwarf //and the race the path is set to.
@@ -30,18 +31,15 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
. = ..()
var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
var/mob/living/carbon/human/H = C
H.grant_language(/datum/language/dwarf)
H.facial_hair_style = dwarf_hair
H.update_hair()
H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM.
RegisterSignal(C, COMSIG_MOB_SAY, .proc/handle_speech) //We register handle_speech is being used.
/datum/species/dwarf/on_species_loss(mob/living/carbon/H, datum/species/new_species)
. = ..()
H.transform = H.transform.Scale(1, 1.25) //And we undo it.
UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used.
H.remove_language(/datum/language/dwarf)
//Dwarf Name stuff
/proc/dwarf_name() //hello caller: my name is urist mcuristurister
@@ -102,12 +100,11 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops..
. = ..()
dwarf_cycle_ticker()
if(owner && owner.stat != DEAD)
dwarf_cycle_ticker()
//Handles the delayed tick cycle by just adding on increments per each on_life() tick
/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker()
if(owner.stat == DEAD)
return //We make sure they are not dead, so they don't increment any tickers.
dwarf_eth_ticker++
dwarf_filth_ticker++
@@ -170,7 +167,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
for(var/datum/reagent/R in owner.reagents.reagent_list)
if(istype(R, /datum/reagent/consumable/ethanol))
var/datum/reagent/consumable/ethanol/E = R
stored_alcohol = CLAMP(stored_alcohol + E.boozepwr / 50, 0, max_alcohol)
stored_alcohol = clamp(stored_alcohol + E.boozepwr / 50, 0, max_alcohol)
var/heal_amt = heal_rate
stored_alcohol -= alcohol_rate //Subtracts alcohol_Rate from stored alcohol so EX: 250 - 0.25 per each loop that occurs.
if(stored_alcohol > 400) //If they are over 400 they start regenerating
@@ -397,7 +397,7 @@
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/target = get_turf(P.starting)
// redirect the projectile
P.preparePixelProjectile(locate(CLAMP(target.x + new_x, 1, world.maxx), CLAMP(target.y + new_y, 1, world.maxy), H.z), H)
P.preparePixelProjectile(locate(clamp(target.x + new_x, 1, world.maxx), clamp(target.y + new_y, 1, world.maxy), H.z), H)
return BULLET_ACT_FORCE_PIERCE
return ..()
@@ -21,20 +21,19 @@
coldmod = 6 // = 3x cold damage
heatmod = 0.5 // = 1/4x heat damage
burnmod = 0.5 // = 1/2x generic burn damage
species_language_holder = /datum/language_holder/jelly
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
regenerate_limbs.Remove(C)
if(slime_change) //CIT CHANGE
slime_change.Remove(C) //CIT CHANGE
C.remove_language(/datum/language/slime)
C.faction -= "slime"
..()
C.faction -= "slime"
/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
C.grant_language(/datum/language/slime)
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
@@ -606,7 +605,7 @@
var/max_D = CONFIG_GET(number/penis_max_inches_prefs)
var/new_length = input(owner, "Penis length in inches:\n([min_D]-[max_D])", "Genital Alteration") as num|null
if(new_length)
H.dna.features["cock_length"] = CLAMP(round(new_length), min_D, max_D)
H.dna.features["cock_length"] = clamp(round(new_length), min_D, max_D)
H.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/testicles)
@@ -24,9 +24,7 @@
disliked_food = GRAIN | DAIRY
liked_food = GROSS | MEAT
inert_mutation = FIREBREATH
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/draconic)
species_language_holder = /datum/language_holder/lizard
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
@@ -86,9 +84,15 @@
mutantlungs = /obj/item/organ/lungs/ashwalker
burnmod = 0.9
brutemod = 0.9
species_language_holder = /datum/language_holder/lizard/ash
/datum/species/lizard/ashwalker/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
if((C.dna.features["spines"] != "None" ) && (C.dna.features["tail_lizard"] == "None")) //tbh, it's kinda ugly for them not to have a tail yet have floating spines
C.dna.features["tail_lizard"] = "Smooth"
C.update_body()
if(C.dna.features["legs"] != "digitigrade")
C.dna.features["legs"] = "digitigrade"
for(var/obj/item/bodypart/leggie in C.bodyparts)
if(leggie.body_zone == BODY_ZONE_L_LEG || leggie.body_zone == BODY_ZONE_R_LEG)
leggie.update_limb(FALSE, C)
return ..()
@@ -23,9 +23,7 @@
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
var/datum/martial_art/mushpunch/mush
/datum/species/mush/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/mushroom) //pomf pomf
species_language_holder = /datum/language_holder/mushroom
/datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -12,6 +12,7 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = MEAT | DAIRY
liked_food = VEGETABLES | FRUIT | GRAIN
species_language_holder = /datum/language_holder/sylvan
var/light_nutrition_gain_factor = 10
var/light_toxheal = 1
var/light_oxyheal = 1
@@ -16,6 +16,7 @@
var/list/initial_inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER,TRAIT_NOBREATH)
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
species_language_holder = /datum/language_holder/synthetic
/datum/species/synth/military
name = "Military Synth"
@@ -106,8 +106,8 @@
to_chat(victim, "<span class='danger'>[H] is draining your blood!</span>")
to_chat(H, "<span class='notice'>You drain some blood!</span>")
playsound(H, 'sound/items/drink.ogg', 30, 1, -2)
victim.blood_volume = CLAMP(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
H.blood_volume = CLAMP(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
H.blood_volume = clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
if(!victim.blood_volume)
to_chat(H, "<span class='warning'>You finish off [victim]'s blood supply!</span>")
@@ -34,12 +34,11 @@
/mob/living/carbon/human/set_drugginess(amount)
..()
if(!amount)
remove_language(/datum/language/beachbum)
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
/mob/living/carbon/human/adjust_drugginess(amount)
..()
if(!dna.check_mutation(STONER))
if(druggy)
grant_language(/datum/language/beachbum)
else
remove_language(/datum/language/beachbum)
if(druggy)
grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
else
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
@@ -129,16 +129,18 @@ There are several things that need to be remembered:
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/mutable_appearance/uniform_overlay
if(dna && dna.species.sexes)
var/G = (dna.features["body_model"] == FEMALE) ? "f" : "m"
if(G == "f" && U.fitted != NO_FEMALE_UNIFORM)
uniform_overlay = U.build_worn_icon(UNIFORM_LAYER, alt_worn, FALSE, U.fitted, target_overlay, variant_flag, FALSE)
if(!uniform_overlay)
uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, NO_FEMALE_UNIFORM, target_overlay, variant_flag, FALSE)
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]
@@ -269,6 +271,11 @@ There are several things that need to be remembered:
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.
return
if(shoes)
var/obj/item/clothing/shoes/S = shoes
shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
@@ -514,12 +521,17 @@ There are several things that need to be remembered:
overlays_standing[BACK_LAYER] = back_overlay
apply_overlay(BACK_LAYER)
/proc/wear_female_version(t_color, icon, layer, type)
var/index = "[t_color]-[icon]"
var/icon/female_clothing_icon = GLOB.female_clothing_icons[index]
if(!female_clothing_icon) //Create standing/laying icons if they don't exist
generate_female_clothing(index,t_color,icon,type)
return mutable_appearance(GLOB.female_clothing_icons[index], layer = -layer)
/proc/wear_alpha_masked_version(state, icon, layer, female, alpha_mask)
var/mask = "-[alpha_mask]"
if(islist(alpha_mask))
mask = "-"
for(var/t in alpha_mask)
mask += t
var/index = "[state]-[icon]-[female][mask]"
. = GLOB.alpha_masked_worn_icons[index]
if(!.) //Create standing/laying icons if they don't exist
. = generate_alpha_masked_clothing(index,state,icon,female,alpha_mask)
return mutable_appearance(., layer = -layer)
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
var/list/out = new
@@ -574,10 +586,12 @@ generate/load female uniform sprites matching all previously decided variables
style_flags: mutant race appearance flags, mostly used for worn_overlays()
alpha_mask: a text string or list of text, the actual icons are stored in a global list and associated with said text string(s).
use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if mob_overlay_icon is present.
*/
/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state, style_flags = NONE, use_mob_overlay_icon = TRUE)
/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state, style_flags = NONE, use_mob_overlay_icon = TRUE, alpha_mask)
var/t_state
t_state = override_state || item_state || icon_state
@@ -597,8 +611,8 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
layer2use = default_layer
var/mutable_appearance/standing
if(femaleuniform)
standing = wear_female_version(t_state,file2use,layer2use,femaleuniform)
if(femaleuniform || alpha_mask)
standing = wear_alpha_masked_version(t_state, file2use, layer2use, femaleuniform, alpha_mask)
if(!standing)
standing = mutable_appearance(file2use, t_state, -layer2use)
@@ -661,19 +675,17 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
. += "-[dna.features["body_model"]]"
var/is_taur = FALSE
if(dna.species.mutant_bodyparts["taur"] && dna.features["taur"] != "None")
is_taur = TRUE
if(dna.species.mutant_bodyparts["taur"])
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
if(T?.hide_legs)
is_taur = TRUE
var/static/list/leg_day = typecacheof(list(/obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg))
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg))
if(is_taur)
continue
if(is_taur && leg_day[BP.type])
continue
. += "-[BP.body_zone]"
if(BP.status == BODYPART_ORGANIC)
+1 -1
View File
@@ -235,7 +235,7 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath_gases[/datum/gas/plasma]/safe_tox_max) * 10
adjustToxLoss(CLAMP(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
@@ -111,7 +111,7 @@
if(pickupTarget)
if(restrained() || blacklistItems[pickupTarget] || HAS_TRAIT(pickupTarget, TRAIT_NODROP))
pickupTarget = null
else
else if(!isobj(loc) || istype(loc, /obj/item/clothing/head/mob_holder))
pickupTimer++
if(pickupTimer >= 4)
blacklistItems[pickupTarget] ++
@@ -126,10 +126,8 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
var/obj/item/clothing/head/mob_holder/h = pickupTarget
if(h && h.held_mob==src)
return//dont let them pickpocket themselves
if(istype(pickupTarget, /obj/item/clothing/head/mob_holder))
return//dont let them pickpocket themselves or hold other monkys.
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
@@ -65,20 +65,20 @@
/mob/living/carbon/monkey/on_reagent_change()
. = ..()
remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
var/amount
if(reagents.has_reagent(/datum/reagent/medicine/morphine))
amount = -1
if(amount)
add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_reagent_speedmod, TRUE, amount)
/mob/living/carbon/monkey/updatehealth()
. = ..()
var/slow = 0
var/health_deficiency = (100 - health)
if(health_deficiency >= 45)
slow += (health_deficiency / 25)
add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN))
var/health_deficiency = (maxHealth - health)
if(health_deficiency >= 45)
slow += (health_deficiency / 25)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_health_speedmod, TRUE, slow)
/mob/living/carbon/monkey/adjust_bodytemperature(amount)
. = ..()
@@ -87,7 +87,7 @@
slow += (283.222 - bodytemperature) / 10 * 1.75
if(slow <= 0)
return
add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_temperature_speedmod, TRUE, slow)
/mob/living/carbon/monkey/Stat()
..()
@@ -99,7 +99,6 @@
if(changeling)
stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
stat("Absorbed DNA", changeling.absorbedcount)
return
/mob/living/carbon/monkey/verb/removeinternal()
+3 -3
View File
@@ -12,9 +12,9 @@
return 0
return ..()
/mob/living/carbon/could_speak_in_language(datum/language/dt)
/mob/living/carbon/could_speak_language(datum/language/language)
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
if(T)
. = T.could_speak_in_language(dt)
return T.could_speak_language(language)
else
. = initial(dt.flags) & TONGUELESS_SPEECH
return initial(language.flags) & TONGUELESS_SPEECH
@@ -23,10 +23,10 @@
clear_alert("high")
/mob/living/carbon/adjust_disgust(amount)
disgust = CLAMP(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT)
disgust = clamp(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT)
/mob/living/carbon/set_disgust(amount)
disgust = CLAMP(amount, 0, DISGUST_LEVEL_MAXEDOUT)
disgust = clamp(amount, 0, DISGUST_LEVEL_MAXEDOUT)
////////////////////////////////////////TRAUMAS/////////////////////////////////////////
@@ -203,6 +203,12 @@
remove_overlay(BODYPARTS_LAYER)
var/is_taur = FALSE
if(dna?.species.mutant_bodyparts["taur"])
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
if(T?.hide_legs)
is_taur = TRUE
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
BP.update_limb()
@@ -213,9 +219,12 @@
return
//GENERATE NEW LIMBS
var/static/list/leg_day = typecacheof(list(/obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg))
var/list/new_limbs = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(is_taur && leg_day[BP.type])
continue
new_limbs += BP.get_limb_icon()
if(new_limbs.len)
overlays_standing[BODYPARTS_LAYER] = new_limbs
+6 -6
View File
@@ -88,7 +88,7 @@
if(EFFECT_STUN)
Stun(effect * hit_percent)
if(EFFECT_KNOCKDOWN)
DefaultCombatKnockdown(effect * hit_percent, override_stamdmg = knockdown_stammax ? CLAMP(knockdown_stamoverride, 0, knockdown_stammax-getStaminaLoss()) : knockdown_stamoverride)
DefaultCombatKnockdown(effect * hit_percent, override_stamdmg = knockdown_stammax ? clamp(knockdown_stamoverride, 0, knockdown_stammax-getStaminaLoss()) : knockdown_stamoverride)
if(EFFECT_UNCONSCIOUS)
Unconscious(effect * hit_percent)
if(EFFECT_IRRADIATE)
@@ -140,7 +140,7 @@
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = CLAMP((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
bruteloss = clamp((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -151,7 +151,7 @@
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
oxyloss = CLAMP((oxyloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
oxyloss = clamp((oxyloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -170,7 +170,7 @@
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
toxloss = CLAMP((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
toxloss = clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -189,7 +189,7 @@
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
fireloss = CLAMP((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
fireloss = clamp((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -200,7 +200,7 @@
/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
cloneloss = CLAMP((cloneloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
cloneloss = clamp((cloneloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
+53 -4
View File
@@ -68,7 +68,7 @@
var/obj/O = A
if(ObjBump(O))
return
if(ismovableatom(A))
if(ismovable(A))
var/atom/movable/AM = A
if(PushAM(AM, move_force))
return
@@ -316,6 +316,45 @@
update_pull_movespeed()
set_pull_offsets(M, state)
/mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE)
if(M.buckled || M.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
return //don't make them change direction or offset them if they're buckled into something or in combat mode.
var/offset = 0
switch(grab_state)
if(GRAB_PASSIVE)
offset = GRAB_PIXEL_SHIFT_PASSIVE
if(GRAB_AGGRESSIVE)
offset = GRAB_PIXEL_SHIFT_AGGRESSIVE
if(GRAB_NECK)
offset = GRAB_PIXEL_SHIFT_NECK
if(GRAB_KILL)
offset = GRAB_PIXEL_SHIFT_NECK
M.setDir(get_dir(M, src))
switch(M.dir)
if(NORTH)
animate(M, pixel_x = 0, pixel_y = offset, 3)
if(SOUTH)
animate(M, pixel_x = 0, pixel_y = -offset, 3)
if(EAST)
if(M.lying == 270) //update the dragged dude's direction if we've turned
M.lying = 90
M.update_transform() //force a transformation update, otherwise it'll take a few ticks for update_mobility() to do so
M.lying_prev = M.lying
animate(M, pixel_x = offset, pixel_y = 0, 3)
if(WEST)
if(M.lying == 90)
M.lying = 270
M.update_transform()
M.lying_prev = M.lying
animate(M, pixel_x = -offset, pixel_y = 0, 3)
/mob/living/proc/reset_pull_offsets(mob/living/M, override)
if(!override && M.buckled)
return
animate(M, pixel_x = 0, pixel_y = 0, 1)
//mob verbs are a lot faster than object verbs
//for more info on why this is not atom/pull, see examinate() in mob.dm
/mob/living/verb/pulled(atom/movable/AM as mob|obj in oview(1))
@@ -328,6 +367,8 @@
stop_pulling()
/mob/living/stop_pulling()
if(ismob(pulling))
reset_pull_offsets(pulling)
..()
update_pull_movespeed()
update_pull_hud_icon()
@@ -502,8 +543,16 @@
var/obj/effect/proc_holder/spell/spell = S
spell.updateButtonIcon()
//proc used to remove all immobilisation effects + reset stamina
/mob/living/proc/remove_CC(should_update_mobility = TRUE)
SetAllImmobility(0, FALSE)
setStaminaLoss(0)
SetUnconscious(0, FALSE)
if(should_update_mobility)
update_mobility()
//proc used to completely heal a mob.
/mob/living/proc/fully_heal(admin_revive = 0)
/mob/living/proc/fully_heal(admin_revive = FALSE)
restore_blood()
setToxLoss(0, 0) //zero as second argument not automatically call updatehealth().
setOxyLoss(0, 0)
@@ -645,7 +694,7 @@
attempt_resist_grab(FALSE)
// Return as we should only resist one thing at a time. Give clickdelay if the grab wasn't passive.
return old_gs? TRUE : FALSE
// unbuckling yourself. stops the chain if you try it.
if(buckled && last_special <= world.time)
log_combat(src, buckled, "resisted buckle")
@@ -1030,7 +1079,7 @@
update_fire()
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
fire_stacks = CLAMP(fire_stacks + add_fire_stacks, -20, 20)
fire_stacks = clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
+13 -15
View File
@@ -1,7 +1,10 @@
// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit".
// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging,
// and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit".
/*
/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
/// You can find the mob_check_block() and mob_run_block() macros in __DEFINES/combat.dm
/// Bitflags for check_block() and run_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
/// Attack was not blocked
#define BLOCK_NONE NONE
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
@@ -23,14 +26,6 @@
#define BLOCK_TARGET_DODGED (1<<7)
*/
///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this.
/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
/// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this.
/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
/** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks.
* Automatically checks all held items for /obj/item/proc/run_block() with the same parameters.
* @params
@@ -57,7 +52,7 @@
if(real_attack)
for(var/obj/item/I in tocheck)
// i don't like this too
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
var/final_block_chance = I.block_chance - (clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
var/results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
. |= results
if((results & BLOCK_SUCCESS) && !(results & BLOCK_CONTINUE_CHAIN))
@@ -65,12 +60,13 @@
else
for(var/obj/item/I in tocheck)
// i don't like this too
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
var/final_block_chance = I.block_chance - (clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
I.check_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
/// Gets an unsortedlist of objects to run block checks on.
/mob/living/proc/get_blocking_items()
. = list()
SEND_SIGNAL(src, COMSIG_LIVING_GET_BLOCKING_ITEMS, .)
for(var/obj/item/I in held_items)
// this is a bad check but i am not removing it until a better catchall is made
if(istype(I, /obj/item/clothing))
@@ -85,11 +81,13 @@
/// Runs block and returns flag for do_run_block to process.
/obj/item/proc/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
SEND_SIGNAL(src, COMSIG_ITEM_RUN_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
. = SEND_SIGNAL(src, COMSIG_ITEM_RUN_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
if(. & BLOCK_SUCCESS)
return
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return BLOCK_NONE
return . | BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return . | BLOCK_NONE
/// Returns block information using list/block_return. Used for check_block() on mobs.
/obj/item/proc/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+6 -1
View File
@@ -17,7 +17,7 @@
update_combat_mode_icon()
/mob/living/proc/disable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE)
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) || (combat_flags & COMBAT_FLAG_COMBAT_FORCED))
return
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_ACTIVE)
SEND_SIGNAL(src, COMSIG_LIVING_COMBAT_DISABLED, was_forced)
@@ -60,6 +60,8 @@
/mob/living/proc/disable_intentional_combat_mode(silent = TRUE, visible = FALSE)
if(!(combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
return
if(combat_flags & COMBAT_FLAG_COMBAT_FORCED)
return
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_TOGGLED)
if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
disable_combat_mode(silent, FALSE, visible, FALSE)
@@ -71,6 +73,9 @@
/mob/living/proc/user_toggle_intentional_combat_mode(visible = TRUE)
var/old = (combat_flags & COMBAT_FLAG_COMBAT_TOGGLED)
if(old)
if(combat_flags & COMBAT_FLAG_COMBAT_FORCED)
to_chat(src, "<span class='warning'>You are unable to relax your muscles.</span>")
return
disable_intentional_combat_mode()
playsound_local(src, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the above!
else if(CAN_TOGGLE_COMBAT_MODE(src))
+12 -11
View File
@@ -68,7 +68,7 @@
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
var/list/returnlist = list()
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
var/returned = mob_run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
if(returned & BLOCK_SHOULD_REDIRECT)
handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD])
if(returned & BLOCK_REDIRECTED)
@@ -88,9 +88,9 @@
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return CLAMP((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
return clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return CLAMP(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
return clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
@@ -111,7 +111,7 @@
I = AM
throwpower = I.throwforce
var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone) & BLOCK_SUCCESS)
if(mob_run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, null) & BLOCK_SUCCESS)
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
@@ -264,12 +264,13 @@
update_mobility() //we fall down
if(!buckled && !density)
Move(user.loc)
user.set_pull_offsets(src, grab_state)
return 1
/mob/living/attack_hand(mob/user)
..() //Ignoring parent return value here.
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
if((user != src) && user.a_intent != INTENT_HELP && (run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS))
if((user != src) && user.a_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
log_combat(user, src, "attempted to touch")
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>")
return TRUE
@@ -280,7 +281,7 @@
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
return TRUE
var/hulk_verb = pick("smash","pummel")
if(user != src && (run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS))
if(user != src && (mob_run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
return TRUE
..()
return FALSE
@@ -302,7 +303,7 @@
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
if(mob_run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS)
return FALSE
if (stat != DEAD)
@@ -321,7 +322,7 @@
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE
if(run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
if(mob_run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS)
return FALSE
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
@@ -339,7 +340,7 @@
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
return FALSE
if(run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
if(mob_run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS)
return FALSE
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75))
@@ -363,7 +364,7 @@
if(HAS_TRAIT(L, TRAIT_PACIFISM))
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE
if(L != src && (run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, L, check_zone(L.zone_selected)) & BLOCK_SUCCESS))
if(L != src && (mob_run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, L, check_zone(L.zone_selected), null) & BLOCK_SUCCESS))
return FALSE
L.do_attack_animation(src)
if(prob(90))
@@ -377,7 +378,7 @@
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
if((M != src) && M.a_intent != INTENT_HELP && (run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS))
if((M != src) && M.a_intent != INTENT_HELP && (mob_run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return FALSE
switch(M.a_intent)
@@ -98,8 +98,6 @@
var/datum/riding/riding_datum
var/datum/language/selected_default_language
var/last_words //used for database logging
var/list/obj/effect/proc_holder/abilities = list()
+4 -2
View File
@@ -94,11 +94,13 @@
if(should_be_lying)
mobility_flags &= ~MOBILITY_STAND
setMovetype(movement_type | CRAWLING)
if(!lying) //force them on the ground
lying = pick(90, 270)
if(has_gravity() && !buckled)
playsound(src, "bodyfall", 20, 1)
else
setMovetype(movement_type & ~CRAWLING)
mobility_flags |= MOBILITY_STAND
lying = 0
@@ -161,8 +163,8 @@
if(!has_legs && has_arms < 2)
limbless_slowdown += 6 - (has_arms * 3)
if(limbless_slowdown)
add_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=limbless_slowdown, blacklisted_movetypes = FLYING|FLOATING)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown)
else
remove_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE)
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
return mobility_flags
+19 -19
View File
@@ -36,38 +36,26 @@
sprint_stamina_cost = CONFIG_GET(number/movedelay/sprint_stamina_cost)
return ..()
/mob/living/movement_delay(ignorewalk = 0)
. = ..()
if(!CHECK_MOBILITY(src, MOBILITY_STAND))
. += 6
/// whether or not we can slide under another living mob. defaults to if we're not dense. CanPass should check "overriding circumstances" like buckled mobs/having PASSMOB flag, etc.
/mob/living/proc/can_move_under_living(mob/living/other)
return !density
/mob/living/proc/update_move_intent_slowdown()
var/mod = 0
if(m_intent == MOVE_INTENT_WALK)
mod = CONFIG_GET(number/movedelay/walk_delay)
else
mod = CONFIG_GET(number/movedelay/run_delay)
if(!isnum(mod))
mod = 1
add_movespeed_modifier(MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED, TRUE, 100, override = TRUE, multiplicative_slowdown = mod)
add_movespeed_modifier((m_intent == MOVE_INTENT_WALK)? /datum/movespeed_modifier/config_walk_run/walk : /datum/movespeed_modifier/config_walk_run/run)
/mob/living/proc/update_turf_movespeed(turf/open/T)
if(isopenturf(T) && !is_flying())
add_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = T.slowdown)
if(isopenturf(T))
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown, multiplicative_slowdown = T.slowdown)
else
remove_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD)
remove_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown)
/mob/living/proc/update_pull_movespeed()
if(pulling && isliving(pulling))
var/mob/living/L = pulling
if(drag_slowdown && L.lying && !L.buckled && grab_state < GRAB_AGGRESSIVE)
add_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING, multiplicative_slowdown = PULL_PRONE_SLOWDOWN)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN)
return
remove_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING)
remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag)
/mob/living/canZMove(dir, turf/target)
return can_zTravel(target, dir) && (movement_type & FLYING)
@@ -87,8 +75,12 @@
. = ..()
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1 && (pulledby != moving_from_pull))//separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
else
if(isliving(pulledby))
var/mob/living/L = pulledby
L.set_pull_offsets(src, pulledby.grab_state)
if(active_storage && !(CanReach(active_storage.parent,view_only = TRUE)))
active_storage.close(src)
@@ -96,6 +88,14 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
/mob/living/Move_Pulled(atom/A)
. = ..()
if(!. || !isliving(A))
return
var/mob/living/L = A
set_pull_offsets(L, grab_state)
/mob/living/forceMove(atom/destination)
stop_pulling()
if(buckled)
+6 -1
View File
@@ -33,7 +33,7 @@
update_sprint_icon()
/mob/living/proc/disable_sprint_mode(update_icon = TRUE)
if(!(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE))
if(!(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) || (combat_flags & COMBAT_FLAG_SPRINT_FORCED))
return
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_ACTIVE)
if(update_icon)
@@ -51,6 +51,8 @@
/mob/living/proc/disable_intentional_sprint_mode()
if(!(combat_flags & COMBAT_FLAG_SPRINT_TOGGLED) && !(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE))
return
if(combat_flags & COMBAT_FLAG_SPRINT_FORCED)
return
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_TOGGLED)
if(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
disable_sprint_mode(FALSE)
@@ -59,6 +61,9 @@
/mob/living/proc/user_toggle_intentional_sprint_mode()
var/old = (combat_flags & COMBAT_FLAG_SPRINT_TOGGLED)
if(old)
if(combat_flags & COMBAT_FLAG_SPRINT_FORCED)
to_chat(src, "<span class='warning'>You are unable to stop sprinting!</span>")
return
disable_intentional_sprint_mode()
if((m_intent == MOVE_INTENT_RUN) && CHECK_ALL_MOBILITY(src, MOBILITY_STAND|MOBILITY_MOVE))
playsound_local(src, 'sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE)
+10 -10
View File
@@ -133,7 +133,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/datum/language/message_language = get_message_language(message)
if(message_language)
// No, you cannot speak in xenocommon just because you know the key
if(can_speak_in_language(message_language))
if(can_speak_language(message_language))
language = message_language
message = copytext_char(message, 3)
@@ -141,7 +141,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
message = trim_left(message)
if(!language)
language = get_default_language()
language = get_selected_language()
// Detection of language needs to be before inherent channels, because
// AIs use inherent channels for the holopad. Most inherent channels
@@ -237,6 +237,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
deaf_message = "<span class='notice'>You can't hear yourself!</span>"
deaf_type = 2 // Since you should be able to hear yourself without looking
// Create map text prior to modifying message for goonchat
if (client?.prefs.chat_on_map && stat != UNCONSCIOUS && (client.prefs.see_chat_non_mob || ismob(speaker)) && can_hear())
create_chat_message(speaker, message_language, raw_message, spans, message_mode)
// Recompose message for AI hrefs, language incomprehension.
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)
@@ -289,7 +293,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
//speech bubble
var/list/speech_bubble_recipients = list()
for(var/mob/M in listening)
if(M.client)
if(M.client && !M.client.prefs.chat_on_map)
speech_bubble_recipients.Add(M.client)
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
@@ -411,11 +415,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced)
/mob/living/get_language_holder(shadow=TRUE)
if(mind && shadow)
// Mind language holders shadow mob holders.
. = mind.get_language_holder()
if(.)
return .
/mob/living/get_language_holder(get_minds = TRUE)
if(get_minds && mind)
return mind.get_language_holder()
. = ..()
+7 -7
View File
@@ -822,21 +822,21 @@
return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5)
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
var/start = "Relayed Speech: "
var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]"
var/hrefpart = "<a href='?src=[REF(src)];track=[html_encode(namepart)]'>"
var/jobpart
var/jobpart = "Unknown"
if (iscarbon(speaker))
var/mob/living/carbon/S = speaker
if(S.job)
jobpart = "[S.job]"
else
jobpart = "Unknown"
var/rendered = "<i><span class='game say'>[start]<span class='name'>[hrefpart][namepart] ([jobpart])</a> </span><span class='message'>[raw_message]</span></span></i>"
var/rendered = "<i><span class='game say'>[start]<span class='name'>[hrefpart][namepart] ([jobpart])</a> </span><span class='message'>[treated_message]</span></span></i>"
if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker)))
create_chat_message(speaker, message_language, raw_message, spans, message_mode)
show_message(rendered, MSG_AUDIBLE)
/mob/living/silicon/ai/fully_replace_character_name(oldname,newname)
@@ -869,7 +869,7 @@
if(istype(A, /obj/machinery/camera))
current = A
if(client)
if(ismovableatom(A))
if(ismovable(A))
if(A != GLOB.ai_camera_room_landmark)
end_multicam()
client.perspective = EYE_PERSPECTIVE
@@ -1016,7 +1016,7 @@
if("Yes.")
src.ghostize(FALSE, penalize = TRUE)
var/announce_rank = "Artificial Intelligence,"
if(GLOB.announcement_systems.len)
if(GLOB.announcement_systems.len)
// Sends an announcement the AI has cryoed.
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
announcer.announce("CRYOSTORAGE", src.real_name, announce_rank, list())
@@ -171,10 +171,3 @@
#undef VOX_DELAY
#endif
/mob/living/silicon/ai/could_speak_in_language(datum/language/dt)
if(is_servant_of_ratvar(src))
// Ratvarian AIs can only speak Ratvarian
. = ispath(dt, /datum/language/ratvar)
else
. = ..()
+4 -4
View File
@@ -154,7 +154,7 @@
/mob/living/silicon/pai/proc/process_hack()
if(cable && cable.machine && istype(cable.machine, /obj/machinery/door) && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1)
hackprogress = CLAMP(hackprogress + 4, 0, 100)
hackprogress = clamp(hackprogress + 4, 0, 100)
else
temp = "Door Jack: Connection to airlock has been lost. Hack aborted."
hackprogress = 0
@@ -273,9 +273,9 @@
/mob/living/silicon/pai/Process_Spacemove(movement_dir = 0)
. = ..()
if(!.)
add_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE, 100, multiplicative_slowdown = 2)
add_movespeed_modifier(/datum/movespeed_modifier/pai_spacewalk)
return TRUE
remove_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE)
remove_movespeed_modifier(/datum/movespeed_modifier/pai_spacewalk)
return TRUE
/mob/living/silicon/pai/examine(mob/user)
@@ -301,7 +301,7 @@
update_stat()
/mob/living/silicon/pai/process()
emitterhealth = CLAMP((emitterhealth + emitterregen), -50, emittermaxhealth)
emitterhealth = clamp((emitterhealth + emitterregen), -50, emittermaxhealth)
/obj/item/paicard/attackby(obj/item/W, mob/user, params)
..()
@@ -69,7 +69,7 @@
return FALSE //No we're not flammable
/mob/living/silicon/pai/proc/take_holo_damage(amount)
emitterhealth = CLAMP((emitterhealth - amount), -50, emittermaxhealth)
emitterhealth = clamp((emitterhealth - amount), -50, emittermaxhealth)
if(emitterhealth < 0)
fold_in(force = TRUE)
if(amount > 0)
@@ -267,9 +267,8 @@
if(href_list["toggle"])
encryptmod = TRUE
if("translator")
if(href_list["toggle"])
grant_all_languages(TRUE)
// this is PERMAMENT.
if(href_list["toggle"]) //This is permanent.
grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE)
if("doorjack")
if(href_list["jack"])
if(cable && cable.machine)
@@ -21,7 +21,7 @@
if(cell && cell.charge)
if(cell.charge <= 100)
uneq_all()
var/amt = CLAMP((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
var/amt = clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
cell.use(amt) //Usage table: 1/tick if off/lowest setting, 4 = 4/tick, 6 = 8/tick, 8 = 12/tick, 10 = 16/tick
else
uneq_all()
@@ -237,7 +237,7 @@
return
if(!CONFIG_GET(flag/disable_secborg) && GLOB.security_level < CONFIG_GET(number/minimum_secborg_alert))
to_chat(src, "<span class='notice'>NOTICE: Due to local station regulations, the security cyborg module and its variants are only available during [num2seclevel(CONFIG_GET(number/minimum_secborg_alert))] alert and greater.</span>")
to_chat(src, "<span class='notice'>NOTICE: Due to local station regulations, the security cyborg module and its variants are only available during [NUM2SECLEVEL(CONFIG_GET(number/minimum_secborg_alert))] alert and greater.</span>")
var/list/modulelist = list("Standard" = /obj/item/robot_module/standard, \
"Engineering" = /obj/item/robot_module/engineering, \
@@ -427,24 +427,23 @@
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/stack/cable_coil/coil = W
if (getFireLoss() > 0 || getToxLoss() > 0)
if(src == user && coil.use(1))
if(src == user)
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
if(!do_after(user, 50, target = src))
if(!W.use_tool(src, user, 50, 1, max_level = JOB_SKILL_TRAINED))
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
return
adjustFireLoss(-10)
adjustToxLoss(-10)
if (coil.use(1))
else
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
if(!do_after(user, 30, target = src))
if(!W.use_tool(src, user, 30, 1))
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
return
adjustFireLoss(-30)
adjustToxLoss(-30)
updatehealth()
user.visible_message("[user] has fixed some of the burnt wires on [src].", "<span class='notice'>You fix some of the burnt wires on [src].</span>")
else
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
else
to_chat(user, "The wires seem fine, there's no need to fix them.")
@@ -276,6 +276,19 @@
R.hud_used.update_robot_modules_display()
SSblackbox.record_feedback("tally", "cyborg_modules", 1, R.module)
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
*/
/obj/item/robot_module/proc/check_menu(mob/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/robot_module/standard
name = "Standard"
basic_modules = list(
@@ -337,13 +350,28 @@
/obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/medmodels = list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot", "Medihound", "Medihound Dark", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
medmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in medmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/med_icons
if(!med_icons)
med_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "medical"),
"Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "medical"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"),
"Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed")
)
var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
med_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-med")
bad_snowflake.pixel_x = -16
med_icons["Alina"] = bad_snowflake
med_icons = sortList(med_icons)
var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(med_borg_icon)
if("Default")
cyborg_base_icon = "medical"
if("Droid")
@@ -391,6 +419,8 @@
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/engineering
@@ -434,13 +464,31 @@
/obj/item/robot_module/engineering/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
engymodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in engymodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/engi_icons
if(!engi_icons)
engi_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "engineer"),
"Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "engi-tread"),
"Loader" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "loaderborg"),
"Handy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "handyeng"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekeng"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng")
)
var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
engi_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-eng")
bad_snowflake.pixel_x = -16
engi_icons["Alina"] = bad_snowflake
engi_icons = sortList(engi_icons)
var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(engi_borg_icon)
if("Default")
cyborg_base_icon = "engineer"
if("Default - Treads")
@@ -485,6 +533,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "alinasleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/security
@@ -512,13 +562,29 @@
/obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
secmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/sec_icons
if(!sec_icons)
sec_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "sec"),
"Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sec-tread"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleeksec"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec")
)
var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
sec_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
bad_snowflake.pixel_x = -16
sec_icons["Alina"] = bad_snowflake
sec_icons = sortList(sec_icons)
var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(sec_borg_icon)
if("Default")
cyborg_base_icon = "sec"
if("Default - Treads")
@@ -561,6 +627,8 @@
sleeper_overlay = "valesecsleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/security/Initialize()
@@ -599,10 +667,13 @@
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Spider", "Borgi")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/peace_icons = sortList(list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
"Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider")
))
var/peace_borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(peace_borg_icon)
if("Default")
cyborg_base_icon = "peace"
if("Spider")
@@ -615,6 +686,8 @@
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
has_snowflake_deadsprite = TRUE
else
return FALSE
return ..()
//Janitor module combined with Service module
@@ -738,10 +811,35 @@
/obj/item/robot_module/butler/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("(Service) Waitress", "(Service) Heavy", "(Service) Sleek", "(Service) Butler", "(Service) Tophat", "(Service) Can", "(Service) Bro", "(Service) DarkK9", "(Service) Vale", "(Service) ValeDark", "(Janitor) Default", "(Janitor) Sleek", "(Janitor) Marina", "(Janitor) Can", "(Janitor) Heavy", "(Janitor) Scrubpuppy")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/service_icons
if(!service_icons)
service_icons = list(
"(Service) Waitress" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_f"),
"(Service) Butler" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_m"),
"(Service) Bro" = image(icon = 'icons/mob/robots.dmi', icon_state = "brobot"),
"(Service) Can" = image(icon = 'icons/mob/robots.dmi', icon_state = "kent"),
"(Service) Tophat" = image(icon = 'icons/mob/robots.dmi', icon_state = "tophat"),
"(Service) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekserv"),
"(Service) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyserv"),
"(Janitor) Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "janitor"),
"(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"),
"(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"),
"(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"),
"(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"),
)
var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
"(Janitor) Scrubpuppy" = "scrubpup")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
service_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
bad_snowflake.pixel_x = -16
service_icons["Alina"] = bad_snowflake
service_icons = sortList(service_icons)
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(service_robot_icon)
if("(Service) Waitress")
cyborg_base_icon = "service_f"
special_light_key = "service"
@@ -799,6 +897,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "jsleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/miner
@@ -833,10 +933,25 @@
/obj/item/robot_module/miner/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Lavaland", "Heavy", "Sleek", "Marina", "Can", "Spider", "Asteroid", "Droid", "Blade", "Vale")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/mining_icons
if(!mining_icons)
mining_icons = list(
"Lavaland" = image(icon = 'icons/mob/robots.dmi', icon_state = "miner"),
"Asteroid" = image(icon = 'icons/mob/robots.dmi', icon_state = "minerOLD"),
"Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "miner"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"),
)
var/list/L = list("Blade" = "blade", "Vale" = "valemine")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
mining_icons[a] = wide
mining_icons = sortList(mining_icons)
var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(mining_borg_icon)
if("Lavaland")
cyborg_base_icon = "miner"
if("Asteroid")
@@ -871,6 +986,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "valeminesleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/syndicate
@@ -1,3 +1,5 @@
/mob/living/silicon/KnockToFloor(disarm_items = FALSE, silent = TRUE, updating = TRUE)
return
/mob/living/silicon/grippedby(mob/living/user, instant = FALSE)
return //can't upgrade a simple pull into a more aggressive grab.
@@ -113,7 +115,7 @@
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
var/list/returnlist = list()
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
var/returned = mob_run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
if(returned & BLOCK_SHOULD_REDIRECT)
handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD])
if(returned & BLOCK_REDIRECTED)
@@ -61,11 +61,10 @@
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(M, src, "disarmed")
else
var/damage = rand(15, 30)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
attack_threshold_check(damage)
attack_threshold_check(M.meleeSlashSAPower)
log_combat(M, src, "attacked")
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
@@ -911,7 +911,6 @@ Pass a positive integer as an argument to override a bot's default speed.
bot_name = name
name = paicard.pai.name
faction = user.faction.Copy()
language_holder = paicard.pai.language_holder.copy(src)
log_combat(user, paicard.pai, "uploaded to [bot_name],")
return TRUE
else
@@ -19,6 +19,11 @@
path_image_color = "#993299"
weather_immunities = list("lava","ash")
var/clean_time = 50 //How long do we take to clean?
var/broom = FALSE //Do we have an speed buff from a broom?
var/adv_mop = FALSE //Do we have a cleaning buff from a better mop?
var/blood = 1
var/trash = 0
var/pests = 0
@@ -75,6 +80,26 @@
to_chat(user, "<span class='warning'>Please close the access panel before locking it.</span>")
else
to_chat(user, "<span class='notice'>\The [src] doesn't seem to respect your authority.</span>")
if(istype(W, /obj/item/mop/advanced))
if(bot_core.allowed(user) && open && adv_mop == TRUE)
to_chat(user, "<span class='notice'>You replace \the [src] old mop with a new better one!</span>")
adv_mop = TRUE
clean_time = 20 //2.5 the speed!
window_name = "Automatic Station Cleaner v2.1 BETA" //New!
qdel(W)
else
to_chat(user, "<span class='notice'>\the [src] already has this mop!</span>")
if(istype(W, /obj/item/twohanded/broom))
if(bot_core.allowed(user) && open && broom == TRUE)
to_chat(user, "<span class='notice'>You add to \the [src] a broom speeding it up!</span>")
broom = TRUE
base_speed = 1 //2x faster!
qdel(W)
else
to_chat(user, "<span class='notice'>\the [src] already has a broom!</span>")
else
return ..()
@@ -221,7 +246,7 @@
icon_state = "cleanbot-c"
visible_message("<span class='notice'>[src] begins to clean up [A].</span>")
mode = BOT_CLEANING
spawn(50)
spawn(clean_time)
if(mode == BOT_CLEANING)
if(A && isturf(A.loc))
var/atom/movable/AM = A
@@ -147,9 +147,8 @@
to_chat(user, "<span class='warning'>You need one length of cable to wire the ED-209!</span>")
return
to_chat(user, "<span class='notice'>You start to wire [src]...</span>")
if(do_after(user, 40, target = src))
if(coil.get_amount() >= 1 && build_step == 6)
coil.use(1)
if(coil.use_tool(src, user, 40, 1))
if(build_step == 6)
to_chat(user, "<span class='notice'>You wire [src].</span>")
name = "wired ED-209 assembly"
build_step++
@@ -264,6 +264,9 @@
if((last_newpatient_speak + 300) < world.time) //Don't spam these messages!
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg')
var/message = pick(messagevoice)
if(prob(1) && ISINRANGE_EX(H.getFireLoss(), 0, 20))
message = "Notices your minor burns*OwO what's this?"
messagevoice[message] = 'sound/voice/medbot/owo.ogg'
speak(message)
playsound(loc, messagevoice[message], 50, 0)
last_newpatient_speak = world.time
@@ -20,7 +20,7 @@
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/armor/vest
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/tackler/combat/insulated
ears = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas
head = /obj/item/clothing/head/helmet/swat
@@ -39,7 +39,7 @@
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/syndi
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/tackler/combat/insulated
ears = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas/syndicate
back = /obj/item/tank/jetpack/oxygen
@@ -59,7 +59,7 @@
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/tackler/combat
ears = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas/syndicate
back = /obj/item/tank/jetpack/oxygen/harness
@@ -130,7 +130,7 @@
uniform = /obj/item/clothing/under/syndicate/camo
suit = /obj/item/clothing/suit/armor/bulletproof
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/tackler/combat
ears = /obj/item/radio/headset
head = /obj/item/clothing/head/helmet/alt
mask = /obj/item/clothing/mask/balaclava
@@ -177,7 +177,7 @@
uniform = /obj/item/clothing/under/rank/security/officer
suit = /obj/item/clothing/suit/armor/vest
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/tackler/combat
ears = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas/sechailer/swat
head = /obj/item/clothing/head/helmet/swat/nanotrasen
@@ -2,7 +2,7 @@
/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = round(CLAMP(bruteloss + amount, 0, maxHealth),DAMAGE_PRECISION)
bruteloss = round(clamp(bruteloss + amount, 0, maxHealth),DAMAGE_PRECISION)
if(updating_health)
updatehealth()
return amount
@@ -87,7 +87,6 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
held_icon = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -99,6 +98,7 @@
gender = FEMALE
gold_core_spawnable = NO_SPAWN
unique_pet = TRUE
held_icon = "cat"
var/list/family = list()//var restored from savefile, has count of each child type
var/list/children = list()//Actual mob instances of children
var/cats_deployed = 0
@@ -11,7 +11,7 @@
blood_volume = 350
speak_chance = 1
turns_per_move = 5
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/rawcrab = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/rawcrab = 4)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "stomps"
@@ -97,6 +97,8 @@
body_color = "brown"
icon_state = "mouse_brown"
GLOBAL_VAR(tom_existed)
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
name = "Tom"
@@ -106,6 +108,10 @@
response_harm = "splats"
gold_core_spawnable = NO_SPAWN
/mob/living/simple_animal/mouse/brown/Tom/Initialize()
. = ..()
GLOB.tom_existed = TRUE
/obj/item/reagent_containers/food/snacks/deadmouse
name = "dead mouse"
desc = "It looks like somebody dropped the bass on it. A lizard's favorite meal."
@@ -54,7 +54,7 @@
var/blocked = FALSE
if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them
blocked = TRUE
if(L.run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
if(L.mob_run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src, null, null) & BLOCK_SUCCESS)
blocked = TRUE
if(!blocked)
L.drop_all_held_items()
@@ -175,7 +175,7 @@
AddElement(/datum/element/cleaning)
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(ismovableatom(target))
if(ismovable(target))
if(istype(target, /obj/effect/decal/cleanable))
visible_message("[src] cleans up \the [target].")
qdel(target)
@@ -7,7 +7,7 @@
icon_living = "carp"
icon_dead = "carp_dead"
icon_gib = "carp_gib"
threat = 0.2
threat = 0.1
mob_biotypes = MOB_ORGANIC|MOB_BEAST
speak_chance = 0
turns_per_move = 5
@@ -186,10 +186,10 @@
. = ..()
if(slowed_by_webs)
if(!(locate(/obj/structure/spider/stickyweb) in loc))
remove_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB)
remove_movespeed_modifier(/datum/movespeed_modifier/tarantula_web)
slowed_by_webs = FALSE
else if(locate(/obj/structure/spider/stickyweb) in loc)
add_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB, priority=100, multiplicative_slowdown=3)
add_movespeed_modifier(/datum/movespeed_modifier/tarantula_web)
slowed_by_webs = TRUE
//midwives are the queen of the spiders, can send messages to all them and web faster. That rare round where you get a queen spider and turn your 'for honor' players into 'r6siege' players will be a fun one.
@@ -265,4 +265,12 @@ Difficulty: Medium
desc = "The sweet blood, oh, it sings to me."
invisibility = 100
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom
name = "hostile-environment miner"
desc = "A miner destined to hop across dimensions for all eternity, hunting anomalous creatures."
speed = 8
move_to_delay = 8
ranged_cooldown_time = 8
dash_cooldown = 8
#undef MINER_DASH_RANGE
@@ -65,10 +65,10 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = CLAMP(round((health/maxHealth) * 10), 3, 10)
move_to_delay = clamp(round((health/maxHealth) * 10), 3, 10)
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
anger_modifier = CLAMP(((maxHealth - health)/50),0,20)
anger_modifier = clamp(((maxHealth - health)/50),0,20)
if(charging)
return
ranged_cooldown = world.time + ranged_cooldown_time
@@ -56,7 +56,7 @@ Difficulty: Very Hard
L.dust()
/mob/living/simple_animal/hostile/megafauna/colossus/OpenFire()
anger_modifier = CLAMP(((maxHealth - health)/50),0,20)
anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + 120
if(enrage(target))
@@ -0,0 +1,361 @@
/*
Difficulty: Extremely Hard
*/
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner
name = "demonic-frost miner"
desc = "An extremely geared miner, driven crazy or possessed by the demonic forces here, either way a terrifying enemy."
health = 1500
maxHealth = 1500
icon_state = "demonic_miner"
icon_living = "demonic_miner"
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
attacktext = "pummels"
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
light_color = "#E4C7C5"
movement_type = GROUND
weather_immunities = list("snow")
speak_emote = list("roars")
armour_penetration = 100
melee_damage_lower = 10
melee_damage_upper = 10
aggro_vision_range = 18 // large vision range so combat doesn't abruptly end when someone runs a bit away
rapid_melee = 4
speed = 20
move_to_delay = 20
ranged = TRUE
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman)
loot = list(/obj/effect/decal/remains/plasma)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
deathmessage = "falls to the ground, decaying into plasma particles."
deathsound = "bodyfall"
attack_action_types = list(/datum/action/innate/megafauna_attack/frost_orbs,
/datum/action/innate/megafauna_attack/snowball_machine_gun,
/datum/action/innate/megafauna_attack/ice_shotgun)
/// Modifies the speed of the projectiles the demonic frost miner shoots out
var/projectile_speed_multiplier = 1
/// If the demonic frost miner is in its enraged state
var/enraged = FALSE
/// If the demonic frost miner is currently transforming to its enraged state
var/enraging = FALSE
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Initialize()
. = ..()
AddComponent(/datum/component/knockback, 7, FALSE, TRUE)
AddComponent(/datum/component/lifesteal, 50)
/datum/action/innate/megafauna_attack/frost_orbs
name = "Fire Frost Orbs"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
chosen_message = "<span class='colossus'>You are now sending out frost orbs to track in on a target.</span>"
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/snowball_machine_gun
name = "Fire Snowball Machine Gun"
icon_icon = 'icons/obj/guns/energy.dmi'
button_icon_state = "kineticgun"
chosen_message = "<span class='colossus'>You are now firing a snowball machine gun at a target.</span>"
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/ice_shotgun
name = "Fire Ice Shotgun"
icon_icon = 'icons/obj/guns/projectile.dmi'
button_icon_state = "shotgun"
chosen_message = "<span class='colossus'>You are now firing shotgun ice blasts.</span>"
chosen_attack_num = 3
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/OpenFire()
check_enraged()
projectile_speed_multiplier = 1 - enraged * 0.25
SetRecoveryTime(100, 100)
if(client)
switch(chosen_attack)
if(1)
frost_orbs()
if(2)
snowball_machine_gun()
if(3)
ice_shotgun()
return
var/easy_attack = prob(80 - enraged * 40)
chosen_attack = rand(1, 3)
switch(chosen_attack)
if(1)
if(easy_attack)
frost_orbs(10, 8)
else
frost_orbs(5, 16)
if(2)
if(easy_attack)
snowball_machine_gun()
else
INVOKE_ASYNC(src, .proc/ice_shotgun, 5, list(list(-180, -140, -100, -60, -20, 20, 60, 100, 140), list(-160, -120, -80, -40, 0, 40, 80, 120, 160)))
snowball_machine_gun(5 * 8, 5)
if(3)
if(easy_attack)
ice_shotgun()
else
ice_shotgun(5, list(list(0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330), list(-30, -15, 0, 15, 30)))
/obj/item/projectile/frost_orb
name = "frost orb"
icon_state = "ice_1"
damage = 20
armour_penetration = 100
speed = 10
homing_turn_speed = 30
damage_type = BURN
/obj/item/projectile/frost_orb/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
/obj/item/projectile/snowball
name = "machine-gun snowball"
icon_state = "nuclear_particle"
damage = 5
armour_penetration = 100
speed = 4
damage_type = BRUTE
/obj/item/projectile/ice_blast
name = "ice blast"
icon_state = "ice_2"
damage = 15
armour_penetration = 100
speed = 4
damage_type = BRUTE
/obj/item/projectile/ice_blast/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/ex_act(severity, target)
adjustBruteLoss(30 * severity - 120)
visible_message("<span class='danger'>[src] absorbs the explosion!</span>", "<span class='userdanger'>You absorb the explosion!</span>")
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Goto(target, delay, minimum_distance)
if(enraging)
return
return ..()
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/MoveToTarget(list/possible_targets)
if(enraging)
return
return ..()
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Move()
if(enraging)
return
return ..()
/// Shoots out homing frost orbs that explode into ice blast projectiles after a couple seconds
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/frost_orbs(added_delay = 10, shoot_times = 8)
for(var/i in 1 to shoot_times)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/frost_orb/P = new(startloc)
P.preparePixelProjectile(endloc, startloc)
P.firer = src
if(target)
P.original = target
P.set_homing_target(target)
P.fire(rand(0, 360))
addtimer(CALLBACK(P, /obj/item/projectile/frost_orb/proc/orb_explosion, projectile_speed_multiplier), 20) // make the orbs home in after a second
SLEEP_CHECK_DEATH(added_delay)
SetRecoveryTime(40, 60)
/// Called when the orb is exploding, shoots out projectiles
/obj/item/projectile/frost_orb/proc/orb_explosion(projectile_speed_multiplier)
for(var/i in 0 to 5)
var/angle = i * 60
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(original)
if(!startloc || !endloc)
break
var/obj/item/projectile/ice_blast/P = new(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, angle + rand(-10, 10))
P.firer = firer
if(original)
P.original = original
P.fire()
qdel(src)
/// Shoots out snowballs with a random spread
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/snowball_machine_gun(shots = 60, spread = 45)
for(var/i in 1 to shots)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/snowball(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, rand(-spread, spread))
P.firer = src
if(target)
P.original = target
P.fire()
SLEEP_CHECK_DEATH(1)
SetRecoveryTime(15, 15)
/// Shoots out ice blasts in a shotgun like pattern
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/ice_shotgun(shots = 5, list/patterns = list(list(-40, -20, 0, 20, 40), list(-30, -10, 10, 30)))
for(var/i in 1 to shots)
var/list/pattern = patterns[i % length(patterns) + 1] // alternating patterns
for(var/spread in pattern)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/ice_blast(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, spread)
P.firer = src
if(target)
P.original = target
P.fire()
SLEEP_CHECK_DEATH(8)
SetRecoveryTime(15, 20)
/// Checks if the demonic frost miner is ready to be enraged
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/check_enraged()
if(enraged)
return
if(health > maxHealth*0.25)
return
SetRecoveryTime(80, 80)
adjustHealth(-maxHealth)
enraged = TRUE
enraging = TRUE
animate(src, pixel_y = pixel_y + 96, time = 100, easing = ELASTIC_EASING)
spin(100, 10)
SLEEP_CHECK_DEATH(60)
playsound(src, 'sound/effects/explosion3.ogg', 100, TRUE)
icon_state = "demonic_miner_phase2"
animate(src, pixel_y = pixel_y - 96, time = 8, flags = ANIMATION_END_NOW)
spin(8, 2)
SLEEP_CHECK_DEATH(8)
for(var/mob/living/L in viewers(src))
shake_camera(L, 3, 2)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
setMovetype(movement_type | FLYING)
enraging = FALSE
adjustHealth(-maxHealth)
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/death(gibbed, list/force_grant)
if(health > 0)
return
var/turf/T = get_turf(src)
var/loot = rand(1, 3)
switch(loot)
if(1)
new /obj/item/resurrection_crystal(T)
if(2)
new /obj/item/clothing/shoes/winterboots/ice_boots/speedy(T)
if(3)
new /obj/item/pickaxe/drill/jackhammer/demonic(T)
return ..()
/obj/item/resurrection_crystal
name = "resurrection crystal"
desc = "When used by anything holding it, this crystal gives them a second chance at life if they die."
icon = 'icons/obj/objects.dmi'
icon_state = "demonic_crystal"
/obj/item/resurrection_crystal/attack_self(mob/living/user)
if(!iscarbon(user))
to_chat(user, "<span class='notice'>A dark presence stops you from absorbing the crystal.</span>")
return
forceMove(user)
to_chat(user, "<span class='notice'>You feel a bit safer... but a demonic presence lurks in the back of your head...</span>")
RegisterSignal(user, COMSIG_MOB_DEATH, .proc/resurrect)
/// Resurrects the target when they die by cloning them into a new duplicate body and transferring their mind to the clone on a safe station turf
/obj/item/resurrection_crystal/proc/resurrect(mob/living/carbon/user, gibbed)
user.visible_message("<span class='notice'>You see [user]'s soul dragged out of their body!</span>", "<span class='notice'>You feel your soul dragged away to a fresh body!</span>")
var/typepath = user.type
var/turf/T = find_safe_turf()
var/mob/living/carbon/clone = new typepath(T)
clone.real_name = user.real_name
user.dna.transfer_identity(clone)
clone.updateappearance(mutcolor_update=1)
user.mind.transfer_to(clone) // second life
to_chat(clone, "<span class='notice'>You blink and find yourself in [get_area_name(T)].</span>")
user.gib()
qdel(src)
/obj/item/clothing/shoes/winterboots/ice_boots/speedy
name = "cursed ice hiking boots"
desc = "A pair of winter boots contractually made by a devil, they cannot be taken off once put on."
slowdown = SHOES_SPEED_SLIGHT
/obj/item/clothing/shoes/winterboots/ice_boots/speedy/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_ITEM_TRAIT)
/obj/item/pickaxe/drill/jackhammer/demonic
name = "demonic jackhammer"
desc = "Cracks rocks at an inhuman speed, as well as being enhanced for combat purposes."
toolspeed = 0
/obj/item/pickaxe/drill/jackhammer/demonic/Initialize()
. = ..()
AddComponent(/datum/component/knockback, 4, FALSE, TRUE)
AddComponent(/datum/component/lifesteal, 5)
/obj/item/crusher_trophy/ice_block_talisman
name = "ice block talisman"
desc = "A glowing trinket that a demonic miner had on him, it seems he couldn't utilize it for whatever reason."
icon_state = "ice_trap_talisman"
denied_type = /obj/item/crusher_trophy/ice_block_talisman
/obj/item/crusher_trophy/ice_block_talisman/effect_desc()
return "mark detonation to freeze a creature in a block of ice for a period, preventing them from moving"
/obj/item/crusher_trophy/ice_block_talisman/on_mark_detonation(mob/living/target, mob/living/user)
target.apply_status_effect(/datum/status_effect/ice_block_talisman)
/datum/status_effect/ice_block_talisman
id = "ice_block_talisman"
duration = 25
status_type = STATUS_EFFECT_REFRESH
alert_type = /obj/screen/alert/status_effect/ice_block_talisman
/// Stored icon overlay for the hit mob, removed when effect is removed
var/icon/cube
/obj/screen/alert/status_effect/ice_block_talisman
name = "Frozen Solid"
desc = "You're frozen inside an ice cube, and cannot move!"
icon_state = "frozen"
/datum/status_effect/ice_block_talisman/on_apply()
RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/owner_moved)
if(!owner.stat)
to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>")
cube = icon('icons/effects/freeze.dmi', "ice_cube")
var/icon/size_check = icon(owner.icon, owner.icon_state)
cube.Scale(size_check.Width(), size_check.Height())
owner.add_overlay(cube)
return ..()
/// Blocks movement from the status effect owner
/datum/status_effect/ice_block_talisman/proc/owner_moved()
return COMPONENT_MOVABLE_BLOCK_PRE_MOVE
/datum/status_effect/ice_block_talisman/on_remove()
. = ..()
if(!owner.stat)
to_chat(owner, "<span class='notice'>The cube melts!</span>")
owner.cut_overlay(cube)
UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE)
@@ -105,7 +105,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
if(swooping)
return
anger_modifier = CLAMP(((maxHealth - health)/50),0,20)
anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + ranged_cooldown_time
if(prob(15 + anger_modifier) && !client)
@@ -394,3 +394,26 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
//fire line keeps going even if dragon is deleted
/proc/dragon_fire_line(source, list/turfs)
var/list/hit_list = list()
for(var/turf/T in turfs)
if(istype(T, /turf/closed))
break
new /obj/effect/hotspot(T)
T.hotspot_expose(700,50,1)
for(var/mob/living/L in T.contents)
if(L in hit_list || L == source)
continue
hit_list += L
L.adjustFireLoss(20)
to_chat(L, "<span class='userdanger'>You're hit by [source]'s fire breath!</span>")
// deals damage to mechs
for(var/obj/mecha/M in T.contents)
if(M in hit_list)
continue
hit_list += M
M.take_damage(45, BRUTE, "melee", 1)
sleep(1.5)
@@ -191,7 +191,7 @@ Difficulty: Normal
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall
did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall
anger_modifier = CLAMP(((maxHealth - health) / 42),0,50)
anger_modifier = clamp(((maxHealth - health) / 42),0,50)
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)

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