Merge remote-tracking branch 'upstream/master' into slime-legs

This commit is contained in:
Timothy Teakettle
2020-12-28 17:22:53 +00:00
1080 changed files with 54402 additions and 21299 deletions
+4 -1
View File
@@ -12,6 +12,7 @@
sight = SEE_SELF
move_on_shuttle = FALSE
/mob/camera/experience_pressure_difference()
return
@@ -23,5 +24,7 @@
/mob/camera/canUseStorage()
return FALSE
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE, forced = FALSE)
if(forced)
return ..()
return
+1 -1
View File
@@ -4,4 +4,4 @@
if(!spawning)//Here so that if they are spawning and log out, the other procs can play out and they will have a mob to come back to.
key = null//We null their key before deleting the mob, so they are properly kicked out.
qdel(src)
return
return
+115 -1
View File
@@ -16,6 +16,9 @@
//Used to make sure someone doesn't get spammed with messages if they're ineligible for roles
var/ineligible_for_roles = FALSE
//is there a result we want to read from the age gate
var/age_gate_result
/mob/dead/new_player/Initialize()
if(client && SSticker.state == GAME_STATE_STARTUP)
var/obj/screen/splash/S = new(client, TRUE, TRUE)
@@ -78,6 +81,67 @@
popup.set_content(output)
popup.open(FALSE)
/mob/dead/new_player/proc/age_gate()
var/list/dat = list("<center>")
dat += "Enter your date of birth here, to confirm that you are over 18.<BR>"
dat += "<b>Your date of birth is not saved, only the fact that you are over/under 18 is.</b><BR>"
dat += "</center>"
dat += "<form action='?src=[REF(src)]'>"
dat += "<input type='hidden' name='src' value='[REF(src)]'>"
dat += HrefTokenFormField()
dat += "<select name = 'Month'>"
var/monthList = list("January" = 1, "February" = 2, "March" = 3, "April" = 4, "May" = 5, "June" = 6, "July" = 7, "August" = 8, "September" = 9, "October" = 10, "November" = 11, "December" = 12)
for(var/month in monthList)
dat += "<option value = [monthList[month]]>[month]</option>"
dat += "</select>"
dat += "<select name = 'Year' style = 'float:right'>"
var/current_year = text2num(time2text(world.realtime, "YYYY"))
var/start_year = 1920
for(var/year in start_year to current_year)
var/reverse_year = 1920 + (current_year - year)
dat += "<option value = [reverse_year]>[reverse_year]</option>"
dat += "</select>"
dat += "<center><input type='submit' value='Submit information'></center>"
dat += "</form>"
winshow(src, "age_gate", TRUE)
var/datum/browser/popup = new(src, "age_gate", "<div align='center'>Age Gate</div>", 400, 250)
popup.set_content(dat.Join())
popup.open(FALSE)
onclose(src, "age_gate")
while(age_gate_result == null)
stoplag(1)
popup.close()
return age_gate_result
/mob/dead/new_player/proc/age_verify()
if(CONFIG_GET(flag/age_verification) && !check_rights_for(client, R_ADMIN) && !(client.ckey in GLOB.bunker_passthrough)) //make sure they are verified
if(!client.set_db_player_flags())
message_admins("Blocked [src] from new player panel because age gate could not access player database flags.")
return FALSE
else
var/dbflags = client.prefs.db_flags
if(dbflags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE) //they have not completed age gate
var/age_verification = age_gate()
if(age_verification != 1)
client.add_system_note("Automated-Age-Gate", "Failed automatic age gate process")
//ban them and kick them
AddBan(client.ckey, client.computer_id, "SYSTEM BAN - Inputted date during join verification was under 18 years of age. Contact administration on discord for verification.", "SYSTEM", FALSE, null, client.address)
qdel(client)
return FALSE
else
//they claim to be of age, so allow them to continue and update their flags
client.update_flag_db(DB_FLAG_AGE_CONFIRMATION_COMPLETE, TRUE)
client.update_flag_db(DB_FLAG_AGE_CONFIRMATION_INCOMPLETE, FALSE)
//log this
message_admins("[ckey] has joined through the automated age gate process.")
return TRUE
return TRUE
/mob/dead/new_player/Topic(href, href_list[])
if(src != usr)
return 0
@@ -85,6 +149,48 @@
if(!client)
return 0
//don't let people get to this unless they are specifically not verified
if(href_list["Month"] && (CONFIG_GET(flag/age_verification) && !check_rights_for(client, R_ADMIN) && !(client.ckey in GLOB.bunker_passthrough)))
var/player_month = text2num(href_list["Month"])
var/player_year = text2num(href_list["Year"])
var/current_time = world.realtime
var/current_month = text2num(time2text(current_time, "MM"))
var/current_year = text2num(time2text(current_time, "YYYY"))
var/player_total_months = (player_year * 12) + player_month
var/current_total_months = (current_year * 12) + current_month
var/months_in_eighteen_years = 18 * 12
var/month_difference = current_total_months - player_total_months
if(month_difference > months_in_eighteen_years)
age_gate_result = TRUE // they're fine
else
if(month_difference < months_in_eighteen_years)
age_gate_result = FALSE
else
//they could be 17 or 18 depending on the /day/ they were born in
var/current_day = text2num(time2text(current_time, "DD"))
var/days_in_months = list(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
if((player_year % 4) == 0) // leap year so february actually has 29 days
days_in_months[2] = 29
var/total_days_in_player_month = days_in_months[player_month]
var/list/days = list()
for(var/number in 1 to total_days_in_player_month)
days += number
var/player_day = input(src, "What day of the month were you born in.") as anything in days
if(player_day <= current_day)
//their birthday has passed
age_gate_result = TRUE
else
//it has NOT been their 18th birthday yet
age_gate_result = FALSE
if(!age_verify())
return
//Determines Relevent Population Cap
var/relevant_cap
var/hpc = CONFIG_GET(number/hard_popcap)
@@ -269,7 +375,9 @@
ready = PLAYER_NOT_READY
return FALSE
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
var/mintime = max(CONFIG_GET(number/respawn_delay), (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time, 0)
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to respawn for [round(mintime / 600, 0.1)] minutes!!","Player Setup","Yes","No")
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
@@ -291,6 +399,7 @@
stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised")
transfer_ckey(observer, FALSE)
observer.client = client
observer.client.prefs?.respawn_time_of_death = world.time
observer.set_ghost_appearance()
if(observer.client && observer.client.prefs)
observer.real_name = observer.client.prefs.real_name
@@ -357,6 +466,9 @@
alert(src, "An administrator has disabled late join spawning.")
return FALSE
if(!respawn_latejoin_check(notify = TRUE))
return FALSE
var/arrivals_docked = TRUE
if(SSshuttle.arrivals)
close_spawn_windows() //In case we get held up
@@ -420,6 +532,8 @@
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character
LAZYOR(character.client.prefs.slots_joined_as, character.client.prefs.default_slot)
LAZYOR(character.client.prefs.characters_joined_as, character.real_name)
if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(SSshuttle.emergency)
@@ -20,16 +20,20 @@
ckeys_allowed = list("poojawa")
extra = TRUE
extra_color_src = MUTCOLORS3
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/mam_body_markings/sabresune
name = "Sabresune"
@@ -63,6 +63,7 @@
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
var/matrixed_sections = MATRIX_NONE //if color_src is MATRIXED, how many sections does it have? 1-3
//Special / holdover traits for Citadel specific sprites.
var/extra = FALSE
@@ -84,4 +85,4 @@
var/has_color = FALSE
var/has_digitigrade = FALSE
var/covers_groin = FALSE
var/covers_chest = FALSE
var/covers_chest = FALSE
@@ -65,4 +65,4 @@
/datum/sprite_accessory/arachnid_mandibles/spiky
name = "Spiky"
icon_state = "spiky"
icon_state = "spiky"
@@ -5,6 +5,7 @@
/datum/sprite_accessory/body_markings
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_ADJ_LAYER)
mutant_part_string = "body_markings"
/datum/sprite_accessory/body_markings/none
name = "None"
@@ -21,6 +22,7 @@
icon_state = "guilmon"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/markings_notmammals.dmi'
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/body_markings/ltiger
name = "Light Tiger Body"
@@ -47,6 +49,7 @@
gender_specific = 0
icon = 'modular_citadel/icons/mob/mam_markings.dmi'
recommended_species = list("mammal", "xeno", "slimeperson", "podweak")
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/mam_body_markings/none
name = "None"
@@ -54,6 +57,7 @@
ckeys_allowed = list("yousshouldnteverbeseeingthisyoumeme")
icon = 'modular_citadel/icons/mob/markings_notmammals.dmi'
relevant_layers = null
matrixed_sections = 0
/datum/sprite_accessory/mam_body_markings/redpanda
name = "Redpanda"
@@ -229,6 +233,7 @@
icon = 'icons/mob/wings.dmi'
color_src = 0
relevant_layers = list(BODY_FRONT_LAYER)
mutant_part_string = "insect_fluff"
/datum/sprite_accessory/insect_fluff/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
@@ -26,18 +26,21 @@
icon_state = "bear"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/human/bigwolf
name = "Big Wolf"
icon_state = "bigwolf"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/human/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
extra = TRUE
extra_color_src = NONE
@@ -46,12 +49,14 @@
icon_state = "bigwolfdark"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/human/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
extra = TRUE
extra_color_src = NONE
@@ -59,6 +64,7 @@
name = "Bunny"
icon_state = "bunny"
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/cat
@@ -73,6 +79,7 @@
icon_state = "cow"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/human/curled
name = "Curled Horn"
@@ -84,6 +91,7 @@
name = "Dog, Floppy"
icon_state = "lab"
color_src = MATRIXED
matrixed_sections = MATRIX_RED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/eevee
@@ -91,12 +99,14 @@
icon_state = "eevee"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/human/elephant
name = "Elephant"
icon_state = "elephant"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/human/elf
name = "Elf"
@@ -109,17 +119,20 @@
icon_state = "fennec"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/fish
name = "Fish"
icon_state = "fish"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/fox
name = "Fox"
icon_state = "fox"
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/jellyfish
@@ -132,17 +145,20 @@
icon_state = "murid"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/human/otie
name = "Otusian"
icon_state = "otie"
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/pede
@@ -150,30 +166,35 @@
icon_state = "pede"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/human/sergal
name = "Sergal"
icon_state = "sergal"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/human/skunk
name = "skunk"
icon_state = "skunk"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/squirrel
name = "Squirrel"
icon_state = "squirrel"
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/wolf
name = "Wolf"
icon_state = "wolf"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
matrixed_sections = MATRIX_RED_BLUE
/******************************************
*************** Furry Ears ****************
@@ -182,7 +203,6 @@
/datum/sprite_accessory/ears/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/ears/mam_ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
@@ -197,38 +217,46 @@
/datum/sprite_accessory/ears/mam_ears/axolotl
name = "Axolotl"
icon_state = "axolotl"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/bat
name = "Bat"
icon_state = "bat"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/bear
name = "Bear"
icon_state = "bear"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/bigwolf
name = "Big Wolf"
icon_state = "bigwolf"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/mam_ears/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
extra = TRUE
extra_color_src = NONE
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/bigwolfdark //alphabetical sort ignored here for ease-of-use
name = "Dark Big Wolf"
icon_state = "bigwolfdark"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/mam_ears/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
extra = TRUE
extra_color_src = NONE
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/bunny
name = "Bunny"
icon_state = "bunny"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/cat
name = "Cat"
@@ -241,10 +269,12 @@
/datum/sprite_accessory/ears/mam_ears/catbig
name = "Cat, Big"
icon_state = "catbig"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/curled
name = "Curled Horn"
@@ -259,6 +289,7 @@
/datum/sprite_accessory/ears/mam_ears/eevee
name = "Eevee"
icon_state = "eevee"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/elf
name = "Elf"
@@ -268,22 +299,27 @@
/datum/sprite_accessory/ears/mam_ears/elephant
name = "Elephant"
icon_state = "elephant"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/fennec
name = "Fennec"
icon_state = "fennec"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/mam_ears/fish
name = "Fish"
icon_state = "fish"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/fox
name = "Fox"
icon_state = "fox"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/husky
name = "Husky"
icon_state = "wolf"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/ears/mam_ears/jellyfish
name = "Jellyfish"
@@ -293,39 +329,49 @@
/datum/sprite_accessory/ears/mam_ears/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/lab
name = "Dog, Long"
icon_state = "lab"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/ears/mam_ears/murid
name = "Murid"
icon_state = "murid"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/otie
name = "Otusian"
icon_state = "otie"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/rabbit
name = "Rabbit"
icon_state = "rabbit"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/pede
name = "Scolipede"
icon_state = "pede"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/sergal
name = "Sergal"
icon_state = "sergal"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/skunk
name = "skunk"
icon_state = "skunk"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/squirrel
name = "Squirrel"
icon_state = "squirrel"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/wolf
name = "Wolf"
icon_state = "wolf"
matrixed_sections = MATRIX_RED_BLUE
@@ -1,6 +1,7 @@
/datum/sprite_accessory/frills
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_ADJ_LAYER)
mutant_part_string = "frills"
/datum/sprite_accessory/frills/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
@@ -145,4 +145,4 @@
/datum/sprite_accessory/facial_hair/elvis
name = "Sideburns (Elvis)"
icon_state = "facial_elvis"
icon_state = "facial_elvis"
@@ -132,6 +132,7 @@
color_src = MUTCOLORS2
relevant_layers = list(BODY_ADJ_LAYER)
recommended_species = list("ipc")
mutant_part_string = "ipc_antenna"
/datum/sprite_accessory/antenna/none
name = "None"
@@ -29,6 +29,7 @@
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
mutant_part_string = "taur"
/datum/sprite_accessory/taur/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (!tauric || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)))
@@ -67,6 +68,7 @@
name = "Cow (Spotted)"
icon_state = "cow_spotted"
color_src = MATRIXED
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/taur/deer
name = "Deer"
@@ -88,6 +90,7 @@
icon_state = "drake_old"
color_src = MATRIXED
extra = FALSE
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/taur/drider
name = "Drider"
@@ -114,17 +117,20 @@
icon_state = "horse"
taur_mode = STYLE_HOOF_TAURIC
alt_taur_mode = STYLE_PAW_TAURIC
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/taur/naga
name = "Naga"
icon_state = "naga"
taur_mode = STYLE_SNEK_TAURIC
hide_legs = USE_SNEK_CLIP_MASK
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/taur/otie
name = "Otie"
icon_state = "otie"
taur_mode = STYLE_PAW_TAURIC
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/taur/pede
name = "Scolipede"
@@ -7,11 +7,6 @@
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.is_robotic_limb(FALSE))
/datum/sprite_accessory/snout/guilmon
name = "Guilmon"
icon_state = "guilmon"
color_src = MATRIXED
/datum/sprite_accessory/snouts/round
name = "Round"
icon_state = "round"
@@ -158,7 +153,6 @@
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_snouts.dmi'
recommended_species = list("mammal", "slimeperson", "insect", "podweak", "lizard")
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/snouts/mam_snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
@@ -174,10 +168,12 @@
/datum/sprite_accessory/snouts/mam_snouts/bird
name = "Beak"
icon_state = "bird"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/bigbeak
name = "Big Beak"
icon_state = "bigbeak"
matrixed_sections = MATRIX_BLUE
/datum/sprite_accessory/snouts/mam_snouts/bug
name = "Bug"
@@ -191,52 +187,64 @@
icon_state = "elephant"
extra = TRUE
extra_color_src = MUTCOLORS3
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/husky
name = "Husky"
icon_state = "husky"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/rhino
name = "Horn"
icon_state = "rhino"
extra = TRUE
extra = MUTCOLORS3
extra_color_src = MUTCOLORS3
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/rodent
name = "Rodent"
icon_state = "rodent"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/lcanid
name = "Mammal, Long"
icon_state = "lcanid"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/lcanidalt
name = "Mammal, Long ALT"
icon_state = "lcanidalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/scanid
name = "Mammal, Short"
icon_state = "scanid"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/scanidalt
name = "Mammal, Short ALT"
icon_state = "scanidalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/scanidalt2
name = "Mammal, Short ALT 2"
icon_state = "scanidalt2"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/wolf
name = "Mammal, Thick"
icon_state = "wolf"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/wolfalt
name = "Mammal, Thick ALT"
icon_state = "wolfalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/otie
name = "Otie"
icon_state = "otie"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/round
name = "Round"
@@ -251,18 +259,22 @@
/datum/sprite_accessory/snouts/mam_snouts/pede
name = "Scolipede"
icon_state = "pede"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/sergal
name = "Sergal"
icon_state = "sergal"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/shark
name = "Shark"
icon_state = "shark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/hshark
name = "hShark"
icon_state = "hshark"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/sharp
name = "Sharp"
@@ -279,18 +291,22 @@
icon_state = "skulldog"
extra = TRUE
extra_color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/toucan
name = "Toucan"
icon_state = "toucan"
matrixed_sections = MATRIX_RED_BLUE //one single pixel of red. one.
/datum/sprite_accessory/snouts/mam_snouts/redpanda
name = "WahCoon"
icon_state = "wah"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/redpandaalt
name = "WahCoon ALT"
icon_state = "wahalt"
matrixed_sections = MATRIX_RED_GREEN
/******************************************
**************** Snouts *******************
@@ -299,10 +315,12 @@
/datum/sprite_accessory/snouts/mam_snouts/fbird
name = "Beak (Top)"
icon_state = "fbird"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/fbigbeak
name = "Big Beak (Top)"
icon_state = "fbigbeak"
matrixed_sections = MATRIX_BLUE
/datum/sprite_accessory/snouts/mam_snouts/fbug
name = "Bug (Top)"
@@ -316,52 +334,64 @@
icon_state = "felephant"
extra = TRUE
extra_color_src = MUTCOLORS3
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/frhino
name = "Horn (Top)"
icon_state = "frhino"
extra = TRUE
extra = MUTCOLORS3
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/fhusky
name = "Husky (Top)"
icon_state = "fhusky"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/flcanid
name = "Mammal, Long (Top)"
icon_state = "flcanid"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/flcanidalt
name = "Mammal, Long ALT (Top)"
icon_state = "flcanidalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fscanid
name = "Mammal, Short (Top)"
icon_state = "fscanid"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fscanidalt
name = "Mammal, Short ALT (Top)"
icon_state = "fscanidalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fscanidalt2
name = "Mammal, Short ALT 2 (Top)"
icon_state = "fscanidalt2"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/fwolf
name = "Mammal, Thick (Top)"
icon_state = "fwolf"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fwolfalt
name = "Mammal, Thick ALT (Top)"
icon_state = "fwolfalt"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fotie
name = "Otie (Top)"
icon_state = "fotie"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/frodent
name = "Rodent (Top)"
icon_state = "frodent"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/fround
name = "Round (Top)"
@@ -376,14 +406,17 @@
/datum/sprite_accessory/snouts/mam_snouts/fpede
name = "Scolipede (Top)"
icon_state = "fpede"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fsergal
name = "Sergal (Top)"
icon_state = "fsergal"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/fshark
name = "Shark (Top)"
icon_state = "fshark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/snouts/mam_snouts/fsharp
name = "Sharp (Top)"
@@ -398,7 +431,14 @@
/datum/sprite_accessory/snouts/mam_snouts/ftoucan
name = "Toucan (Top)"
icon_state = "ftoucan"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/snouts/mam_snouts/fredpanda
name = "WahCoon (Top)"
icon_state = "fwah"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/snouts/mam_snouts/fredpanda/alt
name = "WahCoon ALT (Top)"
icon_state = "fwahalt"
matrixed_sections = MATRIX_RED_GREEN
@@ -169,4 +169,4 @@
/datum/sprite_accessory/underwear/socks/uk_thigh
name = "Thigh-high - UK"
icon_state = "uk_thigh"
icon_state = "uk_thigh"
@@ -1,6 +1,7 @@
/datum/sprite_accessory/spines
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER)
mutant_part_string = "spines"
/datum/sprite_accessory/spines/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
return (!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))
@@ -11,35 +11,41 @@
color_src = MATRIXED
name = "Synthetic Lizard - Snout Under"
icon_state = "synthliz_under"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tert
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MATRIXED
name = "Synthetic Lizard - Snout Tertiary"
icon_state = "synthliz_tert"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tertunder
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MATRIXED
name = "Synthetic Lizard - Snout Tertiary Under"
icon_state = "synthliz_tertunder"
matrixed_sections = MATRIX_ALL
//Synth body markings
/datum/sprite_accessory/mam_body_markings/synthliz/synthliz_pecs
icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi'
name = "Synthetic Lizard - Pecs"
icon_state = "synthlizpecs"
matrixed_sections = MATRIX_GREEN
/datum/sprite_accessory/mam_body_markings/synthliz/synthliz_pecslight
icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi'
name = "Synthetic Lizard - Pecs Light"
icon_state = "synthlizpecslight"
matrixed_sections = MATRIX_GREEN_BLUE
/datum/sprite_accessory/mam_body_markings/synthliz
recommended_species = list("synthliz")
icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi'
name = "Synthetic Lizard - Plates"
icon_state = "synthlizscutes"
matrixed_sections = MATRIX_GREEN
//Synth tails
/datum/sprite_accessory/tails/mam_tails/synthliz
@@ -81,6 +87,7 @@
color_src = MATRIXED
name = "Synthetic Lizard - Horns Light"
icon_state = "synth_hornslight"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/antenna/synthliz/synth_short
icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi'
@@ -99,6 +106,7 @@
color_src = MATRIXED
name = "Synthetic Lizard - Sharp Light"
icon_state = "synth_sharplight"
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/antenna/synthliz/synthliz_thick
icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi'
@@ -111,6 +119,7 @@
color_src = MATRIXED
name = "Synthetic Lizard - Thick Light"
icon_state = "synth_thicklight"
matrixed_sections = MATRIX_RED_BLUE
//Synth Taurs (Ported from Virgo)
/datum/sprite_accessory/taur/synthliz
@@ -118,6 +127,7 @@
icon_state = "synthlizard"
taur_mode = STYLE_PAW_TAURIC
recommended_species = list("synthliz")
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/taur/synthliz/inv
name = "Virgo - Synthetic Lizard (Inverted)"
@@ -8,7 +8,7 @@
/datum/sprite_accessory/tails_animated
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "tailwag"
mutant_part_string = "tailwag" //keep this the same, ALWAYS, this is incredibly important for colouring!
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
/******************************************
@@ -34,12 +34,14 @@
icon_state = "axolotl"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/lizard/axolotl
name = "Axolotl"
icon_state = "axolotl"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/lizard/dtiger
name = "Dark Tiger"
@@ -54,12 +56,14 @@
icon_state = "guilmon"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/lizard/guilmon
name = "Guilmon"
icon_state = "guilmon"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/lizard/ltiger
name = "Light Tiger"
@@ -107,44 +111,28 @@
icon_state = "axolotl"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/axolotl
name = "Axolotl"
icon_state = "axolotl"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
/datum/sprite_accessory/tails/mam_tails/batl
name = "Bat (Long)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "batl"
/datum/sprite_accessory/tails_animated/mam_tails_animated/batl
name = "Bat (Long)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "batl"
/datum/sprite_accessory/tails/mam_tails/bats
name = "Bat (Short)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "bats"
/datum/sprite_accessory/tails_animated/mam_tails_animated/bats
name = "Bat (Short)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "bats"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/bee
name = "Bee"
icon_state = "bee"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/bee
name = "Bee"
icon_state = "bee"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/cat
name = "Cat"
@@ -163,24 +151,28 @@
icon_state = "catbig"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/catbig
name = "Cat, Big"
icon_state = "catbig"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/twocat
name = "Cat, Double"
icon_state = "twocat"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/twocat
name = "Cat, Double"
icon_state = "twocat"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/corvid
name = "Corvid"
@@ -195,12 +187,14 @@
icon_state = "cow"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/cow
name = "Cow"
icon_state = "cow"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/dtiger
name = "Dark Tiger"
@@ -215,60 +209,70 @@
icon_state = "datashark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/tails_animated/human/datashark
name = "datashark"
icon_state = "datashark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_BLUE
/datum/sprite_accessory/tails/human/eevee
name = "Eevee"
icon_state = "eevee"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/eevee
name = "Eevee"
icon_state = "eevee"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/fennec
name = "Fennec"
icon_state = "fennec"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/fennec
name = "Fennec"
icon_state = "fennec"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/fish
name = "Fish"
icon_state = "fish"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/fish
name = "Fish"
icon_state = "fish"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/fox
name = "Fox"
icon_state = "fox"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/fox
name = "Fox"
icon_state = "fox"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/horse
name = "Horse"
@@ -287,36 +291,42 @@
icon_state = "husky"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/husky
name = "Husky"
icon_state = "husky"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/insect
name = "Insect"
icon_state = "insect"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/insect
name = "Insect"
icon_state = "insect"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/kitsune
name = "Kitsune"
icon_state = "kitsune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/kitsune
name = "Kitsune"
icon_state = "kitsune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/ltiger
name = "Light Tiger"
@@ -331,108 +341,126 @@
icon_state = "murid"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_GREEN
/datum/sprite_accessory/tails_animated/human/murid
name = "Murid"
icon_state = "murid"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_GREEN
/datum/sprite_accessory/tails/orca
name = "Orca"
icon_state = "orca"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/orca
name = "Orca"
icon_state = "orca"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/otie
name = "Otusian"
icon_state = "otie"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/otie
name = "Otusian"
icon_state = "otie"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/ailurus
name = "Red Panda"
icon_state = "wah"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/ailurus
name = "Red Panda"
icon_state = "wah"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/pede
name = "Scolipede"
icon_state = "pede"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/pede
name = "Scolipede"
icon_state = "pede"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/sergal
name = "Sergal"
icon_state = "sergal"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/sergal
name = "Sergal"
icon_state = "sergal"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/shark
name = "Shark"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/shark
name = "Shark"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/skunk
name = "skunk"
icon_state = "skunk"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails_animated/human/skunk
name = "skunk"
icon_state = "skunk"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails/human/smooth
name = "Smooth"
@@ -463,60 +491,70 @@
icon_state = "squirrel"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/squirrel
name = "Squirrel"
icon_state = "squirrel"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/tamamo_kitsune
name = "Tamamo Kitsune Tails" //Tamamo-no-Tiro, let it be known!
icon_state = "9sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/tamamo_kitsune
name = "Tamamo Kitsune Tails"
icon_state = "9sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/tentacle
name = "Tentacle"
icon_state = "tentacle"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/tentacle
name = "Tentacle"
icon_state = "tentacle"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/tiger
name = "Tiger"
icon_state = "tiger"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails_animated/human/tiger
name = "Tiger"
icon_state = "tiger"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails/human/wolf
name = "Wolf"
icon_state = "wolf"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/wolf
name = "Wolf"
icon_state = "wolf"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/******************************************
************** Furry Tails ****************
@@ -526,7 +564,6 @@
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/tails/mam_tails/none
@@ -538,7 +575,6 @@
/datum/sprite_accessory/tails_animated/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/tails_animated/mam_tails_animated/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
@@ -552,34 +588,42 @@
/datum/sprite_accessory/tails/mam_tails/axolotl
name = "Axolotl"
icon_state = "axolotl"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/axolotl
name = "Axolotl"
icon_state = "axolotl"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/batl
name = "Bat (Long)"
icon_state = "batl"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/batl
name = "Bat (Long)"
icon_state = "batl"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/bats
name = "Bat (Short)"
icon_state = "bats"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/bats
name = "Bat (Short)"
icon_state = "bats"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/bee
name = "Bee"
icon_state = "bee"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/bee
name = "Bee"
icon_state = "bee"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/cat
name = "Cat"
@@ -594,34 +638,42 @@
/datum/sprite_accessory/tails/mam_tails/catbig
name = "Cat, Big"
icon_state = "catbig"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/catbig
name = "Cat, Big"
icon_state = "catbig"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/twocat
name = "Cat, Double"
icon_state = "twocat"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/twocat
name = "Cat, Double"
icon_state = "twocat"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/corvid
name = "Corvid"
icon_state = "crow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/corvid
name = "Corvid"
icon_state = "crow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tail/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/dtiger
name = "Dark Tiger"
@@ -638,42 +690,52 @@
/datum/sprite_accessory/tails/mam_tails/eevee
name = "Eevee"
icon_state = "eevee"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/eevee
name = "Eevee"
icon_state = "eevee"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/fennec
name = "Fennec"
icon_state = "fennec"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/fennec
name = "Fennec"
icon_state = "fennec"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/human/fish
/datum/sprite_accessory/tails/mam_tails/fish
name = "Fish"
icon_state = "fish"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/human/fish
/datum/sprite_accessory/tails_animated/mam_tails_animated/fish
name = "Fish"
icon_state = "fish"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/fox
name = "Fox"
icon_state = "fox"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/fox
name = "Fox"
icon_state = "fox"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/hawk
name = "Hawk"
icon_state = "hawk"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/hawk
name = "Hawk"
icon_state = "hawk"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/horse
name = "Horse"
@@ -688,42 +750,52 @@
/datum/sprite_accessory/tails/mam_tails/husky
name = "Husky"
icon_state = "husky"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/husky
name = "Husky"
icon_state = "husky"
matrixed_sections = MATRIX_RED_GREEN
datum/sprite_accessory/tails/mam_tails/insect
name = "Insect"
icon_state = "insect"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/insect
name = "Insect"
icon_state = "insect"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/kitsune
name = "Kitsune"
icon_state = "kitsune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/kitsune
name = "Kitsune"
icon_state = "kitsune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/lab
name = "Lab"
icon_state = "lab"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/lab
name = "Lab"
icon_state = "lab"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/ltiger
name = "Light Tiger"
@@ -740,84 +812,104 @@ datum/sprite_accessory/tails/mam_tails/insect
/datum/sprite_accessory/tails/mam_tails/murid
name = "Murid"
icon_state = "murid"
matrixed_sections = MATRIX_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/murid
name = "Murid"
icon_state = "murid"
matrixed_sections = MATRIX_GREEN
/datum/sprite_accessory/tails/mam_tails/orca
name = "Orca"
icon_state = "orca"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/orca
name = "Orca"
icon_state = "orca"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/otie
name = "Otusian"
icon_state = "otie"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/otie
name = "Otusian"
icon_state = "otie"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/rabbit
name = "Rabbit"
icon_state = "rabbit"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/rabbit
name = "Rabbit"
icon_state = "rabbit"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/ailurus
name = "Red Panda"
icon_state = "wah"
extra = TRUE
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/ailurus
name = "Red Panda"
icon_state = "wah"
extra = TRUE
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/pede
name = "Scolipede"
icon_state = "pede"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/pede
name = "Scolipede"
icon_state = "pede"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/sergal
name = "Sergal"
icon_state = "sergal"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/sergal
name = "Sergal"
icon_state = "sergal"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/shark
name = "Shark"
icon_state = "shark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/shark
name = "Shark"
icon_state = "shark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/shepherd
name = "Shepherd"
icon_state = "shepherd"
matrixed_sections = MATRIX_GREEN_BLUE
/datum/sprite_accessory/tails_animated/mam_tails_animated/shepherd
name = "Shepherd"
icon_state = "shepherd"
matrixed_sections = MATRIX_GREEN_BLUE
/datum/sprite_accessory/tails/mam_tails/skunk
name = "Skunk"
icon_state = "skunk"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails_animated/mam_tails_animated/skunk
name = "Skunk"
icon_state = "skunk"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails/mam_tails/smooth
name = "Smooth"
@@ -846,47 +938,59 @@ datum/sprite_accessory/tails/mam_tails/insect
/datum/sprite_accessory/tails/mam_tails/straighttail
name = "Straight Tail"
icon_state = "straighttail"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/straighttail
name = "Straight Tail"
icon_state = "straighttail"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/squirrel
name = "Squirrel"
icon_state = "squirrel"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/squirrel
name = "Squirrel"
icon_state = "squirrel"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/tamamo_kitsune
name = "Tamamo Kitsune Tails"
icon_state = "9sune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/tamamo_kitsune
name = "Tamamo Kitsune Tails"
icon_state = "9sune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/tentacle
name = "Tentacle"
icon_state = "tentacle"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/tentacle
name = "Tentacle"
icon_state = "tentacle"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/tiger
name = "Tiger"
icon_state = "tiger"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails_animated/mam_tails_animated/tiger
name = "Tiger"
icon_state = "tiger"
matrixed_sections = MATRIX_ALL
/datum/sprite_accessory/tails/mam_tails/wolf
name = "Wolf"
icon_state = "wolf"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/wolf
name = "Wolf"
icon_state = "wolf"
matrixed_sections = MATRIX_RED
+11 -3
View File
@@ -264,7 +264,7 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body
Works together with spawning an observer, noted above.
*/
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE, cryo = FALSE)
var/sig_flags = SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize)
penalize = !(sig_flags & COMPONENT_DO_NOT_PENALIZE_GHOSTING) && (suiciding || penalize) // suicide squad.
voluntary_ghosted = voluntary
@@ -277,6 +277,12 @@ Works together with spawning an observer, noted above.
if (client && client.prefs && client.prefs.auto_ooc)
if (!(client.prefs.chat_toggles & CHAT_OOC))
client.prefs.chat_toggles ^= CHAT_OOC
if(ckey && penalize)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_restrictions_active = TRUE
P.respawn_time_of_death = world.time
P.respawn_did_cryo = cryo
transfer_ckey(ghost, FALSE)
ghost.client.init_verbs()
if(penalize)
@@ -423,12 +429,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "<span class='warning'>You're already stuck out of your body!</span>")
return FALSE
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. ","Are you sure you want to stay dead?","Yes","No")
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. THIS WILL ALSO STOP YOU FROM RESPAWNING!!!","Are you sure you want to stay dead and never respawn?","Yes","No")
if(response != "Yes")
return
can_reenter_corpse = FALSE
to_chat(src, "You can no longer be brought back into your body.")
client.prefs?.dnr_triggered = TRUE
to_chat(src, "You can no longer be brought back into your body or respawn.")
return TRUE
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE)
@@ -1,2 +1,2 @@
/mob/dead/observer/canZMove(direction, turf/target)
return TRUE
return TRUE
+181
View File
@@ -0,0 +1,181 @@
// ADMIN VERBS BEGIN
/**
* Fully returns a player to lobby, allowing them to bypass all respawn restrictions
* Works on ghosts or new players (lobby players)
* If a lobby player is selected, their restrictions are removed.
*/
/client/proc/admin_cmd_respawn_return_to_lobby()
set name = "Respawn Player (Unrestricted)"
set desc = "Gives a player an unrestricted respawn, resetting all respawn restrictions for them."
set category = "Admin"
var/list/mob/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - Observing: [I]"] = I.ckey
for(var/mob/dead/new_player/I in GLOB.dead_mob_list)
if(!I.client || !I.client.prefs.respawn_restrictions_active)
continue
valid["[I.ckey] - IN LOBBY"] = I.ckey
if(!valid.len)
to_chat(src, "<span class='warning'>No player found that is either a ghost or is in lobby with restrictions active.</span>")
return
var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid]
var/client/player = GLOB.directory[ckey]
if(!player)
to_chat(src, "<span class='warning'>Client not found.</span>")
return
var/mob/M = player.mob
if(istype(M, /mob/dead/observer))
var/mob/dead/observer/O = M
var/confirm = alert(src, "Send [O]([ckey]) back to the lobby without respawn restrictions?", "Send to Lobby", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] gave [key_name_admin(O)] a full respawn and sent them back to the lobby.")
log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.")
to_chat(O, "<span class='userdanger'>You have been given a full respawn.</span>")
O.do_respawn(FALSE)
O.client.prefs.dnr_triggered = FALSE
else if(istype(M, /mob/dead/new_player))
var/mob/dead/new_player/NP = M
var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.")
log_admin("[key_name(src)] removed [ckey]'s respawn restrictions")
NP.client.prefs.respawn_restrictions_active = FALSE
NP.client.prefs.dnr_triggered = FALSE
to_chat(NP, "<span class='boldnotie'>Your respawn restrictions have been removed.")
else
CRASH("Invalid mobtype")
/**
* Allows a ghost to bypass respawn delay without lifting respawn restrictions
*/
/client/proc/admin_cmd_remove_ghost_respawn_timer()
set name = "Remove Respawn Timer for Player"
set desc = "Removes a player's respawn timer without removing their respawning restrictions."
set category = "Admin"
var/list/mob/dead/observer/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - [I.name]"] = I
if(!valid.len)
to_chat(src, "<span class='warning'>No logged in ghosts found.</span>")
return
var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid]
if(!O.client)
to_chat(src, "<span class='warning'>[O] has no client.</span>")
return
var/timeleft = O.time_left_to_respawn()
if(!timeleft)
to_chat(src, "<span class='warning'>[O] can already respawn.")
return
message_admins("[key_name_admin(src)] removed [key_name_admin(O)]'s respawn timer.")
log_admin("[key_name(src)] removed [key_name(O)]'s respawn timer.")
O.client.prefs.respawn_time_of_death = -INFINITY
to_chat(O, "<span class='boldnotice'>Your respawn timer has been removed.")
// ADMIN VERBS END
/**
* Checks if we can latejoin on the currently selected slot, taking into account respawn status.
*/
/mob/dead/new_player/proc/respawn_latejoin_check(notify = FALSE)
if(!client.prefs.respawn_restrictions_active)
return TRUE
var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn)
if(can_same_person)
return TRUE
var/nameless = client.prefs.nameless
var/randomname = client.prefs.be_random_name
var/randombody = client.prefs.be_random_body
if(randombody && (nameless || randomname))
return TRUE // somewhat unrecognizable
if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same slot. Joined slots: [english_list(client.prefs.slots_joined_as)].")
return FALSE
if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as)))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same character. Joined slots: [english_list(client.prefs.characters_joined_as)].")
return FALSE
return TRUE
/**
* Attempts to respawn.
*/
/mob/dead/observer/verb/respawn()
set name = "Respawn"
set category = "OOC"
if(!CONFIG_GET(flag/respawns_enabled))
to_chat(src, "<span class='warning'>Respawns are disabled in configuration.</span>")
return
if(client.prefs.dnr_triggered)
to_chat(src, "<span class='danger'>You cannot respawn as you have enabled DNR.</span>")
return
var/roundstart_timeleft = (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time
if(roundstart_timeleft > 0)
to_chat(src, "<span class='warning'>It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.</span>")
return
var/list/banned_modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes)
if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])
to_chat(src, "<span class='warning'>The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.</span>")
return
var/timeleft = time_left_to_respawn()
if(timeleft)
to_chat(src, "<span class='warning'>It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.</span>")
return
do_respawn(TRUE)
/**
* Gets time left until we can respawn. Returns 0 if we can respawn now.
*/
/mob/dead/observer/verb/time_left_to_respawn()
ASSERT(client)
return max(0, ((client.prefs.respawn_did_cryo? CONFIG_GET(number/respawn_delay_cryo) : CONFIG_GET(number/respawn_delay)) MINUTES + client.prefs.respawn_time_of_death) - world.time)
/**
* Handles respawning
*/
/mob/dead/observer/proc/do_respawn(penalize)
if(!client)
return
if(isnull(penalize))
penalize = client.prefs.respawn_restrictions_active
client.prefs.respawn_restrictions_active = penalize
to_chat(src, "<span class='userdanger'>You have been respawned to the lobby. \
Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \
Any character you join as has NO knowledge of round events unless specified otherwise by an admin.</span>")
message_admins("[key_name_admin(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
transfer_to_lobby()
/**
* Actual proc that removes us and puts us back on lobby
*/
/mob/dead/observer/proc/transfer_to_lobby()
if(!client) // if no one's in us we can just be deleted
qdel(src)
return
client.screen.Cut()
client.view_size.resetToDefault()
client.generate_clickcatcher()
client.apply_clickcatcher()
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))
client.view_size.resetToDefault()
var/mob/dead/new_player/M = new /mob/dead/new_player
M.ckey = ckey
+1 -1
View File
@@ -11,4 +11,4 @@
/mob/proc/death(gibbed)
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
return
return
+57
View File
@@ -0,0 +1,57 @@
/**
* Sets an ability property
*/
/mob/proc/set_ability_property(ability, property, value)
LAZYINITLIST(ability_properties)
LAZYINITLIST(ability_properties[ability])
ability_properties[ability][property] = value
/**
* Gets an ability property
*/
/mob/proc/get_ability_property(ability, property)
return ability_properties && ability_properties[ability] && ability_properties[ability][property]
GLOBAL_LIST_INIT(innate_ability_typepaths, all_innate_ability_typepaths())
/proc/all_innate_ability_typepaths()
return list(
INNATE_ABILITY_HUMANOID_CUSTOMIZATION = /datum/action/innate/ability/humanoid_customization,
INNATE_ABILITY_SLIME_BLOBFORM = /datum/action/innate/ability/slime_blobform,
INNATE_ABILITY_LIMB_REGROWTH = /datum/action/innate/ability/limb_regrowth
)
/**
* Grants an ability from a source
*/
/mob/proc/grant_ability_from_source(list/abilities, source)
if(!islist(abilities))
abilities = list(abilities)
LAZYINITLIST(ability_actions)
LAZYINITLIST(innate_abilities)
for(var/ability in abilities)
LAZYINITLIST(innate_abilities[ability])
innate_abilities[ability] |= source
if(ability_actions[ability])
continue
var/path = GLOB.innate_ability_typepaths[ability]
var/datum/action/innate/ability/A = new path
ability_actions[ability] = A
A.Grant(src)
/**
* Removes an ability from a source
*/
/mob/proc/remove_ability_from_source(list/abilities, source)
if(!islist(abilities))
abilities = list(abilities)
if(!length(innate_abilities))
return
for(var/ability in abilities)
if(!length(innate_abilities[ability]))
continue
innate_abilities[ability] -= source
if(!length(innate_abilities[ability]))
innate_abilities -= ability
qdel(ability_actions[ability])
ability_actions -= ability
+8
View File
@@ -100,6 +100,14 @@
return held_items.Find(I)
///Find number of held items, multihand compatible
/mob/proc/get_num_held_items()
. = 0
for(var/i in 1 to held_items.len)
if(held_items[i])
.++
//Sad that this will cause some overhead, but the alias seems necessary
//*I* may be happy with a million and one references to "indexes" but others won't be
/mob/proc/is_holding(obj/item/I)
+1 -1
View File
@@ -17,4 +17,4 @@
if(loc)
if(istype(loc, /obj/item/organ/brain))
qdel(loc)//Gets rid of the brain item
..()
..()
+1 -1
View File
@@ -21,4 +21,4 @@
key = "whistle"
key_third_person = "whistles"
message = "whistles."
emote_type = EMOTE_AUDIBLE
emote_type = EMOTE_AUDIBLE
@@ -22,4 +22,4 @@
return
/mob/living/brain/set_blurriness()
return
return
@@ -1,8 +1,8 @@
/mob/living/carbon/alien/getToxLoss()
/mob/living/carbon/alien/getToxLoss(toxins_type = TOX_OMNI)
return 0
/mob/living/carbon/alien/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE) //alien immune to tox damage
/mob/living/carbon/alien/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT) //alien immune to tox damage
return FALSE
//aliens are immune to stamina damage.
@@ -41,4 +41,4 @@
return 1
else
to_chat(user, "<span class='notice'>We already have a living royal!</span>")
return 0
return 0
@@ -20,4 +20,4 @@
if(istype(node)) // just in case someone would ever add a diffirent node to hivenode slot
node.queen_death()
return ..()
return ..()
@@ -1,3 +1,3 @@
//can't unequip since it can't equip anything
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W)
return
return
@@ -30,4 +30,4 @@
hud_used.alien_queen_finder.add_overlay(finder_eye)
/mob/living/carbon/alien/humanoid/royal/queen/findQueen()
return //Queen already knows where she is. Hopefully.
return //Queen already knows where she is. Hopefully.
@@ -8,4 +8,4 @@
return
/mob/living/carbon/alien/update_body_parts()//we don't use the bodyparts layer for aliens.
return
return
+4 -2
View File
@@ -604,14 +604,14 @@
ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_HARD_STAMCRIT)
filters += CIT_FILTER_STAMINACRIT
update_mobility()
if((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && total_health <= STAMINA_CRIT)
if((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && total_health <= STAMINA_CRIT_REMOVAL_THRESHOLD)
to_chat(src, "<span class='notice'>You don't feel nearly as exhausted anymore.</span>")
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_HARD_STAMCRIT)
filters -= CIT_FILTER_STAMINACRIT
update_mobility()
UpdateStaminaBuffer()
update_health_hud()
/mob/living/carbon/update_sight()
if(!client)
return
@@ -839,6 +839,8 @@
/mob/living/carbon/update_stat()
if(status_flags & GODMODE)
return
if(stat != CONSCIOUS)
clear_typing_indicator()
if(stat != DEAD)
if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH))
death()
@@ -212,6 +212,11 @@
. = ..()
if(. & EMP_PROTECT_CONTENTS)
return
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
//EMPs fuck robots over. Up to ~11.5 corruption per EMP if hit by the full power. They also get up to 15 burn damage per EMP (up to 2.5 per limb), plus short hardstun
//Though, note that the burn damage is linear, while corruption is logarythmical, which means at lower severities you still get corruption, but far less burn / stun
//Note than as compensation, they only take half the limb burn damage someone fully augmented would take, which would be up to 30 burn.
adjustToxLoss(round(log(severity)*2.5, 0.1), toxins_type = TOX_SYSCORRUPT)
for(var/X in internal_organs)
var/obj/item/organ/O = X
O.emp_act(severity)
@@ -350,10 +355,10 @@
return embeds
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash, override_protection = 0)
. = ..()
var/damage = intensity - get_eye_protection()
var/damage = override_protection ? intensity : intensity - get_eye_protection()
if(.) // we've been flashed
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
if (!eyes)
@@ -453,14 +458,14 @@
/mob/living/carbon/getBruteLoss_nonProsthetic()
var/amount = 0
for(var/obj/item/bodypart/BP in bodyparts)
if (BP.status < 2)
if (BP.is_organic_limb())
amount += BP.brute_dam
return amount
/mob/living/carbon/getFireLoss_nonProsthetic()
var/amount = 0
for(var/obj/item/bodypart/BP in bodyparts)
if (BP.status < 2)
if (BP.is_organic_limb())
amount += BP.burn_dam
return amount
@@ -65,6 +65,8 @@
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
var/corruption_timer = 0 //Only relevant for robotpeople. A timer that ticks in handle_corruption() so stuff doesn't happen every tick.
/// All of the wounds a carbon has afflicted throughout their limbs
var/list/all_wounds
/// All of the scars a carbon has afflicted throughout their limbs
@@ -85,8 +85,10 @@
heal_overall_damage(0, abs(amount), 0, FALSE, TRUE, updating_health)
return amount
/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage
//God save me from spaghettifying this - Syscorrupt damage is not affected by toxlovers.
/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER) && toxins_type != TOX_SYSCORRUPT) //damage becomes healing and healing becomes damage
amount = -amount
if(amount > 0)
blood_volume -= 3 * amount //5x was too much, this is punishing enough.
@@ -173,7 +175,7 @@
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(status && !status[BP.status])
if(status && !status.Find(BP.status))
continue
if((brute && BP.brute_dam) || (burn && BP.burn_dam) || (stamina && BP.stamina_dam))
parts += BP
+1 -1
View File
@@ -5,7 +5,7 @@
silent = FALSE
losebreath = 0
if(!gibbed)
if(!gibbed && !HAS_TRAIT(src, TRAIT_DEATHCOMA))
emote("deathgasp")
. = ..()
@@ -0,0 +1,165 @@
//////////////////////////////////////
//SYSTEM CORRUPTION FOR ROBOT-PEOPLE//
//////////////////////////////////////
//Moved into its own file for easier accessability & less cluttering of carbon/life.dm. Used in BiologicalLife()
#define CORRUPTION_CHECK_INTERVAL 10 //Life() is called once every second, so ten seconds interval.
#define CORRUPTION_THRESHHOLD_MINOR 10 //Above: Annoyances, to remind you you should get your corruption fixed.
#define CORRUPTION_THRESHHOLD_MAJOR 35 //Above: Very annoying stuff, go get fixed.
#define CORRUPTION_THRESHHOLD_CRITICAL 65 //Above: Extremely annoying stuff, possibly life-threatening
/mob/living/carbon/proc/handle_corruption()
if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM)) //Only robot-people need to care about this
return
corruption_timer++
var/corruption = getToxLoss(toxins_type = TOX_SYSCORRUPT)
var/corruption_state
var/timer_req = CORRUPTION_CHECK_INTERVAL
switch(corruption)
if(0 to CORRUPTION_THRESHHOLD_MINOR)
timer_req = INFINITY //Below minor corruption you are fiiine
corruption_state = "<font color='green'>None</font>" //This should never happen, but have it anyways.
if(CORRUPTION_THRESHHOLD_MINOR to CORRUPTION_THRESHHOLD_MAJOR)
corruption_state = "<font color='blue'>Minor</font>"
if(CORRUPTION_THRESHHOLD_MAJOR to CORRUPTION_THRESHHOLD_CRITICAL)
timer_req -= 1
corruption_state = "<font color='orange'>Major</font>"
if(CORRUPTION_THRESHHOLD_CRITICAL to INFINITY)
timer_req -= 2
corruption_state = "<font color='red'>Critical</font>"
if(corruption_timer < timer_req)
return
corruption_timer = 0
if(!prob(corruption)) //Lucky you beat the rng roll!
return
var/list/whatmighthappen = list()
whatmighthappen += list("avoided" = 3, "dropthing" = 1, "movetile" = 1, "shortdeaf" = 1, "flopover" = 1, "nutriloss" = 1, "selfflash" = 1, "harmies" = 1)
if(corruption >= CORRUPTION_THRESHHOLD_MAJOR)
whatmighthappen += list("longdeaf" = 1, "longknockdown" = 1, "shortlimbdisable" = 1, "shortblind" = 1, "shortstun" = 1, "shortmute" = 1, "vomit" = 1, "halluscinate" = 1)
if(corruption >= CORRUPTION_THRESHHOLD_CRITICAL)
whatmighthappen += list("receporgandamage" = 1, "longlimbdisable" = 1, "blindmutedeaf" = 1, "longstun" = 1, "sleep" = 1, "inducetrauma" = 1, "amplifycorrupt" = 1, "changetemp" = 1)
var/event = pickweight(whatmighthappen)
log_message("has been affected by [event] due to system corruption of [corruption], with a corruption state of [corruption_state]", LOG_ATTACK)
switch(event)
if("avoided")
to_chat(src, "<span class='notice'>System malfunction avoided by hardware safeguards - intervention recommended.</span>")
adjustToxLoss(-0.2, toxins_type = TOX_SYSCORRUPT) //If you roll this, your system safeguards caught onto the system corruption and neutralised a bit of it.
if("dropthing")
drop_all_held_items()
to_chat(src, "<span class='warning'>Error - Malfunction in arm circuitry.</span>")
if("movetile")
if(CHECK_MOBILITY(src, MOBILITY_MOVE) && !ismovable(loc))
step(src, pick(GLOB.cardinals))
to_chat(src, "<span class='warning'>Error - Malfunction in movement control subsystem.</span>")
if("shortdeaf")
ADD_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_hearing), 5 SECONDS)
to_chat(src, "<span class='hear'><b>ZZZZT</b></span>")
if("flopover")
DefaultCombatKnockdown(1)
to_chat(src, "<span class='warning'>Error - Malfunction in actuator circuitry.</span>")
if("nutriloss")
nutrition = max(0, nutrition - 50)
to_chat(src, "<span class='warning'>Power surge detected in internal battery cell.</span>")
if("selfflash")
if(flash_act(override_protection = 1))
confused += 4
to_chat(src, "<span class='warning'>Error - Sensory system overload detected!</span>")
if("harmies")
a_intent_change(INTENT_HARM)
to_chat(src, "<span class='notice'>Intent subsystem successfully recalibrated.</span>")
if("longdeaf")
ADD_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_hearing), 20 SECONDS)
to_chat(src, "<span class='notice'>Hearing subsystem successfully shutdown.</span>")
if("longknockdown")
DefaultCombatKnockdown(50)
to_chat(src, "<span class='warning'>Significant error in actuator subsystem - Rebooting.</span>")
if("shortlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 5 SECONDS)
to_chat(src, "<span class='warning'>Error - Limb control subsystem partially shutdown, rebooting.</span>")
if("shortblind")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), 5 SECONDS)
to_chat(src, "<span class='warning'>Visual receptor shutdown detected - Initiating reboot.</span>")
if("shortstun")
Stun(30)
to_chat(src, "<span class='warning'>Deadlock detected in primary systems, error code [rand(101, 999)].</span>")
if("shortmute")
ADD_TRAIT(src, TRAIT_MUTE, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_speech), 5 SECONDS)
to_chat(src, "<span class='notice'>Communications matrix successfully shutdown for maintenance.</span>")
if("vomit")
to_chat(src, "<span class='notice'>Ejecting contaminant.</span>")
vomit()
if("halluscinate")
hallucination += 20 //Doesn't give a cue
if("receporgandamage")
adjustOrganLoss(ORGAN_SLOT_EARS, rand(10, 20))
adjustOrganLoss(ORGAN_SLOT_EYES, rand(10, 20))
to_chat(src, "<span class='warning'>Power spike detected in auditory and visual systems!</span>")
if("longlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 25 SECONDS)
to_chat(src, "<span class='warning'>Fatal error in limb control subsystem - rebooting.</span>")
if("blindmutedeaf")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), (rand(10, 25)) SECONDS)
ADD_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_hearing), (rand(15, 35)) SECONDS)
ADD_TRAIT(src, TRAIT_MUTE, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_speech), (rand(20, 45)) SECONDS)
to_chat(src, "<span class='warning'>Fatal error in multiple systems - Performing recovery.</span>")
if("longstun")
Stun(80)
to_chat(src, "<span class='warning'Critical divide-by-zero error detected - Failsafe initiated.</span>")
if("sleep")
addtimer(CALLBACK(src, .proc/forcesleep), (rand(6, 10)) SECONDS)
to_chat(src, "<span class='warning'>Priority 1 shutdown order received in operating system - Preparing powerdown.</span>")
if("inducetrauma")
to_chat(src, "<span class='warning'>Major interference detected in main operating matrix - Complications possible.</span>")
var/resistance = pick(
65;TRAUMA_RESILIENCE_BASIC,
35;TRAUMA_RESILIENCE_SURGERY)
var/trauma_type = pickweight(list(
BRAIN_TRAUMA_MILD = 80,
BRAIN_TRAUMA_SEVERE = 10))
gain_trauma_type(trauma_type, resistance) //Gaining the trauma will inform them, but we'll tell them too so they know what the reason was.
if("amplifycorrupt")
adjustToxLoss(5, toxins_type = TOX_SYSCORRUPT)
to_chat(src, "<span class='warning'>System safeguards failing - Action urgently required.</span>")
if("changetemp")
adjust_bodytemperature(rand(150, 250))
to_chat(src, "<span class='warning'>Warning - Fatal coolant flow error at node [rand(6, 99)]!</span>") //This is totally not a reference to anything.
/mob/living/carbon/proc/reenable_limb(disabled_limb)
REMOVE_TRAIT(src, disabled_limb, CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Limb control subsystem successfully rebooted.</span>")
/mob/living/carbon/proc/reenable_hearing()
REMOVE_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Hearing restored.</span>")
/mob/living/carbon/proc/reenable_vision()
REMOVE_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Visual receptors back online.</span>")
/mob/living/carbon/proc/reenable_speech()
REMOVE_TRAIT(src, TRAIT_MUTE, CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Communications subsystem operational.</span>")
/mob/living/carbon/proc/forcesleep(time = 100)
to_chat(src, "<span class='notice'>Preparations complete, powering down.</span>")
Sleeping(time, 0)
#undef CORRUPTION_CHECK_INTERVAL
#undef CORRUPTION_THRESHHOLD_MINOR
#undef CORRUPTION_THRESHHOLD_MAJOR
#undef CORRUPTION_THRESHHOLD_CRITICAL
@@ -212,6 +212,7 @@
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
/mob/living/carbon/human/Crossed(atom/movable/AM)
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
var/mob/living/simple_animal/bot/mulebot/MB = AM
if(istype(MB))
MB.RunOver(src)
@@ -1,4 +1,6 @@
/mob/living/carbon/human/getarmor(def_zone, type)
if(HAS_TRAIT(src, TRAIT_ARMOR_BROKEN)) //trait that makes it act as if you have no armor at all, you take natural damage from all sources
return 0
var/armorval = 0
var/organnum = 0
@@ -18,7 +20,6 @@
organnum++
return (armorval/max(organnum, 1))
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, d_type)
if(!d_type || !def_zone)
return 0
@@ -410,6 +411,8 @@
if(isrobotic(src))
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
severity *= 0.5
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
severity *= 0.5 //Robotpeople take less limb damage, but instead suffer system corruption (see carbon emp_act)
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.is_robotic_limb())
if(!informed)
@@ -14,6 +14,7 @@
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
//Hair colour and style
var/hair_color = "000"
@@ -98,20 +99,54 @@
parry_failed_clickcd_duration = 0.4
parry_data = list( // yeah it's snowflake
"HUMAN_PARRY_STAGGER" = 3 SECONDS,
"HUMAN_PARRY_PUNCH" = TRUE,
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/mob/living/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
. = ..()
if(!owner.Adjacent(attacker))
return ..()
if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"])
return ..()
return
if(parry_efficiency < D.parry_data["UNARMED_PARRY_MINIMUM_EFFICIENCY"])
return
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
if(D.parry_data["HUMAN_PARRY_PUNCH"])
if(D.parry_data["UNARMED_PARRY_PUNCH"])
UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
var/mob/living/L = attacker
if(istype(L))
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
L.Stagger(D.parry_data["UNARMED_PARRY_STAGGER"])
/// Unarmed parry data for pugilists
/datum/block_parry_data/unarmed/pugilist
parry_respect_clickdelay = FALSE
parry_stamina_cost = 4
parry_attack_types = ATTACK_TYPE_UNARMED | ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_TACKLE | ATTACK_TYPE_THROWN | ATTACK_TYPE_MELEE
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
parry_time_windup = 0
parry_time_spindown = 0
parry_time_active = 5
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 20
parry_efficiency_perfect = 100
parry_efficiency_perfect_override = list(
ATTACK_TYPE_PROJECTILE_TEXT = 60,
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 0
parry_cooldown = 0
parry_failed_clickcd_duration = 0.8
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
@@ -100,8 +100,3 @@
if(dna.species.space_move(src))
return TRUE
return ..()
/mob/living/carbon/human/CanPass(atom/movable/mover, turf/target)
if(dna.species.species_pass_check())
return TRUE
return ..()
@@ -0,0 +1,112 @@
/datum/action/innate/ability/slime_blobform
name = "Puddle Transformation"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimepuddle"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
required_mobility_flags = MOBILITY_STAND
var/is_puddle = FALSE
var/in_transformation_duration = 12
var/out_transformation_duration = 7
var/puddle_into_effect = /obj/effect/temp_visual/slime_puddle
var/puddle_from_effect = /obj/effect/temp_visual/slime_puddle/reverse
var/puddle_icon = 'icons/mob/mob.dmi'
var/puddle_state = "puddle"
var/mutable_appearance/tracked_overlay
var/datum/component/squeak/squeak
var/transforming = FALSE
var/last_use
/datum/action/innate/ability/slime_blobform/IsAvailable()
if(!transforming)
return ..()
else
return FALSE
/datum/action/innate/ability/slime_blobform/Remove(mob/M)
if(is_puddle)
detransform()
return ..()
/datum/action/innate/ability/slime_blobform/Activate()
var/mob/living/carbon/human/H = owner
//if they have anything stuck to their hands, we immediately say 'no' and return
for(var/obj/item/I in H.held_items)
if(HAS_TRAIT(I, TRAIT_NODROP))
to_chat(owner, "There's something stuck to your hand, stopping you from transforming!")
return
if(IsAvailable())
transforming = TRUE
UpdateButtonIcon()
var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"])
if(!is_puddle)
if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle
is_puddle = TRUE //so we know which transformation to use when its used
ADD_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
owner.cut_overlays() //we dont show our normal sprite, we show a puddle sprite
var/obj/effect/puddle_effect = new puddle_into_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
H.Stun(in_transformation_duration, ignore_canstun = TRUE) //cant move while transforming
//series of traits that make up the puddle behaviour
ADD_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE) //silently update arms to be paralysed
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer -= 1 //go one layer down so people go over you
ENABLE_BITFIELD(H.pass_flags, PASSMOB) //this actually lets people pass over you
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg')) //blorble noise when people step on you
//if the user is a changeling, retract their sting
H.unset_sting()
sleep(in_transformation_duration) //wait for animation to end
//set the puddle overlay up
var/mutable_appearance/puddle_overlay = mutable_appearance(icon = puddle_icon, icon_state = puddle_state)
puddle_overlay.color = mutcolor
tracked_overlay = puddle_overlay
owner.add_overlay(puddle_overlay)
transforming = FALSE
UpdateButtonIcon()
else
detransform()
else
to_chat(owner, "<span class='warning'>You need to be standing up to do this!") //just assume they're a slime because it's such a weird edgecase to have it and not be one (it shouldn't even be possible)
/datum/action/innate/ability/slime_blobform/proc/detransform()
var/mob/living/carbon/human/H = owner
//like the above, but reverse everything done!
H.cut_overlay(tracked_overlay)
var/obj/effect/puddle_effect = new puddle_from_effect(get_turf(owner), owner.dir)
puddle_effect.color = tracked_overlay.color
H.Stun(out_transformation_duration, ignore_canstun = TRUE)
sleep(out_transformation_duration)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE)
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer += 1 //go one layer back above!
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
is_puddle = FALSE
if(squeak)
squeak.RemoveComponent()
transforming = FALSE
UpdateButtonIcon()
@@ -0,0 +1,208 @@
/datum/action/innate/ability/humanoid_customization
name = "Alter Form"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "alter_form" //placeholder
icon_icon = 'modular_citadel/icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/ability/humanoid_customization/Activate()
if(owner.get_ability_property(INNATE_ABILITY_HUMANOID_CUSTOMIZATION, PROPERTY_CUSTOMIZATION_SILENT))
owner.visible_message("<span class='notice'>[owner] gains a look of \
concentration while standing perfectly still.\
Their body seems to shift and starts getting more goo-like.</span>",
"<span class='notice'>You focus intently on altering your body while \
standing perfectly still...</span>")
change_form()
///////
/////// NOTICE: This currently doens't support skin tone - if anyone wants to add this to non slimes, it's up to YOU to do this.
////// (someone should also add genital color switching, more mutant color selection)
///// maybe just make this entire thing tgui based. maybe.
///////
/datum/action/innate/ability/humanoid_customization/proc/change_form()
var/mob/living/carbon/human/H = owner
var/select_alteration = input(owner, "Select what part of your form to alter", "Form Alteration", "cancel") in list("Body Color","Hair Style", "Genitals", "Tail", "Snout", "Markings", "Ears", "Taur body", "Penis", "Vagina", "Penis Length", "Breast Size", "Breast Shape", "Cancel")
if(select_alteration == "Body Color")
var/new_color = input(owner, "Choose your skin color:", "Race change","#"+H.dna.features["mcolor"]) as color|null
if(new_color)
var/temp_hsv = RGBtoHSV(new_color)
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright
H.dna.features["mcolor"] = sanitize_hexcolor(new_color, 6)
H.update_body()
H.update_hair()
else
to_chat(H, "<span class='notice'>Invalid color. Your color is not bright enough.</span>")
else if(select_alteration == "Hair Style")
if(H.gender == MALE)
var/new_style = input(owner, "Select a facial hair style", "Hair Alterations") as null|anything in GLOB.facial_hair_styles_list
if(new_style)
H.facial_hair_style = new_style
else
H.facial_hair_style = "Shaved"
//handle normal hair
var/new_style = input(owner, "Select a hair style", "Hair Alterations") as null|anything in GLOB.hair_styles_list
if(new_style)
H.hair_style = new_style
H.update_hair()
else if (select_alteration == "Genitals")
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel")
switch(operation)
if("add sexual organ")
var/new_organ = input("Select sexual organ:", "Organ Manipulation") as null|anything in GLOB.genitals_list
if(!new_organ)
return
H.give_genital(GLOB.genitals_list[new_organ])
if("remove sexual organ")
var/list/organs = list()
for(var/obj/item/organ/genital/X in H.internal_organs)
var/obj/item/organ/I = X
organs["[I.name] ([I.type])"] = I
var/obj/item/O = input("Select sexual organ:", "Organ Manipulation", null) as null|anything in organs
var/obj/item/organ/genital/G = organs[O]
if(!G)
return
G.forceMove(get_turf(H))
qdel(G)
H.update_genitals()
else if (select_alteration == "Ears")
var/list/snowflake_ears_list = list("Normal" = null)
for(var/path in GLOB.mam_ears_list)
var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_ears_list[S.name] = path
var/new_ears
new_ears = input(owner, "Choose your character's ears:", "Ear Alteration") as null|anything in snowflake_ears_list
if(new_ears)
H.dna.features["mam_ears"] = new_ears
H.update_body()
else if (select_alteration == "Snout")
var/list/snowflake_snouts_list = list("Normal" = null)
for(var/path in GLOB.mam_snouts_list)
var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_snouts_list[S.name] = path
var/new_snout
new_snout = input(owner, "Choose your character's face:", "Face Alteration") as null|anything in snowflake_snouts_list
if(new_snout)
H.dna.features["mam_snouts"] = new_snout
H.update_body()
else if (select_alteration == "Markings")
var/list/snowflake_markings_list = list("None")
for(var/path in GLOB.mam_body_markings_list)
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_markings_list[S.name] = path
var/new_mam_body_markings
new_mam_body_markings = input(H, "Choose your character's body markings:", "Marking Alteration") as null|anything in snowflake_markings_list
if(new_mam_body_markings)
H.dna.features["mam_body_markings"] = new_mam_body_markings
for(var/X in H.bodyparts) //propagates the markings changes
var/obj/item/bodypart/BP = X
BP.update_limb(FALSE, H)
H.update_body()
else if (select_alteration == "Tail")
var/list/snowflake_tails_list = list("Normal" = null)
for(var/path in GLOB.mam_tails_list)
var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_tails_list[S.name] = path
var/new_tail
new_tail = input(owner, "Choose your character's Tail(s):", "Tail Alteration") as null|anything in snowflake_tails_list
if(new_tail)
H.dna.features["mam_tail"] = new_tail
if(new_tail != "None")
H.dna.features["taur"] = "None"
H.update_body()
else if (select_alteration == "Taur body")
var/list/snowflake_taur_list = list("Normal" = null)
for(var/path in GLOB.taur_list)
var/datum/sprite_accessory/taur/instance = GLOB.taur_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_taur_list[S.name] = path
var/new_taur
new_taur = input(owner, "Choose your character's tauric body:", "Tauric Alteration") as null|anything in snowflake_taur_list
if(new_taur)
H.dna.features["taur"] = new_taur
if(new_taur != "None")
H.dna.features["mam_tail"] = "None"
H.update_body()
else if (select_alteration == "Penis")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Choose your character's dong", "Genital Alteration") as null|anything in GLOB.cock_shapes_list
if(new_shape)
H.dna.features["cock_shape"] = new_shape
H.update_genitals()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
H.apply_overlay()
else if (select_alteration == "Vagina")
for(var/obj/item/organ/genital/vagina/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Choose your character's pussy", "Genital Alteration") as null|anything in GLOB.vagina_shapes_list
if(new_shape)
H.dna.features["vag_shape"] = new_shape
H.update_genitals()
H.give_genital(/obj/item/organ/genital/womb)
H.give_genital(/obj/item/organ/genital/vagina)
H.apply_overlay()
else if (select_alteration == "Penis Length")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/min_D = CONFIG_GET(number/penis_min_inches_prefs)
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.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
else if (select_alteration == "Breast Size")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
qdel(X)
var/new_size = input(owner, "Breast Size", "Genital Alteration") as null|anything in CONFIG_GET(keyed_list/breasts_cups_prefs)
if(new_size)
H.dna.features["breasts_size"] = new_size
H.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/breasts)
else if (select_alteration == "Breast Shape")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Breast Shape", "Genital Alteration") as null|anything in GLOB.breasts_shapes_list
if(new_shape)
H.dna.features["breasts_shape"] = new_shape
H.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/breasts)
else
return
@@ -0,0 +1,49 @@
/datum/action/innate/ability/limb_regrowth
name = "Regenerate Limbs"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeheal"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
required_mobility_flags = NONE
/datum/action/innate/ability/limb_regrowth/IsAvailable(silent = FALSE)
if(..())
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
return 0
var/mode = H.get_ability_property(INNATE_ABILITY_LIMB_REGROWTH, PROPERTY_LIMB_REGROWTH_USAGE_TYPE)
switch(mode)
if(REGROWTH_USES_BLOOD)
if(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
return TRUE
else
return FALSE
return 0
/datum/action/innate/ability/limb_regrowth/Activate()
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
to_chat(H, "<span class='notice'>You feel intact enough as it is.</span>")
return
to_chat(H, "<span class='notice'>You focus intently on your missing [limbs_to_heal.len >= 2 ? "limbs" : "limb"]...</span>")
var/mode = H.get_ability_property(INNATE_ABILITY_LIMB_REGROWTH, PROPERTY_LIMB_REGROWTH_USAGE_TYPE)
switch(mode)
if(REGROWTH_USES_BLOOD)
if(H.blood_volume >= 40*limbs_to_heal.len+(BLOOD_VOLUME_OKAY*H.blood_ratio))
H.regenerate_limbs()
H.blood_volume -= 40*limbs_to_heal.len
to_chat(H, "<span class='notice'>...and after a moment you finish reforming!</span>")
return
else if(H.blood_volume >= 40)//We can partially heal some limbs
while(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
var/healed_limb = pick(limbs_to_heal)
H.regenerate_limb(healed_limb)
limbs_to_heal -= healed_limb
H.blood_volume -= 40
to_chat(H, "<span class='warning'>...but there is not enough of you to fix everything! You must attain more mass to heal completely!</span>")
return
to_chat(H, "<span class='warning'>...but there is not enough of you to go around! You must attain more mass to heal!</span>")
+2 -2
View File
@@ -268,9 +268,9 @@
return round(thermal_protection/max_protection, 0.001)
/mob/living/carbon/human/handle_random_events()
//Puke if toxloss is too high
//Puke if toxloss is too high and we aren't a robot, because those have advanced toxins (corruption) handling
if(!stat)
if(getToxLoss() >= 45 && nutrition > 20)
if(getToxLoss() >= 45 && nutrition > 20 && !HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
lastpuke += prob(50)
if(lastpuke >= 50) // about 25 second delay I guess
vomit(20, toxic = TRUE)
@@ -7,6 +7,7 @@
var/oxy_mod = 1 // % of oxygen damage taken from all sources
var/clone_mod = 1 // % of clone damage taken from all sources
var/stamina_mod = 1 // % of stamina damage taken from all sources
var/stamina_buffer_mod = 1 // % of stamina buffer
var/brain_mod = 1 // % of brain damage taken from all sources
var/pressure_mod = 1 // % of brute damage taken from low or high pressure (stacks with brute_mod)
+64 -33
View File
@@ -175,6 +175,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//Called when cloning, copies some vars that should be kept
/datum/species/proc/copy_properties_from(datum/species/old_species)
mutant_bodyparts["limbs_id"] = old_species.mutant_bodyparts["limbs_id"]
eye_type = old_species.eye_type
mutanttongue = old_species.mutanttongue
return
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
@@ -668,7 +671,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.remove_overlay(BODY_FRONT_LAYER)
H.remove_overlay(HORNS_LAYER)
if(!mutant_bodyparts)
if(!length(mutant_bodyparts))
return
var/tauric = mutant_bodyparts["taur"] && H.dna.features["taur"] && H.dna.features["taur"] != "None"
@@ -746,14 +749,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
)
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"]]00")
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor2"]]00")
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]00")
colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
for(var/index in 1 to colorlist.len)
colorlist[index] /= 255
for(var/layer in relevant_layers)
var/list/standing = list()
@@ -775,6 +771,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(S.center)
accessory_overlay = center_image(accessory_overlay, S.dimension_x, S.dimension_y)
var/advanced_color_system = (H.dna.features["color_scheme"] == ADVANCED_CHARACTER_COLORING)
var/mutant_string = S.mutant_part_string
if(mutant_string == "tailwag") //wagging tails should be coloured the same way as your tail
mutant_string = "tail"
var/primary_string = advanced_color_system ? "[mutant_string]_primary" : "mcolor"
var/secondary_string = advanced_color_system ? "[mutant_string]_secondary" : "mcolor2"
var/tertiary_string = advanced_color_system ? "[mutant_string]_tertiary" : "mcolor3"
//failsafe: if there's no value for any of these, set it to white
if(!H.dna.features[primary_string])
H.dna.features[primary_string] = advanced_color_system ? H.dna.features["mcolor"] : "FFFFFF"
if(!H.dna.features[secondary_string])
H.dna.features[secondary_string] = advanced_color_system ? H.dna.features["mcolor2"] : "FFFFFF"
if(!H.dna.features[tertiary_string])
H.dna.features[tertiary_string] = advanced_color_system ? H.dna.features["mcolor3"] : "FFFFFF"
if(!husk)
if(!forced_colour)
switch(S.color_src)
@@ -784,20 +796,36 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(fixed_mut_color)
accessory_overlay.color = "#[fixed_mut_color]"
else
accessory_overlay.color = "#[H.dna.features["mcolor"]]"
accessory_overlay.color = "#[H.dna.features[primary_string]]"
if(MUTCOLORS2)
if(fixed_mut_color2)
accessory_overlay.color = "#[fixed_mut_color2]"
else
accessory_overlay.color = "#[H.dna.features["mcolor2"]]"
accessory_overlay.color = "#[H.dna.features[primary_string]]"
if(MUTCOLORS3)
if(fixed_mut_color3)
accessory_overlay.color = "#[fixed_mut_color3]"
else
accessory_overlay.color = "#[H.dna.features["mcolor3"]]"
accessory_overlay.color = "#[H.dna.features[primary_string]]"
if(MATRIXED)
accessory_overlay.color = list(colorlist)
var/list/accessory_colorlist = list()
if(S.matrixed_sections == MATRIX_RED || S.matrixed_sections == MATRIX_RED_GREEN || S.matrixed_sections == MATRIX_RED_BLUE || S.matrixed_sections == MATRIX_ALL)
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[primary_string]]00")
else
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("00000000")
if(S.matrixed_sections == MATRIX_GREEN || S.matrixed_sections == MATRIX_RED_GREEN || S.matrixed_sections == MATRIX_GREEN_BLUE || S.matrixed_sections == MATRIX_ALL)
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[secondary_string]]00")
else
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("00000000")
if(S.matrixed_sections == MATRIX_BLUE || S.matrixed_sections == MATRIX_RED_BLUE || S.matrixed_sections == MATRIX_GREEN_BLUE || S.matrixed_sections == MATRIX_ALL)
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[tertiary_string]]00")
else
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("00000000")
accessory_colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
for(var/index in 1 to accessory_colorlist.len)
accessory_colorlist[index] /= 255
accessory_overlay.color = list(accessory_colorlist)
if(HAIR)
if(hair_color == "mutcolor")
@@ -820,7 +848,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(bodypart == "tail")
accessory_overlay.icon_state = "m_tail_husk_[layertext]"
if(S.color_src == MATRIXED)
accessory_overlay.color = colorlist
var/list/accessory_colorlist = list()
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[primary_string]]00")
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[secondary_string]]00")
accessory_colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features[tertiary_string]]00")
accessory_colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
for(var/index in 1 to accessory_colorlist.len)
accessory_colorlist[index] /= 255
accessory_overlay.color = list(accessory_colorlist)
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
@@ -837,23 +872,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(S.center)
extra_accessory_overlay = center_image(extra_accessory_overlay, S.dimension_x, S.dimension_y)
switch(S.extra_color_src) //change the color of the extra overlay
if(MUTCOLORS)
if(fixed_mut_color)
extra_accessory_overlay.color = "#[fixed_mut_color]"
else
extra_accessory_overlay.color = "#[H.dna.features["mcolor"]]"
extra_accessory_overlay.color = "#[H.dna.features[secondary_string]]"
if(MUTCOLORS2)
if(fixed_mut_color2)
extra_accessory_overlay.color = "#[fixed_mut_color2]"
else
extra_accessory_overlay.color = "#[H.dna.features["mcolor2"]]"
extra_accessory_overlay.color = "#[H.dna.features[secondary_string]]"
if(MUTCOLORS3)
if(fixed_mut_color3)
extra_accessory_overlay.color = "#[fixed_mut_color3]"
else
extra_accessory_overlay.color = "#[H.dna.features["mcolor3"]]"
extra_accessory_overlay.color = "#[H.dna.features[secondary_string]]"
if(HAIR)
if(hair_color == "mutcolor")
extra_accessory_overlay.color = "#[H.dna.features["mcolor3"]]"
@@ -889,17 +923,17 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(fixed_mut_color)
extra2_accessory_overlay.color = "#[fixed_mut_color]"
else
extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]"
extra2_accessory_overlay.color = "#[H.dna.features[tertiary_string]]"
if(MUTCOLORS2)
if(fixed_mut_color2)
extra2_accessory_overlay.color = "#[fixed_mut_color2]"
else
extra2_accessory_overlay.color = "#[H.dna.features["mcolor2"]]"
extra2_accessory_overlay.color = "#[H.dna.features[tertiary_string]]"
if(MUTCOLORS3)
if(fixed_mut_color3)
extra2_accessory_overlay.color = "#[fixed_mut_color3]"
else
extra2_accessory_overlay.color = "#[H.dna.features["mcolor3"]]"
extra2_accessory_overlay.color = "#[H.dna.features[tertiary_string]]"
if(HAIR)
if(hair_color == "mutcolor3")
extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]"
@@ -916,7 +950,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
standing += extra2_accessory_overlay
H.overlays_standing[layernum] = standing
H.apply_overlay(BODY_BEHIND_LAYER)
@@ -1284,6 +1317,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
radiation = 0
return TRUE
if(HAS_TRAIT(H, TRAIT_ROBOTIC_ORGANISM))
return //Robots are hardened against radiation, but suffer system corruption at very high levels.
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
if(CHECK_MOBILITY(H, MOBILITY_STAND))
H.emote("collapse")
@@ -1451,9 +1487,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.apply_damage(damage*1.5, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
target.apply_damage(damage*0.5, STAMINA, affecting, armor_block)
log_combat(user, target, "kicked")
else if(HAS_TRAIT(user, TRAIT_MAULER)) // mauler punches deal 1.3x raw damage + 1x stam damage, and have some armor pierce
target.apply_damage(damage*1.3, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
target.apply_damage(damage, STAMINA, affecting, armor_block)
else if(HAS_TRAIT(user, TRAIT_MAULER)) // mauler punches deal 1.1x raw damage + 1.3x stam damage, and have some armor pierce
target.apply_damage(damage*1.1, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
target.apply_damage(damage*1.3, STAMINA, affecting, armor_block)
log_combat(user, target, "punched (mauler)")
else //other attacks deal full raw damage + 2x in stamina damage
target.apply_damage(damage, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
@@ -1689,7 +1725,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(BODY_ZONE_HEAD)
if(!I.get_sharpness() && armor_block < 50)
if(prob(I.force))
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
H.adjustToxLoss(5, toxins_type = TOX_SYSCORRUPT) //Bonk! - Effectively 5 bonus damage
else
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
if(H.stat == CONSCIOUS)
H.visible_message("<span class='danger'>[H] has been knocked senseless!</span>", \
"<span class='userdanger'>You have been knocked senseless!</span>")
@@ -1963,14 +2002,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HAS_BONE in species_traits)
. |= BIO_JUST_BONE
//a check for if you should render any overlays or not
/datum/species/proc/should_render(mob/living/carbon/human/H)
return TRUE
//a check for if you want to forcibly make CanPass return TRUE for the mob with this species
/datum/species/proc/species_pass_check()
return FALSE
/////////////
//BREATHING//
/////////////
@@ -3,12 +3,12 @@
id = SPECIES_ANDROID
say_mod = "states"
species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT, TRAIT_ROBOTIC_ORGANISM)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
meat = null
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"
limbs_id = SPECIES_SYNTH
species_category = SPECIES_CATEGORY_ROBOT
@@ -7,7 +7,7 @@
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
no_equip = list(SLOT_BACK)
blacklisted = 1
limbs_id = "human"
limbs_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
species_category = SPECIES_CATEGORY_BASIC //they're a kind of human
@@ -130,7 +130,7 @@
/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
if(flight && CanFly(H))
stunmod = 2
speedmod = -0.35
speedmod = -0.1
H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
H.pass_flags |= PASSTABLE
@@ -1,6 +1,6 @@
/datum/species/arachnid
name = "Arachnid"
id = "arachnid"
id = SPECIES_ARACHNID
override_bp_icon = 'icons/mob/arachnid_parts.dmi'
say_mod = "chitters"
default_color = "00FF00"
@@ -59,10 +59,10 @@
SW?.Remove(H)
/datum/action/innate/spin_web
name = "Spin Web"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
icon_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "lay_web"
name = "Spin Web"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
icon_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "lay_web"
/datum/action/innate/spin_cocoon
name = "Spin Cocoon"
@@ -139,6 +139,18 @@
if(E.web_ready == FALSE)
to_chat(H, "<span class='warning'>You need to wait awhile to regenerate web fluid.</span>")
return
if(!H.Adjacent(A)) //No.
return
if(!isliving(A) && A.anchored)
to_chat(H, "<span class='warning'>[A] is bolted to the floor!</span>")
return
if(istype(A, /obj/structure/arachnid))
to_chat(H, "<span class='warning'>No double wrapping.</span>")
return
if(istype(A, /obj/effect))
to_chat(H, "<span class='warning'>You cannot wrap this.</span>")
return
H.visible_message("<span class='danger'>[H] starts to wrap [A] into a cocoon!</span>","<span class='warning'>You start to wrap [A] into a cocoon.</span>")
if(!do_after(H, 10 SECONDS, 1, A))
to_chat(H, "<span class='warning'>Your web spinning was interrupted!</span>")
return
@@ -152,4 +164,4 @@
else
A.forceMove(C)
H.visible_message("<span class='danger'>[H] wraps [A] into a cocoon!</span>")
return
return
@@ -11,7 +11,7 @@
mutanttongue = /obj/item/organ/tongue/dullahan
mutantears = /obj/item/organ/ears/dullahan
blacklisted = TRUE
limbs_id = "human"
limbs_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head.
species_category = SPECIES_CATEGORY_UNDEAD
@@ -27,7 +27,7 @@
/datum/species/dullahan/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return FALSE
return ..()
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
@@ -2,7 +2,7 @@
/datum/species/human/felinid
name = "Felinid"
id = SPECIES_FELINID
limbs_id = "human"
limbs_id = SPECIES_HUMAN
mutant_bodyparts = list("mam_tail" = "Cat", "mam_ears" = "Cat", "deco_wings" = "None")
@@ -5,7 +5,7 @@
default_color = "00FF00"
blacklisted = 0
sexes = 0
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR,ROBOTIC_LIMBS)
hair_alpha = 210
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
@@ -15,9 +15,6 @@
exotic_bloodtype = "GEL"
exotic_blood_color = "BLOOD_COLOR_SLIME"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
var/datum/action/innate/slime_change/slime_change
var/datum/action/innate/slime_puddle/slime_puddle
liked_food = TOXIC | MEAT
disliked_food = null
toxic_food = ANTITOXIC
@@ -37,27 +34,19 @@
icon_state = "brain-slime"
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(slime_puddle && slime_puddle.is_puddle)
slime_puddle.Activate()
if(regenerate_limbs)
regenerate_limbs.Remove(C)
if(slime_change)
slime_change.Remove(C)
if(slime_puddle)
slime_puddle.Remove(C)
C.faction -= "slime"
if(ishuman(C))
var/mob/living/carbon/human/H = C
H.remove_ability_from_source(list(INNATE_ABILITY_SLIME_BLOBFORM, INNATE_ABILITY_LIMB_REGROWTH, INNATE_ABILITY_HUMANOID_CUSTOMIZATION), ABILITY_SOURCE_SPECIES)
..()
C.faction -= "slime"
/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
slime_change = new
slime_change.Grant(C)
slime_puddle = new
slime_puddle.Grant(C)
var/mob/living/carbon/human/H = C
H.grant_ability_from_source(list(INNATE_ABILITY_SLIME_BLOBFORM, INNATE_ABILITY_LIMB_REGROWTH, INNATE_ABILITY_HUMANOID_CUSTOMIZATION), ABILITY_SOURCE_SPECIES)
H.set_ability_property(INNATE_ABILITY_LIMB_REGROWTH, PROPERTY_LIMB_REGROWTH_USAGE_TYPE, REGROWTH_USES_BLOOD)
C.faction |= "slime"
/datum/species/jelly/handle_body(mob/living/carbon/human/H)
@@ -65,18 +54,6 @@
//update blood color to body color
exotic_blood_color = "#" + H.dna.features["mcolor"]
/datum/species/jelly/should_render()
if(slime_puddle && slime_puddle.is_puddle)
return FALSE
else
return ..()
/datum/species/jelly/species_pass_check()
if(slime_puddle && slime_puddle.is_puddle)
return TRUE
else
return ..()
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers
return
@@ -94,8 +71,6 @@
to_chat(H, "<span class='danger'>You feel drained!</span>")
if(H.blood_volume < (BLOOD_VOLUME_BAD*H.blood_ratio))
Cannibalize_Body(H)
if(regenerate_limbs)
regenerate_limbs.UpdateButtonIcon()
/datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H)
var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs()
@@ -111,47 +86,6 @@
qdel(consumed_limb)
H.blood_volume += 20
/datum/action/innate/regenerate_limbs
name = "Regenerate Limbs"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeheal"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
required_mobility_flags = NONE
/datum/action/innate/regenerate_limbs/IsAvailable(silent = FALSE)
if(..())
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
return 0
if(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
return 1
return 0
/datum/action/innate/regenerate_limbs/Activate()
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
to_chat(H, "<span class='notice'>You feel intact enough as it is.</span>")
return
to_chat(H, "<span class='notice'>You focus intently on your missing [limbs_to_heal.len >= 2 ? "limbs" : "limb"]...</span>")
if(H.blood_volume >= 40*limbs_to_heal.len+(BLOOD_VOLUME_OKAY*H.blood_ratio))
H.regenerate_limbs()
H.blood_volume -= 40*limbs_to_heal.len
to_chat(H, "<span class='notice'>...and after a moment you finish reforming!</span>")
return
else if(H.blood_volume >= 40)//We can partially heal some limbs
while(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
var/healed_limb = pick(limbs_to_heal)
H.regenerate_limb(healed_limb)
limbs_to_heal -= healed_limb
H.blood_volume -= 40
to_chat(H, "<span class='warning'>...but there is not enough of you to fix everything! You must attain more mass to heal completely!</span>")
return
to_chat(H, "<span class='warning'>...but there is not enough of you to go around! You must attain more mass to heal!</span>")
////////////////////////////////////////////////////////SLIMEPEOPLE///////////////////////////////////////////////////////////////////
//Slime people are able to split like slimes, retaining a single mind that can swap between bodies at will, even after death.
@@ -468,7 +402,7 @@
/datum/species/jelly/roundstartslime
name = "Xenobiological Slime Hybrid"
id = SPECIES_SLIME_HYBRID
limbs_id = "slime"
limbs_id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
inherent_traits = list(TRAIT_TOXINLOVER)
@@ -480,296 +414,7 @@
heatmod = 1
burnmod = 1
allowed_limb_ids = list("slime","stargazer","lum")
/datum/action/innate/slime_change
name = "Alter Form"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "alter_form" //placeholder
icon_icon = 'modular_citadel/icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
/datum/action/innate/slime_change/Activate()
var/mob/living/carbon/human/H = owner
if(!isjellyperson(H))
return
else
H.visible_message("<span class='notice'>[owner] gains a look of \
concentration while standing perfectly still.\
Their body seems to shift and starts getting more goo-like.</span>",
"<span class='notice'>You focus intently on altering your body while \
standing perfectly still...</span>")
change_form()
/datum/action/innate/slime_change/proc/change_form()
var/mob/living/carbon/human/H = owner
var/select_alteration = input(owner, "Select what part of your form to alter", "Form Alteration", "cancel") in list("Body Color","Hair Style", "Genitals", "Tail", "Snout", "Markings", "Ears", "Taur body", "Penis", "Vagina", "Penis Length", "Breast Size", "Breast Shape", "Cancel")
if(select_alteration == "Body Color")
var/new_color = input(owner, "Choose your skin color:", "Race change","#"+H.dna.features["mcolor"]) as color|null
if(new_color)
var/temp_hsv = RGBtoHSV(new_color)
if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright
H.dna.features["mcolor"] = sanitize_hexcolor(new_color, 6)
H.update_body()
H.update_hair()
else
to_chat(H, "<span class='notice'>Invalid color. Your color is not bright enough.</span>")
else if(select_alteration == "Hair Style")
if(H.gender == MALE)
var/new_style = input(owner, "Select a facial hair style", "Hair Alterations") as null|anything in GLOB.facial_hair_styles_list
if(new_style)
H.facial_hair_style = new_style
else
H.facial_hair_style = "Shaved"
//handle normal hair
var/new_style = input(owner, "Select a hair style", "Hair Alterations") as null|anything in GLOB.hair_styles_list
if(new_style)
H.hair_style = new_style
H.update_hair()
else if (select_alteration == "Genitals")
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel")
switch(operation)
if("add sexual organ")
var/new_organ = input("Select sexual organ:", "Organ Manipulation") as null|anything in GLOB.genitals_list
if(!new_organ)
return
H.give_genital(GLOB.genitals_list[new_organ])
if("remove sexual organ")
var/list/organs = list()
for(var/obj/item/organ/genital/X in H.internal_organs)
var/obj/item/organ/I = X
organs["[I.name] ([I.type])"] = I
var/obj/item/O = input("Select sexual organ:", "Organ Manipulation", null) as null|anything in organs
var/obj/item/organ/genital/G = organs[O]
if(!G)
return
G.forceMove(get_turf(H))
qdel(G)
H.update_genitals()
else if (select_alteration == "Ears")
var/list/snowflake_ears_list = list("Normal" = null)
for(var/path in GLOB.mam_ears_list)
var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_ears_list[S.name] = path
var/new_ears
new_ears = input(owner, "Choose your character's ears:", "Ear Alteration") as null|anything in snowflake_ears_list
if(new_ears)
H.dna.features["mam_ears"] = new_ears
H.update_body()
else if (select_alteration == "Snout")
var/list/snowflake_snouts_list = list("Normal" = null)
for(var/path in GLOB.mam_snouts_list)
var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_snouts_list[S.name] = path
var/new_snout
new_snout = input(owner, "Choose your character's face:", "Face Alteration") as null|anything in snowflake_snouts_list
if(new_snout)
H.dna.features["mam_snouts"] = new_snout
H.update_body()
else if (select_alteration == "Markings")
var/list/snowflake_markings_list = list("None")
for(var/path in GLOB.mam_body_markings_list)
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_markings_list[S.name] = path
var/new_mam_body_markings
new_mam_body_markings = input(H, "Choose your character's body markings:", "Marking Alteration") as null|anything in snowflake_markings_list
if(new_mam_body_markings)
H.dna.features["mam_body_markings"] = new_mam_body_markings
for(var/X in H.bodyparts) //propagates the markings changes
var/obj/item/bodypart/BP = X
BP.update_limb(FALSE, H)
H.update_body()
else if (select_alteration == "Tail")
var/list/snowflake_tails_list = list("Normal" = null)
for(var/path in GLOB.mam_tails_list)
var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_tails_list[S.name] = path
var/new_tail
new_tail = input(owner, "Choose your character's Tail(s):", "Tail Alteration") as null|anything in snowflake_tails_list
if(new_tail)
H.dna.features["mam_tail"] = new_tail
if(new_tail != "None")
H.dna.features["taur"] = "None"
H.update_body()
else if (select_alteration == "Taur body")
var/list/snowflake_taur_list = list("Normal" = null)
for(var/path in GLOB.taur_list)
var/datum/sprite_accessory/taur/instance = GLOB.taur_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
snowflake_taur_list[S.name] = path
var/new_taur
new_taur = input(owner, "Choose your character's tauric body:", "Tauric Alteration") as null|anything in snowflake_taur_list
if(new_taur)
H.dna.features["taur"] = new_taur
if(new_taur != "None")
H.dna.features["mam_tail"] = "None"
H.update_body()
else if (select_alteration == "Penis")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Choose your character's dong", "Genital Alteration") as null|anything in GLOB.cock_shapes_list
if(new_shape)
H.dna.features["cock_shape"] = new_shape
H.update_genitals()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
H.apply_overlay()
else if (select_alteration == "Vagina")
for(var/obj/item/organ/genital/vagina/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Choose your character's pussy", "Genital Alteration") as null|anything in GLOB.vagina_shapes_list
if(new_shape)
H.dna.features["vag_shape"] = new_shape
H.update_genitals()
H.give_genital(/obj/item/organ/genital/womb)
H.give_genital(/obj/item/organ/genital/vagina)
H.apply_overlay()
else if (select_alteration == "Penis Length")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/min_D = CONFIG_GET(number/penis_min_inches_prefs)
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.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
else if (select_alteration == "Breast Size")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
qdel(X)
var/new_size = input(owner, "Breast Size", "Genital Alteration") as null|anything in CONFIG_GET(keyed_list/breasts_cups_prefs)
if(new_size)
H.dna.features["breasts_size"] = new_size
H.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/breasts)
else if (select_alteration == "Breast Shape")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(owner, "Breast Shape", "Genital Alteration") as null|anything in GLOB.breasts_shapes_list
if(new_shape)
H.dna.features["breasts_shape"] = new_shape
H.update_genitals()
H.apply_overlay()
H.give_genital(/obj/item/organ/genital/breasts)
else
return
/datum/action/innate/slime_puddle
name = "Puddle Transformation"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimepuddle"
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
required_mobility_flags = MOBILITY_STAND
var/is_puddle = FALSE
var/in_transformation_duration = 12
var/out_transformation_duration = 7
var/puddle_into_effect = /obj/effect/temp_visual/slime_puddle
var/puddle_from_effect = /obj/effect/temp_visual/slime_puddle/reverse
var/puddle_icon = 'icons/mob/mob.dmi'
var/puddle_state = "puddle"
var/tracked_overlay
var/datum/component/squeak/squeak
var/transforming = FALSE
var/last_use
/datum/action/innate/slime_puddle/IsAvailable()
if(!transforming)
return ..()
else
return FALSE
/datum/action/innate/slime_puddle/Activate()
if(isjellyperson(owner) && IsAvailable())
transforming = TRUE
UpdateButtonIcon()
var/mob/living/carbon/human/H = owner
var/mutcolor = "#" + H.dna.features["mcolor"]
if(!is_puddle)
if(CHECK_MOBILITY(H, MOBILITY_USE))
is_puddle = TRUE
owner.cut_overlays()
var/obj/effect/puddle_effect = new puddle_into_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
H.Stun(in_transformation_duration, ignore_canstun = TRUE)
ADD_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.update_disabled_bodyparts(silent = TRUE)
H.layer -= 1 //go one layer down so people go over you
ENABLE_BITFIELD(H.pass_flags, PASSMOB)
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg'))
sleep(in_transformation_duration)
var/mutable_appearance/puddle_overlay = mutable_appearance(icon = puddle_icon, icon_state = puddle_state)
puddle_overlay.color = mutcolor
tracked_overlay = puddle_overlay
owner.add_overlay(puddle_overlay)
transforming = FALSE
UpdateButtonIcon()
else
owner.cut_overlay(tracked_overlay)
var/obj/effect/puddle_effect = new puddle_from_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
H.Stun(out_transformation_duration, ignore_canstun = TRUE)
sleep(out_transformation_duration)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE)
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer += 1 //go one layer back above!
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
is_puddle = FALSE
if(squeak)
squeak.RemoveComponent()
owner.regenerate_icons()
transforming = FALSE
UpdateButtonIcon()
else
to_chat(owner, "<span class='warning'>You need to be standing up to do this!") //just assume they're a slime because it's such a weird edgecase to have it and not be one (it shouldn't even be possible)
allowed_limb_ids = list(SPECIES_SLIME,SPECIES_STARGAZER,SPECIES_SLIME_LUMI)
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
@@ -28,7 +28,7 @@
tail_type = "tail_lizard"
wagging_type = "waggingtail_lizard"
species_category = "lizard"
species_category = SPECIES_CATEGORY_LIZARD
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
@@ -47,7 +47,7 @@
/datum/species/lizard/ashwalker
name = "Ash Walker"
id = SPECIES_ASHWALKER
limbs_id = "lizard"
limbs_id = SPECIES_LIZARD
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
mutantlungs = /obj/item/organ/lungs/ashwalker
@@ -10,6 +10,7 @@
burnmod = 1.25
heatmod = 1.5
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
exotic_blood_color = BLOOD_COLOR_PLANT
disliked_food = MEAT | DAIRY
liked_food = VEGETABLES | FRUIT | GRAIN
species_language_holder = /datum/language_holder/sylvan
@@ -69,7 +70,7 @@
id = SPECIES_POD_WEAK
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
limbs_id = "pod"
limbs_id = SPECIES_POD
light_nutrition_gain_factor = 3
light_bruteheal = -0.2
light_burnheal = -0.2
@@ -33,7 +33,7 @@
/datum/species/shadow/nightmare
name = "Nightmare"
id = SPECIES_NIGHTMARE
limbs_id = "shadow"
limbs_id = SPECIES_SHADOW
burnmod = 1.5
blacklisted = TRUE
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE)
@@ -141,7 +141,7 @@
playsound(owner,'sound/effects/singlebeat.ogg',40,1)
if(respawn_progress >= HEART_RESPAWN_THRESHHOLD)
owner.revive(full_heal = TRUE)
if(!(owner.dna.species.id == "shadow" || owner.dna.species.id == "nightmare"))
if(!(owner.dna.species.id == SPECIES_SHADOW || owner.dna.species.id == SPECIES_NIGHTMARE))
var/mob/living/carbon/old_owner = owner
Remove(HEART_SPECIAL_SHADOWIFY)
old_owner.set_species(/datum/species/shadow)
@@ -32,7 +32,7 @@
/datum/species/skeleton/space
name = "Spooky Spacey Skeleton"
id = SPECIES_SKELETON_SPACE
limbs_id = "skeleton"
limbs_id = SPECIES_SKELETON
blacklisted = 1
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT, TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
@@ -4,7 +4,7 @@
say_mod = "beeps"
default_color = "00FF00"
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
@@ -11,7 +11,7 @@
meat = null
gib_types = /obj/effect/gibspawner/robot
damage_overlay_type = "synth"
limbs_id = "synth"
limbs_id = SPECIES_SYNTH
var/list/initial_species_traits = list(NOTRANSSTING) //for getting these values back for assume_disguise()
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
@@ -80,7 +80,7 @@
qdel(fake_species)
fake_species = null
meat = initial(meat)
limbs_id = "synth"
limbs_id = SPECIES_SYNTH
use_skintones = FALSE
sexes = 0
fixed_mut_color = ""
@@ -11,12 +11,17 @@
mutant_heart = /obj/item/organ/heart/vampire
mutanttongue = /obj/item/organ/tongue/vampire
blacklisted = TRUE
limbs_id = "human"
limbs_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
var/info_text = "You are a <span class='danger'>Vampire</span>. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
species_category = SPECIES_CATEGORY_UNDEAD
var/batform_enabled = TRUE
/datum/species/vampire/check_roundstart_eligible()
/datum/species/vampire/roundstart
id = SPECIES_VAMPIRE_WEAK
batform_enabled = FALSE
/datum/species/vampire/roundstart/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return FALSE
@@ -27,8 +32,9 @@
if(!C.dna.skin_tone_override)
C.skin_tone = "albino"
C.update_body(0)
var/obj/effect/proc_holder/spell/targeted/shapeshift/bat/B = new
C.AddSpell(B)
if(batform_enabled)
var/obj/effect/proc_holder/spell/targeted/shapeshift/bat/B = new
C.AddSpell(B)
/datum/species/vampire/on_species_loss(mob/living/carbon/C)
. = ..()
@@ -153,16 +159,33 @@
to_chat(caster, "<span class='warning'>You're already shapeshifted!</span>")
return
if(!ishuman(caster))
to_chat(caster, "<span class='warning'>You need to be humanoid to be able to do this!</span>")
return
var/mob/living/carbon/human/human_caster = caster
var/mob/living/shape = new shapeshift_type(caster.loc)
H = new(shape,src,caster)
H = new(shape,src,human_caster)
if(istype(H, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = H
if((caster.blood_volume >= (BLOOD_VOLUME_BAD*caster.blood_ratio)) || (ventcrawl_nude_only && length(caster.get_equipped_items(include_pockets = TRUE))))
if((human_caster.blood_volume <= (BLOOD_VOLUME_BAD*human_caster.blood_ratio)) || (ventcrawl_nude_only && length(human_caster.get_equipped_items(include_pockets = TRUE))))
SA.ventcrawler = FALSE
if(transfer_name)
H.name = caster.name
H.name = human_caster.name
clothes_req = NONE
mobs_whitelist = null
mobs_blacklist = null
/obj/effect/proc_holder/spell/targeted/shapeshift/bat/cast(list/targets, mob/user = usr)
if(!(locate(/obj/shapeshift_holder) in targets[1]))
if(!ishuman(user))
to_chat(user, "<span class='warning'>You need to be humanoid to be able to do this!</span>")
return
var/mob/living/carbon/human/human_user = user
if(!(human_user.dna?.species?.id == SPECIES_VAMPIRE))
to_chat(user, "<span class='warning'>You don't seem to be able to shapeshift..</span>")
return
return ..()
@@ -3,7 +3,7 @@
/datum/species/zombie
// 1spooky
name = "High-Functioning Zombie"
id = "zombie"
id = SPECIES_ZOMBIE
say_mod = "moans"
sexes = 0
blacklisted = 1
@@ -19,7 +19,7 @@
/datum/species/zombie/notspaceproof
id = "notspaceproofzombie"
limbs_id = "zombie"
limbs_id = SPECIES_ZOMBIE
blacklisted = 0
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
@@ -31,7 +31,7 @@
/datum/species/zombie/infectious
name = "Infectious Zombie"
id = "memezombies"
limbs_id = "zombie"
limbs_id = SPECIES_ZOMBIE
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_NOSOFTCRIT, TRAIT_FAKEDEATH)
mutanthands = /obj/item/zombie_hand
armor = 20 // 120 damage to KO a zombie, which kills it
@@ -100,7 +100,7 @@
/datum/species/krokodil_addict
name = SPECIES_HUMAN
id = "goofzombies"
limbs_id = "zombie" //They look like zombies
limbs_id = SPECIES_ZOMBIE //They look like zombies
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
mutanttongue = /obj/item/organ/tongue/zombie
@@ -48,18 +48,22 @@ There are several things that need to be remembered:
*/
/mob/living/carbon/human/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_HUMAN_NO_RENDER), /mob.proc/regenerate_icons)
//HAIR OVERLAY
/mob/living/carbon/human/update_hair()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
dna.species.handle_hair(src)
//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/proc/update_mutant_bodyparts()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/update_body(update_genitals = FALSE)
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(BODY_LAYER)
dna.species.handle_body(src)
..()
@@ -69,11 +73,10 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_fire()
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
if(!..())
icon_render_key = null //invalidate bodyparts cache
update_body(TRUE)
@@ -102,7 +105,7 @@ There are several things that need to be remembered:
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
@@ -154,7 +157,7 @@ There are several things that need to be remembered:
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(ID_LAYER)
if(client && hud_used)
@@ -179,7 +182,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_gloves()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(GLOVES_LAYER)
if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
@@ -213,7 +216,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_glasses()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(GLASSES_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
@@ -240,7 +243,7 @@ There are several things that need to be remembered:
apply_overlay(GLASSES_LAYER)
/mob/living/carbon/human/update_inv_ears()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(EARS_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
@@ -266,7 +269,7 @@ There are several things that need to be remembered:
apply_overlay(EARS_LAYER)
/mob/living/carbon/human/update_inv_shoes()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SHOES_LAYER)
if(get_num_legs(FALSE) <2)
@@ -304,7 +307,7 @@ There are several things that need to be remembered:
apply_overlay(SHOES_LAYER)
/mob/living/carbon/human/update_inv_s_store()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SUIT_STORE_LAYER)
if(client && hud_used)
@@ -328,7 +331,7 @@ There are several things that need to be remembered:
apply_overlay(SUIT_STORE_LAYER)
/mob/living/carbon/human/update_inv_head()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(HEAD_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
@@ -368,7 +371,7 @@ There are several things that need to be remembered:
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(BELT_LAYER)
if(client && hud_used)
@@ -390,7 +393,7 @@ There are several things that need to be remembered:
apply_overlay(BELT_LAYER)
/mob/living/carbon/human/update_inv_wear_suit()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SUIT_LAYER)
if(client && hud_used)
@@ -477,7 +480,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_wear_mask()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(FACEMASK_LAYER)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
@@ -518,7 +521,7 @@ There are several things that need to be remembered:
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
..()
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
if(back_overlay)
@@ -669,6 +672,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
//produces a key based on the human's limbs
/mob/living/carbon/human/generate_icon_render_key()
. = "[dna.species.mutant_bodyparts["limbs_id"]]"
. += "[dna.features["color_scheme"]]"
if(dna.check_mutation(HULK))
. += "-coloured-hulk"
@@ -708,6 +712,11 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
. += "-[BP.dmg_overlay_type]"
if(BP.body_markings)
. += "-[BP.body_markings]"
if(length(BP.markings_color) && length(BP.markings_color[1]))
for(var/color in BP.markings_color[1])
. += "-[color]"
if(BP.icon)
. += "-[BP.icon]"
else
. += "-no_marking"
@@ -741,7 +750,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
if(!dna.species)
return
if(dna.species.should_render())
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
return
var/obj/item/bodypart/HD = get_bodypart("head")
+20 -1
View File
@@ -14,10 +14,29 @@
return legcuffed
return null
/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1, critical = FALSE)
for(var/slot in slots)
if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
return slot
if(critical) //it is CRITICAL they get this item, no matter what
//do they have a backpack?
var/obj/item/backpack = get_item_by_slot(SLOT_BACK)
if(!backpack)
//nothing on their back
backpack = new /obj/item/storage/backpack(get_turf(src))
if(equip_to_slot(backpack, SLOT_BACK)) //worst-case-scenario, something that shouldnt wear a backpack gets one
I.forceMove(backpack)
return SLOT_BACK
else if(istype(backpack) && SEND_SIGNAL(backpack, COMSIG_CONTAINS_STORAGE))
//place it in here, regardless of storage capacity
I.forceMove(backpack)
return SLOT_BACK
else
//this should NEVER happen, but if it does, report it with the appropriate information
var/conclusion = qdel_on_fail ? "deleted" : "not moved, staying at current position [I.x], [I.y], [I.z]"
message_admins("User [src] failed to get item of critical importance: [I]. Result: item is [conclusion]")
//it's not dropped at their turf as this is generally un-safe for midround antags and we don't know their status
if(qdel_on_fail)
qdel(I)
return null
+10 -2
View File
@@ -25,6 +25,9 @@
if(stat != DEAD)
handle_liver()
if(stat != DEAD)
handle_corruption()
/mob/living/carbon/PhysicalLife(seconds, times_fired)
if(!(. = ..()))
@@ -406,7 +409,7 @@
for(var/thing in all_wounds)
var/datum/wound/W = thing
if(W.processes) // meh
W.handle_process()
W.handle_process()
/mob/living/carbon/handle_mutations_and_radiation()
if(dna && dna.temporary_mutations.len)
@@ -438,7 +441,12 @@
radiation -= min(radiation, RAD_LOSS_PER_TICK)
if(radiation > RAD_MOB_SAFE)
adjustToxLoss(log(radiation-RAD_MOB_SAFE)*RAD_TOX_COEFFICIENT)
if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
adjustToxLoss(log(radiation-RAD_MOB_SAFE)*RAD_TOX_COEFFICIENT)
else
var/rad_threshold = HAS_TRAIT(src, TRAIT_ROBOT_RADSHIELDING) ? RAD_UPGRADED_ROBOT_SAFE : RAD_DEFAULT_ROBOT_SAFE
if(radiation > rad_threshold)
adjustToxLoss(log(radiation-rad_threshold)*RAD_TOX_COEFFICIENT, toxins_type = TOX_SYSCORRUPT) //Robots are less resistant to rads, unless upgraded in which case they are fine at higher levels than organics.
/mob/living/carbon/handle_stomach()
set waitfor = 0
@@ -77,4 +77,4 @@
/mob/living/carbon/monkey/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_back
client.screen += I
client.screen += I
+1 -1
View File
@@ -17,4 +17,4 @@
if(T)
return T.could_speak_language(language)
else
return initial(language.flags) & TONGUELESS_SPEECH
return initial(language.flags) & TONGUELESS_SPEECH
+29 -4
View File
@@ -168,20 +168,45 @@
updatehealth()
return amount
/mob/living/proc/getToxLoss()
return toxloss
//By default, returns toxins damage no matter what kind of tox damage the target is using.
/mob/living/proc/getToxLoss(toxins_type = TOX_OMNI)
if(toxins_type == TOX_OMNI)
return toxloss
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
var/affected_by = TOX_DEFAULT
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
affected_by = TOX_SYSCORRUPT
if(toxins_type != affected_by)
return 0
else
return toxloss
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
if(!forced && (status_flags & GODMODE))
return FALSE
var/affected_by = TOX_DEFAULT
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
affected_by = TOX_SYSCORRUPT
if(toxins_type != TOX_OMNI && toxins_type != affected_by)
return FALSE
toxloss = clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
/mob/living/proc/setToxLoss(amount, updating_health = TRUE, forced = FALSE)
//Defaults to omni here because setToxLoss is used by very few things that usually want to set all types
/mob/living/proc/setToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_OMNI)
if(!forced && (status_flags & GODMODE))
return FALSE
var/affected_by = TOX_DEFAULT
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
affected_by = TOX_SYSCORRUPT
if(toxins_type != TOX_OMNI && toxins_type != affected_by)
return FALSE
toxloss = amount
if(updating_health)
updatehealth()
+5
View File
@@ -66,6 +66,10 @@
GLOB.alive_mob_list -= src
if(!gibbed)
GLOB.dead_mob_list += src
if(ckey)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_time_of_death = world.time
set_drugginess(0)
set_disgust(0)
SetSleeping(0, 0)
@@ -78,6 +82,7 @@
update_mobility()
med_hud_set_health()
med_hud_set_status()
clear_typing_indicator()
if(!gibbed && !QDELETED(src))
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
stop_pulling()
+2 -13
View File
@@ -443,6 +443,7 @@
key = "me"
key_third_person = "custom"
message = null
emote_type = EMOTE_BOTH
/datum/emote/living/custom/proc/check_invalid(mob/user, input)
if(stop_bad_mime.Find(input, 1, 1))
@@ -462,24 +463,12 @@
else if(!params)
var/custom_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
if(custom_emote && !check_invalid(user, custom_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
if("Visible")
emote_type = EMOTE_VISIBLE
if("Hearable")
emote_type = EMOTE_AUDIBLE
else
alert("Unable to use this emote, must be either hearable or visible.")
return
message = custom_emote
else
message = params
if(type_override)
emote_type = type_override
message = user.say_emphasis(message)
. = ..()
message = null
emote_type = EMOTE_VISIBLE
/datum/emote/living/custom/replace_pronoun(mob/user, message)
return message
@@ -520,7 +509,7 @@
message = "beeps."
message_param = "beeps at %t."
sound = 'sound/machines/twobeep.ogg'
mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/living/carbon/human)
mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/living/carbon/human, /mob/camera/aiEye)
/datum/emote/living/circle
key = "circle"
+1 -1
View File
@@ -3,7 +3,7 @@
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
*/
/mob/living/proc/Life(seconds, times_fired)
SHOULD_NOT_SLEEP(TRUE)
//SHOULD_NOT_SLEEP(TRUE)
if(mob_transforming)
return
+19 -3
View File
@@ -34,6 +34,7 @@
ranged_ability.remove_ranged_ability(src)
if(buckled)
buckled.unbuckle_mob(src,force=1)
QDEL_LIST_ASSOC_VAL(ability_actions)
remove_from_all_data_huds()
GLOB.mob_living_list -= src
@@ -258,6 +259,16 @@
AM.setDir(current_dir)
now_pushing = FALSE
// i wish to have a "friendly chat" with whoever made three tail variables instead of one
/mob/proc/has_tail()
return FALSE
/mob/living/carbon/human/has_tail()
if(!dna || !dna.species)
return ..()
var/list/L = dna.species.mutant_bodyparts // caches list because i refuse to type it out and because performance
return (L["mam_tail"] && (L["mam_tail"] != "None")) || (L["tail_human"] && (L["tail_human"] != "None")) || (L["tail_lizard"] && (L["tail_lizard"] != "None"))
/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
if(!AM || !src)
return FALSE
@@ -296,9 +307,14 @@
log_combat(src, M, "grabbed", addition="passive grab")
if(!supress_message && !(iscarbon(AM) && HAS_TRAIT(src, TRAIT_STRONG_GRABBER)))
visible_message("<span class='warning'>[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!</span>",
"<span class='warning'>You have grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!</span>", target = M,
target_message = "<span class='warning'>[src] has grabbed you[(zone_selected == "l_arm" || zone_selected == "r_arm")? " by your hands":" passively"]!</span>")
if((zone_selected == BODY_ZONE_PRECISE_GROIN) && has_tail() && M.has_tail())
visible_message("<span class='warning'>[src] coils [p_their()] tail with [M]'s, pulling [M.p_them()] along!</span>", "You entwine tails with [M], pulling [M.p_them()] along!", ignored_mobs = M)
M.show_message("<span class='warning'>[src] has entwined [p_their()] tail with yours, pulling you along!</span>", MSG_VISUAL, "<span class='warning'>You feel <b>something</b> coiling around your tail, pulling you along!</span>")
else
visible_message("<span class='warning'>[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!</span>",
"<span class='warning'>You have grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!</span>", target = M,
target_message = "<span class='warning'>[src] has grabbed you[(zone_selected == "l_arm" || zone_selected == "r_arm")? " by your hands":" passively"]!</span>")
if(!iscarbon(src))
M.LAssailant = null
else
@@ -127,7 +127,7 @@
handle_parry_ending_effects(data, effect_text)
parrying = NOT_PARRYING
parry_start_time = 0
parry_end_time_last = world.time
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
successful_parries = null
/**
@@ -154,6 +154,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/parry_failed_stagger_duration = 3.5 SECONDS
/// Clickdelay duration post-parry if you fail to parry an attack
var/parry_failed_clickcd_duration = 2 SECONDS
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
+2 -2
View File
@@ -522,8 +522,8 @@
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(get_eye_protection() < intensity && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND))))
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash, override_protection = 0)
if((override_protection || get_eye_protection() < intensity) && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND))))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
return TRUE
@@ -32,6 +32,10 @@
// Combat - Blocking/Parrying system
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
var/datum/block_parry_data/block_parry_data = /datum/block_parry_data // defaults to *something* because [combat_flags] dictates whether or not we can unarmed block/parry.
/// Default
var/datum/block_parry_data/default_block_parry_data = /datum/block_parry_data
/// If we're a pugilist
var/datum/block_parry_data/pugilist_block_parry_data = /datum/block_parry_data/unarmed/pugilist
// Blocking
/// The item the user is actively blocking with if any.
var/obj/item/active_block_item
+1 -9
View File
@@ -1,11 +1,3 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
//Stuff like mobility flag updates, resting updates, etc.
@@ -148,7 +140,7 @@
L.update_pull_movespeed()
//Handle lying down, voluntary or involuntary
density = !lying
update_density()
if(lying)
set_resting(TRUE, TRUE, FALSE)
if(layer == initial(layer)) //to avoid special cases like hiding larvas.
+3 -2
View File
@@ -1,8 +1,6 @@
/mob/living/Moved()
. = ..()
update_turf_movespeed(loc)
//Hide typing indicator if we move.
clear_typing_indicator()
update_pixel_shifting(TRUE)
/mob/living/setDir(newdir, ismousemovement)
@@ -19,6 +17,9 @@
pixel_x = get_standard_pixel_x_offset(lying)
pixel_y = get_standard_pixel_y_offset(lying)
/mob/living/proc/update_density()
density = !lying && !HAS_TRAIT(src, TRAIT_LIVING_NO_DENSITY)
/mob/living/CanPass(atom/movable/mover, turf/target)
if((mover.pass_flags & PASSMOB))
return TRUE
+20
View File
@@ -0,0 +1,20 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_PUGILIST), .proc/update_pugilism)
/mob/living/proc/update_pugilism()
if(HAS_TRAIT(src, TRAIT_PUGILIST))
combat_flags |= COMBAT_FLAG_UNARMED_PARRY
block_parry_data = pugilist_block_parry_data
else
var/initial_combat_flags = initial(combat_flags)
if(!(initial_combat_flags & COMBAT_FLAG_UNARMED_PARRY))
combat_flags &= ~COMBAT_FLAG_UNARMED_PARRY
block_parry_data = default_block_parry_data
+1 -1
View File
@@ -2,4 +2,4 @@
update_z(null)
..()
if(!key && mind) //key and mind have become separated.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
+7
View File
@@ -86,6 +86,7 @@
var/mob/living/silicon/robot/deployed_shell = null //For shell control
var/datum/action/innate/deploy_shell/deploy_action = new
var/datum/action/innate/deploy_last_shell/redeploy_action = new
var/datum/action/innate/custom_holoform/custom_holoform = new
var/chnotify = 0
@@ -152,6 +153,7 @@
aicamera = new/obj/item/camera/siliconcam/ai_camera(src)
deploy_action.Grant(src)
custom_holoform.Grant(src)
if(isturf(loc))
add_verb(src, list(/mob/living/silicon/ai/proc/ai_network_change, \
@@ -1032,3 +1034,8 @@
qdel(src)
else
return
/mob/living/silicon/ai/emote(act, m_type=1, message = null, intentional = FALSE)
if(current && eyeobj)
return eyeobj.emote(act, m_type, message, intentional, forced = TRUE)
return ..()
@@ -19,4 +19,4 @@
. += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem..."
. += "*---------*</span>"
. += ..()
. += ..()
@@ -204,3 +204,7 @@
alpha = 100
layer = ABOVE_ALL_MOB_LAYER
plane = GAME_PLANE
/mob/camera/aiEye/emote(act, m_type=1, message = null, intentional = FALSE, forced = FALSE)
if(ai?.current)
..()
@@ -48,4 +48,4 @@
eye.dm = Everything about the AI and the AIEye.
updating.dm = Everything about triggers that will update chunks.
*/
*/
@@ -1606,4 +1606,4 @@ GLOBAL_LIST_INIT(vox_sounds_male, list("," = 'sound/vox/_comma.ogg',
"zero" = 'sound/vox/zero.ogg',
"zone" = 'sound/vox/zone.ogg',
"zulu" = 'sound/vox/zulu.ogg',))
#endif
#endif
@@ -1,28 +1,12 @@
/mob/living/silicon/verb/clear_custom_holoform()
set name = "Clear Custom Holoform"
set desc = "Clear your current custom holoform"
set category = "OOC"
/mob/living/silicon/proc/attempt_set_custom_holoform()
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
client.prefs.custom_holoform_icon = null
client.prefs.cached_holoform_icons = null
to_chat(src, "<span class='boldnotice'>Holoform removed.</span>")
/mob/living/silicon/verb/set_custom_holoform()
set name = "Set Custom Holoform"
set desc = "Set your custom holoform using your current preferences slot and a specified set of gear."
set category = "OOC"
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
if(client.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY)
to_chat(src, "<span class='warning'>You are attempting to change custom holoforms too fast!</span>")
var/icon/new_holoform = user_interface_custom_holoform(client)
client.prefs.last_custom_holoform = world.time
if(new_holoform)
client.prefs.custom_holoform_icon = new_holoform
client.prefs.cached_holoform_icons = null
client.prefs.last_custom_holoform = world.time
to_chat(src, "<span class='boldnotice'>Holoform set.</span>")
return TRUE
return FALSE
@@ -18,10 +18,10 @@
/mob/living/silicon/apply_effect(effect = 0,effecttype = EFFECT_STUN, blocked = FALSE)
return FALSE //The only effect that can hit them atm is flashes and they still directly edit so this works for now
/mob/living/silicon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE) //immune to tox damage
/mob/living/silicon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT) //immune to tox damage
return FALSE
/mob/living/silicon/setToxLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/setToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_OMNI)
return FALSE
/mob/living/silicon/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE) //immune to clone damage
+1 -1
View File
@@ -10,4 +10,4 @@
diag_hud_set_status()
diag_hud_set_health()
update_health_hud()
. = ..()
. = ..()
+1 -1
View File
@@ -3,4 +3,4 @@
if(laws && isobserver(user))
. += "<b>[src] has the following laws:</b>"
for(var/law in laws.get_law_list(include_zeroth = TRUE))
. += law
. += law
@@ -131,6 +131,7 @@
var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis
var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest
var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light
var/datum/action/innate/custom_holoform/custom_holoform = new /datum/action/innate/custom_holoform
var/datum/action/language_menu/ALM = new
SW.Grant(src)
@@ -139,6 +140,7 @@
AR.Grant(src)
AL.Grant(src)
ALM.Grant(src)
custom_holoform.Grant(src)
emitter_next_use = world.time + 10 SECONDS
/mob/living/silicon/pai/ComponentInitialize()
@@ -87,7 +87,7 @@
/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
return take_holo_damage(amount)
/mob/living/silicon/pai/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/pai/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
return FALSE
/mob/living/silicon/pai/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
@@ -111,7 +111,7 @@
/mob/living/silicon/pai/getFireLoss()
return emittermaxhealth - emitterhealth
/mob/living/silicon/pai/getToxLoss()
/mob/living/silicon/pai/getToxLoss(toxins_type = TOX_OMNI)
return FALSE
/mob/living/silicon/pai/getOxyLoss()
@@ -129,7 +129,7 @@
/mob/living/silicon/pai/setStaminaLoss()
return FALSE
/mob/living/silicon/pai/setToxLoss()
/mob/living/silicon/pai/setToxLoss(toxins_type = TOX_OMNI)
return FALSE
/mob/living/silicon/pai/setOxyLoss()
@@ -1,9 +1,9 @@
/datum/emote/silicon
mob_type_allowed_typecache = list(/mob/living/silicon)
mob_type_allowed_typecache = list(/mob/living/silicon, /mob/camera/aiEye)
emote_type = EMOTE_AUDIBLE
/datum/emote/sound/silicon
mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human)
mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human, /mob/camera/aiEye)
emote_type = EMOTE_AUDIBLE
var/unrestricted = TRUE
@@ -1022,6 +1022,32 @@
R.undeploy()
return TRUE
/datum/action/innate/custom_holoform
name = "Select Custom Holoform"
desc = "Select one of your existing avatars to use as a holoform."
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "custom_holoform"
required_mobility_flags = NONE
/datum/action/innate/custom_holoform/Trigger()
if(!..())
return FALSE
var/mob/living/silicon/S = owner
//if setting the holoform succeeds, attempt to set it as the current holoform for the pAI or AI
if(S.attempt_set_custom_holoform())
if(istype(S, /mob/living/silicon/pai))
var/mob/living/silicon/pai/P = S
P.chassis = "custom"
else if(istype(S, /mob/living/silicon/ai))
var/mob/living/silicon/ai/A = S
if(A.client?.prefs?.custom_holoform_icon)
A.holo_icon = A.client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI)
else
A.holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female"))
return TRUE
/mob/living/silicon/robot/proc/undeploy()
@@ -1043,6 +1069,8 @@
mainframe.laws.show_laws(mainframe) //Always remind the AI when switching
mainframe = null
/mob/living/silicon/robot/attack_ai(mob/user)
if(shell && (!connected_ai || connected_ai == user))
var/mob/living/silicon/ai/AI = user
@@ -122,4 +122,4 @@
var/laser
var/sleeper_g
var/sleeper_r
var/sleeper_nv
var/sleeper_nv
@@ -206,7 +206,7 @@
icon_state = "toolbox_tiles"
throwforce = 10
created_name = "Floorbot"
var/toolbox = /obj/item/storage/toolbox/mechanical
var/toolbox = /obj/item/storage/toolbox
/obj/item/bot_assembly/floorbot/Initialize()
. = ..()
@@ -225,7 +225,7 @@
name = "incomplete floorbot assembly"
icon_state = "toolbox_tiles_sensor"
/obj/item/storage/toolbox/mechanical/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
/obj/item/storage/toolbox/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
if(!istype(T, /obj/item/stack/tile/plasteel))
..()
return
@@ -574,17 +574,20 @@
if(!C.reagents.has_reagent(R.type))
return TRUE
var/list/brute_damaged_bodyparts = C.get_damaged_bodyparts(TRUE, FALSE, status = list(BODYPART_ORGANIC))
var/list/burn_damaged_bodyparts = C.get_damaged_bodyparts(FALSE, TRUE, status = list(BODYPART_ORGANIC))
//They're injured enough for it!
if((!C.reagents.has_reagent(treatment_brute_avoid)) && (C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_brute)))
if(brute_damaged_bodyparts.len && (!C.reagents.has_reagent(treatment_brute_avoid)) && (C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_brute)))
return TRUE //If they're already medicated don't bother!
if((!C.reagents.has_reagent(treatment_oxy_avoid)) && (C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(treatment_oxy)))
return TRUE
if((!C.reagents.has_reagent(treatment_fire_avoid)) && (C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
if(burn_damaged_bodyparts.len && (!C.reagents.has_reagent(treatment_fire_avoid)) && (C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
return TRUE
var/treatment_toxavoid = get_avoidchem_toxin(C)
if(((isnull(treatment_toxavoid) || !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
if(!HAS_TRAIT(C, TRAIT_ROBOTIC_ORGANISM) && ((isnull(treatment_toxavoid) || !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
return TRUE
if(treat_virus && !C.reagents.has_reagent(treatment_virus_avoid) && !C.reagents.has_reagent(treatment_virus))
@@ -44,6 +44,7 @@
var/can_repair_constructs = FALSE
var/can_repair_self = FALSE
var/runetype
var/datum/mind/original_mind
/mob/living/simple_animal/hostile/construct/Initialize()
. = ..()
@@ -66,6 +67,15 @@
CR.button.screen_loc = "6:[pos],4:-2"
CR.button.moved = "6:[pos],4:-2"
/mob/living/simple_animal/hostile/construct/Destroy()
original_mind = null
. = ..()
/mob/living/simple_animal/hostile/construct/death()
if(original_mind && !(QDELETED(original_mind)))
transfer_ckey(original_mind.current)
..()
/mob/living/simple_animal/hostile/construct/Login()
..()
to_chat(src, playstyle_string)
@@ -107,7 +117,7 @@
return
/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
return 0
return FALSE
/mob/living/simple_animal/hostile/construct/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
@@ -25,7 +25,7 @@
else if(damage_coeff[OXY])
. = adjustHealth(amount * damage_coeff[OXY] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
if(forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[TOX])
@@ -70,4 +70,4 @@
/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/__distance_check(atom/movable/AM, OldLoc, Dir, Forced)
if(get_dist(src, AM) > gravity_power_range)
remove_gravity(AM)
remove_gravity(AM)

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